mirror of https://github.com/hak5/openwrt-owl.git
parent
4e61cbbf5e
commit
10aa4d9e42
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
|
@ -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:
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
|
||||
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);
|
||||
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_req->flags)) {
|
||||
set_one_wpa_key(&pkeymaterial->keyParamSet[index],
|
||||
&assoc_req->wpa_mcast_key);
|
||||
if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
|
||||
set_one_wpa_key(&cmd.keyParamSet[index],
|
||||
&assoc->wpa_mcast_key);
|
||||
index++;
|
||||
}
|
||||
|
||||
cmd->size = cpu_to_le16( S_DS_GEN
|
||||
+ sizeof (pkeymaterial->action)
|
||||
+ (index * sizeof(struct MrvlIEtype_keyParamSet)));
|
||||
/* 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];
|
||||
|
||||
ret = 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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,11 +1379,11 @@ 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,
|
||||
ret = lbs_cmd_802_11_rf_tx_power(cmdptr,
|
||||
cmd_action, pdata_buf);
|
||||
break;
|
||||
|
||||
|
@ -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);
|
||||
lbs_pr_alert("confirm_sleep failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
|
||||
return ret;
|
||||
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,37 +1937,8 @@ 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,
|
||||
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)
|
||||
{
|
||||
|
@ -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 *),
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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, ®ctrl, 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,
|
||||
®ctrl);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static void lbs_ethtool_get_strings(struct net_device *dev,
|
||||
u32 stringset,
|
||||
u8 * s)
|
||||
uint32_t stringset, uint8_t *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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->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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
if (event & 0xffff0000) {
|
||||
u32 trycount = (event & 0xffff0000) >> 16;
|
||||
|
||||
lbs_send_tx_feedback(priv, trycount);
|
||||
} else
|
||||
lbs_queue_event(priv, event & 0xFF);
|
||||
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;
|
||||
|
||||
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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
|
@ -10,6 +10,8 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/kfifo.h>
|
||||
//#include <asm/olpc.h>
|
||||
|
||||
#include <net/iw_handler.h>
|
||||
#include <net/ieee80211.h>
|
||||
|
@ -19,9 +21,10 @@
|
|||
#include "dev.h"
|
||||
#include "wext.h"
|
||||
#include "debugfs.h"
|
||||
#include "scan.h"
|
||||
#include "assoc.h"
|
||||
#include "join.h"
|
||||
#include "cmd.h"
|
||||
#include "ioctl.h"
|
||||
|
||||
#define DRIVER_RELEASE_VERSION "323.p0"
|
||||
const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
|
||||
|
@ -37,6 +40,11 @@ EXPORT_SYMBOL_GPL(lbs_debug);
|
|||
module_param_named(libertas_debug, lbs_debug, int, 0644);
|
||||
|
||||
|
||||
/* This global structure is used to send the confirm_sleep command as
|
||||
* fast as possible down to the firmware. */
|
||||
struct cmd_confirm_sleep confirm_sleep;
|
||||
|
||||
|
||||
#define LBS_TX_PWR_DEFAULT 20 /*100mW */
|
||||
#define LBS_TX_PWR_US_DEFAULT 20 /*100mW */
|
||||
#define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */
|
||||
|
@ -277,10 +285,10 @@ static ssize_t lbs_rtap_set(struct device *dev,
|
|||
struct lbs_private *priv = to_net_dev(dev)->priv;
|
||||
|
||||
sscanf(buf, "%x", &monitor_mode);
|
||||
if (monitor_mode != LBS_MONITOR_OFF) {
|
||||
if(priv->monitormode == monitor_mode)
|
||||
if (monitor_mode) {
|
||||
if (priv->monitormode == monitor_mode)
|
||||
return strlen(buf);
|
||||
if (priv->monitormode == LBS_MONITOR_OFF) {
|
||||
if (!priv->monitormode) {
|
||||
if (priv->infra_open || priv->mesh_open)
|
||||
return -EBUSY;
|
||||
if (priv->mode == IW_MODE_INFRA)
|
||||
|
@ -293,9 +301,9 @@ static ssize_t lbs_rtap_set(struct device *dev,
|
|||
}
|
||||
|
||||
else {
|
||||
if (priv->monitormode == LBS_MONITOR_OFF)
|
||||
if (!priv->monitormode)
|
||||
return strlen(buf);
|
||||
priv->monitormode = LBS_MONITOR_OFF;
|
||||
priv->monitormode = 0;
|
||||
lbs_remove_rtap(priv);
|
||||
|
||||
if (priv->currenttxskb) {
|
||||
|
@ -388,9 +396,11 @@ static int lbs_dev_open(struct net_device *dev)
|
|||
struct lbs_private *priv = (struct lbs_private *) dev->priv ;
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_NET);
|
||||
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
|
||||
if (priv->monitormode != LBS_MONITOR_OFF) {
|
||||
if (priv->monitormode) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
@ -413,6 +423,7 @@ static int lbs_dev_open(struct net_device *dev)
|
|||
out:
|
||||
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -426,6 +437,7 @@ static int lbs_mesh_stop(struct net_device *dev)
|
|||
{
|
||||
struct lbs_private *priv = (struct lbs_private *) (dev->priv);
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MESH);
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
|
||||
priv->mesh_open = 0;
|
||||
|
@ -435,6 +447,8 @@ static int lbs_mesh_stop(struct net_device *dev)
|
|||
netif_carrier_off(dev);
|
||||
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_MESH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -448,13 +462,14 @@ static int lbs_eth_stop(struct net_device *dev)
|
|||
{
|
||||
struct lbs_private *priv = (struct lbs_private *) dev->priv;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_NET);
|
||||
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
|
||||
priv->infra_open = 0;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_NET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -468,10 +483,9 @@ static void lbs_tx_timeout(struct net_device *dev)
|
|||
|
||||
dev->trans_start = jiffies;
|
||||
|
||||
if (priv->currenttxskb) {
|
||||
priv->eventcause = 0x01000000;
|
||||
lbs_send_tx_feedback(priv);
|
||||
}
|
||||
if (priv->currenttxskb)
|
||||
lbs_send_tx_feedback(priv, 0);
|
||||
|
||||
/* XX: Shouldn't we also call into the hw-specific driver
|
||||
to kick it somehow? */
|
||||
lbs_host_to_card_done(priv);
|
||||
|
@ -490,6 +504,8 @@ void lbs_host_to_card_done(struct lbs_private *priv)
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_THREAD);
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
priv->dnld_sent = DNLD_RES_RECEIVED;
|
||||
|
@ -499,6 +515,7 @@ void lbs_host_to_card_done(struct lbs_private *priv)
|
|||
wake_up_interruptible(&priv->waitq);
|
||||
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
lbs_deb_leave(LBS_DEB_THREAD);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
|
||||
|
||||
|
@ -512,6 +529,7 @@ static struct net_device_stats *lbs_get_stats(struct net_device *dev)
|
|||
{
|
||||
struct lbs_private *priv = (struct lbs_private *) dev->priv;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_NET);
|
||||
return &priv->stats;
|
||||
}
|
||||
|
||||
|
@ -520,34 +538,27 @@ static int lbs_set_mac_address(struct net_device *dev, void *addr)
|
|||
int ret = 0;
|
||||
struct lbs_private *priv = (struct lbs_private *) dev->priv;
|
||||
struct sockaddr *phwaddr = addr;
|
||||
struct cmd_ds_802_11_mac_address cmd;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_NET);
|
||||
|
||||
/* In case it was called from the mesh device */
|
||||
dev = priv->dev ;
|
||||
dev = priv->dev;
|
||||
|
||||
memset(priv->current_addr, 0, ETH_ALEN);
|
||||
|
||||
/* dev->dev_addr is 8 bytes */
|
||||
lbs_deb_hex(LBS_DEB_NET, "dev->dev_addr", dev->dev_addr, ETH_ALEN);
|
||||
|
||||
lbs_deb_hex(LBS_DEB_NET, "addr", phwaddr->sa_data, ETH_ALEN);
|
||||
memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
|
||||
|
||||
ret = lbs_prepare_and_send_command(priv, CMD_802_11_MAC_ADDRESS,
|
||||
CMD_ACT_SET,
|
||||
CMD_OPTION_WAITFORRSP, 0, NULL);
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(CMD_ACT_SET);
|
||||
memcpy(cmd.macadd, phwaddr->sa_data, ETH_ALEN);
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
|
||||
if (ret) {
|
||||
lbs_deb_net("set MAC address failed\n");
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
lbs_deb_hex(LBS_DEB_NET, "priv->macaddr", priv->current_addr, ETH_ALEN);
|
||||
memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN);
|
||||
memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
|
||||
memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
|
||||
if (priv->mesh_dev)
|
||||
memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
|
||||
memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
|
||||
|
@ -564,53 +575,51 @@ static int lbs_copy_multicast_address(struct lbs_private *priv,
|
|||
memcpy(&priv->multicastlist[i], mcptr->dmi_addr, ETH_ALEN);
|
||||
mcptr = mcptr->next;
|
||||
}
|
||||
|
||||
return i;
|
||||
|
||||
}
|
||||
|
||||
static void lbs_set_multicast_list(struct net_device *dev)
|
||||
{
|
||||
struct lbs_private *priv = dev->priv;
|
||||
int oldpacketfilter;
|
||||
int old_mac_control;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
lbs_deb_enter(LBS_DEB_NET);
|
||||
|
||||
oldpacketfilter = priv->currentpacketfilter;
|
||||
old_mac_control = priv->mac_control;
|
||||
|
||||
if (dev->flags & IFF_PROMISC) {
|
||||
lbs_deb_net("enable promiscuous mode\n");
|
||||
priv->currentpacketfilter |=
|
||||
priv->mac_control |=
|
||||
CMD_ACT_MAC_PROMISCUOUS_ENABLE;
|
||||
priv->currentpacketfilter &=
|
||||
priv->mac_control &=
|
||||
~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE |
|
||||
CMD_ACT_MAC_MULTICAST_ENABLE);
|
||||
} else {
|
||||
/* Multicast */
|
||||
priv->currentpacketfilter &=
|
||||
priv->mac_control &=
|
||||
~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
|
||||
|
||||
if (dev->flags & IFF_ALLMULTI || dev->mc_count >
|
||||
MRVDRV_MAX_MULTICAST_LIST_SIZE) {
|
||||
lbs_deb_net( "enabling all multicast\n");
|
||||
priv->currentpacketfilter |=
|
||||
priv->mac_control |=
|
||||
CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
|
||||
priv->currentpacketfilter &=
|
||||
priv->mac_control &=
|
||||
~CMD_ACT_MAC_MULTICAST_ENABLE;
|
||||
} else {
|
||||
priv->currentpacketfilter &=
|
||||
priv->mac_control &=
|
||||
~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
|
||||
|
||||
if (!dev->mc_count) {
|
||||
lbs_deb_net("no multicast addresses, "
|
||||
"disabling multicast\n");
|
||||
priv->currentpacketfilter &=
|
||||
priv->mac_control &=
|
||||
~CMD_ACT_MAC_MULTICAST_ENABLE;
|
||||
} else {
|
||||
int i;
|
||||
|
||||
priv->currentpacketfilter |=
|
||||
priv->mac_control |=
|
||||
CMD_ACT_MAC_MULTICAST_ENABLE;
|
||||
|
||||
priv->nr_of_multicastmacaddr =
|
||||
|
@ -620,7 +629,7 @@ static void lbs_set_multicast_list(struct net_device *dev)
|
|||
dev->mc_count);
|
||||
|
||||
for (i = 0; i < dev->mc_count; i++) {
|
||||
lbs_deb_net("Multicast address %d:%s\n",
|
||||
lbs_deb_net("Multicast address %d: %s\n",
|
||||
i, print_mac(mac,
|
||||
priv->multicastlist[i]));
|
||||
}
|
||||
|
@ -633,9 +642,8 @@ static void lbs_set_multicast_list(struct net_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (priv->currentpacketfilter != oldpacketfilter) {
|
||||
lbs_set_mac_packet_filter(priv);
|
||||
}
|
||||
if (priv->mac_control != old_mac_control)
|
||||
lbs_set_mac_control(priv);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_NET);
|
||||
}
|
||||
|
@ -653,7 +661,6 @@ static int lbs_thread(void *data)
|
|||
struct net_device *dev = data;
|
||||
struct lbs_private *priv = dev->priv;
|
||||
wait_queue_t wait;
|
||||
u8 ireg = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_THREAD);
|
||||
|
||||
|
@ -661,9 +668,10 @@ static int lbs_thread(void *data)
|
|||
|
||||
for (;;) {
|
||||
int shouldsleep;
|
||||
u8 resp_idx;
|
||||
|
||||
lbs_deb_thread( "main-thread 111: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
|
||||
priv->intcounter, priv->currenttxskb, priv->dnld_sent);
|
||||
lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n",
|
||||
priv->currenttxskb, priv->dnld_sent);
|
||||
|
||||
add_wait_queue(&priv->waitq, &wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
@ -675,8 +683,6 @@ static int lbs_thread(void *data)
|
|||
shouldsleep = 1; /* We need to wait until we're _told_ to die */
|
||||
else if (priv->psstate == PS_STATE_SLEEP)
|
||||
shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */
|
||||
else if (priv->intcounter)
|
||||
shouldsleep = 0; /* Interrupt pending. Deal with it now */
|
||||
else if (priv->cmd_timed_out)
|
||||
shouldsleep = 0; /* Command timed out. Recover */
|
||||
else if (!priv->fw_ready)
|
||||
|
@ -689,29 +695,34 @@ static int lbs_thread(void *data)
|
|||
shouldsleep = 1; /* Can't send a command; one already running */
|
||||
else if (!list_empty(&priv->cmdpendingq))
|
||||
shouldsleep = 0; /* We have a command to send */
|
||||
else if (__kfifo_len(priv->event_fifo))
|
||||
shouldsleep = 0; /* We have an event to process */
|
||||
else if (priv->resp_len[priv->resp_idx])
|
||||
shouldsleep = 0; /* We have a command response */
|
||||
else
|
||||
shouldsleep = 1; /* No command */
|
||||
|
||||
if (shouldsleep) {
|
||||
lbs_deb_thread("main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n",
|
||||
priv->connect_status, priv->intcounter,
|
||||
lbs_deb_thread("sleeping, connect_status %d, "
|
||||
"ps_mode %d, ps_state %d\n",
|
||||
priv->connect_status,
|
||||
priv->psmode, priv->psstate);
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
schedule();
|
||||
} else
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
|
||||
lbs_deb_thread("main-thread 222 (waking up): intcounter=%d currenttxskb=%p dnld_sent=%d\n",
|
||||
priv->intcounter, priv->currenttxskb, priv->dnld_sent);
|
||||
lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n",
|
||||
priv->currenttxskb, priv->dnld_sent);
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&priv->waitq, &wait);
|
||||
|
||||
lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
|
||||
priv->intcounter, priv->currenttxskb, priv->dnld_sent);
|
||||
lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n",
|
||||
priv->currenttxskb, priv->dnld_sent);
|
||||
|
||||
if (kthread_should_stop()) {
|
||||
lbs_deb_thread("main-thread: break from main thread\n");
|
||||
lbs_deb_thread("break from main thread\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -720,35 +731,23 @@ static int lbs_thread(void *data)
|
|||
continue;
|
||||
}
|
||||
|
||||
lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n",
|
||||
priv->currenttxskb, priv->dnld_sent);
|
||||
|
||||
/* Process any pending command response */
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
|
||||
if (priv->intcounter) {
|
||||
u8 int_status;
|
||||
|
||||
priv->intcounter = 0;
|
||||
int_status = priv->hw_get_int_status(priv, &ireg);
|
||||
|
||||
if (int_status) {
|
||||
lbs_deb_thread("main-thread: reading HOST_INT_STATUS_REG failed\n");
|
||||
resp_idx = priv->resp_idx;
|
||||
if (priv->resp_len[resp_idx]) {
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
continue;
|
||||
}
|
||||
priv->hisregcpy |= ireg;
|
||||
}
|
||||
|
||||
lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
|
||||
priv->intcounter, priv->currenttxskb, priv->dnld_sent);
|
||||
|
||||
/* command response? */
|
||||
if (priv->hisregcpy & MRVDRV_CMD_UPLD_RDY) {
|
||||
lbs_deb_thread("main-thread: cmd response ready\n");
|
||||
|
||||
priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY;
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
lbs_process_rx_command(priv);
|
||||
lbs_process_command_response(priv,
|
||||
priv->resp_buf[resp_idx],
|
||||
priv->resp_len[resp_idx]);
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
priv->resp_len[resp_idx] = 0;
|
||||
}
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
|
||||
/* command timeout stuff */
|
||||
if (priv->cmd_timed_out && priv->cur_cmd) {
|
||||
struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
|
||||
|
||||
|
@ -757,8 +756,17 @@ static int lbs_thread(void *data)
|
|||
le16_to_cpu(cmdnode->cmdbuf->command));
|
||||
lbs_complete_command(priv, cmdnode, -ETIMEDOUT);
|
||||
priv->nr_retries = 0;
|
||||
#ifdef CONFIG_OLPC
|
||||
if (machine_is_olpc()) {
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
printk(KERN_CRIT "Resetting OLPC wireless via EC...\n");
|
||||
olpc_ec_cmd(0x25, NULL, 0, NULL, 0);
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
priv->cur_cmd = NULL;
|
||||
priv->dnld_sent = DNLD_RES_RECEIVED;
|
||||
lbs_pr_info("requeueing command %x due to timeout (#%d)\n",
|
||||
le16_to_cpu(cmdnode->cmdbuf->command), priv->nr_retries);
|
||||
|
||||
|
@ -769,21 +777,18 @@ static int lbs_thread(void *data)
|
|||
}
|
||||
priv->cmd_timed_out = 0;
|
||||
|
||||
/* Any Card Event */
|
||||
if (priv->hisregcpy & MRVDRV_CARDEVENT) {
|
||||
lbs_deb_thread("main-thread: Card Event Activity\n");
|
||||
/* Process hardware events, e.g. card removed, link lost */
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
while (__kfifo_len(priv->event_fifo)) {
|
||||
u32 event;
|
||||
|
||||
priv->hisregcpy &= ~MRVDRV_CARDEVENT;
|
||||
|
||||
if (priv->hw_read_event_cause(priv)) {
|
||||
lbs_pr_alert("main-thread: hw_read_event_cause failed\n");
|
||||
__kfifo_get(priv->event_fifo, (unsigned char *) &event,
|
||||
sizeof(event));
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
continue;
|
||||
lbs_process_event(priv, event);
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
}
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
lbs_process_event(priv);
|
||||
} else
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
|
||||
if (!priv->fw_ready)
|
||||
continue;
|
||||
|
@ -792,10 +797,12 @@ static int lbs_thread(void *data)
|
|||
if (priv->psstate == PS_STATE_PRE_SLEEP &&
|
||||
!priv->dnld_sent && !priv->cur_cmd) {
|
||||
if (priv->connect_status == LBS_CONNECTED) {
|
||||
lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n",
|
||||
priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd);
|
||||
lbs_deb_thread("pre-sleep, currenttxskb %p, "
|
||||
"dnld_sent %d, cur_cmd %p\n",
|
||||
priv->currenttxskb, priv->dnld_sent,
|
||||
priv->cur_cmd);
|
||||
|
||||
lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
|
||||
lbs_ps_confirm_sleep(priv);
|
||||
} else {
|
||||
/* workaround for firmware sending
|
||||
* deauth/linkloss event immediately
|
||||
|
@ -803,7 +810,8 @@ static int lbs_thread(void *data)
|
|||
* after firmware fixes it
|
||||
*/
|
||||
priv->psstate = PS_STATE_AWAKE;
|
||||
lbs_pr_alert("main-thread: ignore PS_SleepConfirm in non-connected state\n");
|
||||
lbs_pr_alert("ignore PS_SleepConfirm in "
|
||||
"non-connected state\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -857,22 +865,24 @@ static int lbs_thread(void *data)
|
|||
static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy,
|
||||
struct cmd_header *cmd)
|
||||
{
|
||||
lbs_deb_fw("HOST_SLEEP_ACTIVATE succeeded\n");
|
||||
lbs_deb_enter(LBS_DEB_FW);
|
||||
|
||||
netif_device_detach(priv->dev);
|
||||
if (priv->mesh_dev)
|
||||
netif_device_detach(priv->mesh_dev);
|
||||
|
||||
priv->fw_ready = 0;
|
||||
lbs_deb_leave(LBS_DEB_FW);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int lbs_suspend(struct lbs_private *priv)
|
||||
{
|
||||
struct cmd_header cmd;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_FW);
|
||||
|
||||
if (priv->wol_criteria == 0xffffffff) {
|
||||
lbs_pr_info("Suspend attempt without configuring wake params!\n");
|
||||
return -EINVAL;
|
||||
|
@ -885,12 +895,15 @@ int lbs_suspend(struct lbs_private *priv)
|
|||
if (ret)
|
||||
lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret);
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_suspend);
|
||||
|
||||
int lbs_resume(struct lbs_private *priv)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_FW);
|
||||
|
||||
priv->fw_ready = 1;
|
||||
|
||||
/* Firmware doesn't seem to give us RX packets any more
|
||||
|
@ -902,6 +915,7 @@ int lbs_resume(struct lbs_private *priv)
|
|||
if (priv->mesh_dev)
|
||||
netif_device_attach(priv->mesh_dev);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_FW);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_resume);
|
||||
|
@ -930,7 +944,7 @@ static int lbs_setup_firmware(struct lbs_private *priv)
|
|||
goto done;
|
||||
}
|
||||
|
||||
lbs_set_mac_packet_filter(priv);
|
||||
lbs_set_mac_control(priv);
|
||||
|
||||
ret = lbs_get_data_rate(priv);
|
||||
if (ret < 0) {
|
||||
|
@ -953,6 +967,7 @@ static void command_timer_fn(unsigned long data)
|
|||
struct lbs_private *priv = (struct lbs_private *)data;
|
||||
unsigned long flags;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
if (!priv->cur_cmd) {
|
||||
|
@ -964,15 +979,30 @@ static void command_timer_fn(unsigned long data)
|
|||
|
||||
priv->cmd_timed_out = 1;
|
||||
wake_up_interruptible(&priv->waitq);
|
||||
out:
|
||||
out:
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
}
|
||||
|
||||
static void lbs_sync_channel_worker(struct work_struct *work)
|
||||
{
|
||||
struct lbs_private *priv = container_of(work, struct lbs_private,
|
||||
sync_channel);
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
if (lbs_update_channel(priv))
|
||||
lbs_pr_info("Channel synchronization failed.");
|
||||
lbs_deb_leave(LBS_DEB_MAIN);
|
||||
}
|
||||
|
||||
|
||||
static int lbs_init_adapter(struct lbs_private *priv)
|
||||
{
|
||||
size_t bufsize;
|
||||
int i, ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
|
||||
/* Allocate buffer to store the BSSID list */
|
||||
bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
|
||||
priv->networks = kzalloc(bufsize, GFP_KERNEL);
|
||||
|
@ -990,14 +1020,6 @@ static int lbs_init_adapter(struct lbs_private *priv)
|
|||
&priv->network_free_list);
|
||||
}
|
||||
|
||||
priv->lbs_ps_confirm_sleep.seqnum = cpu_to_le16(++priv->seqnum);
|
||||
priv->lbs_ps_confirm_sleep.command =
|
||||
cpu_to_le16(CMD_802_11_PS_MODE);
|
||||
priv->lbs_ps_confirm_sleep.size =
|
||||
cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep));
|
||||
priv->lbs_ps_confirm_sleep.action =
|
||||
cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
|
||||
|
||||
memset(priv->current_addr, 0xff, ETH_ALEN);
|
||||
|
||||
priv->connect_status = LBS_DISCONNECTED;
|
||||
|
@ -1005,7 +1027,7 @@ static int lbs_init_adapter(struct lbs_private *priv)
|
|||
priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
|
||||
priv->mode = IW_MODE_INFRA;
|
||||
priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
|
||||
priv->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
|
||||
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
|
||||
priv->radioon = RADIO_ON;
|
||||
priv->auto_rate = 1;
|
||||
priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
|
||||
|
@ -1026,24 +1048,38 @@ static int lbs_init_adapter(struct lbs_private *priv)
|
|||
/* Allocate the command buffers */
|
||||
if (lbs_allocate_cmd_buffer(priv)) {
|
||||
lbs_pr_err("Out of memory allocating command buffers\n");
|
||||
ret = -1;
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
priv->resp_idx = 0;
|
||||
priv->resp_len[0] = priv->resp_len[1] = 0;
|
||||
|
||||
/* Create the event FIFO */
|
||||
priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL);
|
||||
if (IS_ERR(priv->event_fifo)) {
|
||||
lbs_pr_err("Out of memory allocating event FIFO buffer\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lbs_free_adapter(struct lbs_private *priv)
|
||||
{
|
||||
lbs_deb_fw("free command buffer\n");
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
|
||||
lbs_free_cmd_buffer(priv);
|
||||
|
||||
lbs_deb_fw("free command_timer\n");
|
||||
if (priv->event_fifo)
|
||||
kfifo_free(priv->event_fifo);
|
||||
del_timer(&priv->command_timer);
|
||||
|
||||
lbs_deb_fw("free scan results table\n");
|
||||
kfree(priv->networks);
|
||||
priv->networks = NULL;
|
||||
|
||||
lbs_deb_leave(LBS_DEB_MAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1058,7 +1094,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
|
|||
struct net_device *dev = NULL;
|
||||
struct lbs_private *priv = NULL;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_NET);
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
|
||||
/* Allocate an Ethernet device and register it */
|
||||
dev = alloc_etherdev(sizeof(struct lbs_private));
|
||||
|
@ -1084,6 +1120,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
|
|||
dev->stop = lbs_eth_stop;
|
||||
dev->set_mac_address = lbs_set_mac_address;
|
||||
dev->tx_timeout = lbs_tx_timeout;
|
||||
dev->do_ioctl = lbs_do_ioctl;
|
||||
dev->get_stats = lbs_get_stats;
|
||||
dev->watchdog_timeo = 5 * HZ;
|
||||
dev->ethtool_ops = &lbs_ethtool_ops;
|
||||
|
@ -1108,7 +1145,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
|
|||
priv->work_thread = create_singlethread_workqueue("lbs_worker");
|
||||
INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
|
||||
INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
|
||||
INIT_WORK(&priv->sync_channel, lbs_sync_channel);
|
||||
INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);
|
||||
|
||||
sprintf(priv->mesh_ssid, "mesh");
|
||||
priv->mesh_ssid_len = 4;
|
||||
|
@ -1124,7 +1161,7 @@ err_init_adapter:
|
|||
priv = NULL;
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv);
|
||||
lbs_deb_leave_args(LBS_DEB_MAIN, "priv %p", priv);
|
||||
return priv;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_add_card);
|
||||
|
@ -1192,6 +1229,10 @@ int lbs_start_card(struct lbs_private *priv)
|
|||
if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
|
||||
lbs_pr_err("cannot register lbs_rtap attribute\n");
|
||||
|
||||
lbs_update_channel(priv);
|
||||
|
||||
/* 5.0.16p0 is known to NOT support any mesh */
|
||||
if (priv->fwrelease > 0x05001000) {
|
||||
/* Enable mesh, if supported, and work out which TLV it uses.
|
||||
0x100 + 291 is an unofficial value used in 5.110.20.pXX
|
||||
0x100 + 37 is the official value used in 5.110.21.pXX
|
||||
|
@ -1205,7 +1246,6 @@ int lbs_start_card(struct lbs_private *priv)
|
|||
It's just that 5.110.20.pXX will not have done anything
|
||||
useful */
|
||||
|
||||
lbs_update_channel(priv);
|
||||
priv->mesh_tlv = 0x100 + 291;
|
||||
if (lbs_mesh_config(priv, 1, priv->curbssparams.channel)) {
|
||||
priv->mesh_tlv = 0x100 + 37;
|
||||
|
@ -1218,6 +1258,7 @@ int lbs_start_card(struct lbs_private *priv)
|
|||
if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
|
||||
lbs_pr_err("cannot register lbs_mesh attribute\n");
|
||||
}
|
||||
}
|
||||
|
||||
lbs_debugfs_init_one(priv, dev);
|
||||
|
||||
|
@ -1291,6 +1332,7 @@ static int lbs_add_mesh(struct lbs_private *priv)
|
|||
mesh_dev->open = lbs_dev_open;
|
||||
mesh_dev->hard_start_xmit = lbs_hard_start_xmit;
|
||||
mesh_dev->stop = lbs_mesh_stop;
|
||||
mesh_dev->do_ioctl = lbs_do_ioctl;
|
||||
mesh_dev->get_stats = lbs_get_stats;
|
||||
mesh_dev->set_mac_address = lbs_set_mac_address;
|
||||
mesh_dev->ethtool_ops = &lbs_ethtool_ops;
|
||||
|
@ -1327,35 +1369,25 @@ done:
|
|||
lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_add_mesh);
|
||||
|
||||
|
||||
static void lbs_remove_mesh(struct lbs_private *priv)
|
||||
{
|
||||
struct net_device *mesh_dev;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
|
||||
if (!priv)
|
||||
goto out;
|
||||
|
||||
mesh_dev = priv->mesh_dev;
|
||||
if (!mesh_dev)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MESH);
|
||||
netif_stop_queue(mesh_dev);
|
||||
netif_carrier_off(priv->mesh_dev);
|
||||
|
||||
sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
|
||||
unregister_netdev(mesh_dev);
|
||||
|
||||
priv->mesh_dev = NULL;
|
||||
free_netdev(mesh_dev);
|
||||
|
||||
out:
|
||||
lbs_deb_leave(LBS_DEB_MAIN);
|
||||
lbs_deb_leave(LBS_DEB_MESH);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_remove_mesh);
|
||||
|
||||
/**
|
||||
* @brief This function finds the CFP in
|
||||
|
@ -1366,7 +1398,7 @@ EXPORT_SYMBOL_GPL(lbs_remove_mesh);
|
|||
* @param cfp_no A pointer to CFP number
|
||||
* @return A pointer to CFP
|
||||
*/
|
||||
struct chan_freq_power *lbs_get_region_cfp_table(u8 region, u8 band, int *cfp_no)
|
||||
struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
|
||||
{
|
||||
int i, end;
|
||||
|
||||
|
@ -1400,8 +1432,7 @@ int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
|
|||
|
||||
memset(priv->region_channel, 0, sizeof(priv->region_channel));
|
||||
|
||||
{
|
||||
cfp = lbs_get_region_cfp_table(region, band, &cfp_no);
|
||||
cfp = lbs_get_region_cfp_table(region, &cfp_no);
|
||||
if (cfp != NULL) {
|
||||
priv->region_channel[i].nrcfp = cfp_no;
|
||||
priv->region_channel[i].CFP = cfp;
|
||||
|
@ -1415,54 +1446,54 @@ int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
|
|||
priv->region_channel[i].region = region;
|
||||
priv->region_channel[i].band = band;
|
||||
i++;
|
||||
}
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles the interrupt. it will change PS
|
||||
* state if applicable. it will wake up main_thread to handle
|
||||
* the interrupt event as well.
|
||||
*
|
||||
* @param dev A pointer to net_device structure
|
||||
* @return n/a
|
||||
*/
|
||||
void lbs_interrupt(struct lbs_private *priv)
|
||||
void lbs_queue_event(struct lbs_private *priv, u32 event)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_THREAD);
|
||||
|
||||
lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter);
|
||||
|
||||
priv->intcounter++;
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
if (priv->psstate == PS_STATE_SLEEP)
|
||||
priv->psstate = PS_STATE_AWAKE;
|
||||
|
||||
__kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32));
|
||||
|
||||
wake_up_interruptible(&priv->waitq);
|
||||
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
lbs_deb_leave(LBS_DEB_THREAD);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_queue_event);
|
||||
|
||||
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_THREAD);
|
||||
|
||||
if (priv->psstate == PS_STATE_SLEEP)
|
||||
priv->psstate = PS_STATE_AWAKE;
|
||||
|
||||
/* Swap buffers by flipping the response index */
|
||||
BUG_ON(resp_idx > 1);
|
||||
priv->resp_idx = resp_idx;
|
||||
|
||||
wake_up_interruptible(&priv->waitq);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_THREAD);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_interrupt);
|
||||
|
||||
int lbs_reset_device(struct lbs_private *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
ret = lbs_prepare_and_send_command(priv, CMD_802_11_RESET,
|
||||
CMD_ACT_HALT, 0, 0, NULL);
|
||||
msleep_interruptible(10);
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_reset_device);
|
||||
EXPORT_SYMBOL_GPL(lbs_notify_command_response);
|
||||
|
||||
static int __init lbs_init_module(void)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
memset(&confirm_sleep, 0, sizeof(confirm_sleep));
|
||||
confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE);
|
||||
confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep));
|
||||
confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
|
||||
lbs_debugfs_init();
|
||||
lbs_deb_leave(LBS_DEB_MAIN);
|
||||
return 0;
|
||||
|
@ -1471,9 +1502,7 @@ static int __init lbs_init_module(void)
|
|||
static void __exit lbs_exit_module(void)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
|
||||
lbs_debugfs_remove();
|
||||
|
||||
lbs_deb_leave(LBS_DEB_MAIN);
|
||||
}
|
||||
|
||||
|
@ -1484,13 +1513,17 @@ static void __exit lbs_exit_module(void)
|
|||
static int lbs_rtap_open(struct net_device *dev)
|
||||
{
|
||||
/* Yes, _stop_ the queue. Because we don't support injection */
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
netif_carrier_off(dev);
|
||||
netif_stop_queue(dev);
|
||||
lbs_deb_leave(LBS_DEB_LEAVE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_rtap_stop(struct net_device *dev)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
lbs_deb_leave(LBS_DEB_MAIN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1503,30 +1536,38 @@ static int lbs_rtap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
static struct net_device_stats *lbs_rtap_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct lbs_private *priv = dev->priv;
|
||||
lbs_deb_enter(LBS_DEB_NET);
|
||||
return &priv->stats;
|
||||
}
|
||||
|
||||
|
||||
static void lbs_remove_rtap(struct lbs_private *priv)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
if (priv->rtap_net_dev == NULL)
|
||||
return;
|
||||
unregister_netdev(priv->rtap_net_dev);
|
||||
free_netdev(priv->rtap_net_dev);
|
||||
priv->rtap_net_dev = NULL;
|
||||
lbs_deb_leave(LBS_DEB_MAIN);
|
||||
}
|
||||
|
||||
static int lbs_add_rtap(struct lbs_private *priv)
|
||||
{
|
||||
int rc = 0;
|
||||
int ret = 0;
|
||||
struct net_device *rtap_dev;
|
||||
|
||||
if (priv->rtap_net_dev)
|
||||
return -EPERM;
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
if (priv->rtap_net_dev) {
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rtap_dev = alloc_netdev(0, "rtap%d", ether_setup);
|
||||
if (rtap_dev == NULL)
|
||||
return -ENOMEM;
|
||||
if (rtap_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN);
|
||||
rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP;
|
||||
|
@ -1536,17 +1577,46 @@ static int lbs_add_rtap(struct lbs_private *priv)
|
|||
rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit;
|
||||
rtap_dev->set_multicast_list = lbs_set_multicast_list;
|
||||
rtap_dev->priv = priv;
|
||||
SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent);
|
||||
|
||||
rc = register_netdev(rtap_dev);
|
||||
if (rc) {
|
||||
ret = register_netdev(rtap_dev);
|
||||
if (ret) {
|
||||
free_netdev(rtap_dev);
|
||||
return rc;
|
||||
goto out;
|
||||
}
|
||||
priv->rtap_net_dev = rtap_dev;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_IEEE80211
|
||||
const char *escape_essid(const char *essid, u8 essid_len)
|
||||
{
|
||||
static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
|
||||
const char *s = essid;
|
||||
char *d = escaped;
|
||||
|
||||
if (ieee80211_is_empty_essid(essid, essid_len)) {
|
||||
memcpy(escaped, "<hidden>", sizeof("<hidden>"));
|
||||
return escaped;
|
||||
}
|
||||
|
||||
essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
|
||||
while (essid_len--) {
|
||||
if (*s == '\0') {
|
||||
*d++ = '\\';
|
||||
*d++ = '0';
|
||||
s++;
|
||||
} else {
|
||||
*d++ = *s++;
|
||||
}
|
||||
}
|
||||
*d = '\0';
|
||||
return escaped;
|
||||
}
|
||||
#endif
|
||||
|
||||
module_init(lbs_init_module);
|
||||
module_exit(lbs_exit_module);
|
||||
|
|
|
@ -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);
|
||||
if (in_interrupt())
|
||||
netif_rx(skb);
|
||||
else
|
||||
netif_rx_ni(skb);
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,33 +179,18 @@ 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) ?
|
||||
radiotap_hdr->data_retries = try_count ?
|
||||
(1 + priv->txretrycount - try_count) : 0;
|
||||
|
||||
|
||||
priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
|
||||
priv->rtap_net_dev);
|
||||
netif_rx(priv->currenttxskb);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue