update libertas driver

SVN-Revision: 13447
owl
John Crispin 2008-11-30 16:53:16 +00:00
parent 4e61cbbf5e
commit 10aa4d9e42
33 changed files with 4262 additions and 2441 deletions

View File

@ -16,7 +16,7 @@ include $(INCLUDE_DIR)/package.mk
define KernelPackage/libertas
SUBMENU:=Other modules
DEPENDS:=@TARGET_olpc +kmod-ieee80211
DEPENDS:=+kmod-ieee80211
TITLE:=Marvell 88W8015 Wireless Driver
FILES:= \
$(PKG_BUILD_DIR)/libertas.$(LINUX_KMOD_SUFFIX) \
@ -25,9 +25,9 @@ define KernelPackage/libertas
endef
define Download/firmware
URL:=http://dev.laptop.org/pub/firmware/libertas
FILE:=usb8388-5.220.11.p5.bin
MD5SUM=37cc814d5a475fcf8f8fbe89a9c5d546
URL:=http://dev.laptop.org/pub/firmware/libertas/
FILE:=usb8388-5.110.22.p20.bin
#MD5SUM=37cc814d5a475fcf8f8fbe89a9c5d546
endef
define Build/Prepare
@ -44,13 +44,13 @@ define Build/Compile
SUBDIRS="$(PKG_BUILD_DIR)" \
CONFIG_LIBERTAS=m \
CONFIG_LIBERTAS_USB=m \
EXTRA_CFLAGS="-I$(PKG_BUILD_DIR) -DCONFIG_LIBERTAS_DEBUG -include compat.h -I$(STAGING_DIR)/usr/include/mac80211" \
EXTRA_CFLAGS="-I$(PKG_BUILD_DIR) -DCONFIG_LIBERTAS_DEBUG -I$(STAGING_DIR)/usr/include/mac80211" \
modules
endef
define KernelPackage/libertas/install
$(INSTALL_DIR) $(1)/lib/firmware
$(INSTALL_BIN) $(DL_DIR)/usb8388-5.220.11.p5.bin $(1)/lib/firmware/usb8388.bin
$(INSTALL_BIN) $(DL_DIR)/usb8388-5.110.22.p20.bin $(1)/lib/firmware/usb8388.bin
$(INSTALL_DATA) ./files/LICENSE $(1)/lib/firmware/
endef

View File

@ -1,50 +0,0 @@
Index: kmod-libertas/ethtool.c
===================================================================
--- kmod-libertas.orig/ethtool.c 2008-01-14 22:14:06.000000000 +0000
+++ kmod-libertas/ethtool.c 2008-01-14 22:14:14.000000000 +0000
@@ -144,16 +144,6 @@
lbs_deb_enter(LBS_DEB_ETHTOOL);
}
-static int lbs_ethtool_get_sset_count(struct net_device * dev, int sset)
-{
- switch (sset) {
- case ETH_SS_STATS:
- return MESH_STATS_NUM;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static void lbs_ethtool_get_strings(struct net_device *dev,
u32 stringset,
u8 * s)
@@ -221,7 +211,6 @@
.get_drvinfo = lbs_ethtool_get_drvinfo,
.get_eeprom = lbs_ethtool_get_eeprom,
.get_eeprom_len = lbs_ethtool_get_eeprom_len,
- .get_sset_count = lbs_ethtool_get_sset_count,
.get_ethtool_stats = lbs_ethtool_get_stats,
.get_strings = lbs_ethtool_get_strings,
.get_wol = lbs_ethtool_get_wol,
Index: kmod-libertas/if_usb.c
===================================================================
--- kmod-libertas.orig/if_usb.c 2008-01-14 22:14:57.000000000 +0000
+++ kmod-libertas/if_usb.c 2008-01-14 22:17:09.000000000 +0000
@@ -188,14 +188,14 @@
endpoint = &iface_desc->endpoint[i].desc;
if (usb_endpoint_is_bulk_in(endpoint)) {
cardp->ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize);
- cardp->ep_in = usb_endpoint_num(endpoint);
+ cardp->ep_in = endpoint->bEndpointAddress;
lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in);
lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size);
} else if (usb_endpoint_is_bulk_out(endpoint)) {
cardp->ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize);
- cardp->ep_out = usb_endpoint_num(endpoint);
+ cardp->ep_out = endpoint->bEndpointAddress;
lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out);
lbs_deb_usbd(&udev->dev, "Bulk out size is %d\n", cardp->ep_out_size);

View File

@ -0,0 +1,81 @@
Index: kmod-libertas/scan.c
===================================================================
--- kmod-libertas.orig/scan.c 2008-11-30 17:44:39.000000000 +0100
+++ kmod-libertas/scan.c 2008-11-30 17:46:08.000000000 +0100
@@ -13,6 +13,13 @@
#include "scan.h"
#include "cmd.h"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define IWE(func, ...) func(&iweinfo, __VA_ARGS__)
+static struct iw_request_info iweinfo = { 0, 0 };
+#else
+#define IWE(func, ...) func(__VA_ARGS__)
+#endif
+
//! Approximate amount of data needed to pass a scan result back to iwlist
#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
+ IW_ESSID_MAX_SIZE \
@@ -807,7 +814,7 @@
iwe.cmd = SIOCGIWESSID;
iwe.u.data.flags = 1;
iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE);
- start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
+ start = IWE(iwe_stream_add_point, start, stop, &iwe, bss->ssid);
/* Mode */
iwe.cmd = SIOCGIWMODE;
@@ -862,7 +869,7 @@
iwe.u.data.flags = IW_ENCODE_DISABLED;
}
iwe.u.data.length = 0;
- start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
+ start = IWE(iwe_stream_add_point, start, stop, &iwe, bss->ssid);
current_val = start + IW_EV_LCP_LEN;
@@ -874,7 +881,7 @@
for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) {
/* Bit rate given in 500 kb/s units */
iwe.u.bitrate.value = bss->rates[j] * 500000;
- current_val = iwe_stream_add_value(start, current_val,
+ current_val = IWE(iwe_stream_add_value, start, current_val,
stop, &iwe, IW_EV_PARAM_LEN);
}
if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate
@@ -882,7 +889,7 @@
priv->curbssparams.ssid_len,
bss->ssid, bss->ssid_len)) {
iwe.u.bitrate.value = 22 * 500000;
- current_val = iwe_stream_add_value(start, current_val,
+ current_val = IWE(iwe_stream_add_value, start, current_val,
stop, &iwe, IW_EV_PARAM_LEN);
}
/* Check if we added any event */
@@ -895,7 +902,7 @@
memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
iwe.cmd = IWEVGENIE;
iwe.u.data.length = bss->wpa_ie_len;
- start = iwe_stream_add_point(start, stop, &iwe, buf);
+ start = IWE(iwe_stream_add_point, start, stop, &iwe, buf);
}
memset(&iwe, 0, sizeof(iwe));
@@ -904,7 +911,7 @@
memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
iwe.cmd = IWEVGENIE;
iwe.u.data.length = bss->rsn_ie_len;
- start = iwe_stream_add_point(start, stop, &iwe, buf);
+ start = IWE(iwe_stream_add_point, start, stop, &iwe, buf);
}
if (bss->mesh) {
@@ -915,7 +922,7 @@
p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc");
iwe.u.data.length = p - custom;
if (iwe.u.data.length)
- start = iwe_stream_add_point(start, stop, &iwe, custom);
+ start = IWE(iwe_stream_add_point, start, stop, &iwe, custom);
}
out:

View File

@ -46,13 +46,11 @@ static struct chan_freq_power channel_freq_power_UN_BG[] = {
static u8 lbs_region_2_code(u8 *region)
{
u8 i;
u8 size = sizeof(region_code_mapping)/
sizeof(struct region_code_mapping);
for (i = 0; region[i] && i < COUNTRY_CODE_LEN; i++)
region[i] = toupper(region[i]);
for (i = 0; i < size; i++) {
for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
if (!memcmp(region, region_code_mapping[i].region,
COUNTRY_CODE_LEN))
return (region_code_mapping[i].code);
@ -65,9 +63,8 @@ static u8 lbs_region_2_code(u8 *region)
static u8 *lbs_code_2_region(u8 code)
{
u8 i;
u8 size = sizeof(region_code_mapping)
/ sizeof(struct region_code_mapping);
for (i = 0; i < size; i++) {
for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
if (region_code_mapping[i].code == code)
return (region_code_mapping[i].region);
}
@ -82,7 +79,7 @@ static u8 *lbs_code_2_region(u8 code)
* @param nrchan number of channels
* @return the nrchan-th chan number
*/
static u8 lbs_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 *chan)
static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan)
/*find the nrchan-th chan after the firstchan*/
{
u8 i;
@ -90,8 +87,7 @@ static u8 lbs_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 *chan)
u8 cfp_no;
cfp = channel_freq_power_UN_BG;
cfp_no = sizeof(channel_freq_power_UN_BG) /
sizeof(struct chan_freq_power);
cfp_no = ARRAY_SIZE(channel_freq_power_UN_BG);
for (i = 0; i < cfp_no; i++) {
if ((cfp + i)->channel == firstchan) {
@ -138,19 +134,15 @@ static u8 lbs_channel_known_11d(u8 chan,
return 0;
}
u32 lbs_chan_2_freq(u8 chan, u8 band)
u32 lbs_chan_2_freq(u8 chan)
{
struct chan_freq_power *cf;
u16 cnt;
u16 i;
u32 freq = 0;
cf = channel_freq_power_UN_BG;
cnt =
sizeof(channel_freq_power_UN_BG) /
sizeof(struct chan_freq_power);
for (i = 0; i < cnt; i++) {
for (i = 0; i < ARRAY_SIZE(channel_freq_power_UN_BG); i++) {
if (chan == cf[i].channel)
freq = cf[i].freq;
}
@ -272,7 +264,7 @@ static void lbs_generate_parsed_region_chan_11d(struct region_channel *region_ch
* @param chan chan
* @return TRUE;FALSE
*/
static u8 lbs_region_chan_supported_11d(u8 region, u8 band, u8 chan)
static u8 lbs_region_chan_supported_11d(u8 region, u8 chan)
{
struct chan_freq_power *cfp;
int cfp_no;
@ -281,7 +273,7 @@ static u8 lbs_region_chan_supported_11d(u8 region, u8 band, u8 chan)
lbs_deb_enter(LBS_DEB_11D);
cfp = lbs_get_region_cfp_table(region, band, &cfp_no);
cfp = lbs_get_region_cfp_table(region, &cfp_no);
if (cfp == NULL)
return 0;
@ -375,7 +367,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) {
/*step4: channel is supported? */
if (!lbs_get_chan_11d(band, firstchan, i, &curchan)) {
if (!lbs_get_chan_11d(firstchan, i, &curchan)) {
/* Chan is not found in UN table */
lbs_deb_11d("chan is not supported: %d \n", i);
break;
@ -383,8 +375,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
lastchan = curchan;
if (lbs_region_chan_supported_11d
(region, band, curchan)) {
if (lbs_region_chan_supported_11d(region, curchan)) {
/*step5: Check if curchan is supported by mrvl in region */
parsed_region_chan->chanpwr[idx].chan = curchan;
parsed_region_chan->chanpwr[idx].pwr =
@ -562,8 +553,7 @@ done:
* @param resp pointer to command response buffer
* @return 0; -1
*/
int lbs_ret_802_11d_domain_info(struct lbs_private *priv,
struct cmd_ds_command *resp)
int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
{
struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
struct mrvlietypes_domainparamset *domain = &domaininfo->domain;

View File

@ -83,7 +83,7 @@ struct lbs_private;
u8 lbs_get_scan_type_11d(u8 chan,
struct parsed_region_chan_11d *parsed_region_chan);
u32 lbs_chan_2_freq(u8 chan, u8 band);
u32 lbs_chan_2_freq(u8 chan);
void lbs_init_11d(struct lbs_private *priv);
@ -93,8 +93,7 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
struct cmd_ds_command *cmd, u16 cmdno,
u16 cmdOption);
int lbs_ret_802_11d_domain_info(struct lbs_private *priv,
struct cmd_ds_command *resp);
int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
struct bss_descriptor;
int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,

View File

@ -1,9 +1,9 @@
libertas-objs := main.o wext.o \
rx.o tx.o cmd.o \
cmdresp.o scan.o \
join.o 11d.o \
11d.o \
debugfs.o \
ethtool.o assoc.o
ethtool.o assoc.o ioctl.o
usb8xxx-objs += if_usb.o
libertas_cs-objs += if_cs.o

View File

@ -28,6 +28,423 @@ DRIVER LOADING
insmod usb8388.ko [fw_name=usb8388.bin]
=====================
IWPRIV COMMAND
=====================
NAME
This manual describes the usage of private commands used in Marvell WLAN
Linux Driver. All the commands available in Wlanconfig will not be available
in the iwpriv.
SYNOPSIS
iwpriv <ethX> <command> [sub-command] ...
iwpriv ethX setregioncode <n>
iwpriv ethX getregioncode
Version 5 Command:
iwpriv ethX ledgpio <n>
BT Commands:
The blinding table (BT) contains a list of mac addresses that will be,
by default, ignored by the firmware. It is also possible to invert this
behavior so that we will ignore all traffic except for the portion
coming from mac addresess in the list. It is primarily used for
debugging and testing networks. It can be edited and inspected with
the following commands:
iwpriv ethX bt_reset
iwpriv ethX bt_add <mac_address>
iwpriv ethX bt_del <mac_address>
iwpriv ethX bt_list <id>
iwpriv ethX bt_get_invert <n>
iwpriv ethX bt_set_invert <n>
FWT Commands:
The forwarding table (FWT) is a feature used to manage mesh network
routing in the firmware. The FWT is essentially a routing table that
associates a destination mac address (da) with a next hop receiver
address (ra). The FWT can be inspected and edited with the following
iwpriv commands, which are described in greater detail below.
Eventually, the table will be automatically maintained by a custom
routing protocol.
NOTE: FWT commands replace the previous DFT commands. What were the DFT
commands?, you might ask. They were an earlier API to the firmware that
implemented a simple MAC-layer forwarding mechanism. In the unlikely
event that you were using these commands, you must migrate to the new
FWT commands which can be used to achieve the same functionality.
iwpriv ethX fwt_add [parameters]
iwpriv ethX fwt_del [parameters]
iwpriv ethX fwt_lookup [parameters]
iwpriv ethX fwt_list [parameters]
iwpriv ethX fwt_list_route [parameters]
iwpriv ethX fwt_list_neigh [parameters]
iwpriv ethX fwt_reset [parameters]
iwpriv ethX fwt_cleanup
iwpriv ethX fwt_time
MESH Commands:
The MESH commands are used to configure various features of the mesh
routing protocol. The following commands are supported:
iwpriv ethX mesh_get_ttl
iwpriv ethX mesh_set_ttl ttl
iwpriv ethX mesh_get_bcastr rate
iwpriv ethX mesh_set_bcastr rate
iwpriv ethX get_rreq_delay
iwpriv ethX set_rreq_delay delay
iwpriv ethX get_route_exp
iwpriv ethX set_route_exp time
iwpriv ethX get_link_costs
iwpriv ethX set_link_costs "cost54 cost36 cost11 cost1"
DESCRIPTION
Those commands are used to send additional commands to the Marvell WLAN
card via the Linux device driver.
The ethX parameter specifies the network device that is to be used to
perform this command on. it could be eth0, eth1 etc.
setregioncode
This command is used to set the region code in the station.
where value is 'region code' for various regions like
USA FCC, Canada IC, Spain, France, Europe ETSI, Japan ...
Usage:
iwpriv ethX setregioncode 0x10: set region code to USA (0x10).
getregioncode
This command is used to get the region code information set in the
station.
ledgpio
This command is used to set/get LEDs.
iwpriv ethX ledgpio <LEDs>
will set the corresponding LED for the GPIO Line.
iwpriv ethX ledgpio
will give u which LEDs are Enabled.
Usage:
iwpriv eth1 ledgpio 1 0 2 1 3 4
will enable
LED 1 -> GPIO 0
LED 2 -> GPIO 1
LED 3 -> GPIO 4
iwpriv eth1 ledgpio
shows LED information in the format as mentioned above.
Note: LED0 is invalid
Note: Maximum Number of LEDs are 16.
bcn_control
This command is used to enable disable beacons. This can also be used
to set beacon interval.
Usage:
iwpriv ethX bcn_control [enable] [beacon_interval]
enable: 0 to disable beacon. 1 to enable beacon.
beacon_interval: 20 - 1000ms.
Examples:
1. iwpriv ethX bcn_control
Returns (x, y), where x if 1, indicates beacon is enabled, y
beacon period.
2. iwpriv ethX bcn_control 0
Turns off beacon transmission.
3. iwpriv ethX bcn_control 1 500
Enable beacon with beacon interval 500ms.
ledbhv
Command iwpriv mshX ledbhv can be used to change default LEDs behaviors.
A given LED behavior can be on, off or blinking. The duty/cycle can be set
when behavior is programmed as blinking.
Usage:
1. To get default LED behavior
iwpriv mshX ledbhv <firmware state>
2. To set or change default LED behavior
iwpriv mshX ledbhv <firmware state> <lednum> <behavior> <arg>
firmware state: The following are some of the relevant states.
00: disconnected
01: firmware is scanning
02: firmware is connected and awake
03: firmware is sleeping
04: connected deep sleep
06: firmware disconnected link lost
07: firmware disconnected disassociated
09: data transfer while firmware is associated and not scanning.
If firmware is already in this state, LED behavior does not change
on this data transfer.
10: firmware idle, not scanning, not disconnected or disassociated.
lednum: 1 or 2 for first and second LED.
behavior: 0 for steady ON, 1 - steady off and 2- blinking.
arg: It is used when behavior is 2 to set duty and cycle. It is defined as
(duty << 4 | cycle). Here duty could be 0..4 and cycle 0..5 for 34,
74, 149, 298, 596, 1192 ms respectively.
Examples:
1. To get default behavior for scan
iwpriv mshX ledbhv 1
2. To get default behavior while data transfer
iwpriv mshX ledbhv 9
3. To turn off LED 2
iwpriv mshX ledbhv 2 2 1 0
iwpriv mshX ledbhv 10 2 1 0
4. To enable LED 2 and blink LED 1 while data transfer.
iwpriv mshX ledbhv 9 2 0 0
iwpriv mshX ledbhv 9 1 2 4
5. To change duty cycle of LED 2 during data transfer
iwpriv mshX ledbhv 9 2 2 36
6. To turn ON LED 2 when firmware is disassociated/disconnected.
iwpriv mshX ledbhv 0 2 0 0
fwt_add
This command is used to insert an entry into the FWT table. The list of
parameters must follow the following structure:
iwpriv ethX fwt_add da ra [metric dir rate ssn dsn hopcount ttl expiration sleepmode snr]
The parameters between brackets are optional, but they must appear in
the order specified. For example, if you want to specify the metric,
you must also specify the dir, ssn, and dsn but you need not specify the
hopcount, expiration, sleepmode, or snr. Any unspecified parameters
will be assigned the defaults specified below.
The different parameters are:-
da -- DA MAC address in the form 00:11:22:33:44:55
ra -- RA MAC address in the form 00:11:22:33:44:55
metric -- route metric (cost: smaller-metric routes are
preferred, default is 0)
dir -- direction (1 for direct, 0 for reverse,
default is 1)
rate -- data rate used for transmission to the RA,
as specified for the rateadapt command,
default is 3 (11Mbps)
ssn -- Source Sequence Number (time at the RA for
reverse routes. Default is 0)
dsn -- Destination Sequence Number (time at the DA
for direct routes. Default is 0)
hopcount -- hop count (currently unused, default is 0)
ttl -- TTL (Only used in reverse entries)
expiration -- entry expiration (in ticks, where a tick is
1024us, or ~ 1ms. Use 0 for an indefinite
entry, default is 0)
sleepmode -- RA's sleep mode (currently unused, default is
0)
snr -- SNR in the link to RA (currently unused,
default is 0)
The command does not return anything.
fwt_del
This command is used to remove an entry to the FWT table. The list of
parameters must follow the following structure:
iwpriv ethX fwt_del da ra [dir]
where the different parameters are:-
da -- DA MAC address (in the form "00:11:22:33:44:55")
ra -- RA MAC address (in the form "00:11:22:33:44:55")
dir -- direction (1 for direct, 0 for reverse,
default is 1)
The command does not return anything.
fwt_lookup
This command is used to get the best route in the FWT table to a given
host. The only parameter is the MAC address of the host that is being
looked for.
iwpriv ethX fwt_lookup da
where:-
da -- DA MAC address (in the form "00:11:22:33:44:55")
The command returns an output string identical to the one returned by
fwt_list described below.
fwt_list
This command is used to list a route from the FWT table. The only
parameter is the index into the table. If you want to list all the
routes in a table, start with index=0, and keep listing until you get a
"(null)" string. Note that the indicies may change as the fwt is
updated. It is expected that most users will not use fwt_list directly,
but that a utility similar to the traditional route command will be used
to invoke fwt_list over and over.
iwpriv ethX fwt_list index
The output is a string of the following form:
da ra valid metric dir rate ssn dsn hopcount ttl expiration
sleepmode snr precursor
where the different fields are:-
da -- DA MAC address (in the form "00:11:22:33:44:55")
ra -- RA MAC address (in the form "00:11:22:33:44:55")
valid -- whether the route is valid (0 if not valid)
metric -- route metric (cost: smaller-metric routes are preferred)
dir -- direction (1 for direct, 0 for reverse)
rate -- data rate used for transmission to the RA,
as specified for the rateadapt command
ssn -- Source Sequence Number (time at the RA for reverse routes)
dsn -- Destination Sequence Number (time at the DA for direct routes)
hopcount -- hop count (currently unused)
ttl -- TTL (only used in reverse entries)
expiration -- entry expiration (in ticks, where a tick is 1024us, or ~ 1ms. Use 0 for an indefinite entry)
sleepmode -- RA's sleep mode (currently unused)
snr -- SNR in the link to RA (currently unused)
precursor -- predecessor in direct routes
fwt_list_route
This command is equivalent to fwt_list.
fwt_list_neigh
This command is used to list a neighbor from the FWT table. The only
parameter is the neighbor ID. If you want to list all the neighbors in a
table, start with nid=0, and keep incrementing nid until you get a
"(null)" string. Note that the nid from a fwt_list_route command can be
used as an input to this command. Also note that this command is meant
mostly for debugging. It is expected that users will use fwt_lookup.
One important reason for this is that the neighbor id may change as the
neighbor table is altered.
iwpriv ethX fwt_list_neigh nid
The output is a string of the following form:
ra sleepmode snr references
where the different fields are:-
ra -- RA MAC address (in the form "00:11:22:33:44:55")
sleepmode -- RA's sleep mode (currently unused)
snr -- SNR in the link to RA (currently unused)
references -- RA's reference counter
fwt_reset
This command is used to reset the FWT table, getting rid of all the
entries. There are no input parameters.
iwpriv ethX fwt_reset
The command does not return anything.
fwt_cleanup
This command is used to perform user-based garbage recollection. The
FWT table is checked, and all the entries that are expired or invalid
are cleaned. Note that this is exported to the driver for debugging
purposes, as garbage collection is also fired by the firmware when in
space problems. There are no input parameters.
iwpriv ethX fwt_cleanup
The command does returns the number of invalid/expired routes deleted.
fwt_time
This command returns a card's internal time representation. It is this
time that is used to represent the expiration times of FWT entries. The
number is not consistent from card to card; it is simply a timer count.
The fwt_time command is used to inspect the timer so that expiration
times reported by fwt_list can be properly interpreted.
iwpriv ethX fwt_time
mesh_get_ttl
The mesh ttl is the number of hops a mesh packet can traverse before it
is dropped. This parameter is used to prevent infinite loops in the
mesh network. The value returned by this function is the ttl assigned
to all mesh packets. Currently there is no way to control the ttl on a
per packet or per socket basis.
iwpriv ethX mesh_get_ttl
mesh_set_ttl ttl
Set the ttl. The argument must be between 0 and 255.
iwpriv ethX mesh_set_ttl <ttl>
mesh_get_bcastr
Shows the rate index used for mesh broadcast and multicast packets.
Rates are expressed in 2 * Mb/s, ie 11Mb/s is 22, 5.5Mb/s is 11, etc.
iwpriv ethX mesh_get_bcastr rate
mesh_set_bcastr rate
Sets the rate index for mesh broadcast and muticast packets. Rates are
expressed in expressed in 2 * Mb/s, ie 11Mb/s is 22, 5.5Mb/s is 11, etc.
iwpriv ethX mesh_set_bcastr rate
get_rreq_delay
Shows the delay to forward a RREQ frame. This delay allows the node to
forward just the best route in case the same RREQ arrives to the node
through different routes. The argument is shown in 1/100 seconds.
iwpriv ethX get_rreq_delay
set_rreq_delay delay
Sets the RREQ forward delay. The delay is interpreted as 1/100 seconds.
iwpriv ethX set_rreq_delay delay
get_route_exp
Shows the mesh route expiration time, in seconds.
iwpriv ethX get_route_exp
set_route_exp time
Gets the mesh route, expiration time, in seconds.
iwpriv ethX set_route_exp time
get_link_costs
Gets the mesh hop base cost for each used rate. The output gives us the
base cost for hops at 54Mbps, 36Mbps, 11Mbps and 1Mbps, in that order.
The base cost gets divided by a battery state factor to get the actual
cost. A cost of 0 means that rate is deactivated.
iwpriv ethX get_link_costs
set_link_costs "cost54 cost36 cost11 cost1"
Sets the mesh hop base cost for the used speeds. The input parameter
will specify the cost for hops at 54Mbps, 36Mbps, 11Mbps and 1Mbps, in
that order. A cost of 0 will disable a specific rate.
iwpriv ethX set_link_costs "cost54 cost36 cost11 cost1"
=========================
ETHTOOL
=========================

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,33 @@
void lbs_association_worker(struct work_struct *work);
struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
void lbs_sync_channel(struct work_struct *work);
struct cmd_ds_command;
int lbs_cmd_80211_authenticate(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd);
int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
struct cmd_ds_command *cmd);
int lbs_cmd_80211_associate(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
struct cmd_ds_command *resp);
int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv);
int lbs_ret_80211_disassociate(struct lbs_private *priv);
int lbs_ret_80211_associate(struct lbs_private *priv,
struct cmd_ds_command *resp);
int lbs_stop_adhoc_network(struct lbs_private *priv);
int lbs_send_deauthentication(struct lbs_private *priv);
#endif /* _LBS_ASSOC_H */

View File

@ -4,19 +4,57 @@
*/
#include <net/iw_handler.h>
#include <linux/kfifo.h>
#include "host.h"
#include "hostcmd.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "join.h"
#include "assoc.h"
#include "wext.h"
#include "cmd.h"
static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
static void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
struct cmd_ctrl_node *ptempnode,
void *pdata_buf);
/**
* @brief Simple callback that copies response back into command
*
* @param priv A pointer to struct lbs_private structure
* @param extra A pointer to the original command structure for which
* 'resp' is a response
* @param resp A pointer to the command response
*
* @return 0 on success, error on failure
*/
int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
struct cmd_header *resp)
{
struct cmd_header *buf = (void *)extra;
uint16_t copy_len;
copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
memcpy(buf, resp, copy_len);
return 0;
}
EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
/**
* @brief Simple callback that ignores the result. Use this if
* you just want to send a command to the hardware, but don't
* care for the result.
*
* @param priv ignored
* @param extra ignored
* @param resp ignored
*
* @return 0 for success
*/
static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra,
struct cmd_header *resp)
{
return 0;
}
/**
@ -60,13 +98,24 @@ int lbs_update_hw_spec(struct lbs_private *priv)
goto out;
priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
memcpy(priv->fwreleasenumber, cmd.fwreleasenumber, 4);
lbs_deb_cmd("GET_HW_SPEC: firmware release %u.%u.%up%u\n",
priv->fwreleasenumber[2], priv->fwreleasenumber[1],
priv->fwreleasenumber[0], priv->fwreleasenumber[3]);
lbs_deb_cmd("GET_HW_SPEC: MAC addr %s\n",
print_mac(mac, cmd.permanentaddr));
/* The firmware release is in an interesting format: the patch
* level is in the most significant nibble ... so fix that: */
priv->fwrelease = le32_to_cpu(cmd.fwrelease);
priv->fwrelease = (priv->fwrelease << 8) |
(priv->fwrelease >> 24 & 0xff);
/* Some firmware capabilities:
* CF card firmware 5.0.16p0: cap 0x00000303
* USB dongle firmware 5.110.17p2: cap 0x00000303
*/
printk("libertas: %s, fw %u.%u.%up%u, cap 0x%08x\n",
print_mac(mac, cmd.permanentaddr),
priv->fwrelease >> 24 & 0xff,
priv->fwrelease >> 16 & 0xff,
priv->fwrelease >> 8 & 0xff,
priv->fwrelease & 0xff,
priv->fwcapinfo);
lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
cmd.hwifversion, cmd.version);
@ -132,8 +181,7 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria)
}
EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
static int lbs_cmd_802_11_ps_mode(struct lbs_private *priv,
struct cmd_ds_command *cmd,
static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
u16 cmd_action)
{
struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
@ -248,6 +296,7 @@ int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
lbs_deb_enter(LBS_DEB_CMD);
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
@ -311,7 +360,9 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(cmd_action);
if (cmd_action == CMD_ACT_SET) {
if (cmd_action == CMD_ACT_GET)
cmd.enable = 0;
else {
if (*enable)
cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
else
@ -327,81 +378,108 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
return ret;
}
static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
struct enc_key * pkey)
static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
struct enc_key *key)
{
lbs_deb_enter(LBS_DEB_CMD);
if (pkey->flags & KEY_INFO_WPA_ENABLED) {
pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
}
if (pkey->flags & KEY_INFO_WPA_UNICAST) {
pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
}
if (pkey->flags & KEY_INFO_WPA_MCAST) {
pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
}
if (key->flags & KEY_INFO_WPA_ENABLED)
keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
if (key->flags & KEY_INFO_WPA_UNICAST)
keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
if (key->flags & KEY_INFO_WPA_MCAST)
keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
pkeyparamset->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
pkeyparamset->keylen = cpu_to_le16(pkey->len);
memcpy(pkeyparamset->key, pkey->key, pkey->len);
pkeyparamset->length = cpu_to_le16( sizeof(pkeyparamset->keytypeid)
+ sizeof(pkeyparamset->keyinfo)
+ sizeof(pkeyparamset->keylen)
+ sizeof(pkeyparamset->key));
keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
keyparam->keytypeid = cpu_to_le16(key->type);
keyparam->keylen = cpu_to_le16(key->len);
memcpy(keyparam->key, key->key, key->len);
/* Length field doesn't include the {type,length} header */
keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
lbs_deb_leave(LBS_DEB_CMD);
}
static int lbs_cmd_802_11_key_material(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action,
u32 cmd_oid, void *pdata_buf)
int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
struct assoc_request *assoc)
{
struct cmd_ds_802_11_key_material *pkeymaterial =
&cmd->params.keymaterial;
struct assoc_request * assoc_req = pdata_buf;
struct cmd_ds_802_11_key_material cmd;
int ret = 0;
int index = 0;
lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(CMD_802_11_KEY_MATERIAL);
pkeymaterial->action = cpu_to_le16(cmd_action);
cmd.action = cpu_to_le16(cmd_action);
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
if (cmd_action == CMD_ACT_GET) {
cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
ret = 0;
goto done;
cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2);
} else {
memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
set_one_wpa_key(&cmd.keyParamSet[index],
&assoc->wpa_unicast_key);
index++;
}
if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
set_one_wpa_key(&cmd.keyParamSet[index],
&assoc->wpa_mcast_key);
index++;
}
/* The common header and as many keys as we included */
cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
keyParamSet[index]));
}
ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
/* Copy the returned key to driver private data */
if (!ret && cmd_action == CMD_ACT_GET) {
void *buf_ptr = cmd.keyParamSet;
void *resp_end = &(&cmd)[1];
while (buf_ptr < resp_end) {
struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
struct enc_key *key;
uint16_t param_set_len = le16_to_cpu(keyparam->length);
uint16_t key_len = le16_to_cpu(keyparam->keylen);
uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
void *end;
end = (void *)keyparam + sizeof(keyparam->type)
+ sizeof(keyparam->length) + param_set_len;
/* Make sure we don't access past the end of the IEs */
if (end > resp_end)
break;
if (key_flags & KEY_INFO_WPA_UNICAST)
key = &priv->wpa_unicast_key;
else if (key_flags & KEY_INFO_WPA_MCAST)
key = &priv->wpa_mcast_key;
else
break;
/* Copy returned key into driver */
memset(key, 0, sizeof(struct enc_key));
if (key_len > sizeof(key->key))
break;
key->type = key_type;
key->flags = key_flags;
key->len = key_len;
memcpy(key->key, keyparam->key, key->len);
buf_ptr = end + 1;
}
}
memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet));
if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
set_one_wpa_key(&pkeymaterial->keyParamSet[index],
&assoc_req->wpa_unicast_key);
index++;
}
if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
set_one_wpa_key(&pkeymaterial->keyParamSet[index],
&assoc_req->wpa_mcast_key);
index++;
}
cmd->size = cpu_to_le16( S_DS_GEN
+ sizeof (pkeymaterial->action)
+ (index * sizeof(struct MrvlIEtype_keyParamSet)));
ret = 0;
done:
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
static int lbs_cmd_802_11_reset(struct lbs_private *priv,
struct cmd_ds_command *cmd, int cmd_action)
static int lbs_cmd_802_11_reset(struct cmd_ds_command *cmd, int cmd_action)
{
struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
@ -415,30 +493,6 @@ static int lbs_cmd_802_11_reset(struct lbs_private *priv,
return 0;
}
static int lbs_cmd_802_11_get_log(struct lbs_private *priv,
struct cmd_ds_command *cmd)
{
lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(CMD_802_11_GET_LOG);
cmd->size =
cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) + S_DS_GEN);
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
static int lbs_cmd_802_11_get_stat(struct lbs_private *priv,
struct cmd_ds_command *cmd)
{
lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(CMD_802_11_GET_STAT);
cmd->size =
cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN);
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
struct cmd_ds_command *cmd,
int cmd_action,
@ -559,8 +613,7 @@ static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
return 0;
}
static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv,
struct cmd_ds_command *cmd,
static int lbs_cmd_802_11_rf_tx_power(struct cmd_ds_command *cmd,
u16 cmd_action, void *pdata_buf)
{
@ -603,8 +656,7 @@ static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv,
return 0;
}
static int lbs_cmd_802_11_monitor_mode(struct lbs_private *priv,
struct cmd_ds_command *cmd,
static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
u16 cmd_action, void *pdata_buf)
{
struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
@ -762,6 +814,7 @@ int lbs_get_channel(struct lbs_private *priv)
lbs_deb_enter(LBS_DEB_CMD);
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
@ -777,6 +830,22 @@ out:
return ret;
}
int lbs_update_channel(struct lbs_private *priv)
{
int ret;
/* the channel in f/w could be out of sync; get the current channel */
lbs_deb_enter(LBS_DEB_ASSOC);
ret = lbs_get_channel(priv);
if (ret > 0) {
priv->curbssparams.channel = ret;
ret = 0;
}
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
/**
* @brief Set the radio channel
*
@ -793,6 +862,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
lbs_deb_enter(LBS_DEB_CMD);
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
cmd.channel = cpu_to_le16(channel);
@ -831,8 +901,7 @@ static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
return 0;
}
static int lbs_cmd_reg_access(struct lbs_private *priv,
struct cmd_ds_command *cmdptr,
static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
u8 cmd_action, void *pdata_buf)
{
struct lbs_offset_value *offval;
@ -906,53 +975,7 @@ static int lbs_cmd_reg_access(struct lbs_private *priv,
return 0;
}
static int lbs_cmd_802_11_mac_address(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action)
{
lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS);
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
S_DS_GEN);
cmd->result = 0;
cmd->params.macadd.action = cpu_to_le16(cmd_action);
if (cmd_action == CMD_ACT_SET) {
memcpy(cmd->params.macadd.macadd,
priv->current_addr, ETH_ALEN);
lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", priv->current_addr, 6);
}
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
static int lbs_cmd_802_11_eeprom_access(struct lbs_private *priv,
struct cmd_ds_command *cmd,
int cmd_action, void *pdata_buf)
{
struct lbs_ioctl_regrdwr *ea = pdata_buf;
lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(CMD_802_11_EEPROM_ACCESS);
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
S_DS_GEN);
cmd->result = 0;
cmd->params.rdeeprom.action = cpu_to_le16(ea->action);
cmd->params.rdeeprom.offset = cpu_to_le16(ea->offset);
cmd->params.rdeeprom.bytecount = cpu_to_le16(ea->NOB);
cmd->params.rdeeprom.value = 0;
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
static int lbs_cmd_bt_access(struct lbs_private *priv,
struct cmd_ds_command *cmd,
static int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
u16 cmd_action, void *pdata_buf)
{
struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
@ -989,8 +1012,7 @@ static int lbs_cmd_bt_access(struct lbs_private *priv,
return 0;
}
static int lbs_cmd_fwt_access(struct lbs_private *priv,
struct cmd_ds_command *cmd,
static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
u16 cmd_action, void *pdata_buf)
{
struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
@ -1029,7 +1051,6 @@ int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
lbs_deb_leave(LBS_DEB_CMD);
return ret;
}
EXPORT_SYMBOL_GPL(lbs_mesh_access);
int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan)
{
@ -1143,9 +1164,9 @@ static void lbs_submit_command(struct lbs_private *priv,
command == CMD_802_11_AUTHENTICATE)
timeo = 10 * HZ;
lbs_deb_host("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n",
command, le16_to_cpu(cmd->seqnum), cmdsize, jiffies);
lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
command, le16_to_cpu(cmd->seqnum), cmdsize);
lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
@ -1154,9 +1175,7 @@ static void lbs_submit_command(struct lbs_private *priv,
/* Let the timer kick in and retry, and potentially reset
the whole thing if the condition persists */
timeo = HZ;
} else
lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n",
command, jiffies);
}
/* Setup the timer after transmit command */
mod_timer(&priv->command_timer, jiffies + timeo);
@ -1164,24 +1183,6 @@ static void lbs_submit_command(struct lbs_private *priv,
lbs_deb_leave(LBS_DEB_HOST);
}
static int lbs_cmd_mac_control(struct lbs_private *priv,
struct cmd_ds_command *cmd)
{
struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(CMD_MAC_CONTROL);
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
mac->action = cpu_to_le16(priv->currentpacketfilter);
lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
/**
* This function inserts command node to cmdfreeq
* after cleans it. Requires priv->driver_lock held.
@ -1224,7 +1225,7 @@ void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
cmd->cmdwaitqwoken = 1;
wake_up_interruptible(&cmd->cmdwait_q);
if (!cmd->callback)
if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
__lbs_cleanup_and_insert_cmd(priv, cmd);
priv->cur_cmd = NULL;
}
@ -1268,18 +1269,20 @@ int lbs_set_radio_control(struct lbs_private *priv)
return ret;
}
int lbs_set_mac_packet_filter(struct lbs_private *priv)
void lbs_set_mac_control(struct lbs_private *priv)
{
int ret = 0;
struct cmd_ds_mac_control cmd;
lbs_deb_enter(LBS_DEB_CMD);
/* Send MAC control command to station */
ret = lbs_prepare_and_send_command(priv,
CMD_MAC_CONTROL, 0, 0, 0, NULL);
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
cmd.action = cpu_to_le16(priv->mac_control);
cmd.reserved = 0;
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
lbs_cmd_async(priv, CMD_MAC_CONTROL,
&cmd.hdr, sizeof(cmd));
lbs_deb_leave(LBS_DEB_CMD);
}
/**
@ -1328,7 +1331,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
goto done;
}
lbs_set_cmd_ctrl_node(priv, cmdnode, pdata_buf);
cmdnode->callback = NULL;
cmdnode->callback_arg = (unsigned long)pdata_buf;
cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
@ -1343,15 +1347,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
switch (cmd_no) {
case CMD_802_11_PS_MODE:
ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action);
break;
case CMD_802_11_SCAN:
ret = lbs_cmd_80211_scan(priv, cmdptr, pdata_buf);
break;
case CMD_MAC_CONTROL:
ret = lbs_cmd_mac_control(priv, cmdptr);
ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
break;
case CMD_802_11_ASSOCIATE:
@ -1366,25 +1362,15 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
case CMD_802_11_AD_HOC_START:
ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
break;
case CMD_CODE_DNLD:
break;
case CMD_802_11_RESET:
ret = lbs_cmd_802_11_reset(priv, cmdptr, cmd_action);
break;
case CMD_802_11_GET_LOG:
ret = lbs_cmd_802_11_get_log(priv, cmdptr);
ret = lbs_cmd_802_11_reset(cmdptr, cmd_action);
break;
case CMD_802_11_AUTHENTICATE:
ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
break;
case CMD_802_11_GET_STAT:
ret = lbs_cmd_802_11_get_stat(priv, cmdptr);
break;
case CMD_802_11_SNMP_MIB:
ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr,
cmd_action, cmd_oid, pdata_buf);
@ -1393,12 +1379,12 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
case CMD_MAC_REG_ACCESS:
case CMD_BBP_REG_ACCESS:
case CMD_RF_REG_ACCESS:
ret = lbs_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
break;
case CMD_802_11_RF_TX_POWER:
ret = lbs_cmd_802_11_rf_tx_power(priv, cmdptr,
cmd_action, pdata_buf);
ret = lbs_cmd_802_11_rf_tx_power(cmdptr,
cmd_action, pdata_buf);
break;
case CMD_802_11_RATE_ADAPT_RATESET:
@ -1411,7 +1397,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
break;
case CMD_802_11_MONITOR_MODE:
ret = lbs_cmd_802_11_monitor_mode(priv, cmdptr,
ret = lbs_cmd_802_11_monitor_mode(cmdptr,
cmd_action, pdata_buf);
break;
@ -1424,26 +1410,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
break;
case CMD_802_11_AD_HOC_STOP:
ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr);
break;
case CMD_802_11_KEY_MATERIAL:
ret = lbs_cmd_802_11_key_material(priv, cmdptr, cmd_action,
cmd_oid, pdata_buf);
break;
case CMD_802_11_PAIRWISE_TSC:
break;
case CMD_802_11_GROUP_TSC:
break;
case CMD_802_11_MAC_ADDRESS:
ret = lbs_cmd_802_11_mac_address(priv, cmdptr, cmd_action);
break;
case CMD_802_11_EEPROM_ACCESS:
ret = lbs_cmd_802_11_eeprom_access(priv, cmdptr,
cmd_action, pdata_buf);
ret = lbs_cmd_80211_ad_hoc_stop(cmdptr);
break;
case CMD_802_11_SET_AFC:
@ -1499,22 +1466,12 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
break;
}
case CMD_802_11_PWR_CFG:
cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG);
cmdptr->size =
cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg) +
S_DS_GEN);
memmove(&cmdptr->params.pwrcfg, pdata_buf,
sizeof(struct cmd_ds_802_11_pwr_cfg));
ret = 0;
break;
case CMD_BT_ACCESS:
ret = lbs_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf);
ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
break;
case CMD_FWT_ACCESS:
ret = lbs_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf);
ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
break;
case CMD_GET_TSF:
@ -1565,7 +1522,6 @@ done:
lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
return ret;
}
EXPORT_SYMBOL_GPL(lbs_prepare_and_send_command);
/**
* @brief This function allocates the command buffer and link
@ -1687,36 +1643,6 @@ static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
return tempnode;
}
/**
* @brief This function cleans command node.
*
* @param ptempnode A pointer to cmdCtrlNode structure
* @return n/a
*/
/**
* @brief This function initializes the command node.
*
* @param priv A pointer to struct lbs_private structure
* @param ptempnode A pointer to cmd_ctrl_node structure
* @param pdata_buf A pointer to informaion buffer
* @return 0 or -1
*/
static void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
struct cmd_ctrl_node *ptempnode,
void *pdata_buf)
{
lbs_deb_enter(LBS_DEB_HOST);
if (!ptempnode)
return;
ptempnode->callback = NULL;
ptempnode->callback_arg = (unsigned long)pdata_buf;
lbs_deb_leave(LBS_DEB_HOST);
}
/**
* @brief This function executes next command in command
* pending queue. It will put fimware back to PS mode
@ -1732,9 +1658,9 @@ int lbs_execute_next_command(struct lbs_private *priv)
unsigned long flags;
int ret = 0;
// Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
// only caller to us is lbs_thread() and we get even when a
// data packet is received
/* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
* only caller to us is lbs_thread() and we get even when a
* data packet is received */
lbs_deb_enter(LBS_DEB_THREAD);
spin_lock_irqsave(&priv->driver_lock, flags);
@ -1898,44 +1824,35 @@ void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
lbs_deb_leave(LBS_DEB_WEXT);
}
static int sendconfirmsleep(struct lbs_private *priv, u8 *cmdptr, u16 size)
static void lbs_send_confirmsleep(struct lbs_private *priv)
{
unsigned long flags;
int ret = 0;
int ret;
lbs_deb_enter(LBS_DEB_HOST);
lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep,
sizeof(confirm_sleep));
lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n",
size);
lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size);
ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
spin_lock_irqsave(&priv->driver_lock, flags);
if (priv->intcounter || priv->currenttxskb)
lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n",
priv->intcounter, priv->currenttxskb);
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep,
sizeof(confirm_sleep));
if (ret) {
lbs_pr_alert(
"SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n");
} else {
spin_lock_irqsave(&priv->driver_lock, flags);
if (!priv->intcounter) {
priv->psstate = PS_STATE_SLEEP;
} else {
lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n",
priv->intcounter);
}
spin_unlock_irqrestore(&priv->driver_lock, flags);
lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
lbs_pr_alert("confirm_sleep failed\n");
goto out;
}
lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
return ret;
spin_lock_irqsave(&priv->driver_lock, flags);
/* We don't get a response on the sleep-confirmation */
priv->dnld_sent = DNLD_RES_RECEIVED;
/* If nothing to do, go back to sleep (?) */
if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx])
priv->psstate = PS_STATE_SLEEP;
spin_unlock_irqrestore(&priv->driver_lock, flags);
out:
lbs_deb_leave(LBS_DEB_HOST);
}
void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
@ -1983,33 +1900,35 @@ void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
* @param psmode Power Saving mode
* @return n/a
*/
void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode)
void lbs_ps_confirm_sleep(struct lbs_private *priv)
{
unsigned long flags =0;
u8 allowed = 1;
int allowed = 1;
lbs_deb_enter(LBS_DEB_HOST);
spin_lock_irqsave(&priv->driver_lock, flags);
if (priv->dnld_sent) {
allowed = 0;
lbs_deb_host("dnld_sent was set\n");
}
spin_lock_irqsave(&priv->driver_lock, flags);
/* In-progress command? */
if (priv->cur_cmd) {
allowed = 0;
lbs_deb_host("cur_cmd was set\n");
}
if (priv->intcounter > 0) {
/* Pending events or command responses? */
if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
allowed = 0;
lbs_deb_host("intcounter %d\n", priv->intcounter);
lbs_deb_host("pending events or command responses\n");
}
spin_unlock_irqrestore(&priv->driver_lock, flags);
if (allowed) {
lbs_deb_host("sending lbs_ps_confirm_sleep\n");
sendconfirmsleep(priv, (u8 *) & priv->lbs_ps_confirm_sleep,
sizeof(struct PS_CMD_ConfirmSleep));
lbs_send_confirmsleep(priv);
} else {
lbs_deb_host("sleep confirm has been delayed\n");
}
@ -2018,39 +1937,10 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode)
}
/**
* @brief Simple callback that copies response back into command
*
* @param priv A pointer to struct lbs_private structure
* @param extra A pointer to the original command structure for which
* 'resp' is a response
* @param resp A pointer to the command response
*
* @return 0 on success, error on failure
*/
int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
struct cmd_header *resp)
{
struct cmd_header *buf = (void *)extra;
uint16_t copy_len;
lbs_deb_enter(LBS_DEB_CMD);
copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
lbs_deb_cmd("Copying back %u bytes; command response was %u bytes, "
"copy back buffer was %u bytes\n", copy_len,
le16_to_cpu(resp->size), le16_to_cpu(buf->size));
memcpy(buf, resp, copy_len);
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command,
struct cmd_header *in_cmd, int in_cmd_size,
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
unsigned long callback_arg)
static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
unsigned long callback_arg)
{
struct cmd_ctrl_node *cmdnode;
@ -2087,9 +1977,6 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command
lbs_deb_host("PREP_CMD: command 0x%04x\n", command);
/* here was the big old switch() statement, which is now obsolete,
* because the caller of lbs_cmd() sets up all of *cmd for us. */
cmdnode->cmdwaitqwoken = 0;
lbs_queue_cmd(priv, cmdnode);
wake_up_interruptible(&priv->waitq);
@ -2099,6 +1986,15 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command
return cmdnode;
}
void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
struct cmd_header *in_cmd, int in_cmd_size)
{
lbs_deb_enter(LBS_DEB_CMD);
__lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
lbs_cmd_async_callback, 0);
lbs_deb_leave(LBS_DEB_CMD);
}
int __lbs_cmd(struct lbs_private *priv, uint16_t command,
struct cmd_header *in_cmd, int in_cmd_size,
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),

