diff options
author | David Lin <dlin@marvell.com> | 2015-06-19 04:49:53 +0800 |
---|---|---|
committer | David Lin <dlin@marvell.com> | 2015-06-19 04:49:53 +0800 |
commit | 2b93ae5bf32e49ab1b0eff2b27c943ba6adf9734 (patch) | |
tree | 3ef232489b0f0ce5624ebadaa4e6a35ff94e4626 | |
parent | f6f2b26593a35d269eb8c4475234965384c010af (diff) |
Commit mwlwifi driver 10.3.0.3
1. Modified the code in order to be accepted by linux wireless.
2. Let Tx thread be more modularized.
3. Fixed issue #20.
Note: Please check hostapd sample configuration files to know current setting for vht_capab.
Signed-off-by: David Lin <dlin@marvell.com>
-rw-r--r-- | Kconfig | 2 | ||||
-rw-r--r-- | Makefile | 20 | ||||
-rw-r--r-- | Makefile.external | 20 | ||||
-rw-r--r-- | Makefile.kernel | 14 | ||||
-rw-r--r-- | dev.h | 419 | ||||
-rw-r--r-- | fwcmd.c (renamed from mwl_fwcmd.c) | 3020 | ||||
-rw-r--r-- | fwcmd.h (renamed from mwl_fwcmd.h) | 31 | ||||
-rw-r--r-- | fwdl.c (renamed from mwl_fwdl.c) | 129 | ||||
-rw-r--r-- | fwdl.h | 19 | ||||
-rw-r--r-- | isr.c | 142 | ||||
-rw-r--r-- | isr.h | 20 | ||||
-rw-r--r-- | mac80211.c (renamed from mwl_mac80211.c) | 618 | ||||
-rw-r--r-- | mac80211.h | 19 | ||||
-rw-r--r-- | main.c (renamed from mwl_main.c) | 672 | ||||
-rw-r--r-- | mwl_debug.c | 207 | ||||
-rw-r--r-- | mwl_debug.h | 118 | ||||
-rw-r--r-- | mwl_dev.h | 465 | ||||
-rw-r--r-- | mwl_fwdl.h | 29 | ||||
-rw-r--r-- | mwl_mac80211.h | 32 | ||||
-rw-r--r-- | mwl_rx.h | 30 | ||||
-rw-r--r-- | mwl_tx.h | 34 | ||||
-rw-r--r-- | rx.c (renamed from mwl_rx.c) | 519 | ||||
-rw-r--r-- | rx.h | 19 | ||||
-rw-r--r-- | sysadpt.h (renamed from mwl_sysadpt.h) | 35 | ||||
-rw-r--r-- | test/hostapd.conf.1.multi_bssid | 2 | ||||
-rw-r--r-- | test/hostapd.conf.1.open | 2 | ||||
-rw-r--r-- | test/hostapd.conf.36.multi_bssid | 2 | ||||
-rw-r--r-- | test/hostapd.conf.36.open | 2 | ||||
-rw-r--r-- | test/hostapd.conf.36.open.80mhz | 2 | ||||
-rw-r--r-- | test/hostapd.conf.36.wpa2pskaes | 2 | ||||
-rw-r--r-- | test/hostapd.conf.36.wpa2pskaes.80mhz | 2 | ||||
-rw-r--r--[-rwxr-xr-x] | test/wpa_supplicant.conf.open | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | test/wpa_supplicant.conf.psk | 0 | ||||
-rw-r--r-- | tx.c (renamed from mwl_tx.c) | 1024 | ||||
-rw-r--r-- | tx.h | 22 |
35 files changed, 3101 insertions, 4592 deletions
@@ -1,6 +1,6 @@ config MWLWIFI tristate "Marvell Wireless WiFi driver (mwlwifi)" - depends on PCI && MAC80211 + depends on PCI && MAC80211 && MWIFIEX_PCIE=n select FW_LOADER select OF ---help--- @@ -1,23 +1,19 @@ obj-m += mwlwifi.o -mwlwifi-objs += mwl_main.o -mwlwifi-objs += mwl_mac80211.o -mwlwifi-objs += mwl_fwdl.o -mwlwifi-objs += mwl_fwcmd.o -mwlwifi-objs += mwl_tx.o -mwlwifi-objs += mwl_rx.o -mwlwifi-objs += mwl_debug.o +mwlwifi-objs += main.o +mwlwifi-objs += mac80211.o +mwlwifi-objs += fwdl.o +mwlwifi-objs += fwcmd.o +mwlwifi-objs += tx.o +mwlwifi-objs += rx.o +mwlwifi-objs += isr.o AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld CC = $(CROSS_COMPILE)gcc -ifeq (1, $(MWLDBG)) -EXTRA_CFLAGS+= -DMWL_DEBUG -endif - EXTRA_CFLAGS+= -I${KDIR} -EXTRA_CFLAGS+= -O2 -funroll-loops -DDEBUG +EXTRA_CFLAGS+= -O2 -funroll-loops EXTRA_CFLAGS+= -I${PWD} diff --git a/Makefile.external b/Makefile.external index 5771f78..f5e7e74 100644 --- a/Makefile.external +++ b/Makefile.external @@ -1,23 +1,19 @@ obj-m += mwlwifi.o -mwlwifi-objs += mwl_main.o -mwlwifi-objs += mwl_mac80211.o -mwlwifi-objs += mwl_fwdl.o -mwlwifi-objs += mwl_fwcmd.o -mwlwifi-objs += mwl_tx.o -mwlwifi-objs += mwl_rx.o -mwlwifi-objs += mwl_debug.o +mwlwifi-objs += main.o +mwlwifi-objs += mac80211.o +mwlwifi-objs += fwdl.o +mwlwifi-objs += fwcmd.o +mwlwifi-objs += tx.o +mwlwifi-objs += rx.o +mwlwifi-objs += isr.o AS = $(CROSS_COMPILE)as LD = $(CROSS_COMPILE)ld CC = $(CROSS_COMPILE)gcc -ifeq (1, $(MWLDBG)) -EXTRA_CFLAGS+= -DMWL_DEBUG -endif - EXTRA_CFLAGS+= -I${KDIR} -EXTRA_CFLAGS+= -O2 -funroll-loops -DDEBUG +EXTRA_CFLAGS+= -O2 -funroll-loops EXTRA_CFLAGS+= -I${PWD} diff --git a/Makefile.kernel b/Makefile.kernel index ad97138..c6e03a3 100644 --- a/Makefile.kernel +++ b/Makefile.kernel @@ -1,9 +1,9 @@ obj-$(CONFIG_MWLWIFI) += mwlwifi.o -mwlwifi-objs += mwl_main.o -mwlwifi-objs += mwl_mac80211.o -mwlwifi-objs += mwl_fwdl.o -mwlwifi-objs += mwl_fwcmd.o -mwlwifi-objs += mwl_tx.o -mwlwifi-objs += mwl_rx.o -mwlwifi-objs += mwl_debug.o +mwlwifi-objs += main.o +mwlwifi-objs += mac80211.o +mwlwifi-objs += fwdl.o +mwlwifi-objs += fwcmd.o +mwlwifi-objs += tx.o +mwlwifi-objs += rx.o +mwlwifi-objs += isr.o @@ -0,0 +1,419 @@ +/* + * 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 device related information. + */ + +#ifndef _mwl_dev_h_ +#define _mwl_dev_h_ + +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/firmware.h> +#include <linux/delay.h> +#include <linux/bitops.h> +#include <net/mac80211.h> + +/* Map to 0x80000000 (Bus control) on BAR0 */ +#define MACREG_REG_H2A_INTERRUPT_EVENTS 0x00000C18 /* (From host to ARM) */ +#define MACREG_REG_H2A_INTERRUPT_CAUSE 0x00000C1C /* (From host to ARM) */ +#define MACREG_REG_H2A_INTERRUPT_MASK 0x00000C20 /* (From host to ARM) */ +#define MACREG_REG_H2A_INTERRUPT_CLEAR_SEL 0x00000C24 /* (From host to ARM) */ +#define MACREG_REG_H2A_INTERRUPT_STATUS_MASK 0x00000C28 /* (From host to ARM) */ + +#define MACREG_REG_A2H_INTERRUPT_EVENTS 0x00000C2C /* (From ARM to host) */ +#define MACREG_REG_A2H_INTERRUPT_CAUSE 0x00000C30 /* (From ARM to host) */ +#define MACREG_REG_A2H_INTERRUPT_MASK 0x00000C34 /* (From ARM to host) */ +#define MACREG_REG_A2H_INTERRUPT_CLEAR_SEL 0x00000C38 /* (From ARM to host) */ +#define MACREG_REG_A2H_INTERRUPT_STATUS_MASK 0x00000C3C /* (From ARM to host) */ + +/* Map to 0x80000000 on BAR1 */ +#define MACREG_REG_GEN_PTR 0x00000C10 +#define MACREG_REG_INT_CODE 0x00000C14 + +/* Bit definitio 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) +#define MACREG_A2HRIC_BIT_MAC_EVENT BIT(3) +#define MACREG_A2HRIC_BIT_RX_PROBLEM BIT(4) +#define MACREG_A2HRIC_BIT_RADIO_OFF BIT(5) +#define MACREG_A2HRIC_BIT_RADIO_ON BIT(6) +#define MACREG_A2HRIC_BIT_RADAR_DETECT BIT(7) +#define MACREG_A2HRIC_BIT_ICV_ERROR BIT(8) +#define MACREG_A2HRIC_BIT_WEAKIV_ERROR BIT(9) +#define MACREG_A2HRIC_BIT_QUEUE_EMPTY BIT(10) +#define MACREG_A2HRIC_BIT_QUEUE_FULL BIT(11) +#define MACREG_A2HRIC_BIT_CHAN_SWITCH BIT(12) +#define MACREG_A2HRIC_BIT_TX_WATCHDOG BIT(13) +#define MACREG_A2HRIC_BA_WATCHDOG BIT(14) +/* 15 taken by ISR_TXACK */ +#define MACREG_A2HRIC_BIT_SSU_DONE BIT(16) +#define MACREG_A2HRIC_CONSEC_TXFAIL BIT(17) + +#define ISR_SRC_BITS (MACREG_A2HRIC_BIT_RX_RDY | \ + MACREG_A2HRIC_BIT_TX_DONE | \ + MACREG_A2HRIC_BIT_OPC_DONE | \ + MACREG_A2HRIC_BIT_MAC_EVENT | \ + MACREG_A2HRIC_BIT_WEAKIV_ERROR | \ + MACREG_A2HRIC_BIT_ICV_ERROR | \ + MACREG_A2HRIC_BIT_SSU_DONE | \ + MACREG_A2HRIC_BIT_RADAR_DETECT | \ + MACREG_A2HRIC_BIT_CHAN_SWITCH | \ + MACREG_A2HRIC_BIT_TX_WATCHDOG | \ + MACREG_A2HRIC_BIT_QUEUE_EMPTY | \ + MACREG_A2HRIC_BA_WATCHDOG | \ + MACREG_A2HRIC_CONSEC_TXFAIL) + +#define MACREG_A2HRIC_BIT_MASK ISR_SRC_BITS + +/* Bit definitio 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) +#define MACREG_H2ARIC_BIT_PSPOLL BIT(3) +#define ISR_RESET BIT(15) +#define ISR_RESET_AP33 BIT(26) + +/* Data descriptor related constants */ +#define EAGLE_RXD_CTRL_DRIVER_OWN 0x00 +#define EAGLE_RXD_CTRL_DMA_OWN 0x80 + +#define EAGLE_RXD_STATUS_OK 0x01 + +#define EAGLE_TXD_STATUS_IDLE 0x00000000 +#define EAGLE_TXD_STATUS_OK 0x00000001 +#define EAGLE_TXD_STATUS_FW_OWNED 0x80000000 + +/* Antenna control */ +#define ANTENNA_TX_4_AUTO 0 +#define ANTENNA_TX_2 3 +#define ANTENNA_RX_4_AUTO 0 +#define ANTENNA_RX_2 2 + +/* Band related constants */ +#define BAND_24_CHANNEL_NUM 14 +#define BAND_24_RATE_NUM 13 +#define BAND_50_CHANNEL_NUM 24 +#define BAND_50_RATE_NUM 8 + +/* vif and station */ +#define NUM_WEP_KEYS 4 +#define MWL_MAX_TID 8 +#define MWL_AMSDU_SIZE_4K 0 +#define MWL_AMSDU_SIZE_8K 1 + +/* power init */ +#define MWL_POWER_INIT_1 1 +#define MWL_POWER_INIT_2 2 + +enum { + MWL8864 = 0, + MWL8897, + MWLUNKNOWN, +}; + +enum { + AP_MODE_11AC = 0x10, /* generic 11ac indication mode */ + AP_MODE_2_4GHZ_11AC_MIXED = 0x17, +}; + +enum { + AMPDU_NO_STREAM, + AMPDU_STREAM_NEW, + AMPDU_STREAM_IN_PROGRESS, + AMPDU_STREAM_ACTIVE, +}; + +struct mwl_chip_info { + char *part_name; + char *fw_image; +}; + +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; +}; + +struct mwl_hw_data { + u32 fw_release_num; /* MajNbr:MinNbr:SubMin:PatchLevel */ + u8 hw_version; /* plain number indicating version */ + u8 host_interface; /* plain number of interface */ + u16 max_num_tx_desc; /* max number of TX descriptors */ + u16 max_num_mc_addr; /* max number multicast addresses */ + u16 num_antennas; /* number antennas used */ + u16 region_code; /* region (eg. 0x10 for USA FCC) */ + unsigned char mac_addr[ETH_ALEN]; /* well known -> AA:BB:CC:DD:EE:FF */ +}; + +#define MWL_TX_RATE_FORMAT_MASK 0x00000003 +#define MWL_TX_RATE_BANDWIDTH_MASK 0x00000030 +#define MWL_TX_RATE_BANDWIDTH_SHIFT 4 +#define MWL_TX_RATE_SHORTGI_MASK 0x00000040 +#define MWL_TX_RATE_SHORTGI_SHIFT 6 +#define MWL_TX_RATE_RATEIDMCS_MASK 0x00007F00 +#define MWL_TX_RATE_RATEIDMCS_SHIFT 8 + +struct mwl_tx_desc { + u8 data_rate; + u8 tx_priority; + __le16 qos_ctrl; + __le32 pkt_ptr; + __le16 pkt_len; + u8 dest_addr[ETH_ALEN]; + __le32 pphys_next; + __le32 sap_pkt_info; + __le32 rate_info; + u8 type; + u8 xmit_control; /* bit 0: use rateinfo, bit 1: disable ampdu */ + __le16 reserved; + __le32 tcpack_sn; + __le32 tcpack_src_dst; + struct sk_buff *psk_buff; + struct mwl_tx_desc *pnext; + u8 reserved1[2]; + u8 packet_info; + u8 packet_id; + __le16 packet_len_and_retry; + __le16 packet_rate_info; + u8 *sta_info; + __le32 status; +} __packed; + +#define MWL_RX_RATE_FORMAT_MASK 0x0007 +#define MWL_RX_RATE_NSS_MASK 0x0018 +#define MWL_RX_RATE_NSS_SHIFT 3 +#define MWL_RX_RATE_BW_MASK 0x0060 +#define MWL_RX_RATE_BW_SHIFT 5 +#define MWL_RX_RATE_GI_MASK 0x0080 +#define MWL_RX_RATE_GI_SHIFT 7 +#define MWL_RX_RATE_RT_MASK 0xFF00 +#define MWL_RX_RATE_RT_SHIFT 8 + +struct mwl_rx_desc { + __le16 pkt_len; /* total length of received data */ + __le16 rate; /* receive rate information */ + __le32 pphys_buff_data; /* physical address of payload data */ + __le32 pphys_next; /* physical address of next RX desc */ + __le16 qos_ctrl; /* received QosCtrl field variable */ + __le16 ht_sig2; /* like name states */ + __le32 hw_rssi_info; + __le32 hw_noise_floor_info; + u8 noise_floor; + u8 reserved[3]; + u8 rssi; /* received signal strengt indication */ + 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 */ +} __packed; + +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 */ + 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_ampdu_stream { + struct ieee80211_sta *sta; + u8 tid; + u8 state; + u8 idx; +}; + +struct mwl_priv { + struct ieee80211_hw *hw; + const struct firmware *fw_ucode; + int chip_type; + + struct device_node *dt_node; + struct device_node *pwr_node; + bool disable_2g; + bool disable_5g; + int antenna_tx; + int antenna_rx; + + struct mwl_tx_pwr_tbl tx_pwr_tbl[SYSADPT_MAX_NUM_CHANNELS]; + u32 cdd; /* 0: off, 1: on */ + u16 txantenna2; + u8 powinited; + u16 max_tx_pow[SYSADPT_TX_POWER_LEVEL_TOTAL]; /* max tx power (dBm) */ + u16 target_powers[SYSADPT_TX_POWER_LEVEL_TOTAL]; /* target powers */ + u8 cal_tbl[200]; + + struct pci_dev *pdev; + void *iobase0; /* MEM Base Address Register 0 */ + void *iobase1; /* MEM Base Address Register 1 */ + u32 next_bar_num; + + spinlock_t fwcmd_lock; /* for firmware command */ + unsigned short *pcmd_buf; /* pointer to CmdBuf (virtual) */ + dma_addr_t pphys_cmd_buf; /* pointer to CmdBuf (physical) */ + bool in_send_cmd; + + int irq; + struct mwl_hw_data hw_data; /* Adapter HW specific info */ + + /* various descriptor data */ + spinlock_t tx_desc_lock; /* for tx descriptor data */ + struct mwl_desc_data desc_data[SYSADPT_NUM_OF_DESC_DATA]; + struct sk_buff_head txq[SYSADPT_NUM_OF_DESC_DATA]; + struct sk_buff_head delay_q; + /* number of descriptors owned by fw at any one time */ + int fw_desc_cnt[SYSADPT_NUM_OF_DESC_DATA]; + + struct tasklet_struct tx_task; + struct tasklet_struct rx_task; + int txq_limit; + bool is_tx_schedule; + int recv_limit; + bool is_rx_schedule; + s8 noise; /* Most recently reported noise in dBm */ + struct ieee80211_supported_band band_24; + struct ieee80211_channel channels_24[BAND_24_CHANNEL_NUM]; + struct ieee80211_rate rates_24[BAND_24_RATE_NUM]; + struct ieee80211_supported_band band_50; + struct ieee80211_channel channels_50[BAND_50_CHANNEL_NUM]; + struct ieee80211_rate rates_50[BAND_50_RATE_NUM]; + + u32 ap_macids_supported; + u32 sta_macids_supported; + u32 macids_used; + spinlock_t vif_lock; /* for private interface info */ + struct list_head vif_list; /* List of interfaces. */ + u32 running_bsses; /* bitmap of running BSSes */ + + spinlock_t sta_lock; /* for private sta info */ + struct list_head sta_list; /* List of stations */ + + bool radio_on; + bool radio_short_preamble; + bool wmm_enabled; + struct ieee80211_tx_queue_params wmm_params[SYSADPT_TX_WMM_QUEUES]; + + /* Ampdu stream information */ + u8 num_ampdu_queues; + spinlock_t stream_lock; /* for ampdu stream */ + struct mwl_ampdu_stream ampdu[SYSADPT_TX_AMPDU_QUEUES]; + struct work_struct watchdog_ba_handle; +}; + +struct beacon_info { + bool valid; + 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_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]; +}; + +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 */ + u8 enabled; + u8 key[sizeof(struct ieee80211_key_conf) + WLAN_KEY_LEN_WEP104]; + } wep_key_conf[NUM_WEP_KEYS]; + u8 bssid[ETH_ALEN]; /* BSSID */ + u8 sta_mac[ETH_ALEN]; /* Station mac address */ + /* 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; + s8 keyidx; +}; + +struct mwl_tx_info { + u32 start_time; + u32 pkts; +}; + +struct mwl_amsdu_frag { + struct sk_buff *skb; + u8 pad; + u8 *cur_pos; + u8 num; + u32 jiffies; +}; + +struct mwl_amsdu_ctrl { + struct mwl_amsdu_frag frag[SYSADPT_TX_WMM_QUEUES]; + u8 cap; +}; + +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; + struct mwl_amsdu_ctrl amsdu_ctrl; + u16 iv16; + u32 iv32; +}; + +/* DMA header used by firmware and hardware. */ +struct mwl_dma_data { + __le16 fwlen; + struct ieee80211_hdr wh; + char data[0]; +} __packed; + +/* 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; + +static inline struct mwl_vif *mwl_dev_get_vif(const struct ieee80211_vif *vif) +{ + return (struct mwl_vif *)&vif->drv_priv; +} + +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_ */ @@ -1,36 +1,24 @@ /* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ + * 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 implements frimware host command related functions. -*/ + */ #include <linux/etherdevice.h> -#include "mwl_sysadpt.h" -#include "mwl_dev.h" -#include "mwl_debug.h" -#include "mwl_fwcmd.h" - -/* CONSTANTS AND MACROS -*/ +#include "sysadpt.h" +#include "dev.h" +#include "fwcmd.h" #define MAX_WAIT_FW_COMPLETE_ITERATIONS 10000 +#define MAX_WAIT_GET_HW_SPECS_ITERATONS 3 -/* 16 bit host command code - */ +/* 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 @@ -60,10 +48,9 @@ #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 /* OK */ -/* Genenral error */ +/* 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 @@ -74,8 +61,7 @@ /* Data buffer is not big enough */ #define HOSTCMD_RESULT_PARTIAL_DATA 0x0005 -/* Define channel related constants - */ +/* Define channel related constants */ #define FREQ_BAND_2DOT4GHZ 0x1 #define FREQ_BAND_4DOT9GHZ 0x2 #define FREQ_BAND_5GHZ 0x4 @@ -90,77 +76,45 @@ #define EXT_CH_BELOW_CTRL_CH 0x3 #define NO_EXT_CHANNEL 0x0 -/* active primary 1st 20MHz channel */ #define ACT_PRIMARY_CHAN_0 0 -/* active primary 2nd 20MHz channel */ #define ACT_PRIMARY_CHAN_1 1 -/* active primary 3rd 20MHz channel */ #define ACT_PRIMARY_CHAN_2 2 -/* active primary 4th 20MHz channel */ #define ACT_PRIMARY_CHAN_3 3 -/* active primary 5th 20MHz channel */ -#define ACT_PRIMARY_CHAN_4 4 -/* active primary 6th 20MHz channel */ -#define ACT_PRIMARY_CHAN_5 5 -/* active primary 7th 20MHz channel */ -#define ACT_PRIMARY_CHAN_6 6 -/* active primary 8th 20MHz channel */ -#define ACT_PRIMARY_CHAN_7 7 - -/* Define rate related constants - */ + +/* Define rate related constants */ #define HOSTCMD_ACT_NOT_USE_FIXED_RATE 0x0002 -/* Define station related constants - */ +/* Define station related constants */ #define HOSTCMD_ACT_STA_ACTION_ADD 0 #define HOSTCMD_ACT_STA_ACTION_REMOVE 2 -/* Define key related constants - */ +/* Define key related constants */ #define MAX_ENCR_KEY_LENGTH 16 #define MIC_KEY_LENGTH 8 -/* Key type is WEP */ #define KEY_TYPE_ID_WEP 0x00 -/* Key type is TKIP */ #define KEY_TYPE_ID_TKIP 0x01 -/* Key type is AES-CCMP */ #define KEY_TYPE_ID_AES 0x02 -/* Group key for TX */ #define ENCR_KEY_FLAG_TXGROUPKEY 0x00000004 -/* pairwise */ #define ENCR_KEY_FLAG_PAIRWISE 0x00000008 -/* Sequence counters are valid */ #define ENCR_KEY_FLAG_TSC_VALID 0x00000040 -/* Tx key for WEP */ #define ENCR_KEY_FLAG_WEP_TXKEY 0x01000000 -/* Tx/Rx MIC keys are valid */ #define ENCR_KEY_FLAG_MICKEY_VALID 0x02000000 -/* Define block ack related constants - */ +/* Define block ack related constants */ #define BASTREAM_FLAG_IMMEDIATE_TYPE 1 #define BASTREAM_FLAG_DIRECTION_UPSTREAM 0 -/* Define general purpose action - */ +/* 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 MWL_SPIN_LOCK(X) SPIN_LOCK_IRQSAVE(X, flags) -#define MWL_SPIN_UNLOCK(X) SPIN_UNLOCK_IRQRESTORE(X, flags) - +/* Misc */ #define MAX_ENCR_KEY_LENGTH 16 #define MIC_KEY_LENGTH 8 -/* TYPE DEFINITION -*/ - enum { WL_DISABLE = 0, WL_ENABLE = 1, @@ -204,40 +158,34 @@ enum mac_type { WL_MAC_TYPE_SECONDARY_AP, }; -/* General host command header - */ - +/* General host command header */ struct hostcmd_header { - u16 cmd; - u16 len; + __le16 cmd; + __le16 len; u8 seq_num; u8 macid; - u16 result; + __le16 result; } __packed; -/* HOSTCMD_CMD_GET_HW_SPEC - */ - +/* 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 */ - u16 num_wcb; /* Max. number of WCB FW can handle */ - u16 num_mcast_addr; /* MaxNbr of MC addresses FW can handle */ + __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 */ - u16 region_code; - u16 num_antenna; /* Number of antenna used */ - u32 fw_release_num; /* 4 byte of FW release number */ - u32 wcb_base0; - u32 rxpd_wr_ptr; - u32 rxpd_rd_ptr; - u32 fw_awake_cookie; - u32 wcb_base[SYSADPT_TOTAL_TX_QUEUES - 1]; + __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 - */ - +/* HOSTCMD_CMD_SET_HW_SPEC */ struct hostcmd_cmd_set_hw_spec { struct hostcmd_header cmd_hdr; /* HW revision */ @@ -245,208 +193,164 @@ struct hostcmd_cmd_set_hw_spec { /* Host interface */ u8 host_if; /* Max. number of Multicast address FW can handle */ - u16 num_mcast_addr; + __le16 num_mcast_addr; /* MAC address */ u8 permanent_addr[ETH_ALEN]; /* Region Code */ - u16 region_code; + __le16 region_code; /* 4 byte of FW release number, example 0x1234=1.2.3.4 */ - u32 fw_release_num; + __le32 fw_release_num; /* Firmware awake cookie - used to ensure that the device * is not in sleep mode */ - u32 fw_awake_cookie; + __le32 fw_awake_cookie; /* Device capabilities (see above) */ - u32 device_caps; + __le32 device_caps; /* Rx shared memory queue */ - u32 rxpd_wr_ptr; + __le32 rxpd_wr_ptr; /* Actual number of TX queues in WcbBase array */ - u32 num_tx_queues; + __le32 num_tx_queues; /* TX WCB Rings */ - u32 wcb_base[SYSADPT_NUM_OF_DESC_DATA]; + __le32 wcb_base[SYSADPT_NUM_OF_DESC_DATA]; /* Max AMSDU size (00 - AMSDU Disabled, * 01 - 4K, 10 - 8K, 11 - not defined) */ - u32 max_amsdu_size:2; - /* Indicates supported AMPDU type - * (1 = implicit, 0 = explicit (default)) - */ - u32 implicit_ampdu_ba:1; - /* indicates mbss features disable in FW */ - u32 disablembss:1; - u32 host_form_beacon:1; - u32 host_form_probe_response:1; - u32 host_power_save:1; - u32 host_encr_decr_mgt:1; - u32 host_intra_bss_offload:1; - u32 host_iv_offload:1; - u32 host_encr_decr_frame:1; - u32 reserved: 21; /* Reserved */ - u32 tx_wcb_num_per_queue; - u32 total_rx_wcb; + __le32 features; + __le32 tx_wcb_num_per_queue; + __le32 total_rx_wcb; } __packed; -/* HOSTCMD_CMD_802_11_GET_STAT - */ - +/* HOSTCMD_CMD_802_11_GET_STAT */ struct hostcmd_cmd_802_11_get_stat { struct hostcmd_header cmd_hdr; - u32 tx_retry_successes; - u32 tx_multiple_retry_successes; - u32 tx_failures; - u32 rts_successes; - u32 rts_failures; - u32 ack_failures; - u32 rx_duplicate_frames; - u32 rx_fcs_errors; - u32 tx_watchdog_timeouts; - u32 rx_overflows; - u32 rx_frag_errors; - u32 rx_mem_errors; - u32 pointer_errors; - u32 tx_underflows; - u32 tx_done; - u32 tx_done_buf_try_put; - u32 tx_done_buf_put; + __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 */ - u32 wait_for_tx_buf; - u32 tx_attempts; - u32 tx_successes; - u32 tx_fragments; - u32 tx_multicasts; - u32 rx_non_ctl_pkts; - u32 rx_multicasts; - u32 rx_undecryptable_frames; - u32 rx_icv_errors; - u32 rx_excluded_frames; - u32 rx_weak_iv_count; - u32 rx_unicasts; - u32 rx_bytes; - u32 rx_errors; - u32 rx_rts_count; - u32 tx_cts_count; -} __packed; - -/* HOSTCMD_CMD_802_11_RADIO_CONTROL - */ - + __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; - u16 action; + __le16 action; /* @bit0: 1/0,on/off, @bit1: 1/0, long/short @bit2: 1/0,auto/fix */ - u16 control; - u16 radio_on; + __le16 control; + __le16 radio_on; } __packed; -/* HOSTCMD_CMD_802_11_TX_POWER - */ - +/* HOSTCMD_CMD_802_11_TX_POWER */ struct hostcmd_cmd_802_11_tx_power { struct hostcmd_header cmd_hdr; - u16 action; - u16 band; - u16 ch; - u16 bw; - u16 sub_ch; - u16 power_level_list[SYSADPT_TX_POWER_LEVEL_TOTAL]; + __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 - */ - +/* HOSTCMD_CMD_802_11_RF_ANTENNA */ struct hostcmd_cmd_802_11_rf_antenna { struct hostcmd_header cmd_hdr; - u16 action; - u16 antenna_mode; /* Number of antennas or 0xffff(diversity) */ + __le16 action; + __le16 antenna_mode; /* Number of antennas or 0xffff(diversity) */ } __packed; -/* HOSTCMD_CMD_BROADCAST_SSID_ENABLE - */ - +/* HOSTCMD_CMD_BROADCAST_SSID_ENABLE */ struct hostcmd_cmd_broadcast_ssid_enable { struct hostcmd_header cmd_hdr; - u32 enable; + __le32 enable; } __packed; -/* HOSTCMD_CMD_SET_RF_CHANNEL - */ - -struct chnl_flags_11ac { - /* bit0=1: 2.4GHz,bit1=1: 4.9GHz,bit2=1: 5GHz,bit3=1: 5.2GHz, */ - u32 freq_band:6; - /* bit6=1:10MHz, bit7=1:20MHz, bit8=1:40MHz */ - u32 chnl_width:5; - /* 000: 1st 20MHz chan, 001:2nd 20MHz chan, 011:3rd 20MHz chan, - * 100:4th 20MHz chan - */ - u32 act_primary:3; - u32 reserved:18; -} __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; - u16 action; + __le16 action; u8 curr_chnl; - struct chnl_flags_11ac chnl_flags; + __le32 chnl_flags; } __packed; -/* HOSTCMD_CMD_SET_AID - */ - +/* HOSTCMD_CMD_SET_AID */ struct hostcmd_cmd_set_aid { struct hostcmd_header cmd_hdr; - u16 aid; + __le16 aid; u8 mac_addr[ETH_ALEN]; /* AP's Mac Address(BSSID) */ - u32 gprotect; + __le32 gprotect; u8 ap_rates[SYSADPT_MAX_DATA_RATES_G]; } __packed; -/* HOSTCMD_CMD_SET_INFRA_MODE - */ - +/* HOSTCMD_CMD_SET_INFRA_MODE */ struct hostcmd_cmd_set_infra_mode { struct hostcmd_header cmd_hdr; } __packed; -/* HOSTCMD_CMD_802_11_RTS_THSD - */ - +/* HOSTCMD_CMD_802_11_RTS_THSD */ struct hostcmd_cmd_802_11_rts_thsd { struct hostcmd_header cmd_hdr; - u16 action; - u16 threshold; + __le16 action; + __le16 threshold; } __packed; -/* HOSTCMD_CMD_SET_EDCA_PARAMS - */ - +/* 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 */ - u16 action; - u16 txop; /* in unit of 32 us */ - u32 cw_max; /* 0~15 */ - u32 cw_min; /* 0~15 */ + __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 - */ - +/* HOSTCMD_CMD_SET_WMM_MODE */ struct hostcmd_cmd_set_wmm_mode { struct hostcmd_header cmd_hdr; - u16 action; /* 0->unset, 1->set */ + __le16 action; /* 0->unset, 1->set */ } __packed; -/* HOSTCMD_CMD_SET_FIXED_RATE - */ - +/* HOSTCMD_CMD_SET_FIXED_RATE */ struct fix_rate_flag { /* lower rate after the retry count */ /* 0: legacy, 1: HT */ - u32 fix_rate_type; + __le32 fix_rate_type; /* 0: retry count is not valid, 1: use retry count specified */ - u32 retry_count_valid; + __le32 retry_count_valid; } __packed; struct fix_rate_entry { @@ -454,88 +358,76 @@ struct fix_rate_entry { /* depending on the flags above, this can be either a legacy * rate(not index) or an MCS code. */ - u32 fixed_rate; - u32 retry_count; + __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 */ - u32 action; + __le32 action; /* use fixed rate specified but firmware can drop to */ - u32 allow_rate_drop; - u32 entry_count; + __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 - */ - +/* HOSTCMD_CMD_SET_IES */ struct hostcmd_cmd_set_ies { struct hostcmd_header cmd_hdr; - u16 action; /* 0->unset, 1->set */ - u16 ie_list_len_ht; - u16 ie_list_len_vht; - u16 ie_list_len_proprietary; + __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 - */ - +/* HOSTCMD_CMD_SET_RATE_ADAPT_MODE */ struct hostcmd_cmd_set_rate_adapt_mode { struct hostcmd_header cmd_hdr; - u16 action; - u16 rate_adapt_mode; /* 0:Indoor, 1:Outdoor */ + __le16 action; + __le16 rate_adapt_mode; /* 0:Indoor, 1:Outdoor */ } __packed; -/* HOSTCMD_CMD_SET_MAC_ADDR, HOSTCMD_CMD_DEL_MAC_ADDR - */ - +/* HOSTCMD_CMD_SET_MAC_ADDR, HOSTCMD_CMD_DEL_MAC_ADDR */ struct hostcmd_cmd_set_mac_addr { struct hostcmd_header cmd_hdr; - u16 mac_type; + __le16 mac_type; u8 mac_addr[ETH_ALEN]; } __packed; -/* HOSTCMD_CMD_GET_WATCHDOG_BITMAP - */ - +/* 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 - */ - +/* HOSTCMD_CMD_BSS_START */ struct hostcmd_cmd_bss_start { struct hostcmd_header cmd_hdr; - u32 enable; /* FALSE: Disable or TRUE: Enable */ + __le32 enable; /* FALSE: Disable or TRUE: Enable */ } __packed; -/* HOSTCMD_CMD_AP_BEACON - */ - +/* HOSTCMD_CMD_AP_BEACON */ struct cf_params { u8 elem_id; u8 len; u8 cfp_cnt; u8 cfp_period; - u16 cfp_max_duration; - u16 cfp_duration_remaining; + __le16 cfp_max_duration; + __le16 cfp_duration_remaining; } __packed; struct ibss_params { u8 elem_id; u8 len; - u16 atim_window; + __le16 atim_window; } __packed; union ss_params { @@ -546,7 +438,7 @@ union ss_params { struct fh_params { u8 elem_id; u8 len; - u16 dwell_time; + __le16 dwell_time; u8 hop_set; u8 hop_pattern; u8 hop_index; @@ -590,22 +482,10 @@ struct rsn48_ie { u8 reserved[8]; } __packed; -struct aci_aifsn_field { - u8 aifsn:4; - u8 acm:1; - u8 aci:2; - u8 rsvd:1; -} __packed; - -struct ecw_min_max_field { - u8 ecw_min:4; - u8 ecw_max:4; -} __packed; - struct ac_param_rcd { - struct aci_aifsn_field aci_aifsn; - struct ecw_min_max_field ecw_min_max; - u16 txop_lim; + u8 aci_aifsn; + u8 ecw_min_max; + __le16 txop_lim; } __packed; struct wmm_param_elem { @@ -633,25 +513,25 @@ struct country { u8 len; u8 country_str[3]; struct channel_info channel_info[40]; -} __packetd; +} __packed; struct start_cmd { u8 sta_mac_addr[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 bss_type; - u16 bcn_period; + __le16 bcn_period; u8 dtim_period; union ss_params ss_param_set; union phy_params phy_param_set; - u16 probe_delay; - u16 cap_info; + __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; - u32 ap_rf_type; /* 0->B, 1->G, 2->Mixed, 3->A, 4->11J */ + __le32 ap_rf_type; /* 0->B, 1->G, 2->Mixed, 3->A, 4->11J */ } __packed; struct hostcmd_cmd_ap_beacon { @@ -659,107 +539,56 @@ struct hostcmd_cmd_ap_beacon { struct start_cmd start_cmd; } __packed; -/* HOSTCMD_CMD_SET_NEW_STN - */ - -struct cap_info { - u16 ess:1; - u16 ibss:1; - u16 cf_pollable:1; - u16 cf_poll_rqst:1; - u16 privacy:1; - u16 short_preamble:1; - u16 pbcc:1; - u16 chan_agility:1; - u16 spectrum_mgmt:1; - u16 qoS:1; - u16 short_slot_time:1; - u16 apsd:1; - u16 rsrvd1:1; - u16 dsss_ofdm:1; - u16 block_ack:1; - u16 rsrvd2:1; -} __packed; - -struct add_ht_chnl { - u8 ext_chnl_offset:2; - u8 sta_chnl_width:1; - u8 rifs_mode:1; - u8 psmp_stas_only:1; - u8 srvc_intvl_gran:3; -} __packed; - -struct add_ht_op_mode { - u16 op_mode:2; - u16 non_gf_sta_present:1; - u16 rrans_burst_limit:1; - u16 non_ht_sta_present:1; - u16 rsrv:11; -} __packed; - -struct add_ht_stbc { - u16 bsc_stbc:7; - u16 dual_stbc_proc:1; - u16 scd_bcn:1; - u16 lsig_txop_proc_full_sup:1; - u16 pco_active:1; - u16 pco_phase:1; - u16 rsrv:4; -} __packed; - +/* HOSTCMD_CMD_SET_NEW_STN */ struct add_ht_info { u8 control_chnl; - struct add_ht_chnl add_chnl; - struct add_ht_op_mode op_mode; - struct add_ht_stbc stbc; + u8 add_chnl; + __le16 op_mode; + __le16 stbc; } __packed; struct peer_info { - u32 legacy_rate_bitmap; + __le32 legacy_rate_bitmap; u8 ht_rates[4]; - struct cap_info cap_info; - u16 ht_cap_info; + __le16 cap_info; + __le16 ht_cap_info; u8 mac_ht_param_info; u8 mrvl_sta; struct add_ht_info add_ht_info; - u32 tx_bf_capabilities; /* EXBF_SUPPORT */ - u32 vht_max_rx_mcs; - u32 vht_cap; + __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; - u16 aid; + __le16 aid; u8 mac_addr[ETH_ALEN]; - u16 stn_id; - u16 action; - u16 reserved; + __le16 stn_id; + __le16 action; + __le16 reserved; struct peer_info peer_info; /* UAPSD_SUPPORT */ u8 qos_info; u8 is_qos_sta; - u32 fw_sta_ptr; + __le32 fw_sta_ptr; } __packed; -/* HOSTCMD_CMD_SET_APMODE - */ - +/* 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_encryptoin { +/* HOSTCMD_CMD_UPDATE_ENCRYPTION */ +struct hostcmd_cmd_update_encryption { struct hostcmd_header cmd_hdr; /* Action type - see encr_action_type */ - u32 action_type; /* encr_action_type */ + __le32 action_type; /* encr_action_type */ /* size of the data buffer attached. */ - u32 data_length; + __le32 data_length; u8 mac_addr[ETH_ALEN]; u8 action_data[1]; } __packed; @@ -770,8 +599,8 @@ struct wep_type_key { } __packed; struct encr_tkip_seqcnt { - u16 low; - u32 high; + __le16 low; + __le32 high; } __packed; struct tkip_type_key { @@ -793,23 +622,23 @@ struct aes_type_key { } __packed; union mwl_key_type { - struct wep_type_key wep_key; + struct wep_type_key wep_key; struct tkip_type_key tkip_key; - struct aes_type_key aes_key; + struct aes_type_key aes_key; } __packed; struct key_param_set { /* Total length of this structure (Key is variable size array) */ - u16 length; + __le16 length; /* Key type - WEP, TKIP or AES-CCMP. */ /* See definitions above */ - u16 key_type_id; + __le16 key_type_id; /* key flags (ENCR_KEY_FLAG_XXX_ */ - u32 key_info; + __le32 key_info; /* For WEP only - actual key index */ - u32 key_index; + __le32 key_index; /* Size of the key */ - u16 key_len; + __le16 key_len; /* Key material (variable size array) */ union mwl_key_type key; u8 mac_addr[ETH_ALEN]; @@ -818,38 +647,34 @@ struct key_param_set { struct hostcmd_cmd_set_key { struct hostcmd_header cmd_hdr; /* Action type - see encr_action_type */ - u32 action_type; /* encr_action_type */ + __le32 action_type; /* encr_action_type */ /* size of the data buffer attached. */ - u32 data_length; + __le32 data_length; /* data buffer - maps to one KEY_PARAM_SET structure */ struct key_param_set key_param; } __packed; -/* HOSTCMD_CMD_BASTREAM - */ - -struct ba_stream_flags { - u32 ba_type:1; - u32 ba_direction:3; - u32 reserved:24; -} __packed; +/* HOSTCMD_CMD_BASTREAM */ +#define BA_TYPE_MASK 0x00000001 +#define BA_DIRECTION_MASK 0x00000006 +#define BA_DIRECTION_SHIFT 1 struct ba_context { - u32 context; + __le32 context; } __packed; /* parameters for block ack creation */ struct create_ba_params { /* BA Creation flags - see above */ - struct ba_stream_flags flags; + __le32 flags; /* idle threshold */ - u32 idle_thrs; + __le32 idle_thrs; /* block ack transmit threshold (after how many pkts should we * send BAR?) */ - u32 bar_thrs; + __le32 bar_thrs; /* receiver window size */ - u32 window_size; + __le32 window_size; /* MAC Address of the BA partner */ u8 peer_mac_addr[ETH_ALEN]; /* Dialog Token */ @@ -865,7 +690,7 @@ struct create_ba_params { */ struct ba_context fw_ba_context; u8 reset_seq_no; /** 0 or 1**/ - u16 current_seq; + __le16 current_seq; /* This is for virtual station in Sta proxy mode for V6FW */ u8 sta_src_mac_addr[ETH_ALEN]; } __packed; @@ -873,16 +698,16 @@ struct create_ba_params { /* new transmit sequence number information */ struct ba_update_seq_num { /* BA flags - see above */ - struct ba_stream_flags flags; + __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 */ - u16 ba_seq_num; + __le16 ba_seq_num; } __packed; struct ba_stream_context { /* BA Stream flags */ - struct ba_stream_flags flags; + __le32 flags; /* returned by firmware in the create ba stream response */ struct ba_context fw_ba_context; } __packed; @@ -900,95 +725,685 @@ union ba_info { struct hostcmd_cmd_bastream { struct hostcmd_header cmd_hdr; - u32 action_type; + __le32 action_type; union ba_info ba_info; } __packed; -/* HOSTCMD_CMD_DWDS_ENABLE - */ - +/* HOSTCMD_CMD_DWDS_ENABLE */ struct hostcmd_cmd_dwds_enable { struct hostcmd_header cmd_hdr; - u32 enable; /* 0 -- Disable. or 1 -- Enable. */ + __le32 enable; /* 0 -- Disable. or 1 -- Enable. */ } __packed; -/* HOSTCMD_CMD_FW_FLUSH_TIMER - */ - +/* HOSTCMD_CMD_FW_FLUSH_TIMER */ struct hostcmd_cmd_fw_flush_timer { struct hostcmd_header cmd_hdr; /* 0 -- Disable. > 0 -- holds time value in usecs. */ - u32 value; + __le32 value; } __packed; -/* HOSTCMD_CMD_SET_CDD - */ - +/* HOSTCMD_CMD_SET_CDD */ struct hostcmd_cmd_set_cdd { struct hostcmd_header cmd_hdr; - u32 enable; + __le32 enable; } __packed; -/* PRIVATE FUNCTION DECLARATION -*/ +static bool mwl_fwcmd_chk_adapter(struct mwl_priv *priv) +{ + u32 regval; + + regval = readl(priv->iobase1 + MACREG_REG_INT_CODE); + + if (regval == 0xffffffff) { + wiphy_err(priv->hw->wiphy, "adapter is not existed"); + return false; + } + + return true; +} + +static void mwl_fwcmd_send_cmd(struct mwl_priv *priv) +{ + writel(priv->pphys_cmd_buf, priv->iobase1 + MACREG_REG_GEN_PTR); + writel(MACREG_H2ARIC_BIT_DOOR_BELL, + priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS); +} + +static char *mwl_fwcmd_get_cmd_string(unsigned short cmd) +{ + int max_entries = 0; + int curr_cmd = 0; + + static const struct { + u16 cmd; + char *cmd_string; + } cmds[] = { + { HOSTCMD_CMD_GET_HW_SPEC, "GetHwSpecifications" }, + { HOSTCMD_CMD_SET_HW_SPEC, "SetHwSepcifications" }, + { HOSTCMD_CMD_802_11_GET_STAT, "80211GetStat" }, + { HOSTCMD_CMD_802_11_RADIO_CONTROL, "80211RadioControl" }, + { HOSTCMD_CMD_802_11_TX_POWER, "80211TxPower" }, + { HOSTCMD_CMD_802_11_RF_ANTENNA, "80211RfAntenna" }, + { HOSTCMD_CMD_BROADCAST_SSID_ENABLE, "broadcast_ssid_enable" }, + { HOSTCMD_CMD_SET_RF_CHANNEL, "SetRfChannel" }, + { HOSTCMD_CMD_SET_AID, "SetAid" }, + { HOSTCMD_CMD_SET_INFRA_MODE, "SetInfraMode" }, + { HOSTCMD_CMD_802_11_RTS_THSD, "80211RtsThreshold" }, + { HOSTCMD_CMD_SET_EDCA_PARAMS, "SetEDCAParams" }, + { HOSTCMD_CMD_SET_WMM_MODE, "SetWMMMode" }, + { HOSTCMD_CMD_SET_FIXED_RATE, "SetFixedRate" }, + { HOSTCMD_CMD_SET_IES, "SetInformationElements" }, + { HOSTCMD_CMD_SET_RATE_ADAPT_MODE, "SetRateAdaptationMode" }, + { HOSTCMD_CMD_SET_MAC_ADDR, "SetMacAddr" }, + { HOSTCMD_CMD_GET_WATCHDOG_BITMAP, "GetWatchdogBitMap" }, + { HOSTCMD_CMD_DEL_MAC_ADDR, "DelMacAddr" }, + { HOSTCMD_CMD_BSS_START, "BssStart" }, + { HOSTCMD_CMD_AP_BEACON, "SetApBeacon" }, + { HOSTCMD_CMD_SET_NEW_STN, "SetNewStation" }, + { HOSTCMD_CMD_SET_APMODE, "SetApMode" }, + { HOSTCMD_CMD_UPDATE_ENCRYPTION, "UpdateEncryption" }, + { HOSTCMD_CMD_BASTREAM, "BAStream" }, + { HOSTCMD_CMD_DWDS_ENABLE, "DwdsEnable" }, + { HOSTCMD_CMD_FW_FLUSH_TIMER, "FwFlushTimer" }, + { HOSTCMD_CMD_SET_CDD, "SetCDD" }, + }; + + max_entries = sizeof(cmds) / sizeof(cmds[0]); + + for (curr_cmd = 0; curr_cmd < max_entries; curr_cmd++) + if ((cmd & 0x7fff) == cmds[curr_cmd].cmd) + return cmds[curr_cmd].cmd_string; -static bool mwl_fwcmd_chk_adapter(struct mwl_priv *priv); -static int mwl_fwcmd_exec_cmd(struct mwl_priv *priv, unsigned short cmd); -static void mwl_fwcmd_send_cmd(struct mwl_priv *priv); -static int mwl_fwcmd_wait_complete(struct mwl_priv *priv, unsigned short cmd); + return "unknown"; +} + +static int mwl_fwcmd_wait_complete(struct mwl_priv *priv, unsigned short cmd) +{ + unsigned int curr_iteration = MAX_WAIT_FW_COMPLETE_ITERATIONS; + + unsigned short int_code = 0; + + do { + int_code = le16_to_cpu(*((__le16 *)&priv->pcmd_buf[0])); + mdelay(1); + } while ((int_code != cmd) && (--curr_iteration)); + + if (curr_iteration == 0) { + wiphy_err(priv->hw->wiphy, "cmd 0x%04x=%s timed out", + cmd, mwl_fwcmd_get_cmd_string(cmd)); + return -EIO; + } + + mdelay(3); + + return 0; +} + +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"); + priv->in_send_cmd = false; + return -EIO; + } + + if (!priv->in_send_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"); + priv->in_send_cmd = false; + return -EIO; + } + } else { + wiphy_warn(priv->hw->wiphy, + "previous command is still running"); + busy = true; + } + + if (!busy) + priv->in_send_cmd = false; + + return 0; +} static int mwl_fwcmd_802_11_radio_control(struct mwl_priv *priv, - bool enable, bool force); + 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); + + memset(pcmd, 0x00, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_RADIO_CONTROL); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->action = cpu_to_le16(WL_SET); + pcmd->control = cpu_to_le16(priv->radio_short_preamble ? + WL_AUTO_PREAMBLE : WL_LONG_PREAMBLE); + 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"); + return -EIO; + } + + priv->radio_on = enable; + + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + + return 0; +} + static int mwl_fwcmd_get_tx_powers(struct mwl_priv *priv, u16 *powlist, u16 ch, - u16 band, u16 width, u16 sub_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); + + memset(pcmd, 0x00, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_TX_POWER); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->action = cpu_to_le16(HOSTCMD_ACT_GEN_GET_LIST); + pcmd->ch = cpu_to_le16(ch); + pcmd->bw = cpu_to_le16(width); + pcmd->band = cpu_to_le16(band); + 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"); + 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); + + return 0; +} + static int mwl_fwcmd_set_tx_powers(struct mwl_priv *priv, u16 txpow[], u8 action, u16 ch, u16 band, - u16 width, u16 sub_ch); -static u8 mwl_fwcmd_get_80m_pri_chnl_offset(u8 channel); + 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); + + memset(pcmd, 0x00, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_TX_POWER); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->action = cpu_to_le16(action); + pcmd->ch = cpu_to_le16(ch); + pcmd->bw = cpu_to_le16(width); + pcmd->band = cpu_to_le16(band); + pcmd->sub_ch = cpu_to_le16(sub_ch); + + for (i = 0; i < SYSADPT_TX_POWER_LEVEL_TOTAL; i++) + 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"); + return -EIO; + } + + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + + return 0; +} + +static u8 mwl_fwcmd_get_80m_pri_chnl_offset(u8 channel) +{ + u8 act_primary = ACT_PRIMARY_CHAN_0; + + switch (channel) { + case 36: + act_primary = ACT_PRIMARY_CHAN_0; + break; + case 40: + act_primary = ACT_PRIMARY_CHAN_1; + break; + case 44: + act_primary = ACT_PRIMARY_CHAN_2; + break; + case 48: + act_primary = ACT_PRIMARY_CHAN_3; + break; + case 52: + act_primary = ACT_PRIMARY_CHAN_0; + break; + case 56: + act_primary = ACT_PRIMARY_CHAN_1; + break; + case 60: + act_primary = ACT_PRIMARY_CHAN_2; + break; + case 64: + act_primary = ACT_PRIMARY_CHAN_3; + break; + case 100: + act_primary = ACT_PRIMARY_CHAN_0; + break; + case 104: + act_primary = ACT_PRIMARY_CHAN_1; + break; + case 108: + act_primary = ACT_PRIMARY_CHAN_2; + break; + case 112: + act_primary = ACT_PRIMARY_CHAN_3; + break; + case 116: + act_primary = ACT_PRIMARY_CHAN_0; + break; + case 120: + act_primary = ACT_PRIMARY_CHAN_1; + break; + case 124: + act_primary = ACT_PRIMARY_CHAN_2; + break; + case 128: + act_primary = ACT_PRIMARY_CHAN_3; + break; + case 132: + act_primary = ACT_PRIMARY_CHAN_0; + break; + case 136: + act_primary = ACT_PRIMARY_CHAN_1; + break; + case 140: + act_primary = ACT_PRIMARY_CHAN_2; + break; + case 144: + act_primary = ACT_PRIMARY_CHAN_3; + break; + case 149: + act_primary = ACT_PRIMARY_CHAN_0; + break; + case 153: + act_primary = ACT_PRIMARY_CHAN_1; + break; + case 157: + act_primary = ACT_PRIMARY_CHAN_2; + break; + case 161: + act_primary = ACT_PRIMARY_CHAN_3; + break; + } + + return act_primary; +} + static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv, - struct mwl_vif *vif, u8 *beacon, int len); -static int mwl_fwcmd_set_ies(struct mwl_priv *priv, struct mwl_vif *mwl_vif); + struct mwl_vif *vif, u8 *beacon, int len) +{ + struct ieee80211_mgmt *mgmt; + struct beacon_info *beacon_info; + int baselen; + u8 *pos; + size_t left; + bool elem_parse_failed; + + mgmt = (struct ieee80211_mgmt *)beacon; + + baselen = (u8 *)mgmt->u.beacon.variable - (u8 *)mgmt; + if (baselen > len) + return; + + beacon_info = &vif->beacon_info; + memset(beacon_info, 0, sizeof(struct beacon_info)); + beacon_info->valid = false; + beacon_info->ie_ht_ptr = &beacon_info->ie_list_ht[0]; + beacon_info->ie_vht_ptr = &beacon_info->ie_list_vht[0]; + + beacon_info->cap_info = le16_to_cpu(mgmt->u.beacon.capab_info); + + pos = (u8 *)mgmt->u.beacon.variable; + left = len - baselen; + + elem_parse_failed = false; + + while (left >= 2) { + u8 id, elen; + + id = *pos++; + elen = *pos++; + left -= 2; + + if (elen > left) { + elem_parse_failed = true; + break; + } + + switch (id) { + case WLAN_EID_SUPP_RATES: + case WLAN_EID_EXT_SUPP_RATES: + { + int idx, bi, oi; + u8 rate; + + for (bi = 0; bi < SYSADPT_MAX_DATA_RATES_G; + bi++) { + if (beacon_info->b_rate_set[bi] == 0) + break; + } + + for (oi = 0; oi < SYSADPT_MAX_DATA_RATES_G; + oi++) { + if (beacon_info->op_rate_set[oi] == 0) + break; + } + + for (idx = 0; idx < elen; idx++) { + rate = pos[idx]; + if ((rate & 0x80) != 0) { + if (bi < SYSADPT_MAX_DATA_RATES_G) + beacon_info->b_rate_set[bi++] + = rate & 0x7f; + else { + elem_parse_failed = true; + break; + } + } + if (oi < SYSADPT_MAX_DATA_RATES_G) + beacon_info->op_rate_set[oi++] = + rate & 0x7f; + else { + elem_parse_failed = true; + break; + } + } + } + break; + case WLAN_EID_RSN: + beacon_info->ie_rsn48_len = (elen + 2); + beacon_info->ie_rsn48_ptr = (pos - 2); + break; + case WLAN_EID_HT_CAPABILITY: + case WLAN_EID_HT_OPERATION: + case WLAN_EID_OVERLAP_BSS_SCAN_PARAM: + case WLAN_EID_EXT_CAPABILITY: + beacon_info->ie_ht_len += (elen + 2); + if (beacon_info->ie_ht_len > + sizeof(beacon_info->ie_list_ht)) { + elem_parse_failed = true; + } else { + *beacon_info->ie_ht_ptr++ = id; + *beacon_info->ie_ht_ptr++ = elen; + memcpy(beacon_info->ie_ht_ptr, pos, elen); + beacon_info->ie_ht_ptr += elen; + } + break; + case WLAN_EID_VHT_CAPABILITY: + case WLAN_EID_VHT_OPERATION: + case WLAN_EID_OPMODE_NOTIF: + beacon_info->ie_vht_len += (elen + 2); + if (beacon_info->ie_vht_len > + sizeof(beacon_info->ie_list_vht)) { + elem_parse_failed = true; + } else { + *beacon_info->ie_vht_ptr++ = id; + *beacon_info->ie_vht_ptr++ = elen; + memcpy(beacon_info->ie_vht_ptr, pos, elen); + beacon_info->ie_vht_ptr += elen; + } + break; + case WLAN_EID_VENDOR_SPECIFIC: + if ((pos[0] == 0x00) && (pos[1] == 0x50) && + (pos[2] == 0xf2)) { + if (pos[3] == 0x01) { + beacon_info->ie_rsn_len = (elen + 2); + beacon_info->ie_rsn_ptr = (pos - 2); + } + + if (pos[3] == 0x02) { + beacon_info->ie_wmm_len = (elen + 2); + beacon_info->ie_wmm_ptr = (pos - 2); + } + } + break; + default: + break; + } + + left -= elen; + pos += elen; + } + + if (!elem_parse_failed) { + beacon_info->ie_ht_ptr = &beacon_info->ie_list_ht[0]; + beacon_info->ie_vht_ptr = &beacon_info->ie_list_vht[0]; + beacon_info->valid = true; + + wiphy_info(priv->hw->wiphy, + "wmm:%d, rsn:%d, rsn48:%d, ht:%d, vht:%d", + beacon_info->ie_wmm_len, + beacon_info->ie_rsn_len, + beacon_info->ie_rsn48_len, + beacon_info->ie_ht_len, + beacon_info->ie_vht_len); + } +} + +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; + + if (mwl_vif->beacon_info.ie_ht_len > sizeof(pcmd->ie_list_ht)) + goto einval; + + if (mwl_vif->beacon_info.ie_vht_len > sizeof(pcmd->ie_list_vht)) + goto einval; + + pcmd = (struct hostcmd_cmd_set_ies *)&priv->pcmd_buf[0]; + + spin_lock_irqsave(&priv->fwcmd_lock, flags); + + memset(pcmd, 0x00, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_IES); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->cmd_hdr.macid = mwl_vif->macid; + + pcmd->action = cpu_to_le16(HOSTCMD_ACT_GEN_SET); + + pcmd->ie_list_len_ht = cpu_to_le16(mwl_vif->beacon_info.ie_ht_len); + memcpy(pcmd->ie_list_ht, mwl_vif->beacon_info.ie_ht_ptr, + mwl_vif->beacon_info.ie_ht_len); + + pcmd->ie_list_len_vht = cpu_to_le16(mwl_vif->beacon_info.ie_vht_len); + memcpy(pcmd->ie_list_vht, mwl_vif->beacon_info.ie_vht_ptr, + mwl_vif->beacon_info.ie_vht_len); + + if (priv->chip_type == MWL8897) { + pcmd->ie_list_len_proprietary = + cpu_to_le16(mwl_vif->beacon_info.ie_wmm_len); + memcpy(pcmd->ie_list_proprietary, + mwl_vif->beacon_info.ie_wmm_ptr, + mwl_vif->beacon_info.ie_wmm_len); + } + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_IES)) { + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(priv->hw->wiphy, "failed execution"); + return -EIO; + } + + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + + return 0; + +einval: + + wiphy_err(priv->hw->wiphy, "length of IE is too long"); + + return -EINVAL; +} + static int mwl_fwcmd_set_ap_beacon(struct mwl_priv *priv, struct mwl_vif *mwl_vif, - struct ieee80211_bss_conf *bss_conf); + 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) + return -EINVAL; + + /* wmm structure of start command is defined less one byte, + * due to following field country is not used, add byte one + * to bypass the check. + */ + if (mwl_vif->beacon_info.ie_wmm_len > + (sizeof(pcmd->start_cmd.wmm_param) + 1)) + goto ielenerr; + + if (mwl_vif->beacon_info.ie_rsn_len > sizeof(pcmd->start_cmd.rsn_ie)) + goto ielenerr; + + if (mwl_vif->beacon_info.ie_rsn48_len > + sizeof(pcmd->start_cmd.rsn48_ie)) + goto ielenerr; + + pcmd = (struct hostcmd_cmd_ap_beacon *)&priv->pcmd_buf[0]; + + spin_lock_irqsave(&priv->fwcmd_lock, flags); + + memset(pcmd, 0x00, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_AP_BEACON); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->cmd_hdr.macid = mwl_vif->macid; + + ether_addr_copy(pcmd->start_cmd.sta_mac_addr, mwl_vif->bssid); + memcpy(pcmd->start_cmd.ssid, bss_conf->ssid, bss_conf->ssid_len); + pcmd->start_cmd.bss_type = 1; + pcmd->start_cmd.bcn_period = cpu_to_le16(bss_conf->beacon_int); + pcmd->start_cmd.dtim_period = bss_conf->dtim_period; /* 8bit */ + + phy_ds_param_set = &pcmd->start_cmd.phy_param_set.ds_param_set; + phy_ds_param_set->elem_id = WLAN_EID_DS_PARAMS; + phy_ds_param_set->len = sizeof(phy_ds_param_set->current_chnl); + phy_ds_param_set->current_chnl = bss_conf->chandef.chan->hw_value; + + pcmd->start_cmd.probe_delay = cpu_to_le16(10); + pcmd->start_cmd.cap_info = cpu_to_le16(mwl_vif->beacon_info.cap_info); + + memcpy(&pcmd->start_cmd.wmm_param, mwl_vif->beacon_info.ie_wmm_ptr, + mwl_vif->beacon_info.ie_wmm_len); + + memcpy(&pcmd->start_cmd.rsn_ie, mwl_vif->beacon_info.ie_rsn_ptr, + mwl_vif->beacon_info.ie_rsn_len); + + memcpy(&pcmd->start_cmd.rsn48_ie, mwl_vif->beacon_info.ie_rsn48_ptr, + mwl_vif->beacon_info.ie_rsn48_len); + + memcpy(pcmd->start_cmd.b_rate_set, mwl_vif->beacon_info.b_rate_set, + SYSADPT_MAX_DATA_RATES_G); + + memcpy(pcmd->start_cmd.op_rate_set, mwl_vif->beacon_info.op_rate_set, + 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"); + return -EIO; + } + + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + + return 0; + +ielenerr: + + wiphy_err(priv->hw->wiphy, "length of IE is too long"); + + return -EINVAL; +} + static int mwl_fwcmd_encryption_set_cmd_info(struct hostcmd_cmd_set_key *cmd, u8 *addr, - struct ieee80211_key_conf *key); + struct ieee80211_key_conf *key) +{ + cmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_UPDATE_ENCRYPTION); + cmd->cmd_hdr.len = cpu_to_le16(sizeof(*cmd)); + cmd->key_param.length = cpu_to_le16(sizeof(*cmd) - + offsetof(struct hostcmd_cmd_set_key, key_param)); + cmd->key_param.key_index = cpu_to_le32(key->keyidx); + cmd->key_param.key_len = cpu_to_le16(key->keylen); + ether_addr_copy(cmd->key_param.mac_addr, addr); -#ifdef MWL_DEBUG -static char *mwl_fwcmd_get_cmd_string(unsigned short cmd); -#endif + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + cmd->key_param.key_type_id = cpu_to_le16(KEY_TYPE_ID_WEP); + if (key->keyidx == 0) + cmd->key_param.key_info = + cpu_to_le32(ENCR_KEY_FLAG_WEP_TXKEY); + break; + case WLAN_CIPHER_SUITE_TKIP: + cmd->key_param.key_type_id = cpu_to_le16(KEY_TYPE_ID_TKIP); + cmd->key_param.key_info = + (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ? + cpu_to_le32(ENCR_KEY_FLAG_PAIRWISE) : + cpu_to_le32(ENCR_KEY_FLAG_TXGROUPKEY); + cmd->key_param.key_info |= + cpu_to_le32(ENCR_KEY_FLAG_MICKEY_VALID | + ENCR_KEY_FLAG_TSC_VALID); + break; + case WLAN_CIPHER_SUITE_CCMP: + cmd->key_param.key_type_id = cpu_to_le16(KEY_TYPE_ID_AES); + cmd->key_param.key_info = + (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ? + cpu_to_le32(ENCR_KEY_FLAG_PAIRWISE) : + cpu_to_le32(ENCR_KEY_FLAG_TXGROUPKEY); + break; + default: + return -ENOTSUPP; + } -/* PUBLIC FUNCTION DEFINITION -*/ + return 0; +} void mwl_fwcmd_reset(struct ieee80211_hw *hw) { struct mwl_priv *priv; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - if (mwl_fwcmd_chk_adapter(priv)) { + if (mwl_fwcmd_chk_adapter(priv)) writel(ISR_RESET, priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS); - } - - WLDBG_EXIT(DBG_LEVEL_2); } void mwl_fwcmd_int_enable(struct ieee80211_hw *hw) { struct mwl_priv *priv; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); if (mwl_fwcmd_chk_adapter(priv)) { writel(0x00, @@ -996,26 +1411,17 @@ void mwl_fwcmd_int_enable(struct ieee80211_hw *hw) writel((MACREG_A2HRIC_BIT_MASK), priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK); } - - WLDBG_EXIT(DBG_LEVEL_2); } void mwl_fwcmd_int_disable(struct ieee80211_hw *hw) { struct mwl_priv *priv; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - if (mwl_fwcmd_chk_adapter(priv)) { + if (mwl_fwcmd_chk_adapter(priv)) writel(0x00, priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK); - } - - WLDBG_EXIT(DBG_LEVEL_2); } int mwl_fwcmd_get_hw_specs(struct ieee80211_hw *hw) @@ -1023,59 +1429,56 @@ int mwl_fwcmd_get_hw_specs(struct ieee80211_hw *hw) struct mwl_priv *priv; struct hostcmd_cmd_get_hw_spec *pcmd; unsigned long flags; + int retry; int i; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_get_hw_spec *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); - WLDBG_PRINT("pcmd = %x", (unsigned int)pcmd); + wiphy_debug(hw->wiphy, "pcmd = %x", (unsigned int)pcmd); memset(pcmd, 0x00, sizeof(*pcmd)); memset(&pcmd->permanent_addr[0], 0xff, ETH_ALEN); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_GET_HW_SPEC); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->fw_awake_cookie = ENDIAN_SWAP32(priv->pphys_cmd_buf + 2048); - - WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_GET_HW_SPEC); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->fw_awake_cookie = cpu_to_le32(priv->pphys_cmd_buf + 2048); + retry = 0; while (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_GET_HW_SPEC)) { - WLDBG_PRINT("failed execution"); - WL_MSEC_SLEEP(1000); - WLDBG_PRINT("repeat command = %x", (unsigned int)pcmd); + if (retry++ > MAX_WAIT_GET_HW_SPECS_ITERATONS) { + wiphy_err(hw->wiphy, "can't get hw specs"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + return -EIO; + } + + mdelay(1000); + wiphy_debug(hw->wiphy, + "repeat command = %x", (unsigned int)pcmd); } ether_addr_copy(&priv->hw_data.mac_addr[0], pcmd->permanent_addr); priv->desc_data[0].wcb_base = - ENDIAN_SWAP32(pcmd->wcb_base0) & 0x0000ffff; + 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 = - ENDIAN_SWAP32(pcmd->wcb_base[i - 1]) & 0x0000ffff; + le32_to_cpu(pcmd->wcb_base[i - 1]) & 0x0000ffff; #endif priv->desc_data[0].rx_desc_read = - ENDIAN_SWAP32(pcmd->rxpd_rd_ptr) & 0x0000ffff; + le32_to_cpu(pcmd->rxpd_rd_ptr) & 0x0000ffff; priv->desc_data[0].rx_desc_write = - ENDIAN_SWAP32(pcmd->rxpd_wr_ptr) & 0x0000ffff; - priv->hw_data.region_code = ENDIAN_SWAP16(pcmd->region_code) & 0x00ff; - priv->hw_data.fw_release_num = ENDIAN_SWAP32(pcmd->fw_release_num); - priv->hw_data.max_num_tx_desc = ENDIAN_SWAP16(pcmd->num_wcb); - priv->hw_data.max_num_mc_addr = ENDIAN_SWAP16(pcmd->num_mcast_addr); - priv->hw_data.num_antennas = ENDIAN_SWAP16(pcmd->num_antenna); + le32_to_cpu(pcmd->rxpd_wr_ptr) & 0x0000ffff; + priv->hw_data.region_code = le16_to_cpu(pcmd->region_code) & 0x00ff; + priv->hw_data.fw_release_num = le32_to_cpu(pcmd->fw_release_num); + priv->hw_data.max_num_tx_desc = le16_to_cpu(pcmd->num_wcb); + priv->hw_data.max_num_mc_addr = le16_to_cpu(pcmd->num_mcast_addr); + priv->hw_data.num_antennas = le16_to_cpu(pcmd->num_antenna); priv->hw_data.hw_version = pcmd->version; priv->hw_data.host_interface = pcmd->host_if; - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - - WLDBG_EXIT_INFO(DBG_LEVEL_2, - "region code is %i (0x%x), HW version is %i (0x%x)", - priv->hw_data.region_code, priv->hw_data.region_code, - priv->hw_data.hw_version, priv->hw_data.hw_version); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1087,57 +1490,52 @@ int mwl_fwcmd_set_hw_specs(struct ieee80211_hw *hw) unsigned long flags; int i; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); /* Info for debugging */ - WLDBG_PRINT("%s ...", __func__); - WLDBG_PRINT(" -->pPhysTxRing[0] = %x", - priv->desc_data[0].pphys_tx_ring); - WLDBG_PRINT(" -->pPhysTxRing[1] = %x", - priv->desc_data[1].pphys_tx_ring); - WLDBG_PRINT(" -->pPhysTxRing[2] = %x", - priv->desc_data[2].pphys_tx_ring); - WLDBG_PRINT(" -->pPhysTxRing[3] = %x", - priv->desc_data[3].pphys_tx_ring); - WLDBG_PRINT(" -->pPhysRxRing = %x", - priv->desc_data[0].pphys_rx_ring); - WLDBG_PRINT(" -->numtxq %d wcbperq %d totalrxwcb %d", - SYSADPT_NUM_OF_DESC_DATA, - SYSADPT_MAX_NUM_TX_DESC, - SYSADPT_MAX_NUM_RX_DESC); + 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]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_HW_SPEC); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->wcb_base[0] = ENDIAN_SWAP32(priv->desc_data[0].pphys_tx_ring); + 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] = - ENDIAN_SWAP32(priv->desc_data[i].pphys_tx_ring); + cpu_to_le32(priv->desc_data[i].pphys_tx_ring); #endif - pcmd->tx_wcb_num_per_queue = ENDIAN_SWAP32(SYSADPT_MAX_NUM_TX_DESC); - pcmd->num_tx_queues = ENDIAN_SWAP32(SYSADPT_NUM_OF_DESC_DATA); - pcmd->total_rx_wcb = ENDIAN_SWAP32(SYSADPT_MAX_NUM_RX_DESC); - pcmd->rxpd_wr_ptr = ENDIAN_SWAP32(priv->desc_data[0].pphys_rx_ring); - pcmd->disablembss = 0; + 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); + pcmd->rxpd_wr_ptr = cpu_to_le32(priv->desc_data[0].pphys_rx_ring); + pcmd->features = 0; if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_HW_SPEC)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1149,75 +1547,44 @@ int mwl_fwcmd_get_stat(struct ieee80211_hw *hw, struct hostcmd_cmd_802_11_get_stat *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_802_11_get_stat *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_802_11_GET_STAT); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(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)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } stats->dot11ACKFailureCount = - ENDIAN_SWAP32(pcmd->ack_failures); + le32_to_cpu(pcmd->ack_failures); stats->dot11RTSFailureCount = - ENDIAN_SWAP32(pcmd->rts_failures); + le32_to_cpu(pcmd->rts_failures); stats->dot11FCSErrorCount = - ENDIAN_SWAP32(pcmd->rx_fcs_errors); + le32_to_cpu(pcmd->rx_fcs_errors); stats->dot11RTSSuccessCount = - ENDIAN_SWAP32(pcmd->rts_successes); + le32_to_cpu(pcmd->rts_successes); - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } int mwl_fwcmd_radio_enable(struct ieee80211_hw *hw) { - struct mwl_priv *priv; - int rc; - - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); - priv = hw->priv; - BUG_ON(!priv); - - rc = mwl_fwcmd_802_11_radio_control(priv, true, false); - - WLDBG_EXIT(DBG_LEVEL_2); - - return rc; + return mwl_fwcmd_802_11_radio_control(hw->priv, true, false); } int mwl_fwcmd_radio_disable(struct ieee80211_hw *hw) { - struct mwl_priv *priv; - int rc; - - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); - priv = hw->priv; - BUG_ON(!priv); - - rc = mwl_fwcmd_802_11_radio_control(priv, false, false); - - WLDBG_EXIT(DBG_LEVEL_2); - - return rc; + return mwl_fwcmd_802_11_radio_control(hw->priv, false, false); } int mwl_fwcmd_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) @@ -1225,17 +1592,11 @@ int mwl_fwcmd_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) struct mwl_priv *priv; int rc; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); priv->radio_short_preamble = short_preamble; rc = mwl_fwcmd_802_11_radio_control(priv, true, true); - WLDBG_EXIT(DBG_LEVEL_2); - return rc; } @@ -1250,11 +1611,7 @@ int mwl_fwcmd_max_tx_power(struct ieee80211_hw *hw, int i, tmp; int rc; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); switch (fraction) { case 0: @@ -1280,35 +1637,40 @@ int mwl_fwcmd_max_tx_power(struct ieee80211_hw *hw, else if (channel->band == IEEE80211_BAND_5GHZ) band = FREQ_BAND_5GHZ; - if ((conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) || - (conf->chandef.width == NL80211_CHAN_WIDTH_20)) { + switch (conf->chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: width = CH_20_MHZ_WIDTH; sub_ch = NO_EXT_CHANNEL; - - } else if (conf->chandef.width == NL80211_CHAN_WIDTH_40) { + break; + case NL80211_CHAN_WIDTH_40: width = CH_40_MHZ_WIDTH; if (conf->chandef.center_freq1 > channel->center_freq) sub_ch = EXT_CH_ABOVE_CTRL_CH; else sub_ch = EXT_CH_BELOW_CTRL_CH; - } else if (conf->chandef.width == NL80211_CHAN_WIDTH_80) { + break; + case NL80211_CHAN_WIDTH_80: width = CH_80_MHZ_WIDTH; if (conf->chandef.center_freq1 > channel->center_freq) sub_ch = EXT_CH_ABOVE_CTRL_CH; else sub_ch = EXT_CH_BELOW_CTRL_CH; + break; + default: + return -EINVAL; } - if ((priv->powinited & 2) == 0) { + if ((priv->powinited & MWL_POWER_INIT_2) == 0) { mwl_fwcmd_get_tx_powers(priv, priv->max_tx_pow, channel->hw_value, band, width, sub_ch); - priv->powinited |= 2; + priv->powinited |= MWL_POWER_INIT_2; } - if ((priv->powinited & 1) == 0) { + if ((priv->powinited & MWL_POWER_INIT_1) == 0) { mwl_fwcmd_get_tx_powers(priv, priv->target_powers, channel->hw_value, band, width, sub_ch); - priv->powinited |= 1; + priv->powinited |= MWL_POWER_INIT_1; } for (i = 0; i < SYSADPT_TX_POWER_LEVEL_TOTAL; i++) { @@ -1322,8 +1684,6 @@ int mwl_fwcmd_max_tx_power(struct ieee80211_hw *hw, rc = mwl_fwcmd_set_tx_powers(priv, maxtxpow, HOSTCMD_ACT_GEN_SET, channel->hw_value, band, width, sub_ch); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "return code: %d", rc); - return rc; } @@ -1339,11 +1699,7 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, int i, tmp; int rc; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); switch (fraction) { case 0: @@ -1369,33 +1725,37 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, else if (channel->band == IEEE80211_BAND_5GHZ) band = FREQ_BAND_5GHZ; - if ((conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) || - (conf->chandef.width == NL80211_CHAN_WIDTH_20)) { + switch (conf->chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: width = CH_20_MHZ_WIDTH; sub_ch = NO_EXT_CHANNEL; - } else if (conf->chandef.width == NL80211_CHAN_WIDTH_40) { + break; + case NL80211_CHAN_WIDTH_40: width = CH_40_MHZ_WIDTH; if (conf->chandef.center_freq1 > channel->center_freq) sub_ch = EXT_CH_ABOVE_CTRL_CH; else sub_ch = EXT_CH_BELOW_CTRL_CH; - } else if (conf->chandef.width == NL80211_CHAN_WIDTH_80) { + break; + case NL80211_CHAN_WIDTH_80: width = CH_80_MHZ_WIDTH; if (conf->chandef.center_freq1 > channel->center_freq) sub_ch = EXT_CH_ABOVE_CTRL_CH; else sub_ch = EXT_CH_BELOW_CTRL_CH; + break; + default: + return -EINVAL; } - /* search tx power table if exist - */ + /* search tx power table if exist */ for (index = 0; index < SYSADPT_MAX_NUM_CHANNELS; index++) { struct mwl_tx_pwr_tbl *tx_pwr; tx_pwr = &priv->tx_pwr_tbl[index]; - /* do nothing if table is not loaded - */ + /* do nothing if table is not loaded */ if (tx_pwr->channel == 0) break; @@ -1404,9 +1764,9 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, priv->txantenna2 = tx_pwr->txantenna2; if (tx_pwr->setcap) - priv->powinited = 0x01; + priv->powinited = MWL_POWER_INIT_1; else - priv->powinited = 0x02; + priv->powinited = MWL_POWER_INIT_2; for (i = 0; i < SYSADPT_TX_POWER_LEVEL_TOTAL; i++) { if (tx_pwr->setcap) @@ -1422,18 +1782,18 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, } } - if ((priv->powinited & 2) == 0) { + if ((priv->powinited & MWL_POWER_INIT_2) == 0) { mwl_fwcmd_get_tx_powers(priv, priv->max_tx_pow, channel->hw_value, band, width, sub_ch); - priv->powinited |= 2; + priv->powinited |= MWL_POWER_INIT_2; } - if ((priv->powinited & 1) == 0) { + if ((priv->powinited & MWL_POWER_INIT_1) == 0) { mwl_fwcmd_get_tx_powers(priv, priv->target_powers, channel->hw_value, band, width, sub_ch); - priv->powinited |= 1; + priv->powinited |= MWL_POWER_INIT_1; } for (i = 0; i < SYSADPT_TX_POWER_LEVEL_TOTAL; i++) { @@ -1457,8 +1817,6 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, rc = mwl_fwcmd_set_tx_powers(priv, txpow, HOSTCMD_ACT_GEN_SET_LIST, channel->hw_value, band, width, sub_ch); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "return code: %d", rc); - return rc; } @@ -1468,48 +1826,41 @@ int mwl_fwcmd_rf_antenna(struct ieee80211_hw *hw, int dir, int antenna) struct hostcmd_cmd_802_11_rf_antenna *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_802_11_rf_antenna *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_802_11_RF_ANTENNA); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_RF_ANTENNA); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); - pcmd->action = ENDIAN_SWAP16(dir); + pcmd->action = cpu_to_le16(dir); if (dir == WL_ANTENNATYPE_RX) { u8 rx_antenna = 4; /* if auto, set 4 rx antennas in SC2 */ if (antenna != 0) - pcmd->antenna_mode = ENDIAN_SWAP16(antenna); + pcmd->antenna_mode = cpu_to_le16(antenna); else - pcmd->antenna_mode = ENDIAN_SWAP16(rx_antenna); + pcmd->antenna_mode = cpu_to_le16(rx_antenna); } else { u8 tx_antenna = 0xf; /* if auto, set 4 tx antennas in SC2 */ if (antenna != 0) - pcmd->antenna_mode = ENDIAN_SWAP16(antenna); + pcmd->antenna_mode = cpu_to_le16(antenna); else - pcmd->antenna_mode = ENDIAN_SWAP16(tx_antenna); + pcmd->antenna_mode = cpu_to_le16(tx_antenna); } - WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); - if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_RF_ANTENNA)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1522,34 +1873,26 @@ int mwl_fwcmd_broadcast_ssid_enable(struct ieee80211_hw *hw, struct hostcmd_cmd_broadcast_ssid_enable *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_broadcast_ssid_enable *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_BROADCAST_SSID_ENABLE); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BROADCAST_SSID_ENABLE); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; - pcmd->enable = ENDIAN_SWAP32(enable); + pcmd->enable = cpu_to_le32(enable); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BROADCAST_SSID_ENABLE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1561,54 +1904,62 @@ int mwl_fwcmd_set_rf_channel(struct ieee80211_hw *hw, struct mwl_priv *priv; struct hostcmd_cmd_set_rf_channel *pcmd; unsigned long flags; + u32 chnl_flags, freq_band, chnl_width, act_primary; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_set_rf_channel *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_RF_CHANNEL); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->action = ENDIAN_SWAP16(WL_SET); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_RF_CHANNEL); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->action = cpu_to_le16(WL_SET); pcmd->curr_chnl = channel->hw_value; if (channel->band == IEEE80211_BAND_2GHZ) - pcmd->chnl_flags.freq_band = FREQ_BAND_2DOT4GHZ; + freq_band = FREQ_BAND_2DOT4GHZ; else if (channel->band == IEEE80211_BAND_5GHZ) - pcmd->chnl_flags.freq_band = FREQ_BAND_5GHZ; - - if ((conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) || - (conf->chandef.width == NL80211_CHAN_WIDTH_20)) { - pcmd->chnl_flags.chnl_width = CH_20_MHZ_WIDTH; - pcmd->chnl_flags.act_primary = ACT_PRIMARY_CHAN_0; - } else if (conf->chandef.width == NL80211_CHAN_WIDTH_40) { - pcmd->chnl_flags.chnl_width = CH_40_MHZ_WIDTH; + freq_band = FREQ_BAND_5GHZ; + else + return -EINVAL; + + switch (conf->chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + chnl_width = CH_20_MHZ_WIDTH; + act_primary = ACT_PRIMARY_CHAN_0; + break; + case NL80211_CHAN_WIDTH_40: + chnl_width = CH_40_MHZ_WIDTH; if (conf->chandef.center_freq1 > channel->center_freq) - pcmd->chnl_flags.act_primary = ACT_PRIMARY_CHAN_0; + act_primary = ACT_PRIMARY_CHAN_0; else - pcmd->chnl_flags.act_primary = ACT_PRIMARY_CHAN_1; - } else if (conf->chandef.width == NL80211_CHAN_WIDTH_80) { - pcmd->chnl_flags.chnl_width = CH_80_MHZ_WIDTH; - pcmd->chnl_flags.act_primary = + act_primary = ACT_PRIMARY_CHAN_1; + break; + case NL80211_CHAN_WIDTH_80: + chnl_width = CH_80_MHZ_WIDTH; + act_primary = mwl_fwcmd_get_80m_pri_chnl_offset(pcmd->curr_chnl); + break; + default: + return -EINVAL; } - WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); + chnl_flags = (freq_band & FREQ_BAND_MASK) | + ((chnl_width << CHNL_WIDTH_SHIFT) & CHNL_WIDTH_MASK) | + ((act_primary << ACT_PRIMARY_SHIFT) & ACT_PRIMARY_MASK); + + pcmd->chnl_flags = cpu_to_le32(chnl_flags); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_RF_CHANNEL)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1621,35 +1972,27 @@ int mwl_fwcmd_set_aid(struct ieee80211_hw *hw, struct hostcmd_cmd_set_aid *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_set_aid *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_AID); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_AID); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; - pcmd->aid = ENDIAN_SWAP16(aid); + pcmd->aid = cpu_to_le16(aid); ether_addr_copy(pcmd->mac_addr, bssid); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_AID)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1662,33 +2005,25 @@ int mwl_fwcmd_set_infra_mode(struct ieee80211_hw *hw, struct hostcmd_cmd_set_infra_mode *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_set_infra_mode *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_INFRA_MODE); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_INFRA_MODE); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_INFRA_MODE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1699,30 +2034,25 @@ int mwl_fwcmd_set_rts_threshold(struct ieee80211_hw *hw, int threshold) struct hostcmd_cmd_802_11_rts_thsd *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_802_11_rts_thsd *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_802_11_RTS_THSD); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->action = ENDIAN_SWAP16(WL_SET); - pcmd->threshold = ENDIAN_SWAP16(threshold); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_RTS_THSD); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->action = cpu_to_le16(WL_SET); + pcmd->threshold = cpu_to_le16(threshold); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_RTS_THSD)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1734,24 +2064,20 @@ int mwl_fwcmd_set_edca_params(struct ieee80211_hw *hw, u8 index, struct hostcmd_cmd_set_edca_params *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_set_edca_params *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_EDCA_PARAMS); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_EDCA_PARAMS); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); - pcmd->action = ENDIAN_SWAP16(0xffff); - pcmd->txop = ENDIAN_SWAP16(txop); - pcmd->cw_max = ENDIAN_SWAP32(ilog2(cw_max + 1)); - pcmd->cw_min = ENDIAN_SWAP32(ilog2(cw_min + 1)); + pcmd->action = cpu_to_le16(0xffff); + pcmd->txop = cpu_to_le16(txop); + pcmd->cw_max = cpu_to_le32(ilog2(cw_max + 1)); + pcmd->cw_min = cpu_to_le32(ilog2(cw_min + 1)); pcmd->aifsn = aifs; pcmd->txq_num = index; @@ -1764,16 +2090,13 @@ int mwl_fwcmd_set_edca_params(struct ieee80211_hw *hw, u8 index, else if (index == 1) pcmd->txq_num = 0; - WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); - if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_EDCA_PARAMS)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1784,29 +2107,24 @@ int mwl_fwcmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable) struct hostcmd_cmd_set_wmm_mode *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_set_wmm_mode *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_WMM_MODE); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->action = ENDIAN_SWAP16(enable ? WL_ENABLE : WL_DISABLE); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_WMM_MODE); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->action = cpu_to_le16(enable ? WL_ENABLE : WL_DISABLE); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_WMM_MODE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1817,32 +2135,27 @@ int mwl_fwcmd_use_fixed_rate(struct ieee80211_hw *hw, int mcast, int mgmt) struct hostcmd_cmd_set_fixed_rate *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_set_fixed_rate *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_FIXED_RATE); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_FIXED_RATE); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); - pcmd->action = ENDIAN_SWAP32(HOSTCMD_ACT_NOT_USE_FIXED_RATE); + pcmd->action = cpu_to_le32(HOSTCMD_ACT_NOT_USE_FIXED_RATE); pcmd->multicast_rate = mcast; pcmd->management_rate = mgmt; if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_FIXED_RATE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1853,30 +2166,25 @@ int mwl_fwcmd_set_rate_adapt_mode(struct ieee80211_hw *hw, u16 mode) struct hostcmd_cmd_set_rate_adapt_mode *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_set_rate_adapt_mode *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_RATE_ADAPT_MODE); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->action = ENDIAN_SWAP16(WL_SET); - pcmd->rate_adapt_mode = ENDIAN_SWAP16(mode); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_RATE_ADAPT_MODE); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->action = cpu_to_le16(WL_SET); + pcmd->rate_adapt_mode = cpu_to_le16(mode); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_RATE_ADAPT_MODE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1889,35 +2197,27 @@ int mwl_fwcmd_set_mac_addr_client(struct ieee80211_hw *hw, struct hostcmd_cmd_set_mac_addr *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_set_mac_addr *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_MAC_ADDR); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_MAC_ADDR); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; - pcmd->mac_type = WL_MAC_TYPE_SECONDARY_CLIENT; + pcmd->mac_type = cpu_to_le16(WL_MAC_TYPE_SECONDARY_CLIENT); ether_addr_copy(pcmd->mac_addr, mac_addr); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_MAC_ADDR)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1928,30 +2228,25 @@ int mwl_fwcmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap) struct hostcmd_cmd_get_watchdog_bitmap *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_get_watchdog_bitmap *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_GET_WATCHDOG_BITMAP); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(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)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } *bitmap = pcmd->watchdog_bitmap; - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -1964,34 +2259,26 @@ int mwl_fwcmd_remove_mac_addr(struct ieee80211_hw *hw, struct hostcmd_cmd_set_mac_addr *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_set_mac_addr *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_DEL_MAC_ADDR); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_DEL_MAC_ADDR); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; ether_addr_copy(pcmd->mac_addr, mac_addr); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_DEL_MAC_ADDR)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2004,15 +2291,8 @@ int mwl_fwcmd_bss_start(struct ieee80211_hw *hw, struct hostcmd_cmd_bss_start *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); if (enable && (priv->running_bsses & (1 << mwl_vif->macid))) return 0; @@ -2022,25 +2302,25 @@ int mwl_fwcmd_bss_start(struct ieee80211_hw *hw, pcmd = (struct hostcmd_cmd_bss_start *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_BSS_START); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BSS_START); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; if (enable) { - pcmd->enable = ENDIAN_SWAP32(WL_ENABLE); + pcmd->enable = cpu_to_le32(WL_ENABLE); } else { if (mwl_vif->macid == 0) - pcmd->enable = ENDIAN_SWAP32(WL_DISABLE); + pcmd->enable = cpu_to_le32(WL_DISABLE); else - pcmd->enable = ENDIAN_SWAP32(WL_DISABLE_VMAC); + pcmd->enable = cpu_to_le32(WL_DISABLE_VMAC); } if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BSS_START)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } @@ -2049,8 +2329,7 @@ int mwl_fwcmd_bss_start(struct ieee80211_hw *hw, else priv->running_bsses &= ~(1 << mwl_vif->macid); - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2061,15 +2340,8 @@ int mwl_fwcmd_set_beacon(struct ieee80211_hw *hw, struct mwl_priv *priv; struct mwl_vif *mwl_vif; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); mwl_fwcmd_parse_beacon(priv, mwl_vif, beacon, len); @@ -2081,16 +2353,12 @@ int mwl_fwcmd_set_beacon(struct ieee80211_hw *hw, mwl_vif->beacon_info.valid = false; - WLDBG_EXIT(DBG_LEVEL_2); - return 0; err: mwl_vif->beacon_info.valid = false; - WLDBG_EXIT_INFO(DBG_LEVEL_2, "set beacon failed"); - return -EIO; } @@ -2104,34 +2372,25 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw, unsigned long flags; u32 rates; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); - - BUG_ON(!sta); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_set_new_stn *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_NEW_STN); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_NEW_STN); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; - pcmd->action = ENDIAN_SWAP16(HOSTCMD_ACT_STA_ACTION_ADD); + pcmd->action = cpu_to_le16(HOSTCMD_ACT_STA_ACTION_ADD); if (mwl_vif->is_sta) { pcmd->aid = 0; pcmd->stn_id = 0; } else { - pcmd->aid = ENDIAN_SWAP16(sta->aid); - pcmd->stn_id = ENDIAN_SWAP16(sta->aid); + pcmd->aid = cpu_to_le16(sta->aid); + pcmd->stn_id = cpu_to_le16(sta->aid); } ether_addr_copy(pcmd->mac_addr, sta->addr); @@ -2139,14 +2398,14 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw, rates = sta->supp_rates[IEEE80211_BAND_2GHZ]; else rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5; - pcmd->peer_info.legacy_rate_bitmap = ENDIAN_SWAP32(rates); + pcmd->peer_info.legacy_rate_bitmap = cpu_to_le32(rates); if (sta->ht_cap.ht_supported) { pcmd->peer_info.ht_rates[0] = sta->ht_cap.mcs.rx_mask[0]; pcmd->peer_info.ht_rates[1] = sta->ht_cap.mcs.rx_mask[1]; pcmd->peer_info.ht_rates[2] = sta->ht_cap.mcs.rx_mask[2]; pcmd->peer_info.ht_rates[3] = sta->ht_cap.mcs.rx_mask[3]; - pcmd->peer_info.ht_cap_info = ENDIAN_SWAP16(sta->ht_cap.cap); + pcmd->peer_info.ht_cap_info = cpu_to_le16(sta->ht_cap.cap); pcmd->peer_info.mac_ht_param_info = (sta->ht_cap.ampdu_factor & 3) | ((sta->ht_cap.ampdu_density & 7) << 2); @@ -2154,9 +2413,9 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw, if (sta->vht_cap.vht_supported) { pcmd->peer_info.vht_max_rx_mcs = - ENDIAN_SWAP32(*((u32 *) + cpu_to_le32(*((u32 *) &sta->vht_cap.vht_mcs.rx_mcs_map)); - pcmd->peer_info.vht_cap = ENDIAN_SWAP32(sta->vht_cap.cap); + pcmd->peer_info.vht_cap = cpu_to_le32(sta->vht_cap.cap); pcmd->peer_info.vht_rx_channel_width = sta->bandwidth; } @@ -2164,8 +2423,8 @@ 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)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } @@ -2173,14 +2432,13 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw, ether_addr_copy(pcmd->mac_addr, mwl_vif->sta_mac); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2193,36 +2451,28 @@ int mwl_fwcmd_set_new_stn_add_self(struct ieee80211_hw *hw, struct hostcmd_cmd_set_new_stn *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_set_new_stn *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_NEW_STN); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_NEW_STN); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; - pcmd->action = ENDIAN_SWAP16(HOSTCMD_ACT_STA_ACTION_ADD); + pcmd->action = cpu_to_le16(HOSTCMD_ACT_STA_ACTION_ADD); ether_addr_copy(pcmd->mac_addr, vif->addr); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2235,31 +2485,24 @@ int mwl_fwcmd_set_new_stn_del(struct ieee80211_hw *hw, struct hostcmd_cmd_set_new_stn *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_set_new_stn *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_NEW_STN); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_NEW_STN); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; - pcmd->action = ENDIAN_SWAP16(HOSTCMD_ACT_STA_ACTION_REMOVE); + pcmd->action = cpu_to_le16(HOSTCMD_ACT_STA_ACTION_REMOVE); ether_addr_copy(pcmd->mac_addr, addr); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } @@ -2267,14 +2510,13 @@ int mwl_fwcmd_set_new_stn_del(struct ieee80211_hw *hw, ether_addr_copy(pcmd->mac_addr, mwl_vif->sta_mac); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2285,29 +2527,24 @@ int mwl_fwcmd_set_apmode(struct ieee80211_hw *hw, u8 apmode) struct hostcmd_cmd_set_apmode *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_set_apmode *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_APMODE); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_APMODE); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->apmode = apmode; if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_APMODE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2318,35 +2555,28 @@ int mwl_fwcmd_update_encryption_enable(struct ieee80211_hw *hw, { struct mwl_priv *priv; struct mwl_vif *mwl_vif; - struct hostcmd_cmd_update_encryptoin *pcmd; + struct hostcmd_cmd_update_encryption *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); - pcmd = (struct hostcmd_cmd_update_encryptoin *)&priv->pcmd_buf[0]; + pcmd = (struct hostcmd_cmd_update_encryption *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_UPDATE_ENCRYPTION); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_UPDATE_ENCRYPTION); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; - pcmd->action_type = ENDIAN_SWAP32(ENCR_ACTION_ENABLE_HW_ENCR); + pcmd->action_type = cpu_to_le32(ENCR_ACTION_ENABLE_HW_ENCR); ether_addr_copy(pcmd->mac_addr, addr); pcmd->action_data[0] = encr_type; if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } @@ -2357,14 +2587,13 @@ int mwl_fwcmd_update_encryption_enable(struct ieee80211_hw *hw, ether_addr_copy(pcmd->mac_addr, mwl_vif->bssid); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2382,29 +2611,22 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw, u32 action; u8 idx; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_set_key *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_UPDATE_ENCRYPTION); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_UPDATE_ENCRYPTION); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; rc = mwl_fwcmd_encryption_set_cmd_info(pcmd, addr, key); if (rc) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "encryption not support"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "encryption not support"); return rc; } @@ -2434,17 +2656,17 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw, keymlen = key->keylen; break; default: - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "encryption not support"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "encryption not support"); return -ENOTSUPP; } memcpy((void *)&pcmd->key_param.key, key->key, keymlen); - pcmd->action_type = ENDIAN_SWAP32(action); + pcmd->action_type = cpu_to_le32(action); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } @@ -2457,14 +2679,13 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw, mwl_vif->bssid); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2479,46 +2700,38 @@ int mwl_fwcmd_encryption_remove_key(struct ieee80211_hw *hw, unsigned long flags; int rc; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_set_key *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_UPDATE_ENCRYPTION); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_UPDATE_ENCRYPTION); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; rc = mwl_fwcmd_encryption_set_cmd_info(pcmd, addr, key); if (rc) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "encryption not support"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "encryption not support"); return rc; } - pcmd->action_type = ENDIAN_SWAP32(ENCR_ACTION_TYPE_REMOVE_KEY); + pcmd->action_type = cpu_to_le32(ENCR_ACTION_TYPE_REMOVE_KEY); if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) mwl_vif->wep_key_conf[key->keyidx].enabled = 0; if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2531,55 +2744,45 @@ int mwl_fwcmd_check_ba(struct ieee80211_hw *hw, struct mwl_vif *mwl_vif; struct hostcmd_cmd_bastream *pcmd; unsigned long flags; + u32 ba_flags, ba_type, ba_direction; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!stream); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_bastream *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_BASTREAM); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BASTREAM); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; - pcmd->cmd_hdr.result = ENDIAN_SWAP16(0xffff); + pcmd->cmd_hdr.result = cpu_to_le16(0xffff); - pcmd->action_type = ENDIAN_SWAP32(BA_CHECK_STREAM); + pcmd->action_type = cpu_to_le32(BA_CHECK_STREAM); memcpy(&pcmd->ba_info.create_params.peer_mac_addr[0], stream->sta->addr, ETH_ALEN); pcmd->ba_info.create_params.tid = stream->tid; - pcmd->ba_info.create_params.flags.ba_type = - BASTREAM_FLAG_IMMEDIATE_TYPE; - pcmd->ba_info.create_params.flags.ba_direction = - BASTREAM_FLAG_DIRECTION_UPSTREAM; + ba_type = BASTREAM_FLAG_IMMEDIATE_TYPE; + ba_direction = BASTREAM_FLAG_DIRECTION_UPSTREAM; + ba_flags = (ba_type & BA_TYPE_MASK) | + ((ba_direction << BA_DIRECTION_SHIFT) & BA_DIRECTION_MASK); + pcmd->ba_info.create_params.flags = cpu_to_le32(ba_flags); pcmd->ba_info.create_params.queue_id = stream->idx; - WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); - if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BASTREAM)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } if (pcmd->cmd_hdr.result != 0) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "result error"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "result error"); return -EINVAL; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2592,39 +2795,32 @@ int mwl_fwcmd_create_ba(struct ieee80211_hw *hw, struct mwl_vif *mwl_vif; struct hostcmd_cmd_bastream *pcmd; unsigned long flags; + u32 ba_flags, ba_type, ba_direction; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!stream); - - BUG_ON(!vif); - mwl_vif = MWL_VIF(vif); - BUG_ON(!mwl_vif); + mwl_vif = mwl_dev_get_vif(vif); pcmd = (struct hostcmd_cmd_bastream *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_BASTREAM); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BASTREAM); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); pcmd->cmd_hdr.macid = mwl_vif->macid; - pcmd->cmd_hdr.result = ENDIAN_SWAP16(0xffff); + pcmd->cmd_hdr.result = cpu_to_le16(0xffff); - pcmd->action_type = ENDIAN_SWAP32(BA_CREATE_STREAM); - pcmd->ba_info.create_params.bar_thrs = ENDIAN_SWAP32(buf_size); - pcmd->ba_info.create_params.window_size = ENDIAN_SWAP32(buf_size); + pcmd->action_type = cpu_to_le32(BA_CREATE_STREAM); + pcmd->ba_info.create_params.bar_thrs = cpu_to_le32(buf_size); + pcmd->ba_info.create_params.window_size = cpu_to_le32(buf_size); memcpy(&pcmd->ba_info.create_params.peer_mac_addr[0], stream->sta->addr, ETH_ALEN); pcmd->ba_info.create_params.tid = stream->tid; - pcmd->ba_info.create_params.flags.ba_type = - BASTREAM_FLAG_IMMEDIATE_TYPE; - pcmd->ba_info.create_params.flags.ba_direction = - BASTREAM_FLAG_DIRECTION_UPSTREAM; + ba_type = BASTREAM_FLAG_IMMEDIATE_TYPE; + ba_direction = BASTREAM_FLAG_DIRECTION_UPSTREAM; + ba_flags = (ba_type & BA_TYPE_MASK) | + ((ba_direction << BA_DIRECTION_SHIFT) & BA_DIRECTION_MASK); + pcmd->ba_info.create_params.flags = cpu_to_le32(ba_flags); pcmd->ba_info.create_params.queue_id = stream->idx; pcmd->ba_info.create_params.param_info = (stream->sta->ht_cap.ampdu_factor & @@ -2632,24 +2828,21 @@ int mwl_fwcmd_create_ba(struct ieee80211_hw *hw, ((stream->sta->ht_cap.ampdu_density << 2) & IEEE80211_HT_AMPDU_PARM_DENSITY); pcmd->ba_info.create_params.reset_seq_no = 1; - pcmd->ba_info.create_params.current_seq = ENDIAN_SWAP16(0); - - WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); + pcmd->ba_info.create_params.current_seq = cpu_to_le16(0); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BASTREAM)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } if (pcmd->cmd_hdr.result != 0) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "result error"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "result error"); return -EINVAL; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2660,42 +2853,38 @@ int mwl_fwcmd_destroy_ba(struct ieee80211_hw *hw, struct mwl_priv *priv; struct hostcmd_cmd_bastream *pcmd; unsigned long flags; + u32 ba_flags, ba_type, ba_direction; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_bastream *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_BASTREAM); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BASTREAM); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); - pcmd->action_type = ENDIAN_SWAP32(BA_DESTROY_STREAM); - pcmd->ba_info.destroy_params.flags.ba_type = - BASTREAM_FLAG_IMMEDIATE_TYPE; - pcmd->ba_info.destroy_params.flags.ba_direction = - BASTREAM_FLAG_DIRECTION_UPSTREAM; - pcmd->ba_info.destroy_params.fw_ba_context.context = ENDIAN_SWAP32(idx); + pcmd->action_type = cpu_to_le32(BA_DESTROY_STREAM); + ba_type = BASTREAM_FLAG_IMMEDIATE_TYPE; + ba_direction = BASTREAM_FLAG_DIRECTION_UPSTREAM; + ba_flags = (ba_type & BA_TYPE_MASK) | + ((ba_direction << BA_DIRECTION_SHIFT) & BA_DIRECTION_MASK); + pcmd->ba_info.destroy_params.flags = cpu_to_le32(ba_flags); + pcmd->ba_info.destroy_params.fw_ba_context.context = cpu_to_le32(idx); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BASTREAM)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } -/* caller must hold priv->locks.stream_lock when calling the stream functions -*/ +/* caller must hold priv->stream_lock when calling the stream functions */ struct mwl_ampdu_stream *mwl_fwcmd_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid) @@ -2704,11 +2893,7 @@ struct mwl_ampdu_stream *mwl_fwcmd_add_stream(struct ieee80211_hw *hw, struct mwl_ampdu_stream *stream; int i; - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!sta); for (i = 0; i < SYSADPT_TX_AMPDU_QUEUES; i++) { stream = &priv->ampdu[i]; @@ -2728,11 +2913,7 @@ struct mwl_ampdu_stream *mwl_fwcmd_add_stream(struct ieee80211_hw *hw, int mwl_fwcmd_start_stream(struct ieee80211_hw *hw, struct mwl_ampdu_stream *stream) { - BUG_ON(!hw); - BUG_ON(!stream); - - /* if the stream has already been started, don't start it again - */ + /* if the stream has already been started, don't start it again */ if (stream->state != AMPDU_STREAM_NEW) return 0; @@ -2742,9 +2923,6 @@ int mwl_fwcmd_start_stream(struct ieee80211_hw *hw, void mwl_fwcmd_remove_stream(struct ieee80211_hw *hw, struct mwl_ampdu_stream *stream) { - BUG_ON(!hw); - BUG_ON(!stream); - memset(stream, 0, sizeof(*stream)); } @@ -2755,9 +2933,7 @@ struct mwl_ampdu_stream *mwl_fwcmd_lookup_stream(struct ieee80211_hw *hw, struct mwl_ampdu_stream *stream; int i; - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); for (i = 0; i < SYSADPT_TX_AMPDU_QUEUES; i++) { stream = &priv->ampdu[i]; @@ -2778,9 +2954,7 @@ bool mwl_fwcmd_ampdu_allowed(struct ieee80211_sta *sta, u8 tid) struct mwl_sta *sta_info; struct mwl_tx_info *tx_stats; - BUG_ON(!sta); - sta_info = MWL_STA(sta); - BUG_ON(!sta_info); + sta_info = mwl_dev_get_sta(sta); BUG_ON(tid >= SYSADPT_MAX_TID); @@ -2796,29 +2970,24 @@ int mwl_fwcmd_set_dwds_stamode(struct ieee80211_hw *hw, bool enable) struct hostcmd_cmd_dwds_enable *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_dwds_enable *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_DWDS_ENABLE); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->enable = ENDIAN_SWAP32(enable); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_DWDS_ENABLE); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->enable = cpu_to_le32(enable); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_DWDS_ENABLE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2829,29 +2998,24 @@ int mwl_fwcmd_set_fw_flush_timer(struct ieee80211_hw *hw, u32 value) struct hostcmd_cmd_fw_flush_timer *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_fw_flush_timer *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_FW_FLUSH_TIMER); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->value = ENDIAN_SWAP32(value); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_FW_FLUSH_TIMER); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->value = cpu_to_le32(value); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_FW_FLUSH_TIMER)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } @@ -2862,754 +3026,24 @@ int mwl_fwcmd_set_cdd(struct ieee80211_hw *hw) struct hostcmd_cmd_set_cdd *pcmd; unsigned long flags; - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); pcmd = (struct hostcmd_cmd_set_cdd *)&priv->pcmd_buf[0]; - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + spin_lock_irqsave(&priv->fwcmd_lock, flags); memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_CDD); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->enable = ENDIAN_SWAP32(priv->cdd); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_CDD); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->enable = cpu_to_le32(priv->cdd); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_CDD)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); - return -EIO; - } - - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); - - return 0; -} - -/* PRIVATE FUNCTION DEFINITION -*/ - -static bool mwl_fwcmd_chk_adapter(struct mwl_priv *priv) -{ - u32 regval; - - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!priv); - - regval = readl(priv->iobase1 + MACREG_REG_INT_CODE); - - if (regval == 0xffffffff) { - WLDBG_ERROR(DBG_LEVEL_2, "adapter is not existed"); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "adapter is not existed"); - - return false; - } - - WLDBG_EXIT(DBG_LEVEL_2); - - return true; -} - -static int mwl_fwcmd_exec_cmd(struct mwl_priv *priv, unsigned short cmd) -{ - bool busy = false; - - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!priv); - - if (!mwl_fwcmd_chk_adapter(priv)) { - WLDBG_ERROR(DBG_LEVEL_2, "no adapter existed"); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "no adapter plugged in"); - priv->in_send_cmd = false; - return -EIO; - } - - if (!priv->in_send_cmd) { - priv->in_send_cmd = true; - mwl_fwcmd_send_cmd(priv); - if (mwl_fwcmd_wait_complete(priv, 0x8000 | cmd)) { - WLDBG_ERROR(DBG_LEVEL_2, "timeout"); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "timeout"); - priv->in_send_cmd = false; - return -EIO; - } - } else { - WLDBG_WARNING(DBG_LEVEL_2, "previous command is still running"); - busy = true; - } - - WLDBG_EXIT(DBG_LEVEL_2); - if (!busy) - priv->in_send_cmd = false; - - return 0; -} - -static void mwl_fwcmd_send_cmd(struct mwl_priv *priv) -{ - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!priv); - - writel(priv->pphys_cmd_buf, priv->iobase1 + MACREG_REG_GEN_PTR); - writel(MACREG_H2ARIC_BIT_DOOR_BELL, - priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS); - - WLDBG_EXIT(DBG_LEVEL_2); -} - -static int mwl_fwcmd_wait_complete(struct mwl_priv *priv, unsigned short cmd) -{ - unsigned int curr_iteration = MAX_WAIT_FW_COMPLETE_ITERATIONS; - - unsigned short int_code = 0; - - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!priv); - - do { - int_code = ENDIAN_SWAP16(priv->pcmd_buf[0]); - WL_MSEC_SLEEP(1); - } while ((int_code != cmd) && (--curr_iteration)); - - if (curr_iteration == 0) { - WLDBG_ERROR(DBG_LEVEL_2, "cmd 0x%04x=%s timed out", - cmd, mwl_fwcmd_get_cmd_string(cmd)); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "timeout"); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); + wiphy_err(hw->wiphy, "failed execution"); return -EIO; } - WL_MSEC_SLEEP(3); - - WLDBG_EXIT(DBG_LEVEL_2); + spin_unlock_irqrestore(&priv->fwcmd_lock, flags); return 0; } - -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; - - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!priv); - - if (enable == priv->radio_on && !force) - return 0; - - pcmd = (struct hostcmd_cmd_802_11_radio_control *)&priv->pcmd_buf[0]; - - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); - - memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_802_11_RADIO_CONTROL); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->action = ENDIAN_SWAP16(WL_SET); - pcmd->control = ENDIAN_SWAP16(priv->radio_short_preamble ? - WL_AUTO_PREAMBLE : WL_LONG_PREAMBLE); - pcmd->radio_on = ENDIAN_SWAP16(enable ? WL_ENABLE : WL_DISABLE); - - WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); - - if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_RADIO_CONTROL)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); - return -EIO; - } - - priv->radio_on = enable; - - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); - - return 0; -} - -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; - - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!priv); - - pcmd = (struct hostcmd_cmd_802_11_tx_power *)&priv->pcmd_buf[0]; - - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); - - memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_802_11_TX_POWER); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->action = ENDIAN_SWAP16(HOSTCMD_ACT_GEN_GET_LIST); - pcmd->ch = ENDIAN_SWAP16(ch); - pcmd->bw = ENDIAN_SWAP16(width); - pcmd->band = ENDIAN_SWAP16(band); - pcmd->sub_ch = ENDIAN_SWAP16(sub_ch); - - if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_TX_POWER)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); - return -EIO; - } - - for (i = 0; i < SYSADPT_TX_POWER_LEVEL_TOTAL; i++) - powlist[i] = (u8)ENDIAN_SWAP16(pcmd->power_level_list[i]); - - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); - - return 0; -} - -static int mwl_fwcmd_set_tx_powers(struct mwl_priv *priv, u16 txpow[], - u8 action, u16 ch, u16 band, - u16 width, u16 sub_ch) -{ - struct hostcmd_cmd_802_11_tx_power *pcmd; - unsigned long flags; - int i; - - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!priv); - - pcmd = (struct hostcmd_cmd_802_11_tx_power *)&priv->pcmd_buf[0]; - - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); - - memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_802_11_TX_POWER); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->action = ENDIAN_SWAP16(action); - pcmd->ch = ENDIAN_SWAP16(ch); - pcmd->bw = ENDIAN_SWAP16(width); - pcmd->band = ENDIAN_SWAP16(band); - pcmd->sub_ch = ENDIAN_SWAP16(sub_ch); - - for (i = 0; i < SYSADPT_TX_POWER_LEVEL_TOTAL; i++) - pcmd->power_level_list[i] = ENDIAN_SWAP16(txpow[i]); - - if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_TX_POWER)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); - return -EIO; - } - - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); - - return 0; -} - -static u8 mwl_fwcmd_get_80m_pri_chnl_offset(u8 channel) -{ - u8 act_primary = ACT_PRIMARY_CHAN_0; - - switch (channel) { - case 36: - act_primary = ACT_PRIMARY_CHAN_0; - break; - case 40: - act_primary = ACT_PRIMARY_CHAN_1; - break; - case 44: - act_primary = ACT_PRIMARY_CHAN_2; - break; - case 48: - act_primary = ACT_PRIMARY_CHAN_3; - break; - case 52: - act_primary = ACT_PRIMARY_CHAN_0; - break; - case 56: - act_primary = ACT_PRIMARY_CHAN_1; - break; - case 60: - act_primary = ACT_PRIMARY_CHAN_2; - break; - case 64: - act_primary = ACT_PRIMARY_CHAN_3; - break; - case 100: - act_primary = ACT_PRIMARY_CHAN_0; - break; - case 104: - act_primary = ACT_PRIMARY_CHAN_1; - break; - case 108: - act_primary = ACT_PRIMARY_CHAN_2; - break; - case 112: - act_primary = ACT_PRIMARY_CHAN_3; - break; - case 116: - act_primary = ACT_PRIMARY_CHAN_0; - break; - case 120: - act_primary = ACT_PRIMARY_CHAN_1; - break; - case 124: - act_primary = ACT_PRIMARY_CHAN_2; - break; - case 128: - act_primary = ACT_PRIMARY_CHAN_3; - break; - case 132: - act_primary = ACT_PRIMARY_CHAN_0; - break; - case 136: - act_primary = ACT_PRIMARY_CHAN_1; - break; - case 140: - act_primary = ACT_PRIMARY_CHAN_2; - break; - case 144: - act_primary = ACT_PRIMARY_CHAN_3; - break; - case 149: - act_primary = ACT_PRIMARY_CHAN_0; - break; - case 153: - act_primary = ACT_PRIMARY_CHAN_1; - break; - case 157: - act_primary = ACT_PRIMARY_CHAN_2; - break; - case 161: - act_primary = ACT_PRIMARY_CHAN_3; - break; - } - - return act_primary; -} - -static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv, - struct mwl_vif *vif, u8 *beacon, int len) -{ - struct ieee80211_mgmt *mgmt; - struct beacon_info *beacon_info; - int baselen; - u8 *pos; - size_t left; - bool elem_parse_failed; - - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!vif); - BUG_ON(!beacon); - - mgmt = (struct ieee80211_mgmt *)beacon; - - baselen = (u8 *)mgmt->u.beacon.variable - (u8 *)mgmt; - if (baselen > len) - return; - - beacon_info = &vif->beacon_info; - memset(beacon_info, 0, sizeof(struct beacon_info)); - beacon_info->valid = false; - beacon_info->ie_ht_ptr = &beacon_info->ie_list_ht[0]; - beacon_info->ie_vht_ptr = &beacon_info->ie_list_vht[0]; - - beacon_info->cap_info = mgmt->u.beacon.capab_info; - - pos = (u8 *)mgmt->u.beacon.variable; - left = len - baselen; - - elem_parse_failed = false; - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) { - elem_parse_failed = true; - break; - } - - switch (id) { - case WLAN_EID_SUPP_RATES: - case WLAN_EID_EXT_SUPP_RATES: - { - int idx, bi, oi; - u8 rate; - - for (bi = 0; bi < SYSADPT_MAX_DATA_RATES_G; - bi++) { - if (beacon_info->b_rate_set[bi] == 0) - break; - } - - for (oi = 0; oi < SYSADPT_MAX_DATA_RATES_G; - oi++) { - if (beacon_info->op_rate_set[oi] == 0) - break; - } - - for (idx = 0; idx < elen; idx++) { - rate = pos[idx]; - if ((rate & 0x80) != 0) { - if (bi < SYSADPT_MAX_DATA_RATES_G) - beacon_info->b_rate_set[bi++] - = rate & 0x7f; - else { - elem_parse_failed = true; - break; - } - } - if (oi < SYSADPT_MAX_DATA_RATES_G) - beacon_info->op_rate_set[oi++] = - rate & 0x7f; - else { - elem_parse_failed = true; - break; - } - } - } - break; - case WLAN_EID_RSN: - beacon_info->ie_rsn48_len = (elen + 2); - beacon_info->ie_rsn48_ptr = (pos - 2); - break; - case WLAN_EID_HT_CAPABILITY: - case WLAN_EID_HT_OPERATION: - case WLAN_EID_OVERLAP_BSS_SCAN_PARAM: - case WLAN_EID_EXT_CAPABILITY: - beacon_info->ie_ht_len += (elen + 2); - if (beacon_info->ie_ht_len > - sizeof(beacon_info->ie_list_ht)) { - elem_parse_failed = true; - } else { - *beacon_info->ie_ht_ptr++ = id; - *beacon_info->ie_ht_ptr++ = elen; - memcpy(beacon_info->ie_ht_ptr, pos, elen); - beacon_info->ie_ht_ptr += elen; - } - break; - case WLAN_EID_VHT_CAPABILITY: - case WLAN_EID_VHT_OPERATION: - case WLAN_EID_OPMODE_NOTIF: - beacon_info->ie_vht_len += (elen + 2); - if (beacon_info->ie_vht_len > - sizeof(beacon_info->ie_list_vht)) { - elem_parse_failed = true; - } else { - *beacon_info->ie_vht_ptr++ = id; - *beacon_info->ie_vht_ptr++ = elen; - memcpy(beacon_info->ie_vht_ptr, pos, elen); - beacon_info->ie_vht_ptr += elen; - } - break; - case WLAN_EID_VENDOR_SPECIFIC: - if ((pos[0] == 0x00) && (pos[1] == 0x50) && - (pos[2] == 0xf2)) { - if (pos[3] == 0x01) { - beacon_info->ie_rsn_len = (elen + 2); - beacon_info->ie_rsn_ptr = (pos - 2); - } - - if (pos[3] == 0x02) { - beacon_info->ie_wmm_len = (elen + 2); - beacon_info->ie_wmm_ptr = (pos - 2); - } - } - break; - default: - break; - } - - left -= elen; - pos += elen; - } - - if (!elem_parse_failed) { - beacon_info->ie_ht_ptr = &beacon_info->ie_list_ht[0]; - beacon_info->ie_vht_ptr = &beacon_info->ie_list_vht[0]; - beacon_info->valid = true; - - WLDBG_INFO(DBG_LEVEL_2, - "wmm:%d, rsn:%d, rsn48:%d, ht:%d, vht:%d", - beacon_info->ie_wmm_len, - beacon_info->ie_rsn_len, - beacon_info->ie_rsn48_len, - beacon_info->ie_ht_len, - beacon_info->ie_vht_len); - - WLDBG_DUMP_DATA(DBG_LEVEL_2, beacon_info->b_rate_set, - SYSADPT_MAX_DATA_RATES_G); - - WLDBG_DUMP_DATA(DBG_LEVEL_2, beacon_info->op_rate_set, - SYSADPT_MAX_DATA_RATES_G); - } - - WLDBG_EXIT_INFO(DBG_LEVEL_2, "parse valid:%d", beacon_info->valid); -} - -static int mwl_fwcmd_set_ies(struct mwl_priv *priv, struct mwl_vif *mwl_vif) -{ - struct hostcmd_cmd_set_ies *pcmd; - unsigned long flags; - - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!priv); - BUG_ON(!mwl_vif); - - if (!mwl_vif->beacon_info.valid) - return -EINVAL; - - if (mwl_vif->beacon_info.ie_ht_len > sizeof(pcmd->ie_list_ht)) - goto einval; - - if (mwl_vif->beacon_info.ie_vht_len > sizeof(pcmd->ie_list_vht)) - goto einval; - - pcmd = (struct hostcmd_cmd_set_ies *)&priv->pcmd_buf[0]; - - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); - - memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_IES); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->cmd_hdr.macid = mwl_vif->macid; - - pcmd->action = ENDIAN_SWAP16(HOSTCMD_ACT_GEN_SET); - - pcmd->ie_list_len_ht = mwl_vif->beacon_info.ie_ht_len; - memcpy(pcmd->ie_list_ht, mwl_vif->beacon_info.ie_ht_ptr, - pcmd->ie_list_len_ht); - - pcmd->ie_list_len_vht = mwl_vif->beacon_info.ie_vht_len; - memcpy(pcmd->ie_list_vht, mwl_vif->beacon_info.ie_vht_ptr, - pcmd->ie_list_len_vht); - - if (priv->chip_type == MWL8897) { - pcmd->ie_list_len_proprietary = mwl_vif->beacon_info.ie_wmm_len; - memcpy(pcmd->ie_list_proprietary, - mwl_vif->beacon_info.ie_wmm_ptr, - pcmd->ie_list_len_proprietary); - } - - WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); - - if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_IES)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); - return -EIO; - } - - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); - - return 0; - -einval: - - WLDBG_EXIT_INFO(DBG_LEVEL_2, "length of IE is too long"); - - return -EINVAL; -} - -static int mwl_fwcmd_set_ap_beacon(struct mwl_priv *priv, - struct mwl_vif *mwl_vif, - struct ieee80211_bss_conf *bss_conf) -{ - struct hostcmd_cmd_ap_beacon *pcmd; - unsigned long flags; - struct ds_params *phy_ds_param_set; - - WLDBG_ENTER(DBG_LEVEL_2); - - BUG_ON(!priv); - BUG_ON(!mwl_vif); - BUG_ON(!bss_conf); - - if (!mwl_vif->beacon_info.valid) - return -EINVAL; - - /* wmm structure of start command is defined less one byte, - * due to following field country is not used, add byte one - * to bypass the check. - */ - if (mwl_vif->beacon_info.ie_wmm_len > - (sizeof(pcmd->start_cmd.wmm_param) + 1)) - goto ielenerr; - - if (mwl_vif->beacon_info.ie_rsn_len > sizeof(pcmd->start_cmd.rsn_ie)) - goto ielenerr; - - if (mwl_vif->beacon_info.ie_rsn48_len > - sizeof(pcmd->start_cmd.rsn48_ie)) - goto ielenerr; - - pcmd = (struct hostcmd_cmd_ap_beacon *)&priv->pcmd_buf[0]; - - MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); - - memset(pcmd, 0x00, sizeof(*pcmd)); - pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_AP_BEACON); - pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); - pcmd->cmd_hdr.macid = mwl_vif->macid; - - ether_addr_copy(pcmd->start_cmd.sta_mac_addr, mwl_vif->bssid); - memcpy(pcmd->start_cmd.ssid, bss_conf->ssid, bss_conf->ssid_len); - pcmd->start_cmd.bss_type = 1; - pcmd->start_cmd.bcn_period = ENDIAN_SWAP16(bss_conf->beacon_int); - pcmd->start_cmd.dtim_period = bss_conf->dtim_period; /* 8bit */ - - phy_ds_param_set = &pcmd->start_cmd.phy_param_set.ds_param_set; - phy_ds_param_set->elem_id = WLAN_EID_DS_PARAMS; - phy_ds_param_set->len = sizeof(phy_ds_param_set->current_chnl); - phy_ds_param_set->current_chnl = bss_conf->chandef.chan->hw_value; - - pcmd->start_cmd.probe_delay = ENDIAN_SWAP16(10); - pcmd->start_cmd.cap_info = ENDIAN_SWAP16(mwl_vif->beacon_info.cap_info); - - memcpy(&pcmd->start_cmd.wmm_param, mwl_vif->beacon_info.ie_wmm_ptr, - mwl_vif->beacon_info.ie_wmm_len); - - memcpy(&pcmd->start_cmd.rsn_ie, mwl_vif->beacon_info.ie_rsn_ptr, - mwl_vif->beacon_info.ie_rsn_len); - - memcpy(&pcmd->start_cmd.rsn48_ie, mwl_vif->beacon_info.ie_rsn48_ptr, - mwl_vif->beacon_info.ie_rsn48_len); - - memcpy(pcmd->start_cmd.b_rate_set, mwl_vif->beacon_info.b_rate_set, - SYSADPT_MAX_DATA_RATES_G); - - memcpy(pcmd->start_cmd.op_rate_set, mwl_vif->beacon_info.op_rate_set, - SYSADPT_MAX_DATA_RATES_G); - - WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); - - if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_AP_BEACON)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); - return -EIO; - } - - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); - WLDBG_EXIT(DBG_LEVEL_2); - - return 0; - -ielenerr: - - WLDBG_EXIT_INFO(DBG_LEVEL_2, "length of IE is too long"); - - return -EINVAL; -} - -static int mwl_fwcmd_encryption_set_cmd_info(struct hostcmd_cmd_set_key *cmd, - u8 *addr, - struct ieee80211_key_conf *key) -{ - cmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_UPDATE_ENCRYPTION); - cmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*cmd)); - cmd->key_param.length = ENDIAN_SWAP16(sizeof(*cmd) - - offsetof(struct hostcmd_cmd_set_key, key_param)); - cmd->key_param.key_index = ENDIAN_SWAP32(key->keyidx); - cmd->key_param.key_len = ENDIAN_SWAP16(key->keylen); - ether_addr_copy(cmd->key_param.mac_addr, addr); - - switch (key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - cmd->key_param.key_type_id = ENDIAN_SWAP16(KEY_TYPE_ID_WEP); - if (key->keyidx == 0) - cmd->key_param.key_info = - ENDIAN_SWAP32(ENCR_KEY_FLAG_WEP_TXKEY); - break; - case WLAN_CIPHER_SUITE_TKIP: - cmd->key_param.key_type_id = ENDIAN_SWAP16(KEY_TYPE_ID_TKIP); - cmd->key_param.key_info = - (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ? - ENDIAN_SWAP32(ENCR_KEY_FLAG_PAIRWISE) : - ENDIAN_SWAP32(ENCR_KEY_FLAG_TXGROUPKEY); - cmd->key_param.key_info |= - ENDIAN_SWAP32(ENCR_KEY_FLAG_MICKEY_VALID | - ENCR_KEY_FLAG_TSC_VALID); - break; - case WLAN_CIPHER_SUITE_CCMP: - cmd->key_param.key_type_id = ENDIAN_SWAP16(KEY_TYPE_ID_AES); - cmd->key_param.key_info = - (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ? - ENDIAN_SWAP32(ENCR_KEY_FLAG_PAIRWISE) : - ENDIAN_SWAP32(ENCR_KEY_FLAG_TXGROUPKEY); - break; - default: - return -ENOTSUPP; - } - - return 0; -} - -#ifdef MWL_DEBUG -static char *mwl_fwcmd_get_cmd_string(unsigned short cmd) -{ - int max_entries = 0; - int curr_cmd = 0; - - static const struct { - u16 cmd; - char *cmd_string; - } cmds[] = { - { HOSTCMD_CMD_GET_HW_SPEC, "GetHwSpecifications" }, - { HOSTCMD_CMD_SET_HW_SPEC, "SetHwSepcifications" }, - { HOSTCMD_CMD_802_11_GET_STAT, "80211GetStat" }, - { HOSTCMD_CMD_802_11_RADIO_CONTROL, "80211RadioControl" }, - { HOSTCMD_CMD_802_11_TX_POWER, "80211TxPower" }, - { HOSTCMD_CMD_802_11_RF_ANTENNA, "80211RfAntenna" }, - { HOSTCMD_CMD_BROADCAST_SSID_ENABLE, "broadcast_ssid_enable" }, - { HOSTCMD_CMD_SET_RF_CHANNEL, "SetRfChannel" }, - { HOSTCMD_CMD_SET_AID, "SetAid" }, - { HOSTCMD_CMD_SET_INFRA_MODE, "SetInfraMode" }, - { HOSTCMD_CMD_802_11_RTS_THSD, "80211RtsThreshold" }, - { HOSTCMD_CMD_SET_EDCA_PARAMS, "SetEDCAParams" }, - { HOSTCMD_CMD_SET_WMM_MODE, "SetWMMMode" }, - { HOSTCMD_CMD_SET_FIXED_RATE, "SetFixedRate" }, - { HOSTCMD_CMD_SET_IES, "SetInformationElements" }, - { HOSTCMD_CMD_SET_RATE_ADAPT_MODE, "SetRateAdaptationMode" }, - { HOSTCMD_CMD_SET_MAC_ADDR, "SetMacAddr" }, - { HOSTCMD_CMD_GET_WATCHDOG_BITMAP, "GetWatchdogBitMap" }, - { HOSTCMD_CMD_DEL_MAC_ADDR. "DelMacAddr" }, - { HOSTCMD_CMD_BSS_START, "BssStart" }, - { HOSTCMD_CMD_AP_BEACON, "SetApBeacon" }, - { HOSTCMD_CMD_SET_NEW_STN, "SetNewStation" }, - { HOSTCMD_CMD_SET_APMODE, "SetApMode" }, - { HOSTCMD_CMD_UPDATE_ENCRYPTION, "UpdateEncryption" }, - { HOSTCMD_CMD_BASTREAM, "BAStream" }, - { HOSTCMD_CMD_DWDS_ENABLE, "DwdsEnable" }, - { HOSTCMD_CMD_FW_FLUSH_TIMER, "FwFlushTimer" }, - { HOSTCMD_CMD_SET_CDD, "SetCDD" }, - }; - - WLDBG_ENTER(DBG_LEVEL_2); - - max_entries = sizeof(cmds) / sizeof(cmds[0]); - - for (curr_cmd = 0; curr_cmd < max_entries; curr_cmd++) { - if ((cmd & 0x7fff) == cmds[curr_cmd].cmd) { - WLDBG_EXIT(DBG_LEVEL_2); - return cmds[curr_cmd].cmd_string; - } - } - - WLDBG_EXIT_INFO(DBG_LEVEL_2, "unknown"); - - return "unknown"; -} -#endif @@ -1,28 +1,17 @@ /* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ + * 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 firmware host command related functions. -*/ + */ #ifndef _mwl_fwcmd_h_ #define _mwl_fwcmd_h_ -/* CONSTANTS AND MACROS -*/ - /* Define OpMode for SoftAP/Station mode * * The following mode signature has to be written to PCI scratch register#0 @@ -36,9 +25,6 @@ #define HOSTCMD_STA_FWRDY_SIGNATURE 0xF0F1F2F4 #define HOSTCMD_SOFTAP_FWRDY_SIGNATURE 0xF1F2F4A5 -/* TYPE DEFINITION -*/ - enum { WL_ANTENNATYPE_RX = 1, WL_ANTENNATYPE_TX = 2, @@ -52,9 +38,6 @@ enum encr_type { ENCR_TYPE_MIX = 7, }; -/* PUBLIC FUNCTION DECLARATION -*/ - void mwl_fwcmd_reset(struct ieee80211_hw *hw); void mwl_fwcmd_int_enable(struct ieee80211_hw *hw); @@ -1,46 +1,45 @@ /* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ + * 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 implements firmware download related functions. -*/ + */ #include <linux/io.h> -#include "mwl_sysadpt.h" -#include "mwl_dev.h" -#include "mwl_debug.h" -#include "mwl_fwcmd.h" -#include "mwl_fwdl.h" - -/* CONSTANTS AND MACROS -*/ +#include "sysadpt.h" +#include "dev.h" +#include "fwcmd.h" +#include "fwdl.h" #define FW_DOWNLOAD_BLOCK_SIZE 256 #define FW_CHECK_MSECS 1 #define FW_MAX_NUM_CHECKS 0xffff -/* PRIVATE FUNCTION DECLARATION -*/ +static void mwl_fwdl_trig_pcicmd(struct mwl_priv *priv) +{ + writel(priv->pphys_cmd_buf, priv->iobase1 + MACREG_REG_GEN_PTR); + + writel(0x00, priv->iobase1 + MACREG_REG_INT_CODE); + + writel(MACREG_H2ARIC_BIT_DOOR_BELL, + priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS); +} + +static void mwl_fwdl_trig_pcicmd_bootcode(struct mwl_priv *priv) +{ + writel(priv->pphys_cmd_buf, priv->iobase1 + MACREG_REG_GEN_PTR); -static void mwl_fwdl_trig_pcicmd(struct mwl_priv *priv); -static void mwl_fwdl_trig_pcicmd_bootcode(struct mwl_priv *priv); + writel(0x00, priv->iobase1 + MACREG_REG_INT_CODE); -/* PUBLIC FUNCTION DEFINITION -*/ + writel(MACREG_H2ARIC_BIT_DOOR_BELL, + priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS); +} int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) { @@ -51,20 +50,15 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) u32 int_code = 0; u32 len = 0; - WLDBG_ENTER(DBG_LEVEL_1); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); fw = priv->fw_ucode; - BUG_ON(!fw); mwl_fwcmd_reset(hw); /* FW before jumping to boot rom, it will enable PCIe transaction retry, * wait for boot code to stop it. */ - WL_MSEC_SLEEP(FW_CHECK_MSECS); + mdelay(FW_CHECK_MSECS); writel(MACREG_A2HRIC_BIT_MASK, priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CLEAR_SEL); @@ -78,14 +72,12 @@ 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 */ - WLDBG_PRINT("fw download start 88"); + wiphy_info(hw->wiphy, "fw download start 88"); - /* Disable PFU before FWDL - */ + /* Disable PFU before FWDL */ writel(0x100, priv->iobase1 + 0xE0E4); - /* make sure SCRATCH2 C40 is clear, in case we are too quick - */ + /* make sure SCRATCH2 C40 is clear, in case we are too quick */ while (readl(priv->iobase1 + 0xc40) == 0) ; @@ -99,8 +91,7 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) memcpy((char *)&priv->pcmd_buf[0], (fw->data + size_fw_downloaded), len); - /* this function writes pdata to c10, then write 2 to c18 - */ + /* this function writes pdata to c10, then write 2 to c18 */ mwl_fwdl_trig_pcicmd_bootcode(priv); /* this is arbitrary per your platform; we use 0xffff */ @@ -134,15 +125,17 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) * without locking up your entire system just because fw * download failed */ - WLDBG_PRINT("Exhausted curr_iteration for fw download"); + wiphy_err(hw->wiphy, + "Exhausted curr_iteration for fw download"); goto err_download; } size_fw_downloaded += len; } - WLDBG_PRINT("FwSize = %d downloaded Size = %d curr_iteration %d", - (int)fw->size, size_fw_downloaded, curr_iteration); + wiphy_info(hw->wiphy, + "FwSize = %d downloaded Size = %d curr_iteration %d", + (int)fw->size, size_fw_downloaded, curr_iteration); /* Now firware is downloaded successfully, so this part is to check * whether fw can properly execute to an extent that write back @@ -156,23 +149,22 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) do { curr_iteration--; writel(HOSTCMD_SOFTAP_MODE, priv->iobase1 + MACREG_REG_GEN_PTR); - WL_MSEC_SLEEP(FW_CHECK_MSECS); + mdelay(FW_CHECK_MSECS); int_code = readl(priv->iobase1 + MACREG_REG_INT_CODE); if (!(curr_iteration % 0xff)) - WLDBG_PRINT("%x;", int_code); + wiphy_err(hw->wiphy, "%x;", int_code); } while ((curr_iteration) && (int_code != HOSTCMD_SOFTAP_FWRDY_SIGNATURE)); if (curr_iteration == 0) { - WLDBG_PRINT("Exhausted curr_iteration for fw signature"); + wiphy_err(hw->wiphy, + "Exhausted curr_iteration for fw signature"); goto err_download; } - WLDBG_PRINT("complete"); + wiphy_info(hw->wiphy, "complete"); writel(0x00, priv->iobase1 + MACREG_REG_INT_CODE); - WLDBG_EXIT(DBG_LEVEL_1); - return 0; err_download: @@ -181,38 +173,3 @@ err_download: return -EIO; } - -/* PRIVATE FUNCTION DEFINITION -*/ - -static void mwl_fwdl_trig_pcicmd(struct mwl_priv *priv) -{ - WLDBG_ENTER(DBG_LEVEL_1); - - BUG_ON(!priv); - - writel(priv->pphys_cmd_buf, priv->iobase1 + MACREG_REG_GEN_PTR); - - writel(0x00, priv->iobase1 + MACREG_REG_INT_CODE); - - writel(MACREG_H2ARIC_BIT_DOOR_BELL, - priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS); - - WLDBG_EXIT(DBG_LEVEL_1); -} - -static void mwl_fwdl_trig_pcicmd_bootcode(struct mwl_priv *priv) -{ - WLDBG_ENTER(DBG_LEVEL_1); - - BUG_ON(!priv); - - writel(priv->pphys_cmd_buf, priv->iobase1 + MACREG_REG_GEN_PTR); - - writel(0x00, priv->iobase1 + MACREG_REG_INT_CODE); - - writel(MACREG_H2ARIC_BIT_DOOR_BELL, - priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS); - - WLDBG_EXIT(DBG_LEVEL_1); -} @@ -0,0 +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. + */ + +/* Description: This file defines firmware download related functions. + */ + +#ifndef _mwl_fwdl_h_ +#define _mwl_fwdl_h_ + +#include <net/mac80211.h> + +int mwl_fwdl_download_firmware(struct ieee80211_hw *hw); + +#endif /* _mwl_fwdl_h_ */ @@ -0,0 +1,142 @@ +/* + * 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 implements interrupt related functions. + */ + +#include "sysadpt.h" +#include "dev.h" +#include "fwcmd.h" +#include "isr.h" + +#define INVALID_WATCHDOG 0xAA + +irqreturn_t mwl_isr(int irq, void *dev_id) +{ + struct ieee80211_hw *hw = dev_id; + struct mwl_priv *priv; + void *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); + + if (int_status == 0x00000000) + return IRQ_NONE; + + if (int_status == 0xffffffff) { + wiphy_warn(hw->wiphy, "card plugged out???"); + } else { + clr_status = int_status; + + if (int_status & MACREG_A2HRIC_BIT_TX_DONE) { + int_status &= ~MACREG_A2HRIC_BIT_TX_DONE; + + if (!priv->is_tx_schedule) { + status = readl(int_status_mask); + writel((status & ~MACREG_A2HRIC_BIT_TX_DONE), + int_status_mask); + tasklet_schedule(&priv->tx_task); + priv->is_tx_schedule = true; + } + } + + if (int_status & MACREG_A2HRIC_BIT_RX_RDY) { + int_status &= ~MACREG_A2HRIC_BIT_RX_RDY; + + if (!priv->is_rx_schedule) { + status = readl(int_status_mask); + writel((status & ~MACREG_A2HRIC_BIT_RX_RDY), + int_status_mask); + tasklet_schedule(&priv->rx_task); + priv->is_rx_schedule = true; + } + } + + if (int_status & MACREG_A2HRIC_BA_WATCHDOG) { + status = readl(int_status_mask); + writel((status & ~MACREG_A2HRIC_BA_WATCHDOG), + int_status_mask); + int_status &= ~MACREG_A2HRIC_BA_WATCHDOG; + ieee80211_queue_work(hw, &priv->watchdog_ba_handle); + } + + writel(~clr_status, + priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CAUSE); + } + + return IRQ_HANDLED; +} + +void mwl_watchdog_ba_events(struct work_struct *work) +{ + int rc; + u8 bitmap = 0, stream_index; + struct mwl_ampdu_stream *streams; + struct mwl_priv *priv = + container_of(work, struct mwl_priv, watchdog_ba_handle); + struct ieee80211_hw *hw = priv->hw; + u32 status; + + rc = mwl_fwcmd_get_watchdog_bitmap(priv->hw, &bitmap); + + if (rc) + goto done; + + spin_lock(&priv->stream_lock); + + /* the bitmap is the hw queue number. Map it to the ampdu queue. */ + if (bitmap != INVALID_WATCHDOG) { + if (bitmap == SYSADPT_TX_AMPDU_QUEUES) + stream_index = 0; + else if (bitmap > SYSADPT_TX_AMPDU_QUEUES) + stream_index = bitmap - SYSADPT_TX_AMPDU_QUEUES; + else + stream_index = bitmap + 3; /** queue 0 is stream 3*/ + + if (bitmap != 0xFF) { + /* Check if the stream is in use before disabling it */ + streams = &priv->ampdu[stream_index]; + + if (streams->state == AMPDU_STREAM_ACTIVE) { + ieee80211_stop_tx_ba_session(streams->sta, + streams->tid); + spin_unlock(&priv->stream_lock); + mwl_fwcmd_destroy_ba(hw, stream_index); + spin_lock(&priv->stream_lock); + } + } else { + for (stream_index = 0; + stream_index < SYSADPT_TX_AMPDU_QUEUES; + stream_index++) { + streams = &priv->ampdu[stream_index]; + + if (streams->state != AMPDU_STREAM_ACTIVE) + continue; + + ieee80211_stop_tx_ba_session(streams->sta, + streams->tid); + spin_unlock(&priv->stream_lock); + mwl_fwcmd_destroy_ba(hw, stream_index); + spin_lock(&priv->stream_lock); + } + } + } + + spin_unlock(&priv->stream_lock); + +done: + + status = readl(priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); + writel(status | MACREG_A2HRIC_BA_WATCHDOG, + priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); +} @@ -0,0 +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. + */ + +/* Description: This file defines interrupt related functions. + */ + +#ifndef _mwl_isr_h_ +#define _mwl_isr_h_ + +#include <linux/interrupt.h> + +irqreturn_t mwl_isr(int irq, void *dev_id); +void mwl_watchdog_ba_events(struct work_struct *work); + +#endif /* _mwl_isr_h_ */ diff --git a/mwl_mac80211.c b/mac80211.c index 41475d0..4000ea5 100644 --- a/mwl_mac80211.c +++ b/mac80211.c @@ -1,122 +1,27 @@ /* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ + * 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 implements mac80211 related functions. -*/ + */ #include <linux/etherdevice.h> -#include "mwl_sysadpt.h" -#include "mwl_dev.h" -#include "mwl_debug.h" -#include "mwl_fwcmd.h" -#include "mwl_tx.h" -#include "mwl_mac80211.h" - -/* CONSTANTS AND MACROS -*/ +#include "sysadpt.h" +#include "dev.h" +#include "fwcmd.h" +#include "tx.h" +#include "mac80211.h" +#include "isr.h" #define MWL_DRV_NAME KBUILD_MODNAME #define MAX_AMPDU_ATTEMPTS 5 -/* PRIVATE FUNCTION DECLARATION -*/ - -static void mwl_mac80211_tx(struct ieee80211_hw *hw, - struct ieee80211_tx_control *control, - struct sk_buff *skb); -static int mwl_mac80211_start(struct ieee80211_hw *hw); -static void mwl_mac80211_stop(struct ieee80211_hw *hw); -static int mwl_mac80211_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); -static void mwl_mac80211_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); -static int mwl_mac80211_config(struct ieee80211_hw *hw, - u32 changed); -static void mwl_mac80211_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed); -static void mwl_mac80211_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast); -static int mwl_mac80211_set_key(struct ieee80211_hw *hw, - enum set_key_cmd cmd_param, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key); -static int mwl_mac80211_set_rts_threshold(struct ieee80211_hw *hw, - u32 value); -static int mwl_mac80211_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -static int mwl_mac80211_sta_remove(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -static int mwl_mac80211_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - u16 queue, - const struct ieee80211_tx_queue_params *params); -static int mwl_mac80211_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats); -static int mwl_mac80211_get_survey(struct ieee80211_hw *hw, - int idx, - struct survey_info *survey); -static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size); -static void mwl_mac80211_remove_vif(struct mwl_priv *priv, - struct mwl_vif *vif); -static void mwl_mac80211_bss_info_changed_sta(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed); -static void mwl_mac80211_bss_info_changed_ap(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed); - -/* PRIVATE VARIABLES -*/ - -static struct ieee80211_ops mwl_mac80211_ops = { - .tx = mwl_mac80211_tx, - .start = mwl_mac80211_start, - .stop = mwl_mac80211_stop, - .add_interface = mwl_mac80211_add_interface, - .remove_interface = mwl_mac80211_remove_interface, - .config = mwl_mac80211_config, - .bss_info_changed = mwl_mac80211_bss_info_changed, - .configure_filter = mwl_mac80211_configure_filter, - .set_key = mwl_mac80211_set_key, - .set_rts_threshold = mwl_mac80211_set_rts_threshold, - .sta_add = mwl_mac80211_sta_add, - .sta_remove = mwl_mac80211_sta_remove, - .conf_tx = mwl_mac80211_conf_tx, - .get_stats = mwl_mac80211_get_stats, - .get_survey = mwl_mac80211_get_survey, - .ampdu_action = mwl_mac80211_ampdu_action, -}; - -static irqreturn_t (*mwl_mac80211_isr)(int irq, void *dev_id); - static const struct ieee80211_rate mwl_rates_24[] = { { .bitrate = 10, .hw_value = 2, }, { .bitrate = 20, .hw_value = 4, }, @@ -144,53 +49,22 @@ static const struct ieee80211_rate mwl_rates_50[] = { { .bitrate = 540, .hw_value = 108, }, }; -/* PUBLIC FUNCTION DEFINITION -*/ - -struct ieee80211_ops *mwl_mac80211_get_ops(void) -{ - return &mwl_mac80211_ops; -} - -void mwl_mac80211_set_isr(irqreturn_t (*isr)(int irq, void *dev_id)) -{ - WLDBG_ENTER(DBG_LEVEL_5); - - mwl_mac80211_isr = isr; - - WLDBG_EXIT(DBG_LEVEL_5); -} - -/* PRIVATE FUNCTION DEFINITION -*/ - static void mwl_mac80211_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, - struct sk_buff *skb) + struct sk_buff *skb) { struct mwl_priv *priv; - int index; - - WLDBG_ENTER(DBG_LEVEL_5); - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!skb); if (!priv->radio_on) { - WLDBG_EXIT_INFO(DBG_LEVEL_5, - "dropped TX frame since radio disabled"); + wiphy_warn(hw->wiphy, + "dropped TX frame since radio disabled"); dev_kfree_skb_any(skb); return; } - index = skb_get_queue_mapping(skb); - - mwl_tx_xmit(hw, index, control->sta, skb); - - WLDBG_EXIT(DBG_LEVEL_5); + mwl_tx_xmit(hw, control, skb); } static int mwl_mac80211_start(struct ieee80211_hw *hw) @@ -198,55 +72,49 @@ static int mwl_mac80211_start(struct ieee80211_hw *hw) struct mwl_priv *priv; int rc; - WLDBG_ENTER(DBG_LEVEL_5); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - rc = request_irq(priv->pdev->irq, mwl_mac80211_isr, + rc = request_irq(priv->pdev->irq, mwl_isr, IRQF_SHARED, MWL_DRV_NAME, hw); if (rc) { priv->irq = -1; - WLDBG_ERROR(DBG_LEVEL_5, "fail to register IRQ handler"); + wiphy_err(hw->wiphy, "fail to register IRQ handler"); return rc; } priv->irq = priv->pdev->irq; - /* Enable TX reclaim and RX tasklets. - */ + /* Enable TX reclaim and RX tasklets. */ tasklet_enable(&priv->tx_task); tasklet_enable(&priv->rx_task); - /* Enable interrupts - */ + /* Enable interrupts */ mwl_fwcmd_int_enable(hw); rc = mwl_fwcmd_radio_enable(hw); + if (rc) + goto fwcmd_fail; + rc = mwl_fwcmd_set_rate_adapt_mode(hw, 0); + if (rc) + goto fwcmd_fail; + rc = mwl_fwcmd_set_wmm_mode(hw, true); + if (rc) + goto fwcmd_fail; + rc = mwl_fwcmd_set_dwds_stamode(hw, true); + if (rc) + goto fwcmd_fail; + rc = mwl_fwcmd_set_fw_flush_timer(hw, 0); + if (rc) + goto fwcmd_fail; - if (!rc) - rc = mwl_fwcmd_set_rate_adapt_mode(hw, 0); - - if (!rc) - rc = mwl_fwcmd_set_wmm_mode(hw, true); - - if (!rc) - rc = mwl_fwcmd_set_dwds_stamode(hw, true); - - if (!rc) - rc = mwl_fwcmd_set_fw_flush_timer(hw, 0); - - if (rc) { - mwl_fwcmd_int_disable(hw); - free_irq(priv->pdev->irq, hw); - priv->irq = -1; - tasklet_disable(&priv->tx_task); - tasklet_disable(&priv->rx_task); - } else { - ieee80211_wake_queues(hw); - } + ieee80211_wake_queues(hw); + return 0; - WLDBG_EXIT(DBG_LEVEL_5); +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); return rc; } @@ -255,18 +123,13 @@ static void mwl_mac80211_stop(struct ieee80211_hw *hw) { struct mwl_priv *priv; - WLDBG_ENTER(DBG_LEVEL_5); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); mwl_fwcmd_radio_disable(hw); ieee80211_stop_queues(hw); - /* Disable interrupts - */ + /* Disable interrupts */ mwl_fwcmd_int_disable(hw); if (priv->irq != -1) { @@ -276,16 +139,12 @@ static void mwl_mac80211_stop(struct ieee80211_hw *hw) cancel_work_sync(&priv->watchdog_ba_handle); - /* Disable TX reclaim and RX tasklets. - */ + /* Disable TX reclaim and RX tasklets. */ tasklet_disable(&priv->tx_task); tasklet_disable(&priv->rx_task); - /* Return all skbs to mac80211 - */ + /* Return all skbs to mac80211 */ mwl_tx_done((unsigned long)hw); - - WLDBG_EXIT(DBG_LEVEL_5); } static int mwl_mac80211_add_interface(struct ieee80211_hw *hw, @@ -295,8 +154,7 @@ static int mwl_mac80211_add_interface(struct ieee80211_hw *hw, struct mwl_vif *mwl_vif; u32 macids_supported; int macid; - - WLDBG_ENTER(DBG_LEVEL_5); + unsigned long flags; switch (vif->type) { case NL80211_IFTYPE_AP: @@ -312,13 +170,12 @@ static int mwl_mac80211_add_interface(struct ieee80211_hw *hw, macid = ffs(macids_supported & ~priv->macids_used); if (!macid--) { - WLDBG_EXIT_INFO(DBG_LEVEL_5, "no macid can be allocated"); + wiphy_warn(hw->wiphy, "no macid can be allocated"); return -EBUSY; } - /* Setup driver private area. - */ - mwl_vif = MWL_VIF(vif); + /* 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; @@ -344,20 +201,50 @@ static int mwl_mac80211_add_interface(struct ieee80211_hw *hw, } priv->macids_used |= 1 << mwl_vif->macid; + spin_lock_irqsave(&priv->vif_lock, flags); list_add_tail(&mwl_vif->list, &priv->vif_list); - - WLDBG_EXIT(DBG_LEVEL_5); + spin_unlock_irqrestore(&priv->vif_lock, flags); return 0; } +static void mwl_mac80211_remove_vif(struct mwl_priv *priv, struct mwl_vif *vif) +{ + unsigned long flags; + int num; + struct sk_buff *skb, *tmp; + struct ieee80211_tx_info *tx_info; + struct mwl_tx_ctrl *tx_ctrl; + + if (!priv->macids_used) + return; + + for (num = 1; num < SYSADPT_NUM_OF_DESC_DATA; num++) { + spin_lock_irqsave(&priv->txq[num].lock, flags); + skb_queue_walk_safe(&priv->txq[num], skb, tmp) { + tx_info = IEEE80211_SKB_CB(skb); + tx_ctrl = (struct mwl_tx_ctrl *)&tx_info->status; + if (tx_ctrl->vif == vif) { + __skb_unlink(skb, &priv->txq[num]); + dev_kfree_skb_any(skb); + } + } + spin_unlock_irqrestore(&priv->txq[num].lock, flags); + } + + priv->macids_used &= ~(1 << vif->macid); + spin_lock_irqsave(&priv->vif_lock, flags); + list_del(&vif->list); + spin_unlock_irqrestore(&priv->vif_lock, flags); +} + 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(vif); + struct mwl_vif *mwl_vif; - WLDBG_ENTER(DBG_LEVEL_5); + mwl_vif = mwl_dev_get_vif(vif); if (vif->type == NL80211_IFTYPE_STATION) mwl_fwcmd_remove_mac_addr(hw, vif, vif->addr); @@ -366,8 +253,6 @@ static void mwl_mac80211_remove_interface(struct ieee80211_hw *hw, mwl_fwcmd_set_new_stn_del(hw, vif, vif->addr); mwl_mac80211_remove_vif(priv, mwl_vif); - - WLDBG_EXIT(DBG_LEVEL_5); } static int mwl_mac80211_config(struct ieee80211_hw *hw, @@ -376,9 +261,7 @@ static int mwl_mac80211_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf = &hw->conf; int rc; - WLDBG_ENTER(DBG_LEVEL_5); - - WLDBG_INFO(DBG_LEVEL_5, "change: 0x%x", changed); + wiphy_debug(hw->wiphy, "change: 0x%x", changed); if (conf->flags & IEEE80211_CONF_IDLE) rc = mwl_fwcmd_radio_disable(hw); @@ -400,52 +283,103 @@ static int mwl_mac80211_config(struct ieee80211_hw *hw, } rc = mwl_fwcmd_set_rf_channel(hw, conf); - if (rc) goto out; - rc = mwl_fwcmd_use_fixed_rate(hw, rate, rate); - if (rc) goto out; - rc = mwl_fwcmd_max_tx_power(hw, conf, 0); - if (rc) goto out; - rc = mwl_fwcmd_tx_power(hw, conf, 0); - if (rc) goto out; - rc = mwl_fwcmd_set_cdd(hw); } out: - WLDBG_EXIT_INFO(DBG_LEVEL_5, "return code: %d", rc); - return rc; } +static void mwl_mac80211_bss_info_changed_sta(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + if (changed & BSS_CHANGED_ERP_PREAMBLE) + mwl_fwcmd_set_radio_preamble(hw, + vif->bss_conf.use_short_preamble); + + if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) + mwl_fwcmd_set_aid(hw, vif, (u8 *)vif->bss_conf.bssid, + vif->bss_conf.aid); +} + +static void mwl_mac80211_bss_info_changed_ap(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + if (changed & BSS_CHANGED_ERP_PREAMBLE) + mwl_fwcmd_set_radio_preamble(hw, + vif->bss_conf.use_short_preamble); + + if (changed & BSS_CHANGED_BASIC_RATES) { + int idx; + int rate; + + /* Use lowest supported basic rate for multicasts + * and management frames (such as probe responses -- + * beacons will always go out at 1 Mb/s). + */ + idx = ffs(vif->bss_conf.basic_rates); + if (idx) + idx--; + + if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) + rate = mwl_rates_24[idx].hw_value; + else + rate = mwl_rates_50[idx].hw_value; + + mwl_fwcmd_use_fixed_rate(hw, rate, rate); + } + + if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) { + struct sk_buff *skb; + + skb = ieee80211_beacon_get(hw, vif); + + if (skb) { + mwl_fwcmd_set_beacon(hw, vif, skb->data, skb->len); + dev_kfree_skb_any(skb); + } + + if ((info->ssid[0] != '\0') && + (info->ssid_len != 0) && + (!info->hidden_ssid)) + mwl_fwcmd_broadcast_ssid_enable(hw, vif, true); + else + mwl_fwcmd_broadcast_ssid_enable(hw, vif, false); + } + + if (changed & BSS_CHANGED_BEACON_ENABLED) + mwl_fwcmd_bss_start(hw, vif, info->enable_beacon); +} + static void mwl_mac80211_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u32 changed) { - WLDBG_ENTER(DBG_LEVEL_5); - - WLDBG_INFO(DBG_LEVEL_5, "interface: %d, change: 0x%x", - vif->type, changed); + wiphy_debug(hw->wiphy, "interface: %d, change: 0x%x", + vif->type, changed); if (vif->type == NL80211_IFTYPE_STATION) mwl_mac80211_bss_info_changed_sta(hw, vif, info, changed); if (vif->type == NL80211_IFTYPE_AP) mwl_mac80211_bss_info_changed_ap(hw, vif, info, changed); - - WLDBG_EXIT(DBG_LEVEL_5); } static void mwl_mac80211_configure_filter(struct ieee80211_hw *hw, @@ -453,14 +387,10 @@ static void mwl_mac80211_configure_filter(struct ieee80211_hw *hw, unsigned int *total_flags, u64 multicast) { - WLDBG_ENTER(DBG_LEVEL_5); - /* AP firmware doesn't allow fine-grained control over * the receive filter. */ *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC; - - WLDBG_EXIT(DBG_LEVEL_5); } static int mwl_mac80211_set_key(struct ieee80211_hw *hw, @@ -469,16 +399,12 @@ static int mwl_mac80211_set_key(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { + struct mwl_vif *mwl_vif; int rc = 0; u8 encr_type; u8 *addr; - struct mwl_vif *mwl_vif = MWL_VIF(vif); - struct mwl_sta *sta_info = MWL_STA(sta); - - WLDBG_ENTER(DBG_LEVEL_5); - BUG_ON(!mwl_vif); - BUG_ON(!sta_info); + mwl_vif = mwl_dev_get_vif(vif); if (!sta) { addr = vif->addr; @@ -511,59 +437,57 @@ static int mwl_mac80211_set_key(struct ieee80211_hw *hw, rc = mwl_fwcmd_update_encryption_enable(hw, vif, addr, encr_type); - if (rc) goto out; mwl_vif->is_hw_crypto_enabled = true; } else { rc = mwl_fwcmd_encryption_remove_key(hw, vif, addr, key); - if (rc) goto out; } out: - WLDBG_EXIT_INFO(DBG_LEVEL_5, "return code: %d", rc); - return rc; } static int mwl_mac80211_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { - int rc; - - WLDBG_ENTER(DBG_LEVEL_5); - - rc = mwl_fwcmd_set_rts_threshold(hw, value); - - WLDBG_EXIT_INFO(DBG_LEVEL_5, "return code: %d", rc); - - return rc; + return mwl_fwcmd_set_rts_threshold(hw, value); } static int mwl_mac80211_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mwl_vif *mwl_vif = MWL_VIF(vif); - struct mwl_sta *sta_info = MWL_STA(sta); + 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; - WLDBG_ENTER(DBG_LEVEL_5); - - BUG_ON(!mwl_vif); - BUG_ON(!sta_info); + mwl_vif = mwl_dev_get_vif(vif); + 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; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU) + sta_info->amsdu_ctrl.cap = MWL_AMSDU_SIZE_8K; + else + sta_info->amsdu_ctrl.cap = MWL_AMSDU_SIZE_4K; + } sta_info->iv16 = 1; sta_info->iv32 = 0; - if (sta->ht_cap.ht_supported) - sta_info->is_ampdu_allowed = true; + spin_lock_irqsave(&priv->sta_lock, flags); + list_add_tail(&sta_info->list, &priv->sta_list); + spin_unlock_irqrestore(&priv->sta_lock, flags); if (mwl_vif->is_sta) mwl_fwcmd_set_new_stn_del(hw, vif, sta->addr); @@ -571,14 +495,12 @@ static int mwl_mac80211_sta_add(struct ieee80211_hw *hw, rc = mwl_fwcmd_set_new_stn_add(hw, vif, sta); for (i = 0; i < NUM_WEP_KEYS; i++) { - key = IEEE80211_KEY_CONF(mwl_vif->wep_key_conf[i].key); + key = (struct ieee80211_key_conf *)mwl_vif->wep_key_conf[i].key; if (mwl_vif->wep_key_conf[i].enabled) mwl_mac80211_set_key(hw, SET_KEY, vif, sta, key); } - WLDBG_EXIT_INFO(DBG_LEVEL_5, "return code: %d", rc); - return rc; } @@ -586,13 +508,35 @@ static int mwl_mac80211_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { + 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; + struct mwl_tx_ctrl *tx_ctrl; int rc; - WLDBG_ENTER(DBG_LEVEL_5); + 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); + skb_queue_walk_safe(&priv->txq[num], skb, tmp) { + tx_info = IEEE80211_SKB_CB(skb); + tx_ctrl = (struct mwl_tx_ctrl *)&tx_info->status; + if (tx_ctrl->sta == sta) { + __skb_unlink(skb, &priv->txq[num]); + dev_kfree_skb_any(skb); + } + } + spin_unlock_irqrestore(&priv->txq[num].lock, flags); + } rc = mwl_fwcmd_set_new_stn_del(hw, vif, sta->addr); - WLDBG_EXIT_INFO(DBG_LEVEL_5, "return code: %d", rc); + spin_lock_irqsave(&priv->sta_lock, flags); + list_del(&sta_info->list); + spin_unlock_irqrestore(&priv->sta_lock, flags); return rc; } @@ -605,8 +549,6 @@ static int mwl_mac80211_conf_tx(struct ieee80211_hw *hw, struct mwl_priv *priv = hw->priv; int rc = 0; - WLDBG_ENTER(DBG_LEVEL_5); - BUG_ON(queue > SYSADPT_TX_WMM_QUEUES - 1); memcpy(&priv->wmm_params[queue], params, sizeof(*params)); @@ -621,26 +563,16 @@ static int mwl_mac80211_conf_tx(struct ieee80211_hw *hw, rc = mwl_fwcmd_set_edca_params(hw, q, params->cw_min, params->cw_max, - params->aifs, params->txop); + params->aifs, params->txop); } - WLDBG_EXIT_INFO(DBG_LEVEL_5, "return code: %d", rc); - return rc; } static int mwl_mac80211_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { - int rc; - - WLDBG_ENTER(DBG_LEVEL_5); - - rc = mwl_fwcmd_get_stat(hw, stats); - - WLDBG_EXIT_INFO(DBG_LEVEL_5, "return code: %d", rc); - - return rc; + return mwl_fwcmd_get_stat(hw, stats); } static int mwl_mac80211_get_survey(struct ieee80211_hw *hw, @@ -650,8 +582,6 @@ static int mwl_mac80211_get_survey(struct ieee80211_hw *hw, struct mwl_priv *priv = hw->priv; struct ieee80211_conf *conf = &hw->conf; - WLDBG_ENTER(DBG_LEVEL_5); - if (idx != 0) return -ENOENT; @@ -659,8 +589,6 @@ static int mwl_mac80211_get_survey(struct ieee80211_hw *hw, survey->filled = SURVEY_INFO_NOISE_DBM; survey->noise = priv->noise; - WLDBG_EXIT(DBG_LEVEL_5); - return 0; } @@ -674,16 +602,11 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, struct mwl_priv *priv = hw->priv; struct mwl_ampdu_stream *stream; u8 *addr = sta->addr, idx; - struct mwl_sta *sta_info = MWL_STA(sta); + struct mwl_sta *sta_info; - WLDBG_ENTER(DBG_LEVEL_5); + sta_info = mwl_dev_get_sta(sta); - if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) { - WLDBG_EXIT_INFO(DBG_LEVEL_5, "no HW AMPDU"); - return -ENOTSUPP; - } - - SPIN_LOCK(&priv->locks.stream_lock); + spin_lock(&priv->stream_lock); stream = mwl_fwcmd_lookup_stream(hw, addr, tid); @@ -713,26 +636,24 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, } if (!stream) { - WLDBG_EXIT_INFO(DBG_LEVEL_5, "no stream found"); + wiphy_warn(hw->wiphy, "no stream found"); rc = -EBUSY; break; } stream->state = AMPDU_STREAM_IN_PROGRESS; - /* Release the lock before we do the time consuming stuff - */ - SPIN_UNLOCK(&priv->locks.stream_lock); + /* Release the lock before we do the time consuming stuff */ + spin_unlock(&priv->stream_lock); for (i = 0; i < MAX_AMPDU_ATTEMPTS; i++) { - /* Check if link is still valid - */ + /* Check if link is still valid */ if (!sta_info->is_ampdu_allowed) { - SPIN_LOCK(&priv->locks.stream_lock); + spin_lock(&priv->stream_lock); mwl_fwcmd_remove_stream(hw, stream); - SPIN_UNLOCK(&priv->locks.stream_lock); - WLDBG_EXIT_INFO(DBG_LEVEL_5, - "link is no valid now"); + spin_unlock(&priv->stream_lock); + wiphy_warn(hw->wiphy, + "link is no valid now"); return -EBUSY; } @@ -741,14 +662,14 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, if (!rc) break; - WL_MSEC_SLEEP(1000); + mdelay(1000); } - SPIN_LOCK(&priv->locks.stream_lock); + spin_lock(&priv->stream_lock); if (rc) { mwl_fwcmd_remove_stream(hw, stream); - WLDBG_EXIT_INFO(DBG_LEVEL_5, "error code: %d", rc); + wiphy_err(hw->wiphy, "error code: %d", rc); rc = -EBUSY; break; } @@ -761,9 +682,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->locks.stream_lock); + spin_unlock(&priv->stream_lock); mwl_fwcmd_destroy_ba(hw, idx); - SPIN_LOCK(&priv->locks.stream_lock); + spin_lock(&priv->stream_lock); } mwl_fwcmd_remove_stream(hw, stream); @@ -772,19 +693,18 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); break; case IEEE80211_AMPDU_TX_OPERATIONAL: - BUG_ON(!stream); BUG_ON(stream->state != AMPDU_STREAM_IN_PROGRESS); - SPIN_UNLOCK(&priv->locks.stream_lock); + spin_unlock(&priv->stream_lock); rc = mwl_fwcmd_create_ba(hw, stream, buf_size, vif); - SPIN_LOCK(&priv->locks.stream_lock); + spin_lock(&priv->stream_lock); if (!rc) { stream->state = AMPDU_STREAM_ACTIVE; } else { idx = stream->idx; - SPIN_UNLOCK(&priv->locks.stream_lock); + spin_unlock(&priv->stream_lock); mwl_fwcmd_destroy_ba(hw, idx); - SPIN_LOCK(&priv->locks.stream_lock); + spin_lock(&priv->stream_lock); mwl_fwcmd_remove_stream(hw, stream); } break; @@ -792,86 +712,26 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, rc = -ENOTSUPP; } - SPIN_UNLOCK(&priv->locks.stream_lock); - - WLDBG_EXIT(DBG_LEVEL_5); + spin_unlock(&priv->stream_lock); return rc; } -static void mwl_mac80211_remove_vif(struct mwl_priv *priv, struct mwl_vif *vif) -{ - if (!priv->macids_used) - return; - - priv->macids_used &= ~(1 << vif->macid); - list_del(&vif->list); -} - -static void mwl_mac80211_bss_info_changed_sta(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - mwl_fwcmd_set_radio_preamble(hw, - vif->bss_conf.use_short_preamble); - } - - if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) { - mwl_fwcmd_set_aid(hw, vif, (u8 *)vif->bss_conf.bssid, - vif->bss_conf.aid); - } -} - -static void mwl_mac80211_bss_info_changed_ap(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - mwl_fwcmd_set_radio_preamble(hw, - vif->bss_conf.use_short_preamble); - } - - if (changed & BSS_CHANGED_BASIC_RATES) { - int idx; - int rate; - - /* Use lowest supported basic rate for multicasts - * and management frames (such as probe responses -- - * beacons will always go out at 1 Mb/s). - */ - idx = ffs(vif->bss_conf.basic_rates); - if (idx) - idx--; - - if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) - rate = mwl_rates_24[idx].hw_value; - else - rate = mwl_rates_50[idx].hw_value; - - mwl_fwcmd_use_fixed_rate(hw, rate, rate); - } - - if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) { - struct sk_buff *skb; - - skb = ieee80211_beacon_get(hw, vif); - - if (skb) { - mwl_fwcmd_set_beacon(hw, vif, skb->data, skb->len); - dev_kfree_skb_any(skb); - } - - if ((info->ssid[0] != '\0') && - (info->ssid_len != 0) && - (!info->hidden_ssid)) - mwl_fwcmd_broadcast_ssid_enable(hw, vif, true); - else - mwl_fwcmd_broadcast_ssid_enable(hw, vif, false); - } - - if (changed & BSS_CHANGED_BEACON_ENABLED) - mwl_fwcmd_bss_start(hw, vif, info->enable_beacon); -} +const struct ieee80211_ops mwl_mac80211_ops = { + .tx = mwl_mac80211_tx, + .start = mwl_mac80211_start, + .stop = mwl_mac80211_stop, + .add_interface = mwl_mac80211_add_interface, + .remove_interface = mwl_mac80211_remove_interface, + .config = mwl_mac80211_config, + .bss_info_changed = mwl_mac80211_bss_info_changed, + .configure_filter = mwl_mac80211_configure_filter, + .set_key = mwl_mac80211_set_key, + .set_rts_threshold = mwl_mac80211_set_rts_threshold, + .sta_add = mwl_mac80211_sta_add, + .sta_remove = mwl_mac80211_sta_remove, + .conf_tx = mwl_mac80211_conf_tx, + .get_stats = mwl_mac80211_get_stats, + .get_survey = mwl_mac80211_get_survey, + .ampdu_action = mwl_mac80211_ampdu_action, +}; diff --git a/mac80211.h b/mac80211.h new file mode 100644 index 0000000..b70598a --- /dev/null +++ b/mac80211.h @@ -0,0 +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. + */ + +/* Description: This file defines mac80211 related functions. + */ + +#ifndef _mwl_mac80211_h_ +#define _mwl_mac80211_h_ + +#include <net/mac80211.h> + +extern const struct ieee80211_ops mwl_mac80211_ops; + +#endif /* _mwl_mac80211_h_ */ @@ -1,84 +1,40 @@ /* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ + * 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 implements main functions of this module. -*/ + */ #include <linux/module.h> #include <linux/moduleparam.h> -#include "mwl_sysadpt.h" -#include "mwl_dev.h" -#include "mwl_debug.h" -#include "mwl_fwdl.h" -#include "mwl_fwcmd.h" -#include "mwl_tx.h" -#include "mwl_rx.h" -#include "mwl_mac80211.h" - -/* CONSTANTS AND MACROS -*/ +#include "sysadpt.h" +#include "dev.h" +#include "fwdl.h" +#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 88W8864 802.11ac Adapter" +#define MWL_DEV_NAME "Marvell 802.11ac Adapter" #define MWL_DRV_NAME KBUILD_MODNAME -#define MWL_DRV_VERSION "10.3.0.2--" +#define MWL_DRV_VERSION "10.3.0.3" #define FILE_PATH_LEN 64 #define CMD_BUF_SIZE 0x4000 -#define INVALID_WATCHDOG 0xAA - -/* PRIVATE FUNCTION DECLARATION -*/ - -static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id); -static void mwl_remove(struct pci_dev *pdev); -static int mwl_alloc_pci_resource(struct mwl_priv *priv); -static void mwl_free_pci_resource(struct mwl_priv *priv); -static int mwl_init_firmware(struct mwl_priv *priv, char *fw_image); -static void mwl_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request); -static int mwl_process_of_dts(struct mwl_priv *priv); -static void mwl_set_ht_caps(struct mwl_priv *priv, - struct ieee80211_supported_band *band); -static void mwl_set_vht_caps(struct mwl_priv *priv, - struct ieee80211_supported_band *band); -static void mwl_set_caps(struct mwl_priv *priv); -static int mwl_wl_init(struct mwl_priv *priv); -static void mwl_wl_deinit(struct mwl_priv *priv); -static void mwl_watchdog_ba_events(struct work_struct *work); -static irqreturn_t mwl_interrupt(int irq, void *dev_id); - -/* PRIVATE VARIABLES -*/ - static struct pci_device_id mwl_pci_id_tbl[] = { { PCI_VDEVICE(MARVELL, 0x2a55), .driver_data = MWL8864, }, { PCI_VDEVICE(MARVELL, 0x2b38), .driver_data = MWL8897, }, { }, }; -static struct pci_driver mwl_pci_driver = { - .name = MWL_DRV_NAME, - .id_table = mwl_pci_id_tbl, - .probe = mwl_probe, - .remove = mwl_remove -}; - static struct mwl_chip_info mwl_chip_tbl[] = { [MWL8864] = { .part_name = "88W8864", @@ -173,144 +129,6 @@ static const struct ieee80211_iface_combination ap_if_comb = { .num_different_channels = 1, }; -/* PRIVATE FUNCTION DEFINITION -*/ - -static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - static bool printed_version; - struct ieee80211_hw *hw; - struct mwl_priv *priv; - int rc = 0; - - WLDBG_ENTER(DBG_LEVEL_0); - - if (id->driver_data >= MWLUNKNOWN) - return -ENODEV; - - if (!printed_version) { - WLDBG_PRINT("<<%s version %s>>", MWL_DESC, MWL_DRV_VERSION); - printed_version = true; - } - - rc = pci_enable_device(pdev); - if (rc) { - WLDBG_PRINT("%s: cannot enable new PCI device", - MWL_DRV_NAME); - WLDBG_EXIT_INFO(DBG_LEVEL_0, "init error"); - return rc; - } - - rc = pci_set_dma_mask(pdev, 0xffffffff); - if (rc) { - WLDBG_PRINT("%s: 32-bit PCI DMA not supported", - MWL_DRV_NAME); - goto err_pci_disable_device; - } - - pci_set_master(pdev); - - hw = ieee80211_alloc_hw(sizeof(*priv), mwl_mac80211_get_ops()); - if (!hw) { - WLDBG_PRINT("%s: ieee80211 alloc failed", - MWL_DRV_NAME); - rc = -ENOMEM; - goto err_pci_disable_device; - } - - /* hook regulatory domain change notification - */ - hw->wiphy->reg_notifier = mwl_reg_notifier; - - /* set interrupt service routine to mac80211 module - */ - mwl_mac80211_set_isr(mwl_interrupt); - - SET_IEEE80211_DEV(hw, &pdev->dev); - pci_set_drvdata(pdev, hw); - - priv = hw->priv; - priv->hw = hw; - priv->pdev = pdev; - priv->chip_type = id->driver_data; - - rc = mwl_alloc_pci_resource(priv); - if (rc) - goto err_alloc_pci_resource; - - rc = mwl_init_firmware(priv, mwl_chip_tbl[priv->chip_type].fw_image); - if (rc) { - WLDBG_PRINT("%s: fail to initialize firmware", - MWL_DRV_NAME); - goto err_init_firmware; - } - - /* firmware is loaded to H/W, it can be released now - */ - release_firmware(priv->fw_ucode); - - rc = mwl_process_of_dts(priv); - if (rc) { - WLDBG_PRINT("%s: fail to load dts mwlwifi parameters", - MWL_DRV_NAME); - goto err_process_of_dts; - } - - rc = mwl_wl_init(priv); - if (rc) { - WLDBG_PRINT("%s: fail to initialize wireless lan", - MWL_DRV_NAME); - goto err_wl_init; - } - - WLDBG_EXIT(DBG_LEVEL_0); - - return rc; - -err_wl_init: -err_process_of_dts: -err_init_firmware: - - mwl_fwcmd_reset(hw); - -err_alloc_pci_resource: - - pci_set_drvdata(pdev, NULL); - ieee80211_free_hw(hw); - -err_pci_disable_device: - - pci_disable_device(pdev); - - WLDBG_EXIT_INFO(DBG_LEVEL_0, "init error"); - - return rc; -} - -static void mwl_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct mwl_priv *priv; - - WLDBG_ENTER(DBG_LEVEL_0); - - if (!hw) { - WLDBG_EXIT_INFO(DBG_LEVEL_0, "ieee80211 hw is null"); - return; - } - - priv = hw->priv; - BUG_ON(!priv); - - mwl_wl_deinit(priv); - mwl_free_pci_resource(priv); - pci_set_drvdata(pdev, NULL); - ieee80211_free_hw(hw); - pci_disable_device(pdev); - - WLDBG_EXIT(DBG_LEVEL_0); -} - static int mwl_alloc_pci_resource(struct mwl_priv *priv) { struct pci_dev *pdev; @@ -319,11 +137,7 @@ static int mwl_alloc_pci_resource(struct mwl_priv *priv) void *phys_addr1[2]; void *phys_addr2[2]; - WLDBG_ENTER(DBG_LEVEL_0); - - BUG_ON(!priv); pdev = priv->pdev; - BUG_ON(!pdev); phys_addr = pci_resource_start(pdev, 0); flags = pci_resource_flags(pdev, 0); @@ -335,9 +149,9 @@ static int mwl_alloc_pci_resource(struct mwl_priv *priv) if (!request_mem_region(phys_addr, pci_resource_len(pdev, 0), MWL_DRV_NAME)) { - WLDBG_ERROR(DBG_LEVEL_0, - "%s: cannot reserve PCI memory region 0", - MWL_DRV_NAME); + wiphy_err(priv->hw->wiphy, + "%s: cannot reserve PCI memory region 0", + MWL_DRV_NAME); goto err_reserve_mem_region_bar0; } @@ -346,21 +160,23 @@ static int mwl_alloc_pci_resource(struct mwl_priv *priv) priv->iobase0 = phys_addr1[0]; if (!priv->iobase0) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: cannot remap PCI memory region 0", - MWL_DRV_NAME); + wiphy_err(priv->hw->wiphy, + "%s: cannot remap PCI memory region 0", + MWL_DRV_NAME); goto err_release_mem_region_bar0; } - WLDBG_PRINT("priv->iobase0 = %x", (unsigned int)priv->iobase0); + wiphy_info(priv->hw->wiphy, "priv->iobase0 = %x", + (unsigned int)priv->iobase0); phys_addr = pci_resource_start(pdev, priv->next_bar_num); if (!request_mem_region(phys_addr, pci_resource_len(pdev, priv->next_bar_num), MWL_DRV_NAME)) { - WLDBG_ERROR(DBG_LEVEL_0, - "%s: cannot reserve PCI memory region 1", - MWL_DRV_NAME); + wiphy_err(priv->hw->wiphy, + "%s: cannot reserve PCI memory region 1", + MWL_DRV_NAME); goto err_iounmap_iobase0; } @@ -370,12 +186,14 @@ static int mwl_alloc_pci_resource(struct mwl_priv *priv) priv->iobase1 = phys_addr2[0]; if (!priv->iobase1) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: cannot remap PCI memory region 1", - MWL_DRV_NAME); + wiphy_err(priv->hw->wiphy, + "%s: cannot remap PCI memory region 1", + MWL_DRV_NAME); goto err_release_mem_region_bar1; } - WLDBG_PRINT("priv->iobase1 = %x", (unsigned int)priv->iobase1); + wiphy_info(priv->hw->wiphy, "priv->iobase1 = %x", + (unsigned int)priv->iobase1); priv->pcmd_buf = (unsigned short *)dma_alloc_coherent(&priv->pdev->dev, @@ -384,20 +202,19 @@ static int mwl_alloc_pci_resource(struct mwl_priv *priv) GFP_KERNEL); if (!priv->pcmd_buf) { - WLDBG_ERROR(DBG_LEVEL_0, - "%s: cannot alloc memory for command buffer", - MWL_DRV_NAME); + wiphy_err(priv->hw->wiphy, + "%s: cannot alloc memory for command buffer", + MWL_DRV_NAME); goto err_iounmap_iobase1; } - WLDBG_PRINT("priv->pcmd_buf = %x priv->pphys_cmd_buf = %x", - (unsigned int)priv->pcmd_buf, - (unsigned int)priv->pphys_cmd_buf); + 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); memset(priv->pcmd_buf, 0x00, CMD_BUF_SIZE); - WLDBG_EXIT(DBG_LEVEL_0); - return 0; err_iounmap_iobase1: @@ -420,7 +237,7 @@ err_release_mem_region_bar0: err_reserve_mem_region_bar0: - WLDBG_EXIT_INFO(DBG_LEVEL_0, "pci alloc fail"); + wiphy_err(priv->hw->wiphy, "pci alloc fail"); return -EIO; } @@ -429,11 +246,7 @@ static void mwl_free_pci_resource(struct mwl_priv *priv) { struct pci_dev *pdev; - WLDBG_ENTER(DBG_LEVEL_0); - - BUG_ON(!priv); pdev = priv->pdev; - BUG_ON(!pdev); iounmap(priv->iobase0); iounmap(priv->iobase1); @@ -443,8 +256,6 @@ static void mwl_free_pci_resource(struct mwl_priv *priv) pci_resource_len(pdev, 0)); dma_free_coherent(&priv->pdev->dev, CMD_BUF_SIZE, priv->pcmd_buf, priv->pphys_cmd_buf); - - WLDBG_EXIT(DBG_LEVEL_0); } static int mwl_init_firmware(struct mwl_priv *priv, char *fw_name) @@ -452,29 +263,24 @@ static int mwl_init_firmware(struct mwl_priv *priv, char *fw_name) struct pci_dev *pdev; int rc = 0; - WLDBG_ENTER(DBG_LEVEL_0); - - BUG_ON(!priv); pdev = priv->pdev; - BUG_ON(!pdev); rc = request_firmware(&priv->fw_ucode, fw_name, &priv->pdev->dev); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: cannot load firmware image <%s>", - MWL_DRV_NAME, fw_name); + wiphy_err(priv->hw->wiphy, + "%s: cannot load firmware image <%s>", + MWL_DRV_NAME, fw_name); goto err_load_fw; } rc = mwl_fwdl_download_firmware(priv->hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, - "%s: cannot download firmware image <%s>", - MWL_DRV_NAME, fw_name); + wiphy_err(priv->hw->wiphy, + "%s: cannot download firmware image <%s>", + MWL_DRV_NAME, fw_name); goto err_download_fw; } - WLDBG_EXIT(DBG_LEVEL_0); - return rc; err_download_fw: @@ -483,7 +289,7 @@ err_download_fw: err_load_fw: - WLDBG_EXIT_INFO(DBG_LEVEL_0, "firmware init fail"); + wiphy_err(priv->hw->wiphy, "firmware init fail"); return rc; } @@ -500,13 +306,8 @@ static void mwl_reg_notifier(struct wiphy *wiphy, u32 prop_value; int i, j, k; - WLDBG_ENTER(DBG_LEVEL_0); - - BUG_ON(!wiphy); hw = (struct ieee80211_hw *)wiphy_priv(wiphy); - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); if (priv->pwr_node) { for_each_property_of_node(priv->pwr_node, prop) { @@ -531,49 +332,50 @@ static void mwl_reg_notifier(struct wiphy *wiphy, } if (prop) { - /* Reset the whole table - */ + /* Reset the whole table */ for (i = 0; i < SYSADPT_MAX_NUM_CHANNELS; i++) memset(&priv->tx_pwr_tbl[i], 0, sizeof(struct mwl_tx_pwr_tbl)); - /* Load related power table - */ + /* Load related power table */ i = 0; j = 0; while (i < prop->length) { prop_value = - be32_to_cpu(*(u32 *)(prop->value + i)); + be32_to_cpu(*(__be32 *) + (prop->value + i)); priv->tx_pwr_tbl[j].channel = prop_value; i += 4; prop_value = - be32_to_cpu(*(u32 *)(prop->value + i)); + be32_to_cpu(*(__be32 *) + (prop->value + i)); priv->tx_pwr_tbl[j].setcap = prop_value; i += 4; for (k = 0; k < SYSADPT_TX_POWER_LEVEL_TOTAL; k++) { prop_value = - be32_to_cpu(*(u32 *) + be32_to_cpu(*(__be32 *) (prop->value + i)); priv->tx_pwr_tbl[j].tx_power[k] = prop_value; i += 4; } prop_value = - be32_to_cpu(*(u32 *)(prop->value + i)); + be32_to_cpu(*(__be32 *) + (prop->value + i)); priv->tx_pwr_tbl[j].cdd = prop_value; i += 4; prop_value = - be32_to_cpu(*(u32 *)(prop->value + i)); + be32_to_cpu(*(__be32 *) + (prop->value + i)); priv->tx_pwr_tbl[j].txantenna2 = prop_value; i += 4; j++; } - /* Dump loaded power tabel - */ - WLDBG_PRINT("%s: %s\n", dev_name(&wiphy->dev), - prop->name); + /* Dump loaded power tabel */ + wiphy_info(hw->wiphy, "%s: %s\n", dev_name(&wiphy->dev), + prop->name); for (i = 0; i < SYSADPT_MAX_NUM_CHANNELS; i++) { struct mwl_tx_pwr_tbl *pwr_tbl; char disp_buf[64]; @@ -582,11 +384,12 @@ static void mwl_reg_notifier(struct wiphy *wiphy, pwr_tbl = &priv->tx_pwr_tbl[i]; if (pwr_tbl->channel == 0) break; - WLDBG_PRINT("Channel: %d: 0x%x 0x%x 0x%x", - pwr_tbl->channel, - pwr_tbl->setcap, - pwr_tbl->cdd, - pwr_tbl->txantenna2); + wiphy_info(hw->wiphy, + "Channel: %d: 0x%x 0x%x 0x%x", + pwr_tbl->channel, + pwr_tbl->setcap, + pwr_tbl->cdd, + pwr_tbl->txantenna2); disp_ptr = disp_buf; for (j = 0; j < SYSADPT_TX_POWER_LEVEL_TOTAL; j++) { @@ -594,12 +397,10 @@ static void mwl_reg_notifier(struct wiphy *wiphy, sprintf(disp_ptr, "%x ", pwr_tbl->tx_power[j]); } - WLDBG_PRINT("%s", disp_buf); + wiphy_info(hw->wiphy, "%s", disp_buf); } } } - - WLDBG_EXIT(DBG_LEVEL_0); } static int mwl_process_of_dts(struct mwl_priv *priv) @@ -607,10 +408,6 @@ static int mwl_process_of_dts(struct mwl_priv *priv) struct property *prop; u32 prop_value; - WLDBG_ENTER(DBG_LEVEL_0); - - BUG_ON(!priv); - priv->disable_2g = false; priv->disable_5g = false; priv->antenna_tx = ANTENNA_TX_4_AUTO; @@ -622,19 +419,19 @@ static int mwl_process_of_dts(struct mwl_priv *priv) if (!priv->dt_node) return -EPERM; - /* look for all matching property names - */ + /* look for all matching property names */ for_each_property_of_node(priv->dt_node, prop) { if (strcmp(prop->name, "marvell,2ghz") == 0) priv->disable_2g = true; if (strcmp(prop->name, "marvell,5ghz") == 0) priv->disable_5g = true; if (strcmp(prop->name, "marvell,chainmask") == 0) { - prop_value = be32_to_cpu(*((u32 *)prop->value)); + prop_value = be32_to_cpu(*((__be32 *)prop->value)); if (prop_value == 2) priv->antenna_tx = ANTENNA_TX_2; - prop_value = be32_to_cpu(*((u32 *)(prop->value + 4))); + prop_value = be32_to_cpu(*((__be32 *) + (prop->value + 4))); if (prop_value == 2) priv->antenna_rx = ANTENNA_RX_2; } @@ -643,23 +440,23 @@ static int mwl_process_of_dts(struct mwl_priv *priv) priv->pwr_node = of_find_node_by_name(priv->dt_node, "marvell,powertable"); - WLDBG_PRINT("2G: %s\n", priv->disable_2g ? "disable" : "enable"); - WLDBG_PRINT("5G: %s\n", priv->disable_5g ? "disable" : "enable"); + 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) - WLDBG_PRINT("TX: 4 antennas\n"); + wiphy_info(priv->hw->wiphy, "TX: 4 antennas\n"); else if (priv->antenna_tx == ANTENNA_TX_2) - WLDBG_PRINT("TX: 2 antennas\n"); + wiphy_info(priv->hw->wiphy, "TX: 2 antennas\n"); else - WLDBG_PRINT("TX: unknown\n"); + wiphy_info(priv->hw->wiphy, "TX: unknown\n"); if (priv->antenna_rx == ANTENNA_RX_4_AUTO) - WLDBG_PRINT("RX: 4 antennas\n"); + wiphy_info(priv->hw->wiphy, "RX: 4 antennas\n"); else if (priv->antenna_rx == ANTENNA_RX_2) - WLDBG_PRINT("RX: 2 antennas\n"); + wiphy_info(priv->hw->wiphy, "RX: 2 antennas\n"); else - WLDBG_PRINT("RX: unknown\n"); - - WLDBG_EXIT(DBG_LEVEL_0); + wiphy_info(priv->hw->wiphy, "RX: unknown\n"); return 0; } @@ -669,11 +466,7 @@ static void mwl_set_ht_caps(struct mwl_priv *priv, { struct ieee80211_hw *hw; - WLDBG_ENTER(DBG_LEVEL_0); - - BUG_ON(!priv); hw = priv->hw; - BUG_ON(!hw); band->ht_cap.ht_supported = 1; @@ -694,54 +487,41 @@ static void mwl_set_ht_caps(struct mwl_priv *priv, band->ht_cap.mcs.rx_mask[4] = 0x01; band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - - WLDBG_EXIT(DBG_LEVEL_0); } static void mwl_set_vht_caps(struct mwl_priv *priv, struct ieee80211_supported_band *band) { - WLDBG_ENTER(DBG_LEVEL_0); - band->vht_cap.vht_supported = 1; - band->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; + band->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; band->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC; band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; band->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1; band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; - band->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; - band->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; band->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; band->vht_cap.cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN; band->vht_cap.cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; if (priv->antenna_rx == ANTENNA_RX_2) - band->vht_cap.vht_mcs.rx_mcs_map = 0xfffa; + band->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0xfffa); else - band->vht_cap.vht_mcs.rx_mcs_map = 0xffea; + band->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0xffea); if (priv->antenna_tx == ANTENNA_TX_2) - band->vht_cap.vht_mcs.tx_mcs_map = 0xfffa; + band->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0xfffa); else - band->vht_cap.vht_mcs.tx_mcs_map = 0xffea; - - WLDBG_EXIT(DBG_LEVEL_0); + band->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0xffea); } static void mwl_set_caps(struct mwl_priv *priv) { struct ieee80211_hw *hw; - WLDBG_ENTER(DBG_LEVEL_0); - - BUG_ON(!priv); hw = priv->hw; - BUG_ON(!hw); - /* set up band information for 2.4G - */ + /* set up band information for 2.4G */ if (!priv->disable_2g) { BUILD_BUG_ON(sizeof(priv->channels_24) != sizeof(mwl_channels_24)); @@ -763,8 +543,7 @@ static void mwl_set_caps(struct mwl_priv *priv) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24; } - /* set up band information for 5G - */ + /* set up band information for 5G */ if (!priv->disable_5g) { BUILD_BUG_ON(sizeof(priv->channels_50) != sizeof(mwl_channels_50)); @@ -785,8 +564,6 @@ static void mwl_set_caps(struct mwl_priv *priv) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->band_50; } - - WLDBG_EXIT(DBG_LEVEL_0); } static int mwl_wl_init(struct mwl_priv *priv) @@ -795,21 +572,12 @@ static int mwl_wl_init(struct mwl_priv *priv) int rc; int i; - WLDBG_ENTER(DBG_LEVEL_0); - - BUG_ON(!priv); hw = priv->hw; - BUG_ON(!hw); - /* Extra headroom is the size of the required DMA header - * minus the size of the smallest 802.11 frame (CTS frame). - */ - hw->extra_tx_headroom = - sizeof(struct mwl_dma_data) - sizeof(struct ieee80211_cts); + hw->extra_tx_headroom = SYSADPT_MIN_BYTES_HEADROOM; hw->queues = SYSADPT_TX_WMM_QUEUES; - /* Set rssi values to dBm - */ + /* Set rssi values to dBm */ hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL; /* Ask mac80211 to not to trigger PS mode @@ -824,17 +592,16 @@ static int mwl_wl_init(struct mwl_priv *priv) priv->sta_macids_supported = 0x00010000; priv->macids_used = 0; INIT_LIST_HEAD(&priv->vif_list); + INIT_LIST_HEAD(&priv->sta_list); - /* Set default radio state, preamble and wmm - */ + /* Set default radio state, preamble and wmm */ priv->radio_on = false; priv->radio_short_preamble = false; priv->wmm_enabled = false; priv->powinited = 0; - /* Handle watchdog ba events - */ + /* Handle watchdog ba events */ INIT_WORK(&priv->watchdog_ba_handle, mwl_watchdog_ba_events); tasklet_init(&priv->tx_task, (void *)mwl_tx_done, (unsigned long)hw); @@ -846,28 +613,30 @@ static int mwl_wl_init(struct mwl_priv *priv) priv->recv_limit = SYSADPT_RECEIVE_LIMIT; priv->is_rx_schedule = false; - SPIN_LOCK_INIT(&priv->locks.xmit_lock); - SPIN_LOCK_INIT(&priv->locks.fwcmd_lock); - SPIN_LOCK_INIT(&priv->locks.stream_lock); + spin_lock_init(&priv->tx_desc_lock); + spin_lock_init(&priv->fwcmd_lock); + spin_lock_init(&priv->vif_lock); + spin_lock_init(&priv->sta_lock); + spin_lock_init(&priv->stream_lock); rc = mwl_tx_init(hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to initialize TX", - MWL_DRV_NAME); + wiphy_err(hw->wiphy, "%s: fail to initialize TX", + MWL_DRV_NAME); goto err_mwl_tx_init; } rc = mwl_rx_init(hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to initialize RX", - MWL_DRV_NAME); + wiphy_err(hw->wiphy, "%s: fail to initialize RX", + MWL_DRV_NAME); goto err_mwl_rx_init; } rc = mwl_fwcmd_get_hw_specs(hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to get HW specifications", - MWL_DRV_NAME); + wiphy_err(hw->wiphy, "%s: fail to get HW specifications", + MWL_DRV_NAME); goto err_get_hw_specs; } @@ -887,12 +656,13 @@ static int mwl_wl_init(struct mwl_priv *priv) rc = mwl_fwcmd_set_hw_specs(hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to set HW specifications", - MWL_DRV_NAME); + wiphy_err(hw->wiphy, "%s: fail to set HW specifications", + MWL_DRV_NAME); goto err_set_hw_specs; } - WLDBG_PRINT("firmware version: 0x%x", priv->hw_data.fw_release_num); + wiphy_info(hw->wiphy, + "firmware version: 0x%x", priv->hw_data.fw_release_num); mwl_fwcmd_radio_disable(hw); @@ -910,13 +680,11 @@ static int mwl_wl_init(struct mwl_priv *priv) rc = ieee80211_register_hw(hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to register device", - MWL_DRV_NAME); + wiphy_err(hw->wiphy, "%s: fail to register device", + MWL_DRV_NAME); goto err_register_hw; } - WLDBG_EXIT(DBG_LEVEL_0); - return rc; err_register_hw: @@ -931,7 +699,7 @@ err_mwl_rx_init: err_mwl_tx_init: - WLDBG_EXIT_INFO(DBG_LEVEL_0, "init fail"); + wiphy_err(hw->wiphy, "init fail"); return rc; } @@ -940,11 +708,7 @@ static void mwl_wl_deinit(struct mwl_priv *priv) { struct ieee80211_hw *hw; - WLDBG_ENTER(DBG_LEVEL_0); - - BUG_ON(!priv); hw = priv->hw; - BUG_ON(!hw); ieee80211_unregister_hw(hw); mwl_rx_deinit(hw); @@ -952,144 +716,136 @@ static void mwl_wl_deinit(struct mwl_priv *priv) tasklet_kill(&priv->rx_task); tasklet_kill(&priv->tx_task); mwl_fwcmd_reset(hw); - - WLDBG_EXIT(DBG_LEVEL_0); } -static void mwl_watchdog_ba_events(struct work_struct *work) +static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int rc; - u8 bitmap = 0, stream_index; - struct mwl_ampdu_stream *streams; - struct mwl_priv *priv = - container_of(work, struct mwl_priv, watchdog_ba_handle); - struct ieee80211_hw *hw = priv->hw; - u32 status; + static bool printed_version; + struct ieee80211_hw *hw; + struct mwl_priv *priv; + int rc = 0; + + if (id->driver_data >= MWLUNKNOWN) + return -ENODEV; - rc = mwl_fwcmd_get_watchdog_bitmap(priv->hw, &bitmap); + if (!printed_version) { + pr_info("<<%s version %s>>", + MWL_DESC, MWL_DRV_VERSION); + printed_version = true; + } - if (rc) - goto done; - - SPIN_LOCK(&priv->locks.stream_lock); - - /* the bitmap is the hw queue number. Map it to the ampdu queue. - */ - if (bitmap != INVALID_WATCHDOG) { - if (bitmap == SYSADPT_TX_AMPDU_QUEUES) - stream_index = 0; - else if (bitmap > SYSADPT_TX_AMPDU_QUEUES) - stream_index = bitmap - SYSADPT_TX_AMPDU_QUEUES; - else - stream_index = bitmap + 3; /** queue 0 is stream 3*/ - - if (bitmap != 0xFF) { - /* Check if the stream is in use before disabling it - */ - streams = &priv->ampdu[stream_index]; - - if (streams->state == AMPDU_STREAM_ACTIVE) { - ieee80211_stop_tx_ba_session(streams->sta, - streams->tid); - SPIN_UNLOCK(&priv->locks.stream_lock); - mwl_fwcmd_destroy_ba(hw, stream_index); - SPIN_LOCK(&priv->locks.stream_lock); - } - } else { - for (stream_index = 0; - stream_index < SYSADPT_TX_AMPDU_QUEUES; - stream_index++) { - streams = &priv->ampdu[stream_index]; - - if (streams->state != AMPDU_STREAM_ACTIVE) - continue; - - ieee80211_stop_tx_ba_session(streams->sta, - streams->tid); - SPIN_UNLOCK(&priv->locks.stream_lock); - mwl_fwcmd_destroy_ba(hw, stream_index); - SPIN_LOCK(&priv->locks.stream_lock); - } - } + rc = pci_enable_device(pdev); + if (rc) { + pr_err("%s: cannot enable new PCI device", + MWL_DRV_NAME); + return rc; + } + + rc = pci_set_dma_mask(pdev, 0xffffffff); + if (rc) { + pr_err("%s: 32-bit PCI DMA not supported", + MWL_DRV_NAME); + goto err_pci_disable_device; } - SPIN_UNLOCK(&priv->locks.stream_lock); + pci_set_master(pdev); -done: + hw = ieee80211_alloc_hw(sizeof(*priv), &mwl_mac80211_ops); + if (!hw) { + pr_err("%s: ieee80211 alloc failed", + MWL_DRV_NAME); + rc = -ENOMEM; + goto err_pci_disable_device; + } - status = readl(priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); - writel(status | MACREG_A2HRIC_BA_WATCHDOG, - priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); -} + /* hook regulatory domain change notification */ + hw->wiphy->reg_notifier = mwl_reg_notifier; -static irqreturn_t mwl_interrupt(int irq, void *dev_id) -{ - struct ieee80211_hw *hw = dev_id; - struct mwl_priv *priv; - void *int_status_mask; - unsigned int int_status, clr_status; - u32 status; + SET_IEEE80211_DEV(hw, &pdev->dev); + pci_set_drvdata(pdev, hw); - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); + priv->hw = hw; + priv->pdev = pdev; + priv->chip_type = id->driver_data; - int_status_mask = priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK; + rc = mwl_alloc_pci_resource(priv); + if (rc) + goto err_alloc_pci_resource; - int_status = readl(priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CAUSE); + rc = mwl_init_firmware(priv, mwl_chip_tbl[priv->chip_type].fw_image); + if (rc) { + wiphy_err(hw->wiphy, "%s: fail to initialize firmware", + MWL_DRV_NAME); + goto err_init_firmware; + } - if (int_status == 0x00000000) - return IRQ_NONE; + /* firmware is loaded to H/W, it can be released now */ + release_firmware(priv->fw_ucode); - if (int_status == 0xffffffff) { - WLDBG_INFO(DBG_LEVEL_0, "card plugged out???"); - } else { - clr_status = int_status; + 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; + } - if (int_status & MACREG_A2HRIC_BIT_TX_DONE) { - int_status &= ~MACREG_A2HRIC_BIT_TX_DONE; + rc = mwl_wl_init(priv); + if (rc) { + wiphy_err(hw->wiphy, "%s: fail to initialize wireless lan", + MWL_DRV_NAME); + goto err_wl_init; + } - if (!priv->is_tx_schedule) { - status = readl(int_status_mask); - writel((status & ~MACREG_A2HRIC_BIT_TX_DONE), - int_status_mask); - tasklet_schedule(&priv->tx_task); - priv->is_tx_schedule = true; - } - } + return rc; - if (int_status & MACREG_A2HRIC_BIT_RX_RDY) { - int_status &= ~MACREG_A2HRIC_BIT_RX_RDY; +err_wl_init: +err_process_of_dts: +err_init_firmware: - if (!priv->is_rx_schedule) { - status = readl(int_status_mask); - writel((status & ~MACREG_A2HRIC_BIT_RX_RDY), - int_status_mask); - tasklet_schedule(&priv->rx_task); - priv->is_rx_schedule = true; - } - } + mwl_fwcmd_reset(hw); - if (int_status & MACREG_A2HRIC_BA_WATCHDOG) { - status = readl(int_status_mask); - writel((status & ~MACREG_A2HRIC_BA_WATCHDOG), - int_status_mask); - int_status &= ~MACREG_A2HRIC_BA_WATCHDOG; - ieee80211_queue_work(hw, &priv->watchdog_ba_handle); - } +err_alloc_pci_resource: - writel(~clr_status, - priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CAUSE); - } + pci_set_drvdata(pdev, NULL); + ieee80211_free_hw(hw); + +err_pci_disable_device: + + pci_disable_device(pdev); + + return rc; +} + +static void mwl_remove(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct mwl_priv *priv; + + if (!hw) + return; + + priv = hw->priv; - return IRQ_HANDLED; + mwl_wl_deinit(priv); + mwl_free_pci_resource(priv); + pci_set_drvdata(pdev, NULL); + ieee80211_free_hw(hw); + pci_disable_device(pdev); } +static struct pci_driver mwl_pci_driver = { + .name = MWL_DRV_NAME, + .id_table = mwl_pci_id_tbl, + .probe = mwl_probe, + .remove = mwl_remove +}; + module_pci_driver(mwl_pci_driver); MODULE_DESCRIPTION(MWL_DESC); MODULE_VERSION(MWL_DRV_VERSION); MODULE_AUTHOR("Marvell Semiconductor, Inc."); -MODULE_LICENSE("Dual BSD/GPL"); +MODULE_LICENSE("GPL v2"); MODULE_SUPPORTED_DEVICE(MWL_DEV_NAME); MODULE_DEVICE_TABLE(pci, mwl_pci_id_tbl); diff --git a/mwl_debug.c b/mwl_debug.c deleted file mode 100644 index 1ac270c..0000000 --- a/mwl_debug.c +++ /dev/null @@ -1,207 +0,0 @@ -/* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/* Description: This file implements debug related functions. -*/ - -#include <linux/printk.h> -#include <linux/slab.h> -#include <linux/string.h> - -#include "mwl_debug.h" - -/* CONSTANTS AND MACROS -*/ - -#define WLDBG_CLASSES ( \ - DBG_CLASS_PANIC | \ - DBG_CLASS_ERROR | \ - DBG_CLASS_WARNING | \ - DBG_CLASS_INFO | \ - DBG_CLASS_DATA | \ - DBG_CLASS_ENTER | \ - DBG_CLASS_EXIT) - -#define PRT_8BYTES "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n" - -/* PRIVATE VARIABLES -*/ - -static u32 dbg_levels; - -/* PUBLIC FUNCTION DEFINITION -*/ - -void mwl_debug_prt(u32 classlevel, const char *func, const char *format, ...) -{ - unsigned char *debug_string; - u32 level = classlevel & 0x0000ffff; - u32 class = classlevel & 0xffff0000; - va_list a_start; - - if (classlevel != 0) { - if ((class & WLDBG_CLASSES) != class) - return; - - if ((level & dbg_levels) != level) { - if (class != DBG_CLASS_PANIC && - class != DBG_CLASS_ERROR) - return; - } - } - - debug_string = kmalloc(1024, GFP_ATOMIC); - - if (!debug_string) - return; - - if (format) { - va_start(a_start, format); - vsprintf(debug_string, format, a_start); - va_end(a_start); - } else { - debug_string[0] = '\0'; - } - - switch (class) { - case DBG_CLASS_ENTER: - pr_debug("Enter %s() ...\n", func); - break; - case DBG_CLASS_EXIT: - pr_debug("... Exit %s()\n", func); - break; - case DBG_CLASS_WARNING: - pr_debug("WARNING: "); - break; - case DBG_CLASS_ERROR: - pr_debug("ERROR: "); - break; - case DBG_CLASS_PANIC: - pr_debug("PANIC: "); - break; - default: - break; - } - - if (strlen(debug_string) > 0) { - if (debug_string[strlen(debug_string) - 1] == '\n') - debug_string[strlen(debug_string) - 1] = '\0'; - pr_debug("%s(): %s\n", func, debug_string); - } - - kfree(debug_string); -} - -void mwl_debug_prtdata(u32 classlevel, const char *func, - const void *data, int len, const char *format, ...) -{ - unsigned char *dbg_string; - unsigned char dbg_data[16] = ""; - unsigned char *memptr = (unsigned char *)data; - u32 level = classlevel & 0x0000ffff; - u32 class = classlevel & 0xffff0000; - int curr_byte = 0; - int num_bytes = 0; - int offset = 0; - va_list a_start; - - if ((class & WLDBG_CLASSES) != class) - return; - - if ((level & dbg_levels) != level) - return; - - dbg_string = kmalloc(len + 1024, GFP_ATOMIC); - - if (!dbg_string) - return; - - if (format) { - va_start(a_start, format); - vsprintf(dbg_string, format, a_start); - va_end(a_start); - } else { - dbg_string[0] = '\0'; - } - - if (strlen(dbg_string) > 0) { - if (dbg_string[strlen(dbg_string) - 1] == '\n') - dbg_string[strlen(dbg_string) - 1] = '\0'; - pr_debug("%s() %s\n", func, dbg_string); - } else { - pr_debug("%s()\n", func); - } - - for (curr_byte = 0; curr_byte < len; curr_byte = curr_byte + 8) { - if ((curr_byte + 8) < len) { - pr_debug(PRT_8BYTES, - *(memptr + curr_byte + 0), - *(memptr + curr_byte + 1), - *(memptr + curr_byte + 2), - *(memptr + curr_byte + 3), - *(memptr + curr_byte + 4), - *(memptr + curr_byte + 5), - *(memptr + curr_byte + 6), - *(memptr + curr_byte + 7)); - } else { - num_bytes = len - curr_byte; - offset = curr_byte; - for (curr_byte = 0; curr_byte < num_bytes; - curr_byte++) { - sprintf(dbg_data, "0x%02x ", - *(memptr + offset + curr_byte)); - strcat(dbg_string, dbg_data); - } - pr_debug("%s\n", dbg_string); - break; - } - } - - kfree(dbg_string); -} - -void mwl_debug_dumpdata(const void *data, int len, char *marker) -{ - unsigned char *memptr = (unsigned char *)data; - int curr_byte = 0; - int num_bytes = 0; - int offset = 0; - - pr_debug("%s\n", marker); - - for (curr_byte = 0; curr_byte < len; curr_byte = curr_byte + 8) { - if ((curr_byte + 8) < len) { - pr_debug(PRT_8BYTES, - *(memptr + curr_byte + 0), - *(memptr + curr_byte + 1), - *(memptr + curr_byte + 2), - *(memptr + curr_byte + 3), - *(memptr + curr_byte + 4), - *(memptr + curr_byte + 5), - *(memptr + curr_byte + 6), - *(memptr + curr_byte + 7)); - } else { - num_bytes = len - curr_byte; - offset = curr_byte; - for (curr_byte = 0; curr_byte < num_bytes; - curr_byte++) - pr_debug("0x%02x ", - *(memptr + offset + curr_byte)); - pr_debug("\n\n"); - break; - } - } -} diff --git a/mwl_debug.h b/mwl_debug.h deleted file mode 100644 index 226db7b..0000000 --- a/mwl_debug.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/* Description: This file defines debug related functions. -*/ - -#ifndef _mwl_debug_h_ -#define _mwl_debug_h_ - -#include <linux/types.h> -#include <linux/bitops.h> - -/* CONSTANTS AND MACROS -*/ - -#define DBG_LEVEL_0 BIT(0) /* mwl_main.c */ -#define DBG_LEVEL_1 BIT(1) /* mwl_fwdl.c */ -#define DBG_LEVEL_2 BIT(2) /* mwl_fwcmd.c */ -#define DBG_LEVEL_3 BIT(3) /* mwl_tx.c */ -#define DBG_LEVEL_4 BIT(4) /* mwl_rx.c */ -#define DBG_LEVEL_5 BIT(5) /* mwl_mac80211.c */ -#define DBG_LEVEL_6 BIT(6) -#define DBG_LEVEL_7 BIT(7) -#define DBG_LEVEL_8 BIT(8) -#define DBG_LEVEL_9 BIT(9) -#define DBG_LEVEL_10 BIT(10) -#define DBG_LEVEL_11 BIT(11) -#define DBG_LEVEL_12 BIT(12) -#define DBG_LEVEL_13 BIT(13) -#define DBG_LEVEL_14 BIT(14) -#define DBG_LEVEL_15 BIT(15) - -#define DBG_CLASS_PANIC BIT(16) -#define DBG_CLASS_ERROR BIT(17) -#define DBG_CLASS_WARNING BIT(18) -#define DBG_CLASS_ENTER BIT(19) -#define DBG_CLASS_EXIT BIT(20) -#define DBG_CLASS_INFO BIT(21) -#define DBG_CLASS_DATA BIT(22) -#define DBG_CLASS_7 BIT(23) -#define DBG_CLASS_8 BIT(24) -#define DBG_CLASS_9 BIT(25) -#define DBG_CLASS_10 BIT(26) -#define DBG_CLASS_11 BIT(27) -#define DBG_CLASS_12 BIT(28) -#define DBG_CLASS_13 BIT(29) -#define DBG_CLASS_14 BIT(30) -#define DBG_CLASS_15 BIT(31) - -#define WLDBG_PRINT(...) \ - mwl_debug_prt(0, __func__, __VA_ARGS__) - -#ifdef MWL_DEBUG - -#define WLDBG_DUMP_DATA(classlevel, data, len) \ - mwl_debug_prtdata(classlevel | DBG_CLASS_DATA, \ - __func__, data, len, NULL) - -#define WLDBG_ENTER(classlevel) \ - mwl_debug_prt(classlevel | DBG_CLASS_ENTER, __func__, NULL) - -#define WLDBG_ENTER_INFO(classlevel, ...) \ - mwl_debug_prt(classlevel | DBG_CLASS_ENTER, __func__, __VA_ARGS__) - -#define WLDBG_EXIT(classlevel) \ - mwl_debug_prt(classlevel | DBG_CLASS_EXIT, __func__, NULL) - -#define WLDBG_EXIT_INFO(classlevel, ...) \ - mwl_debug_prt(classlevel | DBG_CLASS_EXIT, __func__, __VA_ARGS__) - -#define WLDBG_INFO(classlevel, ...) \ - mwl_debug_prt(classlevel | DBG_CLASS_INFO, __func__, __VA_ARGS__) - -#define WLDBG_WARNING(classlevel, ...) \ - mwl_debug_prt(classlevel | DBG_CLASS_WARNING, __func__, __VA_ARGS__) - -#define WLDBG_ERROR(classlevel, ...) \ - mwl_debug_prt(classlevel | DBG_CLASS_ERROR, __func__, __VA_ARGS__) - -#define WLDBG_PANIC(classlevel, ...) \ - mwl_debug_prt(classlevel | DBG_CLASS_PANIC, __func__, __VA_ARGS__) - -#else - -#define WLDBG_DUMP_DATA(classlevel, data, len) -#define WLDBG_ENTER(classlevel) -#define WLDBG_ENTER_INFO(classlevel, ...) -#define WLDBG_EXIT(classlevel) -#define WLDBG_EXIT_INFO(classlevel, ...) -#define WLDBG_INFO(classlevel, ...) -#define WLDBG_WARNING(classlevel, ...) -#define WLDBG_ERROR(classlevel, ...) -#define WLDBG_PANIC(classlevel, ...) - -#endif /* MWL_DEBUG */ - -/* PUBLIC FUNCTION DECLARATION -*/ - -void mwl_debug_prt(u32 classlevel, const char *func, const char *format, ...); -void mwl_debug_prtdata(u32 classlevel, const char *func, - const void *data, int len, const char *format, ...); -void mwl_debug_dumpdata(const void *data, int len, char *marker); - -#endif /* _mwl_debug_h_ */ diff --git a/mwl_dev.h b/mwl_dev.h deleted file mode 100644 index 7c6facc..0000000 --- a/mwl_dev.h +++ /dev/null @@ -1,465 +0,0 @@ -/* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/* Description: This file defines device related information. -*/ - -#ifndef _mwl_dev_h_ -#define _mwl_dev_h_ - -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/firmware.h> -#include <linux/delay.h> -#include <linux/bitops.h> -#include <net/mac80211.h> - -/* CONSTANTS AND MACROS -*/ - -/* Map to 0x80000000 (Bus control) on BAR0 -*/ -#define MACREG_REG_H2A_INTERRUPT_EVENTS 0x00000C18 /* (From host to ARM) */ -#define MACREG_REG_H2A_INTERRUPT_CAUSE 0x00000C1C /* (From host to ARM) */ -#define MACREG_REG_H2A_INTERRUPT_MASK 0x00000C20 /* (From host to ARM) */ -#define MACREG_REG_H2A_INTERRUPT_CLEAR_SEL 0x00000C24 /* (From host to ARM) */ -#define MACREG_REG_H2A_INTERRUPT_STATUS_MASK 0x00000C28 /* (From host to ARM) */ - -#define MACREG_REG_A2H_INTERRUPT_EVENTS 0x00000C2C /* (From ARM to host) */ -#define MACREG_REG_A2H_INTERRUPT_CAUSE 0x00000C30 /* (From ARM to host) */ -#define MACREG_REG_A2H_INTERRUPT_MASK 0x00000C34 /* (From ARM to host) */ -#define MACREG_REG_A2H_INTERRUPT_CLEAR_SEL 0x00000C38 /* (From ARM to host) */ -#define MACREG_REG_A2H_INTERRUPT_STATUS_MASK 0x00000C3C /* (From ARM to host) */ - -/* Map to 0x80000000 on BAR1 -*/ -#define MACREG_REG_GEN_PTR 0x00000C10 -#define MACREG_REG_INT_CODE 0x00000C14 -#define MACREG_REG_SCRATCH 0x00000C40 -#define MACREG_REG_FW_PRESENT 0x0000BFFC - -/* Bit definitio for MACREG_REG_A2H_INTERRUPT_CAUSE (A2HRIC) -*/ -#define MACREG_A2HRIC_BIT_TX_DONE 0x00000001 /* bit 0 */ -#define MACREG_A2HRIC_BIT_RX_RDY 0x00000002 /* bit 1 */ -#define MACREG_A2HRIC_BIT_OPC_DONE 0x00000004 /* bit 2 */ -#define MACREG_A2HRIC_BIT_MAC_EVENT 0x00000008 /* bit 3 */ -#define MACREG_A2HRIC_BIT_RX_PROBLEM 0x00000010 /* bit 4 */ -#define MACREG_A2HRIC_BIT_RADIO_OFF 0x00000020 /* bit 5 */ -#define MACREG_A2HRIC_BIT_RADIO_ON 0x00000040 /* bit 6 */ -#define MACREG_A2HRIC_BIT_RADAR_DETECT 0x00000080 /* bit 7 */ -#define MACREG_A2HRIC_BIT_ICV_ERROR 0x00000100 /* bit 8 */ -#define MACREG_A2HRIC_BIT_WEAKIV_ERROR 0x00000200 /* bit 9 */ -#define MACREG_A2HRIC_BIT_QUEUE_EMPTY BIT(10) -#define MACREG_A2HRIC_BIT_QUEUE_FULL BIT(11) -#define MACREG_A2HRIC_BIT_CHAN_SWITCH BIT(12) /* IEEE80211_DH */ -#define MACREG_A2HRIC_BIT_TX_WATCHDOG BIT(13) -#define MACREG_A2HRIC_BA_WATCHDOG BIT(14) -#define MACREG_A2HRIC_BIT_SSU_DONE BIT(16) -#define MACREG_A2HRIC_CONSEC_TXFAIL BIT(17) /* 15 taken by ISR_TXACK */ - -#define ISR_SRC_BITS ((MACREG_A2HRIC_BIT_RX_RDY) | \ - (MACREG_A2HRIC_BIT_TX_DONE) | \ - (MACREG_A2HRIC_BIT_OPC_DONE) | \ - (MACREG_A2HRIC_BIT_MAC_EVENT) | \ - (MACREG_A2HRIC_BIT_WEAKIV_ERROR) | \ - (MACREG_A2HRIC_BIT_ICV_ERROR) | \ - (MACREG_A2HRIC_BIT_SSU_DONE) | \ - (MACREG_A2HRIC_BIT_RADAR_DETECT) | \ - (MACREG_A2HRIC_BIT_CHAN_SWITCH) | \ - (MACREG_A2HRIC_BIT_TX_WATCHDOG) | \ - (MACREG_A2HRIC_BIT_QUEUE_EMPTY) | \ - (MACREG_A2HRIC_BA_WATCHDOG) | \ - (MACREG_A2HRIC_CONSEC_TXFAIL)) - -#define MACREG_A2HRIC_BIT_MASK ISR_SRC_BITS - -/* Bit definitio for MACREG_REG_H2A_INTERRUPT_CAUSE (H2ARIC) -*/ -#define MACREG_H2ARIC_BIT_PPA_READY 0x00000001 /* bit 0 */ -#define MACREG_H2ARIC_BIT_DOOR_BELL 0x00000002 /* bit 1 */ -#define MACREG_H2ARIC_BIT_PS 0x00000004 /* bit 2 */ -#define MACREG_H2ARIC_BIT_PSPOLL 0x00000008 /* bit 3 */ -#define ISR_RESET BIT(15) -#define ISR_RESET_AP33 BIT(26) - -/* Data descriptor related constants -*/ -#define EAGLE_RXD_CTRL_DRIVER_OWN 0x00 -#define EAGLE_RXD_CTRL_OS_OWN 0x04 -#define EAGLE_RXD_CTRL_DMA_OWN 0x80 - -#define EAGLE_RXD_STATUS_IDLE 0x00 -#define EAGLE_RXD_STATUS_OK 0x01 -#define EAGLE_RXD_STATUS_MULTICAST_RX 0x02 -#define EAGLE_RXD_STATUS_BROADCAST_RX 0x04 -#define EAGLE_RXD_STATUS_FRAGMENT_RX 0x08 - -#define EAGLE_TXD_STATUS_IDLE 0x00000000 -#define EAGLE_TXD_STATUS_USED 0x00000001 -#define EAGLE_TXD_STATUS_OK 0x00000001 -#define EAGLE_TXD_STATUS_OK_RETRY 0x00000002 -#define EAGLE_TXD_STATUS_OK_MORE_RETRY 0x00000004 -#define EAGLE_TXD_STATUS_MULTICAST_TX 0x00000008 -#define EAGLE_TXD_STATUS_BROADCAST_TX 0x00000010 -#define EAGLE_TXD_STATUS_FAILED_LINK_ERROR 0x00000020 -#define EAGLE_TXD_STATUS_FAILED_EXCEED_LIMIT 0x00000040 -#define EAGLE_TXD_STATUS_FAILED_AGING 0x00000080 -#define EAGLE_TXD_STATUS_FW_OWNED 0x80000000 - -#define EAGLE_TXD_XMITCTRL_USE_RATEINFO 0x1 -#define EAGLE_TXD_XMITCTRL_DISABLE_AMPDU 0x2 -#define EAGLE_TXD_XMITCTRL_ENABLE_AMPDU 0x4 -#define EAGLE_TXD_XMITCTRL_USE_MC_RATE 0x8 - -#define NBR_BYTES_FW_RX_PREPEND_LEN 2 -#define NBR_BYTES_FW_TX_PREPEND_LEN 2 - -/* Antenna control -*/ -#define ANTENNA_TX_4_AUTO 0 -#define ANTENNA_TX_2 3 -#define ANTENNA_RX_4_AUTO 0 -#define ANTENNA_RX_2 2 - -/* Band related constants -*/ -#define BAND_24_CHANNEL_NUM 14 -#define BAND_24_RATE_NUM 13 -#define BAND_50_CHANNEL_NUM 24 -#define BAND_50_RATE_NUM 8 - -/* Misc -*/ -#define WL_SEC_SLEEP(num_secs) mdelay(num_secs * 1000) -#define WL_MSEC_SLEEP(num_milli_secs) mdelay(num_milli_secs) - -#define ENDIAN_SWAP32(_val) (cpu_to_le32(_val)) -#define ENDIAN_SWAP16(_val) (cpu_to_le16(_val)) - -#define DECLARE_LOCK(l) spinlock_t l -#define SPIN_LOCK_INIT(l) spin_lock_init(l) -#define SPIN_LOCK(l) spin_lock(l) -#define SPIN_UNLOCK(l) spin_unlock(l) -#define SPIN_LOCK_IRQSAVE(l, f) spin_lock_irqsave(l, f) -#define SPIN_UNLOCK_IRQRESTORE(l, f) spin_unlock_irqrestore(l, f) - -/* vif and station -*/ -#define MAX_WEP_KEY_LEN 13 -#define NUM_WEP_KEYS 4 -#define MWL_MAX_TID 8 -#define MWL_VIF(_vif) ((struct mwl_vif *)&((_vif)->drv_priv)) -#define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8)) -#define MWL_STA(_sta) ((struct mwl_sta *)&((_sta)->drv_priv)) - -/* TYPE DEFINITION -*/ - -enum { - MWL8864 = 0, - MWL8897, - MWLUNKNOWN, -}; - -enum { - AP_MODE_11AC = 0x10, /* generic 11ac indication mode */ - AP_MODE_2_4GHZ_11AC_MIXED = 0x17, -}; - -enum { - AMPDU_NO_STREAM, - AMPDU_STREAM_NEW, - AMPDU_STREAM_IN_PROGRESS, - AMPDU_STREAM_ACTIVE, -}; - -enum { - IEEE_TYPE_MANAGEMENT = 0, - IEEE_TYPE_CONTROL, - IEEE_TYPE_DATA -}; - -struct mwl_chip_info { - char *part_name; - char *fw_image; -}; - -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; -}; - -struct mwl_hw_data { - u32 fw_release_num; /* MajNbr:MinNbr:SubMin:PatchLevel */ - u8 hw_version; /* plain number indicating version */ - u8 host_interface; /* plain number of interface */ - u16 max_num_tx_desc; /* max number of TX descriptors */ - u16 max_num_mc_addr; /* max number multicast addresses */ - u16 num_antennas; /* number antennas used */ - u16 region_code; /* region (eg. 0x10 for USA FCC) */ - unsigned char mac_addr[ETH_ALEN]; /* well known -> AA:BB:CC:DD:EE:FF */ -}; - -struct mwl_rate_info { - u32 format:2; /* 0 = Legacy, 1 = 11n, 2 = 11ac */ - u32 stbc:1; - u32 rsvd1:1; - u32 bandwidth:2; /* 0 = 20 MHz, 1 = 40 MHz, 2 = 80 MHz */ - u32 short_gi:1; /* 0 = standard guard interval, 1 = short */ - u32 rsvd2:1; - u32 rate_id_mcs:7; - u32 preamble_type:1; /* Preambletype 0 = Long, 1 = Short; */ - u32 power_id:6; - u32 adv_coding:1; /* ldpc */ - u32 bf:1; - u32 ant_select:8; /* Bitmap to select one of the transmit antenna */ -} __packed; - -struct mwl_tx_desc { - u8 data_rate; - u8 tx_priority; - u16 qos_ctrl; - u32 pkt_ptr; - u16 pkt_len; - u8 dest_addr[ETH_ALEN]; - u32 pphys_next; - u32 sap_pkt_info; - struct mwl_rate_info rate_info; - u8 type; - u8 xmit_control; /* bit 0: use rateinfo, bit 1: disable ampdu */ - u16 reserved; - u32 tcpack_sn; - u32 tcpack_src_dst; - struct sk_buff *psk_buff; - struct mwl_tx_desc *pnext; - u8 reserved1[2]; - u8 packet_info; - u8 packet_id; - u16 packet_len_and_retry; - u16 packet_rate_info; - u8 *sta_info; - u32 status; -} __packed; - -struct mwl_hw_rssi_info { - u32 rssi_a:8; - u32 rssi_b:8; - u32 rssi_c:8; - u32 rssi_d:8; -} __packed; - -struct mwl_hw_noise_floor_info { - u32 noise_floor_a:8; - u32 noise_floor_b:8; - u32 noise_floor_c:8; - u32 noise_floor_d:8; -} __packed; - -struct mwl_rxrate_info { - u16 format:3; /* 0: 11a, 1: 11b, 2: 11n, 4: 11ac */ - u16 nss:2; /* number space spectrum */ - u16 bw:2; /* 0: ht20, 1: ht40, 2: ht80 */ - u16 gi:1; /* 0: long interval, 1: short interval*/ - u16 rt:8; /* 11a/11b: 1,2,5,11,22,6,9,12,18,24,36,48,54,72*/ -} __packed; /* 11n/11ac: MCS */ - -struct mwl_rx_desc { - u16 pkt_len; /* total length of received data */ - struct mwl_rxrate_info rate; /* receive rate information */ - u32 pphys_buff_data; /* physical address of payload data */ - u32 pphys_next; /* physical address of next RX desc */ - u16 qos_ctrl; /* received QosCtrl field variable */ - u16 ht_sig2; /* like name states */ - struct mwl_hw_rssi_info hw_rssi_info; - struct mwl_hw_noise_floor_info hw_noise_floor_info; - u8 noise_floor; - u8 reserved[3]; - u8 rssi; /* received signal strengt indication */ - 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 */ -} __packed; - -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 */ - 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_locks { - DECLARE_LOCK(xmit_lock); /* used to protect TX actions */ - DECLARE_LOCK(fwcmd_lock); /* used to protect FW commands */ - DECLARE_LOCK(stream_lock); /* used to protect stream */ -}; - -struct mwl_ampdu_stream { - struct ieee80211_sta *sta; - u8 tid; - u8 state; - u8 idx; -}; - -struct mwl_priv { - struct ieee80211_hw *hw; - const struct firmware *fw_ucode; - int chip_type; - struct device_node *dt_node; - struct device_node *pwr_node; - bool disable_2g; - bool disable_5g; - int antenna_tx; - int antenna_rx; - struct mwl_tx_pwr_tbl tx_pwr_tbl[SYSADPT_MAX_NUM_CHANNELS]; - u32 cdd; /* 0: off, 1: on */ - u16 txantenna2; - u8 powinited; - u16 max_tx_pow[SYSADPT_TX_POWER_LEVEL_TOTAL]; /* max tx power (dBm) */ - u16 target_powers[SYSADPT_TX_POWER_LEVEL_TOTAL]; /* target powers */ - u8 cal_tbl[200]; - struct pci_dev *pdev; - void *iobase0; /* MEM Base Address Register 0 */ - void *iobase1; /* MEM Base Address Register 1 */ - u32 next_bar_num; - unsigned short *pcmd_buf; /* pointer to CmdBuf (virtual) */ - dma_addr_t pphys_cmd_buf; /* pointer to CmdBuf (physical) */ - bool in_send_cmd; - int irq; - struct mwl_hw_data hw_data; /* Adapter HW specific info */ - /* various descriptor data */ - struct mwl_desc_data desc_data[SYSADPT_NUM_OF_DESC_DATA]; - struct sk_buff_head txq[SYSADPT_NUM_OF_DESC_DATA]; - struct sk_buff_head delay_q; - /* number of descriptors owned by fw at any one time */ - int fw_desc_cnt[SYSADPT_NUM_OF_DESC_DATA]; - struct mwl_locks locks; /* various spinlocks */ - struct tasklet_struct tx_task; - struct tasklet_struct rx_task; - int txq_limit; - bool is_tx_schedule; - int recv_limit; - bool is_rx_schedule; - s8 noise; /* Most recently reported noise in dBm */ - struct ieee80211_supported_band band_24; - struct ieee80211_channel channels_24[BAND_24_CHANNEL_NUM]; - struct ieee80211_rate rates_24[BAND_24_RATE_NUM]; - struct ieee80211_supported_band band_50; - struct ieee80211_channel channels_50[BAND_50_CHANNEL_NUM]; - struct ieee80211_rate rates_50[BAND_50_RATE_NUM]; - u32 ap_macids_supported; - u32 sta_macids_supported; - u32 macids_used; - struct list_head vif_list; /* List of interfaces. */ - u32 running_bsses; /* bitmap of running BSSes */ - bool radio_on; - bool radio_short_preamble; - bool wmm_enabled; - struct ieee80211_tx_queue_params wmm_params[SYSADPT_TX_WMM_QUEUES]; - /* Ampdu stream information */ - u8 num_ampdu_queues; - struct mwl_ampdu_stream ampdu[SYSADPT_TX_AMPDU_QUEUES]; - struct work_struct watchdog_ba_handle; -}; - -struct beacon_info { - bool valid; - u16 cap_info; - u8 b_rate_set[SYSADPT_MAX_DATA_RATES_G]; - u8 op_rate_set[SYSADPT_MAX_DATA_RATES_G]; - u8 ie_wmm_len; /* Keep WMM IE */ - u8 *ie_wmm_ptr; - u8 ie_rsn_len; /* Keep WPA IE */ - u8 *ie_rsn_ptr; - u8 ie_rsn48_len; /* Keep WPA2 IE */ - u8 *ie_rsn48_ptr; - u8 ie_ht_len; /* Keep HT IE */ - u8 *ie_ht_ptr; - u8 ie_list_ht[148]; - u8 ie_vht_len; /* Keep VHT IE */ - u8 *ie_vht_ptr; - u8 ie_list_vht[24]; -}; - -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 */ - u8 enabled; - u8 key[sizeof(struct ieee80211_key_conf) + MAX_WEP_KEY_LEN]; - } wep_key_conf[NUM_WEP_KEYS]; - u8 bssid[ETH_ALEN]; /* BSSID */ - u8 sta_mac[ETH_ALEN]; /* Station mac address */ - /* 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; - s8 keyidx; -}; - -struct mwl_tx_info { - u32 start_time; - u32 pkts; -}; - -struct mwl_sta { - u8 is_ampdu_allowed; - struct mwl_tx_info tx_stats[MWL_MAX_TID]; - u16 iv16; - u32 iv32; -}; - -/* DMA header used by firmware and hardware. -*/ -struct mwl_dma_data { - u16 fwlen; - struct ieee80211_hdr wh; - char data[0]; -} __packed; - -/* Transmission information to transmit a socket buffer. - */ -struct mwl_tx_ctrl { - u8 tx_priority; - u16 qos_ctrl; - u8 type; - u8 xmit_control; - u8 *sta_info; - bool ccmp; -} __packed; - -#endif /* _mwl_dev_h_ */ diff --git a/mwl_fwdl.h b/mwl_fwdl.h deleted file mode 100644 index cad4056..0000000 --- a/mwl_fwdl.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/* Description: This file defines firmware download related functions. -*/ - -#ifndef _mwl_fwdl_h_ -#define _mwl_fwdl_h_ - -#include <net/mac80211.h> - -/* PUBLIC FUNCTION DECLARATION -*/ -int mwl_fwdl_download_firmware(struct ieee80211_hw *hw); - -#endif /* _mwl_fwdl_h_ */ diff --git a/mwl_mac80211.h b/mwl_mac80211.h deleted file mode 100644 index 71fc4f8..0000000 --- a/mwl_mac80211.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/* Description: This file defines mac80211 related functions. -*/ - -#ifndef _mwl_mac80211_h_ -#define _mwl_mac80211_h_ - -#include <linux/interrupt.h> -#include <net/mac80211.h> - -/* PUBLIC FUNCTION DECLARATION -*/ - -struct ieee80211_ops *mwl_mac80211_get_ops(void); -void mwl_mac80211_set_isr(irqreturn_t (*isr)(int irq, void *dev_id)); - -#endif /* _mwl_mac80211_h_ */ diff --git a/mwl_rx.h b/mwl_rx.h deleted file mode 100644 index 184ff31..0000000 --- a/mwl_rx.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/* Description: This file defines receive related functions. -*/ - -#ifndef _mwl_rx_h_ -#define _mwl_rx_h_ - -/* PUBLIC FUNCTION DECLARATION -*/ - -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_ */ diff --git a/mwl_tx.h b/mwl_tx.h deleted file mode 100644 index 20a8772..0000000 --- a/mwl_tx.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/* Description: This file defines transmit related functions. -*/ - -#ifndef _mwl_tx_h_ -#define _mwl_tx_h_ - -/* PUBLIC FUNCTION DECLARATION -*/ - -int mwl_tx_init(struct ieee80211_hw *hw); -void mwl_tx_deinit(struct ieee80211_hw *hw); -void mwl_tx_xmit(struct ieee80211_hw *hw, - int index, - struct ieee80211_sta *sta, - struct sk_buff *skb); -void mwl_tx_done(unsigned long data); - -#endif /* _mwl_tx_h_ */ @@ -1,31 +1,19 @@ /* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ + * 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 implements receive related functions. -*/ + */ #include <linux/skbuff.h> -#include "mwl_sysadpt.h" -#include "mwl_dev.h" -#include "mwl_debug.h" -#include "mwl_rx.h" - -/* CONSTANTS AND MACROS -*/ +#include "sysadpt.h" +#include "dev.h" +#include "rx.h" #define MAX_NUM_RX_RING_BYTES (SYSADPT_MAX_NUM_RX_DESC * \ sizeof(struct mwl_rx_desc)) @@ -43,8 +31,7 @@ #define W836X_RSSI_OFFSET 8 -/* Receive rate information constants -*/ +/* Receive rate information constants */ #define RX_RATE_INFO_FORMAT_11A 0 #define RX_RATE_INFO_FORMAT_11B 1 #define RX_RATE_INFO_FORMAT_11N 2 @@ -57,205 +44,8 @@ #define RX_RATE_INFO_LONG_INTERVAL 0 #define RX_RATE_INFO_SHORT_INTERVAL 1 -/* PRIVATE FUNCTION DECLARATION -*/ - -static int mwl_rx_ring_alloc(struct mwl_priv *priv); -static int mwl_rx_ring_init(struct mwl_priv *priv); -static void mwl_rx_ring_cleanup(struct mwl_priv *priv); -static void mwl_rx_ring_free(struct mwl_priv *priv); -static inline void mwl_rx_prepare_status(struct mwl_rx_desc *pdesc, - struct ieee80211_rx_status *status); -static inline struct mwl_vif *mwl_rx_find_vif_bss(struct list_head *vif_list, - u8 *bssid); -static inline void mwl_rx_remove_dma_header(struct sk_buff *skb, u16 qos); -static int mwl_rx_refill(struct mwl_priv *priv, struct mwl_rx_desc *pdesc); - -/* PUBLIC FUNCTION DEFINITION -*/ - -int mwl_rx_init(struct ieee80211_hw *hw) -{ - struct mwl_priv *priv; - int rc; - - WLDBG_ENTER(DBG_LEVEL_4); - - BUG_ON(!hw); - priv = hw->priv; - BUG_ON(!priv); - - rc = mwl_rx_ring_alloc(priv); - if (rc) { - WLDBG_ERROR(DBG_LEVEL_4, "allocating RX ring failed"); - } else { - rc = mwl_rx_ring_init(priv); - if (rc) { - mwl_rx_ring_free(priv); - WLDBG_ERROR(DBG_LEVEL_4, - "initializing RX ring failed"); - } - } - - WLDBG_EXIT(DBG_LEVEL_4); - - return rc; -} - -void mwl_rx_deinit(struct ieee80211_hw *hw) -{ - struct mwl_priv *priv; - - WLDBG_ENTER(DBG_LEVEL_4); - - BUG_ON(!hw); - priv = hw->priv; - BUG_ON(!priv); - - mwl_rx_ring_cleanup(priv); - mwl_rx_ring_free(priv); - - WLDBG_EXIT(DBG_LEVEL_4); -} - -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; - int work_done = 0; - struct sk_buff *prx_skb = NULL; - int pkt_len; - struct ieee80211_rx_status status; - struct mwl_vif *mwl_vif = NULL; - struct ieee80211_hdr *wh; - u32 status_mask; - - WLDBG_ENTER(DBG_LEVEL_4); - - BUG_ON(!hw); - priv = hw->priv; - BUG_ON(!priv); - - curr_desc = priv->desc_data[0].pnext_rx_desc; - - if (!curr_desc) { - status_mask = readl(priv->iobase1 + - MACREG_REG_A2H_INTERRUPT_STATUS_MASK); - writel(status_mask | MACREG_A2HRIC_BIT_RX_RDY, - priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); - - priv->is_rx_schedule = false; - - WLDBG_EXIT_INFO(DBG_LEVEL_4, "busy or no receiving packets"); - return; - } - - while ((curr_desc->rx_control == EAGLE_RXD_CTRL_DMA_OWN) && - (work_done < priv->recv_limit)) { - prx_skb = curr_desc->psk_buff; - if (!prx_skb) - goto out; - pci_unmap_single(priv->pdev, - ENDIAN_SWAP32(curr_desc->pphys_buff_data), - priv->desc_data[0].rx_buf_size, - PCI_DMA_FROMDEVICE); - pkt_len = curr_desc->pkt_len; - - if (skb_tailroom(prx_skb) < pkt_len) { - WLDBG_PRINT("Critical error: %x %x %x %x", - skb_tailroom(prx_skb), pkt_len, - curr_desc, curr_desc->pbuff_data); - dev_kfree_skb_any(prx_skb); - goto out; - } - - if (curr_desc->channel != hw->conf.chandef.chan->hw_value) { - dev_kfree_skb_any(prx_skb); - goto out; - } - - mwl_rx_prepare_status(curr_desc, &status); - - priv->noise = -curr_desc->noise_floor; - - wh = &((struct mwl_dma_data *)prx_skb->data)->wh; - - if (ieee80211_has_protected(wh->frame_control)) { - /* Check if hw crypto has been enabled for - * this bss. If yes, set the status flags - * accordingly - */ - if (ieee80211_has_tods(wh->frame_control)) - mwl_vif = mwl_rx_find_vif_bss(&priv->vif_list, - wh->addr1); - else - mwl_vif = mwl_rx_find_vif_bss(&priv->vif_list, - wh->addr2); - - if (mwl_vif && mwl_vif->is_hw_crypto_enabled) { - /* When MMIC ERROR is encountered - * by the firmware, payload is - * dropped and only 32 bytes of - * mwl8k Firmware header is sent - * to the host. - * - * We need to add four bytes of - * key information. In it - * MAC80211 expects keyidx set to - * 0 for triggering Counter - * Measure of MMIC failure. - */ - if (status.flag & RX_FLAG_MMIC_ERROR) { - struct mwl_dma_data *tr; - - tr = (struct mwl_dma_data *) - prx_skb->data; - memset((void *)&tr->data, 0, 4); - pkt_len += 4; - } - - if (!ieee80211_is_auth(wh->frame_control)) - status.flag |= RX_FLAG_IV_STRIPPED | - RX_FLAG_DECRYPTED | - RX_FLAG_MMIC_STRIPPED; - } - } - - skb_put(prx_skb, pkt_len); - mwl_rx_remove_dma_header(prx_skb, curr_desc->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; - work_done++; - } - - priv->desc_data[0].pnext_rx_desc = curr_desc; - - status_mask = readl(priv->iobase1 + - MACREG_REG_A2H_INTERRUPT_STATUS_MASK); - writel(status_mask | MACREG_A2HRIC_BIT_RX_RDY, - priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); - - priv->is_rx_schedule = false; - - WLDBG_EXIT(DBG_LEVEL_4); -} - -/* PRIVATE FUNCTION DEFINITION -*/ - static int mwl_rx_ring_alloc(struct mwl_priv *priv) { - WLDBG_ENTER_INFO(DBG_LEVEL_4, "allocating %i (0x%x) bytes", - MAX_NUM_RX_RING_BYTES, MAX_NUM_RX_RING_BYTES); - - BUG_ON(!priv); - priv->desc_data[0].prx_ring = (struct mwl_rx_desc *) dma_alloc_coherent(&priv->pdev->dev, @@ -264,17 +54,12 @@ static int mwl_rx_ring_alloc(struct mwl_priv *priv) GFP_KERNEL); if (!priv->desc_data[0].prx_ring) { - WLDBG_ERROR(DBG_LEVEL_4, "can not alloc mem"); - WLDBG_EXIT_INFO(DBG_LEVEL_4, "no memory"); + wiphy_err(priv->hw->wiphy, "can not alloc mem"); return -ENOMEM; } memset(priv->desc_data[0].prx_ring, 0x00, MAX_NUM_RX_RING_BYTES); - WLDBG_EXIT_INFO(DBG_LEVEL_4, "RX ring vaddr: 0x%x paddr: 0x%x", - priv->desc_data[0].prx_ring, - priv->desc_data[0].pphys_rx_ring); - return 0; } @@ -283,9 +68,6 @@ static int mwl_rx_ring_init(struct mwl_priv *priv) int curr_desc; struct mwl_desc_data *desc; - WLDBG_ENTER_INFO(DBG_LEVEL_4, "initializing %i descriptors", - SYSADPT_MAX_NUM_RX_DESC); - desc = &priv->desc_data[0]; if (desc->prx_ring) { @@ -298,10 +80,8 @@ static int mwl_rx_ring_init(struct mwl_priv *priv) if (skb_linearize(CURR_RXD.psk_buff)) { dev_kfree_skb_any(CURR_RXD.psk_buff); - WLDBG_ERROR(DBG_LEVEL_4, - "need linearize memory"); - WLDBG_EXIT_INFO(DBG_LEVEL_4, - "no suitable memory"); + wiphy_err(priv->hw->wiphy, + "need linearize memory"); return -ENOMEM; } @@ -317,57 +97,37 @@ static int mwl_rx_ring_init(struct mwl_priv *priv) dma_addr_t dma; u32 val; - CURR_RXD.pkt_len = SYSADPT_MAX_AGGR_SIZE; + 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 = - ENDIAN_SWAP32(dma); + 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 = - ENDIAN_SWAP32(val); - WLDBG_INFO(DBG_LEVEL_4, - "rxdesc:%i 0x%x(%i) 0x%x(%i)", - curr_desc, - EAGLE_TXD_STATUS_IDLE, - EAGLE_TXD_STATUS_IDLE, - desc->rx_buf_size, - desc->rx_buf_size); - WLDBG_INFO(DBG_LEVEL_4, - "rxdesc: %i vnext: 0x%p pnext: 0x%x", - curr_desc, - CURR_RXD.pnext, - ENDIAN_SWAP32(CURR_RXD.pphys_next)); + cpu_to_le32(val); } else { - WLDBG_ERROR(DBG_LEVEL_4, - "rxdesc %i: no skbuff available", - curr_desc); - WLDBG_EXIT_INFO(DBG_LEVEL_4, - "no socket buffer"); + wiphy_err(priv->hw->wiphy, + "rxdesc %i: no skbuff available", + curr_desc); return -ENOMEM; } } LAST_RXD.pphys_next = - ENDIAN_SWAP32((u32)desc->pphys_rx_ring); + cpu_to_le32((u32)desc->pphys_rx_ring); LAST_RXD.pnext = &FIRST_RXD; priv->desc_data[0].pnext_rx_desc = &FIRST_RXD; - WLDBG_EXIT_INFO(DBG_LEVEL_4, - "last rxdesc vnext:0x%p pnext:0x%x vfirst 0x%x", - LAST_RXD.pnext, - ENDIAN_SWAP32(LAST_RXD.pphys_next), - desc->pnext_rx_desc); - return 0; } - WLDBG_ERROR(DBG_LEVEL_4, "no valid RX mem"); - WLDBG_EXIT_INFO(DBG_LEVEL_4, "no valid RX mem"); + wiphy_err(priv->hw->wiphy, "no valid RX mem"); return -ENOMEM; } @@ -376,10 +136,6 @@ static void mwl_rx_ring_cleanup(struct mwl_priv *priv) { int curr_desc; - WLDBG_ENTER(DBG_LEVEL_4); - - BUG_ON(!priv); - if (priv->desc_data[0].prx_ring) { for (curr_desc = 0; curr_desc < SYSADPT_MAX_NUM_RX_DESC; curr_desc++) { @@ -393,33 +149,27 @@ static void mwl_rx_ring_cleanup(struct mwl_priv *priv) skb_shinfo(CURR_RXD.psk_buff)->frag_list = NULL; pci_unmap_single(priv->pdev, - ENDIAN_SWAP32 + le32_to_cpu (CURR_RXD.pphys_buff_data), priv->desc_data[0].rx_buf_size, PCI_DMA_FROMDEVICE); dev_kfree_skb_any(CURR_RXD.psk_buff); - WLDBG_INFO(DBG_LEVEL_4, + wiphy_info(priv->hw->wiphy, "unmapped+free'd %i 0x%p 0x%x %i", curr_desc, CURR_RXD.pbuff_data, - ENDIAN_SWAP32(CURR_RXD.pphys_buff_data), + le32_to_cpu(CURR_RXD.pphys_buff_data), priv->desc_data[0].rx_buf_size); CURR_RXD.pbuff_data = NULL; CURR_RXD.psk_buff = NULL; } } - - WLDBG_EXIT(DBG_LEVEL_4); } static void mwl_rx_ring_free(struct mwl_priv *priv) { - WLDBG_ENTER(DBG_LEVEL_4); - - BUG_ON(!priv); - if (priv->desc_data[0].prx_ring) { mwl_rx_ring_cleanup(priv); @@ -432,43 +182,45 @@ static void mwl_rx_ring_free(struct mwl_priv *priv) } priv->desc_data[0].pnext_rx_desc = NULL; - - WLDBG_EXIT(DBG_LEVEL_4); } static inline void mwl_rx_prepare_status(struct mwl_rx_desc *pdesc, struct ieee80211_rx_status *status) { - WLDBG_ENTER(DBG_LEVEL_4); - - BUG_ON(!pdesc); - BUG_ON(!status); + u16 rate, format, nss, bw, gi, rt; memset(status, 0, sizeof(*status)); status->signal = -(pdesc->rssi + W836X_RSSI_OFFSET); - switch (pdesc->rate.format) { + rate = le16_to_cpu(pdesc->rate); + format = rate & MWL_RX_RATE_FORMAT_MASK; + nss = (rate & MWL_RX_RATE_NSS_MASK) >> MWL_RX_RATE_NSS_SHIFT; + bw = (rate & MWL_RX_RATE_BW_MASK) >> MWL_RX_RATE_BW_SHIFT; + gi = (rate & MWL_RX_RATE_GI_MASK) >> MWL_RX_RATE_GI_SHIFT; + rt = (rate & MWL_RX_RATE_RT_MASK) >> MWL_RX_RATE_RT_SHIFT; + + switch (format) { case RX_RATE_INFO_FORMAT_11N: status->flag |= RX_FLAG_HT; - if (pdesc->rate.bw == RX_RATE_INFO_HT40) + if (bw == RX_RATE_INFO_HT40) status->flag |= RX_FLAG_40MHZ; - if (pdesc->rate.gi == RX_RATE_INFO_SHORT_INTERVAL) + if (gi == RX_RATE_INFO_SHORT_INTERVAL) status->flag |= RX_FLAG_SHORT_GI; break; case RX_RATE_INFO_FORMAT_11AC: status->flag |= RX_FLAG_VHT; - if (pdesc->rate.bw == RX_RATE_INFO_HT40) + if (bw == RX_RATE_INFO_HT40) status->flag |= RX_FLAG_40MHZ; - if (pdesc->rate.bw == RX_RATE_INFO_HT80) + if (bw == RX_RATE_INFO_HT80) status->vht_flag |= RX_VHT_FLAG_80MHZ; - if (pdesc->rate.gi == RX_RATE_INFO_SHORT_INTERVAL) + if (gi == RX_RATE_INFO_SHORT_INTERVAL) status->flag |= RX_FLAG_SHORT_GI; - status->vht_nss = (pdesc->rate.nss + 1); + status->vht_nss = (nss + 1); break; } - status->rate_idx = pdesc->rate.rt; + status->rate_idx = rt; if (pdesc->channel > BAND_24_CHANNEL_NUM) { status->band = IEEE80211_BAND_5GHZ; @@ -506,24 +258,27 @@ static inline void mwl_rx_prepare_status(struct mwl_rx_desc *pdesc, } } } - - WLDBG_EXIT(DBG_LEVEL_4); } -static inline struct mwl_vif *mwl_rx_find_vif_bss(struct list_head *vif_list, +static inline struct mwl_vif *mwl_rx_find_vif_bss(struct mwl_priv *priv, u8 *bssid) { struct mwl_vif *mwl_vif; + unsigned long flags; - list_for_each_entry(mwl_vif, vif_list, list) { - if (memcmp(bssid, mwl_vif->bssid, ETH_ALEN) == 0) + spin_lock_irqsave(&priv->vif_lock, flags); + 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); return mwl_vif; + } } + spin_unlock_irqrestore(&priv->vif_lock, flags); return NULL; } -static inline void mwl_rx_remove_dma_header(struct sk_buff *skb, u16 qos) +static inline void mwl_rx_remove_dma_header(struct sk_buff *skb, __le16 qos) { struct mwl_dma_data *tr; int hdrlen; @@ -534,7 +289,7 @@ static inline void mwl_rx_remove_dma_header(struct sk_buff *skb, u16 qos) if (hdrlen != sizeof(tr->wh)) { if (ieee80211_is_data_qos(tr->wh.frame_control)) { memmove(tr->data - hdrlen, &tr->wh, hdrlen - 2); - *((u16 *)(tr->data - 2)) = qos; + *((__le16 *)(tr->data - 2)) = qos; } else { memmove(tr->data - hdrlen, &tr->wh, hdrlen); } @@ -546,11 +301,6 @@ static inline void mwl_rx_remove_dma_header(struct sk_buff *skb, u16 qos) static int mwl_rx_refill(struct mwl_priv *priv, struct mwl_rx_desc *pdesc) { - WLDBG_ENTER(DBG_LEVEL_4); - - BUG_ON(!priv); - BUG_ON(!pdesc); - pdesc->psk_buff = dev_alloc_skb(priv->desc_data[0].rx_buf_size); if (!pdesc->psk_buff) @@ -558,7 +308,7 @@ static int mwl_rx_refill(struct mwl_priv *priv, struct mwl_rx_desc *pdesc) if (skb_linearize(pdesc->psk_buff)) { dev_kfree_skb_any(pdesc->psk_buff); - WLDBG_ERROR(DBG_LEVEL_4, "need linearize memory"); + wiphy_err(priv->hw->wiphy, "need linearize memory"); goto nomem; } @@ -569,21 +319,168 @@ static int mwl_rx_refill(struct mwl_priv *priv, struct mwl_rx_desc *pdesc) pdesc->channel = 0x00; pdesc->rssi = 0x00; - pdesc->pkt_len = priv->desc_data[0].rx_buf_size; + pdesc->pkt_len = cpu_to_le16(priv->desc_data[0].rx_buf_size); pdesc->pbuff_data = pdesc->psk_buff->data; pdesc->pphys_buff_data = - ENDIAN_SWAP32(pci_map_single(priv->pdev, - pdesc->psk_buff->data, - priv->desc_data[0].rx_buf_size, - PCI_DMA_BIDIRECTIONAL)); - - WLDBG_EXIT(DBG_LEVEL_4); + cpu_to_le32(pci_map_single(priv->pdev, + pdesc->psk_buff->data, + priv->desc_data[0].rx_buf_size, + PCI_DMA_BIDIRECTIONAL)); return 0; nomem: - WLDBG_EXIT_INFO(DBG_LEVEL_4, "no memory"); + wiphy_err(priv->hw->wiphy, "no memory"); return -ENOMEM; } + +int mwl_rx_init(struct ieee80211_hw *hw) +{ + struct mwl_priv *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"); + } + } + + return rc; +} + +void mwl_rx_deinit(struct ieee80211_hw *hw) +{ + struct mwl_priv *priv; + + priv = hw->priv; + + mwl_rx_ring_cleanup(priv); + mwl_rx_ring_free(priv); +} + +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; + int work_done = 0; + struct sk_buff *prx_skb = NULL; + int pkt_len; + struct ieee80211_rx_status status; + struct mwl_vif *mwl_vif = NULL; + struct ieee80211_hdr *wh; + u32 status_mask; + + priv = hw->priv; + + curr_desc = priv->desc_data[0].pnext_rx_desc; + + if (!curr_desc) { + status_mask = readl(priv->iobase1 + + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); + writel(status_mask | MACREG_A2HRIC_BIT_RX_RDY, + priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); + + priv->is_rx_schedule = false; + + wiphy_warn(hw->wiphy, "busy or no receiving packets"); + return; + } + + while ((curr_desc->rx_control == EAGLE_RXD_CTRL_DMA_OWN) && + (work_done < priv->recv_limit)) { + prx_skb = curr_desc->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, + PCI_DMA_FROMDEVICE); + pkt_len = le16_to_cpu(curr_desc->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) { + dev_kfree_skb_any(prx_skb); + goto out; + } + + mwl_rx_prepare_status(curr_desc, &status); + + priv->noise = -curr_desc->noise_floor; + + wh = &((struct mwl_dma_data *)prx_skb->data)->wh; + + if (ieee80211_has_protected(wh->frame_control)) { + /* Check if hw crypto has been enabled for + * this bss. If yes, set the status flags + * accordingly + */ + if (ieee80211_has_tods(wh->frame_control)) + mwl_vif = mwl_rx_find_vif_bss(priv, wh->addr1); + else + mwl_vif = mwl_rx_find_vif_bss(priv, wh->addr2); + + if (mwl_vif && mwl_vif->is_hw_crypto_enabled) { + /* When MMIC ERROR is encountered + * by the firmware, payload is + * dropped and only 32 bytes of + * mwl8k Firmware header is sent + * to the host. + * + * We need to add four bytes of + * key information. In it + * MAC80211 expects keyidx set to + * 0 for triggering Counter + * Measure of MMIC failure. + */ + if (status.flag & RX_FLAG_MMIC_ERROR) { + struct mwl_dma_data *tr; + + tr = (struct mwl_dma_data *) + prx_skb->data; + memset((void *)&tr->data, 0, 4); + pkt_len += 4; + } + + if (!ieee80211_is_auth(wh->frame_control)) + status.flag |= RX_FLAG_IV_STRIPPED | + RX_FLAG_DECRYPTED | + RX_FLAG_MMIC_STRIPPED; + } + } + + skb_put(prx_skb, pkt_len); + mwl_rx_remove_dma_header(prx_skb, curr_desc->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; + work_done++; + } + + priv->desc_data[0].pnext_rx_desc = curr_desc; + + status_mask = readl(priv->iobase1 + + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); + writel(status_mask | MACREG_A2HRIC_BIT_RX_RDY, + priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); + + priv->is_rx_schedule = false; +} @@ -0,0 +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. + */ + +/* Description: This file defines receive related functions. + */ + +#ifndef _mwl_rx_h_ +#define _mwl_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_ */ diff --git a/mwl_sysadpt.h b/sysadpt.h index 1b17ec0..eb6fa86 100644 --- a/mwl_sysadpt.h +++ b/sysadpt.h @@ -1,28 +1,17 @@ /* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ + * 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 system adaptation related information. -*/ + */ #ifndef _mwl_sysadpt_h_ #define _mwl_sysadpt_h_ -/* CONSTANTS AND MACROS -*/ - #define SYSADPT_MAX_NUM_CHANNELS 64 #define SYSADPT_MAX_DATA_RATES_G 14 @@ -53,12 +42,20 @@ #define SYSADPT_RECEIVE_LIMIT 64 -#define SYSADPT_MAX_AGGR_SIZE 4096 +#define SYSADPT_MAX_AGGR_SIZE 8192 #define SYSADPT_MIN_BYTES_HEADROOM 64 #define SYSADPT_AMPDU_PACKET_THRESHOLD 64 +#define SYSADPT_AMSDU_MAX_SIZE 3300 + +#define SYSADPT_AMSDU_ALLOW_SIZE 1540 + +#define SYSADPT_AMSDU_FLUSH_TIME 500 + +#define SYSADPT_AMSDU_PACKET_THRESHOLD 10 + #define SYSADPT_MAX_TID 8 #endif /* _mwl_sysadpt_h_ */ diff --git a/test/hostapd.conf.1.multi_bssid b/test/hostapd.conf.1.multi_bssid index a2845b3..228ba1c 100644 --- a/test/hostapd.conf.1.multi_bssid +++ b/test/hostapd.conf.1.multi_bssid @@ -10,7 +10,7 @@ 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][MU-BEAMFORMER][MU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +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 562b111..d5cc39d 100644 --- a/test/hostapd.conf.1.open +++ b/test/hostapd.conf.1.open @@ -10,5 +10,5 @@ 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][MU-BEAMFORMER][MU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +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/test/hostapd.conf.36.multi_bssid b/test/hostapd.conf.36.multi_bssid index da0a5fe..0e5492d 100644 --- a/test/hostapd.conf.36.multi_bssid +++ b/test/hostapd.conf.36.multi_bssid @@ -10,7 +10,7 @@ wmm_enabled=1 ieee80211n=1 ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40] ieee80211ac=1 -vht_capab=[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MU-BEAMFORMER][MU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_capab=[MAX-MPDU-7991][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] bss=wlan1_0 ssid=mwlwifi_ap_tset2 wpa=2 diff --git a/test/hostapd.conf.36.open b/test/hostapd.conf.36.open index 08cd7f8..842a1cb 100644 --- a/test/hostapd.conf.36.open +++ b/test/hostapd.conf.36.open @@ -10,5 +10,5 @@ wmm_enabled=1 ieee80211n=1 ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40] ieee80211ac=1 -vht_capab=[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MU-BEAMFORMER][MU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_capab=[MAX-MPDU-7991][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/test/hostapd.conf.36.open.80mhz b/test/hostapd.conf.36.open.80mhz index 8310bba..5d094f2 100644 --- a/test/hostapd.conf.36.open.80mhz +++ b/test/hostapd.conf.36.open.80mhz @@ -10,7 +10,7 @@ wmm_enabled=1 ieee80211n=1 ht_capab=[LDPC][HT40+][SHORT-GI-20][SHORT-GI-40] ieee80211ac=1 -vht_capab=[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MU-BEAMFORMER][MU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_capab=[MAX-MPDU-7991][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] vht_oper_chwidth=1 vht_oper_centr_freq_seg0_idx=42 diff --git a/test/hostapd.conf.36.wpa2pskaes b/test/hostapd.conf.36.wpa2pskaes index 4bf4061..cf60121 100644 --- a/test/hostapd.conf.36.wpa2pskaes +++ b/test/hostapd.conf.36.wpa2pskaes @@ -14,5 +14,5 @@ wmm_enabled=1 ieee80211n=1 ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40] ieee80211ac=1 -vht_capab=[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MU-BEAMFORMER][MU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_capab=[MAX-MPDU-7991][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/test/hostapd.conf.36.wpa2pskaes.80mhz b/test/hostapd.conf.36.wpa2pskaes.80mhz index 5ab66a7..492fc17 100644 --- a/test/hostapd.conf.36.wpa2pskaes.80mhz +++ b/test/hostapd.conf.36.wpa2pskaes.80mhz @@ -14,7 +14,7 @@ wmm_enabled=1 ieee80211n=1 ht_capab=[LDPC][HT40+][SHORT-GI-20][SHORT-GI-40] ieee80211ac=1 -vht_capab=[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MU-BEAMFORMER][MU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_capab=[MAX-MPDU-7991][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] vht_oper_chwidth=1 vht_oper_centr_freq_seg0_idx=42 diff --git a/test/wpa_supplicant.conf.open b/test/wpa_supplicant.conf.open index d7677b9..d7677b9 100755..100644 --- a/test/wpa_supplicant.conf.open +++ b/test/wpa_supplicant.conf.open diff --git a/test/wpa_supplicant.conf.psk b/test/wpa_supplicant.conf.psk index ce154a6..ce154a6 100755..100644 --- a/test/wpa_supplicant.conf.psk +++ b/test/wpa_supplicant.conf.psk @@ -1,33 +1,21 @@ /* -* Copyright (c) 2006-2015 Marvell International Ltd. -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ + * 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 implements transmit related functions. -*/ + */ #include <linux/etherdevice.h> #include <linux/skbuff.h> -#include "mwl_sysadpt.h" -#include "mwl_dev.h" -#include "mwl_debug.h" -#include "mwl_fwcmd.h" -#include "mwl_tx.h" - -/* CONSTANTS AND MACROS -*/ +#include "sysadpt.h" +#include "dev.h" +#include "fwcmd.h" +#include "tx.h" #define MAX_NUM_TX_RING_BYTES (SYSADPT_MAX_NUM_TX_DESC * \ sizeof(struct mwl_tx_desc)) @@ -53,8 +41,7 @@ (iv32)++; \ } -/* Transmit rate information constants -*/ +/* Transmit rate information constants */ #define TX_RATE_FORMAT_LEGACY 0 #define TX_RATE_FORMAT_11N 1 #define TX_RATE_FORMAT_11AC 2 @@ -66,55 +53,420 @@ #define TX_RATE_INFO_STD_GI 0 #define TX_RATE_INFO_SHORT_GI 1 -/* PRIVATE FUNCTION DECLARATION -*/ +enum { + IEEE_TYPE_MANAGEMENT = 0, + IEEE_TYPE_CONTROL, + IEEE_TYPE_DATA +}; + +static int mwl_tx_ring_alloc(struct mwl_priv *priv) +{ + 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); + + if (!mem) { + wiphy_err(priv->hw->wiphy, "can not alloc mem"); + return -ENOMEM; + } + + for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { + priv->desc_data[num].ptx_ring = (struct mwl_tx_desc *) + (mem + num * MAX_NUM_TX_RING_BYTES); + + priv->desc_data[num].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, + MAX_NUM_TX_RING_BYTES); + } + + return 0; +} + +static int mwl_tx_ring_init(struct mwl_priv *priv) +{ + int curr_desc; + struct mwl_desc_data *desc; + int num; + + for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { + skb_queue_head_init(&priv->txq[num]); + priv->fw_desc_cnt[num] = 0; + + 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 = + cpu_to_le32(EAGLE_TXD_STATUS_IDLE); + CURR_TXD(num).pnext = &NEXT_TXD(num); + CURR_TXD(num).pphys_next = + cpu_to_le32((u32)desc->pphys_tx_ring + + ((curr_desc + 1) * + sizeof(struct mwl_tx_desc))); + } + LAST_TXD(num).pnext = &FIRST_TXD(num); + LAST_TXD(num).pphys_next = + cpu_to_le32((u32)desc->pphys_tx_ring); + desc->pstale_tx_desc = &FIRST_TXD(num); + desc->pnext_tx_desc = &FIRST_TXD(num); + } else { + wiphy_err(priv->hw->wiphy, "no valid TX mem"); + return -ENOMEM; + } + } + + return 0; +} + +static void mwl_tx_ring_cleanup(struct mwl_priv *priv) +{ + int cleaned_tx_desc = 0; + int curr_desc; + int num; + + 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) + continue; + + wiphy_info(priv->hw->wiphy, + "unmapped and free'd %i 0x%p 0x%x", + curr_desc, + CURR_TXD(num).psk_buff->data, + le32_to_cpu( + CURR_TXD(num).pkt_ptr)); + pci_unmap_single(priv->pdev, + le32_to_cpu( + CURR_TXD(num).pkt_ptr), + CURR_TXD(num).psk_buff->len, + PCI_DMA_TODEVICE); + dev_kfree_skb_any(CURR_TXD(num).psk_buff); + CURR_TXD(num).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; + cleaned_tx_desc++; + } + } + } + + wiphy_info(priv->hw->wiphy, "cleaned %i TX descr", cleaned_tx_desc); +} + +static void mwl_tx_ring_free(struct mwl_priv *priv) +{ + int num; + + if (priv->desc_data[0].ptx_ring) { + 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); + } + + 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; + } +} -static int mwl_tx_ring_alloc(struct mwl_priv *priv); -static int mwl_tx_ring_init(struct mwl_priv *priv); -static void mwl_tx_ring_cleanup(struct mwl_priv *priv); -static void mwl_tx_ring_free(struct mwl_priv *priv); static inline void mwl_tx_add_dma_header(struct mwl_priv *priv, struct sk_buff *skb, int head_pad, - int tail_pad); + int tail_pad) +{ + struct ieee80211_hdr *wh; + int hdrlen; + int reqd_hdrlen; + struct mwl_dma_data *tr; + + /* Add a firmware DMA header; the firmware requires that we + * present a 2-byte payload length followed by a 4-address + * header (without QoS field), followed (optionally) by any + * WEP/ExtIV header (but only filled in for CCMP). + */ + wh = (struct ieee80211_hdr *)skb->data; + + hdrlen = ieee80211_hdrlen(wh->frame_control); + + reqd_hdrlen = sizeof(*tr) + head_pad; + + if (hdrlen != reqd_hdrlen) + skb_push(skb, reqd_hdrlen - hdrlen); + + if (ieee80211_is_data_qos(wh->frame_control)) + hdrlen -= IEEE80211_QOS_CTL_LEN; + + tr = (struct mwl_dma_data *)skb->data; + + if (wh != &tr->wh) + memmove(&tr->wh, wh, hdrlen); + + if (hdrlen != sizeof(tr->wh)) + memset(((void *)&tr->wh) + hdrlen, 0, sizeof(tr->wh) - hdrlen); + + /* Firmware length is the length of the fully formed "802.11 + * payload". That is, everything except for the 802.11 header. + * This includes all crypto material including the MIC. + */ + tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr) + tail_pad); +} + static inline void mwl_tx_encapsulate_frame(struct mwl_priv *priv, - struct sk_buff *skb, bool *ccmp); + struct sk_buff *skb, + struct ieee80211_key_conf *k_conf, + bool *ccmp) +{ + int head_pad = 0; + int data_pad = 0; + + /* Make sure the packet header is in the DMA header format (4-address + * without QoS), and add head & tail padding when HW crypto is enabled. + * + * We have the following trailer padding requirements: + * - WEP: 4 trailer bytes (ICV) + * - TKIP: 12 trailer bytes (8 MIC + 4 ICV) + * - CCMP: 8 trailer bytes (MIC) + */ + + if (k_conf) { + head_pad = k_conf->iv_len; + + switch (k_conf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + data_pad = 4; + break; + case WLAN_CIPHER_SUITE_TKIP: + data_pad = 12; + break; + case WLAN_CIPHER_SUITE_CCMP: + data_pad = 8; + *ccmp = true; + break; + } + } + + mwl_tx_add_dma_header(priv, skb, head_pad, data_pad); +} + static inline void mwl_tx_insert_ccmp_hdr(u8 *pccmp_hdr, - u8 key_id, u16 iv16, u32 iv32); -static inline int mwl_tx_tid_queue_mapping(u8 tid); -static inline void mwl_tx_count_packet(struct ieee80211_sta *sta, u8 tid); -static inline void mwl_tx_skbs(struct ieee80211_hw *hw); -/* static void mwl_tx_descriptor_dump(struct mwl_priv *priv); */ + 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; +} + +static inline int mwl_tx_tid_queue_mapping(u8 tid) +{ + BUG_ON(tid > 7); + + switch (tid) { + case 0: + case 3: + return IEEE80211_AC_BE; + case 1: + case 2: + return IEEE80211_AC_BK; + case 4: + case 5: + return IEEE80211_AC_VI; + case 6: + case 7: + return IEEE80211_AC_VO; + default: + break; + } + + return -1; +} + +static inline void mwl_tx_count_packet(struct ieee80211_sta *sta, u8 tid) +{ + struct mwl_sta *sta_info; + struct mwl_tx_info *tx_stats; + + BUG_ON(tid >= SYSADPT_MAX_TID); + + sta_info = mwl_dev_get_sta(sta); + + tx_stats = &sta_info->tx_stats[tid]; + + if (tx_stats->start_time == 0) + tx_stats->start_time = jiffies; + + /* reset the packet count after each second elapses. If the number of + * packets ever exceeds the ampdu_min_traffic threshold, we will allow + * an ampdu stream to be started. + */ + if (jiffies - tx_stats->start_time > HZ) { + tx_stats->pkts = 0; + tx_stats->start_time = 0; + } else { + tx_stats->pkts++; + } +} + +static inline bool mwl_tx_available(struct mwl_priv *priv, int desc_num) +{ + if (!priv->desc_data[desc_num].pnext_tx_desc) + return false; + + if (priv->desc_data[desc_num].pnext_tx_desc->status != + EAGLE_TXD_STATUS_IDLE) { + /* Interrupt F/W anyway */ + if (priv->desc_data[desc_num].pnext_tx_desc->status & + cpu_to_le32(EAGLE_TXD_STATUS_FW_OWNED)) + writel(MACREG_H2ARIC_BIT_PPA_READY, + priv->iobase1 + + MACREG_REG_H2A_INTERRUPT_EVENTS); + return false; + } + + return true; +} + +static inline void mwl_tx_skb(struct mwl_priv *priv, int desc_num, + struct sk_buff *tx_skb) +{ + struct ieee80211_tx_info *tx_info; + struct mwl_tx_ctrl *tx_ctrl; + struct mwl_tx_desc *tx_desc; + struct ieee80211_sta *sta; + struct mwl_vif *mwl_vif; + struct ieee80211_key_conf *k_conf; + bool ccmp = false; + struct mwl_dma_data *dma_data; + struct ieee80211_hdr *wh; + + 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; + k_conf = (struct ieee80211_key_conf *)tx_ctrl->k_conf; + + mwl_tx_encapsulate_frame(priv, tx_skb, k_conf, &ccmp); + + dma_data = (struct mwl_dma_data *)tx_skb->data; + wh = &dma_data->wh; + + if (ieee80211_is_data(wh->frame_control)) { + if (is_multicast_ether_addr(wh->addr1)) { + if (ccmp) { + mwl_tx_insert_ccmp_hdr(dma_data->data, + mwl_vif->keyidx, + mwl_vif->iv16, + mwl_vif->iv32); + INCREASE_IV(mwl_vif->iv16, mwl_vif->iv32); + } + } else { + if (ccmp) { + if (mwl_vif->is_sta) { + mwl_tx_insert_ccmp_hdr(dma_data->data, + mwl_vif->keyidx, + mwl_vif->iv16, + mwl_vif->iv32); + INCREASE_IV(mwl_vif->iv16, + mwl_vif->iv32); + } else { + struct mwl_sta *sta_info; + + sta_info = mwl_dev_get_sta(sta); + + mwl_tx_insert_ccmp_hdr(dma_data->data, + 0, + sta_info->iv16, + sta_info->iv32); + INCREASE_IV(sta_info->iv16, + sta_info->iv32); + } + } + } + } -/* PUBLIC FUNCTION DEFINITION -*/ + tx_desc = priv->desc_data[desc_num].pnext_tx_desc; + 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)); + 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->fw_desc_cnt[desc_num]++; +} + +static inline void mwl_tx_skbs(struct ieee80211_hw *hw) +{ + struct mwl_priv *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); + while (num--) { + while (skb_queue_len(&priv->txq[num]) > 0) { + if (mwl_tx_available(priv, num) == false) + break; + tx_skb = skb_dequeue(&priv->txq[num]); + mwl_tx_skb(priv, num, tx_skb); + } + } + spin_unlock_irqrestore(&priv->tx_desc_lock, flags); +} int mwl_tx_init(struct ieee80211_hw *hw) { struct mwl_priv *priv; int rc; - WLDBG_ENTER(DBG_LEVEL_3); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); skb_queue_head_init(&priv->delay_q); rc = mwl_tx_ring_alloc(priv); if (rc) { - WLDBG_ERROR(DBG_LEVEL_3, "allocating TX ring failed"); + wiphy_err(hw->wiphy, "allocating TX ring failed"); } else { rc = mwl_tx_ring_init(priv); if (rc) { mwl_tx_ring_free(priv); - WLDBG_ERROR(DBG_LEVEL_3, "initializing TX ring failed"); + wiphy_err(hw->wiphy, "initializing TX ring failed"); } } - WLDBG_EXIT(DBG_LEVEL_3); - return rc; } @@ -122,26 +474,21 @@ void mwl_tx_deinit(struct ieee80211_hw *hw) { struct mwl_priv *priv; - WLDBG_ENTER(DBG_LEVEL_3); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); skb_queue_purge(&priv->delay_q); mwl_tx_ring_cleanup(priv); mwl_tx_ring_free(priv); - - WLDBG_EXIT(DBG_LEVEL_3); } void mwl_tx_xmit(struct ieee80211_hw *hw, - int index, - struct ieee80211_sta *sta, - struct sk_buff *skb) + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct mwl_priv *priv; + int index; + struct ieee80211_sta *sta; struct ieee80211_tx_info *tx_info; struct mwl_vif *mwl_vif; struct ieee80211_hdr *wh; @@ -154,22 +501,17 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, bool mgmtframe = false; struct ieee80211_mgmt *mgmt; bool eapol_frame = false; - bool ccmp = false; - struct mwl_dma_data *dma_data; struct mwl_tx_ctrl *tx_ctrl; + struct ieee80211_key_conf *k_conf = NULL; - WLDBG_ENTER(DBG_LEVEL_3); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - BUG_ON(!skb); + index = skb_get_queue_mapping(skb); + sta = control->sta; wh = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_data_qos(wh->frame_control)) - qos = ENDIAN_SWAP16(*((u16 *)ieee80211_get_qos_ctl(wh))); + qos = *((u16 *)ieee80211_get_qos_ctl(wh)); else qos = 0; @@ -183,22 +525,16 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, mgmt = (struct ieee80211_mgmt *)skb->data; } - mwl_tx_encapsulate_frame(priv, skb, &ccmp); - - dma_data = (struct mwl_dma_data *)skb->data; - wh = &dma_data->wh; - tx_info = IEEE80211_SKB_CB(skb); - mwl_vif = MWL_VIF(tx_info->control.vif); + mwl_vif = mwl_dev_get_vif(tx_info->control.vif); if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - wh->seq_ctrl &= ENDIAN_SWAP16(IEEE80211_SCTL_FRAG); - wh->seq_ctrl |= ENDIAN_SWAP16(mwl_vif->seqno); + wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + wh->seq_ctrl |= cpu_to_le16(mwl_vif->seqno); mwl_vif->seqno += 0x10; } - /* Setup firmware control bit fields for each frame type. - */ + /* Setup firmware control bit fields for each frame type. */ xmitcontrol = 0; if (mgmtframe || ieee80211_is_ctl(wh->frame_control)) { @@ -214,37 +550,10 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, qos |= MWL_QOS_ACK_POLICY_NORMAL; } - if (is_multicast_ether_addr(wh->addr1)) { + if (is_multicast_ether_addr(wh->addr1)) xmitcontrol |= EAGLE_TXD_XMITCTRL_USE_MC_RATE; - if (ccmp) { - mwl_tx_insert_ccmp_hdr(dma_data->data, - mwl_vif->keyidx, - mwl_vif->iv16, - mwl_vif->iv32); - INCREASE_IV(mwl_vif->iv16, mwl_vif->iv32); - } - } else { - if (ccmp) { - if (mwl_vif->is_sta) { - mwl_tx_insert_ccmp_hdr(dma_data->data, - mwl_vif->keyidx, - mwl_vif->iv16, - mwl_vif->iv32); - INCREASE_IV(mwl_vif->iv16, - mwl_vif->iv32); - } else { - struct mwl_sta *sta_info = MWL_STA(sta); - - mwl_tx_insert_ccmp_hdr(dma_data->data, - 0, - sta_info->iv16, - sta_info->iv32); - INCREASE_IV(sta_info->iv16, - sta_info->iv32); - } - } - } + k_conf = tx_info->control.hw_key; } /* Queue ADDBA request in the respective data queue. While setting up @@ -262,20 +571,21 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ)) { u16 capab = - ENDIAN_SWAP16(mgmt->u.action.u.addba_req.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); } } - txpriority = SYSADPT_TX_WMM_QUEUES - index - 1; + index = SYSADPT_TX_WMM_QUEUES - index - 1; + txpriority = index; if (sta && sta->ht_cap.ht_supported && !eapol_frame && ieee80211_is_data_qos(wh->frame_control)) { tid = qos & 0xf; mwl_tx_count_packet(sta, tid); - SPIN_LOCK(&priv->locks.stream_lock); + spin_lock(&priv->stream_lock); stream = mwl_fwcmd_lookup_stream(hw, sta->addr, tid); if (stream) { @@ -306,9 +616,9 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, * mac80211 queues our packets for us in this * case, so this is really just a safety check. */ - WLDBG_WARNING(DBG_LEVEL_3, - "can't send packet during ADDBA"); - SPIN_UNLOCK(&priv->locks.stream_lock); + wiphy_warn(hw->wiphy, + "can't send packet during ADDBA"); + spin_unlock(&priv->stream_lock); dev_kfree_skb_any(skb); return; } @@ -326,7 +636,7 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, } } - SPIN_UNLOCK(&priv->locks.stream_lock); + spin_unlock(&priv->stream_lock); } else { qos &= ~MWL_QOS_ACK_POLICY_MASK; qos |= MWL_QOS_ACK_POLICY_NORMAL; @@ -337,28 +647,24 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, tx_ctrl->qos_ctrl = qos; tx_ctrl->type = (mgmtframe ? IEEE_TYPE_MANAGEMENT : IEEE_TYPE_DATA); tx_ctrl->xmit_control = xmitcontrol; - tx_ctrl->sta_info = (u8 *)sta; - tx_ctrl->ccmp = ccmp; + tx_ctrl->sta = (void *)sta; + tx_ctrl->vif = (void *)mwl_vif; + tx_ctrl->k_conf = (void *)k_conf; - if (skb_queue_len(&priv->txq[index]) > priv->txq_limit) { + if (skb_queue_len(&priv->txq[index]) > priv->txq_limit) dev_kfree_skb_any(skb); - WLDBG_INFO(DBG_LEVEL_3, "queue len > limit"); - } else { + else skb_queue_tail(&priv->txq[index], skb); - } mwl_tx_skbs(hw); - /* Initiate the ampdu session here - */ + /* Initiate the ampdu session here */ if (start_ba_session) { - SPIN_LOCK(&priv->locks.stream_lock); + spin_lock(&priv->stream_lock); if (mwl_fwcmd_start_stream(hw, stream)) mwl_fwcmd_remove_stream(hw, stream); - SPIN_UNLOCK(&priv->locks.stream_lock); + spin_unlock(&priv->stream_lock); } - - WLDBG_EXIT(DBG_LEVEL_3); } void mwl_tx_done(unsigned long data) @@ -368,34 +674,29 @@ void mwl_tx_done(unsigned long data) unsigned long flags; int num; struct sk_buff *done_skb; - struct mwl_rate_info rate_info; + u32 rate, format, bandwidth, short_gi, rate_id; struct mwl_dma_data *tr; struct ieee80211_tx_info *info; int hdrlen; - WLDBG_ENTER(DBG_LEVEL_3); - - BUG_ON(!hw); priv = hw->priv; - BUG_ON(!priv); - - SPIN_LOCK_IRQSAVE(&priv->locks.xmit_lock, flags); + spin_lock_irqsave(&priv->tx_desc_lock, flags); for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { while (STALE_TXD(num) && (STALE_TXD(num)->status & - ENDIAN_SWAP32(EAGLE_TXD_STATUS_OK)) && + cpu_to_le32(EAGLE_TXD_STATUS_OK)) && (!(STALE_TXD(num)->status & - ENDIAN_SWAP32(EAGLE_TXD_STATUS_FW_OWNED)))) { + cpu_to_le32(EAGLE_TXD_STATUS_FW_OWNED)))) { pci_unmap_single(priv->pdev, - ENDIAN_SWAP32(STALE_TXD(num)->pkt_ptr), + le32_to_cpu(STALE_TXD(num)->pkt_ptr), STALE_TXD(num)->psk_buff->len, PCI_DMA_TODEVICE); done_skb = STALE_TXD(num)->psk_buff; - rate_info = STALE_TXD(num)->rate_info; + 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 = - ENDIAN_SWAP32(EAGLE_TXD_STATUS_IDLE); + cpu_to_le32(EAGLE_TXD_STATUS_IDLE); priv->fw_desc_cnt[num]--; STALE_TXD(num) = STALE_TXD(num)->pnext; wmb(); /* memory barrier */ @@ -416,29 +717,36 @@ void mwl_tx_done(unsigned long data) dev_kfree_skb_any( skb_dequeue(&priv->delay_q)); - /* Prepare rate information - */ - info->status.rates[0].idx = - rate_info.rate_id_mcs; - if (rate_info.format == TX_RATE_FORMAT_LEGACY) { + /* Prepare rate information */ + format = rate & MWL_TX_RATE_FORMAT_MASK; + bandwidth = + (rate & MWL_TX_RATE_BANDWIDTH_MASK) >> + MWL_TX_RATE_BANDWIDTH_SHIFT; + short_gi = (rate & MWL_TX_RATE_SHORTGI_MASK) >> + MWL_TX_RATE_SHORTGI_SHIFT; + rate_id = (rate & MWL_TX_RATE_RATEIDMCS_MASK) >> + MWL_TX_RATE_RATEIDMCS_SHIFT; + + info->status.rates[0].idx = rate_id; + if (format == TX_RATE_FORMAT_LEGACY) { if (hw->conf.chandef.chan->hw_value > BAND_24_CHANNEL_NUM) { info->status.rates[0].idx -= 5; } } - if (rate_info.format == TX_RATE_FORMAT_11N) + if (format == TX_RATE_FORMAT_11N) info->status.rates[0].flags |= IEEE80211_TX_RC_MCS; - if (rate_info.format == TX_RATE_FORMAT_11AC) + if (format == TX_RATE_FORMAT_11AC) info->status.rates[0].flags |= IEEE80211_TX_RC_VHT_MCS; - if (rate_info.bandwidth == TX_RATE_BANDWIDTH_40) + if (bandwidth == TX_RATE_BANDWIDTH_40) info->status.rates[0].flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (rate_info.bandwidth == TX_RATE_BANDWIDTH_80) + if (bandwidth == TX_RATE_BANDWIDTH_80) info->status.rates[0].flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; - if (rate_info.short_gi == TX_RATE_INFO_SHORT_GI) + if (short_gi == TX_RATE_INFO_SHORT_GI) info->status.rates[0].flags |= IEEE80211_TX_RC_SHORT_GI; info->status.rates[0].count = 1; @@ -446,8 +754,7 @@ void mwl_tx_done(unsigned long data) info->status.rates[1].idx = -1; } - /* Remove H/W dma header - */ + /* Remove H/W dma header */ hdrlen = ieee80211_hdrlen(tr->wh.frame_control); memmove(tr->data - hdrlen, &tr->wh, hdrlen); skb_pull(done_skb, sizeof(*tr) - hdrlen); @@ -456,8 +763,7 @@ void mwl_tx_done(unsigned long data) ieee80211_tx_status(hw, done_skb); } } - - SPIN_UNLOCK_IRQRESTORE(&priv->locks.xmit_lock, flags); + spin_unlock_irqrestore(&priv->tx_desc_lock, flags); if (priv->irq != -1) { u32 status; @@ -471,422 +777,4 @@ void mwl_tx_done(unsigned long data) } priv->is_tx_schedule = false; - - WLDBG_EXIT(DBG_LEVEL_3); -} - -/* PRIVATE FUNCTION DEFINITION -*/ - -static int mwl_tx_ring_alloc(struct mwl_priv *priv) -{ - int num; - u8 *mem; - - WLDBG_ENTER(DBG_LEVEL_3); - - BUG_ON(!priv); - - 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); - - if (!mem) { - WLDBG_ERROR(DBG_LEVEL_3, "can not alloc mem"); - WLDBG_EXIT_INFO(DBG_LEVEL_3, "no memory"); - return -ENOMEM; - } - - for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { - WLDBG_INFO(DBG_LEVEL_3, "allocating %i (0x%x) bytes", - MAX_NUM_TX_RING_BYTES, MAX_NUM_TX_RING_BYTES); - - priv->desc_data[num].ptx_ring = (struct mwl_tx_desc *) - (mem + num * MAX_NUM_TX_RING_BYTES); - - priv->desc_data[num].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, - MAX_NUM_TX_RING_BYTES); - - WLDBG_INFO(DBG_LEVEL_3, "TX ring vaddr: 0x%x paddr: 0x%x", - priv->desc_data[num].ptx_ring, - priv->desc_data[num].pphys_tx_ring); - } - - WLDBG_EXIT(DBG_LEVEL_3); - - return 0; -} - -static int mwl_tx_ring_init(struct mwl_priv *priv) -{ - int curr_desc; - struct mwl_desc_data *desc; - int num; - - WLDBG_ENTER(DBG_LEVEL_3); - - BUG_ON(!priv); - - for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { - skb_queue_head_init(&priv->txq[num]); - priv->fw_desc_cnt[num] = 0; - - desc = &priv->desc_data[num]; - - if (desc->ptx_ring) { - WLDBG_INFO(DBG_LEVEL_3, "initializing %i descriptors", - SYSADPT_MAX_NUM_TX_DESC); - - for (curr_desc = 0; curr_desc < SYSADPT_MAX_NUM_TX_DESC; - curr_desc++) { - CURR_TXD(num).status = - ENDIAN_SWAP32(EAGLE_TXD_STATUS_IDLE); - CURR_TXD(num).pnext = &NEXT_TXD(num); - CURR_TXD(num).pphys_next = - ENDIAN_SWAP32((u32)desc->pphys_tx_ring + - ((curr_desc + 1) * - sizeof(struct mwl_tx_desc))); - WLDBG_INFO(DBG_LEVEL_3, - "txdesc: %i 0x%x (%i) 0x%p 0x%x", - curr_desc, EAGLE_TXD_STATUS_IDLE, - EAGLE_TXD_STATUS_IDLE, - CURR_TXD(num).pnext, - ENDIAN_SWAP32( - CURR_TXD(num).pphys_next)); - } - LAST_TXD(num).pnext = &FIRST_TXD(num); - LAST_TXD(num).pphys_next = - ENDIAN_SWAP32((u32)desc->pphys_tx_ring); - desc->pstale_tx_desc = &FIRST_TXD(num); - desc->pnext_tx_desc = &FIRST_TXD(num); - - WLDBG_INFO(DBG_LEVEL_3, - "last txdesc vnext: 0x%p 0x%x 0x%x 0x%x", - LAST_TXD(num).pnext, - ENDIAN_SWAP32(LAST_TXD(num).pphys_next), - desc->pstale_tx_desc, desc->pnext_tx_desc); - } else { - WLDBG_ERROR(DBG_LEVEL_3, "no valid TX mem"); - WLDBG_EXIT_INFO(DBG_LEVEL_3, "no valid memory"); - return -ENOMEM; - } - } - - WLDBG_EXIT(DBG_LEVEL_3); - - return 0; -} - -static void mwl_tx_ring_cleanup(struct mwl_priv *priv) -{ - int cleaned_tx_desc = 0; - int curr_desc; - int num; - - WLDBG_ENTER(DBG_LEVEL_3); - - BUG_ON(!priv); - - 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) - continue; - - WLDBG_INFO(DBG_LEVEL_3, - "unmapped and free'd %i 0x%p 0x%x", - curr_desc, - CURR_TXD(num).psk_buff->data, - ENDIAN_SWAP32( - CURR_TXD(num).pkt_ptr)); - pci_unmap_single(priv->pdev, - ENDIAN_SWAP32( - CURR_TXD(num).pkt_ptr), - CURR_TXD(num).psk_buff->len, - PCI_DMA_TODEVICE); - dev_kfree_skb_any(CURR_TXD(num).psk_buff); - CURR_TXD(num).status = - ENDIAN_SWAP32(EAGLE_TXD_STATUS_IDLE); - CURR_TXD(num).psk_buff = NULL; - CURR_TXD(num).pkt_ptr = 0; - CURR_TXD(num).pkt_len = 0; - cleaned_tx_desc++; - } - } - } - - WLDBG_EXIT_INFO(DBG_LEVEL_3, "cleaned %i TX descr", cleaned_tx_desc); -} - -static void mwl_tx_ring_free(struct mwl_priv *priv) -{ - int num; - - WLDBG_ENTER(DBG_LEVEL_3); - - BUG_ON(!priv); - - if (priv->desc_data[0].ptx_ring) { - 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); - } - - 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; - } - - WLDBG_EXIT(DBG_LEVEL_3); -} - -static inline void mwl_tx_add_dma_header(struct mwl_priv *priv, - struct sk_buff *skb, - int head_pad, - int tail_pad) -{ - struct ieee80211_hdr *wh; - int hdrlen; - int reqd_hdrlen; - struct mwl_dma_data *tr; - - /* Add a firmware DMA header; the firmware requires that we - * present a 2-byte payload length followed by a 4-address - * header (without QoS field), followed (optionally) by any - * WEP/ExtIV header (but only filled in for CCMP). - */ - wh = (struct ieee80211_hdr *)skb->data; - - hdrlen = ieee80211_hdrlen(wh->frame_control); - - reqd_hdrlen = sizeof(*tr) + head_pad; - - if (hdrlen != reqd_hdrlen) - skb_push(skb, reqd_hdrlen - hdrlen); - - if (ieee80211_is_data_qos(wh->frame_control)) - hdrlen -= IEEE80211_QOS_CTL_LEN; - - tr = (struct mwl_dma_data *)skb->data; - - if (wh != &tr->wh) - memmove(&tr->wh, wh, hdrlen); - - if (hdrlen != sizeof(tr->wh)) - memset(((void *)&tr->wh) + hdrlen, 0, sizeof(tr->wh) - hdrlen); - - /* Firmware length is the length of the fully formed "802.11 - * payload". That is, everything except for the 802.11 header. - * This includes all crypto material including the MIC. - */ - tr->fwlen = ENDIAN_SWAP16(skb->len - sizeof(*tr) + tail_pad); -} - -static inline void mwl_tx_encapsulate_frame(struct mwl_priv *priv, - struct sk_buff *skb, bool *ccmp) -{ - struct ieee80211_hdr *wh; - struct ieee80211_tx_info *tx_info; - struct ieee80211_key_conf *key_conf; - int data_pad; - int head_pad = 0; - - wh = (struct ieee80211_hdr *)skb->data; - - tx_info = IEEE80211_SKB_CB(skb); - - key_conf = NULL; - - if (ieee80211_is_data(wh->frame_control)) - key_conf = tx_info->control.hw_key; - - /* Make sure the packet header is in the DMA header format (4-address - * without QoS), and add head & tail padding when HW crypto is enabled. - * - * We have the following trailer padding requirements: - * - WEP: 4 trailer bytes (ICV) - * - TKIP: 12 trailer bytes (8 MIC + 4 ICV) - * - CCMP: 8 trailer bytes (MIC) - */ - data_pad = 0; - - if (key_conf) { - head_pad = key_conf->iv_len; - - switch (key_conf->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - data_pad = 4; - break; - case WLAN_CIPHER_SUITE_TKIP: - data_pad = 12; - break; - case WLAN_CIPHER_SUITE_CCMP: - data_pad = 8; - *ccmp = true; - break; - } - } - - mwl_tx_add_dma_header(priv, skb, head_pad, data_pad); -} - -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; -} - -static inline int mwl_tx_tid_queue_mapping(u8 tid) -{ - BUG_ON(tid > 7); - - switch (tid) { - case 0: - case 3: - return IEEE80211_AC_BE; - case 1: - case 2: - return IEEE80211_AC_BK; - case 4: - case 5: - return IEEE80211_AC_VI; - case 6: - case 7: - return IEEE80211_AC_VO; - default: - break; - } - - return -1; -} - -static inline void mwl_tx_count_packet(struct ieee80211_sta *sta, u8 tid) -{ - struct mwl_sta *sta_info = MWL_STA(sta); - struct mwl_tx_info *tx_stats; - - BUG_ON(!sta); - sta_info = MWL_STA(sta); - BUG_ON(!sta_info); - - BUG_ON(tid >= SYSADPT_MAX_TID); - - tx_stats = &sta_info->tx_stats[tid]; - - if (tx_stats->start_time == 0) - tx_stats->start_time = jiffies; - - /* reset the packet count after each second elapses. If the number of - * packets ever exceeds the ampdu_min_traffic threshold, we will allow - * an ampdu stream to be started. - */ - if (jiffies - tx_stats->start_time > HZ) { - tx_stats->pkts = 0; - tx_stats->start_time = 0; - } else { - tx_stats->pkts++; - } -} - -static inline void mwl_tx_skbs(struct ieee80211_hw *hw) -{ - struct mwl_priv *priv; - unsigned long flags; - int num = SYSADPT_NUM_OF_DESC_DATA; - struct mwl_desc_data *desc; - struct sk_buff *tx_skb; - struct ieee80211_tx_info *tx_info; - struct mwl_tx_ctrl *tx_ctrl; - - WLDBG_ENTER(DBG_LEVEL_3); - - BUG_ON(!hw); - priv = hw->priv; - BUG_ON(!priv); - - SPIN_LOCK_IRQSAVE(&priv->locks.xmit_lock, flags); - - while (num--) { - while (skb_queue_len(&priv->txq[num]) > 0) { - desc = &priv->desc_data[num]; - - if (!desc->pnext_tx_desc) - break; - - /* Only queue to tx desc when Status is 0 (not when 0x1 - * or 0x80000000). If we queue even when Status==0x1 - * (DMA'd to fw but txdone haven't change Status to 0), - * mismatch of fwDescCnt with actual number of desc - * with Status==0 could happen. E.g fwDescCnt 256 - * instead of 255 when there is one desc with Status==0. - * This can cause Tx to stall when fwDescCnt==256 and - * pStaleTxDesc->Status==0. - */ - if (desc->pnext_tx_desc->status != - EAGLE_TXD_STATUS_IDLE) { - /* Interrupt F/W anyway - */ - if (desc->pnext_tx_desc->status & - ENDIAN_SWAP32(EAGLE_TXD_STATUS_FW_OWNED)) - writel(MACREG_H2ARIC_BIT_PPA_READY, - priv->iobase1 + - MACREG_REG_H2A_INTERRUPT_EVENTS); - break; - } - - tx_skb = skb_dequeue(&priv->txq[num]); - - BUG_ON(!tx_skb); - - tx_info = IEEE80211_SKB_CB(tx_skb); - tx_ctrl = (struct mwl_tx_ctrl *)&tx_info->status; - - desc->pnext_tx_desc->tx_priority = tx_ctrl->tx_priority; - desc->pnext_tx_desc->qos_ctrl = tx_ctrl->qos_ctrl; - desc->pnext_tx_desc->psk_buff = tx_skb; - desc->pnext_tx_desc->pkt_len = - ENDIAN_SWAP16(tx_skb->len); - desc->pnext_tx_desc->packet_info = 0; - desc->pnext_tx_desc->data_rate = 0; - desc->pnext_tx_desc->sta_info = tx_ctrl->sta_info; - desc->pnext_tx_desc->type = tx_ctrl->type; - desc->pnext_tx_desc->xmit_control = - tx_ctrl->xmit_control; - desc->pnext_tx_desc->sap_pkt_info = 0; - desc->pnext_tx_desc->pkt_ptr = - ENDIAN_SWAP32(pci_map_single(priv->pdev, - tx_skb->data, - tx_skb->len, - PCI_DMA_TODEVICE)); - desc->pnext_tx_desc->status = - ENDIAN_SWAP32(EAGLE_TXD_STATUS_FW_OWNED); - desc->pnext_tx_desc = desc->pnext_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->fw_desc_cnt[num]++; - } - } - - SPIN_UNLOCK_IRQRESTORE(&priv->locks.xmit_lock, flags); - - WLDBG_EXIT(DBG_LEVEL_3); } @@ -0,0 +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. + */ + +/* Description: This file defines transmit related functions. + */ + +#ifndef _mwl_tx_h_ +#define _mwl_tx_h_ + +int mwl_tx_init(struct ieee80211_hw *hw); +void mwl_tx_deinit(struct ieee80211_hw *hw); +void mwl_tx_xmit(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb); +void mwl_tx_done(unsigned long data); + +#endif /* _mwl_tx_h_ */ |