From 59e0d3d167a5bc2c03010df4ed54cc0653b5ae58 Mon Sep 17 00:00:00 2001 From: David Lin Date: Tue, 18 Aug 2015 17:04:34 +0800 Subject: 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 --- Kconfig | 28 +- Makefile | 2 +- Makefile.external | 2 +- Makefile.kernel | 2 + bin/firmware/88W8897.bin | Bin 134500 -> 489084 bytes dev.h | 131 ++-- fwcmd.c | 1300 +++++++-------------------------------- fwcmd.h | 22 +- fwdl.c | 31 +- fwdl.h | 24 +- hostcmd.h | 753 +++++++++++++++++++++++ isr.c | 48 +- isr.h | 22 +- mac80211.c | 192 +++--- mac80211.h | 19 - main.c | 182 +++--- rx.c | 314 +++++----- rx.h | 22 +- sysadpt.h | 22 +- test/hostapd.conf.1.multi_bssid | 2 - test/hostapd.conf.1.open | 2 - tx.c | 498 +++++++++++---- tx.h | 23 +- 23 files changed, 1959 insertions(+), 1682 deletions(-) create mode 100644 hostcmd.h delete mode 100644 mac80211.h 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 . 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 . 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 Binary files a/bin/firmware/88W8897.bin and b/bin/firmware/88W8897.bin 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 #include #include #include @@ -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 @@ -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 @@ -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 +#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 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 @@ -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 - -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 -#include +#ifdef CONFIG_OF +#include +#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 @@ -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 #include @@ -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_ */ -- cgit v1.2.3