View File

@ -18,12 +18,9 @@
#define lbs_cmd_with_response(priv, cmdnr, cmd) \
lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
/* __lbs_cmd() will free the cmdnode and return success/failure.
__lbs_cmd_async() requires that the callback free the cmdnode */
struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command,
struct cmd_header *in_cmd, int in_cmd_size,
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
unsigned long callback_arg);
void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
struct cmd_header *in_cmd, int in_cmd_size);
int __lbs_cmd(struct lbs_private *priv, uint16_t command,
struct cmd_header *in_cmd, int in_cmd_size,
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
@ -57,5 +54,7 @@ int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
struct assoc_request *assoc);
int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
uint16_t *enable);
int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
struct assoc_request *assoc);
#endif /* _LBS_CMD_H */

View File

@ -12,7 +12,7 @@
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "join.h"
#include "assoc.h"
#include "wext.h"
/**
@ -74,7 +74,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
lbs_deb_cmd("disconnected, so exit PS mode\n");
lbs_ps_wakeup(priv, 0);
}
lbs_deb_leave(LBS_DEB_CMD);
lbs_deb_leave(LBS_DEB_ASSOC);
}
/**
@ -146,22 +146,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
return ret;
}
static int lbs_ret_802_11_stat(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
lbs_deb_enter(LBS_DEB_CMD);
/* currently priv->wlan802_11Stat is unused
struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
// TODO Convert it to Big endian befor copy
memcpy(&priv->wlan802_11Stat,
p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
*/
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
@ -204,74 +188,6 @@ static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
return 0;
}
static int lbs_ret_802_11_key_material(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_key_material *pkeymaterial =
&resp->params.keymaterial;
u16 action = le16_to_cpu(pkeymaterial->action);
lbs_deb_enter(LBS_DEB_CMD);
/* Copy the returned key to driver private data */
if (action == CMD_ACT_GET) {
u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
while (buf_ptr < resp_end) {
struct MrvlIEtype_keyParamSet * pkeyparamset =
(struct MrvlIEtype_keyParamSet *) buf_ptr;
struct enc_key * pkey;
u16 param_set_len = le16_to_cpu(pkeyparamset->length);
u16 key_len = le16_to_cpu(pkeyparamset->keylen);
u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo);
u16 key_type = le16_to_cpu(pkeyparamset->keytypeid);
u8 * end;
end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
+ sizeof (pkeyparamset->length)
+ param_set_len;
/* Make sure we don't access past the end of the IEs */
if (end > resp_end)
break;
if (key_flags & KEY_INFO_WPA_UNICAST)
pkey = &priv->wpa_unicast_key;
else if (key_flags & KEY_INFO_WPA_MCAST)
pkey = &priv->wpa_mcast_key;
else
break;
/* Copy returned key into driver */
memset(pkey, 0, sizeof(struct enc_key));
if (key_len > sizeof(pkey->key))
break;
pkey->type = key_type;
pkey->flags = key_flags;
pkey->len = key_len;
memcpy(pkey->key, pkeyparamset->key, pkey->len);
buf_ptr = end + 1;
}
}
lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
static int lbs_ret_802_11_mac_address(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
lbs_deb_enter(LBS_DEB_CMD);
memcpy(priv->current_addr, macadd->macadd, ETH_ALEN);
lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
@ -333,45 +249,6 @@ static int lbs_ret_802_11_rssi(struct lbs_private *priv,
return 0;
}
static int lbs_ret_802_11_eeprom_access(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct lbs_ioctl_regrdwr *pbuf;
pbuf = (struct lbs_ioctl_regrdwr *) priv->prdeeprom;
lbs_deb_enter_args(LBS_DEB_CMD, "len %d",
le16_to_cpu(resp->params.rdeeprom.bytecount));
if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
pbuf->NOB = 0;
lbs_deb_cmd("EEPROM read length too big\n");
return -1;
}
pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
if (pbuf->NOB > 0) {
memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value,
le16_to_cpu(resp->params.rdeeprom.bytecount));
lbs_deb_hex(LBS_DEB_CMD, "EEPROM", (char *)&pbuf->value,
le16_to_cpu(resp->params.rdeeprom.bytecount));
}
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
static int lbs_ret_get_log(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
lbs_deb_enter(LBS_DEB_CMD);
/* Stored little-endian */
memcpy(&priv->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
struct cmd_ds_command *resp)
{
@ -390,7 +267,6 @@ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
}
static inline int handle_cmd_response(struct lbs_private *priv,
unsigned long dummy,
struct cmd_header *cmd_response)
{
struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response;
@ -407,14 +283,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
ret = lbs_ret_reg_access(priv, respcmd, resp);
break;
case CMD_RET(CMD_802_11_SCAN):
ret = lbs_ret_80211_scan(priv, resp);
break;
case CMD_RET(CMD_802_11_GET_LOG):
ret = lbs_ret_get_log(priv, resp);
break;
case CMD_RET_802_11_ASSOCIATE:
case CMD_RET(CMD_802_11_ASSOCIATE):
case CMD_RET(CMD_802_11_REASSOCIATE):
@ -423,7 +291,7 @@ static inline int handle_cmd_response(struct lbs_private *priv,
case CMD_RET(CMD_802_11_DISASSOCIATE):
case CMD_RET(CMD_802_11_DEAUTHENTICATE):
ret = lbs_ret_80211_disassociate(priv, resp);
ret = lbs_ret_80211_disassociate(priv);
break;
case CMD_RET(CMD_802_11_AD_HOC_START):
@ -431,10 +299,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
ret = lbs_ret_80211_ad_hoc_start(priv, resp);
break;
case CMD_RET(CMD_802_11_GET_STAT):
ret = lbs_ret_802_11_stat(priv, resp);
break;
case CMD_RET(CMD_802_11_SNMP_MIB):
ret = lbs_ret_802_11_snmp_mib(priv, resp);
break;
@ -453,7 +317,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
break;
case CMD_RET(CMD_MAC_MULTICAST_ADR):
case CMD_RET(CMD_MAC_CONTROL):
case CMD_RET(CMD_802_11_RESET):
case CMD_RET(CMD_802_11_AUTHENTICATE):
case CMD_RET(CMD_802_11_BEACON_STOP):
@ -467,24 +330,12 @@ static inline int handle_cmd_response(struct lbs_private *priv,
ret = lbs_ret_802_11_rssi(priv, resp);
break;
case CMD_RET(CMD_802_11_MAC_ADDRESS):
ret = lbs_ret_802_11_mac_address(priv, resp);
break;
case CMD_RET(CMD_802_11_AD_HOC_STOP):
ret = lbs_ret_80211_ad_hoc_stop(priv, resp);
break;
case CMD_RET(CMD_802_11_KEY_MATERIAL):
ret = lbs_ret_802_11_key_material(priv, resp);
break;
case CMD_RET(CMD_802_11_EEPROM_ACCESS):
ret = lbs_ret_802_11_eeprom_access(priv, resp);
ret = lbs_ret_80211_ad_hoc_stop(priv);
break;
case CMD_RET(CMD_802_11D_DOMAIN_INFO):
ret = lbs_ret_802_11d_domain_info(priv, resp);
ret = lbs_ret_802_11d_domain_info(resp);
break;
case CMD_RET(CMD_802_11_TPC_CFG):
@ -500,14 +351,6 @@ static inline int handle_cmd_response(struct lbs_private *priv,
spin_unlock_irqrestore(&priv->driver_lock, flags);
break;
case CMD_RET(CMD_802_11_PWR_CFG):
spin_lock_irqsave(&priv->driver_lock, flags);
memmove((void *)priv->cur_cmd->callback_arg, &resp->params.pwrcfg,
sizeof(struct cmd_ds_802_11_pwr_cfg));
spin_unlock_irqrestore(&priv->driver_lock, flags);
break;
case CMD_RET(CMD_GET_TSF):
spin_lock_irqsave(&priv->driver_lock, flags);
memcpy((void *)priv->cur_cmd->callback_arg,
@ -541,7 +384,7 @@ static inline int handle_cmd_response(struct lbs_private *priv,
return ret;
}
int lbs_process_rx_command(struct lbs_private *priv)
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
{
uint16_t respcmd, curcmd;
struct cmd_header *resp;
@ -561,26 +404,24 @@ int lbs_process_rx_command(struct lbs_private *priv)
goto done;
}
resp = (void *)priv->upld_buf;
curcmd = le16_to_cpu(resp->command);
resp = (void *)data;
curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
respcmd = le16_to_cpu(resp->command);
result = le16_to_cpu(resp->result);
lbs_deb_host("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies);
lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len);
lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n",
respcmd, le16_to_cpu(resp->seqnum), len);
lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len);
if (resp->seqnum != resp->seqnum) {
if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
le16_to_cpu(resp->seqnum), le16_to_cpu(resp->seqnum));
le16_to_cpu(resp->seqnum), le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum));
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
goto done;
}
if (respcmd != CMD_RET(curcmd) &&
respcmd != CMD_802_11_ASSOCIATE && curcmd != CMD_RET_802_11_ASSOCIATE) {
respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) {
lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd);
spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
@ -689,7 +530,7 @@ int lbs_process_rx_command(struct lbs_private *priv)
ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
resp);
} else
ret = handle_cmd_response(priv, 0, resp);
ret = handle_cmd_response(priv, resp);
spin_lock_irqsave(&priv->driver_lock, flags);
@ -707,21 +548,20 @@ done:
static int lbs_send_confirmwake(struct lbs_private *priv)
{
struct cmd_header *cmd = &priv->lbs_ps_confirm_wake;
struct cmd_header cmd;
int ret = 0;
lbs_deb_enter(LBS_DEB_HOST);
cmd->command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
cmd->size = cpu_to_le16(sizeof(*cmd));
cmd->seqnum = cpu_to_le16(++priv->seqnum);
cmd->result = 0;
cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
cmd.size = cpu_to_le16(sizeof(cmd));
cmd.seqnum = cpu_to_le16(++priv->seqnum);
cmd.result = 0;
lbs_deb_host("SEND_WAKEC_CMD: before download\n");
lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd,
sizeof(cmd));
lbs_deb_hex(LBS_DEB_HOST, "wake confirm command", (void *)cmd, sizeof(*cmd));
ret = priv->hw_host_to_card(priv, MVMS_CMD, (void *)cmd, sizeof(*cmd));
ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd));
if (ret)
lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
@ -729,22 +569,15 @@ static int lbs_send_confirmwake(struct lbs_private *priv)
return ret;
}
int lbs_process_event(struct lbs_private *priv)
int lbs_process_event(struct lbs_private *priv, u32 event)
{
int ret = 0;
u32 eventcause;
lbs_deb_enter(LBS_DEB_CMD);
spin_lock_irq(&priv->driver_lock);
eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT;
spin_unlock_irq(&priv->driver_lock);
lbs_deb_cmd("event cause %d\n", eventcause);
switch (eventcause) {
switch (event) {
case MACREG_INT_CODE_LINK_SENSED:
lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
lbs_deb_cmd("EVENT: link sensed\n");
break;
case MACREG_INT_CODE_DEAUTHENTICATED:
@ -763,7 +596,7 @@ int lbs_process_event(struct lbs_private *priv)
break;
case MACREG_INT_CODE_PS_SLEEP:
lbs_deb_cmd("EVENT: sleep\n");
lbs_deb_cmd("EVENT: ps sleep\n");
/* handle unexpected PS SLEEP event */
if (priv->psstate == PS_STATE_FULL_POWER) {
@ -773,17 +606,17 @@ int lbs_process_event(struct lbs_private *priv)
}
priv->psstate = PS_STATE_PRE_SLEEP;
lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
lbs_ps_confirm_sleep(priv);
break;
case MACREG_INT_CODE_HOST_AWAKE:
lbs_deb_cmd("EVENT: HOST_AWAKE\n");
lbs_deb_cmd("EVENT: host awake\n");
lbs_send_confirmwake(priv);
break;
case MACREG_INT_CODE_PS_AWAKE:
lbs_deb_cmd("EVENT: awake\n");
lbs_deb_cmd("EVENT: ps awake\n");
/* handle unexpected PS AWAKE event */
if (priv->psstate == PS_STATE_FULL_POWER) {
lbs_deb_cmd(
@ -814,14 +647,16 @@ int lbs_process_event(struct lbs_private *priv)
lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
break;
case MACREG_INT_CODE_MIB_CHANGED:
case MACREG_INT_CODE_INIT_DONE:
break;
case MACREG_INT_CODE_MIB_CHANGED:
lbs_deb_cmd("EVENT: MIB CHANGED\n");
break;
case MACREG_INT_CODE_INIT_DONE:
lbs_deb_cmd("EVENT: INIT DONE\n");
break;
case MACREG_INT_CODE_ADHOC_BCN_LOST:
lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
break;
case MACREG_INT_CODE_RSSI_LOW:
lbs_pr_alert("EVENT: rssi low\n");
break;
@ -856,14 +691,10 @@ int lbs_process_event(struct lbs_private *priv)
break;
default:
lbs_pr_alert("EVENT: unknown event id %d\n", eventcause);
lbs_pr_alert("EVENT: unknown event id %d\n", event);
break;
}
spin_lock_irq(&priv->driver_lock);
priv->eventcause = 0;
spin_unlock_irq(&priv->driver_lock);
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}

View File

@ -19,7 +19,7 @@ static char *szStates[] = {
};
#ifdef PROC_DEBUG
static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev);
static void lbs_debug_init(struct lbs_private *priv);
#endif
static int open_file_generic(struct inode *inode, struct file *file)
@ -78,7 +78,7 @@ static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
pos += snprintf(buf+pos, len-pos,
"%02u| %03d | %04ld | %s |",
"%02u| %03d | %04d | %s |",
numscansdone, iter_bss->channel, iter_bss->rssi,
print_mac(mac, iter_bss->bssid));
pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
@ -164,172 +164,6 @@ out_unlock:
return ret;
}
static ssize_t lbs_extscan(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
union iwreq_data wrqu;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
lbs_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
memset(&wrqu, 0, sizeof(union iwreq_data));
wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
out_unlock:
free_page(addr);
return count;
}
static void lbs_parse_bssid(char *buf, size_t count,
struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold;
unsigned int mac[ETH_ALEN];
hold = strstr(buf, "bssid=");
if (!hold)
return;
hold += 6;
sscanf(hold, MAC_FMT, mac, mac+1, mac+2, mac+3, mac+4, mac+5);
memcpy(scan_cfg->bssid, mac, ETH_ALEN);
}
static void lbs_parse_ssid(char *buf, size_t count,
struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold, *end;
ssize_t size;
hold = strstr(buf, "ssid=");
if (!hold)
return;
hold += 5;
end = strchr(hold, ' ');
if (!end)
end = buf + count - 1;
size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
strncpy(scan_cfg->ssid, hold, size);
return;
}
static int lbs_parse_clear(char *buf, size_t count, const char *tag)
{
char *hold;
int val;
hold = strstr(buf, tag);
if (!hold)
return 0;
hold += strlen(tag);
sscanf(hold, "%d", &val);
if (val != 0)
val = 1;
return val;
}
static int lbs_parse_dur(char *buf, size_t count,
struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold;
int val;
hold = strstr(buf, "dur=");
if (!hold)
return 0;
hold += 4;
sscanf(hold, "%d", &val);
return val;
}
static void lbs_parse_type(char *buf, size_t count,
struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold;
int val;
hold = strstr(buf, "type=");
if (!hold)
return;
hold += 5;
sscanf(hold, "%d", &val);
/* type=1,2 or 3 */
if (val < 1 || val > 3)
return;
scan_cfg->bsstype = val;
return;
}
static ssize_t lbs_setuserscan(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
struct lbs_ioctl_user_scan_cfg *scan_cfg;
union iwreq_data wrqu;
int dur;
char *buf = (char *)get_zeroed_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_buf;
}
scan_cfg = kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg), GFP_KERNEL);
if (!scan_cfg) {
res = -ENOMEM;
goto out_buf;
}
res = count;
scan_cfg->bsstype = LBS_SCAN_BSS_TYPE_ANY;
dur = lbs_parse_dur(buf, count, scan_cfg);
lbs_parse_bssid(buf, count, scan_cfg);
scan_cfg->clear_bssid = lbs_parse_clear(buf, count, "clear_bssid=");
lbs_parse_ssid(buf, count, scan_cfg);
scan_cfg->clear_ssid = lbs_parse_clear(buf, count, "clear_ssid=");
lbs_parse_type(buf, count, scan_cfg);
lbs_scan_networks(priv, scan_cfg, 1);
wait_event_interruptible(priv->cmd_pending,
priv->surpriseremoved || !priv->last_scanned_channel);
if (priv->surpriseremoved)
goto out_scan_cfg;
memset(&wrqu, 0x00, sizeof(union iwreq_data));
wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
out_scan_cfg:
kfree(scan_cfg);
out_buf:
free_page((unsigned long)buf);
return res;
}
/*
* When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
* get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
@ -478,8 +312,8 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
if (tlv_type != TLV_TYPE_BCNMISS)
tlv->freq = freq;
/* The command header, the event mask, and the one TLV */
events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 2 + sizeof(*tlv));
/* The command header, the action, the event mask, and one TLV */
events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv));
ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
@ -856,8 +690,6 @@ static struct lbs_debugfs_files debugfs_files[] = {
write_file_dummy), },
{ "sleepparams", 0644, FOPS(lbs_sleepparams_read,
lbs_sleepparams_write), },
{ "extscan", 0600, FOPS(NULL, lbs_extscan), },
{ "setuserscan", 0600, FOPS(NULL, lbs_setuserscan), },
};
static struct lbs_debugfs_files debugfs_events_files[] = {
@ -946,7 +778,7 @@ void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
}
#ifdef PROC_DEBUG
lbs_debug_init(priv, dev);
lbs_debug_init(priv);
#endif
exit:
return;
@ -992,7 +824,6 @@ struct debug_data {
/* To debug any member of struct lbs_private, simply add one line here.
*/
static struct debug_data items[] = {
{"intcounter", item_size(intcounter), item_addr(intcounter)},
{"psmode", item_size(psmode), item_addr(psmode)},
{"psstate", item_size(psstate), item_addr(psstate)},
};
@ -1120,7 +951,7 @@ static struct file_operations lbs_debug_fops = {
* @param dev pointer net_device
* @return N/A
*/
static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev)
static void lbs_debug_init(struct lbs_private *priv)
{
int i;

View File

@ -17,9 +17,9 @@ struct net_device;
struct cmd_ctrl_node;
struct cmd_ds_command;
int lbs_set_mac_packet_filter(struct lbs_private *priv);
void lbs_set_mac_control(struct lbs_private *priv);
void lbs_send_tx_feedback(struct lbs_private *priv);
void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
int lbs_free_cmd_buffer(struct lbs_private *priv);
@ -30,17 +30,16 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
int lbs_allocate_cmd_buffer(struct lbs_private *priv);
int lbs_execute_next_command(struct lbs_private *priv);
int lbs_process_event(struct lbs_private *priv);
void lbs_interrupt(struct lbs_private *priv);
int lbs_process_event(struct lbs_private *priv, u32 event);
void lbs_queue_event(struct lbs_private *priv, u32 event);
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
int lbs_set_radio_control(struct lbs_private *priv);
u32 lbs_fw_index_to_data_rate(u8 index);
u8 lbs_data_rate_to_fw_index(u32 rate);
void lbs_get_fwversion(struct lbs_private *priv,
char *fwversion,
int maxlen);
/** The proc fs interface */
int lbs_process_rx_command(struct lbs_private *priv);
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
int result);
int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
@ -49,7 +48,7 @@ int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode);
void lbs_ps_confirm_sleep(struct lbs_private *priv);
void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
@ -63,14 +62,17 @@ void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str);
/* main.c */
struct chan_freq_power *lbs_get_region_cfp_table(u8 region,
u8 band,
int *cfp_no);
struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
int lbs_remove_card(struct lbs_private *priv);
int lbs_start_card(struct lbs_private *priv);
int lbs_stop_card(struct lbs_private *priv);
int lbs_reset_device(struct lbs_private *priv);
void lbs_host_to_card_done(struct lbs_private *priv);
int lbs_update_channel(struct lbs_private *priv);
#ifndef CONFIG_IEEE80211
const char *escape_essid(const char *essid, u8 essid_len);
#endif
#endif

