mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-11-27 17:15:00 +02:00
Updating libertas wireless driver to latest version.
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10235 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
d32a09bb67
commit
03e8a3a945
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2007 OpenWrt.org
|
||||
# Copyright (C) 2007 - 2008 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
@ -33,6 +33,8 @@ endef
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||
$(Build/Patch)
|
||||
$(if $(QUILT),touch $(PKG_BUILD_DIR)/.quilt_used)
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
@ -42,7 +44,7 @@ define Build/Compile
|
||||
SUBDIRS="$(PKG_BUILD_DIR)" \
|
||||
CONFIG_LIBERTAS=m \
|
||||
CONFIG_LIBERTAS_USB=m \
|
||||
EXTRA_CFLAGS="-I$(PKG_BUILD_DIR) -include compat.h -I$(STAGING_DIR)/usr/include/mac80211" \
|
||||
EXTRA_CFLAGS="-I$(PKG_BUILD_DIR) -DCONFIG_LIBERTAS_DEBUG -include compat.h -I$(STAGING_DIR)/usr/include/mac80211" \
|
||||
modules
|
||||
endef
|
||||
|
||||
|
50
package/libertas/patches/100-compile_fix.patch
Normal file
50
package/libertas/patches/100-compile_fix.patch
Normal file
@ -0,0 +1,50 @@
|
||||
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);
|
@ -46,11 +46,13 @@ 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 < ARRAY_SIZE(region_code_mapping); i++) {
|
||||
for (i = 0; i < size; i++) {
|
||||
if (!memcmp(region, region_code_mapping[i].region,
|
||||
COUNTRY_CODE_LEN))
|
||||
return (region_code_mapping[i].code);
|
||||
@ -63,8 +65,9 @@ static u8 lbs_region_2_code(u8 *region)
|
||||
static u8 *lbs_code_2_region(u8 code)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
|
||||
u8 size = sizeof(region_code_mapping)
|
||||
/ sizeof(struct region_code_mapping);
|
||||
for (i = 0; i < size; i++) {
|
||||
if (region_code_mapping[i].code == code)
|
||||
return (region_code_mapping[i].region);
|
||||
}
|
||||
@ -87,7 +90,8 @@ 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 = ARRAY_SIZE(channel_freq_power_UN_BG);
|
||||
cfp_no = sizeof(channel_freq_power_UN_BG) /
|
||||
sizeof(struct chan_freq_power);
|
||||
|
||||
for (i = 0; i < cfp_no; i++) {
|
||||
if ((cfp + i)->channel == firstchan) {
|
||||
@ -137,12 +141,16 @@ static u8 lbs_channel_known_11d(u8 chan,
|
||||
u32 lbs_chan_2_freq(u8 chan, u8 band)
|
||||
{
|
||||
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 < ARRAY_SIZE(channel_freq_power_UN_BG); i++) {
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if (chan == cf[i].channel)
|
||||
freq = cf[i].freq;
|
||||
}
|
||||
|
@ -1,62 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2007 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
# $Id: Makefile 8694 2007-09-08 19:55:42Z nbd $
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=kmod-libertas
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define KernelPackage/libertas
|
||||
SUBMENU:=Other modules
|
||||
DEPENDS:=@TARGET_olpc +kmod-mac80211
|
||||
TITLE:=Marvell 88W8015 Wireless Driver
|
||||
FILES:= \
|
||||
$(PKG_BUILD_DIR)/libertas.$(LINUX_KMOD_SUFFIX) \
|
||||
$(PKG_BUILD_DIR)/usb8xxx.$(LINUX_KMOD_SUFFIX)
|
||||
# AUTOLOAD:=$(call AutoLoad,20,switch-core switch-robo switch-adm)
|
||||
endef
|
||||
|
||||
define Download/firmware
|
||||
URL:=http://dev.laptop.org/pub/firmware/libertas
|
||||
FILE:=usb8388-5.220.11.p5.bin
|
||||
MD5SUM=123
|
||||
endef
|
||||
|
||||
define Download/firmware_license
|
||||
URL:=http://dev.laptop.org/pub/firmware/libertas
|
||||
FILE:=LICENSE
|
||||
MD5SUM=123
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C "$(LINUX_DIR)" \
|
||||
CROSS_COMPILE="$(TARGET_CROSS)" \
|
||||
ARCH="$(LINUX_KARCH)" \
|
||||
SUBDIRS="$(PKG_BUILD_DIR)" \
|
||||
CONFIG_LIBERTAS=m \
|
||||
CONFIG_LIBERTAS_USB=m \
|
||||
EXTRA_CFLAGS="-I$(PKG_BUILD_DIR) -include compat.h -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)/LICENSE $(1)/lib/firmware/
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,libertas))
|
||||
$(eval $(call Download,firmware))
|
@ -163,17 +163,18 @@ done:
|
||||
}
|
||||
|
||||
|
||||
static int update_channel(struct lbs_private *priv)
|
||||
int lbs_update_channel(struct lbs_private *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* the channel in f/w could be out of sync, get the current channel */
|
||||
/* 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 = (u8) ret;
|
||||
|
||||
if (ret > 0) {
|
||||
priv->curbssparams.channel = ret;
|
||||
ret = 0;
|
||||
}
|
||||
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
@ -184,7 +185,7 @@ void lbs_sync_channel(struct work_struct *work)
|
||||
sync_channel);
|
||||
|
||||
lbs_deb_enter(LBS_DEB_ASSOC);
|
||||
if (update_channel(priv) != 0)
|
||||
if (lbs_update_channel(priv))
|
||||
lbs_pr_info("Channel synchronization failed.");
|
||||
lbs_deb_leave(LBS_DEB_ASSOC);
|
||||
}
|
||||
@ -196,33 +197,37 @@ static int assoc_helper_channel(struct lbs_private *priv,
|
||||
|
||||
lbs_deb_enter(LBS_DEB_ASSOC);
|
||||
|
||||
ret = update_channel(priv);
|
||||
if (ret < 0) {
|
||||
lbs_deb_assoc("ASSOC: channel: error getting channel.");
|
||||
ret = lbs_update_channel(priv);
|
||||
if (ret) {
|
||||
lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (assoc_req->channel == priv->curbssparams.channel)
|
||||
goto done;
|
||||
|
||||
if (priv->mesh_dev) {
|
||||
/* Disconnect mesh while associating -- otherwise it
|
||||
won't let us change channels */
|
||||
lbs_mesh_config(priv, 0);
|
||||
/* Change mesh channel first; 21.p21 firmware won't let
|
||||
you change channel otherwise (even though it'll return
|
||||
an error to this */
|
||||
lbs_mesh_config(priv, 0, assoc_req->channel);
|
||||
}
|
||||
|
||||
lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
|
||||
priv->curbssparams.channel, assoc_req->channel);
|
||||
priv->curbssparams.channel, assoc_req->channel);
|
||||
|
||||
ret = lbs_set_channel(priv, assoc_req->channel);
|
||||
if (ret < 0)
|
||||
lbs_deb_assoc("ASSOC: channel: error setting channel.");
|
||||
lbs_deb_assoc("ASSOC: channel: error setting channel.\n");
|
||||
|
||||
/* FIXME: shouldn't need to grab the channel _again_ after setting
|
||||
* it since the firmware is supposed to return the new channel, but
|
||||
* whatever... */
|
||||
ret = update_channel(priv);
|
||||
if (ret < 0)
|
||||
lbs_deb_assoc("ASSOC: channel: error getting channel.");
|
||||
ret = lbs_update_channel(priv);
|
||||
if (ret) {
|
||||
lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (assoc_req->channel != priv->curbssparams.channel) {
|
||||
lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n",
|
||||
@ -240,11 +245,11 @@ static int assoc_helper_channel(struct lbs_private *priv,
|
||||
}
|
||||
|
||||
/* Must restart/rejoin adhoc networks after channel change */
|
||||
set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
|
||||
set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
|
||||
|
||||
restore_mesh:
|
||||
if (priv->mesh_dev)
|
||||
lbs_mesh_config(priv, 1);
|
||||
lbs_mesh_config(priv, 1, priv->curbssparams.channel);
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
|
||||
@ -253,7 +258,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
|
||||
|
||||
|
||||
static int assoc_helper_wep_keys(struct lbs_private *priv,
|
||||
struct assoc_request * assoc_req)
|
||||
struct assoc_request *assoc_req)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
@ -261,22 +266,11 @@ static int assoc_helper_wep_keys(struct lbs_private *priv,
|
||||
lbs_deb_enter(LBS_DEB_ASSOC);
|
||||
|
||||
/* Set or remove WEP keys */
|
||||
if ( assoc_req->wep_keys[0].len
|
||||
|| assoc_req->wep_keys[1].len
|
||||
|| assoc_req->wep_keys[2].len
|
||||
|| assoc_req->wep_keys[3].len) {
|
||||
ret = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_SET_WEP,
|
||||
CMD_ACT_ADD,
|
||||
CMD_OPTION_WAITFORRSP,
|
||||
0, assoc_req);
|
||||
} else {
|
||||
ret = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_SET_WEP,
|
||||
CMD_ACT_REMOVE,
|
||||
CMD_OPTION_WAITFORRSP,
|
||||
0, NULL);
|
||||
}
|
||||
if (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
|
||||
assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)
|
||||
ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_ADD, assoc_req);
|
||||
else
|
||||
ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, assoc_req);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
@ -286,6 +280,7 @@ static int assoc_helper_wep_keys(struct lbs_private *priv,
|
||||
priv->currentpacketfilter |= CMD_ACT_MAC_WEP_ENABLE;
|
||||
else
|
||||
priv->currentpacketfilter &= ~CMD_ACT_MAC_WEP_ENABLE;
|
||||
|
||||
ret = lbs_set_mac_packet_filter(priv);
|
||||
if (ret)
|
||||
goto out;
|
||||
@ -295,7 +290,7 @@ static int assoc_helper_wep_keys(struct lbs_private *priv,
|
||||
/* Copy WEP keys into priv wep key fields */
|
||||
for (i = 0; i < 4; i++) {
|
||||
memcpy(&priv->wep_keys[i], &assoc_req->wep_keys[i],
|
||||
sizeof(struct enc_key));
|
||||
sizeof(struct enc_key));
|
||||
}
|
||||
priv->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
|
||||
|
||||
@ -310,8 +305,8 @@ static int assoc_helper_secinfo(struct lbs_private *priv,
|
||||
struct assoc_request * assoc_req)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 do_wpa;
|
||||
u32 rsn = 0;
|
||||
uint16_t do_wpa;
|
||||
uint16_t rsn = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_ASSOC);
|
||||
|
||||
@ -328,28 +323,19 @@ static int assoc_helper_secinfo(struct lbs_private *priv,
|
||||
*/
|
||||
|
||||
/* Get RSN enabled/disabled */
|
||||
ret = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_ENABLE_RSN,
|
||||
CMD_ACT_GET,
|
||||
CMD_OPTION_WAITFORRSP,
|
||||
0, &rsn);
|
||||
ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn);
|
||||
if (ret) {
|
||||
lbs_deb_assoc("Failed to get RSN status: %d", ret);
|
||||
lbs_deb_assoc("Failed to get RSN status: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Don't re-enable RSN if it's already enabled */
|
||||
do_wpa = (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled);
|
||||
do_wpa = assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled;
|
||||
if (do_wpa == rsn)
|
||||
goto out;
|
||||
|
||||
/* Set RSN enabled/disabled */
|
||||
rsn = do_wpa;
|
||||
ret = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_ENABLE_RSN,
|
||||
CMD_ACT_SET,
|
||||
CMD_OPTION_WAITFORRSP,
|
||||
0, &rsn);
|
||||
ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &do_wpa);
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,16 +6,26 @@
|
||||
#include "hostcmd.h"
|
||||
#include "dev.h"
|
||||
|
||||
#define lbs_cmd(priv, cmdnr, cmd, callback, callback_arg) \
|
||||
__lbs_cmd(priv, cmdnr, &(cmd).hdr, sizeof(cmd), \
|
||||
callback, callback_arg)
|
||||
/* lbs_cmd() infers the size of the buffer to copy data back into, from
|
||||
the size of the target of the pointer. Since the command to be sent
|
||||
may often be smaller, that size is set in cmd->size by the caller.*/
|
||||
#define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \
|
||||
uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \
|
||||
(cmd)->hdr.size = cpu_to_le16(sizeof(*(cmd))); \
|
||||
__lbs_cmd(priv, cmdnr, &(cmd)->hdr, __sz, cb, cb_arg); \
|
||||
})
|
||||
|
||||
#define lbs_cmd_with_response(priv, cmdnr, cmd) \
|
||||
__lbs_cmd(priv, cmdnr, &(cmd).hdr, sizeof(cmd), \
|
||||
lbs_cmd_copyback, (unsigned long) &cmd)
|
||||
|
||||
#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);
|
||||
int __lbs_cmd(struct lbs_private *priv, uint16_t command,
|
||||
struct cmd_header *in_cmd, int in_cmd_size,
|
||||
struct cmd_header *in_cmd, int in_cmd_size,
|
||||
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
|
||||
unsigned long callback_arg);
|
||||
|
||||
@ -33,6 +43,19 @@ int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
|
||||
int lbs_get_channel(struct lbs_private *priv);
|
||||
int lbs_set_channel(struct lbs_private *priv, u8 channel);
|
||||
|
||||
int lbs_mesh_config(struct lbs_private *priv, int enable);
|
||||
int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
|
||||
|
||||
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria);
|
||||
int lbs_suspend(struct lbs_private *priv);
|
||||
int lbs_resume(struct lbs_private *priv);
|
||||
|
||||
int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
|
||||
uint16_t cmd_action, uint16_t *timeout);
|
||||
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct sleep_params *sp);
|
||||
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);
|
||||
|
||||
#endif /* _LBS_CMD_H */
|
||||
|
@ -43,14 +43,15 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
|
||||
msleep_interruptible(1000);
|
||||
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
|
||||
|
||||
/* Free Tx and Rx packets */
|
||||
kfree_skb(priv->currenttxskb);
|
||||
priv->currenttxskb = NULL;
|
||||
|
||||
/* report disconnect to upper layer */
|
||||
netif_stop_queue(priv->dev);
|
||||
netif_carrier_off(priv->dev);
|
||||
|
||||
/* Free Tx and Rx packets */
|
||||
kfree_skb(priv->currenttxskb);
|
||||
priv->currenttxskb = NULL;
|
||||
priv->tx_pending_len = 0;
|
||||
|
||||
/* reset SNR/NF/RSSI values */
|
||||
memset(priv->SNR, 0x00, sizeof(priv->SNR));
|
||||
memset(priv->NF, 0x00, sizeof(priv->NF));
|
||||
@ -145,29 +146,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lbs_ret_802_11_sleep_params(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp)
|
||||
{
|
||||
struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, calcontrol 0x%x "
|
||||
"extsleepclk 0x%x\n", le16_to_cpu(sp->error),
|
||||
le16_to_cpu(sp->offset), le16_to_cpu(sp->stabletime),
|
||||
sp->calcontrol, sp->externalsleepclk);
|
||||
|
||||
priv->sp.sp_error = le16_to_cpu(sp->error);
|
||||
priv->sp.sp_offset = le16_to_cpu(sp->offset);
|
||||
priv->sp.sp_stabletime = le16_to_cpu(sp->stabletime);
|
||||
priv->sp.sp_calcontrol = sp->calcontrol;
|
||||
priv->sp.sp_extsleepclk = sp->externalsleepclk;
|
||||
priv->sp.sp_reserved = le16_to_cpu(sp->reserved);
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_ret_802_11_stat(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp)
|
||||
{
|
||||
@ -394,23 +372,6 @@ static int lbs_ret_get_log(struct lbs_private *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_ret_802_11_enable_rsn(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp)
|
||||
{
|
||||
struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn;
|
||||
u32 * pdata_buf = priv->cur_cmd->pdata_buf;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
if (enable_rsn->action == cpu_to_le16(CMD_ACT_GET)) {
|
||||
if (pdata_buf)
|
||||
*pdata_buf = (u32) le16_to_cpu(enable_rsn->enable);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -428,25 +389,6 @@ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_ret_802_11_subscribe_event(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp)
|
||||
{
|
||||
struct cmd_ds_802_11_subscribe_event *cmd_event =
|
||||
&resp->params.subscribe_event;
|
||||
struct cmd_ds_802_11_subscribe_event *dst_event =
|
||||
priv->cur_cmd->pdata_buf;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
if (dst_event->action == cpu_to_le16(CMD_ACT_GET)) {
|
||||
dst_event->events = cmd_event->events;
|
||||
memcpy(dst_event->tlv, cmd_event->tlv, sizeof(dst_event->tlv));
|
||||
}
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int handle_cmd_response(struct lbs_private *priv,
|
||||
unsigned long dummy,
|
||||
struct cmd_header *cmd_response)
|
||||
@ -504,7 +446,7 @@ static inline int handle_cmd_response(struct lbs_private *priv,
|
||||
case CMD_RET(CMD_802_11_SET_AFC):
|
||||
case CMD_RET(CMD_802_11_GET_AFC):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
memmove(priv->cur_cmd->pdata_buf, &resp->params.afc,
|
||||
memmove((void *)priv->cur_cmd->callback_arg, &resp->params.afc,
|
||||
sizeof(struct cmd_ds_802_11_afc));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
@ -512,17 +454,11 @@ static inline int handle_cmd_response(struct lbs_private *priv,
|
||||
|
||||
case CMD_RET(CMD_MAC_MULTICAST_ADR):
|
||||
case CMD_RET(CMD_MAC_CONTROL):
|
||||
case CMD_RET(CMD_802_11_SET_WEP):
|
||||
case CMD_RET(CMD_802_11_RESET):
|
||||
case CMD_RET(CMD_802_11_AUTHENTICATE):
|
||||
case CMD_RET(CMD_802_11_RADIO_CONTROL):
|
||||
case CMD_RET(CMD_802_11_BEACON_STOP):
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_ENABLE_RSN):
|
||||
ret = lbs_ret_802_11_enable_rsn(priv, resp);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
|
||||
ret = lbs_ret_802_11_rate_adapt_rateset(priv, resp);
|
||||
break;
|
||||
@ -551,35 +487,22 @@ static inline int handle_cmd_response(struct lbs_private *priv,
|
||||
ret = lbs_ret_802_11d_domain_info(priv, resp);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_SLEEP_PARAMS):
|
||||
ret = lbs_ret_802_11_sleep_params(priv, resp);
|
||||
break;
|
||||
case CMD_RET(CMD_802_11_INACTIVITY_TIMEOUT):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
*((u16 *) priv->cur_cmd->pdata_buf) =
|
||||
le16_to_cpu(resp->params.inactivity_timeout.timeout);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_TPC_CFG):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
memmove(priv->cur_cmd->pdata_buf, &resp->params.tpccfg,
|
||||
memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg,
|
||||
sizeof(struct cmd_ds_802_11_tpc_cfg));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
break;
|
||||
case CMD_RET(CMD_802_11_LED_GPIO_CTRL):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
memmove(priv->cur_cmd->pdata_buf, &resp->params.ledgpio,
|
||||
memmove((void *)priv->cur_cmd->callback_arg, &resp->params.ledgpio,
|
||||
sizeof(struct cmd_ds_802_11_led_ctrl));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
break;
|
||||
case CMD_RET(CMD_802_11_SUBSCRIBE_EVENT):
|
||||
ret = lbs_ret_802_11_subscribe_event(priv, resp);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_PWR_CFG):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
memmove(priv->cur_cmd->pdata_buf, &resp->params.pwrcfg,
|
||||
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);
|
||||
|
||||
@ -587,21 +510,21 @@ static inline int handle_cmd_response(struct lbs_private *priv,
|
||||
|
||||
case CMD_RET(CMD_GET_TSF):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
memcpy(priv->cur_cmd->pdata_buf,
|
||||
memcpy((void *)priv->cur_cmd->callback_arg,
|
||||
&resp->params.gettsf.tsfvalue, sizeof(u64));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
break;
|
||||
case CMD_RET(CMD_BT_ACCESS):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
if (priv->cur_cmd->pdata_buf)
|
||||
memcpy(priv->cur_cmd->pdata_buf,
|
||||
if (priv->cur_cmd->callback_arg)
|
||||
memcpy((void *)priv->cur_cmd->callback_arg,
|
||||
&resp->params.bt.addr1, 2 * ETH_ALEN);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
break;
|
||||
case CMD_RET(CMD_FWT_ACCESS):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
if (priv->cur_cmd->pdata_buf)
|
||||
memcpy(priv->cur_cmd->pdata_buf, &resp->params.fwt,
|
||||
if (priv->cur_cmd->callback_arg)
|
||||
memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.fwt,
|
||||
sizeof(resp->params.fwt));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
break;
|
||||
@ -611,7 +534,7 @@ static inline int handle_cmd_response(struct lbs_private *priv,
|
||||
|
||||
default:
|
||||
lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
|
||||
resp->command);
|
||||
le16_to_cpu(resp->command));
|
||||
break;
|
||||
}
|
||||
lbs_deb_leave(LBS_DEB_HOST);
|
||||
@ -620,17 +543,14 @@ static inline int handle_cmd_response(struct lbs_private *priv,
|
||||
|
||||
int lbs_process_rx_command(struct lbs_private *priv)
|
||||
{
|
||||
u16 respcmd;
|
||||
uint16_t respcmd, curcmd;
|
||||
struct cmd_header *resp;
|
||||
int ret = 0;
|
||||
ulong flags;
|
||||
u16 result;
|
||||
unsigned long flags;
|
||||
uint16_t result;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_HOST);
|
||||
|
||||
/* Now we got response from FW, cancel the command timer */
|
||||
del_timer(&priv->command_timer);
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
@ -640,30 +560,57 @@ int lbs_process_rx_command(struct lbs_private *priv)
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
goto done;
|
||||
}
|
||||
resp = priv->cur_cmd->cmdbuf;
|
||||
|
||||
resp = (void *)priv->upld_buf;
|
||||
|
||||
curcmd = le16_to_cpu(resp->command);
|
||||
|
||||
respcmd = le16_to_cpu(resp->command);
|
||||
result = le16_to_cpu(resp->result);
|
||||
|
||||
lbs_deb_host("CMD_RESP: response 0x%04x, size %d, jiffies %lu\n",
|
||||
respcmd, priv->upld_len, jiffies);
|
||||
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);
|
||||
|
||||
if (!(respcmd & 0x8000)) {
|
||||
lbs_deb_host("invalid response!\n");
|
||||
priv->cur_cmd_retcode = -1;
|
||||
__lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
|
||||
priv->cur_cmd = NULL;
|
||||
if (resp->seqnum != resp->seqnum) {
|
||||
lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
|
||||
le16_to_cpu(resp->seqnum), le16_to_cpu(resp->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) {
|
||||
lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (resp->result == cpu_to_le16(0x0004)) {
|
||||
/* 0x0004 means -EAGAIN. Drop the response, let it time out
|
||||
and be resubmitted */
|
||||
lbs_pr_info("Firmware returns DEFER to command %x. Will let it time out...\n",
|
||||
le16_to_cpu(resp->command));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Now we got response from FW, cancel the command timer */
|
||||
del_timer(&priv->command_timer);
|
||||
priv->cmd_timed_out = 0;
|
||||
if (priv->nr_retries) {
|
||||
lbs_pr_info("Received result %x to command %x after %d retries\n",
|
||||
result, curcmd, priv->nr_retries);
|
||||
priv->nr_retries = 0;
|
||||
}
|
||||
|
||||
/* Store the response code to cur_cmd_retcode. */
|
||||
priv->cur_cmd_retcode = result;
|
||||
|
||||
if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
|
||||
struct cmd_ds_802_11_ps_mode *psmode = (void *) resp;
|
||||
struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1];
|
||||
u16 action = le16_to_cpu(psmode->action);
|
||||
|
||||
lbs_deb_host(
|
||||
@ -708,8 +655,7 @@ int lbs_process_rx_command(struct lbs_private *priv)
|
||||
lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
|
||||
}
|
||||
|
||||
__lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
|
||||
priv->cur_cmd = NULL;
|
||||
lbs_complete_command(priv, priv->cur_cmd, result);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
ret = 0;
|
||||
@ -730,9 +676,7 @@ int lbs_process_rx_command(struct lbs_private *priv)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
__lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
|
||||
priv->cur_cmd = NULL;
|
||||
lbs_complete_command(priv, priv->cur_cmd, result);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
ret = -1;
|
||||
@ -751,8 +695,7 @@ int lbs_process_rx_command(struct lbs_private *priv)
|
||||
|
||||
if (priv->cur_cmd) {
|
||||
/* Clean up and Put current command back to cmdfreeq */
|
||||
__lbs_cleanup_and_insert_cmd(priv, priv->cur_cmd);
|
||||
priv->cur_cmd = NULL;
|
||||
lbs_complete_command(priv, priv->cur_cmd, result);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
@ -762,6 +705,30 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lbs_send_confirmwake(struct lbs_private *priv)
|
||||
{
|
||||
struct cmd_header *cmd = &priv->lbs_ps_confirm_wake;
|
||||
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;
|
||||
|
||||
lbs_deb_host("SEND_WAKEC_CMD: before download\n");
|
||||
|
||||
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));
|
||||
if (ret)
|
||||
lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_process_event(struct lbs_private *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
@ -810,9 +777,13 @@ int lbs_process_event(struct lbs_private *priv)
|
||||
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_HOST_AWAKE:
|
||||
lbs_deb_cmd("EVENT: HOST_AWAKE\n");
|
||||
lbs_send_confirmwake(priv);
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_PS_AWAKE:
|
||||
lbs_deb_cmd("EVENT: awake\n");
|
||||
|
||||
/* handle unexpected PS AWAKE event */
|
||||
if (priv->psstate == PS_STATE_FULL_POWER) {
|
||||
lbs_deb_cmd(
|
||||
@ -875,9 +846,10 @@ int lbs_process_event(struct lbs_private *priv)
|
||||
}
|
||||
lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
|
||||
priv->mesh_connect_status = LBS_CONNECTED;
|
||||
if (priv->mesh_open == 1) {
|
||||
netif_wake_queue(priv->mesh_dev);
|
||||
if (priv->mesh_open) {
|
||||
netif_carrier_on(priv->mesh_dev);
|
||||
if (!priv->tx_pending_len)
|
||||
netif_wake_queue(priv->mesh_dev);
|
||||
}
|
||||
priv->mode = IW_MODE_ADHOC;
|
||||
schedule_work(&priv->sync_channel);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "decl.h"
|
||||
#include "host.h"
|
||||
#include "debugfs.h"
|
||||
#include "cmd.h"
|
||||
|
||||
static struct dentry *lbs_dir;
|
||||
static char *szStates[] = {
|
||||
@ -103,71 +104,64 @@ static ssize_t lbs_sleepparams_write(struct file *file,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t buf_size, res;
|
||||
ssize_t buf_size, ret;
|
||||
struct sleep_params sp;
|
||||
int p1, p2, p3, p4, p5, p6;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, user_buf, buf_size)) {
|
||||
res = -EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
res = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
|
||||
if (res != 6) {
|
||||
res = -EFAULT;
|
||||
ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
|
||||
if (ret != 6) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
priv->sp.sp_error = p1;
|
||||
priv->sp.sp_offset = p2;
|
||||
priv->sp.sp_stabletime = p3;
|
||||
priv->sp.sp_calcontrol = p4;
|
||||
priv->sp.sp_extsleepclk = p5;
|
||||
priv->sp.sp_reserved = p6;
|
||||
sp.sp_error = p1;
|
||||
sp.sp_offset = p2;
|
||||
sp.sp_stabletime = p3;
|
||||
sp.sp_calcontrol = p4;
|
||||
sp.sp_extsleepclk = p5;
|
||||
sp.sp_reserved = p6;
|
||||
|
||||
res = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_SLEEP_PARAMS,
|
||||
CMD_ACT_SET,
|
||||
CMD_OPTION_WAITFORRSP, 0, NULL);
|
||||
|
||||
if (!res)
|
||||
res = count;
|
||||
else
|
||||
res = -EINVAL;
|
||||
ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp);
|
||||
if (!ret)
|
||||
ret = count;
|
||||
else if (ret > 0)
|
||||
ret = -EINVAL;
|
||||
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t res;
|
||||
ssize_t ret;
|
||||
size_t pos = 0;
|
||||
struct sleep_params sp;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
|
||||
res = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_SLEEP_PARAMS,
|
||||
CMD_ACT_GET,
|
||||
CMD_OPTION_WAITFORRSP, 0, NULL);
|
||||
if (res) {
|
||||
res = -EFAULT;
|
||||
ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
pos += snprintf(buf, len, "%d %d %d %d %d %d\n", priv->sp.sp_error,
|
||||
priv->sp.sp_offset, priv->sp.sp_stabletime,
|
||||
priv->sp.sp_calcontrol, priv->sp.sp_extsleepclk,
|
||||
priv->sp.sp_reserved);
|
||||
pos += snprintf(buf, len, "%d %d %d %d %d %d\n", sp.sp_error,
|
||||
sp.sp_offset, sp.sp_stabletime,
|
||||
sp.sp_calcontrol, sp.sp_extsleepclk,
|
||||
sp.sp_reserved);
|
||||
|
||||
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t lbs_extscan(struct file *file, const char __user *userbuf,
|
||||
@ -295,7 +289,7 @@ static ssize_t lbs_setuserscan(struct file *file,
|
||||
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
buf_size = min(count, len - 1);
|
||||
if (copy_from_user(buf, userbuf, buf_size)) {
|
||||
res = -EFAULT;
|
||||
@ -352,20 +346,19 @@ static ssize_t lbs_setuserscan(struct file *file,
|
||||
* and returns a pointer to the first data byte of the TLV, or to NULL
|
||||
* if the TLV hasn't been found.
|
||||
*/
|
||||
static void *lbs_tlv_find(u16 tlv_type, const u8 *tlv, u16 size)
|
||||
static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size)
|
||||
{
|
||||
__le16 le_type = cpu_to_le16(tlv_type);
|
||||
ssize_t pos = 0;
|
||||
struct mrvlietypesheader *tlv_h;
|
||||
uint16_t length;
|
||||
ssize_t pos = 0;
|
||||
|
||||
while (pos < size) {
|
||||
u16 length;
|
||||
tlv_h = (struct mrvlietypesheader *) tlv;
|
||||
if (tlv_h->type == le_type)
|
||||
return tlv_h;
|
||||
if (tlv_h->len == 0)
|
||||
if (!tlv_h->len)
|
||||
return NULL;
|
||||
length = le16_to_cpu(tlv_h->len) +
|
||||
sizeof(struct mrvlietypesheader);
|
||||
if (tlv_h->type == cpu_to_le16(tlv_type))
|
||||
return tlv_h;
|
||||
length = le16_to_cpu(tlv_h->len) + sizeof(*tlv_h);
|
||||
pos += length;
|
||||
tlv += length;
|
||||
}
|
||||
@ -373,100 +366,100 @@ static void *lbs_tlv_find(u16 tlv_type, const u8 *tlv, u16 size)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This just gets the bitmap of currently subscribed events. Used when
|
||||
* adding an additonal event subscription.
|
||||
*/
|
||||
static u16 lbs_get_events_bitmap(struct lbs_private *priv)
|
||||
{
|
||||
ssize_t res;
|
||||
|
||||
struct cmd_ds_802_11_subscribe_event *events = kzalloc(
|
||||
sizeof(struct cmd_ds_802_11_subscribe_event),
|
||||
GFP_KERNEL);
|
||||
|
||||
res = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_SUBSCRIBE_EVENT, CMD_ACT_GET,
|
||||
CMD_OPTION_WAITFORRSP, 0, events);
|
||||
|
||||
if (res) {
|
||||
kfree(events);
|
||||
return 0;
|
||||
}
|
||||
return le16_to_cpu(events->events);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_threshold_read(
|
||||
u16 tlv_type, u16 event_mask,
|
||||
struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
|
||||
struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct cmd_ds_802_11_subscribe_event *subscribed;
|
||||
struct mrvlietypes_thresholds *got;
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t res = 0;
|
||||
ssize_t ret = 0;
|
||||
size_t pos = 0;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
char *buf;
|
||||
u8 value;
|
||||
u8 freq;
|
||||
int events = 0;
|
||||
|
||||
struct cmd_ds_802_11_subscribe_event *subscribed = kzalloc(
|
||||
sizeof(struct cmd_ds_802_11_subscribe_event),
|
||||
GFP_KERNEL);
|
||||
struct mrvlietypes_thresholds *got;
|
||||
buf = (char *)get_zeroed_page(GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
res = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_SUBSCRIBE_EVENT, CMD_ACT_GET,
|
||||
CMD_OPTION_WAITFORRSP, 0, subscribed);
|
||||
if (res) {
|
||||
kfree(subscribed);
|
||||
return res;
|
||||
subscribed = kzalloc(sizeof(*subscribed), GFP_KERNEL);
|
||||
if (!subscribed) {
|
||||
ret = -ENOMEM;
|
||||
goto out_page;
|
||||
}
|
||||
|
||||
subscribed->hdr.size = cpu_to_le16(sizeof(*subscribed));
|
||||
subscribed->action = cpu_to_le16(CMD_ACT_GET);
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, subscribed);
|
||||
if (ret)
|
||||
goto out_cmd;
|
||||
|
||||
got = lbs_tlv_find(tlv_type, subscribed->tlv, sizeof(subscribed->tlv));
|
||||
if (got) {
|
||||
value = got->value;
|
||||
freq = got->freq;
|
||||
events = le16_to_cpu(subscribed->events);
|
||||
|
||||
pos += snprintf(buf, len, "%d %d %d\n", value, freq,
|
||||
!!(events & event_mask));
|
||||
}
|
||||
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
|
||||
out_cmd:
|
||||
kfree(subscribed);
|
||||
|
||||
if (got)
|
||||
pos += snprintf(buf, len, "%d %d %d\n", value, freq,
|
||||
!!(events & event_mask));
|
||||
|
||||
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
|
||||
free_page(addr);
|
||||
return res;
|
||||
out_page:
|
||||
free_page((unsigned long)buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_threshold_write(
|
||||
u16 tlv_type, u16 event_mask,
|
||||
struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
|
||||
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;
|
||||
int value, freq, curr_mask, new_mask;
|
||||
unsigned long addr = get_zeroed_page(GFP_KERNEL);
|
||||
char *buf = (char *)addr;
|
||||
struct cmd_ds_802_11_subscribe_event *events;
|
||||
struct mrvlietypes_thresholds *tlv;
|
||||
struct lbs_private *priv = file->private_data;
|
||||
ssize_t buf_size;
|
||||
int value, freq, new_mask;
|
||||
uint16_t curr_mask;
|
||||
char *buf;
|
||||
int ret;
|
||||
|
||||
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_unlock;
|
||||
ret = -EFAULT;
|
||||
goto out_page;
|
||||
}
|
||||
res = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
|
||||
if (res != 3) {
|
||||
res = -EFAULT;
|
||||
goto out_unlock;
|
||||
ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
|
||||
if (ret != 3) {
|
||||
ret = -EINVAL;
|
||||
goto out_page;
|
||||
}
|
||||
curr_mask = lbs_get_events_bitmap(priv);
|
||||
events = kzalloc(sizeof(*events), GFP_KERNEL);
|
||||
if (!events) {
|
||||
ret = -ENOMEM;
|
||||
goto out_page;
|
||||
}
|
||||
|
||||
events->hdr.size = cpu_to_le16(sizeof(*events));
|
||||
events->action = cpu_to_le16(CMD_ACT_GET);
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
|
||||
if (ret)
|
||||
goto out_events;
|
||||
|
||||
curr_mask = le16_to_cpu(events->events);
|
||||
|
||||
if (new_mask)
|
||||
new_mask = curr_mask | event_mask;
|
||||
@ -474,147 +467,128 @@ static ssize_t lbs_threshold_write(
|
||||
new_mask = curr_mask & ~event_mask;
|
||||
|
||||
/* Now everything is set and we can send stuff down to the firmware */
|
||||
events = kzalloc(
|
||||
sizeof(struct cmd_ds_802_11_subscribe_event),
|
||||
GFP_KERNEL);
|
||||
if (events) {
|
||||
struct mrvlietypes_thresholds *tlv =
|
||||
(struct mrvlietypes_thresholds *) events->tlv;
|
||||
events->action = cpu_to_le16(CMD_ACT_SET);
|
||||
events->events = cpu_to_le16(new_mask);
|
||||
tlv->header.type = cpu_to_le16(tlv_type);
|
||||
tlv->header.len = cpu_to_le16(
|
||||
sizeof(struct mrvlietypes_thresholds) -
|
||||
sizeof(struct mrvlietypesheader));
|
||||
tlv->value = value;
|
||||
if (tlv_type != TLV_TYPE_BCNMISS)
|
||||
tlv->freq = freq;
|
||||
lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_SUBSCRIBE_EVENT, CMD_ACT_SET,
|
||||
CMD_OPTION_WAITFORRSP, 0, events);
|
||||
kfree(events);
|
||||
}
|
||||
|
||||
res = count;
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
tlv = (void *)events->tlv;
|
||||
|
||||
events->action = cpu_to_le16(CMD_ACT_SET);
|
||||
events->events = cpu_to_le16(new_mask);
|
||||
tlv->header.type = cpu_to_le16(tlv_type);
|
||||
tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header));
|
||||
tlv->value = value;
|
||||
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));
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
|
||||
|
||||
if (!ret)
|
||||
ret = count;
|
||||
out_events:
|
||||
kfree(events);
|
||||
out_page:
|
||||
free_page((unsigned long)buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_lowrssi_read(
|
||||
struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_lowrssi_write(
|
||||
struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_lowrssi_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_lowsnr_read(
|
||||
struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_lowsnr_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_lowsnr_write(
|
||||
struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_lowsnr_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_failcount_read(
|
||||
struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_failcount_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_failcount_write(
|
||||
struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_failcount_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_highrssi_read(
|
||||
struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_highrssi_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_highrssi_write(
|
||||
struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_highrssi_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_highsnr_read(
|
||||
struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_highsnr_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_highsnr_write(
|
||||
struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_highsnr_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
static ssize_t lbs_bcnmiss_read(
|
||||
struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_bcnmiss_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t lbs_bcnmiss_write(
|
||||
struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return lbs_threshold_write(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
|
||||
file, userbuf, count, ppos);
|
||||
file, userbuf, count, ppos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
@ -28,10 +28,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
|
||||
u16 cmd_action,
|
||||
u16 wait_option, u32 cmd_oid, void *pdata_buf);
|
||||
|
||||
void lbs_queue_cmd(struct lbs_private *priv,
|
||||
struct cmd_ctrl_node *cmdnode,
|
||||
u8 addtail);
|
||||
|
||||
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);
|
||||
@ -45,9 +41,8 @@ void lbs_get_fwversion(struct lbs_private *priv,
|
||||
|
||||
/** The proc fs interface */
|
||||
int lbs_process_rx_command(struct lbs_private *priv);
|
||||
void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
|
||||
struct cmd_ctrl_node *ptempcmd);
|
||||
|
||||
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);
|
||||
int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
|
||||
|
||||
@ -77,4 +72,5 @@ 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);
|
||||
#endif
|
||||
|
@ -141,6 +141,13 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
|
||||
#define LBS_UPLD_SIZE 2312
|
||||
#define DEV_NAME_LEN 32
|
||||
|
||||
/* Wake criteria for HOST_SLEEP_CFG command */
|
||||
#define EHS_WAKE_ON_BROADCAST_DATA 0x0001
|
||||
#define EHS_WAKE_ON_UNICAST_DATA 0x0002
|
||||
#define EHS_WAKE_ON_MAC_EVENT 0x0004
|
||||
#define EHS_WAKE_ON_MULTICAST_DATA 0x0008
|
||||
#define EHS_REMOVE_WAKEUP 0xFFFFFFFF
|
||||
|
||||
/** Misc constants */
|
||||
/* This section defines 802.11 specific contants */
|
||||
|
||||
|
@ -77,12 +77,12 @@ struct current_bss_params {
|
||||
|
||||
/** sleep_params */
|
||||
struct sleep_params {
|
||||
u16 sp_error;
|
||||
u16 sp_offset;
|
||||
u16 sp_stabletime;
|
||||
u8 sp_calcontrol;
|
||||
u8 sp_extsleepclk;
|
||||
u16 sp_reserved;
|
||||
uint16_t sp_error;
|
||||
uint16_t sp_offset;
|
||||
uint16_t sp_stabletime;
|
||||
uint8_t sp_calcontrol;
|
||||
uint8_t sp_extsleepclk;
|
||||
uint16_t sp_reserved;
|
||||
};
|
||||
|
||||
/* Mesh statistics */
|
||||
@ -153,6 +153,11 @@ struct lbs_private {
|
||||
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*/
|
||||
@ -196,11 +201,15 @@ struct lbs_private {
|
||||
|
||||
/** Timers */
|
||||
struct timer_list command_timer;
|
||||
int nr_retries;
|
||||
int cmd_timed_out;
|
||||
|
||||
u8 hisregcpy;
|
||||
|
||||
/** current ssid/bssid related parameters*/
|
||||
struct current_bss_params curbssparams;
|
||||
|
||||
uint16_t mesh_tlv;
|
||||
u8 mesh_ssid[IW_ESSID_MAX_SIZE + 1];
|
||||
u8 mesh_ssid_len;
|
||||
|
||||
@ -251,9 +260,11 @@ struct lbs_private {
|
||||
u16 psmode; /* Wlan802_11PowermodeCAM=disable
|
||||
Wlan802_11PowermodeMAX_PSP=enable */
|
||||
u32 psstate;
|
||||
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;
|
||||
@ -289,9 +300,6 @@ struct lbs_private {
|
||||
u8 cur_rate;
|
||||
u8 auto_rate;
|
||||
|
||||
/** sleep_params */
|
||||
struct sleep_params sp;
|
||||
|
||||
/** RF calibration data */
|
||||
|
||||
#define MAX_REGION_CHANNEL_NUM 2
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "dev.h"
|
||||
#include "join.h"
|
||||
#include "wext.h"
|
||||
#include "cmd.h"
|
||||
|
||||
static const char * mesh_stat_strings[]= {
|
||||
"drop_duplicate_bcast",
|
||||
"drop_ttl_zero",
|
||||
@ -142,6 +144,16 @@ 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)
|
||||
{
|
||||
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)
|
||||
@ -162,11 +174,57 @@ static void lbs_ethtool_get_strings(struct net_device *dev,
|
||||
lbs_deb_enter(LBS_DEB_ETHTOOL);
|
||||
}
|
||||
|
||||
static void lbs_ethtool_get_wol(struct net_device *dev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct lbs_private *priv = dev->priv;
|
||||
|
||||
if (priv->wol_criteria == 0xffffffff) {
|
||||
/* Interface driver didn't configure wake */
|
||||
wol->supported = wol->wolopts = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
|
||||
|
||||
if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA)
|
||||
wol->wolopts |= WAKE_UCAST;
|
||||
if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA)
|
||||
wol->wolopts |= WAKE_MCAST;
|
||||
if (priv->wol_criteria & EHS_WAKE_ON_BROADCAST_DATA)
|
||||
wol->wolopts |= WAKE_BCAST;
|
||||
if (priv->wol_criteria & EHS_WAKE_ON_MAC_EVENT)
|
||||
wol->wolopts |= WAKE_PHY;
|
||||
}
|
||||
|
||||
static int lbs_ethtool_set_wol(struct net_device *dev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct lbs_private *priv = dev->priv;
|
||||
uint32_t criteria = 0;
|
||||
|
||||
if (priv->wol_criteria == 0xffffffff && wol->wolopts)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (wol->wolopts & WAKE_UCAST) criteria |= EHS_WAKE_ON_UNICAST_DATA;
|
||||
if (wol->wolopts & WAKE_MCAST) criteria |= EHS_WAKE_ON_MULTICAST_DATA;
|
||||
if (wol->wolopts & WAKE_BCAST) criteria |= EHS_WAKE_ON_BROADCAST_DATA;
|
||||
if (wol->wolopts & WAKE_PHY) criteria |= EHS_WAKE_ON_MAC_EVENT;
|
||||
|
||||
return lbs_host_sleep_cfg(priv, criteria);
|
||||
}
|
||||
|
||||
struct ethtool_ops lbs_ethtool_ops = {
|
||||
.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,
|
||||
.set_wol = lbs_ethtool_set_wol,
|
||||
};
|
||||
|
||||
|
@ -73,6 +73,9 @@
|
||||
#define CMD_802_11_SET_AFC 0x003c
|
||||
#define CMD_802_11_GET_AFC 0x003d
|
||||
#define CMD_802_11_AD_HOC_STOP 0x0040
|
||||
#define CMD_802_11_HOST_SLEEP_CFG 0x0043
|
||||
#define CMD_802_11_WAKEUP_CONFIRM 0x0044
|
||||
#define CMD_802_11_HOST_SLEEP_ACTIVATE 0x0045
|
||||
#define CMD_802_11_BEACON_STOP 0x0049
|
||||
#define CMD_802_11_MAC_ADDRESS 0x004d
|
||||
#define CMD_802_11_LED_GPIO_CTRL 0x004e
|
||||
@ -82,8 +85,10 @@
|
||||
#define CMD_802_11_KEY_MATERIAL 0x005e
|
||||
#define CMD_802_11_SLEEP_PARAMS 0x0066
|
||||
#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
|
||||
#define CMD_802_11_TX_RATE_QUERY 0x007f
|
||||
@ -204,6 +209,11 @@
|
||||
#define CMD_TYPE_MAX_PSP 0x0001
|
||||
#define CMD_TYPE_FAST_PSP 0x0002
|
||||
|
||||
/* Options for CMD_802_11_FW_WAKE_METHOD */
|
||||
#define CMD_WAKE_METHOD_UNCHANGED 0x0000
|
||||
#define CMD_WAKE_METHOD_COMMAND_INT 0x0001
|
||||
#define CMD_WAKE_METHOD_GPIO 0x0002
|
||||
|
||||
/* Define action or option for CMD_BT_ACCESS */
|
||||
enum cmd_bt_access_opts {
|
||||
/* The bt commands start at 5 instead of 1 because the old dft commands
|
||||
|
@ -74,10 +74,8 @@ struct cmd_header {
|
||||
|
||||
struct cmd_ctrl_node {
|
||||
struct list_head list;
|
||||
/* wait for finish or not */
|
||||
u16 wait_option;
|
||||
int result;
|
||||
/* command response */
|
||||
void *pdata_buf;
|
||||
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *);
|
||||
unsigned long callback_arg;
|
||||
/* command data */
|
||||
@ -158,6 +156,8 @@ struct cmd_ds_802_11_reset {
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_subscribe_event {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 events;
|
||||
|
||||
@ -166,7 +166,7 @@ struct cmd_ds_802_11_subscribe_event {
|
||||
* 40 bytes. However, future firmware might add additional TLVs, so I
|
||||
* bump this up a bit.
|
||||
*/
|
||||
u8 tlv[128];
|
||||
uint8_t tlv[128];
|
||||
};
|
||||
|
||||
/*
|
||||
@ -258,6 +258,8 @@ struct cmd_ds_802_11_ad_hoc_result {
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_set_wep {
|
||||
struct cmd_header hdr;
|
||||
|
||||
/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
|
||||
__le16 action;
|
||||
|
||||
@ -265,8 +267,8 @@ struct cmd_ds_802_11_set_wep {
|
||||
__le16 keyindex;
|
||||
|
||||
/* 40, 128bit or TXWEP */
|
||||
u8 keytype[4];
|
||||
u8 keymaterial[4][16];
|
||||
uint8_t keytype[4];
|
||||
uint8_t keymaterial[4][16];
|
||||
};
|
||||
|
||||
struct cmd_ds_802_3_get_stat {
|
||||
@ -344,6 +346,8 @@ struct cmd_ds_rf_reg_access {
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_radio_control {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 control;
|
||||
};
|
||||
@ -355,6 +359,8 @@ struct cmd_ds_802_11_beacon_control {
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_sleep_params {
|
||||
struct cmd_header hdr;
|
||||
|
||||
/* ACT_GET/ACT_SET */
|
||||
__le16 action;
|
||||
|
||||
@ -368,16 +374,18 @@ struct cmd_ds_802_11_sleep_params {
|
||||
__le16 stabletime;
|
||||
|
||||
/* control periodic calibration */
|
||||
u8 calcontrol;
|
||||
uint8_t calcontrol;
|
||||
|
||||
/* control the use of external sleep clock */
|
||||
u8 externalsleepclk;
|
||||
uint8_t externalsleepclk;
|
||||
|
||||
/* reserved field, should be set to zero */
|
||||
__le16 reserved;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_inactivity_timeout {
|
||||
struct cmd_header hdr;
|
||||
|
||||
/* ACT_GET/ACT_SET */
|
||||
__le16 action;
|
||||
|
||||
@ -441,6 +449,20 @@ struct cmd_ds_set_boot2_ver {
|
||||
__le16 version;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_fw_wake_method {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 method;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_sleep_period {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 period;
|
||||
};
|
||||
|
||||
struct cmd_ds_802_11_ps_mode {
|
||||
__le16 action;
|
||||
__le16 nullpktinterval;
|
||||
@ -516,6 +538,8 @@ struct cmd_ds_802_11_ad_hoc_join {
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_enable_rsn {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 enable;
|
||||
} __attribute__ ((packed));
|
||||
@ -540,6 +564,13 @@ struct MrvlIEtype_keyParamSet {
|
||||
u8 key[32];
|
||||
};
|
||||
|
||||
struct cmd_ds_host_sleep {
|
||||
struct cmd_header hdr;
|
||||
__le32 criteria;
|
||||
uint8_t gpio;
|
||||
uint8_t gap;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_key_material {
|
||||
__le16 action;
|
||||
struct MrvlIEtype_keyParamSet keyParamSet[2];
|
||||
@ -663,7 +694,6 @@ struct cmd_ds_command {
|
||||
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_set_wep wep;
|
||||
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;
|
||||
@ -678,13 +708,10 @@ struct cmd_ds_command {
|
||||
struct cmd_ds_802_11_rate_adapt_rateset rateset;
|
||||
struct cmd_ds_mac_multicast_adr madr;
|
||||
struct cmd_ds_802_11_ad_hoc_join adj;
|
||||
struct cmd_ds_802_11_radio_control radio;
|
||||
struct cmd_ds_802_11_rf_channel rfchannel;
|
||||
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_enable_rsn enbrsn;
|
||||
struct cmd_ds_802_11_key_material keymaterial;
|
||||
struct cmd_ds_mac_reg_access macreg;
|
||||
struct cmd_ds_bbp_reg_access bbpreg;
|
||||
@ -694,8 +721,6 @@ struct cmd_ds_command {
|
||||
struct cmd_ds_802_11d_domain_info domaininfo;
|
||||
struct cmd_ds_802_11d_domain_info domaininforesp;
|
||||
|
||||
struct cmd_ds_802_11_sleep_params sleep_params;
|
||||
struct cmd_ds_802_11_inactivity_timeout inactivity_timeout;
|
||||
struct cmd_ds_802_11_tpc_cfg tpccfg;
|
||||
struct cmd_ds_802_11_pwr_cfg pwrcfg;
|
||||
struct cmd_ds_802_11_afc afc;
|
||||
@ -705,7 +730,6 @@ struct cmd_ds_command {
|
||||
struct cmd_ds_bt_access bt;
|
||||
struct cmd_ds_fwt_access fwt;
|
||||
struct cmd_ds_get_tsf gettsf;
|
||||
struct cmd_ds_802_11_subscribe_event subscribe_event;
|
||||
struct cmd_ds_802_11_beacon_control bcn_ctrl;
|
||||
} params;
|
||||
} __attribute__ ((packed));
|
||||
|
@ -243,7 +243,7 @@ static inline void if_cs_disable_ints(struct if_cs_card *card)
|
||||
|
||||
static irqreturn_t if_cs_interrupt(int irq, void *data)
|
||||
{
|
||||
struct if_cs_card *card = data;
|
||||
struct if_cs_card *card = (struct if_cs_card *)data;
|
||||
u16 int_cause;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CS);
|
||||
@ -647,7 +647,6 @@ 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;
|
||||
u8 *cmdbuf;
|
||||
*ireg = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CS);
|
||||
@ -679,14 +678,7 @@ sbi_get_int_status_exit:
|
||||
/* Card has a command result for us */
|
||||
if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) {
|
||||
spin_lock(&priv->driver_lock);
|
||||
if (!priv->cur_cmd) {
|
||||
cmdbuf = priv->upld_buf;
|
||||
priv->hisregcpy &= ~IF_CS_C_S_RX_UPLD_RDY;
|
||||
} else {
|
||||
cmdbuf = (u8 *) priv->cur_cmd->cmdbuf;
|
||||
}
|
||||
|
||||
ret = if_cs_receive_cmdres(priv, cmdbuf, &priv->upld_len);
|
||||
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");
|
||||
|
@ -19,7 +19,7 @@
|
||||
* current block size.
|
||||
*
|
||||
* As SDIO is still new to the kernel, it is unfortunately common with
|
||||
* bugs in the host controllers related to that. One such bug is that
|
||||
* bugs in the host controllers related to that. One such bug is that
|
||||
* controllers cannot do transfers that aren't a multiple of 4 bytes.
|
||||
* If you don't have time to fix the host controller driver, you can
|
||||
* work around the problem by modifying if_sdio_host_to_card() and
|
||||
@ -136,12 +136,6 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
|
||||
|
||||
spin_lock_irqsave(&card->priv->driver_lock, flags);
|
||||
|
||||
if (!card->priv->cur_cmd) {
|
||||
lbs_deb_sdio("discarding spurious response\n");
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (size > LBS_CMD_BUFFER_SIZE) {
|
||||
lbs_deb_sdio("response packet too large (%d bytes)\n",
|
||||
(int)size);
|
||||
@ -149,7 +143,7 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(card->priv->cur_cmd->cmdbuf, buffer, size);
|
||||
memcpy(card->priv->upld_buf, buffer, size);
|
||||
card->priv->upld_len = size;
|
||||
|
||||
card->int_cause |= MRVDRV_CMD_UPLD_RDY;
|
||||
|
@ -16,6 +16,9 @@
|
||||
#include "cmd.h"
|
||||
#include "if_usb.h"
|
||||
|
||||
#define INSANEDEBUG 0
|
||||
#define lbs_deb_usb2(...) do { if (INSANEDEBUG) lbs_deb_usbd(__VA_ARGS__); } while (0)
|
||||
|
||||
#define MESSAGE_HEADER_LEN 4
|
||||
|
||||
static char *lbs_fw_name = "usb8388.bin";
|
||||
@ -32,17 +35,16 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
|
||||
|
||||
static void if_usb_receive(struct urb *urb);
|
||||
static void if_usb_receive_fwload(struct urb *urb);
|
||||
static int if_usb_prog_firmware(struct usb_card_rec *cardp);
|
||||
static int if_usb_host_to_card(struct lbs_private *priv,
|
||||
u8 type,
|
||||
u8 *payload,
|
||||
u16 nb);
|
||||
static int if_usb_get_int_status(struct lbs_private *priv, u8 *);
|
||||
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 usb_card_rec *cardp, u8 *payload, u16 nb);
|
||||
static void if_usb_free(struct usb_card_rec *cardp);
|
||||
static int if_usb_submit_rx_urb(struct usb_card_rec *cardp);
|
||||
static int if_usb_reset_device(struct usb_card_rec *cardp);
|
||||
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);
|
||||
static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
|
||||
static int if_usb_reset_device(struct if_usb_card *cardp);
|
||||
|
||||
/**
|
||||
* @brief call back function to handle the status of the URB
|
||||
@ -51,18 +53,16 @@ static int if_usb_reset_device(struct usb_card_rec *cardp);
|
||||
*/
|
||||
static void if_usb_write_bulk_callback(struct urb *urb)
|
||||
{
|
||||
struct usb_card_rec *cardp = (struct usb_card_rec *) urb->context;
|
||||
struct if_usb_card *cardp = (struct if_usb_card *) urb->context;
|
||||
|
||||
/* handle the transmission complete validations */
|
||||
|
||||
if (urb->status == 0) {
|
||||
struct lbs_private *priv = cardp->priv;
|
||||
|
||||
/*
|
||||
lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n");
|
||||
lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n",
|
||||
urb->actual_length);
|
||||
*/
|
||||
lbs_deb_usb2(&urb->dev->dev, "URB status is successful\n");
|
||||
lbs_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n",
|
||||
urb->actual_length);
|
||||
|
||||
/* Used for both firmware TX and regular TX. priv isn't
|
||||
* valid at firmware load time.
|
||||
@ -79,10 +79,10 @@ static void if_usb_write_bulk_callback(struct urb *urb)
|
||||
|
||||
/**
|
||||
* @brief free tx/rx urb, skb and rx buffer
|
||||
* @param cardp pointer usb_card_rec
|
||||
* @param cardp pointer if_usb_card
|
||||
* @return N/A
|
||||
*/
|
||||
static void if_usb_free(struct usb_card_rec *cardp)
|
||||
static void if_usb_free(struct if_usb_card *cardp)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_USB);
|
||||
|
||||
@ -96,26 +96,47 @@ static void if_usb_free(struct usb_card_rec *cardp)
|
||||
usb_free_urb(cardp->rx_urb);
|
||||
cardp->rx_urb = NULL;
|
||||
|
||||
kfree(cardp->bulk_out_buffer);
|
||||
cardp->bulk_out_buffer = NULL;
|
||||
kfree(cardp->ep_out_buf);
|
||||
cardp->ep_out_buf = NULL;
|
||||
|
||||
lbs_deb_leave(LBS_DEB_USB);
|
||||
}
|
||||
|
||||
static void if_usb_set_boot2_ver(struct lbs_private *priv)
|
||||
static void if_usb_setup_firmware(struct lbs_private *priv)
|
||||
{
|
||||
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;
|
||||
|
||||
if (lbs_cmd(priv, CMD_SET_BOOT2_VER, b2_cmd, NULL, 0))
|
||||
if (lbs_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
|
||||
lbs_deb_usb("Setting boot2 version failed\n");
|
||||
|
||||
priv->wol_gpio = 2; /* Wake via GPIO2... */
|
||||
priv->wol_gap = 20; /* ... after 20ms */
|
||||
lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA);
|
||||
|
||||
wake_method.hdr.size = cpu_to_le16(sizeof(wake_method));
|
||||
wake_method.action = cpu_to_le16(CMD_ACT_GET);
|
||||
if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) {
|
||||
lbs_pr_info("Firmware does not seem to support PS mode\n");
|
||||
} else {
|
||||
if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) {
|
||||
lbs_deb_usb("Firmware seems to support PS with wake-via-command\n");
|
||||
priv->ps_supported = 1;
|
||||
} else {
|
||||
/* The versions which boot up this way don't seem to
|
||||
work even if we set it to the command interrupt */
|
||||
lbs_pr_info("Firmware doesn't wake via command interrupt; disabling PS mode\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void if_usb_fw_timeo(unsigned long priv)
|
||||
{
|
||||
struct usb_card_rec *cardp = (void *)priv;
|
||||
struct if_usb_card *cardp = (void *)priv;
|
||||
|
||||
if (cardp->fwdnldover) {
|
||||
lbs_deb_usb("Download complete, no event. Assuming success\n");
|
||||
@ -125,6 +146,7 @@ static void if_usb_fw_timeo(unsigned long priv)
|
||||
}
|
||||
wake_up(&cardp->fw_wq);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets the configuration values
|
||||
* @param ifnum interface number
|
||||
@ -138,12 +160,12 @@ static int if_usb_probe(struct usb_interface *intf,
|
||||
struct usb_host_interface *iface_desc;
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
struct lbs_private *priv;
|
||||
struct usb_card_rec *cardp;
|
||||
struct if_usb_card *cardp;
|
||||
int i;
|
||||
|
||||
udev = interface_to_usbdev(intf);
|
||||
|
||||
cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
|
||||
cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL);
|
||||
if (!cardp) {
|
||||
lbs_pr_err("Out of memory allocating private data.\n");
|
||||
goto error;
|
||||
@ -151,12 +173,12 @@ static int if_usb_probe(struct usb_interface *intf,
|
||||
|
||||
setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);
|
||||
init_waitqueue_head(&cardp->fw_wq);
|
||||
|
||||
|
||||
cardp->udev = udev;
|
||||
iface_desc = intf->cur_altsetting;
|
||||
|
||||
lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
|
||||
" bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
|
||||
" bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
|
||||
le16_to_cpu(udev->descriptor.bcdUSB),
|
||||
udev->descriptor.bDeviceClass,
|
||||
udev->descriptor.bDeviceSubClass,
|
||||
@ -164,63 +186,42 @@ static int if_usb_probe(struct usb_interface *intf,
|
||||
|
||||
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
|
||||
endpoint = &iface_desc->endpoint[i].desc;
|
||||
if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
|
||||
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_BULK)) {
|
||||
/* we found a bulk in endpoint */
|
||||
lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n",
|
||||
le16_to_cpu(endpoint->wMaxPacketSize));
|
||||
if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
|
||||
lbs_deb_usbd(&udev->dev,
|
||||
"Rx URB allocation failed\n");
|
||||
goto dealloc;
|
||||
}
|
||||
cardp->bulk_in_size =
|
||||
le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
cardp->bulk_in_endpointAddr =
|
||||
(endpoint->
|
||||
bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
|
||||
lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n",
|
||||
endpoint->bEndpointAddress);
|
||||
}
|
||||
|
||||
if (((endpoint->
|
||||
bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
|
||||
USB_DIR_OUT)
|
||||
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_BULK)) {
|
||||
/* We found bulk out endpoint */
|
||||
if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
|
||||
lbs_deb_usbd(&udev->dev,
|
||||
"Tx URB allocation failed\n");
|
||||
goto dealloc;
|
||||
}
|
||||
|
||||
cardp->bulk_out_size =
|
||||
le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
lbs_deb_usbd(&udev->dev,
|
||||
"Bulk out size is %d\n",
|
||||
le16_to_cpu(endpoint->wMaxPacketSize));
|
||||
cardp->bulk_out_endpointAddr =
|
||||
endpoint->bEndpointAddress;
|
||||
lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n",
|
||||
endpoint->bEndpointAddress);
|
||||
cardp->bulk_out_buffer =
|
||||
kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!cardp->bulk_out_buffer) {
|
||||
lbs_deb_usbd(&udev->dev,
|
||||
"Could not allocate buffer\n");
|
||||
goto dealloc;
|
||||
}
|
||||
if (usb_endpoint_is_bulk_in(endpoint)) {
|
||||
cardp->ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
cardp->ep_in = usb_endpoint_num(endpoint);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (!cardp->ep_out_size || !cardp->ep_in_size) {
|
||||
lbs_deb_usbd(&udev->dev, "Endpoints not found\n");
|
||||
goto dealloc;
|
||||
}
|
||||
if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
|
||||
lbs_deb_usbd(&udev->dev, "Rx URB allocation failed\n");
|
||||
goto dealloc;
|
||||
}
|
||||
if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
|
||||
lbs_deb_usbd(&udev->dev, "Tx URB allocation failed\n");
|
||||
goto dealloc;
|
||||
}
|
||||
cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, GFP_KERNEL);
|
||||
if (!cardp->ep_out_buf) {
|
||||
lbs_deb_usbd(&udev->dev, "Could not allocate buffer\n");
|
||||
goto dealloc;
|
||||
}
|
||||
|
||||
/* Upload firmware */
|
||||
cardp->rinfo.cardp = cardp;
|
||||
if (if_usb_prog_firmware(cardp)) {
|
||||
lbs_deb_usbd(&udev->dev, "FW upload failed");
|
||||
lbs_deb_usbd(&udev->dev, "FW upload failed\n");
|
||||
goto err_prog_firmware;
|
||||
}
|
||||
|
||||
@ -240,7 +241,7 @@ static int if_usb_probe(struct usb_interface *intf,
|
||||
if (lbs_start_card(priv))
|
||||
goto err_start_card;
|
||||
|
||||
if_usb_set_boot2_ver(priv);
|
||||
if_usb_setup_firmware(priv);
|
||||
|
||||
usb_get_dev(udev);
|
||||
usb_set_intfdata(intf, cardp);
|
||||
@ -265,25 +266,19 @@ error:
|
||||
*/
|
||||
static void if_usb_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_card_rec *cardp = usb_get_intfdata(intf);
|
||||
struct if_usb_card *cardp = usb_get_intfdata(intf);
|
||||
struct lbs_private *priv = (struct lbs_private *) cardp->priv;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
|
||||
/* Update Surprise removed to TRUE */
|
||||
cardp->surprise_removed = 1;
|
||||
|
||||
if (priv) {
|
||||
|
||||
priv->surpriseremoved = 1;
|
||||
lbs_stop_card(priv);
|
||||
lbs_remove_card(priv);
|
||||
}
|
||||
|
||||
/* this is (apparently?) necessary for future usage of the device */
|
||||
lbs_prepare_and_send_command(priv, CMD_802_11_RESET, CMD_ACT_HALT,
|
||||
0, 0, NULL);
|
||||
|
||||
/* Unlink and free urb */
|
||||
if_usb_free(cardp);
|
||||
|
||||
@ -298,98 +293,75 @@ static void if_usb_disconnect(struct usb_interface *intf)
|
||||
* @param priv pointer to struct lbs_private
|
||||
* @return 0
|
||||
*/
|
||||
static int if_usb_send_fw_pkt(struct usb_card_rec *cardp)
|
||||
static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
|
||||
{
|
||||
struct FWData *fwdata;
|
||||
struct fwheader *fwheader;
|
||||
u8 *firmware = cardp->fw->data;
|
||||
|
||||
fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC);
|
||||
|
||||
if (!fwdata)
|
||||
return -1;
|
||||
|
||||
fwheader = &fwdata->fwheader;
|
||||
struct fwdata *fwdata = cardp->ep_out_buf;
|
||||
uint8_t *firmware = cardp->fw->data;
|
||||
|
||||
/* If we got a CRC failure on the last block, back
|
||||
up and retry it */
|
||||
if (!cardp->CRC_OK) {
|
||||
cardp->totalbytes = cardp->fwlastblksent;
|
||||
cardp->fwseqnum = cardp->lastseqnum - 1;
|
||||
cardp->fwseqnum--;
|
||||
}
|
||||
|
||||
/*
|
||||
lbs_deb_usbd(&cardp->udev->dev, "totalbytes = %d\n",
|
||||
cardp->totalbytes);
|
||||
*/
|
||||
lbs_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n",
|
||||
cardp->totalbytes);
|
||||
|
||||
memcpy(fwheader, &firmware[cardp->totalbytes],
|
||||
/* struct fwdata (which we sent to the card) has an
|
||||
extra __le32 field in between the header and the data,
|
||||
which is not in the struct fwheader in the actual
|
||||
firmware binary. Insert the seqnum in the middle... */
|
||||
memcpy(&fwdata->hdr, &firmware[cardp->totalbytes],
|
||||
sizeof(struct fwheader));
|
||||
|
||||
cardp->fwlastblksent = cardp->totalbytes;
|
||||
cardp->totalbytes += sizeof(struct fwheader);
|
||||
|
||||
/* lbs_deb_usbd(&cardp->udev->dev,"Copy Data\n"); */
|
||||
memcpy(fwdata->data, &firmware[cardp->totalbytes],
|
||||
le32_to_cpu(fwdata->fwheader.datalength));
|
||||
le32_to_cpu(fwdata->hdr.datalength));
|
||||
|
||||
/*
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"Data length = %d\n", le32_to_cpu(fwdata->fwheader.datalength));
|
||||
*/
|
||||
lbs_deb_usb2(&cardp->udev->dev, "Data length = %d\n",
|
||||
le32_to_cpu(fwdata->hdr.datalength));
|
||||
|
||||
cardp->fwseqnum = cardp->fwseqnum + 1;
|
||||
fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);
|
||||
cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);
|
||||
|
||||
fwdata->seqnum = cpu_to_le32(cardp->fwseqnum);
|
||||
cardp->lastseqnum = cardp->fwseqnum;
|
||||
cardp->totalbytes += le32_to_cpu(fwdata->fwheader.datalength);
|
||||
usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +
|
||||
le32_to_cpu(fwdata->hdr.datalength));
|
||||
|
||||
if (fwheader->dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
|
||||
/*
|
||||
lbs_deb_usbd(&cardp->udev->dev, "There are data to follow\n");
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"seqnum = %d totalbytes = %d\n", cardp->fwseqnum,
|
||||
cardp->totalbytes);
|
||||
*/
|
||||
memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
|
||||
usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
|
||||
if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
|
||||
lbs_deb_usb2(&cardp->udev->dev, "There are data to follow\n");
|
||||
lbs_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n",
|
||||
cardp->fwseqnum, cardp->totalbytes);
|
||||
} else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
|
||||
lbs_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n");
|
||||
lbs_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n");
|
||||
|
||||
} else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
|
||||
/*
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"Host has finished FW downloading\n");
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"Donwloading FW JUMP BLOCK\n");
|
||||
*/
|
||||
memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
|
||||
usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
|
||||
cardp->fwfinalblk = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"The firmware download is done size is %d\n",
|
||||
cardp->totalbytes);
|
||||
*/
|
||||
|
||||
kfree(fwdata);
|
||||
lbs_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n",
|
||||
cardp->totalbytes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int if_usb_reset_device(struct usb_card_rec *cardp)
|
||||
static int if_usb_reset_device(struct if_usb_card *cardp)
|
||||
{
|
||||
struct cmd_ds_command *cmd = (void *)&cardp->bulk_out_buffer[4];
|
||||
struct cmd_ds_command *cmd = cardp->ep_out_buf + 4;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_USB);
|
||||
|
||||
*(__le32 *)cardp->bulk_out_buffer = cpu_to_le32(CMD_TYPE_REQUEST);
|
||||
*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
|
||||
|
||||
cmd->command = cpu_to_le16(CMD_802_11_RESET);
|
||||
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
|
||||
cmd->result = cpu_to_le16(0);
|
||||
cmd->seqnum = cpu_to_le16(0x5a5a);
|
||||
cmd->params.reset.action = cpu_to_le16(CMD_ACT_HALT);
|
||||
usb_tx_block(cardp, cardp->bulk_out_buffer, 4 + S_DS_GEN + sizeof(struct cmd_ds_802_11_reset));
|
||||
usb_tx_block(cardp, cardp->ep_out_buf, 4 + S_DS_GEN + sizeof(struct cmd_ds_802_11_reset));
|
||||
|
||||
msleep(100);
|
||||
ret = usb_reset_device(cardp->udev);
|
||||
@ -407,7 +379,7 @@ static int if_usb_reset_device(struct usb_card_rec *cardp)
|
||||
* @param nb data length
|
||||
* @return 0 or -1
|
||||
*/
|
||||
static int usb_tx_block(struct usb_card_rec *cardp, u8 * payload, u16 nb)
|
||||
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
@ -419,17 +391,16 @@ static int usb_tx_block(struct usb_card_rec *cardp, u8 * payload, u16 nb)
|
||||
|
||||
usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
|
||||
usb_sndbulkpipe(cardp->udev,
|
||||
cardp->bulk_out_endpointAddr),
|
||||
cardp->ep_out),
|
||||
payload, nb, if_usb_write_bulk_callback, cardp);
|
||||
|
||||
cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
|
||||
|
||||
if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
|
||||
/* transfer failed */
|
||||
lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
|
||||
ret = -1;
|
||||
} else {
|
||||
/* lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb success\n"); */
|
||||
lbs_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
@ -437,11 +408,10 @@ tx_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __if_usb_submit_rx_urb(struct usb_card_rec *cardp,
|
||||
static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
|
||||
void (*callbackfn)(struct urb *urb))
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct read_cb_info *rinfo = &cardp->rinfo;
|
||||
int ret = -1;
|
||||
|
||||
if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) {
|
||||
@ -449,27 +419,25 @@ static int __if_usb_submit_rx_urb(struct usb_card_rec *cardp,
|
||||
goto rx_ret;
|
||||
}
|
||||
|
||||
rinfo->skb = skb;
|
||||
cardp->rx_skb = skb;
|
||||
|
||||
/* Fill the receive configuration URB and initialise the Rx call back */
|
||||
usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
|
||||
usb_rcvbulkpipe(cardp->udev,
|
||||
cardp->bulk_in_endpointAddr),
|
||||
usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
|
||||
(void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET),
|
||||
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,
|
||||
rinfo);
|
||||
cardp);
|
||||
|
||||
cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
|
||||
|
||||
/* lbs_deb_usbd(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); */
|
||||
lbs_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
|
||||
if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {
|
||||
/* handle failure conditions */
|
||||
lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret);
|
||||
kfree_skb(skb);
|
||||
rinfo->skb = NULL;
|
||||
cardp->rx_skb = NULL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB success\n"); */
|
||||
lbs_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n");
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
@ -477,27 +445,26 @@ rx_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int if_usb_submit_rx_urb_fwload(struct usb_card_rec *cardp)
|
||||
static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp)
|
||||
{
|
||||
return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload);
|
||||
}
|
||||
|
||||
static int if_usb_submit_rx_urb(struct usb_card_rec *cardp)
|
||||
static int if_usb_submit_rx_urb(struct if_usb_card *cardp)
|
||||
{
|
||||
return __if_usb_submit_rx_urb(cardp, &if_usb_receive);
|
||||
}
|
||||
|
||||
static void if_usb_receive_fwload(struct urb *urb)
|
||||
{
|
||||
struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
|
||||
struct sk_buff *skb = rinfo->skb;
|
||||
struct usb_card_rec *cardp = (struct usb_card_rec *)rinfo->cardp;
|
||||
struct if_usb_card *cardp = urb->context;
|
||||
struct sk_buff *skb = cardp->rx_skb;
|
||||
struct fwsyncheader *syncfwheader;
|
||||
struct bootcmdrespStr bootcmdresp;
|
||||
struct bootcmdresp bootcmdresp;
|
||||
|
||||
if (urb->status) {
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"URB status is failed during fw load\n");
|
||||
"URB status is failed during fw load\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
@ -510,8 +477,8 @@ static void if_usb_receive_fwload(struct urb *urb)
|
||||
lbs_pr_info("Firmware ready event received\n");
|
||||
wake_up(&cardp->fw_wq);
|
||||
} else {
|
||||
lbs_deb_usb("Waiting for confirmation; got %x %x\n", le32_to_cpu(tmp[0]),
|
||||
le32_to_cpu(tmp[1]));
|
||||
lbs_deb_usb("Waiting for confirmation; got %x %x\n",
|
||||
le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1]));
|
||||
if_usb_submit_rx_urb_fwload(cardp);
|
||||
}
|
||||
kfree_skb(skb);
|
||||
@ -520,37 +487,36 @@ static void if_usb_receive_fwload(struct urb *urb)
|
||||
if (cardp->bootcmdresp <= 0) {
|
||||
memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET,
|
||||
sizeof(bootcmdresp));
|
||||
|
||||
if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
|
||||
kfree_skb(skb);
|
||||
if_usb_submit_rx_urb_fwload(cardp);
|
||||
cardp->bootcmdresp = 1;
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"Received valid boot command response\n");
|
||||
"Received valid boot command response\n");
|
||||
return;
|
||||
}
|
||||
if (bootcmdresp.u32magicnumber != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
|
||||
if (bootcmdresp.u32magicnumber == cpu_to_le32(CMD_TYPE_REQUEST) ||
|
||||
bootcmdresp.u32magicnumber == cpu_to_le32(CMD_TYPE_DATA) ||
|
||||
bootcmdresp.u32magicnumber == cpu_to_le32(CMD_TYPE_INDICATION)) {
|
||||
if (bootcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
|
||||
if (bootcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) ||
|
||||
bootcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) ||
|
||||
bootcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) {
|
||||
if (!cardp->bootcmdresp)
|
||||
lbs_pr_info("Firmware already seems alive; resetting\n");
|
||||
cardp->bootcmdresp = -1;
|
||||
} else {
|
||||
lbs_pr_info("boot cmd response wrong magic number (0x%x)\n",
|
||||
le32_to_cpu(bootcmdresp.u32magicnumber));
|
||||
le32_to_cpu(bootcmdresp.magic));
|
||||
}
|
||||
} else if (bootcmdresp.u8cmd_tag != BOOT_CMD_FW_BY_USB) {
|
||||
lbs_pr_info(
|
||||
"boot cmd response cmd_tag error (%d)\n",
|
||||
bootcmdresp.u8cmd_tag);
|
||||
} else if (bootcmdresp.u8result != BOOT_CMD_RESP_OK) {
|
||||
lbs_pr_info(
|
||||
"boot cmd response result error (%d)\n",
|
||||
bootcmdresp.u8result);
|
||||
} else if (bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) {
|
||||
lbs_pr_info("boot cmd response cmd_tag error (%d)\n",
|
||||
bootcmdresp.cmd);
|
||||
} else if (bootcmdresp.result != BOOT_CMD_RESP_OK) {
|
||||
lbs_pr_info("boot cmd response result error (%d)\n",
|
||||
bootcmdresp.result);
|
||||
} else {
|
||||
cardp->bootcmdresp = 1;
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"Received valid boot command response\n");
|
||||
"Received valid boot command response\n");
|
||||
}
|
||||
kfree_skb(skb);
|
||||
if_usb_submit_rx_urb_fwload(cardp);
|
||||
@ -565,20 +531,15 @@ static void if_usb_receive_fwload(struct urb *urb)
|
||||
}
|
||||
|
||||
memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET,
|
||||
sizeof(struct fwsyncheader));
|
||||
sizeof(struct fwsyncheader));
|
||||
|
||||
if (!syncfwheader->cmd) {
|
||||
/*
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"FW received Blk with correct CRC\n");
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"FW received Blk seqnum = %d\n",
|
||||
syncfwheader->seqnum);
|
||||
*/
|
||||
lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
|
||||
lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
|
||||
le32_to_cpu(syncfwheader->seqnum));
|
||||
cardp->CRC_OK = 1;
|
||||
} else {
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"FW received Blk with CRC error\n");
|
||||
lbs_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n");
|
||||
cardp->CRC_OK = 0;
|
||||
}
|
||||
|
||||
@ -605,13 +566,12 @@ static void if_usb_receive_fwload(struct urb *urb)
|
||||
#define MRVDRV_MIN_PKT_LEN 30
|
||||
|
||||
static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
|
||||
struct usb_card_rec *cardp,
|
||||
struct if_usb_card *cardp,
|
||||
struct lbs_private *priv)
|
||||
{
|
||||
if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE +
|
||||
MESSAGE_HEADER_LEN || recvlength < MRVDRV_MIN_PKT_LEN) {
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"Packet length is Invalid\n");
|
||||
if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN
|
||||
|| recvlength < MRVDRV_MIN_PKT_LEN) {
|
||||
lbs_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
@ -619,19 +579,19 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
|
||||
skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
|
||||
skb_put(skb, recvlength);
|
||||
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, u8 *recvbuff,
|
||||
static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
|
||||
struct sk_buff *skb,
|
||||
struct usb_card_rec *cardp,
|
||||
struct if_usb_card *cardp,
|
||||
struct lbs_private *priv)
|
||||
{
|
||||
u8 *cmdbuf;
|
||||
if (recvlength > LBS_CMD_BUFFER_SIZE) {
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"The receive buffer is too large\n");
|
||||
"The receive buffer is too large\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
@ -640,18 +600,9 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
|
||||
BUG();
|
||||
|
||||
spin_lock(&priv->driver_lock);
|
||||
/* take care of cur_cmd = NULL case by reading the
|
||||
* data to clear the interrupt */
|
||||
if (!priv->cur_cmd) {
|
||||
cmdbuf = priv->upld_buf;
|
||||
priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY;
|
||||
} else
|
||||
cmdbuf = (u8 *) priv->cur_cmd->cmdbuf;
|
||||
|
||||
cardp->usb_int_cause |= MRVDRV_CMD_UPLD_RDY;
|
||||
priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
|
||||
memcpy(cmdbuf, recvbuff + MESSAGE_HEADER_LEN,
|
||||
priv->upld_len);
|
||||
memcpy(priv->upld_buf, recvbuff + MESSAGE_HEADER_LEN, priv->upld_len);
|
||||
|
||||
kfree_skb(skb);
|
||||
lbs_interrupt(priv);
|
||||
@ -659,8 +610,6 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
|
||||
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"Wake up main thread to handle cmd response\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -672,30 +621,26 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
|
||||
*/
|
||||
static void if_usb_receive(struct urb *urb)
|
||||
{
|
||||
struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
|
||||
struct sk_buff *skb = rinfo->skb;
|
||||
struct usb_card_rec *cardp = (struct usb_card_rec *) rinfo->cardp;
|
||||
struct if_usb_card *cardp = urb->context;
|
||||
struct sk_buff *skb = cardp->rx_skb;
|
||||
struct lbs_private *priv = cardp->priv;
|
||||
|
||||
int recvlength = urb->actual_length;
|
||||
u8 *recvbuff = NULL;
|
||||
u32 recvtype = 0;
|
||||
uint8_t *recvbuff = NULL;
|
||||
uint32_t recvtype = 0;
|
||||
__le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
|
||||
|
||||
lbs_deb_enter(LBS_DEB_USB);
|
||||
|
||||
if (recvlength) {
|
||||
__le32 tmp;
|
||||
|
||||
if (urb->status) {
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"URB status is failed\n");
|
||||
lbs_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n",
|
||||
urb->status);
|
||||
kfree_skb(skb);
|
||||
goto setup_for_next;
|
||||
}
|
||||
|
||||
recvbuff = skb->data + IPFIELD_ALIGN_OFFSET;
|
||||
memcpy(&tmp, recvbuff, sizeof(u32));
|
||||
recvtype = le32_to_cpu(tmp);
|
||||
recvtype = le32_to_cpu(pkt[0]);
|
||||
lbs_deb_usbd(&cardp->udev->dev,
|
||||
"Recv length = 0x%x, Recv type = 0x%X\n",
|
||||
recvlength, recvtype);
|
||||
@ -716,9 +661,13 @@ static void if_usb_receive(struct urb *urb)
|
||||
case CMD_TYPE_INDICATION:
|
||||
/* Event cause handling */
|
||||
spin_lock(&priv->driver_lock);
|
||||
cardp->usb_event_cause = le32_to_cpu(*(__le32 *) (recvbuff + MESSAGE_HEADER_LEN));
|
||||
|
||||
cardp->usb_event_cause = le32_to_cpu(pkt[1]);
|
||||
|
||||
lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n",
|
||||
cardp->usb_event_cause);
|
||||
cardp->usb_event_cause);
|
||||
|
||||
/* Icky undocumented magic special case */
|
||||
if (cardp->usb_event_cause & 0xffff0000) {
|
||||
lbs_send_tx_feedback(priv);
|
||||
spin_unlock(&priv->driver_lock);
|
||||
@ -732,7 +681,7 @@ static void if_usb_receive(struct urb *urb)
|
||||
goto rx_exit;
|
||||
default:
|
||||
lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n",
|
||||
recvtype);
|
||||
recvtype);
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
}
|
||||
@ -751,55 +700,48 @@ rx_exit:
|
||||
* @param len number of bytes
|
||||
* @return 0 or -1
|
||||
*/
|
||||
static int if_usb_host_to_card(struct lbs_private *priv,
|
||||
u8 type,
|
||||
u8 *payload,
|
||||
u16 nb)
|
||||
static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
|
||||
uint8_t *payload, uint16_t nb)
|
||||
{
|
||||
struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
|
||||
struct if_usb_card *cardp = priv->card;
|
||||
|
||||
lbs_deb_usbd(&cardp->udev->dev,"*** type = %u\n", type);
|
||||
lbs_deb_usbd(&cardp->udev->dev,"size after = %d\n", nb);
|
||||
|
||||
if (type == MVMS_CMD) {
|
||||
__le32 tmp = cpu_to_le32(CMD_TYPE_REQUEST);
|
||||
*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
|
||||
priv->dnld_sent = DNLD_CMD_SENT;
|
||||
memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
|
||||
MESSAGE_HEADER_LEN);
|
||||
|
||||
} else {
|
||||
__le32 tmp = cpu_to_le32(CMD_TYPE_DATA);
|
||||
*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_DATA);
|
||||
priv->dnld_sent = DNLD_DATA_SENT;
|
||||
memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
|
||||
MESSAGE_HEADER_LEN);
|
||||
}
|
||||
|
||||
memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb);
|
||||
memcpy((cardp->ep_out_buf + MESSAGE_HEADER_LEN), payload, nb);
|
||||
|
||||
return usb_tx_block(cardp, cardp->bulk_out_buffer,
|
||||
nb + MESSAGE_HEADER_LEN);
|
||||
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, u8 *ireg)
|
||||
static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *ireg)
|
||||
{
|
||||
struct usb_card_rec *cardp = priv->card;
|
||||
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);
|
||||
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 usb_card_rec *cardp = priv->card;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -809,20 +751,17 @@ static int if_usb_read_event_cause(struct lbs_private *priv)
|
||||
* 2:Boot from FW in EEPROM
|
||||
* @return 0
|
||||
*/
|
||||
static int if_usb_issue_boot_command(struct usb_card_rec *cardp, int ivalue)
|
||||
static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue)
|
||||
{
|
||||
struct bootcmdstr sbootcmd;
|
||||
int i;
|
||||
struct bootcmd *bootcmd = cardp->ep_out_buf;
|
||||
|
||||
/* Prepare command */
|
||||
sbootcmd.u32magicnumber = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER);
|
||||
sbootcmd.u8cmd_tag = ivalue;
|
||||
for (i=0; i<11; i++)
|
||||
sbootcmd.au8dumy[i]=0x00;
|
||||
memcpy(cardp->bulk_out_buffer, &sbootcmd, sizeof(struct bootcmdstr));
|
||||
bootcmd->magic = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER);
|
||||
bootcmd->cmd = ivalue;
|
||||
memset(bootcmd->pad, 0, sizeof(bootcmd->pad));
|
||||
|
||||
/* Issue command */
|
||||
usb_tx_block(cardp, cardp->bulk_out_buffer, sizeof(struct bootcmdstr));
|
||||
usb_tx_block(cardp, cardp->ep_out_buf, sizeof(*bootcmd));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -835,10 +774,10 @@ static int if_usb_issue_boot_command(struct usb_card_rec *cardp, int ivalue)
|
||||
* len image length
|
||||
* @return 0 or -1
|
||||
*/
|
||||
static int check_fwfile_format(u8 *data, u32 totlen)
|
||||
static int check_fwfile_format(uint8_t *data, uint32_t totlen)
|
||||
{
|
||||
u32 bincmd, exit;
|
||||
u32 blksize, offset, len;
|
||||
uint32_t bincmd, exit;
|
||||
uint32_t blksize, offset, len;
|
||||
int ret;
|
||||
|
||||
ret = 1;
|
||||
@ -876,7 +815,7 @@ static int check_fwfile_format(u8 *data, u32 totlen)
|
||||
}
|
||||
|
||||
|
||||
static int if_usb_prog_firmware(struct usb_card_rec *cardp)
|
||||
static int if_usb_prog_firmware(struct if_usb_card *cardp)
|
||||
{
|
||||
int i = 0;
|
||||
static int reset_count = 10;
|
||||
@ -937,7 +876,7 @@ restart:
|
||||
|
||||
/* ... and wait for the process to complete */
|
||||
wait_event_interruptible(cardp->fw_wq, cardp->surprise_removed || cardp->fwdnldover);
|
||||
|
||||
|
||||
del_timer_sync(&cardp->fw_timeout);
|
||||
usb_kill_urb(cardp->rx_urb);
|
||||
|
||||
@ -953,11 +892,11 @@ restart:
|
||||
goto release_fw;
|
||||
}
|
||||
|
||||
release_fw:
|
||||
release_fw:
|
||||
release_firmware(cardp->fw);
|
||||
cardp->fw = NULL;
|
||||
|
||||
done:
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
@ -966,36 +905,38 @@ done:
|
||||
#ifdef CONFIG_PM
|
||||
static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
{
|
||||
struct usb_card_rec *cardp = usb_get_intfdata(intf);
|
||||
struct if_usb_card *cardp = usb_get_intfdata(intf);
|
||||
struct lbs_private *priv = cardp->priv;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_USB);
|
||||
|
||||
if (priv->psstate != PS_STATE_FULL_POWER)
|
||||
return -1;
|
||||
|
||||
netif_device_detach(priv->dev);
|
||||
netif_device_detach(priv->mesh_dev);
|
||||
ret = lbs_suspend(priv);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Unlink tx & rx urb */
|
||||
usb_kill_urb(cardp->tx_urb);
|
||||
usb_kill_urb(cardp->rx_urb);
|
||||
|
||||
out:
|
||||
lbs_deb_leave(LBS_DEB_USB);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int if_usb_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_card_rec *cardp = usb_get_intfdata(intf);
|
||||
struct if_usb_card *cardp = usb_get_intfdata(intf);
|
||||
struct lbs_private *priv = cardp->priv;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_USB);
|
||||
|
||||
if_usb_submit_rx_urb(cardp);
|
||||
|
||||
netif_device_attach(priv->dev);
|
||||
netif_device_attach(priv->mesh_dev);
|
||||
lbs_resume(priv);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_USB);
|
||||
return 0;
|
||||
@ -1039,5 +980,5 @@ module_init(if_usb_init_module);
|
||||
module_exit(if_usb_exit_module);
|
||||
|
||||
MODULE_DESCRIPTION("8388 USB WLAN Driver");
|
||||
MODULE_AUTHOR("Marvell International Ltd.");
|
||||
MODULE_AUTHOR("Marvell International Ltd. and Red Hat, Inc.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -9,72 +9,67 @@ struct lbs_private;
|
||||
/**
|
||||
* This file contains definition for USB interface.
|
||||
*/
|
||||
#define CMD_TYPE_REQUEST 0xF00DFACE
|
||||
#define CMD_TYPE_DATA 0xBEADC0DE
|
||||
#define CMD_TYPE_INDICATION 0xBEEFFACE
|
||||
#define CMD_TYPE_REQUEST 0xF00DFACE
|
||||
#define CMD_TYPE_DATA 0xBEADC0DE
|
||||
#define CMD_TYPE_INDICATION 0xBEEFFACE
|
||||
|
||||
#define IPFIELD_ALIGN_OFFSET 2
|
||||
#define IPFIELD_ALIGN_OFFSET 2
|
||||
|
||||
#define BOOT_CMD_FW_BY_USB 0x01
|
||||
#define BOOT_CMD_FW_IN_EEPROM 0x02
|
||||
#define BOOT_CMD_UPDATE_BOOT2 0x03
|
||||
#define BOOT_CMD_UPDATE_FW 0x04
|
||||
#define BOOT_CMD_MAGIC_NUMBER 0x4C56524D /* M=>0x4D,R=>0x52,V=>0x56,L=>0x4C */
|
||||
#define BOOT_CMD_FW_BY_USB 0x01
|
||||
#define BOOT_CMD_FW_IN_EEPROM 0x02
|
||||
#define BOOT_CMD_UPDATE_BOOT2 0x03
|
||||
#define BOOT_CMD_UPDATE_FW 0x04
|
||||
#define BOOT_CMD_MAGIC_NUMBER 0x4C56524D /* LVRM */
|
||||
|
||||
struct bootcmdstr
|
||||
struct bootcmd
|
||||
{
|
||||
__le32 u32magicnumber;
|
||||
u8 u8cmd_tag;
|
||||
u8 au8dumy[11];
|
||||
__le32 magic;
|
||||
uint8_t cmd;
|
||||
uint8_t pad[11];
|
||||
};
|
||||
|
||||
#define BOOT_CMD_RESP_OK 0x0001
|
||||
#define BOOT_CMD_RESP_FAIL 0x0000
|
||||
#define BOOT_CMD_RESP_OK 0x0001
|
||||
#define BOOT_CMD_RESP_FAIL 0x0000
|
||||
|
||||
struct bootcmdrespStr
|
||||
struct bootcmdresp
|
||||
{
|
||||
__le32 u32magicnumber;
|
||||
u8 u8cmd_tag;
|
||||
u8 u8result;
|
||||
u8 au8dumy[2];
|
||||
};
|
||||
|
||||
/* read callback private data */
|
||||
struct read_cb_info {
|
||||
struct usb_card_rec *cardp;
|
||||
struct sk_buff *skb;
|
||||
__le32 magic;
|
||||
uint8_t cmd;
|
||||
uint8_t result;
|
||||
uint8_t pad[2];
|
||||
};
|
||||
|
||||
/** USB card description structure*/
|
||||
struct usb_card_rec {
|
||||
struct if_usb_card {
|
||||
struct usb_device *udev;
|
||||
struct urb *rx_urb, *tx_urb;
|
||||
struct lbs_private *priv;
|
||||
struct read_cb_info rinfo;
|
||||
|
||||
int bulk_in_size;
|
||||
u8 bulk_in_endpointAddr;
|
||||
struct sk_buff *rx_skb;
|
||||
uint32_t usb_event_cause;
|
||||
uint8_t usb_int_cause;
|
||||
|
||||
u8 *bulk_out_buffer;
|
||||
int bulk_out_size;
|
||||
u8 bulk_out_endpointAddr;
|
||||
uint8_t ep_in;
|
||||
uint8_t ep_out;
|
||||
|
||||
int8_t bootcmdresp;
|
||||
|
||||
int ep_in_size;
|
||||
|
||||
void *ep_out_buf;
|
||||
int ep_out_size;
|
||||
|
||||
const struct firmware *fw;
|
||||
struct timer_list fw_timeout;
|
||||
wait_queue_head_t fw_wq;
|
||||
u8 CRC_OK;
|
||||
u32 fwseqnum;
|
||||
u32 lastseqnum;
|
||||
u32 totalbytes;
|
||||
u32 fwlastblksent;
|
||||
u8 fwdnldover;
|
||||
u8 fwfinalblk;
|
||||
u8 surprise_removed;
|
||||
uint32_t fwseqnum;
|
||||
uint32_t totalbytes;
|
||||
uint32_t fwlastblksent;
|
||||
uint8_t CRC_OK;
|
||||
uint8_t fwdnldover;
|
||||
uint8_t fwfinalblk;
|
||||
uint8_t surprise_removed;
|
||||
|
||||
u32 usb_event_cause;
|
||||
u8 usb_int_cause;
|
||||
|
||||
s8 bootcmdresp;
|
||||
};
|
||||
|
||||
/** fwheader */
|
||||
@ -87,10 +82,10 @@ struct fwheader {
|
||||
|
||||
#define FW_MAX_DATA_BLK_SIZE 600
|
||||
/** FWData */
|
||||
struct FWData {
|
||||
struct fwheader fwheader;
|
||||
struct fwdata {
|
||||
struct fwheader hdr;
|
||||
__le32 seqnum;
|
||||
u8 data[FW_MAX_DATA_BLK_SIZE];
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
/** fwsyncheader */
|
||||
@ -102,7 +97,5 @@ struct fwsyncheader {
|
||||
#define FW_HAS_DATA_TO_RECV 0x00000001
|
||||
#define FW_HAS_LAST_BLOCK 0x00000004
|
||||
|
||||
#define FW_DATA_XMIT_SIZE \
|
||||
sizeof(struct fwheader) + le32_to_cpu(fwdata->fwheader.datalength) + sizeof(u32)
|
||||
|
||||
#endif
|
||||
|
@ -781,8 +781,8 @@ int lbs_ret_80211_associate(struct lbs_private *priv,
|
||||
priv->numSNRNF = 0;
|
||||
|
||||
netif_carrier_on(priv->dev);
|
||||
netif_wake_queue(priv->dev);
|
||||
|
||||
if (!priv->tx_pending_len)
|
||||
netif_wake_queue(priv->dev);
|
||||
|
||||
memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
|
||||
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
|
||||
@ -865,7 +865,8 @@ int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
|
||||
priv->curbssparams.ssid_len = bss->ssid_len;
|
||||
|
||||
netif_carrier_on(priv->dev);
|
||||
netif_wake_queue(priv->dev);
|
||||
if (!priv->tx_pending_len)
|
||||
netif_wake_queue(priv->dev);
|
||||
|
||||
memset(&wrqu, 0, sizeof(wrqu));
|
||||
memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/if_arp.h>
|
||||
@ -256,7 +255,7 @@ static int lbs_add_rtap(struct lbs_private *priv);
|
||||
static void lbs_remove_rtap(struct lbs_private *priv);
|
||||
static int lbs_add_mesh(struct lbs_private *priv);
|
||||
static void lbs_remove_mesh(struct lbs_private *priv);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get function for sysfs attribute rtap
|
||||
@ -345,10 +344,10 @@ static ssize_t lbs_mesh_set(struct device *dev,
|
||||
if (enable == !!priv->mesh_dev)
|
||||
return count;
|
||||
|
||||
ret = lbs_mesh_config(priv, enable);
|
||||
ret = lbs_mesh_config(priv, enable, priv->curbssparams.channel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
if (enable)
|
||||
lbs_add_mesh(priv);
|
||||
else
|
||||
@ -402,7 +401,7 @@ static int lbs_dev_open(struct net_device *dev)
|
||||
netif_carrier_on(dev);
|
||||
} else {
|
||||
priv->infra_open = 1;
|
||||
|
||||
|
||||
if (priv->connect_status == LBS_CONNECTED)
|
||||
netif_carrier_on(dev);
|
||||
else
|
||||
@ -434,7 +433,7 @@ static int lbs_mesh_stop(struct net_device *dev)
|
||||
|
||||
netif_stop_queue(dev);
|
||||
netif_carrier_off(dev);
|
||||
|
||||
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
return 0;
|
||||
}
|
||||
@ -454,7 +453,7 @@ static int lbs_eth_stop(struct net_device *dev)
|
||||
priv->infra_open = 0;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
return 0;
|
||||
}
|
||||
@ -477,6 +476,13 @@ static void lbs_tx_timeout(struct net_device *dev)
|
||||
to kick it somehow? */
|
||||
lbs_host_to_card_done(priv);
|
||||
|
||||
/* More often than not, this actually happens because the
|
||||
firmware has crapped itself -- rather than just a very
|
||||
busy medium. So send a harmless command, and if/when
|
||||
_that_ times out, we'll kick it in the head. */
|
||||
lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
|
||||
0, 0, NULL);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_TX);
|
||||
}
|
||||
|
||||
@ -489,19 +495,9 @@ void lbs_host_to_card_done(struct lbs_private *priv)
|
||||
priv->dnld_sent = DNLD_RES_RECEIVED;
|
||||
|
||||
/* Wake main thread if commands are pending */
|
||||
if (!priv->cur_cmd)
|
||||
if (!priv->cur_cmd || priv->tx_pending_len > 0)
|
||||
wake_up_interruptible(&priv->waitq);
|
||||
|
||||
/* Don't wake netif queues if we're in monitor mode and
|
||||
a TX packet is already pending, or if there are commands
|
||||
queued to be sent. */
|
||||
if (!priv->currenttxskb && list_empty(&priv->cmdpendingq)) {
|
||||
if (priv->dev && priv->connect_status == LBS_CONNECTED)
|
||||
netif_wake_queue(priv->dev);
|
||||
|
||||
if (priv->mesh_dev && priv->mesh_connect_status == LBS_CONNECTED)
|
||||
netif_wake_queue(priv->mesh_dev);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
|
||||
@ -663,8 +659,6 @@ static int lbs_thread(void *data)
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
|
||||
set_freezable();
|
||||
|
||||
for (;;) {
|
||||
int shouldsleep;
|
||||
|
||||
@ -675,12 +669,16 @@ static int lbs_thread(void *data)
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
|
||||
if (priv->surpriseremoved)
|
||||
if (kthread_should_stop())
|
||||
shouldsleep = 0; /* Bye */
|
||||
else if (priv->surpriseremoved)
|
||||
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)
|
||||
shouldsleep = 1; /* Firmware not ready. We're waiting for it */
|
||||
else if (priv->dnld_sent)
|
||||
@ -708,17 +706,19 @@ static int lbs_thread(void *data)
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&priv->waitq, &wait);
|
||||
try_to_freeze();
|
||||
|
||||
lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
|
||||
priv->intcounter, priv->currenttxskb, priv->dnld_sent);
|
||||
|
||||
if (kthread_should_stop() || priv->surpriseremoved) {
|
||||
lbs_deb_thread("main-thread: break from main thread: surpriseremoved=0x%x\n",
|
||||
priv->surpriseremoved);
|
||||
if (kthread_should_stop()) {
|
||||
lbs_deb_thread("main-thread: break from main thread\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (priv->surpriseremoved) {
|
||||
lbs_deb_thread("adapter removed; waiting to die...\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
|
||||
@ -749,6 +749,26 @@ static int lbs_thread(void *data)
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
}
|
||||
|
||||
if (priv->cmd_timed_out && priv->cur_cmd) {
|
||||
struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
|
||||
|
||||
if (++priv->nr_retries > 10) {
|
||||
lbs_pr_info("Excessive timeouts submitting command %x\n",
|
||||
le16_to_cpu(cmdnode->cmdbuf->command));
|
||||
lbs_complete_command(priv, cmdnode, -ETIMEDOUT);
|
||||
priv->nr_retries = 0;
|
||||
} else {
|
||||
priv->cur_cmd = NULL;
|
||||
lbs_pr_info("requeueing command %x due to timeout (#%d)\n",
|
||||
le16_to_cpu(cmdnode->cmdbuf->command), priv->nr_retries);
|
||||
|
||||
/* Stick it back at the _top_ of the pending queue
|
||||
for immediate resubmission */
|
||||
list_add(&cmdnode->list, &priv->cmdpendingq);
|
||||
}
|
||||
}
|
||||
priv->cmd_timed_out = 0;
|
||||
|
||||
/* Any Card Event */
|
||||
if (priv->hisregcpy & MRVDRV_CARDEVENT) {
|
||||
lbs_deb_thread("main-thread: Card Event Activity\n");
|
||||
@ -834,6 +854,58 @@ static int lbs_thread(void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy,
|
||||
struct cmd_header *cmd)
|
||||
{
|
||||
lbs_deb_fw("HOST_SLEEP_ACTIVATE succeeded\n");
|
||||
|
||||
netif_device_detach(priv->dev);
|
||||
if (priv->mesh_dev)
|
||||
netif_device_detach(priv->mesh_dev);
|
||||
|
||||
priv->fw_ready = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int lbs_suspend(struct lbs_private *priv)
|
||||
{
|
||||
struct cmd_header cmd;
|
||||
int ret;
|
||||
|
||||
if (priv->wol_criteria == 0xffffffff) {
|
||||
lbs_pr_info("Suspend attempt without configuring wake params!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd,
|
||||
sizeof(cmd), lbs_suspend_callback, 0);
|
||||
if (ret)
|
||||
lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_suspend);
|
||||
|
||||
int lbs_resume(struct lbs_private *priv)
|
||||
{
|
||||
priv->fw_ready = 1;
|
||||
|
||||
/* Firmware doesn't seem to give us RX packets any more
|
||||
until we send it some command. Might as well update */
|
||||
lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
|
||||
0, 0, NULL);
|
||||
|
||||
netif_device_attach(priv->dev);
|
||||
if (priv->mesh_dev)
|
||||
netif_device_attach(priv->mesh_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_resume);
|
||||
|
||||
/**
|
||||
* @brief This function downloads firmware image, gets
|
||||
* HW spec from firmware and set basic parameters to
|
||||
@ -879,35 +951,21 @@ done:
|
||||
static void command_timer_fn(unsigned long data)
|
||||
{
|
||||
struct lbs_private *priv = (struct lbs_private *)data;
|
||||
struct cmd_ctrl_node *node;
|
||||
unsigned long flags;
|
||||
|
||||
node = priv->cur_cmd;
|
||||
if (node == NULL) {
|
||||
lbs_deb_fw("ptempnode empty\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!node->cmdbuf) {
|
||||
lbs_deb_fw("cmd is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lbs_deb_fw("command_timer_fn fired, cmd %x\n", node->cmdbuf->command);
|
||||
|
||||
if (!priv->fw_ready)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
priv->cur_cmd = NULL;
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
lbs_deb_fw("re-sending same command because of timeout\n");
|
||||
lbs_queue_cmd(priv, node, 0);
|
||||
if (!priv->cur_cmd) {
|
||||
lbs_pr_info("Command timer expired; no pending command\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
lbs_pr_info("Command %x timed out\n", le16_to_cpu(priv->cur_cmd->cmdbuf->command));
|
||||
|
||||
priv->cmd_timed_out = 1;
|
||||
wake_up_interruptible(&priv->waitq);
|
||||
|
||||
return;
|
||||
out:
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
}
|
||||
|
||||
static int lbs_init_adapter(struct lbs_private *priv)
|
||||
@ -1055,6 +1113,9 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
|
||||
sprintf(priv->mesh_ssid, "mesh");
|
||||
priv->mesh_ssid_len = 4;
|
||||
|
||||
priv->wol_criteria = 0xffffffff;
|
||||
priv->wol_gpio = 0xff;
|
||||
|
||||
goto done;
|
||||
|
||||
err_init_adapter:
|
||||
@ -1130,8 +1191,33 @@ 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");
|
||||
if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
|
||||
lbs_pr_err("cannot register lbs_mesh attribute\n");
|
||||
|
||||
/* 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
|
||||
but we check them in that order because 20.pXX doesn't
|
||||
give an error -- it just silently fails. */
|
||||
|
||||
/* 5.110.20.pXX firmware will fail the command if the channel
|
||||
doesn't match the existing channel. But only if the TLV
|
||||
is correct. If the channel is wrong, _BOTH_ versions will
|
||||
give an error to 0x100+291, and allow 0x100+37 to succeed.
|
||||
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;
|
||||
if (lbs_mesh_config(priv, 1, priv->curbssparams.channel))
|
||||
priv->mesh_tlv = 0;
|
||||
}
|
||||
if (priv->mesh_tlv) {
|
||||
lbs_add_mesh(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);
|
||||
|
||||
@ -1160,11 +1246,13 @@ int lbs_stop_card(struct lbs_private *priv)
|
||||
|
||||
lbs_debugfs_remove_one(priv);
|
||||
device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
|
||||
device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
|
||||
if (priv->mesh_tlv)
|
||||
device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
|
||||
|
||||
/* Flush pending command nodes */
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
|
||||
cmdnode->result = -ENOENT;
|
||||
cmdnode->cmdwaitqwoken = 1;
|
||||
wake_up_interruptible(&cmdnode->cmdwait_q);
|
||||
}
|
||||
@ -1347,12 +1435,6 @@ void lbs_interrupt(struct lbs_private *priv)
|
||||
|
||||
lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter);
|
||||
|
||||
if (!spin_trylock(&priv->driver_lock)) {
|
||||
spin_unlock(&priv->driver_lock);
|
||||
printk(KERN_CRIT "%s called without driver_lock held\n", __func__);
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
priv->intcounter++;
|
||||
|
||||
if (priv->psstate == PS_STATE_SLEEP)
|
||||
|
@ -590,13 +590,13 @@ int lbs_scan_networks(struct lbs_private *priv,
|
||||
netif_stop_queue(priv->dev);
|
||||
netif_carrier_off(priv->dev);
|
||||
if (priv->mesh_dev) {
|
||||
netif_stop_queue(priv->mesh_dev);
|
||||
netif_carrier_off(priv->mesh_dev);
|
||||
netif_stop_queue(priv->mesh_dev);
|
||||
netif_carrier_off(priv->mesh_dev);
|
||||
}
|
||||
|
||||
/* Prepare to continue an interrupted scan */
|
||||
lbs_deb_scan("chan_count %d, last_scanned_channel %d\n",
|
||||
chan_count, priv->last_scanned_channel);
|
||||
chan_count, priv->last_scanned_channel);
|
||||
curr_chans = chan_list;
|
||||
/* advance channel list by already-scanned-channels */
|
||||
if (priv->last_scanned_channel > 0) {
|
||||
@ -659,11 +659,13 @@ out2:
|
||||
out:
|
||||
if (priv->connect_status == LBS_CONNECTED) {
|
||||
netif_carrier_on(priv->dev);
|
||||
netif_wake_queue(priv->dev);
|
||||
if (!priv->tx_pending_len)
|
||||
netif_wake_queue(priv->dev);
|
||||
}
|
||||
if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) {
|
||||
netif_carrier_on(priv->mesh_dev);
|
||||
netif_wake_queue(priv->mesh_dev);
|
||||
if (!priv->tx_pending_len)
|
||||
netif_wake_queue(priv->mesh_dev);
|
||||
}
|
||||
kfree(chan_list);
|
||||
|
||||
|
@ -93,8 +93,8 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
netif_stop_queue(priv->mesh_dev);
|
||||
|
||||
if (priv->tx_pending_len) {
|
||||
/* This can happen if packets come in on the mesh and eth
|
||||
device simultaneously -- there's no mutual exclusion on
|
||||
/* This can happen if packets come in on the mesh and eth
|
||||
device simultaneously -- there's no mutual exclusion on
|
||||
hard_start_xmit() calls between devices. */
|
||||
lbs_deb_tx("Packet on %s while busy\n", dev->name);
|
||||
ret = NETDEV_TX_BUSY;
|
||||
|
@ -734,6 +734,13 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
|
||||
|
||||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
if (!priv->ps_supported) {
|
||||
if (vwrq->disabled)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* PS is currently supported only in Infrastructure mode
|
||||
* Remove this check if it is to be supported in IBSS mode also
|
||||
*/
|
||||
@ -1000,9 +1007,8 @@ static int lbs_mesh_set_freq(struct net_device *dev,
|
||||
else if (priv->mode == IW_MODE_ADHOC)
|
||||
lbs_stop_adhoc_network(priv);
|
||||
}
|
||||
priv->curbssparams.channel = fwrq->m;
|
||||
lbs_mesh_config(priv, 0);
|
||||
lbs_mesh_config(priv, 1);
|
||||
lbs_mesh_config(priv, 1, fwrq->m);
|
||||
lbs_update_channel(priv);
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
@ -2010,7 +2016,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
|
||||
priv->mesh_ssid_len = dwrq->length;
|
||||
}
|
||||
|
||||
lbs_mesh_config(priv, 1);
|
||||
lbs_mesh_config(priv, 1, priv->curbssparams.channel);
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user