summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lin <dlin@marvell.com>2015-08-18 17:04:34 +0800
committerDavid Lin <dlin@marvell.com>2015-08-18 17:04:34 +0800
commit59e0d3d167a5bc2c03010df4ed54cc0653b5ae58 (patch)
tree63decbb86c07b9fdc95ad1efe48ecced7fdb5042
parentaaf953e1baf9cd65979103c4fda98c0bd48f4759 (diff)
Commit mwlwifi driver 10.3.0.8
1. Synchronized PATCH v6 sent to LWN. 2. Add code to support AMSDU. Signed-off-by: David Lin <dlin@marvell.com>
-rw-r--r--Kconfig28
-rw-r--r--Makefile2
-rw-r--r--Makefile.external2
-rw-r--r--Makefile.kernel2
-rwxr-xr-xbin/firmware/88W8897.binbin134500 -> 489084 bytes
-rw-r--r--dev.h131
-rw-r--r--fwcmd.c1300
-rw-r--r--fwcmd.h22
-rw-r--r--fwdl.c31
-rw-r--r--fwdl.h24
-rw-r--r--hostcmd.h753
-rw-r--r--isr.c48
-rw-r--r--isr.h22
-rw-r--r--mac80211.c192
-rw-r--r--mac80211.h19
-rw-r--r--main.c182
-rw-r--r--rx.c314
-rw-r--r--rx.h22
-rw-r--r--sysadpt.h22
-rw-r--r--test/hostapd.conf.1.multi_bssid2
-rw-r--r--test/hostapd.conf.1.open2
-rw-r--r--tx.c498
-rw-r--r--tx.h23
23 files changed, 1959 insertions, 1682 deletions
diff --git a/Kconfig b/Kconfig
index fd60ea2..a9bcb9c 100644
--- a/Kconfig
+++ b/Kconfig
@@ -1,17 +1,23 @@
config MWLWIFI
- tristate "Marvell Wireless WiFi driver (mwlwifi)"
- depends on PCI && MAC80211 && MWIFIEX_PCIE=n
+ tristate "Marvell Avastar 88W8864/88W8897 PCIe driver (mac80211 compatible)"
+ depends on PCI && MAC80211
select FW_LOADER
- select OF
---help---
- Select to build the driver supporting the:
+ Select to build the driver supporting the:
- Marvell Wireless WiFi 88W8864 modules
- Marvell Wireless WiFi 88W8897 modules
+ Marvell Wireless Wi-Fi 88W8864 modules
+ Marvell Wireless Wi-Fi 88W8897 modules
- This driver uses the kernel's mac80211 subsystem.
+ This driver uses the kernel's mac80211 subsystem.
+
+ If you want to compile the driver as a module (= code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/kbuild/modules.txt>. The
+ module will be called mwlwifi.
+
+ NOTE: Selecting this driver may cause conflict with MWIFIEX driver
+ that also operates on the same part number 88W8897. Users should
+ select either MWIFIEX or MWLWIFI, not both. MWIFIEX is fullmac,
+ supporting more comprehensive client functions for laptops/embedded
+ devices. MWLWIFI is mac80211-based for full AP/Wireless Bridge.
- If you want to compile the driver as a module (= code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/kbuild/modules.txt>. The
- module will be called mwlwifi.
diff --git a/Makefile b/Makefile
index f5e7e74..43c8632 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
EXTRA_CFLAGS+= -I${KDIR}
-EXTRA_CFLAGS+= -O2 -funroll-loops
+EXTRA_CFLAGS+= -O2 -funroll-loops -D__CHECK_ENDIAN__
EXTRA_CFLAGS+= -I${PWD}
diff --git a/Makefile.external b/Makefile.external
index f5e7e74..43c8632 100644
--- a/Makefile.external
+++ b/Makefile.external
@@ -13,7 +13,7 @@ LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
EXTRA_CFLAGS+= -I${KDIR}
-EXTRA_CFLAGS+= -O2 -funroll-loops
+EXTRA_CFLAGS+= -O2 -funroll-loops -D__CHECK_ENDIAN__
EXTRA_CFLAGS+= -I${PWD}
diff --git a/Makefile.kernel b/Makefile.kernel
index c6e03a3..49bd311 100644
--- a/Makefile.kernel
+++ b/Makefile.kernel
@@ -7,3 +7,5 @@ mwlwifi-objs += fwcmd.o
mwlwifi-objs += tx.o
mwlwifi-objs += rx.o
mwlwifi-objs += isr.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/bin/firmware/88W8897.bin b/bin/firmware/88W8897.bin
index e1229af..10c5cb1 100755
--- a/bin/firmware/88W8897.bin
+++ b/bin/firmware/88W8897.bin
Binary files differ
diff --git a/dev.h b/dev.h
index c2c5a06..243af72 100644
--- a/dev.h
+++ b/dev.h
@@ -1,17 +1,24 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file defines device related information.
- */
+/* Description: This file defines device related information. */
-#ifndef _mwl_dev_h_
-#define _mwl_dev_h_
+#ifndef _dev_h_
+#define _dev_h_
+#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/firmware.h>
@@ -36,7 +43,7 @@
#define MACREG_REG_GEN_PTR 0x00000C10
#define MACREG_REG_INT_CODE 0x00000C14
-/* Bit definitio for MACREG_REG_A2H_INTERRUPT_CAUSE (A2HRIC) */
+/* Bit definition for MACREG_REG_A2H_INTERRUPT_CAUSE (A2HRIC) */
#define MACREG_A2HRIC_BIT_TX_DONE BIT(0)
#define MACREG_A2HRIC_BIT_RX_RDY BIT(1)
#define MACREG_A2HRIC_BIT_OPC_DONE BIT(2)
@@ -72,7 +79,7 @@
#define MACREG_A2HRIC_BIT_MASK ISR_SRC_BITS
-/* Bit definitio for MACREG_REG_H2A_INTERRUPT_CAUSE (H2ARIC) */
+/* Bit definition for MACREG_REG_H2A_INTERRUPT_CAUSE (H2ARIC) */
#define MACREG_H2ARIC_BIT_PPA_READY BIT(0)
#define MACREG_H2ARIC_BIT_DOOR_BELL BIT(1)
#define MACREG_H2ARIC_BIT_PS BIT(2)
@@ -131,16 +138,18 @@ enum {
};
struct mwl_chip_info {
- char *part_name;
- char *fw_image;
+ const char *part_name;
+ const char *fw_image;
+ int antenna_tx;
+ int antenna_rx;
};
struct mwl_tx_pwr_tbl {
u8 channel;
u8 setcap;
- u16 tx_power[SYSADPT_TX_POWER_LEVEL_TOTAL];
- u8 cdd; /* 0: off, 1: on */
u16 txantenna2;
+ u16 tx_power[SYSADPT_TX_POWER_LEVEL_TOTAL];
+ bool cdd;
};
struct mwl_hw_data {
@@ -177,17 +186,23 @@ struct mwl_tx_desc {
__le16 reserved;
__le32 tcpack_sn;
__le32 tcpack_src_dst;
- struct sk_buff *psk_buff;
- struct mwl_tx_desc *pnext;
- u8 reserved1[2];
+ __le32 reserved1;
+ __le32 reserved2;
+ u8 reserved3[2];
u8 packet_info;
u8 packet_id;
__le16 packet_len_and_retry;
__le16 packet_rate_info;
- u8 *sta_info;
+ __le32 reserved4;
__le32 status;
} __packed;
+struct mwl_tx_hndl {
+ struct sk_buff *psk_buff;
+ struct mwl_tx_desc *pdesc;
+ struct mwl_tx_hndl *pnext;
+};
+
#define MWL_RX_RATE_FORMAT_MASK 0x0007
#define MWL_RX_RATE_NSS_MASK 0x0018
#define MWL_RX_RATE_NSS_SHIFT 3
@@ -213,27 +228,30 @@ struct mwl_rx_desc {
u8 status; /* status field containing USED bit */
u8 channel; /* channel this pkt was received on */
u8 rx_control; /* the control element of the desc */
- /* above are 32bits aligned and is same as FW, RxControl put at end
- * for sync
- */
- struct sk_buff *psk_buff; /* associated sk_buff for Linux */
- void *pbuff_data; /* virtual address of payload data */
- struct mwl_rx_desc *pnext; /* virtual address of next RX desc */
+ __le32 reserved1[3];
} __packed;
+struct mwl_rx_hndl {
+ struct sk_buff *psk_buff; /* associated sk_buff for Linux */
+ struct mwl_rx_desc *pdesc;
+ struct mwl_rx_hndl *pnext;
+};
+
struct mwl_desc_data {
dma_addr_t pphys_tx_ring; /* ptr to first TX desc (phys.) */
struct mwl_tx_desc *ptx_ring; /* ptr to first TX desc (virt.) */
- struct mwl_tx_desc *pnext_tx_desc; /* next TX desc that can be used */
- struct mwl_tx_desc *pstale_tx_desc;/* the staled TX descriptor */
+ struct mwl_tx_hndl *tx_hndl;
+ struct mwl_tx_hndl *pnext_tx_hndl; /* next TX handle that can be used */
+ struct mwl_tx_hndl *pstale_tx_hndl;/* the staled TX handle */
dma_addr_t pphys_rx_ring; /* ptr to first RX desc (phys.) */
struct mwl_rx_desc *prx_ring; /* ptr to first RX desc (virt.) */
- struct mwl_rx_desc *pnext_rx_desc; /* next RX desc that can be used */
- unsigned int wcb_base; /* FW base offset for registers */
- unsigned int rx_desc_write; /* FW descriptor write position */
- unsigned int rx_desc_read; /* FW descriptor read position */
- unsigned int rx_buf_size; /* length of the RX buffers */
-} __packed;
+ struct mwl_rx_hndl *rx_hndl;
+ struct mwl_rx_hndl *pnext_rx_hndl; /* next RX handle that can be used */
+ u32 wcb_base; /* FW base offset for registers */
+ u32 rx_desc_write; /* FW descriptor write position */
+ u32 rx_desc_read; /* FW descriptor read position */
+ u32 rx_buf_size; /* length of the RX buffers */
+};
struct mwl_ampdu_stream {
struct ieee80211_sta *sta;
@@ -255,7 +273,7 @@ struct mwl_priv {
int antenna_rx;
struct mwl_tx_pwr_tbl tx_pwr_tbl[SYSADPT_MAX_NUM_CHANNELS];
- u32 cdd; /* 0: off, 1: on */
+ bool cdd;
u16 txantenna2;
u8 powinited;
u16 max_tx_pow[SYSADPT_TX_POWER_LEVEL_TOTAL]; /* max tx power (dBm) */
@@ -263,8 +281,8 @@ struct mwl_priv {
u8 cal_tbl[200];
struct pci_dev *pdev;
- void *iobase0; /* MEM Base Address Register 0 */
- void *iobase1; /* MEM Base Address Register 1 */
+ void __iomem *iobase0; /* MEM Base Address Register 0 */
+ void __iomem *iobase1; /* MEM Base Address Register 1 */
u32 next_bar_num;
spinlock_t fwcmd_lock; /* for firmware command */
@@ -285,10 +303,12 @@ struct mwl_priv {
struct tasklet_struct tx_task;
struct tasklet_struct rx_task;
+ struct tasklet_struct qe_task;
int txq_limit;
bool is_tx_schedule;
int recv_limit;
bool is_rx_schedule;
+ bool is_qe_schedule;
s8 noise; /* Most recently reported noise in dBm */
struct ieee80211_supported_band band_24;
struct ieee80211_channel channels_24[BAND_24_CHANNEL_NUM];
@@ -324,23 +344,22 @@ struct beacon_info {
u16 cap_info;
u8 b_rate_set[SYSADPT_MAX_DATA_RATES_G];
u8 op_rate_set[SYSADPT_MAX_DATA_RATES_G];
- u16 ie_wmm_len; /* Keep WMM IE */
+ u8 ie_list_ht[148];
+ u8 ie_list_vht[24];
u8 *ie_wmm_ptr;
- u16 ie_rsn_len; /* Keep WPA IE */
u8 *ie_rsn_ptr;
- u16 ie_rsn48_len; /* Keep WPA2 IE */
u8 *ie_rsn48_ptr;
- u16 ie_ht_len; /* Keep HT IE */
u8 *ie_ht_ptr;
- u8 ie_list_ht[148];
- u16 ie_vht_len; /* Keep VHT IE */
u8 *ie_vht_ptr;
- u8 ie_list_vht[24];
+ u8 ie_wmm_len;
+ u8 ie_rsn_len;
+ u8 ie_rsn48_len;
+ u8 ie_ht_len;
+ u8 ie_vht_len;
};
struct mwl_vif {
struct list_head list;
- struct ieee80211_vif *vif;
int macid; /* Firmware macid for this vif. */
u16 seqno; /* Non AMPDU sequence number assigned by driver. */
struct { /* Saved WEP keys */
@@ -352,7 +371,6 @@ struct mwl_vif {
/* A flag to indicate is HW crypto is enabled for this bssid */
bool is_hw_crypto_enabled;
/* Indicate if this is station mode */
- bool is_sta;
struct beacon_info beacon_info;
u16 iv16;
u32 iv32;
@@ -360,16 +378,16 @@ struct mwl_vif {
};
struct mwl_tx_info {
- u32 start_time;
+ unsigned long start_time;
u32 pkts;
};
struct mwl_amsdu_frag {
struct sk_buff *skb;
- u8 pad;
u8 *cur_pos;
+ unsigned long jiffies;
+ u8 pad;
u8 num;
- u32 jiffies;
};
struct mwl_amsdu_ctrl {
@@ -379,10 +397,10 @@ struct mwl_amsdu_ctrl {
struct mwl_sta {
struct list_head list;
- struct ieee80211_sta *sta;
bool is_ampdu_allowed;
struct mwl_tx_info tx_stats[MWL_MAX_TID];
bool is_amsdu_allowed;
+ spinlock_t amsdu_lock; /* for amsdu aggregation */
struct mwl_amsdu_ctrl amsdu_ctrl;
u16 iv16;
u32 iv32;
@@ -397,14 +415,14 @@ struct mwl_dma_data {
/* Transmission information to transmit a socket buffer. */
struct mwl_tx_ctrl {
- u8 tx_priority;
- u16 qos_ctrl;
- u8 type;
- u8 xmit_control;
void *sta;
void *vif;
void *k_conf;
-} __packed;
+ u8 tx_priority;
+ u8 type;
+ u16 qos_ctrl;
+ u8 xmit_control;
+};
static inline struct mwl_vif *mwl_dev_get_vif(const struct ieee80211_vif *vif)
{
@@ -416,4 +434,11 @@ static inline struct mwl_sta *mwl_dev_get_sta(const struct ieee80211_sta *sta)
return (struct mwl_sta *)&sta->drv_priv;
}
-#endif /* _mwl_dev_h_ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
+#define ether_addr_copy(dst, src) memcpy(dst, src, ETH_ALEN)
+#endif
+
+/* Defined in mac80211.c. */
+extern const struct ieee80211_ops mwl_mac80211_ops;
+
+#endif /* _dev_h_ */
diff --git a/fwcmd.c b/fwcmd.c
index 9b91752..35da765 100644
--- a/fwcmd.c
+++ b/fwcmd.c
@@ -1,12 +1,20 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file implements frimware host command related functions.
+/* Description: This file implements firmware host command related
+ * functions.
*/
#include <linux/etherdevice.h>
@@ -14,740 +22,11 @@
#include "sysadpt.h"
#include "dev.h"
#include "fwcmd.h"
+#include "hostcmd.h"
-#define MAX_WAIT_FW_COMPLETE_ITERATIONS 10000
+#define MAX_WAIT_FW_COMPLETE_ITERATIONS 500
#define MAX_WAIT_GET_HW_SPECS_ITERATONS 3
-/* 16 bit host command code */
-#define HOSTCMD_CMD_GET_HW_SPEC 0x0003
-#define HOSTCMD_CMD_SET_HW_SPEC 0x0004
-#define HOSTCMD_CMD_802_11_GET_STAT 0x0014
-#define HOSTCMD_CMD_802_11_RADIO_CONTROL 0x001c
-#define HOSTCMD_CMD_802_11_TX_POWER 0x001f
-#define HOSTCMD_CMD_802_11_RF_ANTENNA 0x0020
-#define HOSTCMD_CMD_BROADCAST_SSID_ENABLE 0x0050 /* per-vif */
-#define HOSTCMD_CMD_SET_RF_CHANNEL 0x010a
-#define HOSTCMD_CMD_SET_AID 0x010d /* per-vif */
-#define HOSTCMD_CMD_SET_INFRA_MODE 0x010e /* per-vif */
-#define HOSTCMD_CMD_802_11_RTS_THSD 0x0113
-#define HOSTCMD_CMD_SET_EDCA_PARAMS 0x0115
-#define HOSTCMD_CMD_SET_WMM_MODE 0x0123
-#define HOSTCMD_CMD_SET_FIXED_RATE 0x0126
-#define HOSTCMD_CMD_SET_IES 0x0127
-#define HOSTCMD_CMD_SET_MAC_ADDR 0x0202 /* per-vif */
-#define HOSTCMD_CMD_SET_RATE_ADAPT_MODE 0x0203
-#define HOSTCMD_CMD_GET_WATCHDOG_BITMAP 0x0205
-#define HOSTCMD_CMD_DEL_MAC_ADDR 0x0206 /* pre-vif */
-#define HOSTCMD_CMD_BSS_START 0x1100 /* per-vif */
-#define HOSTCMD_CMD_AP_BEACON 0x1101 /* per-vif */
-#define HOSTCMD_CMD_SET_NEW_STN 0x1111 /* per-vif */
-#define HOSTCMD_CMD_SET_APMODE 0x1114
-#define HOSTCMD_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */
-#define HOSTCMD_CMD_BASTREAM 0x1125
-#define HOSTCMD_CMD_DWDS_ENABLE 0x1144
-#define HOSTCMD_CMD_FW_FLUSH_TIMER 0x1148
-#define HOSTCMD_CMD_SET_CDD 0x1150
-
-/* Define general result code for each command */
-#define HOSTCMD_RESULT_OK 0x0000
-/* General error */
-#define HOSTCMD_RESULT_ERROR 0x0001
-/* Command is not valid */
-#define HOSTCMD_RESULT_NOT_SUPPORT 0x0002
-/* Command is pending (will be processed) */
-#define HOSTCMD_RESULT_PENDING 0x0003
-/* System is busy (command ignored) */
-#define HOSTCMD_RESULT_BUSY 0x0004
-/* Data buffer is not big enough */
-#define HOSTCMD_RESULT_PARTIAL_DATA 0x0005
-
-/* Define channel related constants */
-#define FREQ_BAND_2DOT4GHZ 0x1
-#define FREQ_BAND_4DOT9GHZ 0x2
-#define FREQ_BAND_5GHZ 0x4
-#define FREQ_BAND_5DOT2GHZ 0x8
-#define CH_AUTO_WIDTH 0
-#define CH_10_MHZ_WIDTH 0x1
-#define CH_20_MHZ_WIDTH 0x2
-#define CH_40_MHZ_WIDTH 0x4
-#define CH_80_MHZ_WIDTH 0x5
-#define EXT_CH_ABOVE_CTRL_CH 0x1
-#define EXT_CH_AUTO 0x2
-#define EXT_CH_BELOW_CTRL_CH 0x3
-#define NO_EXT_CHANNEL 0x0
-
-#define ACT_PRIMARY_CHAN_0 0
-#define ACT_PRIMARY_CHAN_1 1
-#define ACT_PRIMARY_CHAN_2 2
-#define ACT_PRIMARY_CHAN_3 3
-
-/* Define rate related constants */
-#define HOSTCMD_ACT_NOT_USE_FIXED_RATE 0x0002
-
-/* Define station related constants */
-#define HOSTCMD_ACT_STA_ACTION_ADD 0
-#define HOSTCMD_ACT_STA_ACTION_REMOVE 2
-
-/* Define key related constants */
-#define MAX_ENCR_KEY_LENGTH 16
-#define MIC_KEY_LENGTH 8
-
-#define KEY_TYPE_ID_WEP 0x00
-#define KEY_TYPE_ID_TKIP 0x01
-#define KEY_TYPE_ID_AES 0x02
-
-#define ENCR_KEY_FLAG_TXGROUPKEY 0x00000004
-#define ENCR_KEY_FLAG_PAIRWISE 0x00000008
-#define ENCR_KEY_FLAG_TSC_VALID 0x00000040
-#define ENCR_KEY_FLAG_WEP_TXKEY 0x01000000
-#define ENCR_KEY_FLAG_MICKEY_VALID 0x02000000
-
-/* Define block ack related constants */
-#define BASTREAM_FLAG_IMMEDIATE_TYPE 1
-#define BASTREAM_FLAG_DIRECTION_UPSTREAM 0
-
-/* Define general purpose action */
-#define HOSTCMD_ACT_GEN_SET 0x0001
-#define HOSTCMD_ACT_GEN_SET_LIST 0x0002
-#define HOSTCMD_ACT_GEN_GET_LIST 0x0003
-
-/* Misc */
-#define MAX_ENCR_KEY_LENGTH 16
-#define MIC_KEY_LENGTH 8
-
-enum {
- WL_DISABLE = 0,
- WL_ENABLE = 1,
- WL_DISABLE_VMAC = 0x80,
-};
-
-enum {
- WL_GET = 0,
- WL_SET = 1,
- WL_RESET = 2,
-};
-
-enum {
- WL_LONG_PREAMBLE = 1,
- WL_SHORT_PREAMBLE = 3,
- WL_AUTO_PREAMBLE = 5,
-};
-
-enum encr_action_type {
- /* request to enable/disable HW encryption */
- ENCR_ACTION_ENABLE_HW_ENCR,
- /* request to set encryption key */
- ENCR_ACTION_TYPE_SET_KEY,
- /* request to remove one or more keys */
- ENCR_ACTION_TYPE_REMOVE_KEY,
- ENCR_ACTION_TYPE_SET_GROUP_KEY,
-};
-
-enum ba_action_type {
- BA_CREATE_STREAM,
- BA_UPDATE_STREAM,
- BA_DESTROY_STREAM,
- BA_FLUSH_STREAM,
- BA_CHECK_STREAM,
-};
-
-enum mac_type {
- WL_MAC_TYPE_PRIMARY_CLIENT,
- WL_MAC_TYPE_SECONDARY_CLIENT,
- WL_MAC_TYPE_PRIMARY_AP,
- WL_MAC_TYPE_SECONDARY_AP,
-};
-
-/* General host command header */
-struct hostcmd_header {
- __le16 cmd;
- __le16 len;
- u8 seq_num;
- u8 macid;
- __le16 result;
-} __packed;
-
-/* HOSTCMD_CMD_GET_HW_SPEC */
-struct hostcmd_cmd_get_hw_spec {
- struct hostcmd_header cmd_hdr;
- u8 version; /* version of the HW */
- u8 host_if; /* host interface */
- __le16 num_wcb; /* Max. number of WCB FW can handle */
- __le16 num_mcast_addr; /* MaxNbr of MC addresses FW can handle */
- u8 permanent_addr[ETH_ALEN]; /* MAC address programmed in HW */
- __le16 region_code;
- __le16 num_antenna; /* Number of antenna used */
- __le32 fw_release_num; /* 4 byte of FW release number */
- __le32 wcb_base0;
- __le32 rxpd_wr_ptr;
- __le32 rxpd_rd_ptr;
- __le32 fw_awake_cookie;
- __le32 wcb_base[SYSADPT_TOTAL_TX_QUEUES - 1];
-} __packed;
-
-/* HOSTCMD_CMD_SET_HW_SPEC */
-struct hostcmd_cmd_set_hw_spec {
- struct hostcmd_header cmd_hdr;
- /* HW revision */
- u8 version;
- /* Host interface */
- u8 host_if;
- /* Max. number of Multicast address FW can handle */
- __le16 num_mcast_addr;
- /* MAC address */
- u8 permanent_addr[ETH_ALEN];
- /* Region Code */
- __le16 region_code;
- /* 4 byte of FW release number, example 0x1234=1.2.3.4 */
- __le32 fw_release_num;
- /* Firmware awake cookie - used to ensure that the device
- * is not in sleep mode
- */
- __le32 fw_awake_cookie;
- /* Device capabilities (see above) */
- __le32 device_caps;
- /* Rx shared memory queue */
- __le32 rxpd_wr_ptr;
- /* Actual number of TX queues in WcbBase array */
- __le32 num_tx_queues;
- /* TX WCB Rings */
- __le32 wcb_base[SYSADPT_NUM_OF_DESC_DATA];
- /* Max AMSDU size (00 - AMSDU Disabled,
- * 01 - 4K, 10 - 8K, 11 - not defined)
- */
- __le32 features;
- __le32 tx_wcb_num_per_queue;
- __le32 total_rx_wcb;
-} __packed;
-
-/* HOSTCMD_CMD_802_11_GET_STAT */
-struct hostcmd_cmd_802_11_get_stat {
- struct hostcmd_header cmd_hdr;
- __le32 tx_retry_successes;
- __le32 tx_multiple_retry_successes;
- __le32 tx_failures;
- __le32 rts_successes;
- __le32 rts_failures;
- __le32 ack_failures;
- __le32 rx_duplicate_frames;
- __le32 rx_fcs_errors;
- __le32 tx_watchdog_timeouts;
- __le32 rx_overflows;
- __le32 rx_frag_errors;
- __le32 rx_mem_errors;
- __le32 pointer_errors;
- __le32 tx_underflows;
- __le32 tx_done;
- __le32 tx_done_buf_try_put;
- __le32 tx_done_buf_put;
- /* Put size of requested buffer in here */
- __le32 wait_for_tx_buf;
- __le32 tx_attempts;
- __le32 tx_successes;
- __le32 tx_fragments;
- __le32 tx_multicasts;
- __le32 rx_non_ctl_pkts;
- __le32 rx_multicasts;
- __le32 rx_undecryptable_frames;
- __le32 rx_icv_errors;
- __le32 rx_excluded_frames;
- __le32 rx_weak_iv_count;
- __le32 rx_unicasts;
- __le32 rx_bytes;
- __le32 rx_errors;
- __le32 rx_rts_count;
- __le32 tx_cts_count;
-} __packed;
-
-/* HOSTCMD_CMD_802_11_RADIO_CONTROL */
-struct hostcmd_cmd_802_11_radio_control {
- struct hostcmd_header cmd_hdr;
- __le16 action;
- /* @bit0: 1/0,on/off, @bit1: 1/0, long/short @bit2: 1/0,auto/fix */
- __le16 control;
- __le16 radio_on;
-} __packed;
-
-/* HOSTCMD_CMD_802_11_TX_POWER */
-struct hostcmd_cmd_802_11_tx_power {
- struct hostcmd_header cmd_hdr;
- __le16 action;
- __le16 band;
- __le16 ch;
- __le16 bw;
- __le16 sub_ch;
- __le16 power_level_list[SYSADPT_TX_POWER_LEVEL_TOTAL];
-} __packed;
-
-/* HOSTCMD_CMD_802_11_RF_ANTENNA */
-struct hostcmd_cmd_802_11_rf_antenna {
- struct hostcmd_header cmd_hdr;
- __le16 action;
- __le16 antenna_mode; /* Number of antennas or 0xffff(diversity) */
-} __packed;
-
-/* HOSTCMD_CMD_BROADCAST_SSID_ENABLE */
-struct hostcmd_cmd_broadcast_ssid_enable {
- struct hostcmd_header cmd_hdr;
- __le32 enable;
-} __packed;
-
-/* HOSTCMD_CMD_SET_RF_CHANNEL */
-#define FREQ_BAND_MASK 0x0000003f
-#define CHNL_WIDTH_MASK 0x000007c0
-#define CHNL_WIDTH_SHIFT 6
-#define ACT_PRIMARY_MASK 0x00003800
-#define ACT_PRIMARY_SHIFT 11
-
-struct hostcmd_cmd_set_rf_channel {
- struct hostcmd_header cmd_hdr;
- __le16 action;
- u8 curr_chnl;
- __le32 chnl_flags;
-} __packed;
-
-/* HOSTCMD_CMD_SET_AID */
-struct hostcmd_cmd_set_aid {
- struct hostcmd_header cmd_hdr;
- __le16 aid;
- u8 mac_addr[ETH_ALEN]; /* AP's Mac Address(BSSID) */
- __le32 gprotect;
- u8 ap_rates[SYSADPT_MAX_DATA_RATES_G];
-} __packed;
-
-/* HOSTCMD_CMD_SET_INFRA_MODE */
-struct hostcmd_cmd_set_infra_mode {
- struct hostcmd_header cmd_hdr;
-} __packed;
-
-/* HOSTCMD_CMD_802_11_RTS_THSD */
-struct hostcmd_cmd_802_11_rts_thsd {
- struct hostcmd_header cmd_hdr;
- __le16 action;
- __le16 threshold;
-} __packed;
-
-/* HOSTCMD_CMD_SET_EDCA_PARAMS */
-struct hostcmd_cmd_set_edca_params {
- struct hostcmd_header cmd_hdr;
- /* 0 = get all, 0x1 =set CWMin/Max, 0x2 = set TXOP , 0x4 =set AIFSN */
- __le16 action;
- __le16 txop; /* in unit of 32 us */
- __le32 cw_max; /* 0~15 */
- __le32 cw_min; /* 0~15 */
- u8 aifsn;
- u8 txq_num; /* Tx Queue number. */
-} __packed;
-
-/* HOSTCMD_CMD_SET_WMM_MODE */
-struct hostcmd_cmd_set_wmm_mode {
- struct hostcmd_header cmd_hdr;
- __le16 action; /* 0->unset, 1->set */
-} __packed;
-
-/* HOSTCMD_CMD_SET_FIXED_RATE */
-struct fix_rate_flag { /* lower rate after the retry count */
- /* 0: legacy, 1: HT */
- __le32 fix_rate_type;
- /* 0: retry count is not valid, 1: use retry count specified */
- __le32 retry_count_valid;
-} __packed;
-
-struct fix_rate_entry {
- struct fix_rate_flag fix_rate_type_flags;
- /* depending on the flags above, this can be either a legacy
- * rate(not index) or an MCS code.
- */
- __le32 fixed_rate;
- __le32 retry_count;
-} __packed;
-
-struct hostcmd_cmd_set_fixed_rate {
- struct hostcmd_header cmd_hdr;
- /* HOSTCMD_ACT_NOT_USE_FIXED_RATE 0x0002 */
- __le32 action;
- /* use fixed rate specified but firmware can drop to */
- __le32 allow_rate_drop;
- __le32 entry_count;
- struct fix_rate_entry fixed_rate_table[4];
- u8 multicast_rate;
- u8 multi_rate_tx_type;
- u8 management_rate;
-} __packed;
-
-/* HOSTCMD_CMD_SET_IES */
-struct hostcmd_cmd_set_ies {
- struct hostcmd_header cmd_hdr;
- __le16 action; /* 0->unset, 1->set */
- __le16 ie_list_len_ht;
- __le16 ie_list_len_vht;
- __le16 ie_list_len_proprietary;
- /*Buffer size same as Generic_Beacon*/
- u8 ie_list_ht[148];
- u8 ie_list_vht[24];
- u8 ie_list_proprietary[112];
-} __packed;
-
-/* HOSTCMD_CMD_SET_RATE_ADAPT_MODE */
-struct hostcmd_cmd_set_rate_adapt_mode {
- struct hostcmd_header cmd_hdr;
- __le16 action;
- __le16 rate_adapt_mode; /* 0:Indoor, 1:Outdoor */
-} __packed;
-
-/* HOSTCMD_CMD_SET_MAC_ADDR, HOSTCMD_CMD_DEL_MAC_ADDR */
-struct hostcmd_cmd_set_mac_addr {
- struct hostcmd_header cmd_hdr;
- __le16 mac_type;
- u8 mac_addr[ETH_ALEN];
-} __packed;
-
-/* HOSTCMD_CMD_GET_WATCHDOG_BITMAP */
-struct hostcmd_cmd_get_watchdog_bitmap {
- struct hostcmd_header cmd_hdr;
- u8 watchdog_bitmap; /* for SW/BA */
-} __packed;
-
-/* HOSTCMD_CMD_BSS_START */
-struct hostcmd_cmd_bss_start {
- struct hostcmd_header cmd_hdr;
- __le32 enable; /* FALSE: Disable or TRUE: Enable */
-} __packed;
-
-/* HOSTCMD_CMD_AP_BEACON */
-struct cf_params {
- u8 elem_id;
- u8 len;
- u8 cfp_cnt;
- u8 cfp_period;
- __le16 cfp_max_duration;
- __le16 cfp_duration_remaining;
-} __packed;
-
-struct ibss_params {
- u8 elem_id;
- u8 len;
- __le16 atim_window;
-} __packed;
-
-union ss_params {
- struct cf_params cf_param_set;
- struct ibss_params ibss_param_set;
-} __packed;
-
-struct fh_params {
- u8 elem_id;
- u8 len;
- __le16 dwell_time;
- u8 hop_set;
- u8 hop_pattern;
- u8 hop_index;
-} __packed;
-
-struct ds_params {
- u8 elem_id;
- u8 len;
- u8 current_chnl;
-} __packed;
-
-union phy_params {
- struct fh_params fh_param_set;
- struct ds_params ds_param_set;
-} __packed;
-
-struct rsn_ie {
- u8 elem_id;
- u8 len;
- u8 oui_type[4]; /* 00:50:f2:01 */
- u8 ver[2];
- u8 grp_key_cipher[4];
- u8 pws_key_cnt[2];
- u8 pws_key_cipher_list[4];
- u8 auth_key_cnt[2];
- u8 auth_key_list[4];
-} __packed;
-
-struct rsn48_ie {
- u8 elem_id;
- u8 len;
- u8 ver[2];
- u8 grp_key_cipher[4];
- u8 pws_key_cnt[2];
- u8 pws_key_cipher_list[4];
- u8 auth_key_cnt[2];
- u8 auth_key_list[4];
- u8 rsn_cap[2];
- u8 pmk_id_cnt[2];
- u8 pmk_id_list[16]; /* Should modify to 16 * S */
- u8 reserved[8];
-} __packed;
-
-struct ac_param_rcd {
- u8 aci_aifsn;
- u8 ecw_min_max;
- __le16 txop_lim;
-} __packed;
-
-struct wmm_param_elem {
- u8 elem_id;
- u8 len;
- u8 oui[3];
- u8 type;
- u8 sub_type;
- u8 version;
- u8 rsvd;
- struct ac_param_rcd ac_be;
- struct ac_param_rcd ac_bk;
- struct ac_param_rcd ac_vi;
- struct ac_param_rcd ac_vo;
-} __packed;
-
-struct channel_info {
- u8 first_channel_num;
- u8 num_channels;
- u8 max_tx_pwr_level;
-} __packed;
-
-struct country {
- u8 elem_id;
- u8 len;
- u8 country_str[3];
- struct channel_info channel_info[40];
-} __packed;
-
-struct start_cmd {
- u8 sta_mac_addr[ETH_ALEN];
- u8 ssid[IEEE80211_MAX_SSID_LEN];
- u8 bss_type;
- __le16 bcn_period;
- u8 dtim_period;
- union ss_params ss_param_set;
- union phy_params phy_param_set;
- __le16 probe_delay;
- __le16 cap_info;
- u8 b_rate_set[SYSADPT_MAX_DATA_RATES_G];
- u8 op_rate_set[SYSADPT_MAX_DATA_RATES_G];
- struct rsn_ie rsn_ie;
- struct rsn48_ie rsn48_ie;
- struct wmm_param_elem wmm_param;
- struct country country;
- __le32 ap_rf_type; /* 0->B, 1->G, 2->Mixed, 3->A, 4->11J */
-} __packed;
-
-struct hostcmd_cmd_ap_beacon {
- struct hostcmd_header cmd_hdr;
- struct start_cmd start_cmd;
-} __packed;
-
-/* HOSTCMD_CMD_SET_NEW_STN */
-struct add_ht_info {
- u8 control_chnl;
- u8 add_chnl;
- __le16 op_mode;
- __le16 stbc;
-} __packed;
-
-struct peer_info {
- __le32 legacy_rate_bitmap;
- u8 ht_rates[4];
- __le16 cap_info;
- __le16 ht_cap_info;
- u8 mac_ht_param_info;
- u8 mrvl_sta;
- struct add_ht_info add_ht_info;
- __le32 tx_bf_capabilities; /* EXBF_SUPPORT */
- __le32 vht_max_rx_mcs;
- __le32 vht_cap;
- /* 0:20Mhz, 1:40Mhz, 2:80Mhz, 3:160 or 80+80Mhz */
- u8 vht_rx_channel_width;
-} __packed;
-
-struct hostcmd_cmd_set_new_stn {
- struct hostcmd_header cmd_hdr;
- __le16 aid;
- u8 mac_addr[ETH_ALEN];
- __le16 stn_id;
- __le16 action;
- __le16 reserved;
- struct peer_info peer_info;
- /* UAPSD_SUPPORT */
- u8 qos_info;
- u8 is_qos_sta;
- __le32 fw_sta_ptr;
-} __packed;
-
-/* HOSTCMD_CMD_SET_APMODE */
-struct hostcmd_cmd_set_apmode {
- struct hostcmd_header cmd_hdr;
- u8 apmode;
-} __packed;
-
-/* HOSTCMD_CMD_UPDATE_ENCRYPTION */
-struct hostcmd_cmd_update_encryption {
- struct hostcmd_header cmd_hdr;
- /* Action type - see encr_action_type */
- __le32 action_type; /* encr_action_type */
- /* size of the data buffer attached. */
- __le32 data_length;
- u8 mac_addr[ETH_ALEN];
- u8 action_data[1];
-} __packed;
-
-struct wep_type_key {
- /* WEP key material (max 128bit) */
- u8 key_material[MAX_ENCR_KEY_LENGTH];
-} __packed;
-
-struct encr_tkip_seqcnt {
- __le16 low;
- __le32 high;
-} __packed;
-
-struct tkip_type_key {
- /* TKIP Key material. Key type (group or pairwise key) is
- * determined by flags
- */
- /* in KEY_PARAM_SET structure. */
- u8 key_material[MAX_ENCR_KEY_LENGTH];
- /* MIC keys */
- u8 tkip_tx_mic_key[MIC_KEY_LENGTH];
- u8 tkip_rx_mic_key[MIC_KEY_LENGTH];
- struct encr_tkip_seqcnt tkip_rsc;
- struct encr_tkip_seqcnt tkip_tsc;
-} __packed;
-
-struct aes_type_key {
- /* AES Key material */
- u8 key_material[MAX_ENCR_KEY_LENGTH];
-} __packed;
-
-union mwl_key_type {
- struct wep_type_key wep_key;
- struct tkip_type_key tkip_key;
- struct aes_type_key aes_key;
-} __packed;
-
-struct key_param_set {
- /* Total length of this structure (Key is variable size array) */
- __le16 length;
- /* Key type - WEP, TKIP or AES-CCMP. */
- /* See definitions above */
- __le16 key_type_id;
- /* key flags (ENCR_KEY_FLAG_XXX_ */
- __le32 key_info;
- /* For WEP only - actual key index */
- __le32 key_index;
- /* Size of the key */
- __le16 key_len;
- /* Key material (variable size array) */
- union mwl_key_type key;
- u8 mac_addr[ETH_ALEN];
-} __packed;
-
-struct hostcmd_cmd_set_key {
- struct hostcmd_header cmd_hdr;
- /* Action type - see encr_action_type */
- __le32 action_type; /* encr_action_type */
- /* size of the data buffer attached. */
- __le32 data_length;
- /* data buffer - maps to one KEY_PARAM_SET structure */
- struct key_param_set key_param;
-} __packed;
-
-/* HOSTCMD_CMD_BASTREAM */
-#define BA_TYPE_MASK 0x00000001
-#define BA_DIRECTION_MASK 0x00000006
-#define BA_DIRECTION_SHIFT 1
-
-struct ba_context {
- __le32 context;
-} __packed;
-
-/* parameters for block ack creation */
-struct create_ba_params {
- /* BA Creation flags - see above */
- __le32 flags;
- /* idle threshold */
- __le32 idle_thrs;
- /* block ack transmit threshold (after how many pkts should we
- * send BAR?)
- */
- __le32 bar_thrs;
- /* receiver window size */
- __le32 window_size;
- /* MAC Address of the BA partner */
- u8 peer_mac_addr[ETH_ALEN];
- /* Dialog Token */
- u8 dialog_token;
- /* TID for the traffic stream in this BA */
- u8 tid;
- /* shared memory queue ID (not sure if this is required) */
- u8 queue_id;
- u8 param_info;
- /* returned by firmware - firmware context pointer. */
- /* this context pointer will be passed to firmware for all
- * future commands.
- */
- struct ba_context fw_ba_context;
- u8 reset_seq_no; /** 0 or 1**/
- __le16 current_seq;
- /* This is for virtual station in Sta proxy mode for V6FW */
- u8 sta_src_mac_addr[ETH_ALEN];
-} __packed;
-
-/* new transmit sequence number information */
-struct ba_update_seq_num {
- /* BA flags - see above */
- __le32 flags;
- /* returned by firmware in the create ba stream response */
- struct ba_context fw_ba_context;
- /* new sequence number for this block ack stream */
- __le16 ba_seq_num;
-} __packed;
-
-struct ba_stream_context {
- /* BA Stream flags */
- __le32 flags;
- /* returned by firmware in the create ba stream response */
- struct ba_context fw_ba_context;
-} __packed;
-
-union ba_info {
- /* information required to create BA Stream... */
- struct create_ba_params create_params;
- /* update starting/new sequence number etc. */
- struct ba_update_seq_num updt_seq_num;
- /* destroy an existing stream... */
- struct ba_stream_context destroy_params;
- /* destroy an existing stream... */
- struct ba_stream_context flush_params;
-} __packed;
-
-struct hostcmd_cmd_bastream {
- struct hostcmd_header cmd_hdr;
- __le32 action_type;
- union ba_info ba_info;
-} __packed;
-
-/* HOSTCMD_CMD_DWDS_ENABLE */
-struct hostcmd_cmd_dwds_enable {
- struct hostcmd_header cmd_hdr;
- __le32 enable; /* 0 -- Disable. or 1 -- Enable. */
-} __packed;
-
-/* HOSTCMD_CMD_FW_FLUSH_TIMER */
-struct hostcmd_cmd_fw_flush_timer {
- struct hostcmd_header cmd_hdr;
- /* 0 -- Disable. > 0 -- holds time value in usecs. */
- __le32 value;
-} __packed;
-
-/* HOSTCMD_CMD_SET_CDD */
-struct hostcmd_cmd_set_cdd {
- struct hostcmd_header cmd_hdr;
- __le32 enable;
-} __packed;
-
static bool mwl_fwcmd_chk_adapter(struct mwl_priv *priv)
{
u32 regval;
@@ -755,7 +34,7 @@ static bool mwl_fwcmd_chk_adapter(struct mwl_priv *priv)
regval = readl(priv->iobase1 + MACREG_REG_INT_CODE);
if (regval == 0xffffffff) {
- wiphy_err(priv->hw->wiphy, "adapter is not existed");
+ wiphy_err(priv->hw->wiphy, "adapter does not exist\n");
return false;
}
@@ -829,7 +108,7 @@ static int mwl_fwcmd_wait_complete(struct mwl_priv *priv, unsigned short cmd)
} while ((int_code != cmd) && (--curr_iteration));
if (curr_iteration == 0) {
- wiphy_err(priv->hw->wiphy, "cmd 0x%04x=%s timed out",
+ wiphy_err(priv->hw->wiphy, "cmd 0x%04x=%s timed out\n",
cmd, mwl_fwcmd_get_cmd_string(cmd));
return -EIO;
}
@@ -844,7 +123,7 @@ static int mwl_fwcmd_exec_cmd(struct mwl_priv *priv, unsigned short cmd)
bool busy = false;
if (!mwl_fwcmd_chk_adapter(priv)) {
- wiphy_err(priv->hw->wiphy, "no adapter existed");
+ wiphy_err(priv->hw->wiphy, "adapter does not exist\n");
priv->in_send_cmd = false;
return -EIO;
}
@@ -853,13 +132,13 @@ static int mwl_fwcmd_exec_cmd(struct mwl_priv *priv, unsigned short cmd)
priv->in_send_cmd = true;
mwl_fwcmd_send_cmd(priv);
if (mwl_fwcmd_wait_complete(priv, 0x8000 | cmd)) {
- wiphy_err(priv->hw->wiphy, "timeout");
+ wiphy_err(priv->hw->wiphy, "timeout\n");
priv->in_send_cmd = false;
return -EIO;
}
} else {
wiphy_warn(priv->hw->wiphy,
- "previous command is still running");
+ "previous command is still running\n");
busy = true;
}
@@ -873,14 +152,13 @@ static int mwl_fwcmd_802_11_radio_control(struct mwl_priv *priv,
bool enable, bool force)
{
struct hostcmd_cmd_802_11_radio_control *pcmd;
- unsigned long flags;
if (enable == priv->radio_on && !force)
return 0;
pcmd = (struct hostcmd_cmd_802_11_radio_control *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_RADIO_CONTROL);
@@ -891,14 +169,14 @@ static int mwl_fwcmd_802_11_radio_control(struct mwl_priv *priv,
pcmd->radio_on = cpu_to_le16(enable ? WL_ENABLE : WL_DISABLE);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_RADIO_CONTROL)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(priv->hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(priv->hw->wiphy, "failed execution\n");
return -EIO;
}
priv->radio_on = enable;
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -907,12 +185,11 @@ static int mwl_fwcmd_get_tx_powers(struct mwl_priv *priv, u16 *powlist, u16 ch,
u16 band, u16 width, u16 sub_ch)
{
struct hostcmd_cmd_802_11_tx_power *pcmd;
- unsigned long flags;
int i;
pcmd = (struct hostcmd_cmd_802_11_tx_power *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_TX_POWER);
@@ -924,15 +201,15 @@ static int mwl_fwcmd_get_tx_powers(struct mwl_priv *priv, u16 *powlist, u16 ch,
pcmd->sub_ch = cpu_to_le16(sub_ch);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_TX_POWER)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(priv->hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(priv->hw->wiphy, "failed execution\n");
return -EIO;
}
for (i = 0; i < SYSADPT_TX_POWER_LEVEL_TOTAL; i++)
powlist[i] = le16_to_cpu(pcmd->power_level_list[i]);
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -942,12 +219,11 @@ static int mwl_fwcmd_set_tx_powers(struct mwl_priv *priv, u16 txpow[],
u16 width, u16 sub_ch)
{
struct hostcmd_cmd_802_11_tx_power *pcmd;
- unsigned long flags;
int i;
pcmd = (struct hostcmd_cmd_802_11_tx_power *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_TX_POWER);
@@ -962,12 +238,12 @@ static int mwl_fwcmd_set_tx_powers(struct mwl_priv *priv, u16 txpow[],
pcmd->power_level_list[i] = cpu_to_le16(txpow[i]);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_TX_POWER)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(priv->hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(priv->hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -1200,7 +476,6 @@ static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv,
static int mwl_fwcmd_set_ies(struct mwl_priv *priv, struct mwl_vif *mwl_vif)
{
struct hostcmd_cmd_set_ies *pcmd;
- unsigned long flags;
if (!mwl_vif->beacon_info.valid)
return -EINVAL;
@@ -1213,7 +488,7 @@ static int mwl_fwcmd_set_ies(struct mwl_priv *priv, struct mwl_vif *mwl_vif)
pcmd = (struct hostcmd_cmd_set_ies *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_IES);
@@ -1239,18 +514,18 @@ static int mwl_fwcmd_set_ies(struct mwl_priv *priv, struct mwl_vif *mwl_vif)
}
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_IES)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(priv->hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(priv->hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
einval:
- wiphy_err(priv->hw->wiphy, "length of IE is too long");
+ wiphy_err(priv->hw->wiphy, "length of IE is too long\n");
return -EINVAL;
}
@@ -1260,7 +535,6 @@ static int mwl_fwcmd_set_ap_beacon(struct mwl_priv *priv,
struct ieee80211_bss_conf *bss_conf)
{
struct hostcmd_cmd_ap_beacon *pcmd;
- unsigned long flags;
struct ds_params *phy_ds_param_set;
if (!mwl_vif->beacon_info.valid)
@@ -1283,7 +557,7 @@ static int mwl_fwcmd_set_ap_beacon(struct mwl_priv *priv,
pcmd = (struct hostcmd_cmd_ap_beacon *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_AP_BEACON);
@@ -1320,18 +594,18 @@ static int mwl_fwcmd_set_ap_beacon(struct mwl_priv *priv,
SYSADPT_MAX_DATA_RATES_G);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_AP_BEACON)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(priv->hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(priv->hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
ielenerr:
- wiphy_err(priv->hw->wiphy, "length of IE is too long");
+ wiphy_err(priv->hw->wiphy, "length of IE is too long\n");
return -EINVAL;
}
@@ -1382,9 +656,7 @@ static int mwl_fwcmd_encryption_set_cmd_info(struct hostcmd_cmd_set_key *cmd,
void mwl_fwcmd_reset(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
-
- priv = hw->priv;
+ struct mwl_priv *priv = hw->priv;
if (mwl_fwcmd_chk_adapter(priv))
writel(ISR_RESET,
@@ -1393,9 +665,7 @@ void mwl_fwcmd_reset(struct ieee80211_hw *hw)
void mwl_fwcmd_int_enable(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
-
- priv = hw->priv;
+ struct mwl_priv *priv = hw->priv;
if (mwl_fwcmd_chk_adapter(priv)) {
writel(0x00,
@@ -1407,9 +677,7 @@ void mwl_fwcmd_int_enable(struct ieee80211_hw *hw)
void mwl_fwcmd_int_disable(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
-
- priv = hw->priv;
+ struct mwl_priv *priv = hw->priv;
if (mwl_fwcmd_chk_adapter(priv))
writel(0x00,
@@ -1418,19 +686,16 @@ void mwl_fwcmd_int_disable(struct ieee80211_hw *hw)
int mwl_fwcmd_get_hw_specs(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_get_hw_spec *pcmd;
- unsigned long flags;
int retry;
int i;
- priv = hw->priv;
-
pcmd = (struct hostcmd_cmd_get_hw_spec *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
- wiphy_debug(hw->wiphy, "pcmd = %x", (unsigned int)pcmd);
+ wiphy_debug(hw->wiphy, "pcmd = %p\n", pcmd);
memset(pcmd, 0x00, sizeof(*pcmd));
memset(&pcmd->permanent_addr[0], 0xff, ETH_ALEN);
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_GET_HW_SPEC);
@@ -1440,24 +705,22 @@ int mwl_fwcmd_get_hw_specs(struct ieee80211_hw *hw)
retry = 0;
while (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_GET_HW_SPEC)) {
if (retry++ > MAX_WAIT_GET_HW_SPECS_ITERATONS) {
- wiphy_err(hw->wiphy, "can't get hw specs");
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ wiphy_err(hw->wiphy, "can't get hw specs\n");
+ spin_unlock_bh(&priv->fwcmd_lock);
return -EIO;
}
mdelay(1000);
wiphy_debug(hw->wiphy,
- "repeat command = %x", (unsigned int)pcmd);
+ "repeat command = %p\n", pcmd);
}
ether_addr_copy(&priv->hw_data.mac_addr[0], pcmd->permanent_addr);
priv->desc_data[0].wcb_base =
le32_to_cpu(pcmd->wcb_base0) & 0x0000ffff;
-#if SYSADPT_NUM_OF_DESC_DATA > 3
for (i = 1; i < SYSADPT_TOTAL_TX_QUEUES; i++)
priv->desc_data[i].wcb_base =
le32_to_cpu(pcmd->wcb_base[i - 1]) & 0x0000ffff;
-#endif
priv->desc_data[0].rx_desc_read =
le32_to_cpu(pcmd->rxpd_rd_ptr) & 0x0000ffff;
priv->desc_data[0].rx_desc_write =
@@ -1470,51 +733,28 @@ int mwl_fwcmd_get_hw_specs(struct ieee80211_hw *hw)
priv->hw_data.hw_version = pcmd->version;
priv->hw_data.host_interface = pcmd->host_if;
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
int mwl_fwcmd_set_hw_specs(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_set_hw_spec *pcmd;
- unsigned long flags;
int i;
- priv = hw->priv;
-
- /* Info for debugging
- */
- wiphy_info(hw->wiphy, "%s ...", __func__);
- wiphy_info(hw->wiphy, " -->pPhysTxRing[0] = %x",
- priv->desc_data[0].pphys_tx_ring);
- wiphy_info(hw->wiphy, " -->pPhysTxRing[1] = %x",
- priv->desc_data[1].pphys_tx_ring);
- wiphy_info(hw->wiphy, " -->pPhysTxRing[2] = %x",
- priv->desc_data[2].pphys_tx_ring);
- wiphy_info(hw->wiphy, " -->pPhysTxRing[3] = %x",
- priv->desc_data[3].pphys_tx_ring);
- wiphy_info(hw->wiphy, " -->pPhysRxRing = %x",
- priv->desc_data[0].pphys_rx_ring);
- wiphy_info(hw->wiphy, " -->numtxq %d wcbperq %d totalrxwcb %d",
- SYSADPT_NUM_OF_DESC_DATA,
- SYSADPT_MAX_NUM_TX_DESC,
- SYSADPT_MAX_NUM_RX_DESC);
-
pcmd = (struct hostcmd_cmd_set_hw_spec *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_HW_SPEC);
pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
pcmd->wcb_base[0] = cpu_to_le32(priv->desc_data[0].pphys_tx_ring);
-#if SYSADPT_NUM_OF_DESC_DATA > 3
for (i = 1; i < SYSADPT_TOTAL_TX_QUEUES; i++)
pcmd->wcb_base[i] =
cpu_to_le32(priv->desc_data[i].pphys_tx_ring);
-#endif
pcmd->tx_wcb_num_per_queue = cpu_to_le32(SYSADPT_MAX_NUM_TX_DESC);
pcmd->num_tx_queues = cpu_to_le32(SYSADPT_NUM_OF_DESC_DATA);
pcmd->total_rx_wcb = cpu_to_le32(SYSADPT_MAX_NUM_RX_DESC);
@@ -1522,12 +762,12 @@ int mwl_fwcmd_set_hw_specs(struct ieee80211_hw *hw)
pcmd->features = 0;
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_HW_SPEC)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -1535,23 +775,20 @@ int mwl_fwcmd_set_hw_specs(struct ieee80211_hw *hw)
int mwl_fwcmd_get_stat(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_802_11_get_stat *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_802_11_get_stat *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_GET_STAT);
pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_GET_STAT)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
@@ -1564,7 +801,7 @@ int mwl_fwcmd_get_stat(struct ieee80211_hw *hw,
stats->dot11RTSSuccessCount =
le32_to_cpu(pcmd->rts_successes);
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -1581,11 +818,9 @@ int mwl_fwcmd_radio_disable(struct ieee80211_hw *hw)
int mwl_fwcmd_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
int rc;
- priv = hw->priv;
-
priv->radio_short_preamble = short_preamble;
rc = mwl_fwcmd_802_11_radio_control(priv, true, true);
@@ -1596,15 +831,13 @@ int mwl_fwcmd_max_tx_power(struct ieee80211_hw *hw,
struct ieee80211_conf *conf, u8 fraction)
{
struct ieee80211_channel *channel = conf->chandef.chan;
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
int reduce_val = 0;
u16 band = 0, width = 0, sub_ch = 0;
u16 maxtxpow[SYSADPT_TX_POWER_LEVEL_TOTAL];
int i, tmp;
int rc;
- priv = hw->priv;
-
switch (fraction) {
case 0:
reduce_val = 0; /* Max */
@@ -1683,7 +916,7 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw,
struct ieee80211_conf *conf, u8 fraction)
{
struct ieee80211_channel *channel = conf->chandef.chan;
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
int reduce_val = 0;
u16 band = 0, width = 0, sub_ch = 0;
u16 txpow[SYSADPT_TX_POWER_LEVEL_TOTAL];
@@ -1691,8 +924,6 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw,
int i, tmp;
int rc;
- priv = hw->priv;
-
switch (fraction) {
case 0:
reduce_val = 0; /* Max */
@@ -1814,15 +1045,12 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw,
int mwl_fwcmd_rf_antenna(struct ieee80211_hw *hw, int dir, int antenna)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_802_11_rf_antenna *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_802_11_rf_antenna *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_RF_ANTENNA);
@@ -1847,12 +1075,12 @@ int mwl_fwcmd_rf_antenna(struct ieee80211_hw *hw, int dir, int antenna)
}
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_RF_ANTENNA)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -1860,17 +1088,15 @@ int mwl_fwcmd_rf_antenna(struct ieee80211_hw *hw, int dir, int antenna)
int mwl_fwcmd_broadcast_ssid_enable(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, bool enable)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_broadcast_ssid_enable *pcmd;
- unsigned long flags;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_broadcast_ssid_enable *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BROADCAST_SSID_ENABLE);
@@ -1879,12 +1105,12 @@ int mwl_fwcmd_broadcast_ssid_enable(struct ieee80211_hw *hw,
pcmd->enable = cpu_to_le32(enable);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BROADCAST_SSID_ENABLE)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -1893,16 +1119,13 @@ int mwl_fwcmd_set_rf_channel(struct ieee80211_hw *hw,
struct ieee80211_conf *conf)
{
struct ieee80211_channel *channel = conf->chandef.chan;
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_set_rf_channel *pcmd;
- unsigned long flags;
u32 chnl_flags, freq_band, chnl_width, act_primary;
- priv = hw->priv;
-
pcmd = (struct hostcmd_cmd_set_rf_channel *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_RF_CHANNEL);
@@ -1910,12 +1133,14 @@ int mwl_fwcmd_set_rf_channel(struct ieee80211_hw *hw,
pcmd->action = cpu_to_le16(WL_SET);
pcmd->curr_chnl = channel->hw_value;
- if (channel->band == IEEE80211_BAND_2GHZ)
+ if (channel->band == IEEE80211_BAND_2GHZ) {
freq_band = FREQ_BAND_2DOT4GHZ;
- else if (channel->band == IEEE80211_BAND_5GHZ)
+ } else if (channel->band == IEEE80211_BAND_5GHZ) {
freq_band = FREQ_BAND_5GHZ;
- else
+ } else {
+ spin_unlock_bh(&priv->fwcmd_lock);
return -EINVAL;
+ }
switch (conf->chandef.width) {
case NL80211_CHAN_WIDTH_20_NOHT:
@@ -1936,6 +1161,7 @@ int mwl_fwcmd_set_rf_channel(struct ieee80211_hw *hw,
mwl_fwcmd_get_80m_pri_chnl_offset(pcmd->curr_chnl);
break;
default:
+ spin_unlock_bh(&priv->fwcmd_lock);
return -EINVAL;
}
@@ -1946,12 +1172,12 @@ int mwl_fwcmd_set_rf_channel(struct ieee80211_hw *hw,
pcmd->chnl_flags = cpu_to_le32(chnl_flags);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_RF_CHANNEL)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -1959,17 +1185,15 @@ int mwl_fwcmd_set_rf_channel(struct ieee80211_hw *hw,
int mwl_fwcmd_set_aid(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u8 *bssid, u16 aid)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_set_aid *pcmd;
- unsigned long flags;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_set_aid *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_AID);
@@ -1979,12 +1203,12 @@ int mwl_fwcmd_set_aid(struct ieee80211_hw *hw,
ether_addr_copy(pcmd->mac_addr, bssid);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_AID)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -1992,17 +1216,15 @@ int mwl_fwcmd_set_aid(struct ieee80211_hw *hw,
int mwl_fwcmd_set_infra_mode(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_set_infra_mode *pcmd;
- unsigned long flags;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_set_infra_mode *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_INFRA_MODE);
@@ -2010,27 +1232,24 @@ int mwl_fwcmd_set_infra_mode(struct ieee80211_hw *hw,
pcmd->cmd_hdr.macid = mwl_vif->macid;
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_INFRA_MODE)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
int mwl_fwcmd_set_rts_threshold(struct ieee80211_hw *hw, int threshold)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_802_11_rts_thsd *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_802_11_rts_thsd *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_RTS_THSD);
@@ -2039,12 +1258,12 @@ int mwl_fwcmd_set_rts_threshold(struct ieee80211_hw *hw, int threshold)
pcmd->threshold = cpu_to_le16(threshold);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_RTS_THSD)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2052,15 +1271,12 @@ int mwl_fwcmd_set_rts_threshold(struct ieee80211_hw *hw, int threshold)
int mwl_fwcmd_set_edca_params(struct ieee80211_hw *hw, u8 index,
u16 cw_min, u16 cw_max, u8 aifs, u16 txop)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_set_edca_params *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_set_edca_params *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_EDCA_PARAMS);
@@ -2083,27 +1299,24 @@ int mwl_fwcmd_set_edca_params(struct ieee80211_hw *hw, u8 index,
pcmd->txq_num = 0;
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_EDCA_PARAMS)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
int mwl_fwcmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_set_wmm_mode *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_set_wmm_mode *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_WMM_MODE);
@@ -2111,27 +1324,24 @@ int mwl_fwcmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable)
pcmd->action = cpu_to_le16(enable ? WL_ENABLE : WL_DISABLE);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_WMM_MODE)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
int mwl_fwcmd_use_fixed_rate(struct ieee80211_hw *hw, int mcast, int mgmt)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_set_fixed_rate *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_set_fixed_rate *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_FIXED_RATE);
@@ -2142,27 +1352,24 @@ int mwl_fwcmd_use_fixed_rate(struct ieee80211_hw *hw, int mcast, int mgmt)
pcmd->management_rate = mgmt;
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_FIXED_RATE)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
int mwl_fwcmd_set_rate_adapt_mode(struct ieee80211_hw *hw, u16 mode)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_set_rate_adapt_mode *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_set_rate_adapt_mode *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_RATE_ADAPT_MODE);
@@ -2171,12 +1378,12 @@ int mwl_fwcmd_set_rate_adapt_mode(struct ieee80211_hw *hw, u16 mode)
pcmd->rate_adapt_mode = cpu_to_le16(mode);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_RATE_ADAPT_MODE)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2184,17 +1391,15 @@ int mwl_fwcmd_set_rate_adapt_mode(struct ieee80211_hw *hw, u16 mode)
int mwl_fwcmd_set_mac_addr_client(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u8 *mac_addr)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_set_mac_addr *pcmd;
- unsigned long flags;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_set_mac_addr *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_MAC_ADDR);
@@ -2204,41 +1409,38 @@ int mwl_fwcmd_set_mac_addr_client(struct ieee80211_hw *hw,
ether_addr_copy(pcmd->mac_addr, mac_addr);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_MAC_ADDR)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
int mwl_fwcmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_get_watchdog_bitmap *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_get_watchdog_bitmap *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_GET_WATCHDOG_BITMAP);
pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_GET_WATCHDOG_BITMAP)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
*bitmap = pcmd->watchdog_bitmap;
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2246,17 +1448,15 @@ int mwl_fwcmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap)
int mwl_fwcmd_remove_mac_addr(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u8 *mac_addr)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_set_mac_addr *pcmd;
- unsigned long flags;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_set_mac_addr *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_DEL_MAC_ADDR);
@@ -2265,12 +1465,12 @@ int mwl_fwcmd_remove_mac_addr(struct ieee80211_hw *hw,
ether_addr_copy(pcmd->mac_addr, mac_addr);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_DEL_MAC_ADDR)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2278,12 +1478,10 @@ int mwl_fwcmd_remove_mac_addr(struct ieee80211_hw *hw,
int mwl_fwcmd_bss_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, bool enable)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_bss_start *pcmd;
- unsigned long flags;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
if (enable && (priv->running_bsses & (1 << mwl_vif->macid)))
@@ -2294,7 +1492,7 @@ int mwl_fwcmd_bss_start(struct ieee80211_hw *hw,
pcmd = (struct hostcmd_cmd_bss_start *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BSS_START);
@@ -2311,8 +1509,8 @@ int mwl_fwcmd_bss_start(struct ieee80211_hw *hw,
}
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BSS_START)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
@@ -2321,7 +1519,7 @@ int mwl_fwcmd_bss_start(struct ieee80211_hw *hw,
else
priv->running_bsses &= ~(1 << mwl_vif->macid);
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2329,10 +1527,9 @@ int mwl_fwcmd_bss_start(struct ieee80211_hw *hw,
int mwl_fwcmd_set_beacon(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u8 *beacon, int len)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
mwl_fwcmd_parse_beacon(priv, mwl_vif, beacon, len);
@@ -2358,18 +1555,16 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_set_new_stn *pcmd;
- unsigned long flags;
u32 rates;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_set_new_stn *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_NEW_STN);
@@ -2377,7 +1572,7 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw,
pcmd->cmd_hdr.macid = mwl_vif->macid;
pcmd->action = cpu_to_le16(HOSTCMD_ACT_STA_ACTION_ADD);
- if (mwl_vif->is_sta) {
+ if (vif->type == NL80211_IFTYPE_STATION) {
pcmd->aid = 0;
pcmd->stn_id = 0;
} else {
@@ -2415,22 +1610,22 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw,
pcmd->qos_info = ((sta->uapsd_queues << 4) | (sta->max_sp << 1));
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- if (mwl_vif->is_sta) {
+ if (vif->type == NL80211_IFTYPE_STATION) {
ether_addr_copy(pcmd->mac_addr, mwl_vif->sta_mac);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2438,17 +1633,15 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw,
int mwl_fwcmd_set_new_stn_add_self(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_set_new_stn *pcmd;
- unsigned long flags;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_set_new_stn *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_NEW_STN);
@@ -2459,12 +1652,12 @@ int mwl_fwcmd_set_new_stn_add_self(struct ieee80211_hw *hw,
ether_addr_copy(pcmd->mac_addr, vif->addr);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2472,17 +1665,15 @@ int mwl_fwcmd_set_new_stn_add_self(struct ieee80211_hw *hw,
int mwl_fwcmd_set_new_stn_del(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u8 *addr)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_set_new_stn *pcmd;
- unsigned long flags;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_set_new_stn *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_NEW_STN);
@@ -2493,37 +1684,34 @@ int mwl_fwcmd_set_new_stn_del(struct ieee80211_hw *hw,
ether_addr_copy(pcmd->mac_addr, addr);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- if (mwl_vif->is_sta) {
+ if (vif->type == NL80211_IFTYPE_STATION) {
ether_addr_copy(pcmd->mac_addr, mwl_vif->sta_mac);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
int mwl_fwcmd_set_apmode(struct ieee80211_hw *hw, u8 apmode)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_set_apmode *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_set_apmode *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_APMODE);
@@ -2531,12 +1719,12 @@ int mwl_fwcmd_set_apmode(struct ieee80211_hw *hw, u8 apmode)
pcmd->apmode = apmode;
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_APMODE)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2545,17 +1733,15 @@ int mwl_fwcmd_update_encryption_enable(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u8 *addr, u8 encr_type)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_update_encryption *pcmd;
- unsigned long flags;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_update_encryption *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_UPDATE_ENCRYPTION);
@@ -2567,25 +1753,25 @@ int mwl_fwcmd_update_encryption_enable(struct ieee80211_hw *hw,
pcmd->action_data[0] = encr_type;
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- if (mwl_vif->is_sta) {
+ if (vif->type == NL80211_IFTYPE_STATION) {
if (memcmp(mwl_vif->bssid, addr, ETH_ALEN) == 0)
ether_addr_copy(pcmd->mac_addr, mwl_vif->sta_mac);
else
ether_addr_copy(pcmd->mac_addr, mwl_vif->bssid);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2594,21 +1780,19 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u8 *addr,
struct ieee80211_key_conf *key)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_set_key *pcmd;
- unsigned long flags;
int rc;
int keymlen;
u32 action;
u8 idx;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_set_key *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_UPDATE_ENCRYPTION);
@@ -2617,8 +1801,8 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw,
rc = mwl_fwcmd_encryption_set_cmd_info(pcmd, addr, key);
if (rc) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "encryption not support");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "encryption not support\n");
return rc;
}
@@ -2648,8 +1832,8 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw,
keymlen = key->keylen;
break;
default:
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "encryption not support");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "encryption not support\n");
return -ENOTSUPP;
}
@@ -2657,12 +1841,12 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw,
pcmd->action_type = cpu_to_le32(action);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- if (mwl_vif->is_sta) {
+ if (vif->type == NL80211_IFTYPE_STATION) {
if (memcmp(mwl_vif->bssid, addr, ETH_ALEN) == 0)
ether_addr_copy(pcmd->key_param.mac_addr,
mwl_vif->sta_mac);
@@ -2671,13 +1855,13 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw,
mwl_vif->bssid);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2686,18 +1870,16 @@ int mwl_fwcmd_encryption_remove_key(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u8 *addr,
struct ieee80211_key_conf *key)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_set_key *pcmd;
- unsigned long flags;
int rc;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_set_key *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_UPDATE_ENCRYPTION);
@@ -2706,8 +1888,8 @@ int mwl_fwcmd_encryption_remove_key(struct ieee80211_hw *hw,
rc = mwl_fwcmd_encryption_set_cmd_info(pcmd, addr, key);
if (rc) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "encryption not support");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "encryption not support\n");
return rc;
}
@@ -2718,12 +1900,12 @@ int mwl_fwcmd_encryption_remove_key(struct ieee80211_hw *hw,
mwl_vif->wep_key_conf[key->keyidx].enabled = 0;
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2732,18 +1914,16 @@ int mwl_fwcmd_check_ba(struct ieee80211_hw *hw,
struct mwl_ampdu_stream *stream,
struct ieee80211_vif *vif)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_bastream *pcmd;
- unsigned long flags;
u32 ba_flags, ba_type, ba_direction;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_bastream *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BASTREAM);
@@ -2763,18 +1943,18 @@ int mwl_fwcmd_check_ba(struct ieee80211_hw *hw,
pcmd->ba_info.create_params.queue_id = stream->idx;
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BASTREAM)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
if (pcmd->cmd_hdr.result != 0) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "result error");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "check ba result error\n");
return -EINVAL;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2783,18 +1963,16 @@ int mwl_fwcmd_create_ba(struct ieee80211_hw *hw,
struct mwl_ampdu_stream *stream,
u8 buf_size, struct ieee80211_vif *vif)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct hostcmd_cmd_bastream *pcmd;
- unsigned long flags;
u32 ba_flags, ba_type, ba_direction;
- priv = hw->priv;
mwl_vif = mwl_dev_get_vif(vif);
pcmd = (struct hostcmd_cmd_bastream *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BASTREAM);
@@ -2823,18 +2001,18 @@ int mwl_fwcmd_create_ba(struct ieee80211_hw *hw,
pcmd->ba_info.create_params.current_seq = cpu_to_le16(0);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BASTREAM)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
if (pcmd->cmd_hdr.result != 0) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "result error");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "create ba result error\n");
return -EINVAL;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2842,16 +2020,13 @@ int mwl_fwcmd_create_ba(struct ieee80211_hw *hw,
int mwl_fwcmd_destroy_ba(struct ieee80211_hw *hw,
u8 idx)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_bastream *pcmd;
- unsigned long flags;
u32 ba_flags, ba_type, ba_direction;
- priv = hw->priv;
-
pcmd = (struct hostcmd_cmd_bastream *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BASTREAM);
@@ -2866,12 +2041,12 @@ int mwl_fwcmd_destroy_ba(struct ieee80211_hw *hw,
pcmd->ba_info.destroy_params.fw_ba_context.context = cpu_to_le32(idx);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BASTREAM)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
@@ -2881,12 +2056,10 @@ struct mwl_ampdu_stream *mwl_fwcmd_add_stream(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
u8 tid)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_ampdu_stream *stream;
int i;
- priv = hw->priv;
-
for (i = 0; i < SYSADPT_TX_AMPDU_QUEUES; i++) {
stream = &priv->ampdu[i];
@@ -2921,12 +2094,10 @@ void mwl_fwcmd_remove_stream(struct ieee80211_hw *hw,
struct mwl_ampdu_stream *mwl_fwcmd_lookup_stream(struct ieee80211_hw *hw,
u8 *addr, u8 tid)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct mwl_ampdu_stream *stream;
int i;
- priv = hw->priv;
-
for (i = 0; i < SYSADPT_TX_AMPDU_QUEUES; i++) {
stream = &priv->ampdu[i];
@@ -2958,15 +2129,12 @@ bool mwl_fwcmd_ampdu_allowed(struct ieee80211_sta *sta, u8 tid)
int mwl_fwcmd_set_dwds_stamode(struct ieee80211_hw *hw, bool enable)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_dwds_enable *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_dwds_enable *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_DWDS_ENABLE);
@@ -2974,27 +2142,24 @@ int mwl_fwcmd_set_dwds_stamode(struct ieee80211_hw *hw, bool enable)
pcmd->enable = cpu_to_le32(enable);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_DWDS_ENABLE)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
int mwl_fwcmd_set_fw_flush_timer(struct ieee80211_hw *hw, u32 value)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_fw_flush_timer *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_fw_flush_timer *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_FW_FLUSH_TIMER);
@@ -3002,27 +2167,24 @@ int mwl_fwcmd_set_fw_flush_timer(struct ieee80211_hw *hw, u32 value)
pcmd->value = cpu_to_le32(value);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_FW_FLUSH_TIMER)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
int mwl_fwcmd_set_cdd(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
struct hostcmd_cmd_set_cdd *pcmd;
- unsigned long flags;
-
- priv = hw->priv;
pcmd = (struct hostcmd_cmd_set_cdd *)&priv->pcmd_buf[0];
- spin_lock_irqsave(&priv->fwcmd_lock, flags);
+ spin_lock_bh(&priv->fwcmd_lock);
memset(pcmd, 0x00, sizeof(*pcmd));
pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_CDD);
@@ -3030,12 +2192,12 @@ int mwl_fwcmd_set_cdd(struct ieee80211_hw *hw)
pcmd->enable = cpu_to_le32(priv->cdd);
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_CDD)) {
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
- wiphy_err(hw->wiphy, "failed execution");
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(hw->wiphy, "failed execution\n");
return -EIO;
}
- spin_unlock_irqrestore(&priv->fwcmd_lock, flags);
+ spin_unlock_bh(&priv->fwcmd_lock);
return 0;
}
diff --git a/fwcmd.h b/fwcmd.h
index 247b01f..6b8ec74 100644
--- a/fwcmd.h
+++ b/fwcmd.h
@@ -1,16 +1,24 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file defines firmware host command related functions.
+/* Description: This file defines firmware host command related
+ * functions.
*/
-#ifndef _mwl_fwcmd_h_
-#define _mwl_fwcmd_h_
+#ifndef _fwcmd_h_
+#define _fwcmd_h_
/* Define OpMode for SoftAP/Station mode
*
@@ -164,4 +172,4 @@ int mwl_fwcmd_set_fw_flush_timer(struct ieee80211_hw *hw, u32 value);
int mwl_fwcmd_set_cdd(struct ieee80211_hw *hw);
-#endif /* _mwl_fwcmd_h_ */
+#endif /* _fwcmd_h_ */
diff --git a/fwdl.c b/fwdl.c
index f3826cf..48c8c3e 100644
--- a/fwdl.c
+++ b/fwdl.c
@@ -1,12 +1,20 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file implements firmware download related functions.
+/* Description: This file implements firmware download related
+ * functions.
*/
#include <linux/io.h>
@@ -43,14 +51,13 @@ static void mwl_fwdl_trig_pcicmd_bootcode(struct mwl_priv *priv)
int mwl_fwdl_download_firmware(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
const struct firmware *fw;
u32 curr_iteration = 0;
u32 size_fw_downloaded = 0;
u32 int_code = 0;
u32 len = 0;
- priv = hw->priv;
fw = priv->fw_ucode;
mwl_fwcmd_reset(hw);
@@ -72,7 +79,7 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw)
* reside on its respective blocks such as ITCM, DTCM, SQRAM,
* (or even DDR, AFTER DDR is init'd before fw download
*/
- wiphy_info(hw->wiphy, "fw download start 88");
+ wiphy_info(hw->wiphy, "fw download start 88\n");
/* Disable PFU before FWDL */
writel(0x100, priv->iobase1 + 0xE0E4);
@@ -126,7 +133,7 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw)
* download failed
*/
wiphy_err(hw->wiphy,
- "Exhausted curr_iteration for fw download");
+ "Exhausted curr_iteration for fw download\n");
goto err_download;
}
@@ -134,7 +141,7 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw)
}
wiphy_info(hw->wiphy,
- "FwSize = %d downloaded Size = %d curr_iteration %d",
+ "FwSize = %d downloaded Size = %d curr_iteration %d\n",
(int)fw->size, size_fw_downloaded, curr_iteration);
/* Now firware is downloaded successfully, so this part is to check
@@ -143,7 +150,7 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw)
* downloaded fw crashes, this signature checking will fail. This
* part is similar as SC1
*/
- writew(0x00, &priv->pcmd_buf[1]);
+ *((u32 *)&priv->pcmd_buf[1]) = 0;
mwl_fwdl_trig_pcicmd(priv);
curr_iteration = FW_MAX_NUM_CHECKS;
do {
@@ -158,11 +165,11 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw)
if (curr_iteration == 0) {
wiphy_err(hw->wiphy,
- "Exhausted curr_iteration for fw signature");
+ "Exhausted curr_iteration for fw signature\n");
goto err_download;
}
- wiphy_info(hw->wiphy, "complete");
+ wiphy_info(hw->wiphy, "complete\n");
writel(0x00, priv->iobase1 + MACREG_REG_INT_CODE);
return 0;
diff --git a/fwdl.h b/fwdl.h
index dc3c3f0..b117142 100644
--- a/fwdl.h
+++ b/fwdl.h
@@ -1,19 +1,25 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file defines firmware download related functions.
+/* Description: This file defines firmware download related
+ * functions.
*/
-#ifndef _mwl_fwdl_h_
-#define _mwl_fwdl_h_
-
-#include <net/mac80211.h>
+#ifndef _fwdl_h_
+#define _fwdl_h_
int mwl_fwdl_download_firmware(struct ieee80211_hw *hw);
-#endif /* _mwl_fwdl_h_ */
+#endif /* _fwdl_h_ */
diff --git a/hostcmd.h b/hostcmd.h
new file mode 100644
index 0000000..d9db0ee
--- /dev/null
+++ b/hostcmd.h
@@ -0,0 +1,753 @@
+/*
+ * Copyright (C) 2006-2015, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+/* Description: This file defines firmware host command related
+ * structure.
+ */
+
+#ifndef _hostcmd_h_
+#define _hostcmd_h_
+
+/* 16 bit host command code */
+#define HOSTCMD_CMD_GET_HW_SPEC 0x0003
+#define HOSTCMD_CMD_SET_HW_SPEC 0x0004
+#define HOSTCMD_CMD_802_11_GET_STAT 0x0014
+#define HOSTCMD_CMD_802_11_RADIO_CONTROL 0x001c
+#define HOSTCMD_CMD_802_11_TX_POWER 0x001f
+#define HOSTCMD_CMD_802_11_RF_ANTENNA 0x0020
+#define HOSTCMD_CMD_BROADCAST_SSID_ENABLE 0x0050 /* per-vif */
+#define HOSTCMD_CMD_SET_RF_CHANNEL 0x010a
+#define HOSTCMD_CMD_SET_AID 0x010d /* per-vif */
+#define HOSTCMD_CMD_SET_INFRA_MODE 0x010e /* per-vif */
+#define HOSTCMD_CMD_802_11_RTS_THSD 0x0113
+#define HOSTCMD_CMD_SET_EDCA_PARAMS 0x0115
+#define HOSTCMD_CMD_SET_WMM_MODE 0x0123
+#define HOSTCMD_CMD_SET_FIXED_RATE 0x0126
+#define HOSTCMD_CMD_SET_IES 0x0127
+#define HOSTCMD_CMD_SET_MAC_ADDR 0x0202 /* per-vif */
+#define HOSTCMD_CMD_SET_RATE_ADAPT_MODE 0x0203
+#define HOSTCMD_CMD_GET_WATCHDOG_BITMAP 0x0205
+#define HOSTCMD_CMD_DEL_MAC_ADDR 0x0206 /* pre-vif */
+#define HOSTCMD_CMD_BSS_START 0x1100 /* per-vif */
+#define HOSTCMD_CMD_AP_BEACON 0x1101 /* per-vif */
+#define HOSTCMD_CMD_SET_NEW_STN 0x1111 /* per-vif */
+#define HOSTCMD_CMD_SET_APMODE 0x1114
+#define HOSTCMD_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */
+#define HOSTCMD_CMD_BASTREAM 0x1125
+#define HOSTCMD_CMD_DWDS_ENABLE 0x1144
+#define HOSTCMD_CMD_FW_FLUSH_TIMER 0x1148
+#define HOSTCMD_CMD_SET_CDD 0x1150
+
+/* Define general result code for each command */
+#define HOSTCMD_RESULT_OK 0x0000
+/* General error */
+#define HOSTCMD_RESULT_ERROR 0x0001
+/* Command is not valid */
+#define HOSTCMD_RESULT_NOT_SUPPORT 0x0002
+/* Command is pending (will be processed) */
+#define HOSTCMD_RESULT_PENDING 0x0003
+/* System is busy (command ignored) */
+#define HOSTCMD_RESULT_BUSY 0x0004
+/* Data buffer is not big enough */
+#define HOSTCMD_RESULT_PARTIAL_DATA 0x0005
+
+/* Define channel related constants */
+#define FREQ_BAND_2DOT4GHZ 0x1
+#define FREQ_BAND_4DOT9GHZ 0x2
+#define FREQ_BAND_5GHZ 0x4
+#define FREQ_BAND_5DOT2GHZ 0x8
+#define CH_AUTO_WIDTH 0
+#define CH_10_MHZ_WIDTH 0x1
+#define CH_20_MHZ_WIDTH 0x2
+#define CH_40_MHZ_WIDTH 0x4
+#define CH_80_MHZ_WIDTH 0x5
+#define EXT_CH_ABOVE_CTRL_CH 0x1
+#define EXT_CH_AUTO 0x2
+#define EXT_CH_BELOW_CTRL_CH 0x3
+#define NO_EXT_CHANNEL 0x0
+
+#define ACT_PRIMARY_CHAN_0 0
+#define ACT_PRIMARY_CHAN_1 1
+#define ACT_PRIMARY_CHAN_2 2
+#define ACT_PRIMARY_CHAN_3 3
+
+/* Define rate related constants */
+#define HOSTCMD_ACT_NOT_USE_FIXED_RATE 0x0002
+
+/* Define station related constants */
+#define HOSTCMD_ACT_STA_ACTION_ADD 0
+#define HOSTCMD_ACT_STA_ACTION_REMOVE 2
+
+/* Define key related constants */
+#define MAX_ENCR_KEY_LENGTH 16
+#define MIC_KEY_LENGTH 8
+
+#define KEY_TYPE_ID_WEP 0x00
+#define KEY_TYPE_ID_TKIP 0x01
+#define KEY_TYPE_ID_AES 0x02
+
+#define ENCR_KEY_FLAG_TXGROUPKEY 0x00000004
+#define ENCR_KEY_FLAG_PAIRWISE 0x00000008
+#define ENCR_KEY_FLAG_TSC_VALID 0x00000040
+#define ENCR_KEY_FLAG_WEP_TXKEY 0x01000000
+#define ENCR_KEY_FLAG_MICKEY_VALID 0x02000000
+
+/* Define block ack related constants */
+#define BASTREAM_FLAG_IMMEDIATE_TYPE 1
+#define BASTREAM_FLAG_DIRECTION_UPSTREAM 0
+
+/* Define general purpose action */
+#define HOSTCMD_ACT_GEN_SET 0x0001
+#define HOSTCMD_ACT_GEN_SET_LIST 0x0002
+#define HOSTCMD_ACT_GEN_GET_LIST 0x0003
+
+/* Misc */
+#define MAX_ENCR_KEY_LENGTH 16
+#define MIC_KEY_LENGTH 8
+
+enum {
+ WL_DISABLE = 0,
+ WL_ENABLE = 1,
+ WL_DISABLE_VMAC = 0x80,
+};
+
+enum {
+ WL_GET = 0,
+ WL_SET = 1,
+ WL_RESET = 2,
+};
+
+enum {
+ WL_LONG_PREAMBLE = 1,
+ WL_SHORT_PREAMBLE = 3,
+ WL_AUTO_PREAMBLE = 5,
+};
+
+enum encr_action_type {
+ /* request to enable/disable HW encryption */
+ ENCR_ACTION_ENABLE_HW_ENCR,
+ /* request to set encryption key */
+ ENCR_ACTION_TYPE_SET_KEY,
+ /* request to remove one or more keys */
+ ENCR_ACTION_TYPE_REMOVE_KEY,
+ ENCR_ACTION_TYPE_SET_GROUP_KEY,
+};
+
+enum ba_action_type {
+ BA_CREATE_STREAM,
+ BA_UPDATE_STREAM,
+ BA_DESTROY_STREAM,
+ BA_FLUSH_STREAM,
+ BA_CHECK_STREAM,
+};
+
+enum mac_type {
+ WL_MAC_TYPE_PRIMARY_CLIENT,
+ WL_MAC_TYPE_SECONDARY_CLIENT,
+ WL_MAC_TYPE_PRIMARY_AP,
+ WL_MAC_TYPE_SECONDARY_AP,
+};
+
+/* General host command header */
+struct hostcmd_header {
+ __le16 cmd;
+ __le16 len;
+ u8 seq_num;
+ u8 macid;
+ __le16 result;
+} __packed;
+
+/* HOSTCMD_CMD_GET_HW_SPEC */
+struct hostcmd_cmd_get_hw_spec {
+ struct hostcmd_header cmd_hdr;
+ u8 version; /* version of the HW */
+ u8 host_if; /* host interface */
+ __le16 num_wcb; /* Max. number of WCB FW can handle */
+ __le16 num_mcast_addr; /* MaxNbr of MC addresses FW can handle */
+ u8 permanent_addr[ETH_ALEN]; /* MAC address programmed in HW */
+ __le16 region_code;
+ __le16 num_antenna; /* Number of antenna used */
+ __le32 fw_release_num; /* 4 byte of FW release number */
+ __le32 wcb_base0;
+ __le32 rxpd_wr_ptr;
+ __le32 rxpd_rd_ptr;
+ __le32 fw_awake_cookie;
+ __le32 wcb_base[SYSADPT_TOTAL_TX_QUEUES - 1];
+} __packed;
+
+/* HOSTCMD_CMD_SET_HW_SPEC */
+struct hostcmd_cmd_set_hw_spec {
+ struct hostcmd_header cmd_hdr;
+ /* HW revision */
+ u8 version;
+ /* Host interface */
+ u8 host_if;
+ /* Max. number of Multicast address FW can handle */
+ __le16 num_mcast_addr;
+ /* MAC address */
+ u8 permanent_addr[ETH_ALEN];
+ /* Region Code */
+ __le16 region_code;
+ /* 4 byte of FW release number, example 0x1234=1.2.3.4 */
+ __le32 fw_release_num;
+ /* Firmware awake cookie - used to ensure that the device
+ * is not in sleep mode
+ */
+ __le32 fw_awake_cookie;
+ /* Device capabilities (see above) */
+ __le32 device_caps;
+ /* Rx shared memory queue */
+ __le32 rxpd_wr_ptr;
+ /* Actual number of TX queues in WcbBase array */
+ __le32 num_tx_queues;
+ /* TX WCB Rings */
+ __le32 wcb_base[SYSADPT_NUM_OF_DESC_DATA];
+ /* Max AMSDU size (00 - AMSDU Disabled,
+ * 01 - 4K, 10 - 8K, 11 - not defined)
+ */
+ __le32 features;
+ __le32 tx_wcb_num_per_queue;
+ __le32 total_rx_wcb;
+} __packed;
+
+/* HOSTCMD_CMD_802_11_GET_STAT */
+struct hostcmd_cmd_802_11_get_stat {
+ struct hostcmd_header cmd_hdr;
+ __le32 tx_retry_successes;
+ __le32 tx_multiple_retry_successes;
+ __le32 tx_failures;
+ __le32 rts_successes;
+ __le32 rts_failures;
+ __le32 ack_failures;
+ __le32 rx_duplicate_frames;
+ __le32 rx_fcs_errors;
+ __le32 tx_watchdog_timeouts;
+ __le32 rx_overflows;
+ __le32 rx_frag_errors;
+ __le32 rx_mem_errors;
+ __le32 pointer_errors;
+ __le32 tx_underflows;
+ __le32 tx_done;
+ __le32 tx_done_buf_try_put;
+ __le32 tx_done_buf_put;
+ /* Put size of requested buffer in here */
+ __le32 wait_for_tx_buf;
+ __le32 tx_attempts;
+ __le32 tx_successes;
+ __le32 tx_fragments;
+ __le32 tx_multicasts;
+ __le32 rx_non_ctl_pkts;
+ __le32 rx_multicasts;
+ __le32 rx_undecryptable_frames;
+ __le32 rx_icv_errors;
+ __le32 rx_excluded_frames;
+ __le32 rx_weak_iv_count;
+ __le32 rx_unicasts;
+ __le32 rx_bytes;
+ __le32 rx_errors;
+ __le32 rx_rts_count;
+ __le32 tx_cts_count;
+} __packed;
+
+/* HOSTCMD_CMD_802_11_RADIO_CONTROL */
+struct hostcmd_cmd_802_11_radio_control {
+ struct hostcmd_header cmd_hdr;
+ __le16 action;
+ /* @bit0: 1/0,on/off, @bit1: 1/0, long/short @bit2: 1/0,auto/fix */
+ __le16 control;
+ __le16 radio_on;
+} __packed;
+
+/* HOSTCMD_CMD_802_11_TX_POWER */
+struct hostcmd_cmd_802_11_tx_power {
+ struct hostcmd_header cmd_hdr;
+ __le16 action;
+ __le16 band;
+ __le16 ch;
+ __le16 bw;
+ __le16 sub_ch;
+ __le16 power_level_list[SYSADPT_TX_POWER_LEVEL_TOTAL];
+} __packed;
+
+/* HOSTCMD_CMD_802_11_RF_ANTENNA */
+struct hostcmd_cmd_802_11_rf_antenna {
+ struct hostcmd_header cmd_hdr;
+ __le16 action;
+ __le16 antenna_mode; /* Number of antennas or 0xffff(diversity) */
+} __packed;
+
+/* HOSTCMD_CMD_BROADCAST_SSID_ENABLE */
+struct hostcmd_cmd_broadcast_ssid_enable {
+ struct hostcmd_header cmd_hdr;
+ __le32 enable;
+} __packed;
+
+/* HOSTCMD_CMD_SET_RF_CHANNEL */
+#define FREQ_BAND_MASK 0x0000003f
+#define CHNL_WIDTH_MASK 0x000007c0
+#define CHNL_WIDTH_SHIFT 6
+#define ACT_PRIMARY_MASK 0x00003800
+#define ACT_PRIMARY_SHIFT 11
+
+struct hostcmd_cmd_set_rf_channel {
+ struct hostcmd_header cmd_hdr;
+ __le16 action;
+ u8 curr_chnl;
+ __le32 chnl_flags;
+} __packed;
+
+/* HOSTCMD_CMD_SET_AID */
+struct hostcmd_cmd_set_aid {
+ struct hostcmd_header cmd_hdr;
+ __le16 aid;
+ u8 mac_addr[ETH_ALEN]; /* AP's Mac Address(BSSID) */
+ __le32 gprotect;
+ u8 ap_rates[SYSADPT_MAX_DATA_RATES_G];
+} __packed;
+
+/* HOSTCMD_CMD_SET_INFRA_MODE */
+struct hostcmd_cmd_set_infra_mode {
+ struct hostcmd_header cmd_hdr;
+} __packed;
+
+/* HOSTCMD_CMD_802_11_RTS_THSD */
+struct hostcmd_cmd_802_11_rts_thsd {
+ struct hostcmd_header cmd_hdr;
+ __le16 action;
+ __le16 threshold;
+} __packed;
+
+/* HOSTCMD_CMD_SET_EDCA_PARAMS */
+struct hostcmd_cmd_set_edca_params {
+ struct hostcmd_header cmd_hdr;
+ /* 0 = get all, 0x1 =set CWMin/Max, 0x2 = set TXOP , 0x4 =set AIFSN */
+ __le16 action;
+ __le16 txop; /* in unit of 32 us */
+ __le32 cw_max; /* 0~15 */
+ __le32 cw_min; /* 0~15 */
+ u8 aifsn;
+ u8 txq_num; /* Tx Queue number. */
+} __packed;
+
+/* HOSTCMD_CMD_SET_WMM_MODE */
+struct hostcmd_cmd_set_wmm_mode {
+ struct hostcmd_header cmd_hdr;
+ __le16 action; /* 0->unset, 1->set */
+} __packed;
+
+/* HOSTCMD_CMD_SET_FIXED_RATE */
+struct fix_rate_flag { /* lower rate after the retry count */
+ /* 0: legacy, 1: HT */
+ __le32 fix_rate_type;
+ /* 0: retry count is not valid, 1: use retry count specified */
+ __le32 retry_count_valid;
+} __packed;
+
+struct fix_rate_entry {
+ struct fix_rate_flag fix_rate_type_flags;
+ /* depending on the flags above, this can be either a legacy
+ * rate(not index) or an MCS code.
+ */
+ __le32 fixed_rate;
+ __le32 retry_count;
+} __packed;
+
+struct hostcmd_cmd_set_fixed_rate {
+ struct hostcmd_header cmd_hdr;
+ /* HOSTCMD_ACT_NOT_USE_FIXED_RATE 0x0002 */
+ __le32 action;
+ /* use fixed rate specified but firmware can drop to */
+ __le32 allow_rate_drop;
+ __le32 entry_count;
+ struct fix_rate_entry fixed_rate_table[4];
+ u8 multicast_rate;
+ u8 multi_rate_tx_type;
+ u8 management_rate;
+} __packed;
+
+/* HOSTCMD_CMD_SET_IES */
+struct hostcmd_cmd_set_ies {
+ struct hostcmd_header cmd_hdr;
+ __le16 action; /* 0->unset, 1->set */
+ __le16 ie_list_len_ht;
+ __le16 ie_list_len_vht;
+ __le16 ie_list_len_proprietary;
+ /*Buffer size same as Generic_Beacon*/
+ u8 ie_list_ht[148];
+ u8 ie_list_vht[24];
+ u8 ie_list_proprietary[112];
+} __packed;
+
+/* HOSTCMD_CMD_SET_RATE_ADAPT_MODE */
+struct hostcmd_cmd_set_rate_adapt_mode {
+ struct hostcmd_header cmd_hdr;
+ __le16 action;
+ __le16 rate_adapt_mode; /* 0:Indoor, 1:Outdoor */
+} __packed;
+
+/* HOSTCMD_CMD_SET_MAC_ADDR, HOSTCMD_CMD_DEL_MAC_ADDR */
+struct hostcmd_cmd_set_mac_addr {
+ struct hostcmd_header cmd_hdr;
+ __le16 mac_type;
+ u8 mac_addr[ETH_ALEN];
+} __packed;
+
+/* HOSTCMD_CMD_GET_WATCHDOG_BITMAP */
+struct hostcmd_cmd_get_watchdog_bitmap {
+ struct hostcmd_header cmd_hdr;
+ u8 watchdog_bitmap; /* for SW/BA */
+} __packed;
+
+/* HOSTCMD_CMD_BSS_START */
+struct hostcmd_cmd_bss_start {
+ struct hostcmd_header cmd_hdr;
+ __le32 enable; /* FALSE: Disable or TRUE: Enable */
+} __packed;
+
+/* HOSTCMD_CMD_AP_BEACON */
+struct cf_params {
+ u8 elem_id;
+ u8 len;
+ u8 cfp_cnt;
+ u8 cfp_period;
+ __le16 cfp_max_duration;
+ __le16 cfp_duration_remaining;
+} __packed;
+
+struct ibss_params {
+ u8 elem_id;
+ u8 len;
+ __le16 atim_window;
+} __packed;
+
+union ss_params {
+ struct cf_params cf_param_set;
+ struct ibss_params ibss_param_set;
+} __packed;
+
+struct fh_params {
+ u8 elem_id;
+ u8 len;
+ __le16 dwell_time;
+ u8 hop_set;
+ u8 hop_pattern;
+ u8 hop_index;
+} __packed;
+
+struct ds_params {
+ u8 elem_id;
+ u8 len;
+ u8 current_chnl;
+} __packed;
+
+union phy_params {
+ struct fh_params fh_param_set;
+ struct ds_params ds_param_set;
+} __packed;
+
+struct rsn_ie {
+ u8 elem_id;
+ u8 len;
+ u8 oui_type[4]; /* 00:50:f2:01 */
+ u8 ver[2];
+ u8 grp_key_cipher[4];
+ u8 pws_key_cnt[2];
+ u8 pws_key_cipher_list[4];
+ u8 auth_key_cnt[2];
+ u8 auth_key_list[4];
+} __packed;
+
+struct rsn48_ie {
+ u8 elem_id;
+ u8 len;
+ u8 ver[2];
+ u8 grp_key_cipher[4];
+ u8 pws_key_cnt[2];
+ u8 pws_key_cipher_list[4];
+ u8 auth_key_cnt[2];
+ u8 auth_key_list[4];
+ u8 rsn_cap[2];
+ u8 pmk_id_cnt[2];
+ u8 pmk_id_list[16]; /* Should modify to 16 * S */
+ u8 reserved[8];
+} __packed;
+
+struct ac_param_rcd {
+ u8 aci_aifsn;
+ u8 ecw_min_max;
+ __le16 txop_lim;
+} __packed;
+
+struct wmm_param_elem {
+ u8 elem_id;
+ u8 len;
+ u8 oui[3];
+ u8 type;
+ u8 sub_type;
+ u8 version;
+ u8 rsvd;
+ struct ac_param_rcd ac_be;
+ struct ac_param_rcd ac_bk;
+ struct ac_param_rcd ac_vi;
+ struct ac_param_rcd ac_vo;
+} __packed;
+
+struct channel_info {
+ u8 first_channel_num;
+ u8 num_channels;
+ u8 max_tx_pwr_level;
+} __packed;
+
+struct country {
+ u8 elem_id;
+ u8 len;
+ u8 country_str[3];
+ struct channel_info channel_info[40];
+} __packed;
+
+struct start_cmd {
+ u8 sta_mac_addr[ETH_ALEN];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ u8 bss_type;
+ __le16 bcn_period;
+ u8 dtim_period;
+ union ss_params ss_param_set;
+ union phy_params phy_param_set;
+ __le16 probe_delay;
+ __le16 cap_info;
+ u8 b_rate_set[SYSADPT_MAX_DATA_RATES_G];
+ u8 op_rate_set[SYSADPT_MAX_DATA_RATES_G];
+ struct rsn_ie rsn_ie;
+ struct rsn48_ie rsn48_ie;
+ struct wmm_param_elem wmm_param;
+ struct country country;
+ __le32 ap_rf_type; /* 0->B, 1->G, 2->Mixed, 3->A, 4->11J */
+} __packed;
+
+struct hostcmd_cmd_ap_beacon {
+ struct hostcmd_header cmd_hdr;
+ struct start_cmd start_cmd;
+} __packed;
+
+/* HOSTCMD_CMD_SET_NEW_STN */
+struct add_ht_info {
+ u8 control_chnl;
+ u8 add_chnl;
+ __le16 op_mode;
+ __le16 stbc;
+} __packed;
+
+struct peer_info {
+ __le32 legacy_rate_bitmap;
+ u8 ht_rates[4];
+ __le16 cap_info;
+ __le16 ht_cap_info;
+ u8 mac_ht_param_info;
+ u8 mrvl_sta;
+ struct add_ht_info add_ht_info;
+ __le32 tx_bf_capabilities; /* EXBF_SUPPORT */
+ __le32 vht_max_rx_mcs;
+ __le32 vht_cap;
+ /* 0:20Mhz, 1:40Mhz, 2:80Mhz, 3:160 or 80+80Mhz */
+ u8 vht_rx_channel_width;
+} __packed;
+
+struct hostcmd_cmd_set_new_stn {
+ struct hostcmd_header cmd_hdr;
+ __le16 aid;
+ u8 mac_addr[ETH_ALEN];
+ __le16 stn_id;
+ __le16 action;
+ __le16 reserved;
+ struct peer_info peer_info;
+ /* UAPSD_SUPPORT */
+ u8 qos_info;
+ u8 is_qos_sta;
+ __le32 fw_sta_ptr;
+} __packed;
+
+/* HOSTCMD_CMD_SET_APMODE */
+struct hostcmd_cmd_set_apmode {
+ struct hostcmd_header cmd_hdr;
+ u8 apmode;
+} __packed;
+
+/* HOSTCMD_CMD_UPDATE_ENCRYPTION */
+struct hostcmd_cmd_update_encryption {
+ struct hostcmd_header cmd_hdr;
+ /* Action type - see encr_action_type */
+ __le32 action_type; /* encr_action_type */
+ /* size of the data buffer attached. */
+ __le32 data_length;
+ u8 mac_addr[ETH_ALEN];
+ u8 action_data[1];
+} __packed;
+
+struct wep_type_key {
+ /* WEP key material (max 128bit) */
+ u8 key_material[MAX_ENCR_KEY_LENGTH];
+} __packed;
+
+struct encr_tkip_seqcnt {
+ __le16 low;
+ __le32 high;
+} __packed;
+
+struct tkip_type_key {
+ /* TKIP Key material. Key type (group or pairwise key) is
+ * determined by flags
+ */
+ /* in KEY_PARAM_SET structure. */
+ u8 key_material[MAX_ENCR_KEY_LENGTH];
+ /* MIC keys */
+ u8 tkip_tx_mic_key[MIC_KEY_LENGTH];
+ u8 tkip_rx_mic_key[MIC_KEY_LENGTH];
+ struct encr_tkip_seqcnt tkip_rsc;
+ struct encr_tkip_seqcnt tkip_tsc;
+} __packed;
+
+struct aes_type_key {
+ /* AES Key material */
+ u8 key_material[MAX_ENCR_KEY_LENGTH];
+} __packed;
+
+union mwl_key_type {
+ struct wep_type_key wep_key;
+ struct tkip_type_key tkip_key;
+ struct aes_type_key aes_key;
+} __packed;
+
+struct key_param_set {
+ /* Total length of this structure (Key is variable size array) */
+ __le16 length;
+ /* Key type - WEP, TKIP or AES-CCMP. */
+ /* See definitions above */
+ __le16 key_type_id;
+ /* key flags (ENCR_KEY_FLAG_XXX_ */
+ __le32 key_info;
+ /* For WEP only - actual key index */
+ __le32 key_index;
+ /* Size of the key */
+ __le16 key_len;
+ /* Key material (variable size array) */
+ union mwl_key_type key;
+ u8 mac_addr[ETH_ALEN];
+} __packed;
+
+struct hostcmd_cmd_set_key {
+ struct hostcmd_header cmd_hdr;
+ /* Action type - see encr_action_type */
+ __le32 action_type; /* encr_action_type */
+ /* size of the data buffer attached. */
+ __le32 data_length;
+ /* data buffer - maps to one KEY_PARAM_SET structure */
+ struct key_param_set key_param;
+} __packed;
+
+/* HOSTCMD_CMD_BASTREAM */
+#define BA_TYPE_MASK 0x00000001
+#define BA_DIRECTION_MASK 0x00000006
+#define BA_DIRECTION_SHIFT 1
+
+struct ba_context {
+ __le32 context;
+} __packed;
+
+/* parameters for block ack creation */
+struct create_ba_params {
+ /* BA Creation flags - see above */
+ __le32 flags;
+ /* idle threshold */
+ __le32 idle_thrs;
+ /* block ack transmit threshold (after how many pkts should we
+ * send BAR?)
+ */
+ __le32 bar_thrs;
+ /* receiver window size */
+ __le32 window_size;
+ /* MAC Address of the BA partner */
+ u8 peer_mac_addr[ETH_ALEN];
+ /* Dialog Token */
+ u8 dialog_token;
+ /* TID for the traffic stream in this BA */
+ u8 tid;
+ /* shared memory queue ID (not sure if this is required) */
+ u8 queue_id;
+ u8 param_info;
+ /* returned by firmware - firmware context pointer. */
+ /* this context pointer will be passed to firmware for all
+ * future commands.
+ */
+ struct ba_context fw_ba_context;
+ u8 reset_seq_no; /** 0 or 1**/
+ __le16 current_seq;
+ /* This is for virtual station in Sta proxy mode for V6FW */
+ u8 sta_src_mac_addr[ETH_ALEN];
+} __packed;
+
+/* new transmit sequence number information */
+struct ba_update_seq_num {
+ /* BA flags - see above */
+ __le32 flags;
+ /* returned by firmware in the create ba stream response */
+ struct ba_context fw_ba_context;
+ /* new sequence number for this block ack stream */
+ __le16 ba_seq_num;
+} __packed;
+
+struct ba_stream_context {
+ /* BA Stream flags */
+ __le32 flags;
+ /* returned by firmware in the create ba stream response */
+ struct ba_context fw_ba_context;
+} __packed;
+
+union ba_info {
+ /* information required to create BA Stream... */
+ struct create_ba_params create_params;
+ /* update starting/new sequence number etc. */
+ struct ba_update_seq_num updt_seq_num;
+ /* destroy an existing stream... */
+ struct ba_stream_context destroy_params;
+ /* destroy an existing stream... */
+ struct ba_stream_context flush_params;
+} __packed;
+
+struct hostcmd_cmd_bastream {
+ struct hostcmd_header cmd_hdr;
+ __le32 action_type;
+ union ba_info ba_info;
+} __packed;
+
+/* HOSTCMD_CMD_DWDS_ENABLE */
+struct hostcmd_cmd_dwds_enable {
+ struct hostcmd_header cmd_hdr;
+ __le32 enable; /* 0 -- Disable. or 1 -- Enable. */
+} __packed;
+
+/* HOSTCMD_CMD_FW_FLUSH_TIMER */
+struct hostcmd_cmd_fw_flush_timer {
+ struct hostcmd_header cmd_hdr;
+ /* 0 -- Disable. > 0 -- holds time value in usecs. */
+ __le32 value;
+} __packed;
+
+/* HOSTCMD_CMD_SET_CDD */
+struct hostcmd_cmd_set_cdd {
+ struct hostcmd_header cmd_hdr;
+ __le32 enable;
+} __packed;
+
+#endif /* _hostcmd_h_ */
diff --git a/isr.c b/isr.c
index 7109896..9e7d473 100644
--- a/isr.c
+++ b/isr.c
@@ -1,13 +1,19 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file implements interrupt related functions.
- */
+/* Description: This file implements interrupt related functions. */
#include "sysadpt.h"
#include "dev.h"
@@ -19,13 +25,11 @@
irqreturn_t mwl_isr(int irq, void *dev_id)
{
struct ieee80211_hw *hw = dev_id;
- struct mwl_priv *priv;
- void *int_status_mask;
+ struct mwl_priv *priv = hw->priv;
+ void __iomem *int_status_mask;
unsigned int int_status, clr_status;
u32 status;
- priv = hw->priv;
-
int_status_mask = priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK;
int_status = readl(priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CAUSE);
@@ -34,7 +38,7 @@ irqreturn_t mwl_isr(int irq, void *dev_id)
return IRQ_NONE;
if (int_status == 0xffffffff) {
- wiphy_warn(hw->wiphy, "card plugged out???");
+ wiphy_warn(hw->wiphy, "card unplugged?\n");
} else {
clr_status = int_status;
@@ -62,6 +66,18 @@ irqreturn_t mwl_isr(int irq, void *dev_id)
}
}
+ if (int_status & MACREG_A2HRIC_BIT_QUEUE_EMPTY) {
+ int_status &= ~MACREG_A2HRIC_BIT_QUEUE_EMPTY;
+
+ if (!priv->is_qe_schedule) {
+ status = readl(int_status_mask);
+ writel((status & ~MACREG_A2HRIC_BIT_QUEUE_EMPTY),
+ int_status_mask);
+ tasklet_schedule(&priv->qe_task);
+ priv->is_qe_schedule = true;
+ }
+ }
+
if (int_status & MACREG_A2HRIC_BA_WATCHDOG) {
status = readl(int_status_mask);
writel((status & ~MACREG_A2HRIC_BA_WATCHDOG),
@@ -92,7 +108,7 @@ void mwl_watchdog_ba_events(struct work_struct *work)
if (rc)
goto done;
- spin_lock(&priv->stream_lock);
+ spin_lock_bh(&priv->stream_lock);
/* the bitmap is the hw queue number. Map it to the ampdu queue. */
if (bitmap != INVALID_WATCHDOG) {
@@ -110,9 +126,9 @@ void mwl_watchdog_ba_events(struct work_struct *work)
if (streams->state == AMPDU_STREAM_ACTIVE) {
ieee80211_stop_tx_ba_session(streams->sta,
streams->tid);
- spin_unlock(&priv->stream_lock);
+ spin_unlock_bh(&priv->stream_lock);
mwl_fwcmd_destroy_ba(hw, stream_index);
- spin_lock(&priv->stream_lock);
+ spin_lock_bh(&priv->stream_lock);
}
} else {
for (stream_index = 0;
@@ -125,14 +141,14 @@ void mwl_watchdog_ba_events(struct work_struct *work)
ieee80211_stop_tx_ba_session(streams->sta,
streams->tid);
- spin_unlock(&priv->stream_lock);
+ spin_unlock_bh(&priv->stream_lock);
mwl_fwcmd_destroy_ba(hw, stream_index);
- spin_lock(&priv->stream_lock);
+ spin_lock_bh(&priv->stream_lock);
}
}
}
- spin_unlock(&priv->stream_lock);
+ spin_unlock_bh(&priv->stream_lock);
done:
diff --git a/isr.h b/isr.h
index 1c8c146..2598115 100644
--- a/isr.h
+++ b/isr.h
@@ -1,20 +1,26 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file defines interrupt related functions.
- */
+/* Description: This file defines interrupt related functions. */
-#ifndef _mwl_isr_h_
-#define _mwl_isr_h_
+#ifndef _isr_h_
+#define _isr_h_
#include <linux/interrupt.h>
irqreturn_t mwl_isr(int irq, void *dev_id);
void mwl_watchdog_ba_events(struct work_struct *work);
-#endif /* _mwl_isr_h_ */
+#endif /* _isr_h_ */
diff --git a/mac80211.c b/mac80211.c
index 1a1f73e..a4242e0 100644
--- a/mac80211.c
+++ b/mac80211.c
@@ -1,13 +1,19 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file implements mac80211 related functions.
- */
+/* Description: This file implements mac80211 related functions. */
#include <linux/etherdevice.h>
@@ -15,8 +21,6 @@
#include "dev.h"
#include "fwcmd.h"
#include "tx.h"
-#include "mac80211.h"
-#include "isr.h"
#define MWL_DRV_NAME KBUILD_MODNAME
@@ -53,13 +57,11 @@ static void mwl_mac80211_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
{
- struct mwl_priv *priv;
-
- priv = hw->priv;
+ struct mwl_priv *priv = hw->priv;
if (!priv->radio_on) {
wiphy_warn(hw->wiphy,
- "dropped TX frame since radio disabled");
+ "dropped TX frame since radio is disabled\n");
dev_kfree_skb_any(skb);
return;
}
@@ -69,23 +71,13 @@ static void mwl_mac80211_tx(struct ieee80211_hw *hw,
static int mwl_mac80211_start(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
int rc;
- priv = hw->priv;
-
- rc = request_irq(priv->pdev->irq, mwl_isr,
- IRQF_SHARED, MWL_DRV_NAME, hw);
- if (rc) {
- priv->irq = -1;
- wiphy_err(hw->wiphy, "fail to register IRQ handler");
- return rc;
- }
- priv->irq = priv->pdev->irq;
-
/* Enable TX reclaim and RX tasklets. */
tasklet_enable(&priv->tx_task);
tasklet_enable(&priv->rx_task);
+ tasklet_enable(&priv->qe_task);
/* Enable interrupts */
mwl_fwcmd_int_enable(hw);
@@ -102,7 +94,7 @@ static int mwl_mac80211_start(struct ieee80211_hw *hw)
rc = mwl_fwcmd_set_dwds_stamode(hw, true);
if (rc)
goto fwcmd_fail;
- rc = mwl_fwcmd_set_fw_flush_timer(hw, 0);
+ rc = mwl_fwcmd_set_fw_flush_timer(hw, SYSADPT_AMSDU_FLUSH_TIME);
if (rc)
goto fwcmd_fail;
@@ -111,19 +103,16 @@ static int mwl_mac80211_start(struct ieee80211_hw *hw)
fwcmd_fail:
mwl_fwcmd_int_disable(hw);
- free_irq(priv->pdev->irq, hw);
- priv->irq = -1;
tasklet_disable(&priv->tx_task);
tasklet_disable(&priv->rx_task);
+ tasklet_disable(&priv->qe_task);
return rc;
}
static void mwl_mac80211_stop(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
-
- priv = hw->priv;
+ struct mwl_priv *priv = hw->priv;
mwl_fwcmd_radio_disable(hw);
@@ -132,16 +121,10 @@ static void mwl_mac80211_stop(struct ieee80211_hw *hw)
/* Disable interrupts */
mwl_fwcmd_int_disable(hw);
- if (priv->irq != -1) {
- free_irq(priv->pdev->irq, hw);
- priv->irq = -1;
- }
-
- cancel_work_sync(&priv->watchdog_ba_handle);
-
/* Disable TX reclaim and RX tasklets. */
tasklet_disable(&priv->tx_task);
tasklet_disable(&priv->rx_task);
+ tasklet_disable(&priv->qe_task);
/* Return all skbs to mac80211 */
mwl_tx_done((unsigned long)hw);
@@ -154,7 +137,6 @@ static int mwl_mac80211_add_interface(struct ieee80211_hw *hw,
struct mwl_vif *mwl_vif;
u32 macids_supported;
int macid;
- unsigned long flags;
switch (vif->type) {
case NL80211_IFTYPE_AP:
@@ -169,58 +151,60 @@ static int mwl_mac80211_add_interface(struct ieee80211_hw *hw,
macid = ffs(macids_supported & ~priv->macids_used);
- if (!macid--) {
- wiphy_warn(hw->wiphy, "no macid can be allocated");
+ if (!macid) {
+ wiphy_warn(hw->wiphy, "no macid can be allocated\n");
return -EBUSY;
}
+ macid--;
/* Setup driver private area. */
mwl_vif = mwl_dev_get_vif(vif);
memset(mwl_vif, 0, sizeof(*mwl_vif));
- mwl_vif->vif = vif;
mwl_vif->macid = macid;
mwl_vif->seqno = 0;
mwl_vif->is_hw_crypto_enabled = false;
- mwl_vif->is_sta = false;
mwl_vif->beacon_info.valid = false;
mwl_vif->iv16 = 1;
mwl_vif->iv32 = 0;
mwl_vif->keyidx = 0;
- if (vif->type == NL80211_IFTYPE_STATION) {
+ switch (vif->type) {
+ case NL80211_IFTYPE_AP:
+ ether_addr_copy(mwl_vif->bssid, vif->addr);
+ mwl_fwcmd_set_new_stn_add_self(hw, vif);
+ break;
+ case NL80211_IFTYPE_STATION:
ether_addr_copy(mwl_vif->sta_mac, vif->addr);
- mwl_vif->is_sta = true;
mwl_fwcmd_bss_start(hw, vif, true);
mwl_fwcmd_set_infra_mode(hw, vif);
mwl_fwcmd_set_mac_addr_client(hw, vif, vif->addr);
- }
-
- if (vif->type == NL80211_IFTYPE_AP) {
- ether_addr_copy(mwl_vif->bssid, vif->addr);
- mwl_fwcmd_set_new_stn_add_self(hw, vif);
+ break;
+ default:
+ return -EINVAL;
}
priv->macids_used |= 1 << mwl_vif->macid;
- spin_lock_irqsave(&priv->vif_lock, flags);
+ spin_lock_bh(&priv->vif_lock);
list_add_tail(&mwl_vif->list, &priv->vif_list);
- spin_unlock_irqrestore(&priv->vif_lock, flags);
+ spin_unlock_bh(&priv->vif_lock);
return 0;
}
-static void mwl_mac80211_remove_vif(struct mwl_priv *priv, struct mwl_vif *vif)
+static void mwl_mac80211_remove_vif(struct mwl_priv *priv,
+ struct ieee80211_vif *vif)
{
- unsigned long flags;
int num;
struct sk_buff *skb, *tmp;
struct ieee80211_tx_info *tx_info;
struct mwl_tx_ctrl *tx_ctrl;
+ struct mwl_vif *mwl_vif = mwl_dev_get_vif(vif);
if (!priv->macids_used)
return;
for (num = 1; num < SYSADPT_NUM_OF_DESC_DATA; num++) {
- spin_lock_irqsave(&priv->txq[num].lock, flags);
+ spin_lock_bh(&priv->txq[num].lock);
skb_queue_walk_safe(&priv->txq[num], skb, tmp) {
tx_info = IEEE80211_SKB_CB(skb);
tx_ctrl = (struct mwl_tx_ctrl *)&tx_info->status;
@@ -229,30 +213,32 @@ static void mwl_mac80211_remove_vif(struct mwl_priv *priv, struct mwl_vif *vif)
dev_kfree_skb_any(skb);
}
}
- spin_unlock_irqrestore(&priv->txq[num].lock, flags);
+ spin_unlock_bh(&priv->txq[num].lock);
}
- priv->macids_used &= ~(1 << vif->macid);
- spin_lock_irqsave(&priv->vif_lock, flags);
- list_del(&vif->list);
- spin_unlock_irqrestore(&priv->vif_lock, flags);
+ priv->macids_used &= ~(1 << mwl_vif->macid);
+ spin_lock_bh(&priv->vif_lock);
+ list_del(&mwl_vif->list);
+ spin_unlock_bh(&priv->vif_lock);
}
static void mwl_mac80211_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct mwl_priv *priv = hw->priv;
- struct mwl_vif *mwl_vif;
-
- mwl_vif = mwl_dev_get_vif(vif);
-
- if (vif->type == NL80211_IFTYPE_STATION)
- mwl_fwcmd_remove_mac_addr(hw, vif, vif->addr);
- if (vif->type == NL80211_IFTYPE_AP)
+ switch (vif->type) {
+ case NL80211_IFTYPE_AP:
mwl_fwcmd_set_new_stn_del(hw, vif, vif->addr);
+ break;
+ case NL80211_IFTYPE_STATION:
+ mwl_fwcmd_remove_mac_addr(hw, vif, vif->addr);
+ break;
+ default:
+ break;
+ }
- mwl_mac80211_remove_vif(priv, mwl_vif);
+ mwl_mac80211_remove_vif(priv, vif);
}
static int mwl_mac80211_config(struct ieee80211_hw *hw,
@@ -261,7 +247,7 @@ static int mwl_mac80211_config(struct ieee80211_hw *hw,
struct ieee80211_conf *conf = &hw->conf;
int rc;
- wiphy_debug(hw->wiphy, "change: 0x%x", changed);
+ wiphy_debug(hw->wiphy, "change: 0x%x\n", changed);
if (conf->flags & IEEE80211_CONF_IDLE)
rc = mwl_fwcmd_radio_disable(hw);
@@ -372,11 +358,16 @@ static void mwl_mac80211_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *info,
u32 changed)
{
- if (vif->type == NL80211_IFTYPE_STATION)
- mwl_mac80211_bss_info_changed_sta(hw, vif, info, changed);
-
- if (vif->type == NL80211_IFTYPE_AP)
+ switch (vif->type) {
+ case NL80211_IFTYPE_AP:
mwl_mac80211_bss_info_changed_ap(hw, vif, info, changed);
+ break;
+ case NL80211_IFTYPE_STATION:
+ mwl_mac80211_bss_info_changed_sta(hw, vif, info, changed);
+ break;
+ default:
+ break;
+ }
}
static void mwl_mac80211_configure_filter(struct ieee80211_hw *hw,
@@ -407,7 +398,7 @@ static int mwl_mac80211_set_key(struct ieee80211_hw *hw,
addr = vif->addr;
} else {
addr = sta->addr;
- if (mwl_vif->is_sta)
+ if (vif->type == NL80211_IFTYPE_STATION)
ether_addr_copy(mwl_vif->bssid, addr);
}
@@ -423,7 +414,7 @@ static int mwl_mac80211_set_key(struct ieee80211_hw *hw,
} else if (key->cipher == WLAN_CIPHER_SUITE_CCMP) {
encr_type = ENCR_TYPE_AES;
if ((key->flags & IEEE80211_KEY_FLAG_PAIRWISE) == 0) {
- if (!mwl_vif->is_sta)
+ if (vif->type != NL80211_IFTYPE_STATION)
mwl_vif->keyidx = key->keyidx;
}
} else if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
@@ -462,7 +453,6 @@ static int mwl_mac80211_sta_add(struct ieee80211_hw *hw,
struct mwl_priv *priv = hw->priv;
struct mwl_vif *mwl_vif;
struct mwl_sta *sta_info;
- unsigned long flags;
struct ieee80211_key_conf *key;
int rc;
int i;
@@ -471,7 +461,6 @@ static int mwl_mac80211_sta_add(struct ieee80211_hw *hw,
sta_info = mwl_dev_get_sta(sta);
memset(sta_info, 0, sizeof(*sta_info));
- sta_info->sta = sta;
if (sta->ht_cap.ht_supported) {
sta_info->is_ampdu_allowed = true;
sta_info->is_amsdu_allowed = true;
@@ -482,11 +471,12 @@ static int mwl_mac80211_sta_add(struct ieee80211_hw *hw,
}
sta_info->iv16 = 1;
sta_info->iv32 = 0;
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_init(&sta_info->amsdu_lock);
+ spin_lock_bh(&priv->sta_lock);
list_add_tail(&sta_info->list, &priv->sta_list);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
- if (mwl_vif->is_sta)
+ if (vif->type == NL80211_IFTYPE_STATION)
mwl_fwcmd_set_new_stn_del(hw, vif, sta->addr);
rc = mwl_fwcmd_set_new_stn_add(hw, vif, sta);
@@ -507,7 +497,6 @@ static int mwl_mac80211_sta_remove(struct ieee80211_hw *hw,
{
struct mwl_priv *priv = hw->priv;
struct mwl_sta *sta_info;
- unsigned long flags;
int num;
struct sk_buff *skb, *tmp;
struct ieee80211_tx_info *tx_info;
@@ -517,7 +506,7 @@ static int mwl_mac80211_sta_remove(struct ieee80211_hw *hw,
sta_info = mwl_dev_get_sta(sta);
for (num = 1; num < SYSADPT_NUM_OF_DESC_DATA; num++) {
- spin_lock_irqsave(&priv->txq[num].lock, flags);
+ spin_lock_bh(&priv->txq[num].lock);
skb_queue_walk_safe(&priv->txq[num], skb, tmp) {
tx_info = IEEE80211_SKB_CB(skb);
tx_ctrl = (struct mwl_tx_ctrl *)&tx_info->status;
@@ -526,14 +515,21 @@ static int mwl_mac80211_sta_remove(struct ieee80211_hw *hw,
dev_kfree_skb_any(skb);
}
}
- spin_unlock_irqrestore(&priv->txq[num].lock, flags);
+ spin_unlock_bh(&priv->txq[num].lock);
+ }
+
+ spin_lock_bh(&sta_info->amsdu_lock);
+ for (num = 0; num < SYSADPT_TX_WMM_QUEUES; num++) {
+ if (!sta_info->amsdu_ctrl.frag[num].skb)
+ dev_kfree_skb_any(sta_info->amsdu_ctrl.frag[num].skb);
}
+ spin_unlock_bh(&sta_info->amsdu_lock);
rc = mwl_fwcmd_set_new_stn_del(hw, vif, sta->addr);
- spin_lock_irqsave(&priv->sta_lock, flags);
+ spin_lock_bh(&priv->sta_lock);
list_del(&sta_info->list);
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ spin_unlock_bh(&priv->sta_lock);
return rc;
}
@@ -603,7 +599,7 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
sta_info = mwl_dev_get_sta(sta);
- spin_lock(&priv->stream_lock);
+ spin_lock_bh(&priv->stream_lock);
stream = mwl_fwcmd_lookup_stream(hw, addr, tid);
@@ -633,7 +629,7 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
}
if (!stream) {
- wiphy_warn(hw->wiphy, "no stream found");
+ wiphy_warn(hw->wiphy, "no stream found\n");
rc = -EBUSY;
break;
}
@@ -641,16 +637,16 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
stream->state = AMPDU_STREAM_IN_PROGRESS;
/* Release the lock before we do the time consuming stuff */
- spin_unlock(&priv->stream_lock);
+ spin_unlock_bh(&priv->stream_lock);
for (i = 0; i < MAX_AMPDU_ATTEMPTS; i++) {
/* Check if link is still valid */
if (!sta_info->is_ampdu_allowed) {
- spin_lock(&priv->stream_lock);
+ spin_lock_bh(&priv->stream_lock);
mwl_fwcmd_remove_stream(hw, stream);
- spin_unlock(&priv->stream_lock);
+ spin_unlock_bh(&priv->stream_lock);
wiphy_warn(hw->wiphy,
- "link is no valid now");
+ "link is no valid now\n");
return -EBUSY;
}
@@ -662,11 +658,11 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
mdelay(1000);
}
- spin_lock(&priv->stream_lock);
+ spin_lock_bh(&priv->stream_lock);
if (rc) {
mwl_fwcmd_remove_stream(hw, stream);
- wiphy_err(hw->wiphy, "error code: %d", rc);
+ wiphy_err(hw->wiphy, "error code: %d\n", rc);
rc = -EBUSY;
break;
}
@@ -679,9 +675,9 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
if (stream) {
if (stream->state == AMPDU_STREAM_ACTIVE) {
idx = stream->idx;
- spin_unlock(&priv->stream_lock);
+ spin_unlock_bh(&priv->stream_lock);
mwl_fwcmd_destroy_ba(hw, idx);
- spin_lock(&priv->stream_lock);
+ spin_lock_bh(&priv->stream_lock);
}
mwl_fwcmd_remove_stream(hw, stream);
@@ -691,17 +687,17 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
BUG_ON(stream->state != AMPDU_STREAM_IN_PROGRESS);
- spin_unlock(&priv->stream_lock);
+ spin_unlock_bh(&priv->stream_lock);
rc = mwl_fwcmd_create_ba(hw, stream, buf_size, vif);
- spin_lock(&priv->stream_lock);
+ spin_lock_bh(&priv->stream_lock);
if (!rc) {
stream->state = AMPDU_STREAM_ACTIVE;
} else {
idx = stream->idx;
- spin_unlock(&priv->stream_lock);
+ spin_unlock_bh(&priv->stream_lock);
mwl_fwcmd_destroy_ba(hw, idx);
- spin_lock(&priv->stream_lock);
+ spin_lock_bh(&priv->stream_lock);
mwl_fwcmd_remove_stream(hw, stream);
}
break;
@@ -709,7 +705,7 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
rc = -ENOTSUPP;
}
- spin_unlock(&priv->stream_lock);
+ spin_unlock_bh(&priv->stream_lock);
return rc;
}
diff --git a/mac80211.h b/mac80211.h
deleted file mode 100644
index b70598a..0000000
--- a/mac80211.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2006-2015, Marvell International Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Description: This file defines mac80211 related functions.
- */
-
-#ifndef _mwl_mac80211_h_
-#define _mwl_mac80211_h_
-
-#include <net/mac80211.h>
-
-extern const struct ieee80211_ops mwl_mac80211_ops;
-
-#endif /* _mwl_mac80211_h_ */
diff --git a/main.c b/main.c
index 24a3686..667c231 100644
--- a/main.c
+++ b/main.c
@@ -1,16 +1,24 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file implements main functions of this module.
- */
+/* Description: This file implements main functions of this module. */
#include <linux/module.h>
-#include <linux/moduleparam.h>
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif
#include "sysadpt.h"
#include "dev.h"
@@ -18,13 +26,12 @@
#include "fwcmd.h"
#include "tx.h"
#include "rx.h"
-#include "mac80211.h"
#include "isr.h"
#define MWL_DESC "Marvell 802.11ac Wireless Network Driver"
#define MWL_DEV_NAME "Marvell 802.11ac Adapter"
#define MWL_DRV_NAME KBUILD_MODNAME
-#define MWL_DRV_VERSION "10.3.0.3"
+#define MWL_DRV_VERSION "10.3.0.8"
#define FILE_PATH_LEN 64
#define CMD_BUF_SIZE 0x4000
@@ -39,10 +46,14 @@ static struct mwl_chip_info mwl_chip_tbl[] = {
[MWL8864] = {
.part_name = "88W8864",
.fw_image = "mwlwifi/88W8864.bin",
+ .antenna_tx = ANTENNA_TX_4_AUTO,
+ .antenna_rx = ANTENNA_RX_4_AUTO,
},
[MWL8897] = {
.part_name = "88W8897",
.fw_image = "mwlwifi/88W8897.bin",
+ .antenna_tx = ANTENNA_TX_2,
+ .antenna_rx = ANTENNA_RX_2,
},
};
@@ -134,8 +145,8 @@ static int mwl_alloc_pci_resource(struct mwl_priv *priv)
struct pci_dev *pdev;
u32 phys_addr = 0;
u32 flags;
- void *phys_addr1[2];
- void *phys_addr2[2];
+ void __iomem *phys_addr1[2];
+ void __iomem *phys_addr2[2];
pdev = priv->pdev;
@@ -150,24 +161,23 @@ static int mwl_alloc_pci_resource(struct mwl_priv *priv)
if (!request_mem_region(phys_addr, pci_resource_len(pdev, 0),
MWL_DRV_NAME)) {
wiphy_err(priv->hw->wiphy,
- "%s: cannot reserve PCI memory region 0",
+ "%s: cannot reserve PCI memory region 0\n",
MWL_DRV_NAME);
goto err_reserve_mem_region_bar0;
}
phys_addr1[0] = ioremap(phys_addr, pci_resource_len(pdev, 0));
- phys_addr1[1] = 0;
+ phys_addr1[1] = NULL;
priv->iobase0 = phys_addr1[0];
if (!priv->iobase0) {
wiphy_err(priv->hw->wiphy,
- "%s: cannot remap PCI memory region 0",
+ "%s: cannot remap PCI memory region 0\n",
MWL_DRV_NAME);
goto err_release_mem_region_bar0;
}
- wiphy_info(priv->hw->wiphy, "priv->iobase0 = %x",
- (unsigned int)priv->iobase0);
+ wiphy_debug(priv->hw->wiphy, "priv->iobase0 = %p\n", priv->iobase0);
phys_addr = pci_resource_start(pdev, priv->next_bar_num);
@@ -175,25 +185,24 @@ static int mwl_alloc_pci_resource(struct mwl_priv *priv)
pci_resource_len(pdev, priv->next_bar_num),
MWL_DRV_NAME)) {
wiphy_err(priv->hw->wiphy,
- "%s: cannot reserve PCI memory region 1",
+ "%s: cannot reserve PCI memory region 1\n",
MWL_DRV_NAME);
goto err_iounmap_iobase0;
}
phys_addr2[0] = ioremap(phys_addr,
pci_resource_len(pdev, priv->next_bar_num));
- phys_addr2[1] = 0;
+ phys_addr2[1] = NULL;
priv->iobase1 = phys_addr2[0];
if (!priv->iobase1) {
wiphy_err(priv->hw->wiphy,
- "%s: cannot remap PCI memory region 1",
+ "%s: cannot remap PCI memory region 1\n",
MWL_DRV_NAME);
goto err_release_mem_region_bar1;
}
- wiphy_info(priv->hw->wiphy, "priv->iobase1 = %x",
- (unsigned int)priv->iobase1);
+ wiphy_debug(priv->hw->wiphy, "priv->iobase1 = %p\n", priv->iobase1);
priv->pcmd_buf =
(unsigned short *)dma_alloc_coherent(&priv->pdev->dev,
@@ -203,15 +212,15 @@ static int mwl_alloc_pci_resource(struct mwl_priv *priv)
if (!priv->pcmd_buf) {
wiphy_err(priv->hw->wiphy,
- "%s: cannot alloc memory for command buffer",
+ "%s: cannot alloc memory for command buffer\n",
MWL_DRV_NAME);
goto err_iounmap_iobase1;
}
- wiphy_info(priv->hw->wiphy,
- "priv->pcmd_buf = %x priv->pphys_cmd_buf = %x",
- (unsigned int)priv->pcmd_buf,
- (unsigned int)priv->pphys_cmd_buf);
+ wiphy_debug(priv->hw->wiphy,
+ "priv->pcmd_buf = %p priv->pphys_cmd_buf = %p\n",
+ priv->pcmd_buf,
+ (void *)priv->pphys_cmd_buf);
memset(priv->pcmd_buf, 0x00, CMD_BUF_SIZE);
@@ -237,7 +246,7 @@ err_release_mem_region_bar0:
err_reserve_mem_region_bar0:
- wiphy_err(priv->hw->wiphy, "pci alloc fail");
+ wiphy_err(priv->hw->wiphy, "pci alloc fail\n");
return -EIO;
}
@@ -258,7 +267,7 @@ static void mwl_free_pci_resource(struct mwl_priv *priv)
priv->pcmd_buf, priv->pphys_cmd_buf);
}
-static int mwl_init_firmware(struct mwl_priv *priv, char *fw_name)
+static int mwl_init_firmware(struct mwl_priv *priv, const char *fw_name)
{
struct pci_dev *pdev;
int rc = 0;
@@ -268,7 +277,7 @@ static int mwl_init_firmware(struct mwl_priv *priv, char *fw_name)
rc = request_firmware(&priv->fw_ucode, fw_name, &priv->pdev->dev);
if (rc) {
wiphy_err(priv->hw->wiphy,
- "%s: cannot load firmware image <%s>",
+ "%s: cannot load firmware image <%s>\n",
MWL_DRV_NAME, fw_name);
goto err_load_fw;
}
@@ -276,7 +285,7 @@ static int mwl_init_firmware(struct mwl_priv *priv, char *fw_name)
rc = mwl_fwdl_download_firmware(priv->hw);
if (rc) {
wiphy_err(priv->hw->wiphy,
- "%s: cannot download firmware image <%s>",
+ "%s: cannot download firmware image <%s>\n",
MWL_DRV_NAME, fw_name);
goto err_download_fw;
}
@@ -289,7 +298,7 @@ err_download_fw:
err_load_fw:
- wiphy_err(priv->hw->wiphy, "firmware init fail");
+ wiphy_err(priv->hw->wiphy, "firmware init fail\n");
return rc;
}
@@ -297,6 +306,7 @@ err_load_fw:
static void mwl_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
{
+#ifdef CONFIG_OF
struct ieee80211_hw *hw;
struct mwl_priv *priv;
struct property *prop;
@@ -363,7 +373,8 @@ static void mwl_reg_notifier(struct wiphy *wiphy,
prop_value =
be32_to_cpu(*(__be32 *)
(prop->value + i));
- priv->tx_pwr_tbl[j].cdd = prop_value;
+ priv->tx_pwr_tbl[j].cdd =
+ (prop_value == 0) ? false : true;
i += 4;
prop_value =
be32_to_cpu(*(__be32 *)
@@ -385,7 +396,7 @@ static void mwl_reg_notifier(struct wiphy *wiphy,
if (pwr_tbl->channel == 0)
break;
wiphy_info(hw->wiphy,
- "Channel: %d: 0x%x 0x%x 0x%x",
+ "Channel: %d: 0x%x 0x%x 0x%x\n",
pwr_tbl->channel,
pwr_tbl->setcap,
pwr_tbl->cdd,
@@ -397,27 +408,24 @@ static void mwl_reg_notifier(struct wiphy *wiphy,
sprintf(disp_ptr, "%x ",
pwr_tbl->tx_power[j]);
}
- wiphy_info(hw->wiphy, "%s", disp_buf);
+ wiphy_info(hw->wiphy, "%s\n", disp_buf);
}
}
}
+#endif
}
-static int mwl_process_of_dts(struct mwl_priv *priv)
+static void mwl_process_of_dts(struct mwl_priv *priv)
{
+#ifdef CONFIG_OF
struct property *prop;
u32 prop_value;
- priv->disable_2g = false;
- priv->disable_5g = false;
- priv->antenna_tx = ANTENNA_TX_4_AUTO;
- priv->antenna_rx = ANTENNA_RX_4_AUTO;
-
priv->dt_node =
of_find_node_by_name(pci_bus_to_OF_node(priv->pdev->bus),
"mwlwifi");
if (!priv->dt_node)
- return -EPERM;
+ return;
/* look for all matching property names */
for_each_property_of_node(priv->dt_node, prop) {
@@ -439,26 +447,7 @@ static int mwl_process_of_dts(struct mwl_priv *priv)
priv->pwr_node = of_find_node_by_name(priv->dt_node,
"marvell,powertable");
-
- wiphy_info(priv->hw->wiphy,
- "2G: %s\n", priv->disable_2g ? "disable" : "enable");
- wiphy_info(priv->hw->wiphy,
- "5G: %s\n", priv->disable_5g ? "disable" : "enable");
-
- if (priv->antenna_tx == ANTENNA_TX_4_AUTO)
- wiphy_info(priv->hw->wiphy, "TX: 4 antennas\n");
- else if (priv->antenna_tx == ANTENNA_TX_2)
- wiphy_info(priv->hw->wiphy, "TX: 2 antennas\n");
- else
- wiphy_info(priv->hw->wiphy, "TX: unknown\n");
- if (priv->antenna_rx == ANTENNA_RX_4_AUTO)
- wiphy_info(priv->hw->wiphy, "RX: 4 antennas\n");
- else if (priv->antenna_rx == ANTENNA_RX_2)
- wiphy_info(priv->hw->wiphy, "RX: 2 antennas\n");
- else
- wiphy_info(priv->hw->wiphy, "RX: unknown\n");
-
- return 0;
+#endif
}
static void mwl_set_ht_caps(struct mwl_priv *priv,
@@ -608,10 +597,14 @@ static int mwl_wl_init(struct mwl_priv *priv)
tasklet_disable(&priv->tx_task);
tasklet_init(&priv->rx_task, (void *)mwl_rx_recv, (unsigned long)hw);
tasklet_disable(&priv->rx_task);
+ tasklet_init(&priv->qe_task,
+ (void *)mwl_tx_flush_amsdu, (unsigned long)hw);
+ tasklet_disable(&priv->qe_task);
priv->txq_limit = SYSADPT_TX_QUEUE_LIMIT;
priv->is_tx_schedule = false;
priv->recv_limit = SYSADPT_RECEIVE_LIMIT;
priv->is_rx_schedule = false;
+ priv->is_qe_schedule = false;
spin_lock_init(&priv->tx_desc_lock);
spin_lock_init(&priv->fwcmd_lock);
@@ -621,21 +614,21 @@ static int mwl_wl_init(struct mwl_priv *priv)
rc = mwl_tx_init(hw);
if (rc) {
- wiphy_err(hw->wiphy, "%s: fail to initialize TX",
+ wiphy_err(hw->wiphy, "%s: fail to initialize TX\n",
MWL_DRV_NAME);
goto err_mwl_tx_init;
}
rc = mwl_rx_init(hw);
if (rc) {
- wiphy_err(hw->wiphy, "%s: fail to initialize RX",
+ wiphy_err(hw->wiphy, "%s: fail to initialize RX\n",
MWL_DRV_NAME);
goto err_mwl_rx_init;
}
rc = mwl_fwcmd_get_hw_specs(hw);
if (rc) {
- wiphy_err(hw->wiphy, "%s: fail to get HW specifications",
+ wiphy_err(hw->wiphy, "%s: fail to get HW specifications\n",
MWL_DRV_NAME);
goto err_get_hw_specs;
}
@@ -644,11 +637,9 @@ static int mwl_wl_init(struct mwl_priv *priv)
writel(priv->desc_data[0].pphys_tx_ring,
priv->iobase0 + priv->desc_data[0].wcb_base);
-#if SYSADPT_NUM_OF_DESC_DATA > 3
for (i = 1; i < SYSADPT_TOTAL_TX_QUEUES; i++)
writel(priv->desc_data[i].pphys_tx_ring,
priv->iobase0 + priv->desc_data[i].wcb_base);
-#endif
writel(priv->desc_data[0].pphys_rx_ring,
priv->iobase0 + priv->desc_data[0].rx_desc_read);
writel(priv->desc_data[0].pphys_rx_ring,
@@ -656,13 +647,13 @@ static int mwl_wl_init(struct mwl_priv *priv)
rc = mwl_fwcmd_set_hw_specs(hw);
if (rc) {
- wiphy_err(hw->wiphy, "%s: fail to set HW specifications",
+ wiphy_err(hw->wiphy, "%s: fail to set HW specifications\n",
MWL_DRV_NAME);
goto err_set_hw_specs;
}
wiphy_info(hw->wiphy,
- "firmware version: 0x%x", priv->hw_data.fw_release_num);
+ "firmware version: 0x%x\n", priv->hw_data.fw_release_num);
mwl_fwcmd_radio_disable(hw);
@@ -680,13 +671,23 @@ static int mwl_wl_init(struct mwl_priv *priv)
rc = ieee80211_register_hw(hw);
if (rc) {
- wiphy_err(hw->wiphy, "%s: fail to register device",
+ wiphy_err(hw->wiphy, "%s: fail to register device\n",
MWL_DRV_NAME);
goto err_register_hw;
}
+ rc = request_irq(priv->pdev->irq, mwl_isr,
+ IRQF_SHARED, MWL_DRV_NAME, hw);
+ if (rc) {
+ priv->irq = -1;
+ wiphy_err(hw->wiphy, "fail to register IRQ handler\n");
+ goto err_register_irq;
+ }
+ priv->irq = priv->pdev->irq;
+
return rc;
+err_register_irq:
err_register_hw:
err_set_hw_specs:
err_get_hw_specs:
@@ -699,7 +700,7 @@ err_mwl_rx_init:
err_mwl_tx_init:
- wiphy_err(hw->wiphy, "init fail");
+ wiphy_err(hw->wiphy, "init fail\n");
return rc;
}
@@ -710,11 +711,18 @@ static void mwl_wl_deinit(struct mwl_priv *priv)
hw = priv->hw;
+ if (priv->irq != -1) {
+ free_irq(priv->pdev->irq, hw);
+ priv->irq = -1;
+ }
+
ieee80211_unregister_hw(hw);
mwl_rx_deinit(hw);
mwl_tx_deinit(hw);
+ tasklet_kill(&priv->qe_task);
tasklet_kill(&priv->rx_task);
tasklet_kill(&priv->tx_task);
+ cancel_work_sync(&priv->watchdog_ba_handle);
mwl_fwcmd_reset(hw);
}
@@ -741,7 +749,7 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return rc;
}
- rc = pci_set_dma_mask(pdev, 0xffffffff);
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc) {
pr_err("%s: 32-bit PCI DMA not supported",
MWL_DRV_NAME);
@@ -768,6 +776,10 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
priv->hw = hw;
priv->pdev = pdev;
priv->chip_type = id->driver_data;
+ priv->disable_2g = false;
+ priv->disable_5g = false;
+ priv->antenna_tx = mwl_chip_tbl[priv->chip_type].antenna_tx;
+ priv->antenna_rx = mwl_chip_tbl[priv->chip_type].antenna_rx;
rc = mwl_alloc_pci_resource(priv);
if (rc)
@@ -775,7 +787,7 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
rc = mwl_init_firmware(priv, mwl_chip_tbl[priv->chip_type].fw_image);
if (rc) {
- wiphy_err(hw->wiphy, "%s: fail to initialize firmware",
+ wiphy_err(hw->wiphy, "%s: fail to initialize firmware\n",
MWL_DRV_NAME);
goto err_init_firmware;
}
@@ -783,24 +795,36 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* firmware is loaded to H/W, it can be released now */
release_firmware(priv->fw_ucode);
- rc = mwl_process_of_dts(priv);
- if (rc) {
- wiphy_err(hw->wiphy, "%s: fail to load dts mwlwifi parameters",
- MWL_DRV_NAME);
- goto err_process_of_dts;
- }
+ mwl_process_of_dts(priv);
rc = mwl_wl_init(priv);
if (rc) {
- wiphy_err(hw->wiphy, "%s: fail to initialize wireless lan",
+ wiphy_err(hw->wiphy, "%s: fail to initialize wireless lan\n",
MWL_DRV_NAME);
goto err_wl_init;
}
+ wiphy_info(priv->hw->wiphy,
+ "2G: %s\n", priv->disable_2g ? "disable" : "enable");
+ wiphy_info(priv->hw->wiphy,
+ "5G: %s\n", priv->disable_5g ? "disable" : "enable");
+
+ if (priv->antenna_tx == ANTENNA_TX_4_AUTO)
+ wiphy_info(priv->hw->wiphy, "TX: 4 antennas\n");
+ else if (priv->antenna_tx == ANTENNA_TX_2)
+ wiphy_info(priv->hw->wiphy, "TX: 2 antennas\n");
+ else
+ wiphy_info(priv->hw->wiphy, "TX: unknown\n");
+ if (priv->antenna_rx == ANTENNA_RX_4_AUTO)
+ wiphy_info(priv->hw->wiphy, "RX: 4 antennas\n");
+ else if (priv->antenna_rx == ANTENNA_RX_2)
+ wiphy_info(priv->hw->wiphy, "RX: 2 antennas\n");
+ else
+ wiphy_info(priv->hw->wiphy, "RX: unknown\n");
+
return rc;
err_wl_init:
-err_process_of_dts:
err_init_firmware:
mwl_fwcmd_reset(hw);
diff --git a/rx.c b/rx.c
index 34dafdf..3390c5d 100644
--- a/rx.c
+++ b/rx.c
@@ -1,13 +1,19 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file implements receive related functions.
- */
+/* Description: This file implements receive related functions. */
#include <linux/skbuff.h>
@@ -18,10 +24,8 @@
#define MAX_NUM_RX_RING_BYTES (SYSADPT_MAX_NUM_RX_DESC * \
sizeof(struct mwl_rx_desc))
-#define FIRST_RXD priv->desc_data[0].prx_ring[0]
-#define CURR_RXD priv->desc_data[0].prx_ring[curr_desc]
-#define NEXT_RXD priv->desc_data[0].prx_ring[curr_desc + 1]
-#define LAST_RXD priv->desc_data[0].prx_ring[SYSADPT_MAX_NUM_RX_DESC - 1]
+#define MAX_NUM_RX_HNDL_BYTES (SYSADPT_MAX_NUM_RX_DESC * \
+ sizeof(struct mwl_rx_hndl))
#define DECRYPT_ERR_MASK 0x80
#define GENERAL_DECRYPT_ERR 0xFF
@@ -46,142 +50,157 @@
static int mwl_rx_ring_alloc(struct mwl_priv *priv)
{
- priv->desc_data[0].prx_ring =
- (struct mwl_rx_desc *)
+ struct mwl_desc_data *desc;
+
+ desc = &priv->desc_data[0];
+
+ desc->prx_ring = (struct mwl_rx_desc *)
dma_alloc_coherent(&priv->pdev->dev,
MAX_NUM_RX_RING_BYTES,
- &priv->desc_data[0].pphys_rx_ring,
+ &desc->pphys_rx_ring,
GFP_KERNEL);
- if (!priv->desc_data[0].prx_ring) {
- wiphy_err(priv->hw->wiphy, "can not alloc mem");
+ if (!desc->prx_ring) {
+ wiphy_err(priv->hw->wiphy, "cannot alloc mem\n");
return -ENOMEM;
}
- memset(priv->desc_data[0].prx_ring, 0x00, MAX_NUM_RX_RING_BYTES);
+ memset(desc->prx_ring, 0x00, MAX_NUM_RX_RING_BYTES);
+
+ desc->rx_hndl = kmalloc(MAX_NUM_RX_HNDL_BYTES, GFP_KERNEL);
+
+ if (!desc->rx_hndl) {
+ dma_free_coherent(&priv->pdev->dev,
+ MAX_NUM_RX_RING_BYTES,
+ desc->prx_ring,
+ desc->pphys_rx_ring);
+ return -ENOMEM;
+ }
+
+ memset(desc->rx_hndl, 0x00, MAX_NUM_RX_HNDL_BYTES);
return 0;
}
static int mwl_rx_ring_init(struct mwl_priv *priv)
{
- int curr_desc;
struct mwl_desc_data *desc;
+ int i;
+ struct mwl_rx_hndl *rx_hndl;
+ dma_addr_t dma;
+ u32 val;
desc = &priv->desc_data[0];
if (desc->prx_ring) {
desc->rx_buf_size = SYSADPT_MAX_AGGR_SIZE;
- for (curr_desc = 0; curr_desc < SYSADPT_MAX_NUM_RX_DESC;
- curr_desc++) {
- CURR_RXD.psk_buff =
+ for (i = 0; i < SYSADPT_MAX_NUM_RX_DESC; i++) {
+ rx_hndl = &desc->rx_hndl[i];
+ rx_hndl->psk_buff =
dev_alloc_skb(desc->rx_buf_size);
- if (skb_linearize(CURR_RXD.psk_buff)) {
- dev_kfree_skb_any(CURR_RXD.psk_buff);
+ if (!rx_hndl->psk_buff) {
wiphy_err(priv->hw->wiphy,
- "need linearize memory");
+ "rxdesc %i: no skbuff available\n",
+ i);
return -ENOMEM;
}
- skb_reserve(CURR_RXD.psk_buff,
+ skb_reserve(rx_hndl->psk_buff,
SYSADPT_MIN_BYTES_HEADROOM);
- CURR_RXD.rx_control = EAGLE_RXD_CTRL_DRIVER_OWN;
- CURR_RXD.status = EAGLE_RXD_STATUS_OK;
- CURR_RXD.qos_ctrl = 0x0000;
- CURR_RXD.channel = 0x00;
- CURR_RXD.rssi = 0x00;
-
- if (CURR_RXD.psk_buff) {
- dma_addr_t dma;
- u32 val;
-
- CURR_RXD.pkt_len =
- cpu_to_le16(SYSADPT_MAX_AGGR_SIZE);
- CURR_RXD.pbuff_data = CURR_RXD.psk_buff->data;
- dma = pci_map_single(priv->pdev,
- CURR_RXD.psk_buff->data,
- desc->rx_buf_size,
- PCI_DMA_FROMDEVICE);
- CURR_RXD.pphys_buff_data =
- cpu_to_le32(dma);
- CURR_RXD.pnext = &NEXT_RXD;
- val = (u32)desc->pphys_rx_ring +
- ((curr_desc + 1) *
- sizeof(struct mwl_rx_desc));
- CURR_RXD.pphys_next =
- cpu_to_le32(val);
- } else {
+ desc->prx_ring[i].rx_control =
+ EAGLE_RXD_CTRL_DRIVER_OWN;
+ desc->prx_ring[i].status = EAGLE_RXD_STATUS_OK;
+ desc->prx_ring[i].qos_ctrl = 0x0000;
+ desc->prx_ring[i].channel = 0x00;
+ desc->prx_ring[i].rssi = 0x00;
+ desc->prx_ring[i].pkt_len =
+ cpu_to_le16(SYSADPT_MAX_AGGR_SIZE);
+ dma = pci_map_single(priv->pdev,
+ rx_hndl->psk_buff->data,
+ desc->rx_buf_size,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(priv->pdev, dma)) {
wiphy_err(priv->hw->wiphy,
- "rxdesc %i: no skbuff available",
- curr_desc);
+ "failed to map pci memory!\n");
return -ENOMEM;
}
+ desc->prx_ring[i].pphys_buff_data = cpu_to_le32(dma);
+ val = (u32)desc->pphys_rx_ring +
+ ((i + 1) * sizeof(struct mwl_rx_desc));
+ desc->prx_ring[i].pphys_next = cpu_to_le32(val);
+ rx_hndl->pdesc = &desc->prx_ring[i];
+ if (i < (SYSADPT_MAX_NUM_RX_DESC - 1))
+ rx_hndl->pnext = &desc->rx_hndl[i + 1];
}
- LAST_RXD.pphys_next =
+ desc->prx_ring[SYSADPT_MAX_NUM_RX_DESC - 1].pphys_next =
cpu_to_le32((u32)desc->pphys_rx_ring);
- LAST_RXD.pnext = &FIRST_RXD;
- priv->desc_data[0].pnext_rx_desc = &FIRST_RXD;
+ desc->rx_hndl[SYSADPT_MAX_NUM_RX_DESC - 1].pnext =
+ &desc->rx_hndl[0];
+ desc->pnext_rx_hndl = &desc->rx_hndl[0];
return 0;
}
- wiphy_err(priv->hw->wiphy, "no valid RX mem");
+ wiphy_err(priv->hw->wiphy, "no valid RX mem\n");
return -ENOMEM;
}
static void mwl_rx_ring_cleanup(struct mwl_priv *priv)
{
- int curr_desc;
-
- if (priv->desc_data[0].prx_ring) {
- for (curr_desc = 0; curr_desc < SYSADPT_MAX_NUM_RX_DESC;
- curr_desc++) {
- if (!CURR_RXD.psk_buff)
- continue;
+ struct mwl_desc_data *desc;
+ int i;
+ struct mwl_rx_hndl *rx_hndl;
- if (skb_shinfo(CURR_RXD.psk_buff)->nr_frags)
- skb_shinfo(CURR_RXD.psk_buff)->nr_frags = 0;
+ desc = &priv->desc_data[0];
- if (skb_shinfo(CURR_RXD.psk_buff)->frag_list)
- skb_shinfo(CURR_RXD.psk_buff)->frag_list = NULL;
+ if (desc->prx_ring) {
+ for (i = 0; i < SYSADPT_MAX_NUM_RX_DESC; i++) {
+ rx_hndl = &desc->rx_hndl[i];
+ if (!rx_hndl->psk_buff)
+ continue;
pci_unmap_single(priv->pdev,
le32_to_cpu
- (CURR_RXD.pphys_buff_data),
- priv->desc_data[0].rx_buf_size,
+ (rx_hndl->pdesc->pphys_buff_data),
+ desc->rx_buf_size,
PCI_DMA_FROMDEVICE);
- dev_kfree_skb_any(CURR_RXD.psk_buff);
+ dev_kfree_skb_any(rx_hndl->psk_buff);
wiphy_info(priv->hw->wiphy,
- "unmapped+free'd %i 0x%p 0x%x %i",
- curr_desc, CURR_RXD.pbuff_data,
- le32_to_cpu(CURR_RXD.pphys_buff_data),
- priv->desc_data[0].rx_buf_size);
+ "unmapped+free'd %i 0x%p 0x%x %i\n",
+ i, rx_hndl->psk_buff->data,
+ le32_to_cpu(rx_hndl->pdesc->pphys_buff_data),
+ desc->rx_buf_size);
- CURR_RXD.pbuff_data = NULL;
- CURR_RXD.psk_buff = NULL;
+ rx_hndl->psk_buff = NULL;
}
}
}
static void mwl_rx_ring_free(struct mwl_priv *priv)
{
- if (priv->desc_data[0].prx_ring) {
+ struct mwl_desc_data *desc;
+
+ desc = &priv->desc_data[0];
+
+ if (desc->prx_ring) {
mwl_rx_ring_cleanup(priv);
dma_free_coherent(&priv->pdev->dev,
MAX_NUM_RX_RING_BYTES,
- priv->desc_data[0].prx_ring,
- priv->desc_data[0].pphys_rx_ring);
+ desc->prx_ring,
+ desc->pphys_rx_ring);
- priv->desc_data[0].prx_ring = NULL;
+ desc->prx_ring = NULL;
}
- priv->desc_data[0].pnext_rx_desc = NULL;
+ kfree(desc->rx_hndl);
+
+ desc->pnext_rx_hndl = NULL;
}
static inline void mwl_rx_prepare_status(struct mwl_rx_desc *pdesc,
@@ -212,8 +231,10 @@ static inline void mwl_rx_prepare_status(struct mwl_rx_desc *pdesc,
status->flag |= RX_FLAG_VHT;
if (bw == RX_RATE_INFO_HT40)
status->flag |= RX_FLAG_40MHZ;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 18, 0)
if (bw == RX_RATE_INFO_HT80)
status->vht_flag |= RX_VHT_FLAG_80MHZ;
+#endif
if (gi == RX_RATE_INFO_SHORT_INTERVAL)
status->flag |= RX_FLAG_SHORT_GI;
status->vht_nss = (nss + 1);
@@ -264,16 +285,15 @@ static inline struct mwl_vif *mwl_rx_find_vif_bss(struct mwl_priv *priv,
u8 *bssid)
{
struct mwl_vif *mwl_vif;
- unsigned long flags;
- spin_lock_irqsave(&priv->vif_lock, flags);
+ spin_lock_bh(&priv->vif_lock);
list_for_each_entry(mwl_vif, &priv->vif_list, list) {
if (memcmp(bssid, mwl_vif->bssid, ETH_ALEN) == 0) {
- spin_unlock_irqrestore(&priv->vif_lock, flags);
+ spin_unlock_bh(&priv->vif_lock);
return mwl_vif;
}
}
- spin_unlock_irqrestore(&priv->vif_lock, flags);
+ spin_unlock_bh(&priv->vif_lock);
return NULL;
}
@@ -299,70 +319,67 @@ static inline void mwl_rx_remove_dma_header(struct sk_buff *skb, __le16 qos)
skb_pull(skb, sizeof(*tr) - hdrlen);
}
-static int mwl_rx_refill(struct mwl_priv *priv, struct mwl_rx_desc *pdesc)
+static int mwl_rx_refill(struct mwl_priv *priv, struct mwl_rx_hndl *rx_hndl)
{
- pdesc->psk_buff = dev_alloc_skb(priv->desc_data[0].rx_buf_size);
+ struct mwl_desc_data *desc;
+ dma_addr_t dma;
- if (!pdesc->psk_buff)
- goto nomem;
+ desc = &priv->desc_data[0];
- if (skb_linearize(pdesc->psk_buff)) {
- dev_kfree_skb_any(pdesc->psk_buff);
- wiphy_err(priv->hw->wiphy, "need linearize memory");
- goto nomem;
- }
+ rx_hndl->psk_buff = dev_alloc_skb(desc->rx_buf_size);
- skb_reserve(pdesc->psk_buff, SYSADPT_MIN_BYTES_HEADROOM);
+ if (!rx_hndl->psk_buff)
+ return -ENOMEM;
- pdesc->status = EAGLE_RXD_STATUS_OK;
- pdesc->qos_ctrl = 0x0000;
- pdesc->channel = 0x00;
- pdesc->rssi = 0x00;
+ skb_reserve(rx_hndl->psk_buff, SYSADPT_MIN_BYTES_HEADROOM);
+
+ rx_hndl->pdesc->status = EAGLE_RXD_STATUS_OK;
+ rx_hndl->pdesc->qos_ctrl = 0x0000;
+ rx_hndl->pdesc->channel = 0x00;
+ rx_hndl->pdesc->rssi = 0x00;
+ rx_hndl->pdesc->pkt_len = cpu_to_le16(desc->rx_buf_size);
+
+ dma = pci_map_single(priv->pdev,
+ rx_hndl->psk_buff->data,
+ desc->rx_buf_size,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(priv->pdev, dma)) {
+ dev_kfree_skb_any(rx_hndl->psk_buff);
+ wiphy_err(priv->hw->wiphy,
+ "failed to map pci memory!\n");
+ return -ENOMEM;
+ }
- pdesc->pkt_len = cpu_to_le16(priv->desc_data[0].rx_buf_size);
- pdesc->pbuff_data = pdesc->psk_buff->data;
- pdesc->pphys_buff_data =
- cpu_to_le32(pci_map_single(priv->pdev,
- pdesc->psk_buff->data,
- priv->desc_data[0].rx_buf_size,
- PCI_DMA_BIDIRECTIONAL));
+ rx_hndl->pdesc->pphys_buff_data = cpu_to_le32(dma);
return 0;
-
-nomem:
-
- wiphy_err(priv->hw->wiphy, "no memory");
-
- return -ENOMEM;
}
int mwl_rx_init(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
int rc;
- priv = hw->priv;
-
rc = mwl_rx_ring_alloc(priv);
if (rc) {
- wiphy_err(hw->wiphy, "allocating RX ring failed");
- } else {
- rc = mwl_rx_ring_init(priv);
- if (rc) {
- mwl_rx_ring_free(priv);
- wiphy_err(hw->wiphy,
- "initializing RX ring failed");
- }
+ wiphy_err(hw->wiphy, "allocating RX ring failed\n");
+ return rc;
+ }
+
+ rc = mwl_rx_ring_init(priv);
+ if (rc) {
+ mwl_rx_ring_free(priv);
+ wiphy_err(hw->wiphy,
+ "initializing RX ring failed\n");
+ return rc;
}
- return rc;
+ return 0;
}
void mwl_rx_deinit(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
-
- priv = hw->priv;
+ struct mwl_priv *priv = hw->priv;
mwl_rx_ring_cleanup(priv);
mwl_rx_ring_free(priv);
@@ -371,8 +388,9 @@ void mwl_rx_deinit(struct ieee80211_hw *hw)
void mwl_rx_recv(unsigned long data)
{
struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
- struct mwl_priv *priv;
- struct mwl_rx_desc *curr_desc;
+ struct mwl_priv *priv = hw->priv;
+ struct mwl_desc_data *desc;
+ struct mwl_rx_hndl *curr_hndl;
int work_done = 0;
struct sk_buff *prx_skb = NULL;
int pkt_len;
@@ -381,11 +399,10 @@ void mwl_rx_recv(unsigned long data)
struct ieee80211_hdr *wh;
u32 status_mask;
- priv = hw->priv;
-
- curr_desc = priv->desc_data[0].pnext_rx_desc;
+ desc = &priv->desc_data[0];
+ curr_hndl = desc->pnext_rx_hndl;
- if (!curr_desc) {
+ if (!curr_hndl) {
status_mask = readl(priv->iobase1 +
MACREG_REG_A2H_INTERRUPT_STATUS_MASK);
writel(status_mask | MACREG_A2HRIC_BIT_RX_RDY,
@@ -393,34 +410,35 @@ void mwl_rx_recv(unsigned long data)
priv->is_rx_schedule = false;
- wiphy_warn(hw->wiphy, "busy or no receiving packets");
+ wiphy_warn(hw->wiphy, "busy or no receiving packets\n");
return;
}
- while ((curr_desc->rx_control == EAGLE_RXD_CTRL_DMA_OWN) &&
+ while ((curr_hndl->pdesc->rx_control == EAGLE_RXD_CTRL_DMA_OWN) &&
(work_done < priv->recv_limit)) {
- prx_skb = curr_desc->psk_buff;
+ prx_skb = curr_hndl->psk_buff;
if (!prx_skb)
goto out;
pci_unmap_single(priv->pdev,
- le32_to_cpu(curr_desc->pphys_buff_data),
- priv->desc_data[0].rx_buf_size,
+ le32_to_cpu(curr_hndl->pdesc->pphys_buff_data),
+ desc->rx_buf_size,
PCI_DMA_FROMDEVICE);
- pkt_len = le16_to_cpu(curr_desc->pkt_len);
+ pkt_len = le16_to_cpu(curr_hndl->pdesc->pkt_len);
if (skb_tailroom(prx_skb) < pkt_len) {
dev_kfree_skb_any(prx_skb);
goto out;
}
- if (curr_desc->channel != hw->conf.chandef.chan->hw_value) {
+ if (curr_hndl->pdesc->channel !=
+ hw->conf.chandef.chan->hw_value) {
dev_kfree_skb_any(prx_skb);
goto out;
}
- mwl_rx_prepare_status(curr_desc, &status);
+ mwl_rx_prepare_status(curr_hndl->pdesc, &status);
- priv->noise = -curr_desc->noise_floor;
+ priv->noise = -curr_hndl->pdesc->noise_floor;
wh = &((struct mwl_dma_data *)prx_skb->data)->wh;
@@ -438,7 +456,7 @@ void mwl_rx_recv(unsigned long data)
/* When MMIC ERROR is encountered
* by the firmware, payload is
* dropped and only 32 bytes of
- * mwl8k Firmware header is sent
+ * mwlwifi Firmware header is sent
* to the host.
*
* We need to add four bytes of
@@ -464,18 +482,18 @@ void mwl_rx_recv(unsigned long data)
}
skb_put(prx_skb, pkt_len);
- mwl_rx_remove_dma_header(prx_skb, curr_desc->qos_ctrl);
+ mwl_rx_remove_dma_header(prx_skb, curr_hndl->pdesc->qos_ctrl);
memcpy(IEEE80211_SKB_RXCB(prx_skb), &status, sizeof(status));
ieee80211_rx(hw, prx_skb);
out:
- mwl_rx_refill(priv, curr_desc);
- curr_desc->rx_control = EAGLE_RXD_CTRL_DRIVER_OWN;
- curr_desc->qos_ctrl = 0;
- curr_desc = curr_desc->pnext;
+ mwl_rx_refill(priv, curr_hndl);
+ curr_hndl->pdesc->rx_control = EAGLE_RXD_CTRL_DRIVER_OWN;
+ curr_hndl->pdesc->qos_ctrl = 0;
+ curr_hndl = curr_hndl->pnext;
work_done++;
}
- priv->desc_data[0].pnext_rx_desc = curr_desc;
+ desc->pnext_rx_hndl = curr_hndl;
status_mask = readl(priv->iobase1 +
MACREG_REG_A2H_INTERRUPT_STATUS_MASK);
diff --git a/rx.h b/rx.h
index a4d2478..d32c558 100644
--- a/rx.h
+++ b/rx.h
@@ -1,19 +1,25 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file defines receive related functions.
- */
+/* Description: This file defines receive related functions. */
-#ifndef _mwl_rx_h_
-#define _mwl_rx_h_
+#ifndef _rx_h_
+#define _rx_h_
int mwl_rx_init(struct ieee80211_hw *hw);
void mwl_rx_deinit(struct ieee80211_hw *hw);
void mwl_rx_recv(unsigned long data);
-#endif /* _mwl_rx_h_ */
+#endif /* _rx_h_ */
diff --git a/sysadpt.h b/sysadpt.h
index eb6fa86..bf8f3bd 100644
--- a/sysadpt.h
+++ b/sysadpt.h
@@ -1,13 +1,19 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file defines system adaptation related information.
- */
+/* Description: This file defines system adaptation related information. */
#ifndef _mwl_sysadpt_h_
#define _mwl_sysadpt_h_
@@ -48,7 +54,11 @@
#define SYSADPT_AMPDU_PACKET_THRESHOLD 64
-#define SYSADPT_AMSDU_MAX_SIZE 3300
+#define SYSADPT_AMSDU_FW_MAX_SIZE 3300
+
+#define SYSADPT_AMSDU_4K_MAX_SIZE SYSADPT_AMSDU_FW_MAX_SIZE
+
+#define SYSADPT_AMSDU_8K_MAX_SIZE SYSADPT_AMSDU_FW_MAX_SIZE
#define SYSADPT_AMSDU_ALLOW_SIZE 1540
diff --git a/test/hostapd.conf.1.multi_bssid b/test/hostapd.conf.1.multi_bssid
index 228ba1c..a85a97d 100644
--- a/test/hostapd.conf.1.multi_bssid
+++ b/test/hostapd.conf.1.multi_bssid
@@ -9,8 +9,6 @@ auth_algs=1
wmm_enabled=1
ieee80211n=1
ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40]
-ieee80211ac=1
-vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]
bss=wlan0_0
ssid=mwlwifi_ap_tset2
wpa=2
diff --git a/test/hostapd.conf.1.open b/test/hostapd.conf.1.open
index d5cc39d..f9e14f7 100644
--- a/test/hostapd.conf.1.open
+++ b/test/hostapd.conf.1.open
@@ -9,6 +9,4 @@ auth_algs=1
wmm_enabled=1
ieee80211n=1
ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40]
-ieee80211ac=1
-vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]
diff --git a/tx.c b/tx.c
index 57b6dd4..7687e38 100644
--- a/tx.c
+++ b/tx.c
@@ -1,13 +1,19 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file implements transmit related functions.
- */
+/* Description: This file implements transmit related functions. */
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
@@ -20,12 +26,8 @@
#define MAX_NUM_TX_RING_BYTES (SYSADPT_MAX_NUM_TX_DESC * \
sizeof(struct mwl_tx_desc))
-#define FIRST_TXD(i) priv->desc_data[i].ptx_ring[0]
-#define CURR_TXD(i) priv->desc_data[i].ptx_ring[curr_desc]
-#define NEXT_TXD(i) priv->desc_data[i].ptx_ring[curr_desc + 1]
-#define LAST_TXD(i) priv->desc_data[i].ptx_ring[SYSADPT_MAX_NUM_TX_DESC - 1]
-
-#define STALE_TXD(i) priv->desc_data[i].pstale_tx_desc
+#define MAX_NUM_TX_HNDL_BYTES (SYSADPT_MAX_NUM_TX_DESC * \
+ sizeof(struct mwl_tx_hndl))
#define EAGLE_TXD_XMITCTRL_USE_MC_RATE 0x8 /* Use multicast data rate */
@@ -59,40 +61,76 @@ enum {
IEEE_TYPE_DATA
};
+struct ccmp_hdr {
+ __le16 iv16;
+ u8 rsvd;
+ u8 key_id;
+ __le32 iv32;
+} __packed;
+
static int mwl_tx_ring_alloc(struct mwl_priv *priv)
{
+ struct mwl_desc_data *desc;
int num;
u8 *mem;
- mem = (u8 *)dma_alloc_coherent(&priv->pdev->dev,
- MAX_NUM_TX_RING_BYTES * SYSADPT_NUM_OF_DESC_DATA,
- &priv->desc_data[0].pphys_tx_ring, GFP_KERNEL);
+ desc = &priv->desc_data[0];
+
+ mem = dma_alloc_coherent(&priv->pdev->dev,
+ MAX_NUM_TX_RING_BYTES *
+ SYSADPT_NUM_OF_DESC_DATA,
+ &desc->pphys_tx_ring,
+ GFP_KERNEL);
if (!mem) {
- wiphy_err(priv->hw->wiphy, "can not alloc mem");
+ wiphy_err(priv->hw->wiphy, "cannot alloc mem\n");
return -ENOMEM;
}
for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) {
- priv->desc_data[num].ptx_ring = (struct mwl_tx_desc *)
+ desc = &priv->desc_data[num];
+
+ desc->ptx_ring = (struct mwl_tx_desc *)
(mem + num * MAX_NUM_TX_RING_BYTES);
- priv->desc_data[num].pphys_tx_ring = (dma_addr_t)
+ desc->pphys_tx_ring = (dma_addr_t)
((u32)priv->desc_data[0].pphys_tx_ring +
num * MAX_NUM_TX_RING_BYTES);
- memset(priv->desc_data[num].ptx_ring, 0x00,
+ memset(desc->ptx_ring, 0x00,
MAX_NUM_TX_RING_BYTES);
}
+ mem = kmalloc(MAX_NUM_TX_HNDL_BYTES * SYSADPT_NUM_OF_DESC_DATA,
+ GFP_KERNEL);
+
+ if (!mem) {
+ wiphy_err(priv->hw->wiphy, "cannot alloc mem\n");
+ dma_free_coherent(&priv->pdev->dev,
+ MAX_NUM_TX_RING_BYTES *
+ SYSADPT_NUM_OF_DESC_DATA,
+ priv->desc_data[0].ptx_ring,
+ priv->desc_data[0].pphys_tx_ring);
+ return -ENOMEM;
+ }
+
+ for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) {
+ desc = &priv->desc_data[num];
+
+ desc->tx_hndl = (struct mwl_tx_hndl *)
+ (mem + num * MAX_NUM_TX_HNDL_BYTES);
+
+ memset(desc->tx_hndl, 0x00,
+ MAX_NUM_TX_HNDL_BYTES);
+ }
+
return 0;
}
static int mwl_tx_ring_init(struct mwl_priv *priv)
{
- int curr_desc;
+ int num, i;
struct mwl_desc_data *desc;
- int num;
for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) {
skb_queue_head_init(&priv->txq[num]);
@@ -101,23 +139,27 @@ static int mwl_tx_ring_init(struct mwl_priv *priv)
desc = &priv->desc_data[num];
if (desc->ptx_ring) {
- for (curr_desc = 0; curr_desc < SYSADPT_MAX_NUM_TX_DESC;
- curr_desc++) {
- CURR_TXD(num).status =
+ for (i = 0; i < SYSADPT_MAX_NUM_TX_DESC; i++) {
+ desc->ptx_ring[i].status =
cpu_to_le32(EAGLE_TXD_STATUS_IDLE);
- CURR_TXD(num).pnext = &NEXT_TXD(num);
- CURR_TXD(num).pphys_next =
+ desc->ptx_ring[i].pphys_next =
cpu_to_le32((u32)desc->pphys_tx_ring +
- ((curr_desc + 1) *
- sizeof(struct mwl_tx_desc)));
+ ((i + 1) * sizeof(struct mwl_tx_desc)));
+ desc->tx_hndl[i].pdesc =
+ &desc->ptx_ring[i];
+ if (i < SYSADPT_MAX_NUM_TX_DESC - 1)
+ desc->tx_hndl[i].pnext =
+ &desc->tx_hndl[i + 1];
}
- LAST_TXD(num).pnext = &FIRST_TXD(num);
- LAST_TXD(num).pphys_next =
+ desc->ptx_ring[SYSADPT_MAX_NUM_TX_DESC - 1].pphys_next =
cpu_to_le32((u32)desc->pphys_tx_ring);
- desc->pstale_tx_desc = &FIRST_TXD(num);
- desc->pnext_tx_desc = &FIRST_TXD(num);
+ desc->tx_hndl[SYSADPT_MAX_NUM_TX_DESC - 1].pnext =
+ &desc->tx_hndl[0];
+
+ desc->pstale_tx_hndl = &desc->tx_hndl[0];
+ desc->pnext_tx_hndl = &desc->tx_hndl[0];
} else {
- wiphy_err(priv->hw->wiphy, "no valid TX mem");
+ wiphy_err(priv->hw->wiphy, "no valid TX mem\n");
return -ENOMEM;
}
}
@@ -128,41 +170,43 @@ static int mwl_tx_ring_init(struct mwl_priv *priv)
static void mwl_tx_ring_cleanup(struct mwl_priv *priv)
{
int cleaned_tx_desc = 0;
- int curr_desc;
- int num;
+ int num, i;
+ struct mwl_desc_data *desc;
for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) {
skb_queue_purge(&priv->txq[num]);
priv->fw_desc_cnt[num] = 0;
- if (priv->desc_data[num].ptx_ring) {
- for (curr_desc = 0; curr_desc < SYSADPT_MAX_NUM_TX_DESC;
- curr_desc++) {
- if (!CURR_TXD(num).psk_buff)
+
+ desc = &priv->desc_data[num];
+
+ if (desc->ptx_ring) {
+ for (i = 0; i < SYSADPT_MAX_NUM_TX_DESC; i++) {
+ if (!desc->tx_hndl[i].psk_buff)
continue;
wiphy_info(priv->hw->wiphy,
- "unmapped and free'd %i 0x%p 0x%x",
- curr_desc,
- CURR_TXD(num).psk_buff->data,
+ "unmapped and free'd %i 0x%p 0x%x\n",
+ i,
+ desc->tx_hndl[i].psk_buff->data,
le32_to_cpu(
- CURR_TXD(num).pkt_ptr));
+ desc->ptx_ring[i].pkt_ptr));
pci_unmap_single(priv->pdev,
le32_to_cpu(
- CURR_TXD(num).pkt_ptr),
- CURR_TXD(num).psk_buff->len,
+ desc->ptx_ring[i].pkt_ptr),
+ desc->tx_hndl[i].psk_buff->len,
PCI_DMA_TODEVICE);
- dev_kfree_skb_any(CURR_TXD(num).psk_buff);
- CURR_TXD(num).status =
+ dev_kfree_skb_any(desc->tx_hndl[i].psk_buff);
+ desc->ptx_ring[i].status =
cpu_to_le32(EAGLE_TXD_STATUS_IDLE);
- CURR_TXD(num).psk_buff = NULL;
- CURR_TXD(num).pkt_ptr = 0;
- CURR_TXD(num).pkt_len = 0;
+ desc->ptx_ring[i].pkt_ptr = 0;
+ desc->ptx_ring[i].pkt_len = 0;
+ desc->tx_hndl[i].psk_buff = NULL;
cleaned_tx_desc++;
}
}
}
- wiphy_info(priv->hw->wiphy, "cleaned %i TX descr", cleaned_tx_desc);
+ wiphy_info(priv->hw->wiphy, "cleaned %i TX descr\n", cleaned_tx_desc);
}
static void mwl_tx_ring_free(struct mwl_priv *priv)
@@ -180,9 +224,11 @@ static void mwl_tx_ring_free(struct mwl_priv *priv)
for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) {
if (priv->desc_data[num].ptx_ring)
priv->desc_data[num].ptx_ring = NULL;
- priv->desc_data[num].pstale_tx_desc = NULL;
- priv->desc_data[num].pnext_tx_desc = NULL;
+ priv->desc_data[num].pstale_tx_hndl = NULL;
+ priv->desc_data[num].pnext_tx_hndl = NULL;
}
+
+ kfree(priv->desc_data[0].tx_hndl);
}
static inline void mwl_tx_add_dma_header(struct mwl_priv *priv,
@@ -268,10 +314,12 @@ static inline void mwl_tx_encapsulate_frame(struct mwl_priv *priv,
static inline void mwl_tx_insert_ccmp_hdr(u8 *pccmp_hdr,
u8 key_id, u16 iv16, u32 iv32)
{
- *((u16 *)pccmp_hdr) = iv16;
- pccmp_hdr[2] = 0;
- pccmp_hdr[3] = EXT_IV | (key_id << 6);
- *((u32 *)&pccmp_hdr[4]) = iv32;
+ struct ccmp_hdr *ccmp_h = (struct ccmp_hdr *)pccmp_hdr;
+
+ ccmp_h->iv16 = cpu_to_le16(iv16);
+ ccmp_h->rsvd = 0;
+ ccmp_h->key_id = EXT_IV | (key_id << 6);
+ ccmp_h->iv32 = cpu_to_le32(iv32);
}
static inline int mwl_tx_tid_queue_mapping(u8 tid)
@@ -326,13 +374,16 @@ static inline void mwl_tx_count_packet(struct ieee80211_sta *sta, u8 tid)
static inline bool mwl_tx_available(struct mwl_priv *priv, int desc_num)
{
- if (!priv->desc_data[desc_num].pnext_tx_desc)
+ struct mwl_tx_hndl *tx_hndl;
+
+ tx_hndl = priv->desc_data[desc_num].pnext_tx_hndl;
+
+ if (!tx_hndl->pdesc)
return false;
- if (priv->desc_data[desc_num].pnext_tx_desc->status !=
- EAGLE_TXD_STATUS_IDLE) {
+ if (tx_hndl->pdesc->status != EAGLE_TXD_STATUS_IDLE) {
/* Interrupt F/W anyway */
- if (priv->desc_data[desc_num].pnext_tx_desc->status &
+ if (tx_hndl->pdesc->status &
cpu_to_le32(EAGLE_TXD_STATUS_FW_OWNED))
writel(MACREG_H2ARIC_BIT_PPA_READY,
priv->iobase1 +
@@ -348,20 +399,24 @@ static inline void mwl_tx_skb(struct mwl_priv *priv, int desc_num,
{
struct ieee80211_tx_info *tx_info;
struct mwl_tx_ctrl *tx_ctrl;
+ struct mwl_tx_hndl *tx_hndl;
struct mwl_tx_desc *tx_desc;
struct ieee80211_sta *sta;
+ struct ieee80211_vif *vif;
struct mwl_vif *mwl_vif;
struct ieee80211_key_conf *k_conf;
bool ccmp = false;
struct mwl_dma_data *dma_data;
struct ieee80211_hdr *wh;
+ dma_addr_t dma;
BUG_ON(!tx_skb);
tx_info = IEEE80211_SKB_CB(tx_skb);
tx_ctrl = (struct mwl_tx_ctrl *)&tx_info->status;
sta = (struct ieee80211_sta *)tx_ctrl->sta;
- mwl_vif = (struct mwl_vif *)tx_ctrl->vif;
+ vif = (struct ieee80211_vif *)tx_ctrl->vif;
+ mwl_vif = mwl_dev_get_vif(vif);
k_conf = (struct ieee80211_key_conf *)tx_ctrl->k_conf;
mwl_tx_encapsulate_frame(priv, tx_skb, k_conf, &ccmp);
@@ -380,7 +435,7 @@ static inline void mwl_tx_skb(struct mwl_priv *priv, int desc_num,
}
} else {
if (ccmp) {
- if (mwl_vif->is_sta) {
+ if (vif->type == NL80211_IFTYPE_STATION) {
mwl_tx_insert_ccmp_hdr(dma_data->data,
mwl_vif->keyidx,
mwl_vif->iv16,
@@ -403,78 +458,212 @@ static inline void mwl_tx_skb(struct mwl_priv *priv, int desc_num,
}
}
- tx_desc = priv->desc_data[desc_num].pnext_tx_desc;
+ tx_hndl = priv->desc_data[desc_num].pnext_tx_hndl;
+ tx_hndl->psk_buff = tx_skb;
+ tx_desc = tx_hndl->pdesc;
tx_desc->tx_priority = tx_ctrl->tx_priority;
tx_desc->qos_ctrl = cpu_to_le16(tx_ctrl->qos_ctrl);
- tx_desc->psk_buff = tx_skb;
tx_desc->pkt_len = cpu_to_le16(tx_skb->len);
tx_desc->packet_info = 0;
tx_desc->data_rate = 0;
- tx_desc->sta_info = tx_ctrl->sta;
tx_desc->type = tx_ctrl->type;
tx_desc->xmit_control = tx_ctrl->xmit_control;
tx_desc->sap_pkt_info = 0;
- tx_desc->pkt_ptr =
- cpu_to_le32(pci_map_single(priv->pdev, tx_skb->data,
- tx_skb->len, PCI_DMA_TODEVICE));
+ dma = pci_map_single(priv->pdev, tx_skb->data,
+ tx_skb->len, PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(priv->pdev, dma)) {
+ dev_kfree_skb_any(tx_skb);
+ wiphy_err(priv->hw->wiphy,
+ "failed to map pci memory!\n");
+ return;
+ }
+ tx_desc->pkt_ptr = cpu_to_le32(dma);
tx_desc->status = cpu_to_le32(EAGLE_TXD_STATUS_FW_OWNED);
- priv->desc_data[desc_num].pnext_tx_desc = tx_desc->pnext;
/* make sure all the memory transactions done by cpu were completed */
wmb(); /*Data Memory Barrier*/
writel(MACREG_H2ARIC_BIT_PPA_READY,
priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS);
+ priv->desc_data[desc_num].pnext_tx_hndl = tx_hndl->pnext;
priv->fw_desc_cnt[desc_num]++;
}
+static inline struct sk_buff *mwl_tx_do_amsdu(struct mwl_priv *priv,
+ int desc_num,
+ struct sk_buff *tx_skb,
+ struct mwl_tx_ctrl *tx_ctrl)
+{
+ struct ieee80211_sta *sta;
+ struct mwl_sta *sta_info;
+ struct mwl_amsdu_frag *amsdu;
+ int amsdu_allow_size;
+ struct ieee80211_hdr *wh;
+ int wh_len;
+ u16 len;
+ u8 *data;
+
+ sta = (struct ieee80211_sta *)tx_ctrl->sta;
+ sta_info = mwl_dev_get_sta(sta);
+
+ if (!sta_info->is_amsdu_allowed)
+ return tx_skb;
+
+ if (sta_info->amsdu_ctrl.cap == MWL_AMSDU_SIZE_4K)
+ amsdu_allow_size = SYSADPT_AMSDU_4K_MAX_SIZE;
+ else if (sta_info->amsdu_ctrl.cap == MWL_AMSDU_SIZE_8K)
+ amsdu_allow_size = SYSADPT_AMSDU_8K_MAX_SIZE;
+ else
+ return tx_skb;
+
+ spin_lock_bh(&sta_info->amsdu_lock);
+ amsdu = &sta_info->amsdu_ctrl.frag[desc_num];
+
+ if (tx_skb->len > SYSADPT_AMSDU_ALLOW_SIZE) {
+ if (amsdu->num) {
+ mwl_tx_skb(priv, desc_num, amsdu->skb);
+ amsdu->num = 0;
+ amsdu->cur_pos = NULL;
+
+ if (!mwl_tx_available(priv, desc_num)) {
+ skb_queue_head(&priv->txq[desc_num], tx_skb);
+ spin_unlock_bh(&sta_info->amsdu_lock);
+ return NULL;
+ }
+ }
+ spin_unlock_bh(&sta_info->amsdu_lock);
+ return tx_skb;
+ }
+
+ /* potential amsdu size, should add amsdu header 14 bytes +
+ * maximum padding 3.
+ */
+ wh = (struct ieee80211_hdr *)tx_skb->data;
+ wh_len = ieee80211_hdrlen(wh->frame_control);
+ len = tx_skb->len - wh_len + 17;
+
+ if (amsdu->num) {
+ if ((amsdu->skb->len + len) > amsdu_allow_size) {
+ mwl_tx_skb(priv, desc_num, amsdu->skb);
+ amsdu->num = 0;
+ amsdu->cur_pos = NULL;
+ }
+ }
+
+ amsdu->jiffies = jiffies;
+ len = tx_skb->len - wh_len;
+
+ if (amsdu->num == 0) {
+ struct sk_buff *newskb;
+ struct ieee80211_tx_info *tx_info;
+
+ newskb = dev_alloc_skb(amsdu_allow_size +
+ SYSADPT_MIN_BYTES_HEADROOM);
+
+ if (newskb == NULL) {
+ spin_unlock_bh(&sta_info->amsdu_lock);
+ return tx_skb;
+ }
+
+ data = newskb->data;
+
+ memcpy(data, tx_skb->data, wh_len);
+ ether_addr_copy(data + wh_len, ieee80211_get_DA(wh));
+ ether_addr_copy(data + wh_len + ETH_ALEN, ieee80211_get_SA(wh));
+ *(u8 *)(data + wh_len + ETH_HLEN - 1) = len & 0xff;
+ *(u8 *)(data + wh_len + ETH_HLEN - 2) = (len >> 8) & 0xff;
+ memcpy(data + wh_len + ETH_HLEN, tx_skb->data + wh_len, len);
+
+ skb_put(newskb, tx_skb->len + ETH_HLEN);
+ tx_ctrl->qos_ctrl |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+ tx_info = IEEE80211_SKB_CB(newskb);
+ memcpy(&tx_info->status, tx_ctrl, sizeof(*tx_ctrl));
+ amsdu->skb = newskb;
+ } else {
+ amsdu->cur_pos += amsdu->pad;
+ data = amsdu->cur_pos;
+
+ ether_addr_copy(data, ieee80211_get_DA(wh));
+ ether_addr_copy(data + ETH_ALEN, ieee80211_get_SA(wh));
+ *(u8 *)(data + ETH_HLEN - 1) = len & 0xff;
+ *(u8 *)(data + ETH_HLEN - 2) = (len >> 8) & 0xff;
+ memcpy(data + ETH_HLEN, tx_skb->data + wh_len, len);
+
+ skb_put(amsdu->skb, len + ETH_HLEN + amsdu->pad);
+ }
+
+ amsdu->num++;
+ amsdu->pad = ((len + ETH_HLEN) % 4) ? (4 - (len + ETH_HLEN) % 4) : 0;
+ amsdu->cur_pos = amsdu->skb->data + amsdu->skb->len;
+ dev_kfree_skb_any(tx_skb);
+
+ if (amsdu->num > SYSADPT_AMSDU_PACKET_THRESHOLD) {
+ amsdu->num = 0;
+ amsdu->cur_pos = NULL;
+ spin_unlock_bh(&sta_info->amsdu_lock);
+ return amsdu->skb;
+ }
+
+ spin_unlock_bh(&sta_info->amsdu_lock);
+ return NULL;
+}
+
static inline void mwl_tx_skbs(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
int num = SYSADPT_NUM_OF_DESC_DATA;
struct sk_buff *tx_skb;
- unsigned long flags;
- priv = hw->priv;
-
- spin_lock_irqsave(&priv->tx_desc_lock, flags);
+ spin_lock_bh(&priv->tx_desc_lock);
while (num--) {
while (skb_queue_len(&priv->txq[num]) > 0) {
- if (mwl_tx_available(priv, num) == false)
+ struct ieee80211_tx_info *tx_info;
+ struct mwl_tx_ctrl *tx_ctrl;
+
+ if (!mwl_tx_available(priv, num))
break;
+
tx_skb = skb_dequeue(&priv->txq[num]);
- mwl_tx_skb(priv, num, tx_skb);
+ tx_info = IEEE80211_SKB_CB(tx_skb);
+ tx_ctrl = (struct mwl_tx_ctrl *)&tx_info->status;
+
+ if ((tx_skb->protocol != cpu_to_be16(ETH_P_PAE)) &&
+ (tx_ctrl->tx_priority >= SYSADPT_TX_WMM_QUEUES)) {
+ tx_skb = mwl_tx_do_amsdu(priv, num,
+ tx_skb, tx_ctrl);
+ }
+
+ if (tx_skb)
+ mwl_tx_skb(priv, num, tx_skb);
}
}
- spin_unlock_irqrestore(&priv->tx_desc_lock, flags);
+ spin_unlock_bh(&priv->tx_desc_lock);
}
int mwl_tx_init(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
int rc;
- priv = hw->priv;
-
skb_queue_head_init(&priv->delay_q);
rc = mwl_tx_ring_alloc(priv);
if (rc) {
- wiphy_err(hw->wiphy, "allocating TX ring failed");
- } else {
- rc = mwl_tx_ring_init(priv);
- if (rc) {
- mwl_tx_ring_free(priv);
- wiphy_err(hw->wiphy, "initializing TX ring failed");
- }
+ wiphy_err(hw->wiphy, "allocating TX ring failed\n");
+ return rc;
+ }
+
+ rc = mwl_tx_ring_init(priv);
+ if (rc) {
+ mwl_tx_ring_free(priv);
+ wiphy_err(hw->wiphy, "initializing TX ring failed\n");
+ return rc;
}
- return rc;
+ return 0;
}
void mwl_tx_deinit(struct ieee80211_hw *hw)
{
- struct mwl_priv *priv;
-
- priv = hw->priv;
+ struct mwl_priv *priv = hw->priv;
skb_queue_purge(&priv->delay_q);
@@ -486,7 +675,7 @@ void mwl_tx_xmit(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
{
- struct mwl_priv *priv;
+ struct mwl_priv *priv = hw->priv;
int index;
struct ieee80211_sta *sta;
struct ieee80211_tx_info *tx_info;
@@ -504,7 +693,6 @@ void mwl_tx_xmit(struct ieee80211_hw *hw,
struct mwl_tx_ctrl *tx_ctrl;
struct ieee80211_key_conf *k_conf = NULL;
- priv = hw->priv;
index = skb_get_queue_mapping(skb);
sta = control->sta;
@@ -566,15 +754,25 @@ void mwl_tx_xmit(struct ieee80211_hw *hw,
* been setup.
*/
if (mgmtframe) {
+ u16 capab;
+
if (unlikely(ieee80211_is_action(wh->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
mgmt->u.action.u.addba_req.action_code ==
WLAN_ACTION_ADDBA_REQ)) {
- u16 capab =
- le16_to_cpu(mgmt->u.action.u.addba_req.capab);
+ capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
index = mwl_tx_tid_queue_mapping(tid);
}
+
+ if (unlikely(ieee80211_is_action(wh->frame_control) &&
+ mgmt->u.action.category == WLAN_CATEGORY_BACK &&
+ mgmt->u.action.u.addba_resp.action_code ==
+ WLAN_ACTION_ADDBA_RESP)) {
+ capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
+ capab |= 1;
+ mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
+ }
}
index = SYSADPT_TX_WMM_QUEUES - index - 1;
@@ -585,7 +783,7 @@ void mwl_tx_xmit(struct ieee80211_hw *hw,
tid = qos & 0xf;
mwl_tx_count_packet(sta, tid);
- spin_lock(&priv->stream_lock);
+ spin_lock_bh(&priv->stream_lock);
stream = mwl_fwcmd_lookup_stream(hw, sta->addr, tid);
if (stream) {
@@ -617,13 +815,13 @@ void mwl_tx_xmit(struct ieee80211_hw *hw,
* case, so this is really just a safety check.
*/
wiphy_warn(hw->wiphy,
- "can't send packet during ADDBA");
- spin_unlock(&priv->stream_lock);
+ "can't send packet during ADDBA\n");
+ spin_unlock_bh(&priv->stream_lock);
dev_kfree_skb_any(skb);
return;
}
} else {
- /* Defer calling mwl8k_start_stream so that the current
+ /* Defer calling mwl_fwcmd_start_stream so that the current
* skb can go out before the ADDBA request. This
* prevents sequence number mismatch at the recipient
* as described above.
@@ -636,7 +834,7 @@ void mwl_tx_xmit(struct ieee80211_hw *hw,
}
}
- spin_unlock(&priv->stream_lock);
+ spin_unlock_bh(&priv->stream_lock);
} else {
qos &= ~MWL_QOS_ACK_POLICY_MASK;
qos |= MWL_QOS_ACK_POLICY_NORMAL;
@@ -648,7 +846,7 @@ void mwl_tx_xmit(struct ieee80211_hw *hw,
tx_ctrl->type = (mgmtframe ? IEEE_TYPE_MANAGEMENT : IEEE_TYPE_DATA);
tx_ctrl->xmit_control = xmitcontrol;
tx_ctrl->sta = (void *)sta;
- tx_ctrl->vif = (void *)mwl_vif;
+ tx_ctrl->vif = (void *)tx_info->control.vif;
tx_ctrl->k_conf = (void *)k_conf;
if (skb_queue_len(&priv->txq[index]) > priv->txq_limit)
@@ -660,45 +858,47 @@ void mwl_tx_xmit(struct ieee80211_hw *hw,
/* Initiate the ampdu session here */
if (start_ba_session) {
- spin_lock(&priv->stream_lock);
+ spin_lock_bh(&priv->stream_lock);
if (mwl_fwcmd_start_stream(hw, stream))
mwl_fwcmd_remove_stream(hw, stream);
- spin_unlock(&priv->stream_lock);
+ spin_unlock_bh(&priv->stream_lock);
}
}
void mwl_tx_done(unsigned long data)
{
struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
- struct mwl_priv *priv;
- unsigned long flags;
+ struct mwl_priv *priv = hw->priv;
int num;
+ struct mwl_desc_data *desc;
+ struct mwl_tx_hndl *tx_hndl;
+ struct mwl_tx_desc *tx_desc;
struct sk_buff *done_skb;
u32 rate, format, bandwidth, short_gi, rate_id;
struct mwl_dma_data *tr;
struct ieee80211_tx_info *info;
int hdrlen;
- priv = hw->priv;
-
- spin_lock_irqsave(&priv->tx_desc_lock, flags);
+ spin_lock_bh(&priv->tx_desc_lock);
for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) {
- while (STALE_TXD(num) && (STALE_TXD(num)->status &
- cpu_to_le32(EAGLE_TXD_STATUS_OK)) &&
- (!(STALE_TXD(num)->status &
+ desc = &priv->desc_data[num];
+ tx_hndl = desc->pstale_tx_hndl;
+ tx_desc = tx_hndl->pdesc;
+
+ while (tx_hndl &&
+ (tx_desc->status & cpu_to_le32(EAGLE_TXD_STATUS_OK)) &&
+ (!(tx_desc->status &
cpu_to_le32(EAGLE_TXD_STATUS_FW_OWNED)))) {
pci_unmap_single(priv->pdev,
- le32_to_cpu(STALE_TXD(num)->pkt_ptr),
- STALE_TXD(num)->psk_buff->len,
+ le32_to_cpu(tx_desc->pkt_ptr),
+ le16_to_cpu(tx_desc->pkt_len),
PCI_DMA_TODEVICE);
- done_skb = STALE_TXD(num)->psk_buff;
- rate = le32_to_cpu(STALE_TXD(num)->rate_info);
- STALE_TXD(num)->pkt_len = 0;
- STALE_TXD(num)->psk_buff = NULL;
- STALE_TXD(num)->status =
+ done_skb = tx_hndl->psk_buff;
+ rate = le32_to_cpu(tx_desc->rate_info);
+ tx_desc->pkt_len = 0;
+ tx_desc->status =
cpu_to_le32(EAGLE_TXD_STATUS_IDLE);
- priv->fw_desc_cnt[num]--;
- STALE_TXD(num) = STALE_TXD(num)->pnext;
+ tx_hndl->psk_buff = NULL;
wmb(); /* memory barrier */
tr = (struct mwl_dma_data *)done_skb->data;
@@ -706,6 +906,8 @@ void mwl_tx_done(unsigned long data)
ieee80211_tx_info_clear_status(info);
info->status.rates[0].idx = -1;
+ info->status.rates[0].count = 0;
+ info->status.rates[0].flags = 0;
if (ieee80211_is_data(tr->wh.frame_control) ||
ieee80211_is_data_qos(tr->wh.frame_control)) {
@@ -761,16 +963,22 @@ void mwl_tx_done(unsigned long data)
info->flags |= IEEE80211_TX_STAT_ACK;
ieee80211_tx_status(hw, done_skb);
+
+ tx_hndl = tx_hndl->pnext;
+ tx_desc = tx_hndl->pdesc;
+ priv->fw_desc_cnt[num]--;
}
+
+ desc->pstale_tx_hndl = tx_hndl;
}
- spin_unlock_irqrestore(&priv->tx_desc_lock, flags);
+ spin_unlock_bh(&priv->tx_desc_lock);
if (priv->irq != -1) {
- u32 status;
+ u32 status_mask;
- status = readl(priv->iobase1 +
- MACREG_REG_A2H_INTERRUPT_STATUS_MASK);
- writel(status | MACREG_A2HRIC_BIT_TX_DONE,
+ status_mask = readl(priv->iobase1 +
+ MACREG_REG_A2H_INTERRUPT_STATUS_MASK);
+ writel(status_mask | MACREG_A2HRIC_BIT_TX_DONE,
priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK);
mwl_tx_skbs(hw);
@@ -778,3 +986,43 @@ void mwl_tx_done(unsigned long data)
priv->is_tx_schedule = false;
}
+
+void mwl_tx_flush_amsdu(unsigned long data)
+{
+ struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
+ struct mwl_priv *priv = hw->priv;
+ u32 status_mask;
+ struct mwl_sta *sta_info;
+ int i;
+ struct mwl_amsdu_frag *amsdu_frag;
+
+ spin_lock_bh(&priv->sta_lock);
+
+ list_for_each_entry(sta_info, &priv->sta_list, list) {
+ spin_lock_bh(&sta_info->amsdu_lock);
+ for (i = 0; i < SYSADPT_TX_WMM_QUEUES; i++) {
+ amsdu_frag = &sta_info->amsdu_ctrl.frag[i];
+ if (amsdu_frag->num) {
+ if (jiffies > (amsdu_frag->jiffies + 1)) {
+ spin_lock_bh(&priv->tx_desc_lock);
+ if (mwl_tx_available(priv, i)) {
+ mwl_tx_skb(priv, i, amsdu_frag->skb);
+ amsdu_frag->num = 0;
+ amsdu_frag->cur_pos = NULL;
+ }
+ spin_unlock_bh(&priv->tx_desc_lock);
+ }
+ }
+ }
+ spin_unlock_bh(&sta_info->amsdu_lock);
+ }
+
+ spin_unlock_bh(&priv->sta_lock);
+
+ status_mask = readl(priv->iobase1 +
+ MACREG_REG_A2H_INTERRUPT_STATUS_MASK);
+ writel(status_mask | MACREG_A2HRIC_BIT_QUEUE_EMPTY,
+ priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK);
+
+ priv->is_qe_schedule = false;
+}
diff --git a/tx.h b/tx.h
index df485f9..0dafc80 100644
--- a/tx.h
+++ b/tx.h
@@ -1,16 +1,22 @@
/*
* Copyright (C) 2006-2015, Marvell International Ltd.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
*/
-/* Description: This file defines transmit related functions.
- */
+/* Description: This file defines transmit related functions. */
-#ifndef _mwl_tx_h_
-#define _mwl_tx_h_
+#ifndef _tx_h_
+#define _tx_h_
int mwl_tx_init(struct ieee80211_hw *hw);
void mwl_tx_deinit(struct ieee80211_hw *hw);
@@ -18,5 +24,6 @@ void mwl_tx_xmit(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb);
void mwl_tx_done(unsigned long data);
+void mwl_tx_flush_amsdu(unsigned long data);
-#endif /* _mwl_tx_h_ */
+#endif /* _tx_h_ */