View File

@ -53,14 +53,14 @@ do { if ((lbs_debug & (grp)) == (grp)) \
#endif
#define lbs_deb_enter(grp) \
LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s():%d\n", __FUNCTION__, __LINE__);
LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__);
#define lbs_deb_enter_args(grp, fmt, args...) \
LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt "):%d\n", __FUNCTION__, ## args, __LINE__);
LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
#define lbs_deb_leave(grp) \
LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s():%d\n", __FUNCTION__, __LINE__);
LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s()\n", __func__);
#define lbs_deb_leave_args(grp, fmt, args...) \
LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s():%d, " fmt "\n", \
__FUNCTION__, __LINE__, ##args);
LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
__func__, ##args);
#define lbs_deb_main(fmt, args...) LBS_DEB_LL(LBS_DEB_MAIN, " main", fmt, ##args)
#define lbs_deb_net(fmt, args...) LBS_DEB_LL(LBS_DEB_NET, " net", fmt, ##args)
#define lbs_deb_mesh(fmt, args...) LBS_DEB_LL(LBS_DEB_MESH, " mesh", fmt, ##args)
@ -165,7 +165,7 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
#define MRVDRV_MAX_CHANNELS_PER_SCAN 14
#define MRVDRV_MIN_BEACON_INTERVAL 20
#define MRVDRV_MAX_BEACON_INTERVAL 1000
#define MRVDRV_MAX_BEACON_INTERVAL 10000
#define MRVDRV_BEACON_INTERVAL 100
#define MARVELL_MESH_IE_LENGTH 9
@ -177,8 +177,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
#define MRVDRV_CMD_UPLD_RDY 0x0008
#define MRVDRV_CARDEVENT 0x0010
#define SBI_EVENT_CAUSE_SHIFT 3
/** TxPD status */
/* Station firmware use TxPD status field to report final Tx transmit

View File

@ -10,9 +10,10 @@
#include <linux/wireless.h>
#include <linux/ethtool.h>
#include <linux/debugfs.h>
#include <net/ieee80211.h>
#include "defs.h"
#include "scan.h"
#include "hostcmd.h"
extern struct ethtool_ops lbs_ethtool_ops;
@ -102,7 +103,6 @@ struct lbs_private {
int mesh_open;
int infra_open;
int mesh_autostart_enabled;
__le16 boot2_version;
char name[DEV_NAME_LEN];
@ -129,10 +129,6 @@ struct lbs_private {
u32 bbp_offset;
u32 rf_offset;
/** Upload length */
u32 upld_len;
/* Upload buffer */
u8 upld_buf[LBS_UPLD_SIZE];
/* Download sent:
bit0 1/0=data_sent/data_tx_done,
bit1 1/0=cmd_sent/cmd_tx_done,
@ -144,27 +140,27 @@ struct lbs_private {
wait_queue_head_t waitq;
struct workqueue_struct *work_thread;
/** Scanning */
struct delayed_work scan_work;
struct delayed_work assoc_work;
struct work_struct sync_channel;
/* remember which channel was scanned last, != 0 if currently scanning */
int scan_channel;
u8 scan_ssid[IW_ESSID_MAX_SIZE + 1];
u8 scan_ssid_len;
/** Hardware access */
int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
int (*hw_get_int_status) (struct lbs_private *priv, u8 *);
int (*hw_read_event_cause) (struct lbs_private *);
/* Wake On LAN */
uint32_t wol_criteria;
uint8_t wol_gpio;
uint8_t wol_gap;
/* was struct lbs_adapter from here... */
/** Wlan adapter data structure*/
/** STATUS variables */
u8 fwreleasenumber[4];
u32 fwrelease;
u32 fwcapinfo;
/* protected with big lock */
struct mutex lock;
@ -176,7 +172,6 @@ struct lbs_private {
/** command-related variables */
u16 seqnum;
/* protected by big lock */
struct cmd_ctrl_node *cmd_array;
/** Current command */
@ -189,12 +184,17 @@ struct lbs_private {
struct list_head cmdpendingq;
wait_queue_head_t cmd_pending;
/* command related variables protected by priv->driver_lock */
/** Async and Sync Event variables */
u32 intcounter;
u32 eventcause;
u8 nodename[16]; /* nickname */
/* Command responses sent from the hardware to the driver */
u8 resp_idx;
u8 resp_buf[2][LBS_UPLD_SIZE];
u32 resp_len[2];
/* Events sent from hardware to driver */
struct kfifo *event_fifo;
/* nickname */
u8 nodename[16];
/** spin locks */
spinlock_t driver_lock;
@ -204,8 +204,6 @@ struct lbs_private {
int nr_retries;
int cmd_timed_out;
u8 hisregcpy;
/** current ssid/bssid related parameters*/
struct current_bss_params curbssparams;
@ -248,7 +246,7 @@ struct lbs_private {
struct sk_buff *currenttxskb;
/** NIC Operation characteristics */
u16 currentpacketfilter;
u16 mac_control;
u32 connect_status;
u32 mesh_connect_status;
u16 regioncode;
@ -263,9 +261,6 @@ struct lbs_private {
char ps_supported;
u8 needtowakeup;
struct PS_CMD_ConfirmSleep lbs_ps_confirm_sleep;
struct cmd_header lbs_ps_confirm_wake;
struct assoc_request * pending_assoc_req;
struct assoc_request * in_progress_assoc_req;
@ -316,16 +311,52 @@ struct lbs_private {
u32 enable11d;
/** MISCELLANEOUS */
u8 *prdeeprom;
struct lbs_offset_value offsetvalue;
struct cmd_ds_802_11_get_log logmsg;
u32 monitormode;
int last_scanned_channel;
u8 fw_ready;
};
extern struct cmd_confirm_sleep confirm_sleep;
/**
* @brief Structure used to store information for each beacon/probe response
*/
struct bss_descriptor {
u8 bssid[ETH_ALEN];
u8 ssid[IW_ESSID_MAX_SIZE + 1];
u8 ssid_len;
u16 capability;
u32 rssi;
u32 channel;
u16 beaconperiod;
u32 atimwindow;
/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
u8 mode;
/* zero-terminated array of supported data rates */
u8 rates[MAX_RATES + 1];
unsigned long last_scanned;
union ieeetypes_phyparamset phyparamset;
union IEEEtypes_ssparamset ssparamset;
struct ieeetypes_countryinfofullset countryinfo;
u8 wpa_ie[MAX_WPA_IE_LEN];
size_t wpa_ie_len;
u8 rsn_ie[MAX_WPA_IE_LEN];
size_t rsn_ie_len;
u8 mesh;
struct list_head list;
};
/** Association request
*
* Encapsulates all the options that describe a specific assocation request
@ -350,7 +381,7 @@ struct assoc_request {
u8 channel;
u8 band;
u8 mode;
u8 bssid[ETH_ALEN];
u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
/** WEP keys */
struct enc_key wep_keys[4];

View File

@ -6,7 +6,6 @@
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "join.h"
#include "wext.h"
#include "cmd.h"
@ -25,13 +24,14 @@ static void lbs_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
struct lbs_private *priv = (struct lbs_private *) dev->priv;
char fwver[32];
lbs_get_fwversion(priv, fwver, sizeof(fwver) - 1);
snprintf(info->fw_version, 32, "%u.%u.%u.p%u",
priv->fwrelease >> 24 & 0xff,
priv->fwrelease >> 16 & 0xff,
priv->fwrelease >> 8 & 0xff,
priv->fwrelease & 0xff);
strcpy(info->driver, "libertas");
strcpy(info->version, lbs_driver_version);
strcpy(info->fw_version, fwver);
}
/* All 8388 parts have 16KiB EEPROM size at the time of writing.
@ -48,66 +48,33 @@ static int lbs_ethtool_get_eeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 * bytes)
{
struct lbs_private *priv = (struct lbs_private *) dev->priv;
struct lbs_ioctl_regrdwr regctrl;
char *ptr;
struct cmd_ds_802_11_eeprom_access cmd;
int ret;
regctrl.action = 0;
regctrl.offset = eeprom->offset;
regctrl.NOB = eeprom->len;
lbs_deb_enter(LBS_DEB_ETHTOOL);
if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN)
return -EINVAL;
// mutex_lock(&priv->mutex);
priv->prdeeprom = kmalloc(eeprom->len+sizeof(regctrl), GFP_KERNEL);
if (!priv->prdeeprom)
return -ENOMEM;
memcpy(priv->prdeeprom, &regctrl, sizeof(regctrl));
/* +14 is for action, offset, and NOB in
* response */
lbs_deb_ethtool("action:%d offset: %x NOB: %02x\n",
regctrl.action, regctrl.offset, regctrl.NOB);
ret = lbs_prepare_and_send_command(priv,
CMD_802_11_EEPROM_ACCESS,
regctrl.action,
CMD_OPTION_WAITFORRSP, 0,
&regctrl);
if (ret) {
if (priv->prdeeprom)
kfree(priv->prdeeprom);
goto done;
if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN ||
eeprom->len > LBS_EEPROM_READ_LEN) {
ret = -EINVAL;
goto out;
}
mdelay(10);
cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) -
LBS_EEPROM_READ_LEN + eeprom->len);
cmd.action = cpu_to_le16(CMD_ACT_GET);
cmd.offset = cpu_to_le16(eeprom->offset);
cmd.len = cpu_to_le16(eeprom->len);
ret = lbs_cmd_with_response(priv, CMD_802_11_EEPROM_ACCESS, &cmd);
if (!ret)
memcpy(bytes, cmd.value, eeprom->len);
ptr = (char *)priv->prdeeprom;
/* skip the command header, but include the "value" u32 variable */
ptr = ptr + sizeof(struct lbs_ioctl_regrdwr) - 4;
/*
* Return the result back to the user
*/
memcpy(bytes, ptr, eeprom->len);
if (priv->prdeeprom)
kfree(priv->prdeeprom);
// mutex_unlock(&priv->mutex);
ret = 0;
done:
lbs_deb_enter_args(LBS_DEB_ETHTOOL, "ret %d", ret);
out:
lbs_deb_leave_args(LBS_DEB_ETHTOOL, "ret %d", ret);
return ret;
}
static void lbs_ethtool_get_stats(struct net_device * dev,
struct ethtool_stats * stats, u64 * data)
static void lbs_ethtool_get_stats(struct net_device *dev,
struct ethtool_stats *stats, uint64_t *data)
{
struct lbs_private *priv = dev->priv;
struct cmd_ds_mesh_access mesh_access;
@ -116,12 +83,12 @@ static void lbs_ethtool_get_stats(struct net_device * dev,
lbs_deb_enter(LBS_DEB_ETHTOOL);
/* Get Mesh Statistics */
ret = lbs_prepare_and_send_command(priv,
CMD_MESH_ACCESS, CMD_ACT_MESH_GET_STATS,
CMD_OPTION_WAITFORRSP, 0, &mesh_access);
ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access);
if (ret)
if (ret) {
memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t)));
return;
}
priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
@ -144,19 +111,18 @@ static void lbs_ethtool_get_stats(struct net_device * dev,
lbs_deb_enter(LBS_DEB_ETHTOOL);
}
static int lbs_ethtool_get_sset_count(struct net_device * dev, int sset)
static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset)
{
switch (sset) {
case ETH_SS_STATS:
struct lbs_private *priv = dev->priv;
if (sset == ETH_SS_STATS && dev == priv->mesh_dev)
return MESH_STATS_NUM;
default:
return -EOPNOTSUPP;
}
return -EOPNOTSUPP;
}
static void lbs_ethtool_get_strings(struct net_device *dev,
u32 stringset,
u8 * s)
uint32_t stringset, uint8_t *s)
{
int i;

View File

@ -33,7 +33,6 @@
#define CMD_RET_802_11_ASSOCIATE 0x8012
/* Command codes */
#define CMD_CODE_DNLD 0x0002
#define CMD_GET_HW_SPEC 0x0003
#define CMD_EEPROM_UPDATE 0x0004
#define CMD_802_11_RESET 0x0005
@ -68,8 +67,6 @@
#define CMD_802_11_AD_HOC_JOIN 0x002c
#define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e
#define CMD_802_11_ENABLE_RSN 0x002f
#define CMD_802_11_PAIRWISE_TSC 0x0036
#define CMD_802_11_GROUP_TSC 0x0037
#define CMD_802_11_SET_AFC 0x003c
#define CMD_802_11_GET_AFC 0x003d
#define CMD_802_11_AD_HOC_STOP 0x0040
@ -87,7 +84,6 @@
#define CMD_802_11_INACTIVITY_TIMEOUT 0x0067
#define CMD_802_11_SLEEP_PERIOD 0x0068
#define CMD_802_11_TPC_CFG 0x0072
#define CMD_802_11_PWR_CFG 0x0073
#define CMD_802_11_FW_WAKE_METHOD 0x0074
#define CMD_802_11_SUBSCRIBE_EVENT 0x0075
#define CMD_802_11_RATE_ADAPT_RATESET 0x0076

View File

@ -136,8 +136,8 @@ struct cmd_ds_get_hw_spec {
/* Number of antenna used */
__le16 nr_antenna;
/* FW release number, example 1,2,3,4 = 3.2.1p4 */
u8 fwreleasenumber[4];
/* FW release number, example 0x01030304 = 2.3.4p1 */
__le32 fwrelease;
/* Base Address of TxPD queue */
__le32 wcb_base;
@ -174,9 +174,11 @@ struct cmd_ds_802_11_subscribe_event {
* Define data structure for CMD_802_11_SCAN
*/
struct cmd_ds_802_11_scan {
u8 bsstype;
u8 bssid[ETH_ALEN];
u8 tlvbuffer[1];
struct cmd_header hdr;
uint8_t bsstype;
uint8_t bssid[ETH_ALEN];
uint8_t tlvbuffer[0];
#if 0
mrvlietypes_ssidparamset_t ssidParamSet;
mrvlietypes_chanlistparamset_t ChanListParamSet;
@ -185,12 +187,16 @@ struct cmd_ds_802_11_scan {
};
struct cmd_ds_802_11_scan_rsp {
struct cmd_header hdr;
__le16 bssdescriptsize;
u8 nr_sets;
u8 bssdesc_and_tlvbuffer[1];
uint8_t nr_sets;
uint8_t bssdesc_and_tlvbuffer[0];
};
struct cmd_ds_802_11_get_log {
struct cmd_header hdr;
__le32 mcasttxframe;
__le32 failed;
__le32 retry;
@ -207,8 +213,9 @@ struct cmd_ds_802_11_get_log {
};
struct cmd_ds_mac_control {
struct cmd_header hdr;
__le16 action;
__le16 reserved;
u16 reserved;
};
struct cmd_ds_mac_multicast_adr {
@ -420,6 +427,8 @@ struct cmd_ds_802_11_rssi_rsp {
};
struct cmd_ds_802_11_mac_address {
struct cmd_header hdr;
__le16 action;
u8 macadd[ETH_ALEN];
};
@ -471,14 +480,11 @@ struct cmd_ds_802_11_ps_mode {
__le16 locallisteninterval;
};
struct PS_CMD_ConfirmSleep {
__le16 command;
__le16 size;
__le16 seqnum;
__le16 result;
struct cmd_confirm_sleep {
struct cmd_header hdr;
__le16 action;
__le16 reserved1;
__le16 nullpktinterval;
__le16 multipledtim;
__le16 reserved;
__le16 locallisteninterval;
@ -572,17 +578,20 @@ struct cmd_ds_host_sleep {
} __attribute__ ((packed));
struct cmd_ds_802_11_key_material {
struct cmd_header hdr;
__le16 action;
struct MrvlIEtype_keyParamSet keyParamSet[2];
} __attribute__ ((packed));
struct cmd_ds_802_11_eeprom_access {
struct cmd_header hdr;
__le16 action;
/* multiple 4 */
__le16 offset;
__le16 bytecount;
u8 value;
__le16 len;
/* firmware says it returns a maximum of 20 bytes */
#define LBS_EEPROM_READ_LEN 20
u8 value[LBS_EEPROM_READ_LEN];
} __attribute__ ((packed));
struct cmd_ds_802_11_tpc_cfg {
@ -597,15 +606,7 @@ struct cmd_ds_802_11_tpc_cfg {
struct cmd_ds_802_11_led_ctrl {
__le16 action;
__le16 numled;
u8 data[256];
} __attribute__ ((packed));
struct cmd_ds_802_11_pwr_cfg {
__le16 action;
u8 enable;
s8 PA_P0;
s8 PA_P1;
s8 PA_P2;
u8 data[288];
} __attribute__ ((packed));
struct cmd_ds_802_11_afc {
@ -689,15 +690,11 @@ struct cmd_ds_command {
/* command Body */
union {
struct cmd_ds_802_11_ps_mode psmode;
struct cmd_ds_802_11_scan scan;
struct cmd_ds_802_11_scan_rsp scanresp;
struct cmd_ds_mac_control macctrl;
struct cmd_ds_802_11_associate associate;
struct cmd_ds_802_11_deauthenticate deauth;
struct cmd_ds_802_11_ad_hoc_start ads;
struct cmd_ds_802_11_reset reset;
struct cmd_ds_802_11_ad_hoc_result result;
struct cmd_ds_802_11_get_log glog;
struct cmd_ds_802_11_authenticate auth;
struct cmd_ds_802_11_get_stat gstat;
struct cmd_ds_802_3_get_stat gstat_8023;
@ -711,18 +708,14 @@ struct cmd_ds_command {
struct cmd_ds_802_11_rssi rssi;
struct cmd_ds_802_11_rssi_rsp rssirsp;
struct cmd_ds_802_11_disassociate dassociate;
struct cmd_ds_802_11_mac_address macadd;
struct cmd_ds_802_11_key_material keymaterial;
struct cmd_ds_mac_reg_access macreg;
struct cmd_ds_bbp_reg_access bbpreg;
struct cmd_ds_rf_reg_access rfreg;
struct cmd_ds_802_11_eeprom_access rdeeprom;
struct cmd_ds_802_11d_domain_info domaininfo;
struct cmd_ds_802_11d_domain_info domaininforesp;
struct cmd_ds_802_11_tpc_cfg tpccfg;
struct cmd_ds_802_11_pwr_cfg pwrcfg;
struct cmd_ds_802_11_afc afc;
struct cmd_ds_802_11_led_ctrl ledgpio;

View File

@ -83,14 +83,14 @@ static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg)
{
unsigned int val = ioread8(card->iobase + reg);
if (debug_output)
printk(KERN_INFO "##inb %08x<%02x\n", reg, val);
printk(KERN_INFO "inb %08x<%02x\n", reg, val);
return val;
}
static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg)
{
unsigned int val = ioread16(card->iobase + reg);
if (debug_output)
printk(KERN_INFO "##inw %08x<%04x\n", reg, val);
printk(KERN_INFO "inw %08x<%04x\n", reg, val);
return val;
}
static inline void if_cs_read16_rep(
@ -100,7 +100,7 @@ static inline void if_cs_read16_rep(
unsigned long count)
{
if (debug_output)
printk(KERN_INFO "##insw %08x<(0x%lx words)\n",
printk(KERN_INFO "insw %08x<(0x%lx words)\n",
reg, count);
ioread16_rep(card->iobase + reg, buf, count);
}
@ -108,14 +108,14 @@ static inline void if_cs_read16_rep(
static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val)
{
if (debug_output)
printk(KERN_INFO "##outb %08x>%02x\n", reg, val);
printk(KERN_INFO "outb %08x>%02x\n", reg, val);
iowrite8(val, card->iobase + reg);
}
static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val)
{
if (debug_output)
printk(KERN_INFO "##outw %08x>%04x\n", reg, val);
printk(KERN_INFO "outw %08x>%04x\n", reg, val);
iowrite16(val, card->iobase + reg);
}
@ -126,7 +126,7 @@ static inline void if_cs_write16_rep(
unsigned long count)
{
if (debug_output)
printk(KERN_INFO "##outsw %08x>(0x%lx words)\n",
printk(KERN_INFO "outsw %08x>(0x%lx words)\n",
reg, count);
iowrite16_rep(card->iobase + reg, buf, count);
}
@ -199,17 +199,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
#define IF_CS_C_S_CARDEVENT 0x0010
#define IF_CS_C_S_MASK 0x001f
#define IF_CS_C_S_STATUS_MASK 0x7f00
/* The following definitions should be the same as the MRVDRV_ ones */
#if MRVDRV_CMD_DNLD_RDY != IF_CS_C_S_CMD_DNLD_RDY
#error MRVDRV_CMD_DNLD_RDY and IF_CS_C_S_CMD_DNLD_RDY not in sync
#endif
#if MRVDRV_CMD_UPLD_RDY != IF_CS_C_S_CMD_UPLD_RDY
#error MRVDRV_CMD_UPLD_RDY and IF_CS_C_S_CMD_UPLD_RDY not in sync
#endif
#if MRVDRV_CARDEVENT != IF_CS_C_S_CARDEVENT
#error MRVDRV_CARDEVENT and IF_CS_C_S_CARDEVENT not in sync
#endif
#define IF_CS_C_INT_CAUSE 0x00000022
#define IF_CS_C_IC_MASK 0x001f
@ -225,55 +214,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
/********************************************************************/
/* Interrupts */
/********************************************************************/
static inline void if_cs_enable_ints(struct if_cs_card *card)
{
lbs_deb_enter(LBS_DEB_CS);
if_cs_write16(card, IF_CS_H_INT_MASK, 0);
}
static inline void if_cs_disable_ints(struct if_cs_card *card)
{
lbs_deb_enter(LBS_DEB_CS);
if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK);
}
static irqreturn_t if_cs_interrupt(int irq, void *data)
{
struct if_cs_card *card = (struct if_cs_card *)data;
u16 int_cause;
lbs_deb_enter(LBS_DEB_CS);
int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
if(int_cause == 0x0) {
/* Not for us */
return IRQ_NONE;
} else if (int_cause == 0xffff) {
/* Read in junk, the card has probably been removed */
card->priv->surpriseremoved = 1;
} else {
if (int_cause & IF_CS_H_IC_TX_OVER)
lbs_host_to_card_done(card->priv);
/* clear interrupt */
if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause & IF_CS_C_IC_MASK);
}
spin_lock(&card->priv->driver_lock);
lbs_interrupt(card->priv);
spin_unlock(&card->priv->driver_lock);
return IRQ_HANDLED;
}
/********************************************************************/
/* I/O */
/********************************************************************/
@ -351,6 +291,7 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
*/
static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
{
unsigned long flags;
int ret = -1;
u16 val;
@ -378,6 +319,12 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
* bytes */
*len -= 8;
ret = 0;
/* Clear this flag again */
spin_lock_irqsave(&priv->driver_lock, flags);
priv->dnld_sent = DNLD_RES_RECEIVED;
spin_unlock_irqrestore(&priv->driver_lock, flags);
out:
lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len);
return ret;
@ -396,11 +343,9 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len);
priv->stats.rx_dropped++;
printk(KERN_INFO "##HS %s:%d TODO\n", __FUNCTION__, __LINE__);
goto dat_err;
}
//TODO: skb = dev_alloc_skb(len+ETH_FRAME_LEN+MRVDRV_SNAP_HEADER_LEN+EXTRA_LEN);
skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2);
if (!skb)
goto out;
@ -424,6 +369,96 @@ out:
/********************************************************************/
/* Interrupts */
/********************************************************************/
static inline void if_cs_enable_ints(struct if_cs_card *card)
{
lbs_deb_enter(LBS_DEB_CS);
if_cs_write16(card, IF_CS_H_INT_MASK, 0);
}
static inline void if_cs_disable_ints(struct if_cs_card *card)
{
lbs_deb_enter(LBS_DEB_CS);
if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK);
}
static irqreturn_t if_cs_interrupt(int irq, void *data)
{
struct if_cs_card *card = data;
struct lbs_private *priv = card->priv;
u16 cause;
lbs_deb_enter(LBS_DEB_CS);
cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK);
lbs_deb_cs("cause 0x%04x\n", cause);
if (cause == 0) {
/* Not for us */
return IRQ_NONE;
}
if (cause == 0xffff) {
/* Read in junk, the card has probably been removed */
card->priv->surpriseremoved = 1;
return IRQ_HANDLED;
}
/* TODO: I'm not sure what the best ordering is */
cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
if (cause & IF_CS_C_S_RX_UPLD_RDY) {
struct sk_buff *skb;
lbs_deb_cs("rx packet\n");
skb = if_cs_receive_data(priv);
if (skb)
lbs_process_rxed_packet(priv, skb);
}
if (cause & IF_CS_H_IC_TX_OVER) {
lbs_deb_cs("tx over\n");
lbs_host_to_card_done(priv);
}
if (cause & IF_CS_C_S_CMD_UPLD_RDY) {
unsigned long flags;
u8 i;
lbs_deb_cs("cmd upload ready\n");
spin_lock_irqsave(&priv->driver_lock, flags);
i = (priv->resp_idx == 0) ? 1 : 0;
spin_unlock_irqrestore(&priv->driver_lock, flags);
BUG_ON(priv->resp_len[i]);
if_cs_receive_cmdres(priv, priv->resp_buf[i],
&priv->resp_len[i]);
spin_lock_irqsave(&priv->driver_lock, flags);
lbs_notify_command_response(priv, i);
spin_unlock_irqrestore(&priv->driver_lock, flags);
}
if (cause & IF_CS_H_IC_HOST_EVENT) {
u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS)
& IF_CS_C_S_STATUS_MASK;
if_cs_write16(priv->card, IF_CS_H_INT_CAUSE,
IF_CS_H_IC_HOST_EVENT);
lbs_deb_cs("eventcause 0x%04x\n", event);
lbs_queue_event(priv, event >> 8 & 0xff);
}
return IRQ_HANDLED;
}
/********************************************************************/
/* Firmware */
/********************************************************************/
@ -476,8 +511,6 @@ static int if_cs_prog_helper(struct if_cs_card *card)
if (remain < count)
count = remain;
/* printk(KERN_INFO "//HS %d loading %d of %d bytes\n",
__LINE__, sent, fw->size); */
/* "write the number of bytes to be sent to the I/O Command
* write length register" */
@ -544,18 +577,12 @@ static int if_cs_prog_real(struct if_cs_card *card)
ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK);
if (ret < 0) {
int i;
lbs_pr_err("helper firmware doesn't answer\n");
for (i = 0; i < 0x50; i += 2)
printk(KERN_INFO "## HS %02x: %04x\n",
i, if_cs_read16(card, i));
goto err_release;
}
for (sent = 0; sent < fw->size; sent += len) {
len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW);
/* printk(KERN_INFO "//HS %d loading %d of %d bytes\n",
__LINE__, sent, fw->size); */
if (len & 1) {
retry++;
lbs_pr_info("odd, need to retry this firmware block\n");
@ -642,66 +669,6 @@ static int if_cs_host_to_card(struct lbs_private *priv,
}
static int if_cs_get_int_status(struct lbs_private *priv, u8 *ireg)
{
struct if_cs_card *card = (struct if_cs_card *)priv->card;
int ret = 0;
u16 int_cause;
*ireg = 0;
lbs_deb_enter(LBS_DEB_CS);
if (priv->surpriseremoved)
goto out;
int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE) & IF_CS_C_IC_MASK;
if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause);
*ireg = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
if (!*ireg)
goto sbi_get_int_status_exit;
sbi_get_int_status_exit:
/* is there a data packet for us? */
if (*ireg & IF_CS_C_S_RX_UPLD_RDY) {
struct sk_buff *skb = if_cs_receive_data(priv);
lbs_process_rxed_packet(priv, skb);
*ireg &= ~IF_CS_C_S_RX_UPLD_RDY;
}
if (*ireg & IF_CS_C_S_TX_DNLD_RDY) {
priv->dnld_sent = DNLD_RES_RECEIVED;
}
/* Card has a command result for us */
if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) {
spin_lock(&priv->driver_lock);
ret = if_cs_receive_cmdres(priv, priv->upld_buf, &priv->upld_len);
spin_unlock(&priv->driver_lock);
if (ret < 0)
lbs_pr_err("could not receive cmd from card\n");
}
out:
lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->hisregcpy);
return ret;
}
static int if_cs_read_event_cause(struct lbs_private *priv)
{
lbs_deb_enter(LBS_DEB_CS);
priv->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5;
if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_HOST_EVENT);
return 0;
}
/********************************************************************/
/* Card Services */
/********************************************************************/
@ -717,8 +684,8 @@ static void if_cs_release(struct pcmcia_device *p_dev)
lbs_deb_enter(LBS_DEB_CS);
pcmcia_disable_device(p_dev);
free_irq(p_dev->irq.AssignedIRQ, card);
pcmcia_disable_device(p_dev);
if (card->iobase)
ioport_unmap(card->iobase);
@ -854,13 +821,10 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
goto out2;
}
/* Store pointers to our call-back functions */
/* Finish setting up fields in lbs_private */
card->priv = priv;
priv->card = card;
priv->hw_host_to_card = if_cs_host_to_card;
priv->hw_get_int_status = if_cs_get_int_status;
priv->hw_read_event_cause = if_cs_read_event_cause;
priv->hw_host_to_card = if_cs_host_to_card;
priv->fw_ready = 1;
/* Now actually get the IRQ */
@ -882,6 +846,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
goto out3;
}
/* The firmware for the CF card supports powersave */
priv->ps_supported = 1;
ret = 0;
goto out;

View File

@ -91,8 +91,6 @@ struct if_sdio_card {
const char *firmware;
u8 buffer[65536];
u8 int_cause;
u32 event;
spinlock_t lock;
struct if_sdio_packet *packets;
@ -129,13 +127,13 @@ static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err)
static int if_sdio_handle_cmd(struct if_sdio_card *card,
u8 *buffer, unsigned size)
{
struct lbs_private *priv = card->priv;
int ret;
unsigned long flags;
u8 i;
lbs_deb_enter(LBS_DEB_SDIO);
spin_lock_irqsave(&card->priv->driver_lock, flags);
if (size > LBS_CMD_BUFFER_SIZE) {
lbs_deb_sdio("response packet too large (%d bytes)\n",
(int)size);
@ -143,20 +141,20 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
goto out;
}
memcpy(card->priv->upld_buf, buffer, size);
card->priv->upld_len = size;
spin_lock_irqsave(&priv->driver_lock, flags);
card->int_cause |= MRVDRV_CMD_UPLD_RDY;
i = (priv->resp_idx == 0) ? 1 : 0;
BUG_ON(priv->resp_len[i]);
priv->resp_len[i] = size;
memcpy(priv->resp_buf[i], buffer, size);
lbs_notify_command_response(priv, i);
lbs_interrupt(card->priv);
spin_unlock_irqrestore(&card->priv->driver_lock, flags);
ret = 0;
out:
spin_unlock_irqrestore(&card->priv->driver_lock, flags);
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
return ret;
}
@ -202,7 +200,6 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
u8 *buffer, unsigned size)
{
int ret;
unsigned long flags;
u32 event;
lbs_deb_enter(LBS_DEB_SDIO);
@ -222,18 +219,9 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
event |= buffer[2] << 16;
event |= buffer[1] << 8;
event |= buffer[0] << 0;
event <<= SBI_EVENT_CAUSE_SHIFT;
}
spin_lock_irqsave(&card->priv->driver_lock, flags);
card->event = event;
card->int_cause |= MRVDRV_CARDEVENT;
lbs_interrupt(card->priv);
spin_unlock_irqrestore(&card->priv->driver_lock, flags);
lbs_queue_event(card->priv, event & 0xFF);
ret = 0;
out:
@ -770,37 +758,6 @@ out:
return ret;
}
static int if_sdio_get_int_status(struct lbs_private *priv, u8 *ireg)
{
struct if_sdio_card *card;
lbs_deb_enter(LBS_DEB_SDIO);
card = priv->card;
*ireg = card->int_cause;
card->int_cause = 0;
lbs_deb_leave(LBS_DEB_SDIO);
return 0;
}
static int if_sdio_read_event_cause(struct lbs_private *priv)
{
struct if_sdio_card *card;
lbs_deb_enter(LBS_DEB_SDIO);
card = priv->card;
priv->eventcause = card->event;
lbs_deb_leave(LBS_DEB_SDIO);
return 0;
}
/*******************************************************************/
/* SDIO callbacks */
/*******************************************************************/
@ -863,6 +820,10 @@ static int if_sdio_probe(struct sdio_func *func,
if (sscanf(func->card->info[i],
"ID: %x", &model) == 1)
break;
if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) {
model = 4;
break;
}
}
if (i == func->card->num_info) {
@ -949,8 +910,6 @@ static int if_sdio_probe(struct sdio_func *func,
priv->card = card;
priv->hw_host_to_card = if_sdio_host_to_card;
priv->hw_get_int_status = if_sdio_get_int_status;
priv->hw_read_event_cause = if_sdio_read_event_cause;
priv->fw_ready = 1;

View File

@ -6,6 +6,7 @@
#include <linux/firmware.h>
#include <linux/netdevice.h>
#include <linux/usb.h>
//#include <asm/olpc.h>
#define DRV_NAME "usb8xxx"
@ -38,8 +39,6 @@ static void if_usb_receive_fwload(struct urb *urb);
static int if_usb_prog_firmware(struct if_usb_card *cardp);
static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
uint8_t *payload, uint16_t nb);
static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *);
static int if_usb_read_event_cause(struct lbs_private *);
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
uint16_t nb);
static void if_usb_free(struct if_usb_card *cardp);
@ -104,12 +103,13 @@ static void if_usb_free(struct if_usb_card *cardp)
static void if_usb_setup_firmware(struct lbs_private *priv)
{
struct if_usb_card *cardp = priv->card;
struct cmd_ds_set_boot2_ver b2_cmd;
struct cmd_ds_802_11_fw_wake_method wake_method;
b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));
b2_cmd.action = 0;
b2_cmd.version = priv->boot2_version;
b2_cmd.version = cardp->boot2_version;
if (lbs_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
lbs_deb_usb("Setting boot2 version failed\n");
@ -232,9 +232,7 @@ static int if_usb_probe(struct usb_interface *intf,
cardp->priv->fw_ready = 1;
priv->hw_host_to_card = if_usb_host_to_card;
priv->hw_get_int_status = if_usb_get_int_status;
priv->hw_read_event_cause = if_usb_read_event_cause;
priv->boot2_version = udev->descriptor.bcdDevice;
cardp->boot2_version = udev->descriptor.bcdDevice;
if_usb_submit_rx_urb(cardp);
@ -367,6 +365,13 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
ret = usb_reset_device(cardp->udev);
msleep(100);
#ifdef CONFIG_OLPC
if (ret && machine_is_olpc()) {
printk(KERN_CRIT "Resetting OLPC wireless via EC...\n");
olpc_ec_cmd(0x25, NULL, 0, NULL, 0);
}
#endif
lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
return ret;
@ -581,7 +586,6 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
skb_pull(skb, MESSAGE_HEADER_LEN);
lbs_process_rxed_packet(priv, skb);
priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
}
static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
@ -589,6 +593,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
struct if_usb_card *cardp,
struct lbs_private *priv)
{
u8 i;
if (recvlength > LBS_CMD_BUFFER_SIZE) {
lbs_deb_usbd(&cardp->udev->dev,
"The receive buffer is too large\n");
@ -600,12 +606,15 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
BUG();
spin_lock(&priv->driver_lock);
cardp->usb_int_cause |= MRVDRV_CMD_UPLD_RDY;
priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
memcpy(priv->upld_buf, recvbuff + MESSAGE_HEADER_LEN, priv->upld_len);
i = (priv->resp_idx == 0) ? 1 : 0;
BUG_ON(priv->resp_len[i]);
priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN);
memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN,
priv->resp_len[i]);
kfree_skb(skb);
lbs_interrupt(priv);
lbs_notify_command_response(priv, i);
spin_unlock(&priv->driver_lock);
lbs_deb_usbd(&cardp->udev->dev,
@ -628,6 +637,7 @@ static void if_usb_receive(struct urb *urb)
uint8_t *recvbuff = NULL;
uint32_t recvtype = 0;
__le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
uint32_t event;
lbs_deb_enter(LBS_DEB_USB);
@ -659,26 +669,20 @@ static void if_usb_receive(struct urb *urb)
break;
case CMD_TYPE_INDICATION:
/* Event cause handling */
spin_lock(&priv->driver_lock);
cardp->usb_event_cause = le32_to_cpu(pkt[1]);
lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n",
cardp->usb_event_cause);
/* Event handling */
event = le32_to_cpu(pkt[1]);
lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event);
kfree_skb(skb);
/* Icky undocumented magic special case */
if (cardp->usb_event_cause & 0xffff0000) {
lbs_send_tx_feedback(priv);
spin_unlock(&priv->driver_lock);
break;
}
cardp->usb_event_cause <<= 3;
cardp->usb_int_cause |= MRVDRV_CARDEVENT;
kfree_skb(skb);
lbs_interrupt(priv);
spin_unlock(&priv->driver_lock);
goto rx_exit;
if (event & 0xffff0000) {
u32 trycount = (event & 0xffff0000) >> 16;
lbs_send_tx_feedback(priv, trycount);
} else
lbs_queue_event(priv, event & 0xFF);
break;
default:
lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n",
recvtype);
@ -721,30 +725,6 @@ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN);
}
/* called with priv->driver_lock held */
static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *ireg)
{
struct if_usb_card *cardp = priv->card;
*ireg = cardp->usb_int_cause;
cardp->usb_int_cause = 0;
lbs_deb_usbd(&cardp->udev->dev, "Int cause is 0x%X\n", *ireg);
return 0;
}
static int if_usb_read_event_cause(struct lbs_private *priv)
{
struct if_usb_card *cardp = priv->card;
priv->eventcause = cardp->usb_event_cause;
/* Re-submit rx urb here to avoid event lost issue */
if_usb_submit_rx_urb(cardp);
return 0;
}
/**
* @brief This function issues Boot command to the Boot2 code
* @param ivalue 1:Boot from FW by USB-Download
@ -953,6 +933,7 @@ static struct usb_driver if_usb_driver = {
.id_table = if_usb_table,
.suspend = if_usb_suspend,
.resume = if_usb_resume,
.reset_resume = if_usb_resume,
};
static int __init if_usb_init_module(void)

View File

@ -46,8 +46,6 @@ struct if_usb_card {
struct lbs_private *priv;
struct sk_buff *rx_skb;
uint32_t usb_event_cause;
uint8_t usb_int_cause;
uint8_t ep_in;
uint8_t ep_out;
@ -70,6 +68,7 @@ struct if_usb_card {
uint8_t fwfinalblk;
uint8_t surprise_removed;
__le16 boot2_version;
};
/** fwheader */

1243
package/libertas/src/ioctl.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
#define COSTS_LIST_SIZE 4
/* iwpriv places the subcmd number in the first uint32_t;
data buffer follows that */
#define SUBCMD_OFFSET sizeof(uint32_t)
#define SUBCMD_DATA(x) *((int *)(x->u.name + SUBCMD_OFFSET))
/** Private ioctls and ioctls subcommands */
#define LBS_SETNONE_GETNONE (SIOCIWFIRSTPRIV + 8)
#define LBS_SUBCMD_BT_RESET 13
#define LBS_SUBCMD_FWT_RESET 14
#define LBS_SETNONE_GETONEINT (SIOCIWFIRSTPRIV + 15)
#define LBS_SUBCMD_GET_REGION 1
#define LBS_SUBCMD_FWT_CLEANUP 15
#define LBS_SUBCMD_FWT_TIME 16
#define LBS_SUBCMD_MESH_GET_TTL 17
#define LBS_SUBCMD_BT_GET_INVERT 18
#define LBS_SUBCMD_MESH_GET_BCAST_RATE 19
#define LBS_SUBCMD_MESH_GET_RREQ_DELAY 20
#define LBS_SUBCMD_MESH_GET_ROUTE_EXP 21
#define LBS_SETONEINT_GETNONE (SIOCIWFIRSTPRIV + 24)
#define LBS_SUBCMD_SET_REGION 8
#define LBS_SUBCMD_MESH_SET_TTL 18
#define LBS_SUBCMD_BT_SET_INVERT 19
#define LBS_SUBCMD_MESH_SET_BCAST_RATE 20
#define LBS_SUBCMD_MESH_SET_RREQ_DELAY 21
#define LBS_SUBCMD_MESH_SET_ROUTE_EXP 22
#define LBS_SET128CHAR_GET128CHAR (SIOCIWFIRSTPRIV + 25)
#define LBS_SUBCMD_BT_ADD 18
#define LBS_SUBCMD_BT_DEL 19
#define LBS_SUBCMD_BT_LIST 20
#define LBS_SUBCMD_FWT_ADD 21
#define LBS_SUBCMD_FWT_DEL 22
#define LBS_SUBCMD_FWT_LOOKUP 23
#define LBS_SUBCMD_FWT_LIST_NEIGHBOR 24
#define LBS_SUBCMD_FWT_LIST 25
#define LBS_SUBCMD_FWT_LIST_ROUTE 26
#define LBS_SUBCMD_MESH_SET_LINK_COSTS 27
#define LBS_SUBCMD_MESH_GET_LINK_COSTS 28
#define LBS_SET_GET_SIXTEEN_INT (SIOCIWFIRSTPRIV + 29)
#define LBS_LED_GPIO_CTRL 5
#define LBS_BCN_CTRL 6
#define LBS_LED_BEHAVIOR_CTRL 7
int lbs_do_ioctl(struct net_device *dev, struct ifreq *req, int i);

File diff suppressed because it is too large Load Diff

View File

@ -145,17 +145,17 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
struct net_device *dev = priv->dev;
struct rxpackethdr *p_rx_pkt;
struct rxpd *p_rx_pd;
int hdrchop;
struct ethhdr *p_ethhdr;
const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
lbs_deb_enter(LBS_DEB_RX);
BUG_ON(!skb);
skb->ip_summed = CHECKSUM_NONE;
if (priv->monitormode != LBS_MONITOR_OFF)
if (priv->monitormode)
return process_rxed_802_11_packet(priv, skb);
p_rx_pkt = (struct rxpackethdr *) skb->data;
@ -247,7 +247,10 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
priv->stats.rx_packets++;
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
if (in_interrupt())
netif_rx(skb);
else
netif_rx_ni(skb);
ret = 0;
done:

File diff suppressed because it is too large Load Diff

View File

@ -7,198 +7,22 @@
#ifndef _LBS_SCAN_H
#define _LBS_SCAN_H
#include <net/ieee80211.h>
#include "hostcmd.h"
/**
* @brief Maximum number of channels that can be sent in a setuserscan ioctl
*
* @sa lbs_ioctl_user_scan_cfg
*/
#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
//! Infrastructure BSS scan type in lbs_scan_cmd_config
#define LBS_SCAN_BSS_TYPE_BSS 1
//! Adhoc BSS scan type in lbs_scan_cmd_config
#define LBS_SCAN_BSS_TYPE_IBSS 2
//! Adhoc or Infrastructure BSS scan type in lbs_scan_cmd_config, no filter
#define LBS_SCAN_BSS_TYPE_ANY 3
/**
* @brief Structure used internally in the wlan driver to configure a scan.
*
* Sent to the command processing module to configure the firmware
* scan command prepared by lbs_cmd_80211_scan.
*
* @sa lbs_scan_networks
*
*/
struct lbs_scan_cmd_config {
/**
* @brief BSS type to be sent in the firmware command
*
* Field can be used to restrict the types of networks returned in the
* scan. valid settings are:
*
* - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
* - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
* - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
*/
u8 bsstype;
/**
* @brief Specific BSSID used to filter scan results in the firmware
*/
u8 bssid[ETH_ALEN];
/**
* @brief length of TLVs sent in command starting at tlvBuffer
*/
int tlvbufferlen;
/**
* @brief SSID TLV(s) and ChanList TLVs to be sent in the firmware command
*
* @sa TLV_TYPE_CHANLIST, mrvlietypes_chanlistparamset_t
* @sa TLV_TYPE_SSID, mrvlietypes_ssidparamset_t
*/
u8 tlvbuffer[1]; //!< SSID TLV(s) and ChanList TLVs are stored here
};
/**
* @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg
*
* Multiple instances of this structure are included in the IOCTL command
* to configure a instance of a scan on the specific channel.
*/
struct lbs_ioctl_user_scan_chan {
u8 channumber; //!< channel Number to scan
u8 radiotype; //!< Radio type: 'B/G' band = 0, 'A' band = 1
u8 scantype; //!< Scan type: Active = 0, Passive = 1
u16 scantime; //!< Scan duration in milliseconds; if 0 default used
};
/**
* @brief IOCTL input structure to configure an immediate scan cmd to firmware
*
* Used in the setuserscan (LBS_SET_USER_SCAN) private ioctl. Specifies
* a number of parameters to be used in general for the scan as well
* as a channel list (lbs_ioctl_user_scan_chan) for each scan period
* desired.
*
* @sa lbs_set_user_scan_ioctl
*/
struct lbs_ioctl_user_scan_cfg {
/**
* @brief BSS type to be sent in the firmware command
*
* Field can be used to restrict the types of networks returned in the
* scan. valid settings are:
*
* - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
* - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
* - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
*/
u8 bsstype;
/**
* @brief BSSID filter sent in the firmware command to limit the results
*/
u8 bssid[ETH_ALEN];
/* Clear existing scan results matching this BSSID */
u8 clear_bssid;
/**
* @brief SSID filter sent in the firmware command to limit the results
*/
char ssid[IW_ESSID_MAX_SIZE];
u8 ssid_len;
/* Clear existing scan results matching this SSID */
u8 clear_ssid;
};
/**
* @brief Structure used to store information for each beacon/probe response
*/
struct bss_descriptor {
u8 bssid[ETH_ALEN];
u8 ssid[IW_ESSID_MAX_SIZE + 1];
u8 ssid_len;
u16 capability;
/* receive signal strength in dBm */
long rssi;
u32 channel;
u16 beaconperiod;
u32 atimwindow;
/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
u8 mode;
/* zero-terminated array of supported data rates */
u8 rates[MAX_RATES + 1];
unsigned long last_scanned;
union ieeetypes_phyparamset phyparamset;
union IEEEtypes_ssparamset ssparamset;
struct ieeetypes_countryinfofullset countryinfo;
u8 wpa_ie[MAX_WPA_IE_LEN];
size_t wpa_ie_len;
u8 rsn_ie[MAX_WPA_IE_LEN];
size_t rsn_ie_len;
u8 mesh;
struct list_head list;
};
int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
u8 *ssid, u8 ssid_len, u8 *bssid, u8 mode,
int channel);
struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
u8 *bssid, u8 mode);
int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid,
u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
u8 ssid_len, u8 clear_ssid);
u8 ssid_len);
int lbs_cmd_80211_scan(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
int lbs_ret_80211_scan(struct lbs_private *priv,
struct cmd_ds_command *resp);
int lbs_scan_networks(struct lbs_private *priv,
const struct lbs_ioctl_user_scan_cfg *puserscanin,
int full_scan);
struct ifreq;
struct iw_point;
struct iw_param;
struct iw_request_info;
int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra);
int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra);
union iwreq_data *wrqu, char *extra);
int lbs_scan_networks(struct lbs_private *priv, int full_scan);
void lbs_scan_worker(struct work_struct *work);

View File

@ -151,7 +151,7 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
if (priv->monitormode != LBS_MONITOR_OFF) {
if (priv->monitormode) {
/* Keep the skb to echo it back once Tx feedback is
received from FW */
skb_orphan(skb);
@ -179,32 +179,17 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
*
* @returns void
*/
void lbs_send_tx_feedback(struct lbs_private *priv)
void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
{
struct tx_radiotap_hdr *radiotap_hdr;
u32 status = priv->eventcause;
int txfail;
int try_count;
if (priv->monitormode == LBS_MONITOR_OFF ||
priv->currenttxskb == NULL)
if (!priv->monitormode || priv->currenttxskb == NULL)
return;
radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
txfail = (status >> 24);
#if 0
/* The version of roofnet that we've tested does not use this yet
* But it may be used in the future.
*/
if (txfail)
radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL;
#endif
try_count = (status >> 16) & 0xff;
radiotap_hdr->data_retries = (try_count) ?
(1 + priv->txretrycount - try_count) : 0;
radiotap_hdr->data_retries = try_count ?
(1 + priv->txretrycount - try_count) : 0;
priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
priv->rtap_net_dev);

View File

@ -239,4 +239,17 @@ struct mrvlietypes_ledgpio {
struct led_pin ledpin[1];
} __attribute__ ((packed));
struct led_bhv {
uint8_t firmwarestate;
uint8_t led;
uint8_t ledstate;
uint8_t ledarg;
} __attribute__ ((packed));
struct mrvlietypes_ledbhv {
struct mrvlietypesheader header;
struct led_bhv ledbhv[1];
} __attribute__ ((packed));
#endif

View File

@ -16,11 +16,11 @@
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "join.h"
#include "wext.h"
#include "scan.h"
#include "assoc.h"
#include "cmd.h"
#include "ioctl.h"
static inline void lbs_postpone_association_work(struct lbs_private *priv)
{
@ -579,6 +579,9 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
range->num_bitrates);
range->num_frequency = 0;
range->scan_capa = IW_SCAN_CAPA_ESSID;
if (priv->enable11d &&
(priv->connect_status == LBS_CONNECTED ||
priv->mesh_connect_status == LBS_CONNECTED)) {
@ -602,7 +605,7 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
lbs_deb_wext("chan_no %d\n", chan_no);
range->freq[range->num_frequency].i = (long)chan_no;
range->freq[range->num_frequency].m =
(long)lbs_chan_2_freq(chan_no, band) * 100000;
(long)lbs_chan_2_freq(chan_no) * 100000;
range->freq[range->num_frequency].e = 1;
range->num_frequency++;
}
@ -653,13 +656,10 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
range->num_encoding_sizes = 2;
range->max_encoding_tokens = 4;
range->min_pmp = 1000000;
range->max_pmp = 120000000;
range->min_pmt = 1000;
range->max_pmt = 1000000;
range->pmp_flags = IW_POWER_PERIOD;
range->pmt_flags = IW_POWER_TIMEOUT;
range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
/*
* Right now we support only "iwconfig ethX power on|off"
*/
range->pm_capa = IW_POWER_ON;
/*
* Minimum version we recommend
@ -781,21 +781,14 @@ static int lbs_get_power(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
struct lbs_private *priv = dev->priv;
int mode;
lbs_deb_enter(LBS_DEB_WEXT);
mode = priv->psmode;
if ((vwrq->disabled = (mode == LBS802_11POWERMODECAM))
|| priv->connect_status == LBS_DISCONNECTED)
{
goto out;
}
vwrq->value = 0;
vwrq->flags = 0;
vwrq->disabled = priv->psmode == LBS802_11POWERMODECAM
|| priv->connect_status == LBS_DISCONNECTED;
out:
lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
@ -817,6 +810,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
int stats_valid = 0;
u8 rssi;
u32 tx_retries;
struct cmd_ds_802_11_get_log log;
lbs_deb_enter(LBS_DEB_WEXT);
@ -860,7 +854,11 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
/* Quality by TX errors */
priv->wstats.discard.retries = priv->stats.tx_errors;
tx_retries = le32_to_cpu(priv->logmsg.retry);
memset(&log, 0, sizeof(log));
log.hdr.size = cpu_to_le16(sizeof(log));
lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
tx_retries = le32_to_cpu(log.retry);
if (tx_retries > 75)
tx_qual = (90 - tx_retries) * POOR / 15;
@ -876,10 +874,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
(PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
quality = min(quality, tx_qual);
priv->wstats.discard.code = le32_to_cpu(priv->logmsg.wepundecryptable);
priv->wstats.discard.fragment = le32_to_cpu(priv->logmsg.rxfrag);
priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable);
priv->wstats.discard.retries = tx_retries;
priv->wstats.discard.misc = le32_to_cpu(priv->logmsg.ackfailure);
priv->wstats.discard.misc = le32_to_cpu(log.ackfailure);
/* Calculate quality */
priv->wstats.qual.qual = min_t(u8, quality, 100);
@ -889,8 +886,6 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
/* update stats asynchronously for future calls */
lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
0, 0, NULL);
lbs_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0,
0, 0, NULL);
out:
if (!stats_valid) {
priv->wstats.miss.beacon = 0;
@ -2065,29 +2060,6 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
return ret;
}
void lbs_get_fwversion(struct lbs_private *priv, char *fwversion, int maxlen)
{
char fwver[32];
mutex_lock(&priv->lock);
if (priv->fwreleasenumber[3] == 0)
sprintf(fwver, "%u.%u.%u",
priv->fwreleasenumber[2],
priv->fwreleasenumber[1],
priv->fwreleasenumber[0]);
else
sprintf(fwver, "%u.%u.%u.p%u",
priv->fwreleasenumber[2],
priv->fwreleasenumber[1],
priv->fwreleasenumber[0],
priv->fwreleasenumber[3]);
mutex_unlock(&priv->lock);
snprintf(fwversion, maxlen, fwver);
}
/*
* iwconfig settable callbacks
*/
@ -2206,14 +2178,63 @@ static const iw_handler mesh_wlan_handler[] = {
(iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
(iw_handler) NULL, /* SIOCSIWPMKSA */
};
#define INT_PARAM (IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1)
#define INT16_PARAM (IW_PRIV_TYPE_INT | 16)
#define CHAR128_PARAM (IW_PRIV_TYPE_CHAR | 128)
static const struct iw_priv_args lbs_private_args[] = {
/* { cmd, set_args, get_args, name } */
{ LBS_SETNONE_GETNONE, 0, 0, "" },
{ LBS_SUBCMD_FWT_RESET, 0, 0, "fwt_reset"},
{ LBS_SUBCMD_BT_RESET, 0, 0, "bt_reset"},
{ LBS_SETNONE_GETONEINT, 0, INT_PARAM, ""},
{ LBS_SUBCMD_GET_REGION, 0, INT_PARAM, "getregioncode"},
{ LBS_SUBCMD_FWT_CLEANUP, 0, INT_PARAM, "fwt_cleanup"},
{ LBS_SUBCMD_FWT_TIME, 0, INT_PARAM, "fwt_time"},
{ LBS_SUBCMD_MESH_GET_TTL, 0, INT_PARAM, "mesh_get_ttl"},
{ LBS_SUBCMD_BT_GET_INVERT, 0, INT_PARAM, "bt_get_invert"},
{ LBS_SUBCMD_MESH_GET_BCAST_RATE, 0, INT_PARAM, "mesh_get_bcastr"},
{ LBS_SUBCMD_MESH_GET_RREQ_DELAY, 0, INT_PARAM, "get_rreq_delay"},
{ LBS_SUBCMD_MESH_GET_ROUTE_EXP, 0, INT_PARAM, "get_route_exp"},
{ LBS_SETONEINT_GETNONE, INT_PARAM, 0, ""},
{ LBS_SUBCMD_SET_REGION, INT_PARAM, 0, "setregioncode"},
{ LBS_SUBCMD_MESH_SET_TTL, INT_PARAM, 0, "mesh_set_ttl"},
{ LBS_SUBCMD_BT_SET_INVERT, INT_PARAM, 0, "bt_set_invert"},
{ LBS_SUBCMD_MESH_SET_BCAST_RATE, INT_PARAM, 0, "mesh_set_bcastr"},
{ LBS_SUBCMD_MESH_SET_RREQ_DELAY, INT_PARAM, 0, "set_rreq_delay"},
{ LBS_SUBCMD_MESH_SET_ROUTE_EXP, INT_PARAM, 0, "set_route_exp"},
{ LBS_SET128CHAR_GET128CHAR, CHAR128_PARAM, CHAR128_PARAM, ""},
{ LBS_SUBCMD_BT_ADD, CHAR128_PARAM, CHAR128_PARAM, "bt_add"},
{ LBS_SUBCMD_BT_DEL, CHAR128_PARAM, CHAR128_PARAM, "bt_del"},
{ LBS_SUBCMD_BT_LIST, CHAR128_PARAM, CHAR128_PARAM, "bt_list"},
{ LBS_SUBCMD_FWT_ADD, CHAR128_PARAM, CHAR128_PARAM, "fwt_add"},
{ LBS_SUBCMD_FWT_DEL, CHAR128_PARAM, CHAR128_PARAM, "fwt_del"},
{ LBS_SUBCMD_FWT_LOOKUP, CHAR128_PARAM, CHAR128_PARAM, "fwt_lookup"},
{ LBS_SUBCMD_FWT_LIST_NEIGHBOR, CHAR128_PARAM, CHAR128_PARAM, "fwt_list_neigh"},
{ LBS_SUBCMD_FWT_LIST, CHAR128_PARAM, CHAR128_PARAM, "fwt_list"},
{ LBS_SUBCMD_FWT_LIST_ROUTE, CHAR128_PARAM, CHAR128_PARAM, "fwt_list_route"},
{ LBS_SUBCMD_MESH_SET_LINK_COSTS, CHAR128_PARAM, CHAR128_PARAM, "set_link_costs"},
{ LBS_SUBCMD_MESH_GET_LINK_COSTS, CHAR128_PARAM, CHAR128_PARAM, "get_link_costs"},
{ LBS_SET_GET_SIXTEEN_INT, INT16_PARAM, INT16_PARAM, ""},
{ LBS_LED_GPIO_CTRL, INT16_PARAM, INT16_PARAM, "ledgpio"},
{ LBS_BCN_CTRL, INT16_PARAM, INT16_PARAM, "bcn_control"},
{ LBS_LED_BEHAVIOR_CTRL, INT16_PARAM, INT16_PARAM, "ledbhv"},
};
struct iw_handler_def lbs_handler_def = {
.num_standard = ARRAY_SIZE(lbs_handler),
.standard = (iw_handler *) lbs_handler,
.get_wireless_stats = lbs_get_wireless_stats,
.num_private_args = ARRAY_SIZE(lbs_private_args),
.private_args = lbs_private_args,
};
struct iw_handler_def mesh_handler_def = {
.num_standard = ARRAY_SIZE(mesh_wlan_handler),
.standard = (iw_handler *) mesh_wlan_handler,
.get_wireless_stats = lbs_get_wireless_stats,
.num_private_args = ARRAY_SIZE(lbs_private_args),
.private_args = lbs_private_args,
};

View File

@ -4,19 +4,6 @@
#ifndef _LBS_WEXT_H_
#define _LBS_WEXT_H_
/** lbs_ioctl_regrdwr */
struct lbs_ioctl_regrdwr {
/** Which register to access */
u16 whichreg;
/** Read or Write */
u16 action;
u32 offset;
u16 NOB;
u32 value;
};
#define LBS_MONITOR_OFF 0
extern struct iw_handler_def lbs_handler_def;
extern struct iw_handler_def mesh_handler_def;