diff options
192 files changed, 7185 insertions, 5919 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 8e0de9a0586..11b41fd40c2 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -188,7 +188,7 @@ config BT_MRVL  	  The core driver to support Marvell Bluetooth devices.  	  This driver is required if you want to support -	  Marvell Bluetooth devices, such as 8688. +	  Marvell Bluetooth devices, such as 8688/8787.  	  Say Y here to compile Marvell Bluetooth driver  	  into the kernel or say M to compile it as module. @@ -201,7 +201,7 @@ config BT_MRVL_SDIO  	  The driver for Marvell Bluetooth chipsets with SDIO interface.  	  This driver is required if you want to use Marvell Bluetooth -	  devices with SDIO interface. Currently only SD8688 chipset is +	  devices with SDIO interface. Currently SD8688/SD8787 chipsets are  	  supported.  	  Say Y here to compile support for Marvell BT-over-SDIO driver diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 5577ed656e2..695d4414bd4 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -138,9 +138,6 @@ static int ath3k_load_firmware(struct usb_device *udev,  		count -= size;  	} -	kfree(send_buf); -	return 0; -  error:  	kfree(send_buf);  	return err; diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index dcc2a6ec23f..7f521d4ac65 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -49,15 +49,59 @@  static u8 user_rmmod;  static u8 sdio_ireg; +static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = { +	.cfg = 0x03, +	.host_int_mask = 0x04, +	.host_intstatus = 0x05, +	.card_status = 0x20, +	.sq_read_base_addr_a0 = 0x10, +	.sq_read_base_addr_a1 = 0x11, +	.card_fw_status0 = 0x40, +	.card_fw_status1 = 0x41, +	.card_rx_len = 0x42, +	.card_rx_unit = 0x43, +	.io_port_0 = 0x00, +	.io_port_1 = 0x01, +	.io_port_2 = 0x02, +}; +static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = { +	.cfg = 0x00, +	.host_int_mask = 0x02, +	.host_intstatus = 0x03, +	.card_status = 0x30, +	.sq_read_base_addr_a0 = 0x40, +	.sq_read_base_addr_a1 = 0x41, +	.card_revision = 0x5c, +	.card_fw_status0 = 0x60, +	.card_fw_status1 = 0x61, +	.card_rx_len = 0x62, +	.card_rx_unit = 0x63, +	.io_port_0 = 0x78, +	.io_port_1 = 0x79, +	.io_port_2 = 0x7a, +}; +  static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {  	.helper		= "sd8688_helper.bin",  	.firmware	= "sd8688.bin", +	.reg		= &btmrvl_reg_8688, +	.sd_blksz_fw_dl	= 64, +}; + +static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { +	.helper		= NULL, +	.firmware	= "mrvl/sd8787_uapsta.bin", +	.reg		= &btmrvl_reg_8787, +	.sd_blksz_fw_dl	= 256,  };  static const struct sdio_device_id btmrvl_sdio_ids[] = {  	/* Marvell SD8688 Bluetooth device */  	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),  			.driver_data = (unsigned long) &btmrvl_sdio_sd6888 }, +	/* Marvell SD8787 Bluetooth device */ +	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), +			.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },  	{ }	/* Terminating entry */  }; @@ -69,7 +113,7 @@ static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)  	u8 reg;  	int ret; -	reg = sdio_readb(card->func, CARD_RX_UNIT_REG, &ret); +	reg = sdio_readb(card->func, card->reg->card_rx_unit, &ret);  	if (!ret)  		card->rx_unit = reg; @@ -83,11 +127,11 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)  	*dat = 0; -	fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret); +	fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);  	if (ret)  		return -EIO; -	fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret); +	fws1 = sdio_readb(card->func, card->reg->card_fw_status1, &ret);  	if (ret)  		return -EIO; @@ -101,7 +145,7 @@ static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)  	u8 reg;  	int ret; -	reg = sdio_readb(card->func, CARD_RX_LEN_REG, &ret); +	reg = sdio_readb(card->func, card->reg->card_rx_len, &ret);  	if (!ret)  		*dat = (u16) reg << card->rx_unit; @@ -113,7 +157,7 @@ static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,  {  	int ret; -	sdio_writeb(card->func, mask, HOST_INT_MASK_REG, &ret); +	sdio_writeb(card->func, mask, card->reg->host_int_mask, &ret);  	if (ret) {  		BT_ERR("Unable to enable the host interrupt!");  		ret = -EIO; @@ -128,13 +172,13 @@ static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,  	u8 host_int_mask;  	int ret; -	host_int_mask = sdio_readb(card->func, HOST_INT_MASK_REG, &ret); +	host_int_mask = sdio_readb(card->func, card->reg->host_int_mask, &ret);  	if (ret)  		return -EIO;  	host_int_mask &= ~mask; -	sdio_writeb(card->func, host_int_mask, HOST_INT_MASK_REG, &ret); +	sdio_writeb(card->func, host_int_mask, card->reg->host_int_mask, &ret);  	if (ret < 0) {  		BT_ERR("Unable to disable the host interrupt!");  		return -EIO; @@ -150,7 +194,7 @@ static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)  	int ret;  	for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) { -		status = sdio_readb(card->func, CARD_STATUS_REG, &ret); +		status = sdio_readb(card->func, card->reg->card_status,	&ret);  		if (ret)  			goto failed;  		if ((status & bits) == bits) @@ -299,7 +343,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)  	u8 base0, base1;  	void *tmpfwbuf = NULL;  	u8 *fwbuf; -	u16 len; +	u16 len, blksz_dl = card->sd_blksz_fw_dl;  	int txlen = 0, tx_blocks = 0, count = 0;  	ret = request_firmware(&fw_firmware, card->firmware, @@ -345,7 +389,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)  		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {  			base0 = sdio_readb(card->func, -					SQ_READ_BASE_ADDRESS_A0_REG, &ret); +					card->reg->sq_read_base_addr_a0, &ret);  			if (ret) {  				BT_ERR("BASE0 register read failed:"  					" base0 = 0x%04X(%d)." @@ -355,7 +399,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)  				goto done;  			}  			base1 = sdio_readb(card->func, -					SQ_READ_BASE_ADDRESS_A1_REG, &ret); +					card->reg->sq_read_base_addr_a1, &ret);  			if (ret) {  				BT_ERR("BASE1 register read failed:"  					" base1 = 0x%04X(%d)." @@ -403,20 +447,19 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)  			if (firmwarelen - offset < txlen)  				txlen = firmwarelen - offset; -			tx_blocks = -			    (txlen + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE; +			tx_blocks = (txlen + blksz_dl - 1) / blksz_dl;  			memcpy(fwbuf, &firmware[offset], txlen);  		}  		ret = sdio_writesb(card->func, card->ioport, fwbuf, -					tx_blocks * SDIO_BLOCK_SIZE); +						tx_blocks * blksz_dl);  		if (ret < 0) {  			BT_ERR("FW download, writesb(%d) failed @%d",  							count, offset); -			sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG, -									&ret); +			sdio_writeb(card->func, HOST_CMD53_FIN, +						card->reg->cfg, &ret);  			if (ret)  				BT_ERR("writeb failed (CFG)");  		} @@ -597,7 +640,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)  	priv = card->priv; -	ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret); +	ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);  	if (ret) {  		BT_ERR("sdio_readb: read int status register failed");  		return; @@ -613,7 +656,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)  		sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |  					UP_LD_HOST_INT_STATUS), -				HOST_INTSTATUS_REG, &ret); +				card->reg->host_intstatus, &ret);  		if (ret) {  			BT_ERR("sdio_writeb: clear int status register failed");  			return; @@ -664,7 +707,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)  		goto release_irq;  	} -	reg = sdio_readb(func, IO_PORT_0_REG, &ret); +	reg = sdio_readb(func, card->reg->io_port_0, &ret);  	if (ret < 0) {  		ret = -EIO;  		goto release_irq; @@ -672,7 +715,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)  	card->ioport = reg; -	reg = sdio_readb(func, IO_PORT_1_REG, &ret); +	reg = sdio_readb(func, card->reg->io_port_1, &ret);  	if (ret < 0) {  		ret = -EIO;  		goto release_irq; @@ -680,7 +723,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)  	card->ioport |= (reg << 8); -	reg = sdio_readb(func, IO_PORT_2_REG, &ret); +	reg = sdio_readb(func, card->reg->io_port_2, &ret);  	if (ret < 0) {  		ret = -EIO;  		goto release_irq; @@ -815,6 +858,8 @@ exit:  static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)  {  	int ret = 0; +	u8 fws0; +	int pollnum = MAX_POLL_TRIES;  	if (!card || !card->func) {  		BT_ERR("card or function is NULL!"); @@ -827,20 +872,36 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)  		goto done;  	} -	ret = btmrvl_sdio_download_helper(card); +	/* Check if other function driver is downloading the firmware */ +	fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);  	if (ret) { -		BT_ERR("Failed to download helper!"); +		BT_ERR("Failed to read FW downloading status!");  		ret = -EIO;  		goto done;  	} +	if (fws0) { +		BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0); -	if (btmrvl_sdio_download_fw_w_helper(card)) { -		BT_ERR("Failed to download firmware!"); -		ret = -EIO; -		goto done; +		/* Give other function more time to download the firmware */ +		pollnum *= 10; +	} else { +		if (card->helper) { +			ret = btmrvl_sdio_download_helper(card); +			if (ret) { +				BT_ERR("Failed to download helper!"); +				ret = -EIO; +				goto done; +			} +		} + +		if (btmrvl_sdio_download_fw_w_helper(card)) { +			BT_ERR("Failed to download firmware!"); +			ret = -EIO; +			goto done; +		}  	} -	if (btmrvl_sdio_verify_fw_download(card, MAX_POLL_TRIES)) { +	if (btmrvl_sdio_verify_fw_download(card, pollnum)) {  		BT_ERR("FW failed to be active in time!");  		ret = -ETIMEDOUT;  		goto done; @@ -864,7 +925,7 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)  	sdio_claim_host(card->func); -	sdio_writeb(card->func, HOST_POWER_UP, CONFIG_REG, &ret); +	sdio_writeb(card->func, HOST_POWER_UP, card->reg->cfg, &ret);  	sdio_release_host(card->func); @@ -893,8 +954,10 @@ static int btmrvl_sdio_probe(struct sdio_func *func,  	if (id->driver_data) {  		struct btmrvl_sdio_device *data = (void *) id->driver_data; -		card->helper   = data->helper; +		card->helper = data->helper;  		card->firmware = data->firmware; +		card->reg = data->reg; +		card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;  	}  	if (btmrvl_sdio_register_dev(card) < 0) { @@ -1011,3 +1074,4 @@ MODULE_VERSION(VERSION);  MODULE_LICENSE("GPL v2");  MODULE_FIRMWARE("sd8688_helper.bin");  MODULE_FIRMWARE("sd8688.bin"); +MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h index 27329f107e5..43d35a609ca 100644 --- a/drivers/bluetooth/btmrvl_sdio.h +++ b/drivers/bluetooth/btmrvl_sdio.h @@ -47,44 +47,46 @@  /* Max retry number of CMD53 write */  #define MAX_WRITE_IOMEM_RETRY		2 -/* Host Control Registers */ -#define IO_PORT_0_REG			0x00 -#define IO_PORT_1_REG			0x01 -#define IO_PORT_2_REG			0x02 +/* register bitmasks */ +#define HOST_POWER_UP				BIT(1) +#define HOST_CMD53_FIN				BIT(2) -#define CONFIG_REG			0x03 -#define HOST_POWER_UP			BIT(1) -#define HOST_CMD53_FIN			BIT(2) +#define HIM_DISABLE				0xff +#define HIM_ENABLE				(BIT(0) | BIT(1)) -#define HOST_INT_MASK_REG		0x04 -#define HIM_DISABLE			0xff -#define HIM_ENABLE			(BIT(0) | BIT(1)) +#define UP_LD_HOST_INT_STATUS			BIT(0) +#define DN_LD_HOST_INT_STATUS			BIT(1) -#define HOST_INTSTATUS_REG		0x05 -#define UP_LD_HOST_INT_STATUS		BIT(0) -#define DN_LD_HOST_INT_STATUS		BIT(1) +#define DN_LD_CARD_RDY				BIT(0) +#define CARD_IO_READY				BIT(3) -/* Card Control Registers */ -#define SQ_READ_BASE_ADDRESS_A0_REG  	0x10 -#define SQ_READ_BASE_ADDRESS_A1_REG  	0x11 +#define FIRMWARE_READY				0xfedc -#define CARD_STATUS_REG              	0x20 -#define DN_LD_CARD_RDY               	BIT(0) -#define CARD_IO_READY              	BIT(3) - -#define CARD_FW_STATUS0_REG		0x40 -#define CARD_FW_STATUS1_REG		0x41 -#define FIRMWARE_READY			0xfedc - -#define CARD_RX_LEN_REG			0x42 -#define CARD_RX_UNIT_REG		0x43 +struct btmrvl_sdio_card_reg { +	u8 cfg; +	u8 host_int_mask; +	u8 host_intstatus; +	u8 card_status; +	u8 sq_read_base_addr_a0; +	u8 sq_read_base_addr_a1; +	u8 card_revision; +	u8 card_fw_status0; +	u8 card_fw_status1; +	u8 card_rx_len; +	u8 card_rx_unit; +	u8 io_port_0; +	u8 io_port_1; +	u8 io_port_2; +};  struct btmrvl_sdio_card {  	struct sdio_func *func;  	u32 ioport;  	const char *helper;  	const char *firmware; +	const struct btmrvl_sdio_card_reg *reg; +	u16 sd_blksz_fw_dl;  	u8 rx_unit;  	struct btmrvl_private *priv;  }; @@ -92,6 +94,8 @@ struct btmrvl_sdio_card {  struct btmrvl_sdio_device {  	const char *helper;  	const char *firmware; +	const struct btmrvl_sdio_card_reg *reg; +	u16 sd_blksz_fw_dl;  }; diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c index bd34406faaa..4093935ddf4 100644 --- a/drivers/bluetooth/hci_ath.c +++ b/drivers/bluetooth/hci_ath.c @@ -201,8 +201,13 @@ static struct sk_buff *ath_dequeue(struct hci_uart *hu)  /* Recv data */  static int ath_recv(struct hci_uart *hu, void *data, int count)  { -	if (hci_recv_stream_fragment(hu->hdev, data, count) < 0) +	int ret; + +	ret = hci_recv_stream_fragment(hu->hdev, data, count); +	if (ret < 0) {  		BT_ERR("Frame Reassembly Failed"); +		return ret; +	}  	return count;  } diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index 7b8ad93e2c3..2fcd8b387d6 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c @@ -151,8 +151,13 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)  /* Recv data */  static int h4_recv(struct hci_uart *hu, void *data, int count)  { -	if (hci_recv_stream_fragment(hu->hdev, data, count) < 0) +	int ret; + +	ret = hci_recv_stream_fragment(hu->hdev, data, count); +	if (ret < 0) {  		BT_ERR("Frame Reassembly Failed"); +		return ret; +	}  	return count;  } diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 48ad2a7ab08..320f71803a2 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -359,6 +359,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)   */  static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)  { +	int ret;  	struct hci_uart *hu = (void *)tty->disc_data;  	if (!hu || tty != hu->tty) @@ -368,8 +369,9 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f  		return;  	spin_lock(&hu->rx_lock); -	hu->proto->recv(hu, (void *) data, count); -	hu->hdev->stat.byte_rx += count; +	ret = hu->proto->recv(hu, (void *) data, count); +	if (ret > 0) +		hu->hdev->stat.byte_rx += count;  	spin_unlock(&hu->rx_lock);  	tty_unthrottle(tty); diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 6d7105b7e8f..7cf4317a2a8 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -123,14 +123,7 @@ struct ath_ops {  };  struct ath_common; - -struct ath_bus_ops { -	enum ath_bus_type ath_bus_type; -	void (*read_cachesize)(struct ath_common *common, int *csz); -	bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); -	void (*bt_coex_prep)(struct ath_common *common); -	void (*extn_synch_en)(struct ath_common *common); -}; +struct ath_bus_ops;  struct ath_common {  	void *ah; diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index 82324e98efe..ea998278155 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -18,6 +18,7 @@  #include <linux/nl80211.h>  #include <linux/platform_device.h> +#include <linux/etherdevice.h>  #include <ar231x_platform.h>  #include "ath5k.h"  #include "debug.h" @@ -62,10 +63,27 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)  	return 0;  } +static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) +{ +	struct ath5k_softc *sc = ah->ah_sc; +	struct platform_device *pdev = to_platform_device(sc->dev); +	struct ar231x_board_config *bcfg = pdev->dev.platform_data; +	u8 *cfg_mac; + +	if (to_platform_device(sc->dev)->id == 0) +		cfg_mac = bcfg->config->wlan0_mac; +	else +		cfg_mac = bcfg->config->wlan1_mac; + +	memcpy(mac, cfg_mac, ETH_ALEN); +	return 0; +} +  static const struct ath_bus_ops ath_ahb_bus_ops = {  	.ath_bus_type = ATH_AHB,  	.read_cachesize = ath5k_ahb_read_cachesize,  	.eeprom_read = ath5k_ahb_eeprom_read, +	.eeprom_read_mac = ath5k_ahb_eeprom_read_mac,  };  /*Initialization*/ @@ -142,6 +160,16 @@ static int ath_ahb_probe(struct platform_device *pdev)  		else  			reg |= AR5K_AR5312_ENABLE_WLAN1;  		__raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); + +		/* +		 * On a dual-band AR5312, the multiband radio is only +		 * used as pass-through. Disable 2 GHz support in the +		 * driver for it +		 */ +		if (to_platform_device(sc->dev)->id == 0 && +		    (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) == +		     (BD_WLAN1|BD_WLAN0)) +			__set_bit(ATH_STAT_2G_DISABLED, sc->status);  	}  	ret = ath5k_init_softc(sc, &ath_ahb_bus_ops); diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 8a06dbd3962..bb50700436f 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -224,8 +224,7 @@  /* SIFS */  #define	AR5K_INIT_SIFS_TURBO			6 -/* XXX: 8 from initvals 10 from standard */ -#define	AR5K_INIT_SIFS_DEFAULT_BG		8 +#define	AR5K_INIT_SIFS_DEFAULT_BG		10  #define	AR5K_INIT_SIFS_DEFAULT_A		16  #define	AR5K_INIT_SIFS_HALF_RATE		32  #define AR5K_INIT_SIFS_QUARTER_RATE		64 @@ -453,12 +452,10 @@ struct ath5k_tx_status {  	u16	ts_seqnum;  	u16	ts_tstamp;  	u8	ts_status; -	u8	ts_rate[4]; -	u8	ts_retry[4];  	u8	ts_final_idx; +	u8	ts_final_retry;  	s8	ts_rssi;  	u8	ts_shortretry; -	u8	ts_longretry;  	u8	ts_virtcol;  	u8	ts_antenna;  }; @@ -875,6 +872,19 @@ enum ath5k_int {  	AR5K_INT_QTRIG	=	0x40000000, /* Non common */  	AR5K_INT_GLOBAL =	0x80000000, +	AR5K_INT_TX_ALL = AR5K_INT_TXOK +		| AR5K_INT_TXDESC +		| AR5K_INT_TXERR +		| AR5K_INT_TXEOL +		| AR5K_INT_TXURN, + +	AR5K_INT_RX_ALL = AR5K_INT_RXOK +		| AR5K_INT_RXDESC +		| AR5K_INT_RXERR +		| AR5K_INT_RXNOFRM +		| AR5K_INT_RXEOL +		| AR5K_INT_RXORN, +  	AR5K_INT_COMMON  = AR5K_INT_RXOK  		| AR5K_INT_RXDESC  		| AR5K_INT_RXERR @@ -1058,6 +1068,7 @@ struct ath5k_hw {  	u8			ah_coverage_class;  	bool			ah_ack_bitrate_high;  	u8			ah_bwmode; +	bool			ah_short_slot;  	/* Antenna Control */  	u32			ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; @@ -1144,6 +1155,13 @@ struct ath5k_hw {  		struct ath5k_rx_status *);  }; +struct ath_bus_ops { +	enum ath_bus_type ath_bus_type; +	void (*read_cachesize)(struct ath_common *common, int *csz); +	bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); +	int (*eeprom_read_mac)(struct ath5k_hw *ah, u8 *mac); +}; +  /*   * Prototypes   */ @@ -1227,13 +1245,12 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah);  /* EEPROM access functions */  int ath5k_eeprom_init(struct ath5k_hw *ah);  void ath5k_eeprom_detach(struct ath5k_hw *ah); -int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);  /* Protocol Control Unit Functions */  /* Helpers */  int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, -		int len, struct ieee80211_rate *rate); +		int len, struct ieee80211_rate *rate, bool shortpre);  unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);  unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);  extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index bc824056048..1588401de3c 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -313,12 +313,17 @@ int ath5k_hw_init(struct ath5k_softc *sc)  		goto err;  	} +	if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) { +		__clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode); +		__clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode); +	} +  	/* Crypto settings */  	common->keymax = (sc->ah->ah_version == AR5K_AR5210 ?  			  AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211);  	if (srev >= AR5K_SREV_AR5212_V4 && -	    (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && +	    (ee->ee_version < AR5K_EEPROM_VERSION_5_0 ||  	    !AR5K_EEPROM_AES_DIS(ee->ee_misc5)))  		common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 349a5963931..203243bacc8 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1444,6 +1444,21 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)  }  static void +ath5k_set_current_imask(struct ath5k_softc *sc) +{ +	enum ath5k_int imask = sc->imask; +	unsigned long flags; + +	spin_lock_irqsave(&sc->irqlock, flags); +	if (sc->rx_pending) +		imask &= ~AR5K_INT_RX_ALL; +	if (sc->tx_pending) +		imask &= ~AR5K_INT_TX_ALL; +	ath5k_hw_set_imr(sc->ah, imask); +	spin_unlock_irqrestore(&sc->irqlock, flags); +} + +static void  ath5k_tasklet_rx(unsigned long data)  {  	struct ath5k_rx_status rs = {}; @@ -1506,6 +1521,8 @@ next:  	} while (ath5k_rxbuf_setup(sc, bf) == 0);  unlock:  	spin_unlock(&sc->rxbuflock); +	sc->rx_pending = false; +	ath5k_set_current_imask(sc);  } @@ -1573,28 +1590,28 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,  			 struct ath5k_txq *txq, struct ath5k_tx_status *ts)  {  	struct ieee80211_tx_info *info; +	u8 tries[3];  	int i;  	sc->stats.tx_all_count++;  	sc->stats.tx_bytes_count += skb->len;  	info = IEEE80211_SKB_CB(skb); +	tries[0] = info->status.rates[0].count; +	tries[1] = info->status.rates[1].count; +	tries[2] = info->status.rates[2].count; +  	ieee80211_tx_info_clear_status(info); -	for (i = 0; i < 4; i++) { + +	for (i = 0; i < ts->ts_final_idx; i++) {  		struct ieee80211_tx_rate *r =  			&info->status.rates[i]; -		if (ts->ts_rate[i]) { -			r->idx = ath5k_hw_to_driver_rix(sc, ts->ts_rate[i]); -			r->count = ts->ts_retry[i]; -		} else { -			r->idx = -1; -			r->count = 0; -		} +		r->count = tries[i];  	} -	/* count the successful attempt as well */ -	info->status.rates[ts->ts_final_idx].count++; +	info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry; +	info->status.rates[ts->ts_final_idx + 1].idx = -1;  	if (unlikely(ts->ts_status)) {  		sc->stats.ack_fail++; @@ -1609,6 +1626,9 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,  	} else {  		info->flags |= IEEE80211_TX_STAT_ACK;  		info->status.ack_signal = ts->ts_rssi; + +		/* count the successful attempt as well */ +		info->status.rates[ts->ts_final_idx].count++;  	}  	/* @@ -1690,6 +1710,9 @@ ath5k_tasklet_tx(unsigned long data)  	for (i=0; i < AR5K_NUM_TX_QUEUES; i++)  		if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))  			ath5k_tx_processq(sc, &sc->txqs[i]); + +	sc->tx_pending = false; +	ath5k_set_current_imask(sc);  } @@ -2119,6 +2142,20 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)  	 * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */  } +static void +ath5k_schedule_rx(struct ath5k_softc *sc) +{ +	sc->rx_pending = true; +	tasklet_schedule(&sc->rxtq); +} + +static void +ath5k_schedule_tx(struct ath5k_softc *sc) +{ +	sc->tx_pending = true; +	tasklet_schedule(&sc->txtq); +} +  irqreturn_t  ath5k_intr(int irq, void *dev_id)  { @@ -2161,7 +2198,7 @@ ath5k_intr(int irq, void *dev_id)  				ieee80211_queue_work(sc->hw, &sc->reset_work);  			}  			else -				tasklet_schedule(&sc->rxtq); +				ath5k_schedule_rx(sc);  		} else {  			if (status & AR5K_INT_SWBA) {  				tasklet_hi_schedule(&sc->beacontq); @@ -2179,10 +2216,10 @@ ath5k_intr(int irq, void *dev_id)  				ath5k_hw_update_tx_triglevel(ah, true);  			}  			if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) -				tasklet_schedule(&sc->rxtq); +				ath5k_schedule_rx(sc);  			if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC  					| AR5K_INT_TXERR | AR5K_INT_TXEOL)) -				tasklet_schedule(&sc->txtq); +				ath5k_schedule_tx(sc);  			if (status & AR5K_INT_BMISS) {  				/* TODO */  			} @@ -2201,6 +2238,9 @@ ath5k_intr(int irq, void *dev_id)  	} while (ath5k_hw_is_intr_pending(ah) && --counter > 0); +	if (sc->rx_pending || sc->tx_pending) +		ath5k_set_current_imask(sc); +  	if (unlikely(!counter))  		ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); @@ -2572,6 +2612,8 @@ done:  static void stop_tasklets(struct ath5k_softc *sc)  { +	sc->rx_pending = false; +	sc->tx_pending = false;  	tasklet_kill(&sc->rxtq);  	tasklet_kill(&sc->txtq);  	tasklet_kill(&sc->calib); @@ -2838,7 +2880,7 @@ ath5k_init(struct ieee80211_hw *hw)  	INIT_WORK(&sc->reset_work, ath5k_reset_work);  	INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work); -	ret = ath5k_eeprom_read_mac(ah, mac); +	ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac);  	if (ret) {  		ATH5K_ERR(sc, "unable to read address from EEPROM\n");  		goto err_queues; @@ -2898,7 +2940,6 @@ ath5k_deinit_softc(struct ath5k_softc *sc)  	 * XXX: ??? detach ath5k_hw ???  	 * Other than that, it's straightforward...  	 */ -	ath5k_debug_finish_device(sc);  	ieee80211_unregister_hw(hw);  	ath5k_desc_free(sc);  	ath5k_txq_release(sc); diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 978f1f4ac2f..b294f330501 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -193,12 +193,13 @@ struct ath5k_softc {  	dma_addr_t		desc_daddr;	/* DMA (physical) address */  	size_t			desc_len;	/* size of TX/RX descriptors */ -	DECLARE_BITMAP(status, 5); +	DECLARE_BITMAP(status, 6);  #define ATH_STAT_INVALID	0		/* disable hardware accesses */  #define ATH_STAT_MRRETRY	1		/* multi-rate retry support */  #define ATH_STAT_PROMISC	2  #define ATH_STAT_LEDSOFT	3		/* enable LED gpio status */  #define ATH_STAT_STARTED	4		/* opened & irqs enabled */ +#define ATH_STAT_2G_DISABLED	5		/* multiband radio without 2G */  	unsigned int		filter_flags;	/* HW flags, AR5K_RX_FILTER_* */  	struct ieee80211_channel *curchan;	/* current h/w channel */ @@ -207,6 +208,10 @@ struct ath5k_softc {  	enum ath5k_int		imask;		/* interrupt mask copy */ +	spinlock_t		irqlock; +	bool			rx_pending;	/* rx tasklet pending */ +	bool			tx_pending;	/* tx tasklet pending */ +  	u8			lladdr[ETH_ALEN];  	u8			bssidmask[ETH_ALEN]; diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index f77e8a703c5..7dd88e1c3ff 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c @@ -94,6 +94,9 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)  		}  	} +	if ((ah->ah_radio_5ghz_revision & 0xf0) == AR5K_SREV_RAD_2112) +		__clear_bit(AR5K_MODE_11A, caps->cap_mode); +  	/* Set number of supported TX queues */  	if (ah->ah_version == AR5K_AR5210)  		caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU; diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 0230f30e9e9..0bf7313b8a1 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -888,65 +888,38 @@ static const struct file_operations fops_queue = {  void  ath5k_debug_init_device(struct ath5k_softc *sc)  { -	sc->debug.level = ath5k_debug; +	struct dentry *phydir; -	sc->debug.debugfs_phydir = debugfs_create_dir("ath5k", -				sc->hw->wiphy->debugfsdir); +	sc->debug.level = ath5k_debug; -	sc->debug.debugfs_debug = debugfs_create_file("debug", -				S_IWUSR | S_IRUSR, -				sc->debug.debugfs_phydir, sc, &fops_debug); +	phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir); +	if (!phydir) +	    return; -	sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR, -				sc->debug.debugfs_phydir, sc, &fops_registers); +	debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc, +			    &fops_debug); -	sc->debug.debugfs_beacon = debugfs_create_file("beacon", -				S_IWUSR | S_IRUSR, -				sc->debug.debugfs_phydir, sc, &fops_beacon); +	debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers); -	sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, -				sc->debug.debugfs_phydir, sc, &fops_reset); +	debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc, +			    &fops_beacon); -	sc->debug.debugfs_antenna = debugfs_create_file("antenna", -				S_IWUSR | S_IRUSR, -				sc->debug.debugfs_phydir, sc, &fops_antenna); +	debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset); -	sc->debug.debugfs_misc = debugfs_create_file("misc", -				S_IRUSR, -				sc->debug.debugfs_phydir, sc, &fops_misc); +	debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc, +			    &fops_antenna); -	sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors", -				S_IWUSR | S_IRUSR, -				sc->debug.debugfs_phydir, sc, -				&fops_frameerrors); +	debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc); -	sc->debug.debugfs_ani = debugfs_create_file("ani", -				S_IWUSR | S_IRUSR, -				sc->debug.debugfs_phydir, sc, -				&fops_ani); +	debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc, +			    &fops_frameerrors); -	sc->debug.debugfs_queue = debugfs_create_file("queue", -				S_IWUSR | S_IRUSR, -				sc->debug.debugfs_phydir, sc, -				&fops_queue); -} +	debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani); -void -ath5k_debug_finish_device(struct ath5k_softc *sc) -{ -	debugfs_remove(sc->debug.debugfs_debug); -	debugfs_remove(sc->debug.debugfs_registers); -	debugfs_remove(sc->debug.debugfs_beacon); -	debugfs_remove(sc->debug.debugfs_reset); -	debugfs_remove(sc->debug.debugfs_antenna); -	debugfs_remove(sc->debug.debugfs_misc); -	debugfs_remove(sc->debug.debugfs_frameerrors); -	debugfs_remove(sc->debug.debugfs_ani); -	debugfs_remove(sc->debug.debugfs_queue); -	debugfs_remove(sc->debug.debugfs_phydir); +	debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc, +			    &fops_queue);  } -  /* functions used in other places */  void diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index b0355aef68d..193dd2d4ea3 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -68,17 +68,6 @@ struct ath5k_buf;  struct ath5k_dbg_info {  	unsigned int		level;		/* debug level */ -	/* debugfs entries */ -	struct dentry		*debugfs_phydir; -	struct dentry		*debugfs_debug; -	struct dentry		*debugfs_registers; -	struct dentry		*debugfs_beacon; -	struct dentry		*debugfs_reset; -	struct dentry		*debugfs_antenna; -	struct dentry		*debugfs_misc; -	struct dentry		*debugfs_frameerrors; -	struct dentry		*debugfs_ani; -	struct dentry		*debugfs_queue;  };  /** @@ -141,9 +130,6 @@ void  ath5k_debug_init_device(struct ath5k_softc *sc);  void -ath5k_debug_finish_device(struct ath5k_softc *sc); - -void  ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);  void @@ -167,9 +153,6 @@ static inline void  ath5k_debug_init_device(struct ath5k_softc *sc) {}  static inline void -ath5k_debug_finish_device(struct ath5k_softc *sc) {} - -static inline void  ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}  static inline void diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index a8fcc94269f..62172d58572 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -185,6 +185,12 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,  	struct ath5k_hw_4w_tx_ctl *tx_ctl;  	unsigned int frame_len; +	/* +	 * Use local variables for these to reduce load/store access on +	 * uncached memory +	 */ +	u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0; +  	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;  	/* @@ -208,8 +214,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,  	if (tx_power > AR5K_TUNE_MAX_TXPOWER)  		tx_power = AR5K_TUNE_MAX_TXPOWER; -	/* Clear descriptor */ -	memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); +	/* Clear descriptor status area */ +	memset(&desc->ud.ds_tx5212.tx_stat, 0, +	       sizeof(desc->ud.ds_tx5212.tx_stat));  	/* Setup control descriptor */ @@ -221,7 +228,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,  	if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)  		return -EINVAL; -	tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; +	txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;  	/* Verify and set buffer length */ @@ -232,21 +239,17 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,  	if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)  		return -EINVAL; -	tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; +	txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; -	tx_ctl->tx_control_0 |= -		AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | -		AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); -	tx_ctl->tx_control_1 |= AR5K_REG_SM(type, -					AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); -	tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0, -					AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); -	tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; +	txctl0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | +		  AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); +	txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); +	txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); +	txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;  #define _TX_FLAGS(_c, _flag)					\  	if (flags & AR5K_TXDESC_##_flag) {			\ -		tx_ctl->tx_control_##_c |=			\ -			AR5K_4W_TX_DESC_CTL##_c##_##_flag;	\ +		txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag;	\  	}  	_TX_FLAGS(0, CLRDMASK); @@ -262,8 +265,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,  	 * WEP crap  	 */  	if (key_index != AR5K_TXKEYIX_INVALID) { -		tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; -		tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, +		txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; +		txctl1 |= AR5K_REG_SM(key_index,  				AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX);  	} @@ -274,12 +277,16 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,  		if ((flags & AR5K_TXDESC_RTSENA) &&  				(flags & AR5K_TXDESC_CTSENA))  			return -EINVAL; -		tx_ctl->tx_control_2 |= rtscts_duration & -				AR5K_4W_TX_DESC_CTL2_RTS_DURATION; -		tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, +		txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION; +		txctl3 |= AR5K_REG_SM(rtscts_rate,  				AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);  	} +	tx_ctl->tx_control_0 = txctl0; +	tx_ctl->tx_control_1 = txctl1; +	tx_ctl->tx_control_2 = txctl2; +	tx_ctl->tx_control_3 = txctl3; +  	return 0;  } @@ -364,7 +371,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,  		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);  	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,  		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); -	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, +	ts->ts_final_retry = AR5K_REG_MS(tx_status->tx_status_0,  		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);  	/*TODO: ts->ts_virtcol + test*/  	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, @@ -373,9 +380,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,  		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);  	ts->ts_antenna = 1;  	ts->ts_status = 0; -	ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0, -		AR5K_2W_TX_DESC_CTL0_XMIT_RATE); -	ts->ts_retry[0] = ts->ts_longretry;  	ts->ts_final_idx = 0;  	if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { @@ -401,81 +405,48 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,  {  	struct ath5k_hw_4w_tx_ctl *tx_ctl;  	struct ath5k_hw_tx_status *tx_status; +	u32 txstat0, txstat1;  	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;  	tx_status = &desc->ud.ds_tx5212.tx_stat; +	txstat1 = ACCESS_ONCE(tx_status->tx_status_1); +  	/* No frame has been send or error */ -	if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))) +	if (unlikely(!(txstat1 & AR5K_DESC_TX_STATUS1_DONE)))  		return -EINPROGRESS; +	txstat0 = ACCESS_ONCE(tx_status->tx_status_0); +  	/*  	 * Get descriptor status  	 */ -	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, +	ts->ts_tstamp = AR5K_REG_MS(txstat0,  		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); -	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, +	ts->ts_shortretry = AR5K_REG_MS(txstat0,  		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); -	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, +	ts->ts_final_retry = AR5K_REG_MS(txstat0,  		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); -	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, +	ts->ts_seqnum = AR5K_REG_MS(txstat1,  		AR5K_DESC_TX_STATUS1_SEQ_NUM); -	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, +	ts->ts_rssi = AR5K_REG_MS(txstat1,  		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); -	ts->ts_antenna = (tx_status->tx_status_1 & +	ts->ts_antenna = (txstat1 &  		AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1;  	ts->ts_status = 0; -	ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, +	ts->ts_final_idx = AR5K_REG_MS(txstat1,  			AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); -	/* The longretry counter has the number of un-acked retries -	 * for the final rate. To get the total number of retries -	 * we have to add the retry counters for the other rates -	 * as well -	 */ -	ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; -	switch (ts->ts_final_idx) { -	case 3: -		ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3, -			AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); - -		ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, -			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); -		ts->ts_longretry += ts->ts_retry[2]; -		/* fall through */ -	case 2: -		ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3, -			AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); - -		ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, -			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); -		ts->ts_longretry += ts->ts_retry[1]; -		/* fall through */ -	case 1: -		ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3, -			AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); - -		ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, -			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); -		ts->ts_longretry += ts->ts_retry[0]; -		/* fall through */ -	case 0: -		ts->ts_rate[0] = tx_ctl->tx_control_3 & -			AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; -		break; -	} -  	/* TX error */ -	if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { -		if (tx_status->tx_status_0 & -				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) +	if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { +		if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)  			ts->ts_status |= AR5K_TXERR_XRETRY; -		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) +		if (txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)  			ts->ts_status |= AR5K_TXERR_FIFO; -		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) +		if (txstat0 & AR5K_DESC_TX_STATUS0_FILTERED)  			ts->ts_status |= AR5K_TXERR_FILT;  	} @@ -609,37 +580,37 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,  					struct ath5k_rx_status *rs)  {  	struct ath5k_hw_rx_status *rx_status; +	u32 rxstat0, rxstat1;  	rx_status = &desc->ud.ds_rx.rx_stat; +	rxstat1 = ACCESS_ONCE(rx_status->rx_status_1);  	/* No frame received / not ready */ -	if (unlikely(!(rx_status->rx_status_1 & -				AR5K_5212_RX_DESC_STATUS1_DONE))) +	if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE)))  		return -EINPROGRESS;  	memset(rs, 0, sizeof(struct ath5k_rx_status)); +	rxstat0 = ACCESS_ONCE(rx_status->rx_status_0);  	/*  	 * Frame receive status  	 */ -	rs->rs_datalen = rx_status->rx_status_0 & -		AR5K_5212_RX_DESC_STATUS0_DATA_LEN; -	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, +	rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN; +	rs->rs_rssi = AR5K_REG_MS(rxstat0,  		AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); -	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, +	rs->rs_rate = AR5K_REG_MS(rxstat0,  		AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); -	rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, +	rs->rs_antenna = AR5K_REG_MS(rxstat0,  		AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); -	rs->rs_more = !!(rx_status->rx_status_0 & -		AR5K_5212_RX_DESC_STATUS0_MORE); -	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, +	rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE); +	rs->rs_tstamp = AR5K_REG_MS(rxstat1,  		AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);  	/*  	 * Key table status  	 */ -	if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) -		rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, +	if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) +		rs->rs_keyix = AR5K_REG_MS(rxstat1,  					   AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);  	else  		rs->rs_keyix = AR5K_RXKEYIX_INVALID; @@ -647,27 +618,22 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,  	/*  	 * Receive/descriptor errors  	 */ -	if (!(rx_status->rx_status_1 & -	    AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { -		if (rx_status->rx_status_1 & -				AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) +	if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { +		if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)  			rs->rs_status |= AR5K_RXERR_CRC; -		if (rx_status->rx_status_1 & -				AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { +		if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {  			rs->rs_status |= AR5K_RXERR_PHY; -			rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, +			rs->rs_phyerr = AR5K_REG_MS(rxstat1,  				AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE);  			if (!ah->ah_capabilities.cap_has_phyerr_counters)  				ath5k_ani_phy_error_report(ah, rs->rs_phyerr);  		} -		if (rx_status->rx_status_1 & -				AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) +		if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)  			rs->rs_status |= AR5K_RXERR_DECRYPT; -		if (rx_status->rx_status_1 & -				AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) +		if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)  			rs->rs_status |= AR5K_RXERR_MIC;  	}  	return 0; diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index efb672cb31e..1fef84f87c7 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -660,6 +660,53 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)  		vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;  } +static int +ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) +{ +	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; +	struct ath5k_chan_pcal_info *chinfo; +	u8 pier, pdg; + +	switch (mode) { +	case AR5K_EEPROM_MODE_11A: +		if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) +			return 0; +		chinfo = ee->ee_pwr_cal_a; +		break; +	case AR5K_EEPROM_MODE_11B: +		if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) +			return 0; +		chinfo = ee->ee_pwr_cal_b; +		break; +	case AR5K_EEPROM_MODE_11G: +		if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) +			return 0; +		chinfo = ee->ee_pwr_cal_g; +		break; +	default: +		return -EINVAL; +	} + +	for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { +		if (!chinfo[pier].pd_curves) +			continue; + +		for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { +			struct ath5k_pdgain_info *pd = +					&chinfo[pier].pd_curves[pdg]; + +			if (pd != NULL) { +				kfree(pd->pd_step); +				kfree(pd->pd_pwr); +			} +		} + +		kfree(chinfo[pier].pd_curves); +	} + +	return 0; +} +  /* Convert RF5111 specific data to generic raw data   * used by interpolation code */  static int @@ -684,7 +731,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,  				GFP_KERNEL);  		if (!chinfo[pier].pd_curves) -			return -ENOMEM; +			goto err_out;  		/* Only one curve for RF5111  		 * find out which one and place @@ -708,12 +755,12 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,  		pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,  					sizeof(u8), GFP_KERNEL);  		if (!pd->pd_step) -			return -ENOMEM; +			goto err_out;  		pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111,  					sizeof(s16), GFP_KERNEL);  		if (!pd->pd_pwr) -			return -ENOMEM; +			goto err_out;  		/* Fill raw dataset  		 * (convert power to 0.25dB units @@ -734,6 +781,10 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,  	}  	return 0; + +err_out: +	ath5k_eeprom_free_pcal_info(ah, mode); +	return -ENOMEM;  }  /* Parse EEPROM data */ @@ -867,7 +918,7 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,  					GFP_KERNEL);  		if (!chinfo[pier].pd_curves) -			return -ENOMEM; +			goto err_out;  		/* Fill pd_curves */  		for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { @@ -886,14 +937,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,  						sizeof(u8), GFP_KERNEL);  				if (!pd->pd_step) -					return -ENOMEM; +					goto err_out;  				pd->pd_pwr = kcalloc(pd->pd_points,  						sizeof(s16), GFP_KERNEL);  				if (!pd->pd_pwr) -					return -ENOMEM; - +					goto err_out;  				/* Fill raw dataset  				 * (all power levels are in 0.25dB units) */ @@ -925,13 +975,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,  						sizeof(u8), GFP_KERNEL);  				if (!pd->pd_step) -					return -ENOMEM; +					goto err_out;  				pd->pd_pwr = kcalloc(pd->pd_points,  						sizeof(s16), GFP_KERNEL);  				if (!pd->pd_pwr) -					return -ENOMEM; +					goto err_out;  				/* Fill raw dataset  				 * (all power levels are in 0.25dB units) */ @@ -954,6 +1004,10 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,  	}  	return 0; + +err_out: +	ath5k_eeprom_free_pcal_info(ah, mode); +	return -ENOMEM;  }  /* Parse EEPROM data */ @@ -1156,7 +1210,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,  					GFP_KERNEL);  		if (!chinfo[pier].pd_curves) -			return -ENOMEM; +			goto err_out;  		/* Fill pd_curves */  		for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { @@ -1177,13 +1231,13 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,  					sizeof(u8), GFP_KERNEL);  			if (!pd->pd_step) -				return -ENOMEM; +				goto err_out;  			pd->pd_pwr = kcalloc(pd->pd_points,  					sizeof(s16), GFP_KERNEL);  			if (!pd->pd_pwr) -				return -ENOMEM; +				goto err_out;  			/* Fill raw dataset  			 * convert all pwr levels to @@ -1213,6 +1267,10 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,  	}  	return 0; + +err_out: +	ath5k_eeprom_free_pcal_info(ah, mode); +	return -ENOMEM;  }  /* Parse EEPROM data */ @@ -1534,53 +1592,6 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)  	return 0;  } -static int -ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) -{ -	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; -	struct ath5k_chan_pcal_info *chinfo; -	u8 pier, pdg; - -	switch (mode) { -	case AR5K_EEPROM_MODE_11A: -		if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) -			return 0; -		chinfo = ee->ee_pwr_cal_a; -		break; -	case AR5K_EEPROM_MODE_11B: -		if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) -			return 0; -		chinfo = ee->ee_pwr_cal_b; -		break; -	case AR5K_EEPROM_MODE_11G: -		if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) -			return 0; -		chinfo = ee->ee_pwr_cal_g; -		break; -	default: -		return -EINVAL; -	} - -	for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { -		if (!chinfo[pier].pd_curves) -			continue; - -		for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { -			struct ath5k_pdgain_info *pd = -					&chinfo[pier].pd_curves[pdg]; - -			if (pd != NULL) { -				kfree(pd->pd_step); -				kfree(pd->pd_pwr); -			} -		} - -		kfree(chinfo[pier].pd_curves); -	} - -	return 0; -} -  /* Read conformance test limits used for regulatory control */  static int  ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) @@ -1721,35 +1732,6 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah)  	return ret;  } -/* - * Read the MAC address from eeprom - */ -int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) -{ -	u8 mac_d[ETH_ALEN] = {}; -	u32 total, offset; -	u16 data; -	int octet; - -	AR5K_EEPROM_READ(0x20, data); - -	for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { -		AR5K_EEPROM_READ(offset, data); - -		total += data; -		mac_d[octet + 1] = data & 0xff; -		mac_d[octet] = data >> 8; -		octet += 2; -	} - -	if (!total || total == 3 * 0xffff) -		return -EINVAL; - -	memcpy(mac, mac_d, ETH_ALEN); - -	return 0; -} -  /***********************\  * Init/Detach functions * diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 9be29b728b1..807bd644016 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -282,6 +282,15 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	if (changes & BSS_CHANGED_BEACON_INT)  		sc->bintval = bss_conf->beacon_int; +	if (changes & BSS_CHANGED_ERP_SLOT) { +		int slot_time; + +		ah->ah_short_slot = bss_conf->use_short_slot; +		slot_time = ath5k_hw_get_default_slottime(ah) + +			    3 * ah->ah_coverage_class; +		ath5k_hw_set_ifs_intervals(ah, slot_time); +	} +  	if (changes & BSS_CHANGED_ASSOC) {  		avf->assoc = bss_conf->assoc;  		if (bss_conf->assoc) diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index 3c44689a700..296c316a834 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c @@ -17,6 +17,7 @@  #include <linux/nl80211.h>  #include <linux/pci.h>  #include <linux/pci-aspm.h> +#include <linux/etherdevice.h>  #include "../ath.h"  #include "ath5k.h"  #include "debug.h" @@ -108,11 +109,42 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)  	return 0;  } +/* + * Read the MAC address from eeprom or platform_data + */ +static int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) +{ +	u8 mac_d[ETH_ALEN] = {}; +	u32 total, offset; +	u16 data; +	int octet; + +	AR5K_EEPROM_READ(0x20, data); + +	for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { +		AR5K_EEPROM_READ(offset, data); + +		total += data; +		mac_d[octet + 1] = data & 0xff; +		mac_d[octet] = data >> 8; +		octet += 2; +	} + +	if (!total || total == 3 * 0xffff) +		return -EINVAL; + +	memcpy(mac, mac_d, ETH_ALEN); + +	return 0; +} + +  /* Common ath_bus_opts structure */  static const struct ath_bus_ops ath_pci_bus_ops = {  	.ath_bus_type = ATH_PCI,  	.read_cachesize = ath5k_pci_read_cachesize,  	.eeprom_read = ath5k_pci_eeprom_read, +	.eeprom_read_mac = ath5k_pci_eeprom_read_mac,  };  /********************\ diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index d9b3f828455..712a9ac4000 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -75,7 +75,7 @@ static const unsigned int ack_rates_high[] =   * bwmodes.   */  int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, -		int len, struct ieee80211_rate *rate) +		int len, struct ieee80211_rate *rate, bool shortpre)  {  	struct ath5k_softc *sc = ah->ah_sc;  	int sifs, preamble, plcp_bits, sym_time; @@ -84,9 +84,15 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,  	/* Fallback */  	if (!ah->ah_bwmode) { -		dur = ieee80211_generic_frame_duration(sc->hw, -						NULL, len, rate); -		return le16_to_cpu(dur); +		__le16 raw_dur = ieee80211_generic_frame_duration(sc->hw, +					NULL, len, rate); + +		/* subtract difference between long and short preamble */ +		dur = le16_to_cpu(raw_dur); +		if (shortpre) +			dur -= 96; + +		return dur;  	}  	bitrate = rate->bitrate; @@ -145,9 +151,9 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)  		slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE;  		break;  	case AR5K_BWMODE_DEFAULT: -		slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;  	default: -		if (channel->hw_value & CHANNEL_CCK) +		slot_time = AR5K_INIT_SLOT_TIME_DEFAULT; +		if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot)  			slot_time = AR5K_INIT_SLOT_TIME_B;  		break;  	} @@ -263,27 +269,14 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)  		 * actual rate for this rate. See mac80211 tx.c  		 * ieee80211_duration() for a brief description of  		 * what rate we should choose to TX ACKs. */ -		tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); +		tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);  		ath5k_hw_reg_write(ah, tx_time, reg);  		if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))  			continue; -		/* -		 * We're not distinguishing short preamble here, -		 * This is true, all we'll get is a longer value here -		 * which is not necessarilly bad. We could use -		 * export ieee80211_frame_duration() but that needs to be -		 * fixed first to be properly used by mac802111 drivers: -		 * -		 *  - remove erp stuff and let the routine figure ofdm -		 *    erp rates -		 *  - remove passing argument ieee80211_local as -		 *    drivers don't have access to it -		 *  - move drivers using ieee80211_generic_frame_duration() -		 *    to this -		 */ +		tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true);  		ath5k_hw_reg_write(ah, tx_time,  			reg + (AR5K_SET_SHORT_PREAMBLE << 2));  	} diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 3343fb9e494..b18c5021aac 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -519,7 +519,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)  		return -EINVAL;  	sifs = ath5k_hw_get_default_sifs(ah); -	sifs_clock = ath5k_hw_htoclock(ah, sifs); +	sifs_clock = ath5k_hw_htoclock(ah, sifs - 2);  	/* EIFS  	 * Txtime of ack at lowest rate + SIFS + DIFS @@ -550,7 +550,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)  	else  		rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; -	ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); +	ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);  	/* ack_tx_time includes an SIFS already */  	eifs = ack_tx_time + sifs + 2 * slot_time; diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index ad57a6d2311..d9ff8413ab9 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -5,7 +5,7 @@ config ATH9K_COMMON  config ATH9K  	tristate "Atheros 802.11n wireless cards support" -	depends on PCI && MAC80211 +	depends on MAC80211  	select ATH9K_HW  	select MAC80211_LEDS  	select LEDS_CLASS @@ -23,6 +23,25 @@ config ATH9K  	  If you choose to build a module, it'll be called ath9k. +config ATH9K_PCI +	bool "Atheros ath9k PCI/PCIe bus support" +	depends on ATH9K && PCI +	default PCI +	---help--- +	  This option enables the PCI bus support in ath9k. + +	  Say Y, if you have a compatible PCI/PCIe wireless card. + +config ATH9K_AHB +	bool "Atheros ath9k AHB bus support" +	depends on ATH9K +	default n +	---help--- +	  This option enables the AHB bus support in ath9k. + +	  Say Y, if you have a SoC with a compatible built-in +	  wireless MAC. Say N if unsure. +  config ATH9K_DEBUGFS  	bool "Atheros ath9k debugging"  	depends on ATH9K && DEBUG_FS diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 4d66ca8042e..05a6fade7b1 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -6,8 +6,8 @@ ath9k-y +=	beacon.o \  		xmit.o \  ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o -ath9k-$(CONFIG_PCI) += pci.o -ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o +ath9k-$(CONFIG_ATH9K_PCI) += pci.o +ath9k-$(CONFIG_ATH9K_AHB) += ahb.o  ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o  obj-$(CONFIG_ATH9K) += ath9k.o @@ -48,4 +48,6 @@ ath9k_htc-y +=	htc_hst.o \  		htc_drv_init.o \  		htc_drv_gpio.o +ath9k_htc-$(CONFIG_ATH9K_HTC_DEBUGFS) += htc_drv_debug.o +  obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 9cb0efa9b4c..5193ed58a17 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -21,6 +21,14 @@  #include <linux/ath9k_platform.h>  #include "ath9k.h" +const struct platform_device_id ath9k_platform_id_table[] = { +	{ +		.name = "ath9k", +		.driver_data = AR5416_AR9100_DEVID, +	}, +	{}, +}; +  /* return bus cachesize in 4B word units */  static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)  { @@ -57,6 +65,7 @@ static int ath_ahb_probe(struct platform_device *pdev)  	struct ath_softc *sc;  	struct ieee80211_hw *hw;  	struct resource *res; +	const struct platform_device_id *id = platform_get_device_id(pdev);  	int irq;  	int ret = 0;  	struct ath_hw *ah; @@ -116,7 +125,7 @@ static int ath_ahb_probe(struct platform_device *pdev)  		goto err_free_hw;  	} -	ret = ath9k_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops); +	ret = ath9k_init_device(id->driver_data, sc, 0x0, &ath_ahb_bus_ops);  	if (ret) {  		dev_err(&pdev->dev, "failed to initialize device\n");  		goto err_irq; @@ -165,8 +174,11 @@ static struct platform_driver ath_ahb_driver = {  		.name	= "ath9k",  		.owner	= THIS_MODULE,  	}, +	.id_table    = ath9k_platform_id_table,  }; +MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table); +  int ath_ahb_init(void)  {  	return platform_driver_register(&ath_ahb_driver); diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 8dd8f630850..c338efbccf4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -290,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,  		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)  		| SM(txPower, AR_XmitPower)  		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) -		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)  		| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)  		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); @@ -311,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,  	}  } +static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); + +	if (val) +		ads->ds_ctl0 |= AR_ClrDestMask; +	else +		ads->ds_ctl0 &= ~AR_ClrDestMask; +} +  static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,  					  void *lastds,  					  u32 durUpdateEn, u32 rtsctsRate, @@ -448,4 +457,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)  	ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;  	ops->clr11n_aggr = ar9002_hw_clr11n_aggr;  	ops->set11n_burstduration = ar9002_hw_set11n_burstduration; +	ops->set_clrdmask = ar9002_hw_set_clrdmask;  } diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 37663dbbcf5..47780ef1c89 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -483,7 +483,11 @@  #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN     0x01F80000  #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S   19 +#define AR_PHY_TX_PWRCTRL8       0xa278 +  #define AR_PHY_TX_PWRCTRL9       0xa27C + +#define AR_PHY_TX_PWRCTRL10       0xa394  #define AR_PHY_TX_DESIRED_SCALE_CCK        0x00007C00  #define AR_PHY_TX_DESIRED_SCALE_CCK_S      10  #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL  0x80000000 @@ -495,6 +499,8 @@  #define AR_PHY_CH0_TX_PWRCTRL11  0xa398  #define AR_PHY_CH1_TX_PWRCTRL11  0xb398 +#define AR_PHY_CH0_TX_PWRCTRL12  0xa3dc +#define AR_PHY_CH0_TX_PWRCTRL13  0xa3e0  #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP   0x0000FC00  #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 9ecca93392e..f915a3dbfca 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -34,10 +34,10 @@ static const u32 ar9300_2p2_radio_postamble[][5] = {  static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {  	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ -	{0x0000a2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, -	{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, -	{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, -	{0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +	{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +	{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, +	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},  	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},  	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},  	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, @@ -119,14 +119,14 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {  	{0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},  	{0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},  	{0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, -	{0x0000b2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, -	{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, -	{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, -	{0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -	{0x0000c2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, -	{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, -	{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, -	{0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +	{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +	{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, +	{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +	{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +	{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, +	{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},  	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},  	{0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},  	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, @@ -835,10 +835,10 @@ static const u32 ar9300_2p2_baseband_core[][2] = {  static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {  	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ -	{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, -	{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, -	{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, -	{0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},  	{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},  	{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},  	{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, @@ -920,14 +920,14 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {  	{0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},  	{0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},  	{0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, -	{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, -	{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, -	{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, -	{0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -	{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, -	{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, -	{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, -	{0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},  	{0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},  	{0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},  	{0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, @@ -941,10 +941,10 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {  static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {  	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ -	{0x0000a2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, -	{0x0000a2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, -	{0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, -	{0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, +	{0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, +	{0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},  	{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},  	{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},  	{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, @@ -1026,14 +1026,14 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {  	{0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},  	{0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},  	{0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, -	{0x0000b2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, -	{0x0000b2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, -	{0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, -	{0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -	{0x0000c2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, -	{0x0000c2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, -	{0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, -	{0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, +	{0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, +	{0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, +	{0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, +	{0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},  	{0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},  	{0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},  	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, @@ -1307,10 +1307,10 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = {  static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {  	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ -	{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, -	{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, -	{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, -	{0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +	{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +	{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, +	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},  	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},  	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},  	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, @@ -1329,21 +1329,21 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {  	{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},  	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},  	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, -	{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, -	{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, -	{0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, -	{0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, -	{0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, -	{0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, -	{0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, -	{0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, -	{0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, -	{0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, -	{0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, -	{0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, -	{0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, -	{0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, -	{0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, +	{0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, +	{0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, +	{0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, +	{0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, +	{0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, +	{0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, +	{0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, +	{0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +	{0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},  	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},  	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},  	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, @@ -1361,45 +1361,45 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = {  	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},  	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},  	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, -	{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, -	{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, -	{0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, -	{0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, -	{0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, -	{0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, -	{0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, -	{0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, -	{0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, -	{0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, -	{0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, -	{0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, -	{0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, -	{0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, -	{0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, +	{0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, +	{0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, +	{0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, +	{0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, +	{0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, +	{0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, +	{0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, +	{0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +	{0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},  	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},  	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},  	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},  	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},  	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, -	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, -	{0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, -	{0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, -	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, -	{0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, -	{0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, -	{0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, -	{0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, -	{0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, -	{0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, -	{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, -	{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, -	{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, -	{0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -	{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, -	{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, -	{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, -	{0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, +	{0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, +	{0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, +	{0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, +	{0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, +	{0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +	{0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +	{0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +	{0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +	{0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +	{0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +	{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +	{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, +	{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +	{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +	{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, +	{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},  	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},  	{0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},  	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 724ac2464ad..c1264d60c49 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -329,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,  		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)  		| SM(txpower, AR_XmitPower)  		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) -		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)  		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)  		| (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); @@ -350,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,  	ads->ctl22 = 0;  } +static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) +{ +	struct ar9003_txc *ads = (struct ar9003_txc *) ds; + +	if (val) +		ads->ctl11 |= AR_ClrDestMask; +	else +		ads->ctl11 &= ~AR_ClrDestMask; +} +  static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,  					  void *lastds,  					  u32 durUpdateEn, u32 rtsctsRate, @@ -510,6 +519,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)  	ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;  	ops->clr11n_aggr = ar9003_hw_clr11n_aggr;  	ops->set11n_burstduration = ar9003_hw_set11n_burstduration; +	ops->set_clrdmask = ar9003_hw_set_clrdmask;  }  void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index eb250d6b803..1bc33f51e46 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -75,9 +75,18 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)  	freq = centers.synth_center;  	if (freq < 4800) {     /* 2 GHz, fractional mode */ -		if (AR_SREV_9485(ah)) -			channelSel = CHANSEL_2G_9485(freq); -		else +		if (AR_SREV_9485(ah)) { +			u32 chan_frac; + +			/* +			 * freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0 +			 * ndiv = ((chan_mhz * 4) / 3) / freq_ref; +			 * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 +			 */ +			channelSel = (freq * 4) / 120; +			chan_frac = (((freq * 4) % 120) * 0x20000) / 120; +			channelSel = (channelSel << 17) | chan_frac; +		} else  			channelSel = CHANSEL_2G(freq);  		/* Set to 2G mode */  		bMode = 1; @@ -401,7 +410,7 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah,  	ar9003_hw_spur_ofdm_clear(ah); -	for (i = 0; spurChansPtr[i] && i < 5; i++) { +	for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) {  		freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq;  		if (abs(freq_offset) < range) {  			ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index f91f73e50d0..fbdde29f0ab 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h @@ -396,7 +396,7 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {  	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},  	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},  	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, -	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},  	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},  	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},  	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -469,7 +469,7 @@ static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = {  	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},  	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},  	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, -	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},  	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},  	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},  	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -635,7 +635,7 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {  	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},  	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},  	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, -	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},  	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},  	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},  	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -728,7 +728,7 @@ static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = {  	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},  	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},  	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, -	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},  	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},  	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},  	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, @@ -827,7 +827,7 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {  	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},  	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},  	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, -	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},  	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},  	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},  	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 38835bc324b..a6b53880225 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -200,6 +200,7 @@ struct ath_atx_ac {  	int sched;  	struct list_head list;  	struct list_head tid_q; +	bool clear_ps_filter;  };  struct ath_frame_info { @@ -255,8 +256,12 @@ struct ath_node {  #endif  	struct ath_atx_tid tid[WME_NUM_TID];  	struct ath_atx_ac ac[WME_NUM_AC]; +	int ps_key; +  	u16 maxampdu;  	u8 mpdudensity; + +	bool sleeping;  };  #define AGGR_CLEANUP         BIT(1) @@ -338,6 +343,9 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,  void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);  void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); +void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an); +  /********/  /* VIFs */  /********/ @@ -665,7 +673,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);  bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);  bool ath9k_uses_beacons(int type); -#ifdef CONFIG_PCI +#ifdef CONFIG_ATH9K_PCI  int ath_pci_init(void);  void ath_pci_exit(void);  #else @@ -673,7 +681,7 @@ static inline int ath_pci_init(void) { return 0; };  static inline void ath_pci_exit(void) {};  #endif -#ifdef CONFIG_ATHEROS_AR71XX +#ifdef CONFIG_ATH9K_AHB  int ath_ahb_init(void);  void ath_ahb_exit(void);  #else diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index eccb0ec87ad..24f565ba998 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -320,6 +320,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)  	if (avp->av_bcbuf != NULL) {  		struct ath_buf *bf; +		avp->is_bslot_active = false;  		if (avp->av_bslot != -1) {  			sc->beacon.bslot[avp->av_bslot] = NULL;  			sc->nbcnvifs--; @@ -743,9 +744,27 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)  		cur_conf->dtim_period = 1;  	ath_set_beacon(sc); -	sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;  } +static bool ath_has_valid_bslot(struct ath_softc *sc) +{ +	struct ath_vif *avp; +	int slot; +	bool found = false; + +	for (slot = 0; slot < ATH_BCBUF; slot++) { +		if (sc->beacon.bslot[slot]) { +			avp = (void *)sc->beacon.bslot[slot]->drv_priv; +			if (avp->is_bslot_active) { +				found = true; +				break; +			} +		} +	} +	return found; +} + +  void ath_set_beacon(struct ath_softc *sc)  {  	struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@ -753,7 +772,8 @@ void ath_set_beacon(struct ath_softc *sc)  	switch (sc->sc_ah->opmode) {  	case NL80211_IFTYPE_AP: -		ath_beacon_config_ap(sc, cur_conf); +		if (ath_has_valid_bslot(sc)) +			ath_beacon_config_ap(sc, cur_conf);  		break;  	case NL80211_IFTYPE_ADHOC:  	case NL80211_IFTYPE_MESH_POINT: @@ -761,6 +781,12 @@ void ath_set_beacon(struct ath_softc *sc)  		break;  	case NL80211_IFTYPE_STATION:  		ath_beacon_config_sta(sc, cur_conf); +		/* +		 * Request a re-configuration of Beacon related timers +		 * on the receipt of the first Beacon frame (i.e., +		 * after time sync with the AP). +		 */ +		sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;  		break;  	default:  		ath_dbg(common, ATH_DBG_CONFIG, @@ -774,20 +800,8 @@ void ath_set_beacon(struct ath_softc *sc)  void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)  {  	struct ath_hw *ah = sc->sc_ah; -	struct ath_vif *avp; -	int slot; -	bool found = false; -	for (slot = 0; slot < ATH_BCBUF; slot++) { -		if (sc->beacon.bslot[slot]) { -			avp = (void *)sc->beacon.bslot[slot]->drv_priv; -			if (avp->is_bslot_active) { -				found = true; -				break; -			} -		} -	} -	if (!found) +	if (!ath_has_valid_bslot(sc))  		return;  	ath9k_ps_wakeup(sc); diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index a762cadb3ab..34f191ec8e8 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -845,7 +845,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,  	struct ath_softc *sc = file->private_data;  	char *buf; -	unsigned int len = 0, size = 1152; +	unsigned int len = 0, size = 1400;  	ssize_t retval = 0;  	buf = kzalloc(size, GFP_KERNEL); @@ -874,6 +874,34 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,  			"%18s : %10u\n", "DECRYPT BUSY ERR",  			sc->debug.stats.rxstats.decrypt_busy_err); +	len += snprintf(buf + len, size - len, +			"%18s : %10d\n", "RSSI-CTL0", +			sc->debug.stats.rxstats.rs_rssi_ctl0); + +	len += snprintf(buf + len, size - len, +			"%18s : %10d\n", "RSSI-CTL1", +			sc->debug.stats.rxstats.rs_rssi_ctl1); + +	len += snprintf(buf + len, size - len, +			"%18s : %10d\n", "RSSI-CTL2", +			sc->debug.stats.rxstats.rs_rssi_ctl2); + +	len += snprintf(buf + len, size - len, +			"%18s : %10d\n", "RSSI-EXT0", +			sc->debug.stats.rxstats.rs_rssi_ext0); + +	len += snprintf(buf + len, size - len, +			"%18s : %10d\n", "RSSI-EXT1", +			sc->debug.stats.rxstats.rs_rssi_ext1); + +	len += snprintf(buf + len, size - len, +			"%18s : %10d\n", "RSSI-EXT2", +			sc->debug.stats.rxstats.rs_rssi_ext2); + +	len += snprintf(buf + len, size - len, +			"%18s : %10d\n", "Rx Antenna", +			sc->debug.stats.rxstats.rs_antenna); +  	PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN);  	PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);  	PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); @@ -948,6 +976,16 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)  		RX_PHY_ERR_INC(phyerr);  	} +	sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0; +	sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1; +	sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2; + +	sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0; +	sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1; +	sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2; + +	sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna; +  #undef RX_STAT_INC  #undef RX_PHY_ERR_INC  } diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 59338de0ce1..1f9f8eada46 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -157,6 +157,13 @@ struct ath_rx_stats {  	u32 post_delim_crc_err;  	u32 decrypt_busy_err;  	u32 phy_err_stats[ATH9K_PHYERR_MAX]; +	int8_t rs_rssi_ctl0; +	int8_t rs_rssi_ctl1; +	int8_t rs_rssi_ctl2; +	int8_t rs_rssi_ext0; +	int8_t rs_rssi_ext1; +	int8_t rs_rssi_ext2; +	u8 rs_antenna;  };  struct ath_stats { diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index bd82447f5b7..3e316133f11 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -436,7 +436,11 @@ struct modal_eep_4k_header {  	u8 db2_2:4, db2_3:4;  	u8 db2_4:4, reserved:4;  #endif -	u8 futureModal[4]; +	u8 tx_diversity; +	u8 flc_pwr_thresh; +	u8 bb_scale_smrt_antenna; +#define EEP_4K_BB_DESIRED_SCALE_MASK	0x1f +	u8 futureModal[1];  	struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];  } __packed; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index bc77a308c90..6f714dd7236 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -781,6 +781,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,  {  	struct modal_eep_4k_header *pModal;  	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; +	struct base_eep_header_4k *pBase = &eep->baseEepHeader;  	u8 txRxAttenLocal;  	u8 ob[5], db1[5], db2[5];  	u8 ant_div_control1, ant_div_control2; @@ -1003,6 +1004,31 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,  				      AR_PHY_SETTLING_SWITCH,  				      pModal->swSettleHt40);  	} +	if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) { +		u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna & +				EEP_4K_BB_DESIRED_SCALE_MASK); +		if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) { +			u32 pwrctrl, mask, clr; + +			mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); +			pwrctrl = mask * bb_desired_scale; +			clr = mask * 0x1f; +			REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); +			REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); +			REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); + +			mask = BIT(0)|BIT(5)|BIT(15); +			pwrctrl = mask * bb_desired_scale; +			clr = mask * 0x1f; +			REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); + +			mask = BIT(0)|BIT(5); +			pwrctrl = mask * bb_desired_scale; +			clr = mask * 0x1f; +			REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); +			REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); +		} +	}  }  static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 2f0712ea49a..13579752a30 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -858,35 +858,12 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,  {  	struct ar9287_eeprom *eep = &ah->eeprom.map9287;  	struct modal_eep_ar9287_header *pModal = &eep->modalHeader; -	u16 antWrites[AR9287_ANT_16S];  	u32 regChainOffset, regval;  	u8 txRxAttenLocal; -	int i, j, offset_num; +	int i;  	pModal = &eep->modalHeader; -	antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF); -	antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF); -	antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF); -	antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF); -	antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF); -	antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF); -	antWrites[6] = (u16)((pModal->antCtrlCommon >> 4)  & 0xF); -	antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF); - -	offset_num = 8; - -	for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { -		antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf); -		antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3); -		antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3); -		antWrites[j++] = 0; -		antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3); -		antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3); -		antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3); -		antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3); -	} -  	REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);  	for (i = 0; i < AR9287_MAX_CHAINS; i++)	{ diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 2d10239ce82..2e3a33a5340 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -17,11 +17,9 @@  #include "htc.h"  /* identify firmware images */ -#define FIRMWARE_AR7010		"ar7010.fw" -#define FIRMWARE_AR7010_1_1	"ar7010_1_1.fw" -#define FIRMWARE_AR9271		"ar9271.fw" +#define FIRMWARE_AR7010_1_1     "htc_7010.fw" +#define FIRMWARE_AR9271         "htc_9271.fw" -MODULE_FIRMWARE(FIRMWARE_AR7010);  MODULE_FIRMWARE(FIRMWARE_AR7010_1_1);  MODULE_FIRMWARE(FIRMWARE_AR9271); @@ -80,7 +78,7 @@ static void hif_usb_regout_cb(struct urb *urb)  	if (cmd) {  		ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, -					  cmd->skb, 1); +					  cmd->skb, true);  		kfree(cmd);  	} @@ -126,6 +124,90 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,  	return ret;  } +static void hif_usb_mgmt_cb(struct urb *urb) +{ +	struct cmd_buf *cmd = (struct cmd_buf *)urb->context; +	struct hif_device_usb *hif_dev = cmd->hif_dev; +	bool txok = true; + +	if (!cmd || !cmd->skb || !cmd->hif_dev) +		return; + +	switch (urb->status) { +	case 0: +		break; +	case -ENOENT: +	case -ECONNRESET: +	case -ENODEV: +	case -ESHUTDOWN: +		txok = false; + +		/* +		 * If the URBs are being flushed, no need to complete +		 * this packet. +		 */ +		spin_lock(&hif_dev->tx.tx_lock); +		if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { +			spin_unlock(&hif_dev->tx.tx_lock); +			dev_kfree_skb_any(cmd->skb); +			kfree(cmd); +			return; +		} +		spin_unlock(&hif_dev->tx.tx_lock); + +		break; +	default: +		txok = false; +		break; +	} + +	skb_pull(cmd->skb, 4); +	ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, +				  cmd->skb, txok); +	kfree(cmd); +} + +static int hif_usb_send_mgmt(struct hif_device_usb *hif_dev, +			     struct sk_buff *skb) +{ +	struct urb *urb; +	struct cmd_buf *cmd; +	int ret = 0; +	__le16 *hdr; + +	urb = usb_alloc_urb(0, GFP_ATOMIC); +	if (urb == NULL) +		return -ENOMEM; + +	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); +	if (cmd == NULL) { +		usb_free_urb(urb); +		return -ENOMEM; +	} + +	cmd->skb = skb; +	cmd->hif_dev = hif_dev; + +	hdr = (__le16 *) skb_push(skb, 4); +	*hdr++ = cpu_to_le16(skb->len - 4); +	*hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG); + +	usb_fill_bulk_urb(urb, hif_dev->udev, +			 usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE), +			 skb->data, skb->len, +			 hif_usb_mgmt_cb, cmd); + +	usb_anchor_urb(urb, &hif_dev->mgmt_submitted); +	ret = usb_submit_urb(urb, GFP_ATOMIC); +	if (ret) { +		usb_unanchor_urb(urb); +		kfree(cmd); +	} +	usb_free_urb(urb); + +	return ret; +} +  static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,  					 struct sk_buff_head *list)  { @@ -133,7 +215,22 @@ static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,  	while ((skb = __skb_dequeue(list)) != NULL) {  		dev_kfree_skb_any(skb); -		TX_STAT_INC(skb_dropped); +	} +} + +static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev, +					    struct sk_buff_head *queue, +					    bool txok) +{ +	struct sk_buff *skb; + +	while ((skb = __skb_dequeue(queue)) != NULL) { +		ath9k_htc_txcompletion_cb(hif_dev->htc_handle, +					  skb, txok); +		if (txok) +			TX_STAT_INC(skb_success); +		else +			TX_STAT_INC(skb_failed);  	}  } @@ -141,7 +238,7 @@ static void hif_usb_tx_cb(struct urb *urb)  {  	struct tx_buf *tx_buf = (struct tx_buf *) urb->context;  	struct hif_device_usb *hif_dev; -	struct sk_buff *skb; +	bool txok = true;  	if (!tx_buf || !tx_buf->hif_dev)  		return; @@ -155,10 +252,7 @@ static void hif_usb_tx_cb(struct urb *urb)  	case -ECONNRESET:  	case -ENODEV:  	case -ESHUTDOWN: -		/* -		 * The URB has been killed, free the SKBs. -		 */ -		ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); +		txok = false;  		/*  		 * If the URBs are being flushed, no need to add this @@ -167,41 +261,19 @@ static void hif_usb_tx_cb(struct urb *urb)  		spin_lock(&hif_dev->tx.tx_lock);  		if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {  			spin_unlock(&hif_dev->tx.tx_lock); +			ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);  			return;  		}  		spin_unlock(&hif_dev->tx.tx_lock); -		/* -		 * In the stop() case, this URB has to be added to -		 * the free list. -		 */ -		goto add_free; +		break;  	default: +		txok = false;  		break;  	} -	/* -	 * Check if TX has been stopped, this is needed because -	 * this CB could have been invoked just after the TX lock -	 * was released in hif_stop() and kill_urb() hasn't been -	 * called yet. -	 */ -	spin_lock(&hif_dev->tx.tx_lock); -	if (hif_dev->tx.flags & HIF_USB_TX_STOP) { -		spin_unlock(&hif_dev->tx.tx_lock); -		ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); -		goto add_free; -	} -	spin_unlock(&hif_dev->tx.tx_lock); - -	/* Complete the queued SKBs. */ -	while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { -		ath9k_htc_txcompletion_cb(hif_dev->htc_handle, -					  skb, 1); -		TX_STAT_INC(skb_completed); -	} +	ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, txok); -add_free:  	/* Re-initialize the SKB queue */  	tx_buf->len = tx_buf->offset = 0;  	__skb_queue_head_init(&tx_buf->skb_queue); @@ -274,7 +346,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)  	ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC);  	if (ret) {  		tx_buf->len = tx_buf->offset = 0; -		ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); +		ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, false);  		__skb_queue_head_init(&tx_buf->skb_queue);  		list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);  		hif_dev->tx.tx_buf_cnt++; @@ -286,10 +358,11 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)  	return ret;  } -static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb, -			   struct ath9k_htc_tx_ctl *tx_ctl) +static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb)  { +	struct ath9k_htc_tx_ctl *tx_ctl;  	unsigned long flags; +	int ret = 0;  	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); @@ -304,26 +377,36 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb,  		return -ENOMEM;  	} -	__skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); -	hif_dev->tx.tx_skb_cnt++; +	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); -	/* Send normal frames immediately */ -	if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL))) -		__hif_usb_tx(hif_dev); +	tx_ctl = HTC_SKB_CB(skb); + +	/* Mgmt/Beacon frames don't use the TX buffer pool */ +	if ((tx_ctl->type == ATH9K_HTC_MGMT) || +	    (tx_ctl->type == ATH9K_HTC_BEACON)) { +		ret = hif_usb_send_mgmt(hif_dev, skb); +	} + +	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + +	if ((tx_ctl->type == ATH9K_HTC_NORMAL) || +	    (tx_ctl->type == ATH9K_HTC_AMPDU)) { +		__skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); +		hif_dev->tx.tx_skb_cnt++; +	}  	/* Check if AMPDUs have to be sent immediately */ -	if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) && -	    (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && +	if ((hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&  	    (hif_dev->tx.tx_skb_cnt < 2)) {  		__hif_usb_tx(hif_dev);  	}  	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); -	return 0; +	return ret;  } -static void hif_usb_start(void *hif_handle, u8 pipe_id) +static void hif_usb_start(void *hif_handle)  {  	struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;  	unsigned long flags; @@ -335,14 +418,14 @@ static void hif_usb_start(void *hif_handle, u8 pipe_id)  	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);  } -static void hif_usb_stop(void *hif_handle, u8 pipe_id) +static void hif_usb_stop(void *hif_handle)  {  	struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;  	struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;  	unsigned long flags;  	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); -	ath9k_skb_queue_purge(hif_dev, &hif_dev->tx.tx_skb_queue); +	ath9k_skb_queue_complete(hif_dev, &hif_dev->tx.tx_skb_queue, false);  	hif_dev->tx.tx_skb_cnt = 0;  	hif_dev->tx.flags |= HIF_USB_TX_STOP;  	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); @@ -352,17 +435,18 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id)  				 &hif_dev->tx.tx_pending, list) {  		usb_kill_urb(tx_buf->urb);  	} + +	usb_kill_anchored_urbs(&hif_dev->mgmt_submitted);  } -static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, -			struct ath9k_htc_tx_ctl *tx_ctl) +static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb)  {  	struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;  	int ret = 0;  	switch (pipe_id) {  	case USB_WLAN_TX_PIPE: -		ret = hif_usb_send_tx(hif_dev, skb, tx_ctl); +		ret = hif_usb_send_tx(hif_dev, skb);  		break;  	case USB_REG_OUT_PIPE:  		ret = hif_usb_send_regout(hif_dev, skb); @@ -377,6 +461,40 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,  	return ret;  } +static inline bool check_index(struct sk_buff *skb, u8 idx) +{ +	struct ath9k_htc_tx_ctl *tx_ctl; + +	tx_ctl = HTC_SKB_CB(skb); + +	if ((tx_ctl->type == ATH9K_HTC_AMPDU) && +	    (tx_ctl->sta_idx == idx)) +		return true; + +	return false; +} + +static void hif_usb_sta_drain(void *hif_handle, u8 idx) +{ +	struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; +	struct sk_buff *skb, *tmp; +	unsigned long flags; + +	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + +	skb_queue_walk_safe(&hif_dev->tx.tx_skb_queue, skb, tmp) { +		if (check_index(skb, idx)) { +			__skb_unlink(skb, &hif_dev->tx.tx_skb_queue); +			ath9k_htc_txcompletion_cb(hif_dev->htc_handle, +						  skb, false); +			hif_dev->tx.tx_skb_cnt--; +			TX_STAT_INC(skb_failed); +		} +	} + +	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); +} +  static struct ath9k_htc_hif hif_usb = {  	.transport = ATH9K_HIF_USB,  	.name = "ath9k_hif_usb", @@ -386,6 +504,7 @@ static struct ath9k_htc_hif hif_usb = {  	.start = hif_usb_start,  	.stop = hif_usb_stop, +	.sta_drain = hif_usb_sta_drain,  	.send = hif_usb_send,  }; @@ -567,6 +686,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)  	case -ESHUTDOWN:  		goto free;  	default: +		skb_reset_tail_pointer(skb); +		skb_trim(skb, 0); +  		goto resubmit;  	} @@ -591,23 +713,15 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)  						 USB_REG_IN_PIPE),  				 nskb->data, MAX_REG_IN_BUF_SIZE,  				 ath9k_hif_usb_reg_in_cb, nskb); - -		ret = usb_submit_urb(urb, GFP_ATOMIC); -		if (ret) { -			kfree_skb(nskb); -			urb->context = NULL; -		} - -		return;  	}  resubmit: -	skb_reset_tail_pointer(skb); -	skb_trim(skb, 0); - +	usb_anchor_urb(urb, &hif_dev->reg_in_submitted);  	ret = usb_submit_urb(urb, GFP_ATOMIC); -	if (ret) +	if (ret) { +		usb_unanchor_urb(urb);  		goto free; +	}  	return;  free: @@ -641,6 +755,8 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)  		kfree(tx_buf->buf);  		kfree(tx_buf);  	} + +	usb_kill_anchored_urbs(&hif_dev->mgmt_submitted);  }  static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) @@ -652,6 +768,7 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)  	INIT_LIST_HEAD(&hif_dev->tx.tx_pending);  	spin_lock_init(&hif_dev->tx.tx_lock);  	__skb_queue_head_init(&hif_dev->tx.tx_skb_queue); +	init_usb_anchor(&hif_dev->mgmt_submitted);  	for (i = 0; i < MAX_TX_URB_NUM; i++) {  		tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); @@ -748,43 +865,67 @@ err_urb:  	return ret;  } -static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev) +static void ath9k_hif_usb_dealloc_reg_in_urbs(struct hif_device_usb *hif_dev)  { -	if (hif_dev->reg_in_urb) { -		usb_kill_urb(hif_dev->reg_in_urb); -		if (hif_dev->reg_in_urb->context) -			kfree_skb((void *)hif_dev->reg_in_urb->context); -		usb_free_urb(hif_dev->reg_in_urb); -		hif_dev->reg_in_urb = NULL; -	} +	usb_kill_anchored_urbs(&hif_dev->reg_in_submitted);  } -static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) +static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev)  { -	struct sk_buff *skb; +	struct urb *urb = NULL; +	struct sk_buff *skb = NULL; +	int i, ret; -	hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL); -	if (hif_dev->reg_in_urb == NULL) -		return -ENOMEM; +	init_usb_anchor(&hif_dev->reg_in_submitted); -	skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); -	if (!skb) -		goto err; +	for (i = 0; i < MAX_REG_IN_URB_NUM; i++) { -	usb_fill_bulk_urb(hif_dev->reg_in_urb, hif_dev->udev, -			 usb_rcvbulkpipe(hif_dev->udev, -					 USB_REG_IN_PIPE), -			 skb->data, MAX_REG_IN_BUF_SIZE, -			 ath9k_hif_usb_reg_in_cb, skb); +		/* Allocate URB */ +		urb = usb_alloc_urb(0, GFP_KERNEL); +		if (urb == NULL) { +			ret = -ENOMEM; +			goto err_urb; +		} -	if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) -		goto err; +		/* Allocate buffer */ +		skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); +		if (!skb) { +			ret = -ENOMEM; +			goto err_skb; +		} + +		usb_fill_bulk_urb(urb, hif_dev->udev, +				  usb_rcvbulkpipe(hif_dev->udev, +						  USB_REG_IN_PIPE), +				  skb->data, MAX_REG_IN_BUF_SIZE, +				  ath9k_hif_usb_reg_in_cb, skb); + +		/* Anchor URB */ +		usb_anchor_urb(urb, &hif_dev->reg_in_submitted); + +		/* Submit URB */ +		ret = usb_submit_urb(urb, GFP_KERNEL); +		if (ret) { +			usb_unanchor_urb(urb); +			goto err_submit; +		} + +		/* +		 * Drop reference count. +		 * This ensures that the URB is freed when killing them. +		 */ +		usb_free_urb(urb); +	}  	return 0; -err: -	ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); -	return -ENOMEM; +err_submit: +	kfree_skb(skb); +err_skb: +	usb_free_urb(urb); +err_urb: +	ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev); +	return ret;  }  static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) @@ -801,7 +942,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)  		goto err_rx;  	/* Register Read */ -	if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) +	if (ath9k_hif_usb_alloc_reg_in_urbs(hif_dev) < 0)  		goto err_reg;  	return 0; @@ -816,7 +957,7 @@ err:  static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)  {  	usb_kill_anchored_urbs(&hif_dev->regout_submitted); -	ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); +	ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);  	ath9k_hif_usb_dealloc_tx_urbs(hif_dev);  	ath9k_hif_usb_dealloc_rx_urbs(hif_dev);  } @@ -1026,10 +1167,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,  	/* Find out which firmware to load */  	if (IS_AR7010_DEVICE(id->driver_info)) -		if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) -			hif_dev->fw_name = FIRMWARE_AR7010_1_1; -		else -			hif_dev->fw_name = FIRMWARE_AR7010; +		hif_dev->fw_name = FIRMWARE_AR7010_1_1;  	else  		hif_dev->fw_name = FIRMWARE_AR9271; diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 7b9d863d403..f59df48a86e 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -31,7 +31,7 @@  /* FIXME: Verify these numbers (with Windows) */  #define MAX_TX_URB_NUM  8 -#define MAX_TX_BUF_NUM  1024 +#define MAX_TX_BUF_NUM  256  #define MAX_TX_BUF_SIZE 32768  #define MAX_TX_AGGR_NUM 20 @@ -40,7 +40,7 @@  #define MAX_PKT_NUM_IN_TRANSFER 10  #define MAX_REG_OUT_URB_NUM  1 -#define MAX_REG_OUT_BUF_NUM  8 +#define MAX_REG_IN_URB_NUM   64  #define MAX_REG_IN_BUF_SIZE 64 @@ -90,9 +90,10 @@ struct hif_device_usb {  	const struct firmware *firmware;  	struct htc_target *htc_handle;  	struct hif_usb_tx tx; -	struct urb *reg_in_urb;  	struct usb_anchor regout_submitted;  	struct usb_anchor rx_submitted; +	struct usb_anchor reg_in_submitted; +	struct usb_anchor mgmt_submitted;  	struct sk_buff *remain_skb;  	const char *fw_name;  	int rx_remain_len; diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index ec47be94b74..48a88557508 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -67,8 +67,11 @@ enum htc_opmode {  };  #define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr) -#define ATH9K_HTC_AMPDU	1 + +#define ATH9K_HTC_AMPDU  1  #define ATH9K_HTC_NORMAL 2 +#define ATH9K_HTC_BEACON 3 +#define ATH9K_HTC_MGMT   4  #define ATH9K_HTC_TX_CTSONLY      0x1  #define ATH9K_HTC_TX_RTSCTS       0x2 @@ -82,7 +85,8 @@ struct tx_frame_hdr {  	__be32 flags; /* ATH9K_HTC_TX_* */  	u8 key_type;  	u8 keyix; -	u8 reserved[26]; +	u8 cookie; +	u8 pad;  } __packed;  struct tx_mgmt_hdr { @@ -92,26 +96,16 @@ struct tx_mgmt_hdr {  	u8 flags;  	u8 key_type;  	u8 keyix; -	u16 reserved; +	u8 cookie; +	u8 pad;  } __packed;  struct tx_beacon_header { -	u8 len_changed;  	u8 vif_index; +	u8 len_changed;  	u16 rev;  } __packed; -struct ath9k_htc_target_hw { -	u32 flags; -	u32 flags_ext; -	u32 ampdu_limit; -	u8 ampdu_subframes; -	u8 tx_chainmask; -	u8 tx_chainmask_legacy; -	u8 rtscts_ratecode; -	u8 protmode; -} __packed; -  struct ath9k_htc_cap_target {  	u32 flags;  	u32 flags_ext; @@ -121,21 +115,16 @@ struct ath9k_htc_cap_target {  	u8 tx_chainmask_legacy;  	u8 rtscts_ratecode;  	u8 protmode; +	u8 pad;  } __packed;  struct ath9k_htc_target_vif {  	u8 index; -	u8 des_bssid[ETH_ALEN]; -	__be32 opmode; +	u8 opmode;  	u8 myaddr[ETH_ALEN]; -	u8 bssid[ETH_ALEN]; -	u32 flags; -	u32 flags_ext; -	u16 ps_sta; -	__be16 rtsthreshold;  	u8 ath_cap; -	u8 node; -	s8 mcast_rate; +	__be16 rtsthreshold; +	u8 pad;  } __packed;  #define ATH_HTC_STA_AUTH  0x0001 @@ -143,27 +132,16 @@ struct ath9k_htc_target_vif {  #define ATH_HTC_STA_ERP   0x0004  #define ATH_HTC_STA_HT    0x0008 -/* FIXME: UAPSD variables */  struct ath9k_htc_target_sta { -	u16 associd; -	u16 txpower; -	u32 ucastkey;  	u8 macaddr[ETH_ALEN];  	u8 bssid[ETH_ALEN];  	u8 sta_index;  	u8 vif_index; -	u8 vif_sta; -	__be16 flags; /* ATH_HTC_STA_* */ -	u16 htcap; -	u8 valid; -	u16 capinfo; -	struct ath9k_htc_target_hw *hw; -	struct ath9k_htc_target_vif *vif; -	u16 txseqmgmt;  	u8 is_vif_sta; -	u16 maxampdu; -	u16 iv16; -	u32 iv32; +	__be16 flags; /* ATH_HTC_STA_* */ +	__be16 htcap; +	__be16 maxampdu; +	u8 pad;  } __packed;  struct ath9k_htc_target_aggr { @@ -197,12 +175,31 @@ struct ath9k_htc_target_rate {  	struct ath9k_htc_rate rates;  }; -struct ath9k_htc_target_stats { -	__be32 tx_shortretry; -	__be32 tx_longretry; -	__be32 tx_xretries; -	__be32 ht_txunaggr_xretry; -	__be32 ht_tx_xretries; +struct ath9k_htc_target_int_stats { +	__be32 rx; +	__be32 rxorn; +	__be32 rxeol; +	__be32 txurn; +	__be32 txto; +	__be32 cst; +} __packed; + +struct ath9k_htc_target_tx_stats { +	__be32 xretries; +	__be32 fifoerr; +	__be32 filtered; +	__be32 timer_exp; +	__be32 shortretries; +	__be32 longretries; +	__be32 qnull; +	__be32 encap_fail; +	__be32 nobuf; +} __packed; + +struct ath9k_htc_target_rx_stats { +	__be32 nobuf; +	__be32 host_send; +	__be32 host_done;  } __packed;  #define ATH9K_HTC_MAX_VIF 2 @@ -244,6 +241,8 @@ struct ath9k_htc_vif {  	u8 index;  	u16 seq_no;  	bool beacon_configured; +	int bslot; +	__le64 tsfadjust;  };  struct ath9k_vif_iter_data { @@ -282,23 +281,65 @@ struct ath9k_htc_rx {  	spinlock_t rxbuflock;  }; +#define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */ +#define ATH9K_HTC_TX_TIMEOUT_INTERVAL 2500 /* ms */ +#define ATH9K_HTC_TX_RESERVE 10 +#define ATH9K_HTC_TX_TIMEOUT_COUNT 20 +#define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE) + +#define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0) +#define ATH9K_HTC_OP_TX_DRAIN       BIT(1) + +struct ath9k_htc_tx { +	u8 flags; +	int queued_cnt; +	struct sk_buff_head mgmt_ep_queue; +	struct sk_buff_head cab_ep_queue; +	struct sk_buff_head data_be_queue; +	struct sk_buff_head data_bk_queue; +	struct sk_buff_head data_vi_queue; +	struct sk_buff_head data_vo_queue; +	struct sk_buff_head tx_failed; +	DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM); +	struct timer_list cleanup_timer; +	spinlock_t tx_lock; +}; +  struct ath9k_htc_tx_ctl {  	u8 type; /* ATH9K_HTC_* */ +	u8 epid; +	u8 txok; +	u8 sta_idx; +	unsigned long timestamp;  }; +static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) +{ +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + +	BUILD_BUG_ON(sizeof(struct ath9k_htc_tx_ctl) > +		     IEEE80211_TX_INFO_DRIVER_DATA_SIZE); +	return (struct ath9k_htc_tx_ctl *) &tx_info->driver_data; +} +  #ifdef CONFIG_ATH9K_HTC_DEBUGFS  #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)  #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) +#define CAB_STAT_INC   priv->debug.tx_stats.cab_queued++  #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) +void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, +			   struct ath_htc_rx_status *rxs); +  struct ath_tx_stats {  	u32 buf_queued;  	u32 buf_completed;  	u32 skb_queued; -	u32 skb_completed; -	u32 skb_dropped; +	u32 skb_success; +	u32 skb_failed; +	u32 cab_queued;  	u32 queue_stats[WME_NUM_AC];  }; @@ -306,25 +347,35 @@ struct ath_rx_stats {  	u32 skb_allocated;  	u32 skb_completed;  	u32 skb_dropped; +	u32 err_crc; +	u32 err_decrypt_crc; +	u32 err_mic; +	u32 err_pre_delim; +	u32 err_post_delim; +	u32 err_decrypt_busy; +	u32 err_phy; +	u32 err_phy_stats[ATH9K_PHYERR_MAX];  };  struct ath9k_debug {  	struct dentry *debugfs_phy; -	struct dentry *debugfs_tgt_stats; -	struct dentry *debugfs_xmit; -	struct dentry *debugfs_recv;  	struct ath_tx_stats tx_stats;  	struct ath_rx_stats rx_stats; -	u32 txrate;  };  #else  #define TX_STAT_INC(c) do { } while (0)  #define RX_STAT_INC(c) do { } while (0) +#define CAB_STAT_INC   do { } while (0)  #define TX_QSTAT_INC(c) do { } while (0) +static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, +					 struct ath_htc_rx_status *rxs) +{ +} +  #endif /* CONFIG_ATH9K_HTC_DEBUGFS */  #define ATH_LED_PIN_DEF             1 @@ -351,10 +402,21 @@ struct ath_led {  	int brightness;  }; +#define BSTUCK_THRESHOLD 10 + +/* + * Adjust these when the max. no of beaconing interfaces is + * increased. + */ +#define DEFAULT_SWBA_RESPONSE 40 /* in TUs */ +#define MIN_SWBA_RESPONSE     10 /* in TUs */ +  struct htc_beacon_config { +	struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF];  	u16 beacon_interval;  	u16 dtim_period;  	u16 bmiss_timeout; +	u32 bmiss_cnt;  };  struct ath_btcoex { @@ -388,6 +450,9 @@ struct ath9k_htc_priv {  	struct htc_target *htc;  	struct wmi *wmi; +	u16 fw_version_major; +	u16 fw_version_minor; +  	enum htc_endpoint_id wmi_cmd_ep;  	enum htc_endpoint_id beacon_ep;  	enum htc_endpoint_id cab_ep; @@ -411,27 +476,23 @@ struct ath9k_htc_priv {  	u16 txpowlimit;  	u16 nvifs;  	u16 nstations; -	u32 bmiss_cnt;  	bool rearm_ani;  	bool reconfig_beacon; +	unsigned int rxfilter;  	struct ath9k_hw_cal_data caldata; +	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];  	spinlock_t beacon_lock; +	struct htc_beacon_config cur_beacon_conf; -	bool tx_queues_stop; -	spinlock_t tx_lock; +	struct ath9k_htc_rx rx; +	struct ath9k_htc_tx tx; -	struct ieee80211_vif *vif; -	struct htc_beacon_config cur_beacon_conf; -	unsigned int rxfilter;  	struct tasklet_struct swba_tasklet;  	struct tasklet_struct rx_tasklet; -	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; -	struct ath9k_htc_rx rx; -	struct tasklet_struct tx_tasklet; -	struct sk_buff_head tx_queue;  	struct delayed_work ani_work; +	struct tasklet_struct tx_failed_tasklet;  	struct work_struct ps_work;  	struct work_struct fatal_work; @@ -470,11 +531,18 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)  void ath9k_htc_reset(struct ath9k_htc_priv *priv); +void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, +			    struct ieee80211_vif *vif); +void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, +			    struct ieee80211_vif *vif); +void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, +			     struct ieee80211_vif *vif);  void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);  void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,  			     struct ieee80211_vif *vif);  void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv); -void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); +void ath9k_htc_swba(struct ath9k_htc_priv *priv, +		    struct wmi_event_swba *swba);  void ath9k_htc_rxep(void *priv, struct sk_buff *skb,  		    enum htc_endpoint_id ep_id); @@ -491,14 +559,23 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv);  void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv);  int ath9k_tx_init(struct ath9k_htc_priv *priv); -void ath9k_tx_tasklet(unsigned long data); -int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); +int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, +		       struct sk_buff *skb, u8 slot, bool is_cab);  void ath9k_tx_cleanup(struct ath9k_htc_priv *priv);  bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype);  int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv);  int get_hw_qnum(u16 queue, int *hwq_map);  int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,  		       struct ath9k_tx_queue_info *qinfo); +void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv); +void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv); +int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv); +void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot); +void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv); +void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event); +void ath9k_htc_tx_failed(struct ath9k_htc_priv *priv); +void ath9k_tx_failed_tasklet(unsigned long data); +void ath9k_htc_tx_cleanup_timer(unsigned long data);  int ath9k_rx_init(struct ath9k_htc_priv *priv);  void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); @@ -528,15 +605,9 @@ void ath9k_htc_suspend(struct htc_target *htc_handle);  int ath9k_htc_resume(struct htc_target *htc_handle);  #endif  #ifdef CONFIG_ATH9K_HTC_DEBUGFS -int ath9k_htc_debug_create_root(void); -void ath9k_htc_debug_remove_root(void);  int ath9k_htc_init_debug(struct ath_hw *ah); -void ath9k_htc_exit_debug(struct ath_hw *ah);  #else -static inline int ath9k_htc_debug_create_root(void) { return 0; }; -static inline void ath9k_htc_debug_remove_root(void) {};  static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; -static inline void ath9k_htc_exit_debug(struct ath_hw *ah) {};  #endif /* CONFIG_ATH9K_HTC_DEBUGFS */  #endif /* HTC_H */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 8f56158e588..a157107b3f3 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -18,6 +18,50 @@  #define FUDGE 2 +void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) +{ +	struct ath_hw *ah = priv->ah; +	struct ath9k_tx_queue_info qi, qi_be; + +	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); +	memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); + +	ath9k_hw_get_txq_props(ah, priv->beaconq, &qi); + +	if (priv->ah->opmode == NL80211_IFTYPE_AP) { +		qi.tqi_aifs = 1; +		qi.tqi_cwmin = 0; +		qi.tqi_cwmax = 0; +	} else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { +		int qnum = priv->hwq_map[WME_AC_BE]; + +		ath9k_hw_get_txq_props(ah, qnum, &qi_be); + +		qi.tqi_aifs = qi_be.tqi_aifs; + +		/* +		 * For WIFI Beacon Distribution +		 * Long slot time  : 2x cwmin +		 * Short slot time : 4x cwmin +		 */ +		if (ah->slottime == ATH9K_SLOT_TIME_20) +			qi.tqi_cwmin = 2*qi_be.tqi_cwmin; +		else +			qi.tqi_cwmin = 4*qi_be.tqi_cwmin; + +		qi.tqi_cwmax = qi_be.tqi_cwmax; + +	} + +	if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { +		ath_err(ath9k_hw_common(ah), +			"Unable to update beacon queue %u!\n", priv->beaconq); +	} else { +		ath9k_hw_resettxqueue(ah, priv->beaconq); +	} +} + +  static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,  					struct htc_beacon_config *bss_conf)  { @@ -154,6 +198,15 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,  	intval /= ATH9K_HTC_MAX_BCN_VIF;  	nexttbtt = intval; +	/* +	 * To reduce beacon misses under heavy TX load, +	 * set the beacon response time to a larger value. +	 */ +	if (intval > DEFAULT_SWBA_RESPONSE) +		priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; +	else +		priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; +  	if (priv->op_flags & OP_TSF_RESET) {  		ath9k_hw_reset_tsf(priv->ah);  		priv->op_flags &= ~OP_TSF_RESET; @@ -172,12 +225,16 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,  		imask |= ATH9K_INT_SWBA;  	ath_dbg(common, ATH_DBG_CONFIG, -		"AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n", -		bss_conf->beacon_interval, nexttbtt, imask); +		"AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d " +		"imask: 0x%x\n", +		bss_conf->beacon_interval, nexttbtt, +		priv->ah->config.sw_beacon_response_time, imask); + +	ath9k_htc_beaconq_config(priv);  	WMI_CMD(WMI_DISABLE_INTR_CMDID);  	ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); -	priv->bmiss_cnt = 0; +	priv->cur_beacon_conf.bmiss_cnt = 0;  	htc_imask = cpu_to_be32(imask);  	WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);  } @@ -205,16 +262,26 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,  		nexttbtt += intval;  	} while (nexttbtt < tsftu); +	/* +	 * Only one IBSS interfce is allowed. +	 */ +	if (intval > DEFAULT_SWBA_RESPONSE) +		priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; +	else +		priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; +  	if (priv->op_flags & OP_ENABLE_BEACON)  		imask |= ATH9K_INT_SWBA;  	ath_dbg(common, ATH_DBG_CONFIG, -		"IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n", -		bss_conf->beacon_interval, nexttbtt, imask); +		"IBSS Beacon config, intval: %d, nexttbtt: %u, " +		"resp_time: %d, imask: 0x%x\n", +		bss_conf->beacon_interval, nexttbtt, +		priv->ah->config.sw_beacon_response_time, imask);  	WMI_CMD(WMI_DISABLE_INTR_CMDID);  	ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); -	priv->bmiss_cnt = 0; +	priv->cur_beacon_conf.bmiss_cnt = 0;  	htc_imask = cpu_to_be32(imask);  	WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);  } @@ -225,38 +292,101 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,  	dev_kfree_skb_any(skb);  } -void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) +static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, +				    int slot)  { -	struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv; +	struct ath_common *common = ath9k_hw_common(priv->ah); +	struct ieee80211_vif *vif; +	struct sk_buff *skb; +	struct ieee80211_hdr *hdr; +	int padpos, padsize, ret, tx_slot; + +	spin_lock_bh(&priv->beacon_lock); + +	vif = priv->cur_beacon_conf.bslot[slot]; + +	skb = ieee80211_get_buffered_bc(priv->hw, vif); + +	while(skb) { +		hdr = (struct ieee80211_hdr *) skb->data; + +		padpos = ath9k_cmn_padpos(hdr->frame_control); +		padsize = padpos & 3; +		if (padsize && skb->len > padpos) { +			if (skb_headroom(skb) < padsize) { +				dev_kfree_skb_any(skb); +				goto next; +			} +			skb_push(skb, padsize); +			memmove(skb->data, skb->data + padsize, padpos); +		} + +		tx_slot = ath9k_htc_tx_get_slot(priv); +		if (tx_slot < 0) { +			ath_dbg(common, ATH_DBG_XMIT, "No free CAB slot\n"); +			dev_kfree_skb_any(skb); +			goto next; +		} + +		ret = ath9k_htc_tx_start(priv, skb, tx_slot, true); +		if (ret != 0) { +			ath9k_htc_tx_clear_slot(priv, tx_slot); +			dev_kfree_skb_any(skb); + +			ath_dbg(common, ATH_DBG_XMIT, +				"Failed to send CAB frame\n"); +		} else { +			spin_lock_bh(&priv->tx.tx_lock); +			priv->tx.queued_cnt++; +			spin_unlock_bh(&priv->tx.tx_lock); +		} +	next: +		skb = ieee80211_get_buffered_bc(priv->hw, vif); +	} + +	spin_unlock_bh(&priv->beacon_lock); +} + +static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, +				  int slot) +{ +	struct ath_common *common = ath9k_hw_common(priv->ah); +	struct ieee80211_vif *vif; +	struct ath9k_htc_vif *avp;  	struct tx_beacon_header beacon_hdr; -	struct ath9k_htc_tx_ctl tx_ctl; +	struct ath9k_htc_tx_ctl *tx_ctl;  	struct ieee80211_tx_info *info; +	struct ieee80211_mgmt *mgmt;  	struct sk_buff *beacon;  	u8 *tx_fhdr; +	int ret;  	memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); -	memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); - -	/* FIXME: Handle BMISS */ -	if (beacon_pending != 0) { -		priv->bmiss_cnt++; -		return; -	}  	spin_lock_bh(&priv->beacon_lock); +	vif = priv->cur_beacon_conf.bslot[slot]; +	avp = (struct ath9k_htc_vif *)vif->drv_priv; +  	if (unlikely(priv->op_flags & OP_SCANNING)) {  		spin_unlock_bh(&priv->beacon_lock);  		return;  	}  	/* Get a new beacon */ -	beacon = ieee80211_beacon_get(priv->hw, priv->vif); +	beacon = ieee80211_beacon_get(priv->hw, vif);  	if (!beacon) {  		spin_unlock_bh(&priv->beacon_lock);  		return;  	} +	/* +	 * Update the TSF adjust value here, the HW will +	 * add this value for every beacon. +	 */ +	mgmt = (struct ieee80211_mgmt *)beacon->data; +	mgmt->u.beacon.timestamp = avp->tsfadjust; +  	info = IEEE80211_SKB_CB(beacon);  	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {  		struct ieee80211_hdr *hdr = @@ -266,45 +396,149 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)  		hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);  	} -	tx_ctl.type = ATH9K_HTC_NORMAL; +	tx_ctl = HTC_SKB_CB(beacon); +	memset(tx_ctl, 0, sizeof(*tx_ctl)); + +	tx_ctl->type = ATH9K_HTC_BEACON; +	tx_ctl->epid = priv->beacon_ep; +  	beacon_hdr.vif_index = avp->index;  	tx_fhdr = skb_push(beacon, sizeof(beacon_hdr));  	memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); -	htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); +	ret = htc_send(priv->htc, beacon); +	if (ret != 0) { +		if (ret == -ENOMEM) { +			ath_dbg(common, ATH_DBG_BSTUCK, +				"Failed to send beacon, no free TX buffer\n"); +		} +		dev_kfree_skb_any(beacon); +	} + +	spin_unlock_bh(&priv->beacon_lock); +} + +static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv, +				  struct wmi_event_swba *swba) +{ +	struct ath_common *common = ath9k_hw_common(priv->ah); +	u64 tsf; +	u32 tsftu; +	u16 intval; +	int slot; + +	intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD; +	tsf = be64_to_cpu(swba->tsf); +	tsftu = TSF_TO_TU(tsf >> 32, tsf); +	slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval; +	slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1; + +	ath_dbg(common, ATH_DBG_BEACON, +		"Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n", +		slot, tsf, tsftu, intval); + +	return slot; +} + +void ath9k_htc_swba(struct ath9k_htc_priv *priv, +		    struct wmi_event_swba *swba) +{ +	struct ath_common *common = ath9k_hw_common(priv->ah); +	int slot; + +	if (swba->beacon_pending != 0) { +		priv->cur_beacon_conf.bmiss_cnt++; +		if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) { +			ath_dbg(common, ATH_DBG_BSTUCK, +				"Beacon stuck, HW reset\n"); +			ieee80211_queue_work(priv->hw, +					     &priv->fatal_work); +		} +		return; +	} + +	if (priv->cur_beacon_conf.bmiss_cnt) { +		ath_dbg(common, ATH_DBG_BSTUCK, +			"Resuming beacon xmit after %u misses\n", +			priv->cur_beacon_conf.bmiss_cnt); +		priv->cur_beacon_conf.bmiss_cnt = 0; +	} + +	slot = ath9k_htc_choose_bslot(priv, swba); +	spin_lock_bh(&priv->beacon_lock); +	if (priv->cur_beacon_conf.bslot[slot] == NULL) { +		spin_unlock_bh(&priv->beacon_lock); +		return; +	}  	spin_unlock_bh(&priv->beacon_lock); + +	ath9k_htc_send_buffered(priv, slot); +	ath9k_htc_send_beacon(priv, slot);  } -/* Currently, only for IBSS */ -void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) +void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, +			    struct ieee80211_vif *vif)  { -	struct ath_hw *ah = priv->ah; -	struct ath9k_tx_queue_info qi, qi_be; -	int qnum = priv->hwq_map[WME_AC_BE]; +	struct ath_common *common = ath9k_hw_common(priv->ah); +	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; +	int i = 0; -	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); -	memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); +	spin_lock_bh(&priv->beacon_lock); +	for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) { +		if (priv->cur_beacon_conf.bslot[i] == NULL) { +			avp->bslot = i; +			break; +		} +	} -	ath9k_hw_get_txq_props(ah, qnum, &qi_be); +	priv->cur_beacon_conf.bslot[avp->bslot] = vif; +	spin_unlock_bh(&priv->beacon_lock); -	qi.tqi_aifs = qi_be.tqi_aifs; -	/* For WIFI Beacon Distribution -	 * Long slot time  : 2x cwmin -	 * Short slot time : 4x cwmin +	ath_dbg(common, ATH_DBG_CONFIG, +		"Added interface at beacon slot: %d\n", avp->bslot); +} + +void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, +			    struct ieee80211_vif *vif) +{ +	struct ath_common *common = ath9k_hw_common(priv->ah); +	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; + +	spin_lock_bh(&priv->beacon_lock); +	priv->cur_beacon_conf.bslot[avp->bslot] = NULL; +	spin_unlock_bh(&priv->beacon_lock); + +	ath_dbg(common, ATH_DBG_CONFIG, +		"Removed interface at beacon slot: %d\n", avp->bslot); +} + +/* + * Calculate the TSF adjustment value for all slots + * other than zero. + */ +void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, +			     struct ieee80211_vif *vif) +{ +	struct ath_common *common = ath9k_hw_common(priv->ah); +	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; +	struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; +	u64 tsfadjust; + +	if (avp->bslot == 0) +		return; + +	/* +	 * The beacon interval cannot be different for multi-AP mode, +	 * and we reach here only for VIF slots greater than zero, +	 * so beacon_interval is guaranteed to be set in cur_conf.  	 */ -	if (ah->slottime == ATH9K_SLOT_TIME_20) -		qi.tqi_cwmin = 2*qi_be.tqi_cwmin; -	else -		qi.tqi_cwmin = 4*qi_be.tqi_cwmin; -	qi.tqi_cwmax = qi_be.tqi_cwmax; +	tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF; +	avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); -	if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { -		ath_err(ath9k_hw_common(ah), -			"Unable to update beacon queue %u!\n", qnum); -	} else { -		ath9k_hw_resettxqueue(ah, priv->beaconq); -	} +	ath_dbg(common, ATH_DBG_CONFIG, +		"tsfadjust is: %llu for bslot: %d\n", +		(unsigned long long)tsfadjust, avp->bslot);  }  static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c new file mode 100644 index 00000000000..eca777497fe --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -0,0 +1,505 @@ +/* + * Copyright (c) 2010-2011 Atheros Communications Inc. + * + * 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. + */ + +#include "htc.h" + +static int ath9k_debugfs_open(struct inode *inode, struct file *file) +{ +	file->private_data = inode->i_private; +	return 0; +} + +static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf, +				       size_t count, loff_t *ppos) +{ +	struct ath9k_htc_priv *priv = file->private_data; +	struct ath9k_htc_target_int_stats cmd_rsp; +	char buf[512]; +	unsigned int len = 0; +	int ret = 0; + +	memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + +	WMI_CMD(WMI_INT_STATS_CMDID); +	if (ret) +		return -EINVAL; + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "RX", +			be32_to_cpu(cmd_rsp.rx)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "RXORN", +			be32_to_cpu(cmd_rsp.rxorn)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "RXEOL", +			be32_to_cpu(cmd_rsp.rxeol)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "TXURN", +			be32_to_cpu(cmd_rsp.txurn)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "TXTO", +			be32_to_cpu(cmd_rsp.txto)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "CST", +			be32_to_cpu(cmd_rsp.cst)); + +	if (len > sizeof(buf)) +		len = sizeof(buf); + +	return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_tgt_int_stats = { +	.read = read_file_tgt_int_stats, +	.open = ath9k_debugfs_open, +	.owner = THIS_MODULE, +	.llseek = default_llseek, +}; + +static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf, +				      size_t count, loff_t *ppos) +{ +	struct ath9k_htc_priv *priv = file->private_data; +	struct ath9k_htc_target_tx_stats cmd_rsp; +	char buf[512]; +	unsigned int len = 0; +	int ret = 0; + +	memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + +	WMI_CMD(WMI_TX_STATS_CMDID); +	if (ret) +		return -EINVAL; + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "Xretries", +			be32_to_cpu(cmd_rsp.xretries)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "FifoErr", +			be32_to_cpu(cmd_rsp.fifoerr)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "Filtered", +			be32_to_cpu(cmd_rsp.filtered)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "TimerExp", +			be32_to_cpu(cmd_rsp.timer_exp)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "ShortRetries", +			be32_to_cpu(cmd_rsp.shortretries)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "LongRetries", +			be32_to_cpu(cmd_rsp.longretries)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "QueueNull", +			be32_to_cpu(cmd_rsp.qnull)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "EncapFail", +			be32_to_cpu(cmd_rsp.encap_fail)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "NoBuf", +			be32_to_cpu(cmd_rsp.nobuf)); + +	if (len > sizeof(buf)) +		len = sizeof(buf); + +	return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_tgt_tx_stats = { +	.read = read_file_tgt_tx_stats, +	.open = ath9k_debugfs_open, +	.owner = THIS_MODULE, +	.llseek = default_llseek, +}; + +static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf, +				      size_t count, loff_t *ppos) +{ +	struct ath9k_htc_priv *priv = file->private_data; +	struct ath9k_htc_target_rx_stats cmd_rsp; +	char buf[512]; +	unsigned int len = 0; +	int ret = 0; + +	memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + +	WMI_CMD(WMI_RX_STATS_CMDID); +	if (ret) +		return -EINVAL; + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "NoBuf", +			be32_to_cpu(cmd_rsp.nobuf)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "HostSend", +			be32_to_cpu(cmd_rsp.host_send)); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "HostDone", +			be32_to_cpu(cmd_rsp.host_done)); + +	if (len > sizeof(buf)) +		len = sizeof(buf); + +	return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_tgt_rx_stats = { +	.read = read_file_tgt_rx_stats, +	.open = ath9k_debugfs_open, +	.owner = THIS_MODULE, +	.llseek = default_llseek, +}; + +static ssize_t read_file_xmit(struct file *file, char __user *user_buf, +			      size_t count, loff_t *ppos) +{ +	struct ath9k_htc_priv *priv = file->private_data; +	char buf[512]; +	unsigned int len = 0; + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "Buffers queued", +			priv->debug.tx_stats.buf_queued); +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "Buffers completed", +			priv->debug.tx_stats.buf_completed); +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "SKBs queued", +			priv->debug.tx_stats.skb_queued); +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "SKBs success", +			priv->debug.tx_stats.skb_success); +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "SKBs failed", +			priv->debug.tx_stats.skb_failed); +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "CAB queued", +			priv->debug.tx_stats.cab_queued); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "BE queued", +			priv->debug.tx_stats.queue_stats[WME_AC_BE]); +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "BK queued", +			priv->debug.tx_stats.queue_stats[WME_AC_BK]); +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "VI queued", +			priv->debug.tx_stats.queue_stats[WME_AC_VI]); +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "VO queued", +			priv->debug.tx_stats.queue_stats[WME_AC_VO]); + +	if (len > sizeof(buf)) +		len = sizeof(buf); + +	return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_xmit = { +	.read = read_file_xmit, +	.open = ath9k_debugfs_open, +	.owner = THIS_MODULE, +	.llseek = default_llseek, +}; + +void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, +			   struct ath_htc_rx_status *rxs) +{ +#define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++ + +	if (rxs->rs_status & ATH9K_RXERR_CRC) +		priv->debug.rx_stats.err_crc++; +	if (rxs->rs_status & ATH9K_RXERR_DECRYPT) +		priv->debug.rx_stats.err_decrypt_crc++; +	if (rxs->rs_status & ATH9K_RXERR_MIC) +		priv->debug.rx_stats.err_mic++; +	if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE) +		priv->debug.rx_stats.err_pre_delim++; +	if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST) +		priv->debug.rx_stats.err_post_delim++; +	if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY) +		priv->debug.rx_stats.err_decrypt_busy++; + +	if (rxs->rs_status & ATH9K_RXERR_PHY) { +		priv->debug.rx_stats.err_phy++; +		if (rxs->rs_phyerr < ATH9K_PHYERR_MAX) +			RX_PHY_ERR_INC(rxs->rs_phyerr); +	} + +#undef RX_PHY_ERR_INC +} + +static ssize_t read_file_recv(struct file *file, char __user *user_buf, +			      size_t count, loff_t *ppos) +{ +#define PHY_ERR(s, p)							\ +	len += snprintf(buf + len, size - len, "%20s : %10u\n", s,	\ +			priv->debug.rx_stats.err_phy_stats[p]); + +	struct ath9k_htc_priv *priv = file->private_data; +	char *buf; +	unsigned int len = 0, size = 1500; +	ssize_t retval = 0; + +	buf = kzalloc(size, GFP_KERNEL); +	if (buf == NULL) +		return -ENOMEM; + +	len += snprintf(buf + len, size - len, +			"%20s : %10u\n", "SKBs allocated", +			priv->debug.rx_stats.skb_allocated); +	len += snprintf(buf + len, size - len, +			"%20s : %10u\n", "SKBs completed", +			priv->debug.rx_stats.skb_completed); +	len += snprintf(buf + len, size - len, +			"%20s : %10u\n", "SKBs Dropped", +			priv->debug.rx_stats.skb_dropped); + +	len += snprintf(buf + len, size - len, +			"%20s : %10u\n", "CRC ERR", +			priv->debug.rx_stats.err_crc); +	len += snprintf(buf + len, size - len, +			"%20s : %10u\n", "DECRYPT CRC ERR", +			priv->debug.rx_stats.err_decrypt_crc); +	len += snprintf(buf + len, size - len, +			"%20s : %10u\n", "MIC ERR", +			priv->debug.rx_stats.err_mic); +	len += snprintf(buf + len, size - len, +			"%20s : %10u\n", "PRE-DELIM CRC ERR", +			priv->debug.rx_stats.err_pre_delim); +	len += snprintf(buf + len, size - len, +			"%20s : %10u\n", "POST-DELIM CRC ERR", +			priv->debug.rx_stats.err_post_delim); +	len += snprintf(buf + len, size - len, +			"%20s : %10u\n", "DECRYPT BUSY ERR", +			priv->debug.rx_stats.err_decrypt_busy); +	len += snprintf(buf + len, size - len, +			"%20s : %10u\n", "TOTAL PHY ERR", +			priv->debug.rx_stats.err_phy); + + +	PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); +	PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); +	PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); +	PHY_ERR("RATE", ATH9K_PHYERR_RATE); +	PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH); +	PHY_ERR("RADAR", ATH9K_PHYERR_RADAR); +	PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE); +	PHY_ERR("TOR", ATH9K_PHYERR_TOR); +	PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING); +	PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); +	PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); +	PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); +	PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP); +	PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE); +	PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART); +	PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT); +	PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING); +	PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC); +	PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL); +	PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE); +	PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART); +	PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); +	PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP); +	PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR); +	PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); +	PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); + +	if (len > size) +		len = size; + +	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); +	kfree(buf); + +	return retval; + +#undef PHY_ERR +} + +static const struct file_operations fops_recv = { +	.read = read_file_recv, +	.open = ath9k_debugfs_open, +	.owner = THIS_MODULE, +	.llseek = default_llseek, +}; + +static ssize_t read_file_slot(struct file *file, char __user *user_buf, +			      size_t count, loff_t *ppos) +{ +	struct ath9k_htc_priv *priv = file->private_data; +	char buf[512]; +	unsigned int len = 0; + +	spin_lock_bh(&priv->tx.tx_lock); + +	len += snprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : "); + +	len += bitmap_scnprintf(buf + len, sizeof(buf) - len, +			       priv->tx.tx_slot, MAX_TX_BUF_NUM); + +	len += snprintf(buf + len, sizeof(buf) - len, "\n"); + +	len += snprintf(buf + len, sizeof(buf) - len, +			"Used slots     : %d\n", +			bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM)); + +	spin_unlock_bh(&priv->tx.tx_lock); + +	if (len > sizeof(buf)) +		len = sizeof(buf); + +	return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_slot = { +	.read = read_file_slot, +	.open = ath9k_debugfs_open, +	.owner = THIS_MODULE, +	.llseek = default_llseek, +}; + +static ssize_t read_file_queue(struct file *file, char __user *user_buf, +			       size_t count, loff_t *ppos) +{ +	struct ath9k_htc_priv *priv = file->private_data; +	char buf[512]; +	unsigned int len = 0; + +	len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", +			"Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue)); + +	len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", +			"Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue)); + +	len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", +			"Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue)); + +	len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", +			"Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue)); + +	len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", +			"Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue)); + +	len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", +			"Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue)); + +	len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", +			"Failed queue", skb_queue_len(&priv->tx.tx_failed)); + +	spin_lock_bh(&priv->tx.tx_lock); +	len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", +			"Queued count", priv->tx.queued_cnt); +	spin_unlock_bh(&priv->tx.tx_lock); + +	if (len > sizeof(buf)) +		len = sizeof(buf); + +	return simple_read_from_buffer(user_buf, count, ppos, buf, len); + +} + +static const struct file_operations fops_queue = { +	.read = read_file_queue, +	.open = ath9k_debugfs_open, +	.owner = THIS_MODULE, +	.llseek = default_llseek, +}; + +static ssize_t read_file_debug(struct file *file, char __user *user_buf, +			       size_t count, loff_t *ppos) +{ +	struct ath9k_htc_priv *priv = file->private_data; +	struct ath_common *common = ath9k_hw_common(priv->ah); +	char buf[32]; +	unsigned int len; + +	len = sprintf(buf, "0x%08x\n", common->debug_mask); +	return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_debug(struct file *file, const char __user *user_buf, +				size_t count, loff_t *ppos) +{ +	struct ath9k_htc_priv *priv = file->private_data; +	struct ath_common *common = ath9k_hw_common(priv->ah); +	unsigned long mask; +	char buf[32]; +	ssize_t len; + +	len = min(count, sizeof(buf) - 1); +	if (copy_from_user(buf, user_buf, len)) +		return -EFAULT; + +	buf[len] = '\0'; +	if (strict_strtoul(buf, 0, &mask)) +		return -EINVAL; + +	common->debug_mask = mask; +	return count; +} + +static const struct file_operations fops_debug = { +	.read = read_file_debug, +	.write = write_file_debug, +	.open = ath9k_debugfs_open, +	.owner = THIS_MODULE, +	.llseek = default_llseek, +}; + +int ath9k_htc_init_debug(struct ath_hw *ah) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + +	priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME, +					     priv->hw->wiphy->debugfsdir); +	if (!priv->debug.debugfs_phy) +		return -ENOMEM; + +	debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, +				priv, &fops_tgt_int_stats); +	debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, +				priv, &fops_tgt_tx_stats); +	debugfs_create_file("tgt_rx_stats", S_IRUSR, priv->debug.debugfs_phy, +				priv, &fops_tgt_rx_stats); +	debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy, +				priv, &fops_xmit); +	debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy, +				priv, &fops_recv); +	debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, +				priv, &fops_slot); +	debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy, +				priv, &fops_queue); +	debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy, +				priv, &fops_debug); + +	return 0; +} diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 7e630a81b45..dc0b33d0121 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -398,9 +398,9 @@ void ath9k_htc_radio_enable(struct ieee80211_hw *hw)  	/* Start TX */  	htc_start(priv->htc); -	spin_lock_bh(&priv->tx_lock); -	priv->tx_queues_stop = false; -	spin_unlock_bh(&priv->tx_lock); +	spin_lock_bh(&priv->tx.tx_lock); +	priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; +	spin_unlock_bh(&priv->tx.tx_lock);  	ieee80211_wake_queues(hw);  	WMI_CMD(WMI_ENABLE_INTR_CMDID); @@ -429,13 +429,15 @@ void ath9k_htc_radio_disable(struct ieee80211_hw *hw)  	/* Stop TX */  	ieee80211_stop_queues(hw); -	htc_stop(priv->htc); +	ath9k_htc_tx_drain(priv);  	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); -	skb_queue_purge(&priv->tx_queue);  	/* Stop RX */  	WMI_CMD(WMI_STOP_RECV_CMDID); +	/* Clear the WMI event queue */ +	ath9k_wmi_event_drain(priv); +  	/*  	 * The MIB counters have to be disabled here,  	 * since the target doesn't do it. diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 8303b34bdc9..06e043bffaf 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -140,7 +140,6 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)  static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)  { -	ath9k_htc_exit_debug(priv->ah);  	ath9k_hw_deinit(priv->ah);  	kfree(priv->ah);  	priv->ah = NULL; @@ -643,7 +642,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,  {  	struct ath_hw *ah = NULL;  	struct ath_common *common; -	int ret = 0, csz = 0; +	int i, ret = 0, csz = 0;  	priv->op_flags |= OP_INVALID; @@ -671,20 +670,19 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,  	common->priv = priv;  	common->debug_mask = ath9k_debug; -	spin_lock_init(&priv->wmi->wmi_lock);  	spin_lock_init(&priv->beacon_lock); -	spin_lock_init(&priv->tx_lock); +	spin_lock_init(&priv->tx.tx_lock);  	mutex_init(&priv->mutex);  	mutex_init(&priv->htc_pm_lock); -	tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet, -		     (unsigned long)priv);  	tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,  		     (unsigned long)priv); -	tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, +	tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,  		     (unsigned long)priv);  	INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);  	INIT_WORK(&priv->ps_work, ath9k_ps_work);  	INIT_WORK(&priv->fatal_work, ath9k_fatal_work); +	setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer, +		    (unsigned long)priv);  	/*  	 * Cache line size is used to size and align various @@ -701,16 +699,13 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,  		goto err_hw;  	} -	ret = ath9k_htc_init_debug(ah); -	if (ret) { -		ath_err(common, "Unable to create debugfs files\n"); -		goto err_debug; -	} -  	ret = ath9k_init_queues(priv);  	if (ret)  		goto err_queues; +	for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) +		priv->cur_beacon_conf.bslot[i] = NULL; +  	ath9k_init_crypto(priv);  	ath9k_init_channels_rates(priv);  	ath9k_init_misc(priv); @@ -723,8 +718,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,  	return 0;  err_queues: -	ath9k_htc_exit_debug(ah); -err_debug:  	ath9k_hw_deinit(ah);  err_hw: @@ -745,11 +738,15 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,  		IEEE80211_HW_HAS_RATE_CONTROL |  		IEEE80211_HW_RX_INCLUDES_FCS |  		IEEE80211_HW_SUPPORTS_PS | -		IEEE80211_HW_PS_NULLFUNC_STACK; +		IEEE80211_HW_PS_NULLFUNC_STACK | +		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;  	hw->wiphy->interface_modes =  		BIT(NL80211_IFTYPE_STATION) | -		BIT(NL80211_IFTYPE_ADHOC); +		BIT(NL80211_IFTYPE_ADHOC) | +		BIT(NL80211_IFTYPE_AP) | +		BIT(NL80211_IFTYPE_P2P_GO) | +		BIT(NL80211_IFTYPE_P2P_CLIENT);  	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; @@ -782,6 +779,32 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,  	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);  } +static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) +{ +	struct ieee80211_hw *hw = priv->hw; +	struct wmi_fw_version cmd_rsp; +	int ret; + +	memset(&cmd_rsp, 0, sizeof(cmd_rsp)); + +	WMI_CMD(WMI_GET_FW_VERSION); +	if (ret) +		return -EINVAL; + +	priv->fw_version_major = be16_to_cpu(cmd_rsp.major); +	priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor); + +	snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d", +		 priv->fw_version_major, +		 priv->fw_version_minor); + +	dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n", +		 priv->fw_version_major, +		 priv->fw_version_minor); + +	return 0; +} +  static int ath9k_init_device(struct ath9k_htc_priv *priv,  			     u16 devid, char *product, u32 drv_info)  { @@ -801,6 +824,10 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,  	common = ath9k_hw_common(ah);  	ath9k_set_hw_capab(priv, hw); +	error = ath9k_init_firmware_version(priv); +	if (error != 0) +		goto err_fw; +  	/* Initialize regulatory */  	error = ath_regd_init(&common->regulatory, priv->hw->wiphy,  			      ath9k_reg_notifier); @@ -831,6 +858,12 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,  			goto err_world;  	} +	error = ath9k_htc_init_debug(priv->ah); +	if (error) { +		ath_err(common, "Unable to create debugfs files\n"); +		goto err_world; +	} +  	ath_dbg(common, ATH_DBG_CONFIG,  		"WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, "  		"BE:%d, BK:%d, VI:%d, VO:%d\n", @@ -861,6 +894,8 @@ err_rx:  err_tx:  	/* Nothing */  err_regd: +	/* Nothing */ +err_fw:  	ath9k_deinit_priv(priv);  err_init:  	return error; @@ -949,38 +984,20 @@ int ath9k_htc_resume(struct htc_target *htc_handle)  static int __init ath9k_htc_init(void)  { -	int error; - -	error = ath9k_htc_debug_create_root(); -	if (error < 0) { -		printk(KERN_ERR -			"ath9k_htc: Unable to create debugfs root: %d\n", -			error); -		goto err_dbg; -	} - -	error = ath9k_hif_usb_init(); -	if (error < 0) { +	if (ath9k_hif_usb_init() < 0) {  		printk(KERN_ERR  			"ath9k_htc: No USB devices found,"  			" driver not installed.\n"); -		error = -ENODEV; -		goto err_usb; +		return -ENODEV;  	}  	return 0; - -err_usb: -	ath9k_htc_debug_remove_root(); -err_dbg: -	return error;  }  module_init(ath9k_htc_init);  static void __exit ath9k_htc_exit(void)  {  	ath9k_hif_usb_exit(); -	ath9k_htc_debug_remove_root();  	printk(KERN_INFO "ath9k_htc: Driver unloaded\n");  }  module_exit(ath9k_htc_exit); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index db8c0c044e9..4de38643cb5 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -16,10 +16,6 @@  #include "htc.h" -#ifdef CONFIG_ATH9K_HTC_DEBUGFS -static struct dentry *ath9k_debugfs_root; -#endif -  /*************/  /* Utilities */  /*************/ @@ -197,11 +193,16 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)  	ath9k_htc_stop_ani(priv);  	ieee80211_stop_queues(priv->hw); -	htc_stop(priv->htc); + +	del_timer_sync(&priv->tx.cleanup_timer); +	ath9k_htc_tx_drain(priv); +  	WMI_CMD(WMI_DISABLE_INTR_CMDID);  	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);  	WMI_CMD(WMI_STOP_RECV_CMDID); +	ath9k_wmi_event_drain(priv); +  	caldata = &priv->caldata;  	ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);  	if (ret) { @@ -225,6 +226,9 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)  	ath9k_htc_vif_reconfig(priv);  	ieee80211_wake_queues(priv->hw); +	mod_timer(&priv->tx.cleanup_timer, +		  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); +  	ath9k_htc_ps_restore(priv);  	mutex_unlock(&priv->mutex);  } @@ -250,11 +254,16 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,  	fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);  	ath9k_htc_ps_wakeup(priv); -	htc_stop(priv->htc); + +	del_timer_sync(&priv->tx.cleanup_timer); +	ath9k_htc_tx_drain(priv); +  	WMI_CMD(WMI_DISABLE_INTR_CMDID);  	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);  	WMI_CMD(WMI_STOP_RECV_CMDID); +	ath9k_wmi_event_drain(priv); +  	ath_dbg(common, ATH_DBG_CONFIG,  		"(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n",  		priv->ah->curchan->channel, @@ -263,6 +272,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,  	if (!fastcc)  		caldata = &priv->caldata; +  	ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);  	if (ret) {  		ath_err(common, @@ -296,6 +306,9 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,  	    !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))  		ath9k_htc_vif_reconfig(priv); +	mod_timer(&priv->tx.cleanup_timer, +		  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); +  err:  	ath9k_htc_ps_restore(priv);  	return ret; @@ -349,7 +362,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)  	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));  	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); -	hvif.opmode = cpu_to_be32(HTC_M_MONITOR); +	hvif.opmode = HTC_M_MONITOR;  	hvif.index = ffz(priv->vif_slot);  	WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); @@ -382,7 +395,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)  	tsta.is_vif_sta = 1;  	tsta.sta_index = sta_idx;  	tsta.vif_index = hvif.index; -	tsta.maxampdu = 0xffff; +	tsta.maxampdu = cpu_to_be16(0xffff);  	WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);  	if (ret) { @@ -463,9 +476,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,  		ista = (struct ath9k_htc_sta *) sta->drv_priv;  		memcpy(&tsta.macaddr, sta->addr, ETH_ALEN);  		memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); -		tsta.associd = common->curaid;  		tsta.is_vif_sta = 0; -		tsta.valid = true;  		ista->index = sta_idx;  	} else {  		memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); @@ -474,7 +485,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,  	tsta.sta_index = sta_idx;  	tsta.vif_index = avp->index; -	tsta.maxampdu = 0xffff; +	tsta.maxampdu = cpu_to_be16(0xffff);  	if (sta && sta->ht_cap.ht_supported)  		tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); @@ -709,218 +720,13 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv,  			(aggr.aggr_enable) ? "Starting" : "Stopping",  			sta->addr, tid); -	spin_lock_bh(&priv->tx_lock); +	spin_lock_bh(&priv->tx.tx_lock);  	ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; -	spin_unlock_bh(&priv->tx_lock); +	spin_unlock_bh(&priv->tx.tx_lock);  	return ret;  } -/*********/ -/* DEBUG */ -/*********/ - -#ifdef CONFIG_ATH9K_HTC_DEBUGFS - -static int ath9k_debugfs_open(struct inode *inode, struct file *file) -{ -	file->private_data = inode->i_private; -	return 0; -} - -static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, -				   size_t count, loff_t *ppos) -{ -	struct ath9k_htc_priv *priv = file->private_data; -	struct ath9k_htc_target_stats cmd_rsp; -	char buf[512]; -	unsigned int len = 0; -	int ret = 0; - -	memset(&cmd_rsp, 0, sizeof(cmd_rsp)); - -	WMI_CMD(WMI_TGT_STATS_CMDID); -	if (ret) -		return -EINVAL; - - -	len += snprintf(buf + len, sizeof(buf) - len, -			"%19s : %10u\n", "TX Short Retries", -			be32_to_cpu(cmd_rsp.tx_shortretry)); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%19s : %10u\n", "TX Long Retries", -			be32_to_cpu(cmd_rsp.tx_longretry)); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%19s : %10u\n", "TX Xretries", -			be32_to_cpu(cmd_rsp.tx_xretries)); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%19s : %10u\n", "TX Unaggr. Xretries", -			be32_to_cpu(cmd_rsp.ht_txunaggr_xretry)); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%19s : %10u\n", "TX Xretries (HT)", -			be32_to_cpu(cmd_rsp.ht_tx_xretries)); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%19s : %10u\n", "TX Rate", priv->debug.txrate); - -	if (len > sizeof(buf)) -		len = sizeof(buf); - -	return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_tgt_stats = { -	.read = read_file_tgt_stats, -	.open = ath9k_debugfs_open, -	.owner = THIS_MODULE, -	.llseek = default_llseek, -}; - -static ssize_t read_file_xmit(struct file *file, char __user *user_buf, -			      size_t count, loff_t *ppos) -{ -	struct ath9k_htc_priv *priv = file->private_data; -	char buf[512]; -	unsigned int len = 0; - -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "Buffers queued", -			priv->debug.tx_stats.buf_queued); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "Buffers completed", -			priv->debug.tx_stats.buf_completed); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "SKBs queued", -			priv->debug.tx_stats.skb_queued); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "SKBs completed", -			priv->debug.tx_stats.skb_completed); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "SKBs dropped", -			priv->debug.tx_stats.skb_dropped); - -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "BE queued", -			priv->debug.tx_stats.queue_stats[WME_AC_BE]); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "BK queued", -			priv->debug.tx_stats.queue_stats[WME_AC_BK]); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "VI queued", -			priv->debug.tx_stats.queue_stats[WME_AC_VI]); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "VO queued", -			priv->debug.tx_stats.queue_stats[WME_AC_VO]); - -	if (len > sizeof(buf)) -		len = sizeof(buf); - -	return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_xmit = { -	.read = read_file_xmit, -	.open = ath9k_debugfs_open, -	.owner = THIS_MODULE, -	.llseek = default_llseek, -}; - -static ssize_t read_file_recv(struct file *file, char __user *user_buf, -			      size_t count, loff_t *ppos) -{ -	struct ath9k_htc_priv *priv = file->private_data; -	char buf[512]; -	unsigned int len = 0; - -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "SKBs allocated", -			priv->debug.rx_stats.skb_allocated); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "SKBs completed", -			priv->debug.rx_stats.skb_completed); -	len += snprintf(buf + len, sizeof(buf) - len, -			"%20s : %10u\n", "SKBs Dropped", -			priv->debug.rx_stats.skb_dropped); - -	if (len > sizeof(buf)) -		len = sizeof(buf); - -	return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_recv = { -	.read = read_file_recv, -	.open = ath9k_debugfs_open, -	.owner = THIS_MODULE, -	.llseek = default_llseek, -}; - -int ath9k_htc_init_debug(struct ath_hw *ah) -{ -	struct ath_common *common = ath9k_hw_common(ah); -	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - -	if (!ath9k_debugfs_root) -		return -ENOENT; - -	priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy), -						     ath9k_debugfs_root); -	if (!priv->debug.debugfs_phy) -		goto err; - -	priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR, -						    priv->debug.debugfs_phy, -						    priv, &fops_tgt_stats); -	if (!priv->debug.debugfs_tgt_stats) -		goto err; - - -	priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, -						       priv->debug.debugfs_phy, -						       priv, &fops_xmit); -	if (!priv->debug.debugfs_xmit) -		goto err; - -	priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR, -						       priv->debug.debugfs_phy, -						       priv, &fops_recv); -	if (!priv->debug.debugfs_recv) -		goto err; - -	return 0; - -err: -	ath9k_htc_exit_debug(ah); -	return -ENOMEM; -} - -void ath9k_htc_exit_debug(struct ath_hw *ah) -{ -	struct ath_common *common = ath9k_hw_common(ah); -	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - -	debugfs_remove(priv->debug.debugfs_recv); -	debugfs_remove(priv->debug.debugfs_xmit); -	debugfs_remove(priv->debug.debugfs_tgt_stats); -	debugfs_remove(priv->debug.debugfs_phy); -} - -int ath9k_htc_debug_create_root(void) -{ -	ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); -	if (!ath9k_debugfs_root) -		return -ENOENT; - -	return 0; -} - -void ath9k_htc_debug_remove_root(void) -{ -	debugfs_remove(ath9k_debugfs_root); -	ath9k_debugfs_root = NULL; -} - -#endif /* CONFIG_ATH9K_HTC_DEBUGFS */ -  /*******/  /* ANI */  /*******/ @@ -1040,7 +846,8 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  {  	struct ieee80211_hdr *hdr;  	struct ath9k_htc_priv *priv = hw->priv; -	int padpos, padsize, ret; +	struct ath_common *common = ath9k_hw_common(priv->ah); +	int padpos, padsize, ret, slot;  	hdr = (struct ieee80211_hdr *) skb->data; @@ -1048,30 +855,32 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  	padpos = ath9k_cmn_padpos(hdr->frame_control);  	padsize = padpos & 3;  	if (padsize && skb->len > padpos) { -		if (skb_headroom(skb) < padsize) +		if (skb_headroom(skb) < padsize) { +			ath_dbg(common, ATH_DBG_XMIT, "No room for padding\n");  			goto fail_tx; +		}  		skb_push(skb, padsize);  		memmove(skb->data, skb->data + padsize, padpos);  	} -	ret = ath9k_htc_tx_start(priv, skb); -	if (ret != 0) { -		if (ret == -ENOMEM) { -			ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, -				"Stopping TX queues\n"); -			ieee80211_stop_queues(hw); -			spin_lock_bh(&priv->tx_lock); -			priv->tx_queues_stop = true; -			spin_unlock_bh(&priv->tx_lock); -		} else { -			ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, -				"Tx failed\n"); -		} +	slot = ath9k_htc_tx_get_slot(priv); +	if (slot < 0) { +		ath_dbg(common, ATH_DBG_XMIT, "No free TX slot\n");  		goto fail_tx;  	} +	ret = ath9k_htc_tx_start(priv, skb, slot, false); +	if (ret != 0) { +		ath_dbg(common, ATH_DBG_XMIT, "Tx failed\n"); +		goto clear_slot; +	} + +	ath9k_htc_check_stop_queues(priv); +  	return; +clear_slot: +	ath9k_htc_tx_clear_slot(priv, slot);  fail_tx:  	dev_kfree_skb_any(skb);  } @@ -1130,12 +939,15 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)  	priv->op_flags &= ~OP_INVALID;  	htc_start(priv->htc); -	spin_lock_bh(&priv->tx_lock); -	priv->tx_queues_stop = false; -	spin_unlock_bh(&priv->tx_lock); +	spin_lock_bh(&priv->tx.tx_lock); +	priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; +	spin_unlock_bh(&priv->tx.tx_lock);  	ieee80211_wake_queues(hw); +	mod_timer(&priv->tx.cleanup_timer, +		  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); +  	if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) {  		ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,  					   AR_STOMP_LOW_WLAN_WGHT); @@ -1164,16 +976,16 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)  	}  	ath9k_htc_ps_wakeup(priv); -	htc_stop(priv->htc); +  	WMI_CMD(WMI_DISABLE_INTR_CMDID);  	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);  	WMI_CMD(WMI_STOP_RECV_CMDID); -	tasklet_kill(&priv->swba_tasklet);  	tasklet_kill(&priv->rx_tasklet); -	tasklet_kill(&priv->tx_tasklet); -	skb_queue_purge(&priv->tx_queue); +	del_timer_sync(&priv->tx.cleanup_timer); +	ath9k_htc_tx_drain(priv); +	ath9k_wmi_event_drain(priv);  	mutex_unlock(&priv->mutex); @@ -1245,13 +1057,13 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,  	switch (vif->type) {  	case NL80211_IFTYPE_STATION: -		hvif.opmode = cpu_to_be32(HTC_M_STA); +		hvif.opmode = HTC_M_STA;  		break;  	case NL80211_IFTYPE_ADHOC: -		hvif.opmode = cpu_to_be32(HTC_M_IBSS); +		hvif.opmode = HTC_M_IBSS;  		break;  	case NL80211_IFTYPE_AP: -		hvif.opmode = cpu_to_be32(HTC_M_HOSTAP); +		hvif.opmode = HTC_M_HOSTAP;  		break;  	default:  		ath_err(common, @@ -1281,14 +1093,20 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,  	priv->vif_slot |= (1 << avp->index);  	priv->nvifs++; -	priv->vif = vif;  	INC_VIF(priv, vif->type); + +	if ((vif->type == NL80211_IFTYPE_AP) || +	    (vif->type == NL80211_IFTYPE_ADHOC)) +		ath9k_htc_assign_bslot(priv, vif); +  	ath9k_htc_set_opmode(priv);  	if ((priv->ah->opmode == NL80211_IFTYPE_AP) && -	    !(priv->op_flags & OP_ANI_RUNNING)) +	    !(priv->op_flags & OP_ANI_RUNNING)) { +		ath9k_hw_set_tsfadjust(priv->ah, 1);  		ath9k_htc_start_ani(priv); +	}  	ath_dbg(common, ATH_DBG_CONFIG,  		"Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); @@ -1321,9 +1139,13 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,  	priv->vif_slot &= ~(1 << avp->index);  	ath9k_htc_remove_station(priv, vif, NULL); -	priv->vif = NULL;  	DEC_VIF(priv, vif->type); + +	if ((vif->type == NL80211_IFTYPE_AP) || +	    (vif->type == NL80211_IFTYPE_ADHOC)) +		ath9k_htc_remove_bslot(priv, vif); +  	ath9k_htc_set_opmode(priv);  	/* @@ -1493,10 +1315,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,  				struct ieee80211_sta *sta)  {  	struct ath9k_htc_priv *priv = hw->priv; +	struct ath9k_htc_sta *ista;  	int ret;  	mutex_lock(&priv->mutex);  	ath9k_htc_ps_wakeup(priv); +	ista = (struct ath9k_htc_sta *) sta->drv_priv; +	htc_sta_drain(priv->htc, ista->index);  	ret = ath9k_htc_remove_station(priv, vif, sta);  	ath9k_htc_ps_restore(priv);  	mutex_unlock(&priv->mutex); @@ -1644,6 +1469,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,  	if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) {  		ath_dbg(common, ATH_DBG_CONFIG,  			"Beacon enabled for BSS: %pM\n", bss_conf->bssid); +		ath9k_htc_set_tsfadjust(priv, vif);  		priv->op_flags |= OP_ENABLE_BEACON;  		ath9k_htc_beacon_config(priv, vif);  	} @@ -1758,9 +1584,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,  		break;  	case IEEE80211_AMPDU_TX_OPERATIONAL:  		ista = (struct ath9k_htc_sta *) sta->drv_priv; -		spin_lock_bh(&priv->tx_lock); +		spin_lock_bh(&priv->tx.tx_lock);  		ista->tid_state[tid] = AGGR_OPERATIONAL; -		spin_unlock_bh(&priv->tx_lock); +		spin_unlock_bh(&priv->tx.tx_lock);  		break;  	default:  		ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 4a4f27ba96a..723a3a9c5cd 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -53,6 +53,138 @@ int get_hw_qnum(u16 queue, int *hwq_map)  	}  } +void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv) +{ +	spin_lock_bh(&priv->tx.tx_lock); +	priv->tx.queued_cnt++; +	if ((priv->tx.queued_cnt >= ATH9K_HTC_TX_THRESHOLD) && +	    !(priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { +		priv->tx.flags |= ATH9K_HTC_OP_TX_QUEUES_STOP; +		ieee80211_stop_queues(priv->hw); +	} +	spin_unlock_bh(&priv->tx.tx_lock); +} + +void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv) +{ +	spin_lock_bh(&priv->tx.tx_lock); +	if ((priv->tx.queued_cnt < ATH9K_HTC_TX_THRESHOLD) && +	    (priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { +		priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; +		ieee80211_wake_queues(priv->hw); +	} +	spin_unlock_bh(&priv->tx.tx_lock); +} + +int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv) +{ +	int slot; + +	spin_lock_bh(&priv->tx.tx_lock); +	slot = find_first_zero_bit(priv->tx.tx_slot, MAX_TX_BUF_NUM); +	if (slot >= MAX_TX_BUF_NUM) { +		spin_unlock_bh(&priv->tx.tx_lock); +		return -ENOBUFS; +	} +	__set_bit(slot, priv->tx.tx_slot); +	spin_unlock_bh(&priv->tx.tx_lock); + +	return slot; +} + +void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot) +{ +	spin_lock_bh(&priv->tx.tx_lock); +	__clear_bit(slot, priv->tx.tx_slot); +	spin_unlock_bh(&priv->tx.tx_lock); +} + +static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, +						u16 qnum) +{ +	enum htc_endpoint_id epid; + +	switch (qnum) { +	case 0: +		TX_QSTAT_INC(WME_AC_VO); +		epid = priv->data_vo_ep; +		break; +	case 1: +		TX_QSTAT_INC(WME_AC_VI); +		epid = priv->data_vi_ep; +		break; +	case 2: +		TX_QSTAT_INC(WME_AC_BE); +		epid = priv->data_be_ep; +		break; +	case 3: +	default: +		TX_QSTAT_INC(WME_AC_BK); +		epid = priv->data_bk_ep; +		break; +	} + +	return epid; +} + +static inline struct sk_buff_head* +get_htc_epid_queue(struct ath9k_htc_priv *priv, u8 epid) +{ +	struct ath_common *common = ath9k_hw_common(priv->ah); +	struct sk_buff_head *epid_queue = NULL; + +	if (epid == priv->mgmt_ep) +		epid_queue = &priv->tx.mgmt_ep_queue; +	else if (epid == priv->cab_ep) +		epid_queue = &priv->tx.cab_ep_queue; +	else if (epid == priv->data_be_ep) +		epid_queue = &priv->tx.data_be_queue; +	else if (epid == priv->data_bk_ep) +		epid_queue = &priv->tx.data_bk_queue; +	else if (epid == priv->data_vi_ep) +		epid_queue = &priv->tx.data_vi_queue; +	else if (epid == priv->data_vo_ep) +		epid_queue = &priv->tx.data_vo_queue; +	else +		ath_err(common, "Invalid EPID: %d\n", epid); + +	return epid_queue; +} + +/* + * Removes the driver header and returns the TX slot number + */ +static inline int strip_drv_header(struct ath9k_htc_priv *priv, +				   struct sk_buff *skb) +{ +	struct ath_common *common = ath9k_hw_common(priv->ah); +	struct ath9k_htc_tx_ctl *tx_ctl; +	int slot; + +	tx_ctl = HTC_SKB_CB(skb); + +	if (tx_ctl->epid == priv->mgmt_ep) { +		struct tx_mgmt_hdr *tx_mhdr = +			(struct tx_mgmt_hdr *)skb->data; +		slot = tx_mhdr->cookie; +		skb_pull(skb, sizeof(struct tx_mgmt_hdr)); +	} else if ((tx_ctl->epid == priv->data_bk_ep) || +		   (tx_ctl->epid == priv->data_be_ep) || +		   (tx_ctl->epid == priv->data_vi_ep) || +		   (tx_ctl->epid == priv->data_vo_ep) || +		   (tx_ctl->epid == priv->cab_ep)) { +		struct tx_frame_hdr *tx_fhdr = +			(struct tx_frame_hdr *)skb->data; +		slot = tx_fhdr->cookie; +		skb_pull(skb, sizeof(struct tx_frame_hdr)); +	} else { +		ath_err(common, "Unsupported EPID: %d\n", tx_ctl->epid); +		slot = -EINVAL; +	} + +	return slot; +} +  int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,  		       struct ath9k_tx_queue_info *qinfo)  { @@ -79,23 +211,140 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,  	return error;  } -int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) +static void ath9k_htc_tx_mgmt(struct ath9k_htc_priv *priv, +			      struct ath9k_htc_vif *avp, +			      struct sk_buff *skb, +			      u8 sta_idx, u8 vif_idx, u8 slot) +{ +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); +	struct ieee80211_mgmt *mgmt; +	struct ieee80211_hdr *hdr; +	struct tx_mgmt_hdr mgmt_hdr; +	struct ath9k_htc_tx_ctl *tx_ctl; +	u8 *tx_fhdr; + +	tx_ctl = HTC_SKB_CB(skb); +	hdr = (struct ieee80211_hdr *) skb->data; + +	memset(tx_ctl, 0, sizeof(*tx_ctl)); +	memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); + +	/* +	 * Set the TSF adjust value for probe response +	 * frame also. +	 */ +	if (avp && unlikely(ieee80211_is_probe_resp(hdr->frame_control))) { +		mgmt = (struct ieee80211_mgmt *)skb->data; +		mgmt->u.probe_resp.timestamp = avp->tsfadjust; +	} + +	tx_ctl->type = ATH9K_HTC_MGMT; + +	mgmt_hdr.node_idx = sta_idx; +	mgmt_hdr.vif_idx = vif_idx; +	mgmt_hdr.tidno = 0; +	mgmt_hdr.flags = 0; +	mgmt_hdr.cookie = slot; + +	mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); +	if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) +		mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; +	else +		mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; + +	tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); +	memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); +	tx_ctl->epid = priv->mgmt_ep; +} + +static void ath9k_htc_tx_data(struct ath9k_htc_priv *priv, +			      struct ieee80211_vif *vif, +			      struct sk_buff *skb, +			      u8 sta_idx, u8 vif_idx, u8 slot, +			      bool is_cab) +{ +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); +	struct ieee80211_hdr *hdr; +	struct ath9k_htc_tx_ctl *tx_ctl; +	struct tx_frame_hdr tx_hdr; +	u32 flags = 0; +	u8 *qc, *tx_fhdr; +	u16 qnum; + +	tx_ctl = HTC_SKB_CB(skb); +	hdr = (struct ieee80211_hdr *) skb->data; + +	memset(tx_ctl, 0, sizeof(*tx_ctl)); +	memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); + +	tx_hdr.node_idx = sta_idx; +	tx_hdr.vif_idx = vif_idx; +	tx_hdr.cookie = slot; + +	/* +	 * This is a bit redundant but it helps to get +	 * the per-packet index quickly when draining the +	 * TX queue in the HIF layer. Otherwise we would +	 * have to parse the packet contents ... +	 */ +	tx_ctl->sta_idx = sta_idx; + +	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { +		tx_ctl->type = ATH9K_HTC_AMPDU; +		tx_hdr.data_type = ATH9K_HTC_AMPDU; +	} else { +		tx_ctl->type = ATH9K_HTC_NORMAL; +		tx_hdr.data_type = ATH9K_HTC_NORMAL; +	} + +	if (ieee80211_is_data_qos(hdr->frame_control)) { +		qc = ieee80211_get_qos_ctl(hdr); +		tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; +	} + +	/* Check for RTS protection */ +	if (priv->hw->wiphy->rts_threshold != (u32) -1) +		if (skb->len > priv->hw->wiphy->rts_threshold) +			flags |= ATH9K_HTC_TX_RTSCTS; + +	/* CTS-to-self */ +	if (!(flags & ATH9K_HTC_TX_RTSCTS) && +	    (vif && vif->bss_conf.use_cts_prot)) +		flags |= ATH9K_HTC_TX_CTSONLY; + +	tx_hdr.flags = cpu_to_be32(flags); +	tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); +	if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) +		tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; +	else +		tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; + +	tx_fhdr = skb_push(skb, sizeof(tx_hdr)); +	memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); + +	if (is_cab) { +		CAB_STAT_INC; +		tx_ctl->epid = priv->cab_ep; +		return; +	} + +	qnum = skb_get_queue_mapping(skb); +	tx_ctl->epid = get_htc_epid(priv, qnum); +} + +int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, +		       struct sk_buff *skb, +		       u8 slot, bool is_cab)  {  	struct ieee80211_hdr *hdr;  	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);  	struct ieee80211_sta *sta = tx_info->control.sta;  	struct ieee80211_vif *vif = tx_info->control.vif;  	struct ath9k_htc_sta *ista; -	struct ath9k_htc_vif *avp; -	struct ath9k_htc_tx_ctl tx_ctl; -	enum htc_endpoint_id epid; -	u16 qnum; -	__le16 fc; -	u8 *tx_fhdr; +	struct ath9k_htc_vif *avp = NULL;  	u8 sta_idx, vif_idx;  	hdr = (struct ieee80211_hdr *) skb->data; -	fc = hdr->frame_control;  	/*  	 * Find out on which interface this packet has to be @@ -124,218 +373,432 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)  		sta_idx = priv->vif_sta_pos[vif_idx];  	} -	memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); +	if (ieee80211_is_data(hdr->frame_control)) +		ath9k_htc_tx_data(priv, vif, skb, +				  sta_idx, vif_idx, slot, is_cab); +	else +		ath9k_htc_tx_mgmt(priv, avp, skb, +				  sta_idx, vif_idx, slot); + -	if (ieee80211_is_data(fc)) { -		struct tx_frame_hdr tx_hdr; -		u32 flags = 0; -		u8 *qc; +	return htc_send(priv->htc, skb); +} -		memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); +static inline bool __ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, +					     struct ath9k_htc_sta *ista, u8 tid) +{ +	bool ret = false; -		tx_hdr.node_idx = sta_idx; -		tx_hdr.vif_idx = vif_idx; +	spin_lock_bh(&priv->tx.tx_lock); +	if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) +		ret = true; +	spin_unlock_bh(&priv->tx.tx_lock); -		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { -			tx_ctl.type = ATH9K_HTC_AMPDU; -			tx_hdr.data_type = ATH9K_HTC_AMPDU; -		} else { -			tx_ctl.type = ATH9K_HTC_NORMAL; -			tx_hdr.data_type = ATH9K_HTC_NORMAL; -		} +	return ret; +} +static void ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, +				    struct ieee80211_vif *vif, +				    struct sk_buff *skb) +{ +	struct ieee80211_sta *sta; +	struct ieee80211_hdr *hdr; +	__le16 fc; + +	hdr = (struct ieee80211_hdr *) skb->data; +	fc = hdr->frame_control; + +	rcu_read_lock(); + +	sta = ieee80211_find_sta(vif, hdr->addr1); +	if (!sta) { +		rcu_read_unlock(); +		return; +	} + +	if (sta && conf_is_ht(&priv->hw->conf) && +	    !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {  		if (ieee80211_is_data_qos(fc)) { +			u8 *qc, tid; +			struct ath9k_htc_sta *ista; +  			qc = ieee80211_get_qos_ctl(hdr); -			tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; +			tid = qc[0] & 0xf; +			ista = (struct ath9k_htc_sta *)sta->drv_priv; +			if (__ath9k_htc_check_tx_aggr(priv, ista, tid)) { +				ieee80211_start_tx_ba_session(sta, tid, 0); +				spin_lock_bh(&priv->tx.tx_lock); +				ista->tid_state[tid] = AGGR_PROGRESS; +				spin_unlock_bh(&priv->tx.tx_lock); +			}  		} +	} -		/* Check for RTS protection */ -		if (priv->hw->wiphy->rts_threshold != (u32) -1) -			if (skb->len > priv->hw->wiphy->rts_threshold) -				flags |= ATH9K_HTC_TX_RTSCTS; +	rcu_read_unlock(); +} -		/* CTS-to-self */ -		if (!(flags & ATH9K_HTC_TX_RTSCTS) && -		    (vif && vif->bss_conf.use_cts_prot)) -			flags |= ATH9K_HTC_TX_CTSONLY; +static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, +				 struct sk_buff *skb, +				 struct __wmi_event_txstatus *txs) +{ +	struct ieee80211_vif *vif; +	struct ath9k_htc_tx_ctl *tx_ctl; +	struct ieee80211_tx_info *tx_info; +	struct ieee80211_tx_rate *rate; +	struct ieee80211_conf *cur_conf = &priv->hw->conf; +	struct ieee80211_supported_band *sband; +	bool txok; +	int slot; -		tx_hdr.flags = cpu_to_be32(flags); -		tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); -		if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) -			tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; -		else -			tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; +	slot = strip_drv_header(priv, skb); +	if (slot < 0) { +		dev_kfree_skb_any(skb); +		return; +	} -		tx_fhdr = skb_push(skb, sizeof(tx_hdr)); -		memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); +	tx_ctl = HTC_SKB_CB(skb); +	txok = tx_ctl->txok; +	tx_info = IEEE80211_SKB_CB(skb); +	vif = tx_info->control.vif; +	rate = &tx_info->status.rates[0]; +	sband = priv->hw->wiphy->bands[cur_conf->channel->band]; -		qnum = skb_get_queue_mapping(skb); +	memset(&tx_info->status, 0, sizeof(tx_info->status)); -		switch (qnum) { -		case 0: -			TX_QSTAT_INC(WME_AC_VO); -			epid = priv->data_vo_ep; -			break; -		case 1: -			TX_QSTAT_INC(WME_AC_VI); -			epid = priv->data_vi_ep; -			break; -		case 2: -			TX_QSTAT_INC(WME_AC_BE); -			epid = priv->data_be_ep; -			break; -		case 3: -		default: -			TX_QSTAT_INC(WME_AC_BK); -			epid = priv->data_bk_ep; -			break; -		} -	} else { -		struct tx_mgmt_hdr mgmt_hdr; +	/* +	 * URB submission failed for this frame, it never reached +	 * the target. +	 */ +	if (!txok || !vif || !txs) +		goto send_mac80211; + +	if (txs->ts_flags & ATH9K_HTC_TXSTAT_ACK) +		tx_info->flags |= IEEE80211_TX_STAT_ACK; -		memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); +	if (txs->ts_flags & ATH9K_HTC_TXSTAT_FILT) +		tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; -		tx_ctl.type = ATH9K_HTC_NORMAL; +	if (txs->ts_flags & ATH9K_HTC_TXSTAT_RTC_CTS) +		rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; -		mgmt_hdr.node_idx = sta_idx; -		mgmt_hdr.vif_idx = vif_idx; -		mgmt_hdr.tidno = 0; -		mgmt_hdr.flags = 0; +	rate->count = 1; +	rate->idx = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_RATE); -		mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); -		if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) -			mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; -		else -			mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; +	if (txs->ts_flags & ATH9K_HTC_TXSTAT_MCS) { +		rate->flags |= IEEE80211_TX_RC_MCS; -		tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); -		memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); -		epid = priv->mgmt_ep; +		if (txs->ts_flags & ATH9K_HTC_TXSTAT_CW40) +			rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; +		if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI) +			rate->flags |= IEEE80211_TX_RC_SHORT_GI; +	} else { +		if (cur_conf->channel->band == IEEE80211_BAND_5GHZ) +			rate->idx += 4; /* No CCK rates */  	} -	return htc_send(priv->htc, skb, epid, &tx_ctl); +	ath9k_htc_check_tx_aggr(priv, vif, skb); + +send_mac80211: +	spin_lock_bh(&priv->tx.tx_lock); +	if (WARN_ON(--priv->tx.queued_cnt < 0)) +		priv->tx.queued_cnt = 0; +	spin_unlock_bh(&priv->tx.tx_lock); + +	ath9k_htc_tx_clear_slot(priv, slot); + +	/* Send status to mac80211 */ +	ieee80211_tx_status(priv->hw, skb);  } -static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, -				    struct ath9k_htc_sta *ista, u8 tid) +static inline void ath9k_htc_tx_drainq(struct ath9k_htc_priv *priv, +				       struct sk_buff_head *queue)  { -	bool ret = false; +	struct sk_buff *skb; -	spin_lock_bh(&priv->tx_lock); -	if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) -		ret = true; -	spin_unlock_bh(&priv->tx_lock); +	while ((skb = skb_dequeue(queue)) != NULL) { +		ath9k_htc_tx_process(priv, skb, NULL); +	} +} -	return ret; +void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv) +{ +	struct ath9k_htc_tx_event *event, *tmp; + +	spin_lock_bh(&priv->tx.tx_lock); +	priv->tx.flags |= ATH9K_HTC_OP_TX_DRAIN; +	spin_unlock_bh(&priv->tx.tx_lock); + +	/* +	 * Ensure that all pending TX frames are flushed, +	 * and that the TX completion/failed tasklets is killed. +	 */ +	htc_stop(priv->htc); +	tasklet_kill(&priv->wmi->wmi_event_tasklet); +	tasklet_kill(&priv->tx_failed_tasklet); + +	ath9k_htc_tx_drainq(priv, &priv->tx.mgmt_ep_queue); +	ath9k_htc_tx_drainq(priv, &priv->tx.cab_ep_queue); +	ath9k_htc_tx_drainq(priv, &priv->tx.data_be_queue); +	ath9k_htc_tx_drainq(priv, &priv->tx.data_bk_queue); +	ath9k_htc_tx_drainq(priv, &priv->tx.data_vi_queue); +	ath9k_htc_tx_drainq(priv, &priv->tx.data_vo_queue); +	ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); + +	/* +	 * The TX cleanup timer has already been killed. +	 */ +	spin_lock_bh(&priv->wmi->event_lock); +	list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) { +		list_del(&event->list); +		kfree(event); +	} +	spin_unlock_bh(&priv->wmi->event_lock); + +	spin_lock_bh(&priv->tx.tx_lock); +	priv->tx.flags &= ~ATH9K_HTC_OP_TX_DRAIN; +	spin_unlock_bh(&priv->tx.tx_lock);  } -void ath9k_tx_tasklet(unsigned long data) +void ath9k_tx_failed_tasklet(unsigned long data)  {  	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; -	struct ieee80211_vif *vif; -	struct ieee80211_sta *sta; -	struct ieee80211_hdr *hdr; -	struct ieee80211_tx_info *tx_info; -	struct sk_buff *skb = NULL; -	__le16 fc; -	while ((skb = skb_dequeue(&priv->tx_queue)) != NULL) { +	spin_lock_bh(&priv->tx.tx_lock); +	if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { +		spin_unlock_bh(&priv->tx.tx_lock); +		return; +	} +	spin_unlock_bh(&priv->tx.tx_lock); -		hdr = (struct ieee80211_hdr *) skb->data; -		fc = hdr->frame_control; -		tx_info = IEEE80211_SKB_CB(skb); -		vif = tx_info->control.vif; +	ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); +} -		memset(&tx_info->status, 0, sizeof(tx_info->status)); +static inline bool check_cookie(struct ath9k_htc_priv *priv, +				struct sk_buff *skb, +				u8 cookie, u8 epid) +{ +	u8 fcookie = 0; -		if (!vif) -			goto send_mac80211; +	if (epid == priv->mgmt_ep) { +		struct tx_mgmt_hdr *hdr; +		hdr = (struct tx_mgmt_hdr *) skb->data; +		fcookie = hdr->cookie; +	} else if ((epid == priv->data_bk_ep) || +		   (epid == priv->data_be_ep) || +		   (epid == priv->data_vi_ep) || +		   (epid == priv->data_vo_ep) || +		   (epid == priv->cab_ep)) { +		struct tx_frame_hdr *hdr; +		hdr = (struct tx_frame_hdr *) skb->data; +		fcookie = hdr->cookie; +	} -		rcu_read_lock(); +	if (fcookie == cookie) +		return true; -		sta = ieee80211_find_sta(vif, hdr->addr1); -		if (!sta) { -			rcu_read_unlock(); -			ieee80211_tx_status(priv->hw, skb); -			continue; +	return false; +} + +static struct sk_buff* ath9k_htc_tx_get_packet(struct ath9k_htc_priv *priv, +					       struct __wmi_event_txstatus *txs) +{ +	struct ath_common *common = ath9k_hw_common(priv->ah); +	struct sk_buff_head *epid_queue; +	struct sk_buff *skb, *tmp; +	unsigned long flags; +	u8 epid = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_EPID); + +	epid_queue = get_htc_epid_queue(priv, epid); +	if (!epid_queue) +		return NULL; + +	spin_lock_irqsave(&epid_queue->lock, flags); +	skb_queue_walk_safe(epid_queue, skb, tmp) { +		if (check_cookie(priv, skb, txs->cookie, epid)) { +			__skb_unlink(skb, epid_queue); +			spin_unlock_irqrestore(&epid_queue->lock, flags); +			return skb;  		} +	} +	spin_unlock_irqrestore(&epid_queue->lock, flags); -		/* Check if we need to start aggregation */ +	ath_dbg(common, ATH_DBG_XMIT, +		"No matching packet for cookie: %d, epid: %d\n", +		txs->cookie, epid); -		if (sta && conf_is_ht(&priv->hw->conf) && -		    !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { -			if (ieee80211_is_data_qos(fc)) { -				u8 *qc, tid; -				struct ath9k_htc_sta *ista; +	return NULL; +} -				qc = ieee80211_get_qos_ctl(hdr); -				tid = qc[0] & 0xf; -				ista = (struct ath9k_htc_sta *)sta->drv_priv; +void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event) +{ +	struct wmi_event_txstatus *txs = (struct wmi_event_txstatus *)wmi_event; +	struct __wmi_event_txstatus *__txs; +	struct sk_buff *skb; +	struct ath9k_htc_tx_event *tx_pend; +	int i; -				if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { -					ieee80211_start_tx_ba_session(sta, tid, 0); -					spin_lock_bh(&priv->tx_lock); -					ista->tid_state[tid] = AGGR_PROGRESS; -					spin_unlock_bh(&priv->tx_lock); -				} -			} -		} +	for (i = 0; i < txs->cnt; i++) { +		WARN_ON(txs->cnt > HTC_MAX_TX_STATUS); -		rcu_read_unlock(); +		__txs = &txs->txstatus[i]; + +		skb = ath9k_htc_tx_get_packet(priv, __txs); +		if (!skb) { +			/* +			 * Store this event, so that the TX cleanup +			 * routine can check later for the needed packet. +			 */ +			tx_pend = kzalloc(sizeof(struct ath9k_htc_tx_event), +					  GFP_ATOMIC); +			if (!tx_pend) +				continue; + +			memcpy(&tx_pend->txs, __txs, +			       sizeof(struct __wmi_event_txstatus)); -	send_mac80211: -		/* Send status to mac80211 */ -		ieee80211_tx_status(priv->hw, skb); +			spin_lock(&priv->wmi->event_lock); +			list_add_tail(&tx_pend->list, +				      &priv->wmi->pending_tx_events); +			spin_unlock(&priv->wmi->event_lock); + +			continue; +		} + +		ath9k_htc_tx_process(priv, skb, __txs);  	}  	/* Wake TX queues if needed */ -	spin_lock_bh(&priv->tx_lock); -	if (priv->tx_queues_stop) { -		priv->tx_queues_stop = false; -		spin_unlock_bh(&priv->tx_lock); -		ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, -			"Waking up TX queues\n"); -		ieee80211_wake_queues(priv->hw); -		return; -	} -	spin_unlock_bh(&priv->tx_lock); +	ath9k_htc_check_wake_queues(priv);  }  void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,  		    enum htc_endpoint_id ep_id, bool txok)  {  	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; -	struct ath_common *common = ath9k_hw_common(priv->ah); -	struct ieee80211_tx_info *tx_info; +	struct ath9k_htc_tx_ctl *tx_ctl; +	struct sk_buff_head *epid_queue; + +	tx_ctl = HTC_SKB_CB(skb); +	tx_ctl->txok = txok; +	tx_ctl->timestamp = jiffies; -	if (!skb) +	if (!txok) { +		skb_queue_tail(&priv->tx.tx_failed, skb); +		tasklet_schedule(&priv->tx_failed_tasklet);  		return; +	} -	if (ep_id == priv->mgmt_ep) { -		skb_pull(skb, sizeof(struct tx_mgmt_hdr)); -	} else if ((ep_id == priv->data_bk_ep) || -		   (ep_id == priv->data_be_ep) || -		   (ep_id == priv->data_vi_ep) || -		   (ep_id == priv->data_vo_ep)) { -		skb_pull(skb, sizeof(struct tx_frame_hdr)); -	} else { -		ath_err(common, "Unsupported TX EPID: %d\n", ep_id); +	epid_queue = get_htc_epid_queue(priv, ep_id); +	if (!epid_queue) {  		dev_kfree_skb_any(skb);  		return;  	} -	tx_info = IEEE80211_SKB_CB(skb); +	skb_queue_tail(epid_queue, skb); +} -	if (txok) -		tx_info->flags |= IEEE80211_TX_STAT_ACK; +static inline bool check_packet(struct ath9k_htc_priv *priv, struct sk_buff *skb) +{ +	struct ath_common *common = ath9k_hw_common(priv->ah); +	struct ath9k_htc_tx_ctl *tx_ctl; + +	tx_ctl = HTC_SKB_CB(skb); + +	if (time_after(jiffies, +		       tx_ctl->timestamp + +		       msecs_to_jiffies(ATH9K_HTC_TX_TIMEOUT_INTERVAL))) { +		ath_dbg(common, ATH_DBG_XMIT, +			"Dropping a packet due to TX timeout\n"); +		return true; +	} + +	return false; +} + +static void ath9k_htc_tx_cleanup_queue(struct ath9k_htc_priv *priv, +				       struct sk_buff_head *epid_queue) +{ +	bool process = false; +	unsigned long flags; +	struct sk_buff *skb, *tmp; +	struct sk_buff_head queue; + +	skb_queue_head_init(&queue); + +	spin_lock_irqsave(&epid_queue->lock, flags); +	skb_queue_walk_safe(epid_queue, skb, tmp) { +		if (check_packet(priv, skb)) { +			__skb_unlink(skb, epid_queue); +			__skb_queue_tail(&queue, skb); +			process = true; +		} +	} +	spin_unlock_irqrestore(&epid_queue->lock, flags); -	skb_queue_tail(&priv->tx_queue, skb); -	tasklet_schedule(&priv->tx_tasklet); +	if (process) { +		skb_queue_walk_safe(&queue, skb, tmp) { +			__skb_unlink(skb, &queue); +			ath9k_htc_tx_process(priv, skb, NULL); +		} +	} +} + +void ath9k_htc_tx_cleanup_timer(unsigned long data) +{ +	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) data; +	struct ath_common *common = ath9k_hw_common(priv->ah); +	struct ath9k_htc_tx_event *event, *tmp; +	struct sk_buff *skb; + +	spin_lock(&priv->wmi->event_lock); +	list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) { + +		skb = ath9k_htc_tx_get_packet(priv, &event->txs); +		if (skb) { +			ath_dbg(common, ATH_DBG_XMIT, +				"Found packet for cookie: %d, epid: %d\n", +				event->txs.cookie, +				MS(event->txs.ts_rate, ATH9K_HTC_TXSTAT_EPID)); + +			ath9k_htc_tx_process(priv, skb, &event->txs); +			list_del(&event->list); +			kfree(event); +			continue; +		} + +		if (++event->count >= ATH9K_HTC_TX_TIMEOUT_COUNT) { +			list_del(&event->list); +			kfree(event); +		} +	} +	spin_unlock(&priv->wmi->event_lock); + +	/* +	 * Check if status-pending packets have to be cleaned up. +	 */ +	ath9k_htc_tx_cleanup_queue(priv, &priv->tx.mgmt_ep_queue); +	ath9k_htc_tx_cleanup_queue(priv, &priv->tx.cab_ep_queue); +	ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_be_queue); +	ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_bk_queue); +	ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vi_queue); +	ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vo_queue); + +	/* Wake TX queues if needed */ +	ath9k_htc_check_wake_queues(priv); + +	mod_timer(&priv->tx.cleanup_timer, +		  jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));  }  int ath9k_tx_init(struct ath9k_htc_priv *priv)  { -	skb_queue_head_init(&priv->tx_queue); +	skb_queue_head_init(&priv->tx.mgmt_ep_queue); +	skb_queue_head_init(&priv->tx.cab_ep_queue); +	skb_queue_head_init(&priv->tx.data_be_queue); +	skb_queue_head_init(&priv->tx.data_bk_queue); +	skb_queue_head_init(&priv->tx.data_vi_queue); +	skb_queue_head_init(&priv->tx.data_vo_queue); +	skb_queue_head_init(&priv->tx.tx_failed);  	return 0;  } @@ -507,8 +970,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,  	int last_rssi = ATH_RSSI_DUMMY_MARKER;  	__le16 fc; -	if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) { -		ath_err(common, "Corrupted RX frame, dropping\n"); +	if (skb->len < HTC_RX_FRAME_HEADER_SIZE) { +		ath_err(common, "Corrupted RX frame, dropping (len: %d)\n", +			skb->len);  		goto rx_next;  	} @@ -522,6 +986,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,  		goto rx_next;  	} +	ath9k_htc_err_stat_rx(priv, rxstatus); +  	/* Get the RX status information */  	memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);  	skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 62e139a30a7..cee970fdf65 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -17,8 +17,8 @@  #include "htc.h"  static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, -			  u16 len, u8 flags, u8 epid, -			  struct ath9k_htc_tx_ctl *tx_ctl) +			  u16 len, u8 flags, u8 epid) +  {  	struct htc_frame_hdr *hdr;  	struct htc_endpoint *endpoint = &target->endpoint[epid]; @@ -30,8 +30,8 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb,  	hdr->flags = flags;  	hdr->payload_len = cpu_to_be16(len); -	status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb, -				   tx_ctl); +	status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb); +  	return status;  } @@ -162,7 +162,7 @@ static int htc_config_pipe_credits(struct htc_target *target)  	target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; -	ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); +	ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);  	if (ret)  		goto err; @@ -197,7 +197,7 @@ static int htc_setup_complete(struct htc_target *target)  	target->htc_flags |= HTC_OP_START_WAIT; -	ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); +	ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);  	if (ret)  		goto err; @@ -268,7 +268,7 @@ int htc_connect_service(struct htc_target *target,  	conn_msg->dl_pipeid = endpoint->dl_pipeid;  	conn_msg->ul_pipeid = endpoint->ul_pipeid; -	ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); +	ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);  	if (ret)  		goto err; @@ -286,35 +286,33 @@ err:  	return ret;  } -int htc_send(struct htc_target *target, struct sk_buff *skb, -	     enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl) +int htc_send(struct htc_target *target, struct sk_buff *skb)  { -	return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl); +	struct ath9k_htc_tx_ctl *tx_ctl; + +	tx_ctl = HTC_SKB_CB(skb); +	return htc_issue_send(target, skb, skb->len, 0, tx_ctl->epid);  } -void htc_stop(struct htc_target *target) +int htc_send_epid(struct htc_target *target, struct sk_buff *skb, +		  enum htc_endpoint_id epid)  { -	enum htc_endpoint_id epid; -	struct htc_endpoint *endpoint; +	return htc_issue_send(target, skb, skb->len, 0, epid); +} -	for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { -		endpoint = &target->endpoint[epid]; -		if (endpoint->service_id != 0) -			target->hif->stop(target->hif_dev, endpoint->ul_pipeid); -	} +void htc_stop(struct htc_target *target) +{ +	target->hif->stop(target->hif_dev);  }  void htc_start(struct htc_target *target)  { -	enum htc_endpoint_id epid; -	struct htc_endpoint *endpoint; +	target->hif->start(target->hif_dev); +} -	for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { -		endpoint = &target->endpoint[epid]; -		if (endpoint->service_id != 0) -			target->hif->start(target->hif_dev, -					   endpoint->ul_pipeid); -	} +void htc_sta_drain(struct htc_target *target, u8 idx) +{ +	target->hif->sta_drain(target->hif_dev, idx);  }  void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index ecd018798c4..cb9174ade53 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -33,10 +33,10 @@ struct ath9k_htc_hif {  	u8 control_dl_pipe;  	u8 control_ul_pipe; -	void (*start) (void *hif_handle, u8 pipe); -	void (*stop) (void *hif_handle, u8 pipe); -	int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf, -		     struct ath9k_htc_tx_ctl *tx_ctl); +	void (*start) (void *hif_handle); +	void (*stop) (void *hif_handle); +	void (*sta_drain) (void *hif_handle, u8 idx); +	int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf);  };  enum htc_endpoint_id { @@ -205,10 +205,12 @@ int htc_init(struct htc_target *target);  int htc_connect_service(struct htc_target *target,  			  struct htc_service_connreq *service_connreq,  			  enum htc_endpoint_id *conn_rsp_eid); -int htc_send(struct htc_target *target, struct sk_buff *skb, -	     enum htc_endpoint_id eid, struct ath9k_htc_tx_ctl *tx_ctl); +int htc_send(struct htc_target *target, struct sk_buff *skb); +int htc_send_epid(struct htc_target *target, struct sk_buff *skb, +		  enum htc_endpoint_id epid);  void htc_stop(struct htc_target *target);  void htc_start(struct htc_target *target); +void htc_sta_drain(struct htc_target *target, u8 idx);  void ath9k_htc_rx_msg(struct htc_target *htc_handle,  		      struct sk_buff *skb, u32 len, u8 pipe_id); diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 22ee888b0ba..9dd90a85ad6 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -122,6 +122,11 @@ static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds,  	ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration);  } +static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) +{ +	ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); +} +  /* Private hardware call ops */  /* PHY ops */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c8a2d0dae79..045abd55784 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -676,42 +676,55 @@ unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah)  }  EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); -#define DPLL2_KD_VAL            0x3D -#define DPLL2_KI_VAL            0x06 -#define DPLL3_PHASE_SHIFT_VAL   0x1 - +#define DPLL3_PHASE_SHIFT_VAL 0x1  static void ath9k_hw_init_pll(struct ath_hw *ah,  			      struct ath9k_channel *chan)  {  	u32 pll;  	if (AR_SREV_9485(ah)) { -		REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); -		REG_WRITE(ah, AR_CH0_DDR_DPLL2, 0x19e82f01); - -		REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3, -			      AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); -		REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); -		udelay(1000); +		/* program BB PLL ki and kd value, ki=0x4, kd=0x40 */ +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, +			      AR_CH0_BB_DPLL2_PLL_PWD, 0x1); +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, +			      AR_CH0_DPLL2_KD, 0x40); +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, +			      AR_CH0_DPLL2_KI, 0x4); -		REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, +			      AR_CH0_BB_DPLL1_REFDIV, 0x5); +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, +			      AR_CH0_BB_DPLL1_NINI, 0x58); +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, +			      AR_CH0_BB_DPLL1_NFRAC, 0x0);  		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, -			      AR_CH0_DPLL2_KD, DPLL2_KD_VAL); +			      AR_CH0_BB_DPLL2_OUTDIV, 0x1); +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, +			      AR_CH0_BB_DPLL2_LOCAL_PLL, 0x1);  		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, -			      AR_CH0_DPLL2_KI, DPLL2_KI_VAL); +			      AR_CH0_BB_DPLL2_EN_NEGTRIG, 0x1); +		/* program BB PLL phase_shift to 0x6 */  		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, -			      AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); -		REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c); +			      AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6); + +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, +			      AR_CH0_BB_DPLL2_PLL_PWD, 0x0);  		udelay(1000); + +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, +			      AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);  	}  	pll = ath9k_hw_compute_pll_control(ah, chan);  	REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); +	if (AR_SREV_9485(ah)) +		udelay(1000); +  	/* Switch the core clock for ar9271 to 117Mhz */  	if (AR_SREV_9271(ah)) {  		udelay(500); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index a778b66f443..1018d6cbd53 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -626,6 +626,7 @@ struct ath_hw_ops {  	void (*clr11n_aggr)(struct ath_hw *ah, void *ds);  	void (*set11n_burstduration)(struct ath_hw *ah, void *ds,  				     u32 burstDuration); +	void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);  };  struct ath_nf_limits { @@ -846,6 +847,14 @@ struct ath_hw {  	u32 ent_mode;  }; +struct ath_bus_ops { +	enum ath_bus_type ath_bus_type; +	void (*read_cachesize)(struct ath_common *common, int *csz); +	bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); +	void (*bt_coex_prep)(struct ath_common *common); +	void (*extn_synch_en)(struct ath_common *common); +}; +  static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)  {  	return &ah->common; diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index c2a59386fb9..b60c130917f 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -239,7 +239,6 @@ struct ath_desc {  	void *ds_vdata;  } __packed __aligned(4); -#define ATH9K_TXDESC_CLRDMASK		0x0001  #define ATH9K_TXDESC_NOACK		0x0002  #define ATH9K_TXDESC_RTSENA		0x0004  #define ATH9K_TXDESC_CTSENA		0x0008 diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 4c5c9997dac..a8d9009a76d 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1373,6 +1373,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,  	if ((iter_data.naps + iter_data.nadhocs) > 0) {  		sc->sc_flags |= SC_OP_ANI_RUN;  		ath_start_ani(common); +	} else { +		sc->sc_flags &= ~SC_OP_ANI_RUN; +		del_timer_sync(&common->ani.timer);  	}  } @@ -1733,23 +1736,63 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,  			 struct ieee80211_sta *sta)  {  	struct ath_softc *sc = hw->priv; +	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	struct ath_node *an = (struct ath_node *) sta->drv_priv; +	struct ieee80211_key_conf ps_key = { };  	ath_node_attach(sc, sta); +	an->ps_key = ath_key_config(common, vif, sta, &ps_key);  	return 0;  } +static void ath9k_del_ps_key(struct ath_softc *sc, +			     struct ieee80211_vif *vif, +			     struct ieee80211_sta *sta) +{ +	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	struct ath_node *an = (struct ath_node *) sta->drv_priv; +	struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key }; + +	if (!an->ps_key) +	    return; + +	ath_key_delete(common, &ps_key); +} +  static int ath9k_sta_remove(struct ieee80211_hw *hw,  			    struct ieee80211_vif *vif,  			    struct ieee80211_sta *sta)  {  	struct ath_softc *sc = hw->priv; +	ath9k_del_ps_key(sc, vif, sta);  	ath_node_detach(sc, sta);  	return 0;  } +static void ath9k_sta_notify(struct ieee80211_hw *hw, +			 struct ieee80211_vif *vif, +			 enum sta_notify_cmd cmd, +			 struct ieee80211_sta *sta) +{ +	struct ath_softc *sc = hw->priv; +	struct ath_node *an = (struct ath_node *) sta->drv_priv; + +	switch (cmd) { +	case STA_NOTIFY_SLEEP: +		an->sleeping = true; +		if (ath_tx_aggr_sleep(sc, an)) +			ieee80211_sta_set_tim(sta); +		break; +	case STA_NOTIFY_AWAKE: +		an->sleeping = false; +		ath_tx_aggr_wakeup(sc, an); +		break; +	} +} +  static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,  			 const struct ieee80211_tx_queue_params *params)  { @@ -1826,6 +1869,9 @@ static int ath9k_set_key(struct ieee80211_hw *hw,  	switch (cmd) {  	case SET_KEY: +		if (sta) +			ath9k_del_ps_key(sc, vif, sta); +  		ret = ath_key_config(common, vif, sta, key);  		if (ret >= 0) {  			key->hw_key_idx = ret; @@ -2209,6 +2255,21 @@ out:  	ath9k_ps_restore(sc);  } +static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) +{ +	struct ath_softc *sc = hw->priv; +	int i; + +	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { +		if (!ATH_TXQ_SETUP(sc, i)) +			continue; + +		if (ath9k_has_pending_frames(sc, &sc->tx.txq[i])) +			return true; +	} +	return false; +} +  struct ieee80211_ops ath9k_ops = {  	.tx 		    = ath9k_tx,  	.start 		    = ath9k_start, @@ -2220,6 +2281,7 @@ struct ieee80211_ops ath9k_ops = {  	.configure_filter   = ath9k_configure_filter,  	.sta_add	    = ath9k_sta_add,  	.sta_remove	    = ath9k_sta_remove, +	.sta_notify         = ath9k_sta_notify,  	.conf_tx 	    = ath9k_conf_tx,  	.bss_info_changed   = ath9k_bss_info_changed,  	.set_key            = ath9k_set_key, @@ -2231,4 +2293,5 @@ struct ieee80211_ops ath9k_ops = {  	.rfkill_poll        = ath9k_rfkill_poll_state,  	.set_coverage_class = ath9k_set_coverage_class,  	.flush		    = ath9k_flush, +	.tx_frames_pending  = ath9k_tx_frames_pending,  }; diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index f50e2c29f71..8e5fe9d7f17 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -19,7 +19,6 @@  #define CHANSEL_DIV		15  #define CHANSEL_2G(_freq)	(((_freq) * 0x10000) / CHANSEL_DIV) -#define CHANSEL_2G_9485(_freq)	((((_freq) * 0x10000) - 215) / CHANSEL_DIV)  #define CHANSEL_5G(_freq)	(((_freq) * 0x8000) / CHANSEL_DIV)  #define AR_PHY_BASE     0x9800 diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 4c0d36a6980..18094094b29 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1092,8 +1092,7 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,  	if (!(rate->flags & IEEE80211_TX_RC_MCS))  		return rate->idx; -	while (rate->idx > mcs_rix_off[i] && -	       i < ARRAY_SIZE(mcs_rix_off)) { +	while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) {  		rix++; i++;  	} diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index cfaf0a48b93..642504f9638 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -75,7 +75,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)  		*sc->rx.rxlink = bf->bf_daddr;  	sc->rx.rxlink = &ds->ds_link; -	ath9k_hw_rxena(ah);  }  static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) @@ -426,9 +425,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)  	else  		rfilt |= ATH9K_RX_FILTER_BEACON; -	if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) || -	    AR_SREV_9285_12_OR_LATER(sc->sc_ah)) && -	    (sc->sc_ah->opmode == NL80211_IFTYPE_AP) && +	if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||  	    (sc->rx.rxfilter & FIF_PSPOLL))  		rfilt |= ATH9K_RX_FILTER_PSPOLL; @@ -1767,6 +1764,7 @@ requeue:  		} else {  			list_move_tail(&bf->list, &sc->rx.rxbuf);  			ath_rx_buf_link(sc, bf); +			ath9k_hw_rxena(ah);  		}  	} while (1); diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 693d543937b..6acbf0e2240 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -858,9 +858,7 @@  #define AR_SREV_9300(_ah) \  	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))  #define AR_SREV_9300_20_OR_LATER(_ah) \ -	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \ -	 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ -	  ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20))) +	((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300)  #define AR_SREV_9485(_ah) \  	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) @@ -1088,14 +1086,35 @@ enum {  #define AR_ENT_OTP		  0x40d8  #define AR_ENT_OTP_CHAIN2_DISABLE               0x00020000  #define AR_ENT_OTP_MPSD		0x00800000 -#define AR_CH0_BB_DPLL2          0x16184 + +#define AR_CH0_BB_DPLL1		 0x16180 +#define AR_CH0_BB_DPLL1_REFDIV	 0xF8000000 +#define AR_CH0_BB_DPLL1_REFDIV_S 27 +#define AR_CH0_BB_DPLL1_NINI	 0x07FC0000 +#define AR_CH0_BB_DPLL1_NINI_S	 18 +#define AR_CH0_BB_DPLL1_NFRAC	 0x0003FFFF +#define AR_CH0_BB_DPLL1_NFRAC_S	 0 + +#define AR_CH0_BB_DPLL2		     0x16184 +#define AR_CH0_BB_DPLL2_LOCAL_PLL       0x40000000 +#define AR_CH0_BB_DPLL2_LOCAL_PLL_S     30 +#define AR_CH0_DPLL2_KI              0x3C000000 +#define AR_CH0_DPLL2_KI_S            26 +#define AR_CH0_DPLL2_KD              0x03F80000 +#define AR_CH0_DPLL2_KD_S            19 +#define AR_CH0_BB_DPLL2_EN_NEGTRIG   0x00040000 +#define AR_CH0_BB_DPLL2_EN_NEGTRIG_S 18 +#define AR_CH0_BB_DPLL2_PLL_PWD	     0x00010000 +#define AR_CH0_BB_DPLL2_PLL_PWD_S    16 +#define AR_CH0_BB_DPLL2_OUTDIV	     0x0000E000 +#define AR_CH0_BB_DPLL2_OUTDIV_S     13 +  #define AR_CH0_BB_DPLL3          0x16188 +#define AR_CH0_BB_DPLL3_PHASE_SHIFT	0x3F800000 +#define AR_CH0_BB_DPLL3_PHASE_SHIFT_S	23 +  #define AR_CH0_DDR_DPLL2         0x16244  #define AR_CH0_DDR_DPLL3         0x16248 -#define AR_CH0_DPLL2_KD              0x03F80000 -#define AR_CH0_DPLL2_KD_S            19 -#define AR_CH0_DPLL2_KI              0x3C000000 -#define AR_CH0_DPLL2_KI_S            26  #define AR_CH0_DPLL3_PHASE_SHIFT     0x3F800000  #define AR_CH0_DPLL3_PHASE_SHIFT_S   23  #define AR_PHY_CCA_NOM_VAL_2GHZ      -118 diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index d3d24904f62..8f095ad0a3d 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -23,20 +23,18 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)  		return "WMI_ECHO_CMDID";  	case WMI_ACCESS_MEMORY_CMDID:  		return "WMI_ACCESS_MEMORY_CMDID"; +	case WMI_GET_FW_VERSION: +		return "WMI_GET_FW_VERSION";  	case WMI_DISABLE_INTR_CMDID:  		return "WMI_DISABLE_INTR_CMDID";  	case WMI_ENABLE_INTR_CMDID:  		return "WMI_ENABLE_INTR_CMDID"; -	case WMI_RX_LINK_CMDID: -		return "WMI_RX_LINK_CMDID";  	case WMI_ATH_INIT_CMDID:  		return "WMI_ATH_INIT_CMDID";  	case WMI_ABORT_TXQ_CMDID:  		return "WMI_ABORT_TXQ_CMDID";  	case WMI_STOP_TX_DMA_CMDID:  		return "WMI_STOP_TX_DMA_CMDID"; -	case WMI_STOP_DMA_RECV_CMDID: -		return "WMI_STOP_DMA_RECV_CMDID";  	case WMI_ABORT_TX_DMA_CMDID:  		return "WMI_ABORT_TX_DMA_CMDID";  	case WMI_DRAIN_TXQ_CMDID: @@ -51,8 +49,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)  		return "WMI_FLUSH_RECV_CMDID";  	case WMI_SET_MODE_CMDID:  		return "WMI_SET_MODE_CMDID"; -	case WMI_RESET_CMDID: -		return "WMI_RESET_CMDID";  	case WMI_NODE_CREATE_CMDID:  		return "WMI_NODE_CREATE_CMDID";  	case WMI_NODE_REMOVE_CMDID: @@ -61,8 +57,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)  		return "WMI_VAP_REMOVE_CMDID";  	case WMI_VAP_CREATE_CMDID:  		return "WMI_VAP_CREATE_CMDID"; -	case WMI_BEACON_UPDATE_CMDID: -		return "WMI_BEACON_UPDATE_CMDID";  	case WMI_REG_READ_CMDID:  		return "WMI_REG_READ_CMDID";  	case WMI_REG_WRITE_CMDID: @@ -71,20 +65,20 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd)  		return "WMI_RC_STATE_CHANGE_CMDID";  	case WMI_RC_RATE_UPDATE_CMDID:  		return "WMI_RC_RATE_UPDATE_CMDID"; -	case WMI_DEBUG_INFO_CMDID: -		return "WMI_DEBUG_INFO_CMDID"; -	case WMI_HOST_ATTACH: -		return "WMI_HOST_ATTACH";  	case WMI_TARGET_IC_UPDATE_CMDID:  		return "WMI_TARGET_IC_UPDATE_CMDID"; -	case WMI_TGT_STATS_CMDID: -		return "WMI_TGT_STATS_CMDID";  	case WMI_TX_AGGR_ENABLE_CMDID:  		return "WMI_TX_AGGR_ENABLE_CMDID";  	case WMI_TGT_DETACH_CMDID:  		return "WMI_TGT_DETACH_CMDID"; -	case WMI_TGT_TXQ_ENABLE_CMDID: -		return "WMI_TGT_TXQ_ENABLE_CMDID"; +	case WMI_NODE_UPDATE_CMDID: +		return "WMI_NODE_UPDATE_CMDID"; +	case WMI_INT_STATS_CMDID: +		return "WMI_INT_STATS_CMDID"; +	case WMI_TX_STATS_CMDID: +		return "WMI_TX_STATS_CMDID"; +	case WMI_RX_STATS_CMDID: +		return "WMI_RX_STATS_CMDID";  	case WMI_AGGR_LIMIT_CMD:  		return "WMI_AGGR_LIMIT_CMD";  	} @@ -102,9 +96,15 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv)  	wmi->drv_priv = priv;  	wmi->stopped = false; +	skb_queue_head_init(&wmi->wmi_event_queue); +	spin_lock_init(&wmi->wmi_lock); +	spin_lock_init(&wmi->event_lock);  	mutex_init(&wmi->op_mutex);  	mutex_init(&wmi->multi_write_mutex);  	init_completion(&wmi->cmd_wait); +	INIT_LIST_HEAD(&wmi->pending_tx_events); +	tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet, +		     (unsigned long)wmi);  	return wmi;  } @@ -120,11 +120,65 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv)  	kfree(priv->wmi);  } -void ath9k_swba_tasklet(unsigned long data) +void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv)  { -	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; +	unsigned long flags; + +	tasklet_kill(&priv->wmi->wmi_event_tasklet); +	spin_lock_irqsave(&priv->wmi->wmi_lock, flags); +	__skb_queue_purge(&priv->wmi->wmi_event_queue); +	spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); +} + +void ath9k_wmi_event_tasklet(unsigned long data) +{ +	struct wmi *wmi = (struct wmi *)data; +	struct ath9k_htc_priv *priv = wmi->drv_priv; +	struct wmi_cmd_hdr *hdr; +	void *wmi_event; +	struct wmi_event_swba *swba; +	struct sk_buff *skb = NULL; +	unsigned long flags; +	u16 cmd_id; + +	do { +		spin_lock_irqsave(&wmi->wmi_lock, flags); +		skb = __skb_dequeue(&wmi->wmi_event_queue); +		if (!skb) { +			spin_unlock_irqrestore(&wmi->wmi_lock, flags); +			return; +		} +		spin_unlock_irqrestore(&wmi->wmi_lock, flags); + +		hdr = (struct wmi_cmd_hdr *) skb->data; +		cmd_id = be16_to_cpu(hdr->command_id); +		wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); + +		switch (cmd_id) { +		case WMI_SWBA_EVENTID: +			swba = (struct wmi_event_swba *) wmi_event; +			ath9k_htc_swba(priv, swba); +			break; +		case WMI_FATAL_EVENTID: +			ieee80211_queue_work(wmi->drv_priv->hw, +					     &wmi->drv_priv->fatal_work); +			break; +		case WMI_TXSTATUS_EVENTID: +			spin_lock_bh(&priv->tx.tx_lock); +			if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { +				spin_unlock_bh(&priv->tx.tx_lock); +				break; +			} +			spin_unlock_bh(&priv->tx.tx_lock); -	ath9k_htc_swba(priv, priv->wmi->beacon_pending); +			ath9k_htc_txstatus(priv, wmi_event); +			break; +		default: +			break; +		} + +		kfree_skb(skb); +	} while (1);  }  void ath9k_fatal_work(struct work_struct *work) @@ -153,10 +207,6 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,  	struct wmi *wmi = (struct wmi *) priv;  	struct wmi_cmd_hdr *hdr;  	u16 cmd_id; -	void *wmi_event; -#ifdef CONFIG_ATH9K_HTC_DEBUGFS -	__be32 txrate; -#endif  	if (unlikely(wmi->stopped))  		goto free_skb; @@ -165,26 +215,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,  	cmd_id = be16_to_cpu(hdr->command_id);  	if (cmd_id & 0x1000) { -		wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); -		switch (cmd_id) { -		case WMI_SWBA_EVENTID: -			wmi->beacon_pending = *(u8 *)wmi_event; -			tasklet_schedule(&wmi->drv_priv->swba_tasklet); -			break; -		case WMI_FATAL_EVENTID: -			ieee80211_queue_work(wmi->drv_priv->hw, -					     &wmi->drv_priv->fatal_work); -			break; -		case WMI_TXRATE_EVENTID: -#ifdef CONFIG_ATH9K_HTC_DEBUGFS -			txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; -			wmi->drv_priv->debug.txrate = be32_to_cpu(txrate); -#endif -			break; -		default: -			break; -		} -		kfree_skb(skb); +		spin_lock(&wmi->wmi_lock); +		__skb_queue_tail(&wmi->wmi_event_queue, skb); +		spin_unlock(&wmi->wmi_lock); +		tasklet_schedule(&wmi->wmi_event_tasklet);  		return;  	} @@ -243,7 +277,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi,  	hdr->command_id = cpu_to_be16(cmd);  	hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); -	return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL); +	return htc_send_epid(wmi->htc, skb, wmi->ctrl_epid);  }  int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 42084277522..02ecb9f06db 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -17,7 +17,6 @@  #ifndef WMI_H  #define WMI_H -  struct wmi_event_txrate {  	__be32 txrate;  	struct { @@ -31,18 +30,65 @@ struct wmi_cmd_hdr {  	__be16 seq_no;  } __packed; +struct wmi_fw_version { +	__be16 major; +	__be16 minor; + +} __packed; + +struct wmi_event_swba { +	__be64 tsf; +	u8 beacon_pending; +}; + +/* + * 64 - HTC header - WMI header - 1 / txstatus + * And some other hdr. space is also accounted for. + * 12 seems to be the magic number. + */ +#define HTC_MAX_TX_STATUS 12 + +#define ATH9K_HTC_TXSTAT_ACK        BIT(0) +#define ATH9K_HTC_TXSTAT_FILT       BIT(1) +#define ATH9K_HTC_TXSTAT_RTC_CTS    BIT(2) +#define ATH9K_HTC_TXSTAT_MCS        BIT(3) +#define ATH9K_HTC_TXSTAT_CW40       BIT(4) +#define ATH9K_HTC_TXSTAT_SGI        BIT(5) + +/* + * Legacy rates are indicated as indices. + * HT rates are indicated as dot11 numbers. + * This allows us to resrict the rate field + * to 4 bits. + */ +#define ATH9K_HTC_TXSTAT_RATE       0x0f +#define ATH9K_HTC_TXSTAT_RATE_S     0 + +#define ATH9K_HTC_TXSTAT_EPID       0xf0 +#define ATH9K_HTC_TXSTAT_EPID_S     4 + +struct __wmi_event_txstatus { +	u8 cookie; +	u8 ts_rate; /* Also holds EP ID */ +	u8 ts_flags; +}; + +struct wmi_event_txstatus { +	u8 cnt; +	struct __wmi_event_txstatus txstatus[HTC_MAX_TX_STATUS]; +} __packed; +  enum wmi_cmd_id {  	WMI_ECHO_CMDID = 0x0001,  	WMI_ACCESS_MEMORY_CMDID,  	/* Commands to Target */ +	WMI_GET_FW_VERSION,  	WMI_DISABLE_INTR_CMDID,  	WMI_ENABLE_INTR_CMDID, -	WMI_RX_LINK_CMDID,  	WMI_ATH_INIT_CMDID,  	WMI_ABORT_TXQ_CMDID,  	WMI_STOP_TX_DMA_CMDID, -	WMI_STOP_DMA_RECV_CMDID,  	WMI_ABORT_TX_DMA_CMDID,  	WMI_DRAIN_TXQ_CMDID,  	WMI_DRAIN_TXQ_ALL_CMDID, @@ -50,23 +96,21 @@ enum wmi_cmd_id {  	WMI_STOP_RECV_CMDID,  	WMI_FLUSH_RECV_CMDID,  	WMI_SET_MODE_CMDID, -	WMI_RESET_CMDID,  	WMI_NODE_CREATE_CMDID,  	WMI_NODE_REMOVE_CMDID,  	WMI_VAP_REMOVE_CMDID,  	WMI_VAP_CREATE_CMDID, -	WMI_BEACON_UPDATE_CMDID,  	WMI_REG_READ_CMDID,  	WMI_REG_WRITE_CMDID,  	WMI_RC_STATE_CHANGE_CMDID,  	WMI_RC_RATE_UPDATE_CMDID, -	WMI_DEBUG_INFO_CMDID, -	WMI_HOST_ATTACH,  	WMI_TARGET_IC_UPDATE_CMDID, -	WMI_TGT_STATS_CMDID,  	WMI_TX_AGGR_ENABLE_CMDID,  	WMI_TGT_DETACH_CMDID, -	WMI_TGT_TXQ_ENABLE_CMDID, +	WMI_NODE_UPDATE_CMDID, +	WMI_INT_STATS_CMDID, +	WMI_TX_STATS_CMDID, +	WMI_RX_STATS_CMDID,  	WMI_AGGR_LIMIT_CMD = 0x0026,  }; @@ -76,9 +120,8 @@ enum wmi_event_id {  	WMI_FATAL_EVENTID,  	WMI_TXTO_EVENTID,  	WMI_BMISS_EVENTID, -	WMI_WLAN_TXCOMP_EVENTID,  	WMI_DELBA_EVENTID, -	WMI_TXRATE_EVENTID, +	WMI_TXSTATUS_EVENTID,  };  #define MAX_CMD_NUMBER 62 @@ -88,6 +131,12 @@ struct register_write {  	__be32 val;  }; +struct ath9k_htc_tx_event { +	int count; +	struct __wmi_event_txstatus txs; +	struct list_head list; +}; +  struct wmi {  	struct ath9k_htc_priv *drv_priv;  	struct htc_target *htc; @@ -95,12 +144,16 @@ struct wmi {  	struct mutex op_mutex;  	struct completion cmd_wait;  	enum wmi_cmd_id last_cmd_id; +	struct sk_buff_head wmi_event_queue; +	struct tasklet_struct wmi_event_tasklet;  	u16 tx_seq_id;  	u8 *cmd_rsp_buf;  	u32 cmd_rsp_len;  	bool stopped; -	u8 beacon_pending; +	struct list_head pending_tx_events; +	spinlock_t event_lock; +  	spinlock_t wmi_lock;  	atomic_t mwrite_cnt; @@ -117,8 +170,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,  		  u8 *cmd_buf, u32 cmd_len,  		  u8 *rsp_buf, u32 rsp_len,  		  u32 timeout); -void ath9k_swba_tasklet(unsigned long data); +void ath9k_wmi_event_tasklet(unsigned long data);  void ath9k_fatal_work(struct work_struct *work); +void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv);  #define WMI_CMD(_wmi_cmd)						\  	do {								\ diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 3cea3f76e37..e9e99f730ca 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -357,6 +357,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  	struct ath_frame_info *fi;  	int nframes;  	u8 tidno; +	bool clear_filter;  	skb = bf->bf_mpdu;  	hdr = (struct ieee80211_hdr *)skb->data; @@ -441,22 +442,24 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  			/* transmit completion */  			acked_cnt++;  		} else { -			if (!(tid->state & AGGR_CLEANUP) && retry) { -				if (fi->retries < ATH_MAX_SW_RETRIES) { -					ath_tx_set_retry(sc, txq, bf->bf_mpdu); -					txpending = 1; -				} else { -					bf->bf_state.bf_type |= BUF_XRETRY; -					txfail = 1; -					sendbar = 1; -					txfail_cnt++; -				} -			} else { +			if ((tid->state & AGGR_CLEANUP) || !retry) {  				/*  				 * cleanup in progress, just fail  				 * the un-acked sub-frames  				 */  				txfail = 1; +			} else if (fi->retries < ATH_MAX_SW_RETRIES) { +				if (!(ts->ts_status & ATH9K_TXERR_FILT) || +				    !an->sleeping) +					ath_tx_set_retry(sc, txq, bf->bf_mpdu); + +				clear_filter = true; +				txpending = 1; +			} else { +				bf->bf_state.bf_type |= BUF_XRETRY; +				txfail = 1; +				sendbar = 1; +				txfail_cnt++;  			}  		} @@ -496,6 +499,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  				!txfail, sendbar);  		} else {  			/* retry the un-acked ones */ +			ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);  			if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {  				if (bf->bf_next == NULL && bf_last->bf_stale) {  					struct ath_buf *tbf; @@ -546,7 +550,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  	/* prepend un-acked frames to the beginning of the pending frame queue */  	if (!list_empty(&bf_pending)) { +		if (an->sleeping) +			ieee80211_sta_set_tim(sta); +  		spin_lock_bh(&txq->axq_lock); +		if (clear_filter) +			tid->ac->clear_ps_filter = true;  		list_splice(&bf_pending, &tid->buf_q);  		ath_tx_queue_tid(txq, tid);  		spin_unlock_bh(&txq->axq_lock); @@ -816,6 +825,11 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,  		bf = list_first_entry(&bf_q, struct ath_buf, list);  		bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); +		if (tid->ac->clear_ps_filter) { +			tid->ac->clear_ps_filter = false; +			ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); +		} +  		/* if only one frame, send as non-aggregate */  		if (bf == bf->bf_lastbf) {  			fi = get_frame_info(bf->bf_mpdu); @@ -896,6 +910,67 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)  	ath_tx_flush_tid(sc, txtid);  } +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) +{ +	struct ath_atx_tid *tid; +	struct ath_atx_ac *ac; +	struct ath_txq *txq; +	bool buffered = false; +	int tidno; + +	for (tidno = 0, tid = &an->tid[tidno]; +	     tidno < WME_NUM_TID; tidno++, tid++) { + +		if (!tid->sched) +			continue; + +		ac = tid->ac; +		txq = ac->txq; + +		spin_lock_bh(&txq->axq_lock); + +		if (!list_empty(&tid->buf_q)) +			buffered = true; + +		tid->sched = false; +		list_del(&tid->list); + +		if (ac->sched) { +			ac->sched = false; +			list_del(&ac->list); +		} + +		spin_unlock_bh(&txq->axq_lock); +	} + +	return buffered; +} + +void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) +{ +	struct ath_atx_tid *tid; +	struct ath_atx_ac *ac; +	struct ath_txq *txq; +	int tidno; + +	for (tidno = 0, tid = &an->tid[tidno]; +	     tidno < WME_NUM_TID; tidno++, tid++) { + +		ac = tid->ac; +		txq = ac->txq; + +		spin_lock_bh(&txq->axq_lock); +		ac->clear_ps_filter = true; + +		if (!list_empty(&tid->buf_q) && !tid->paused) { +			ath_tx_queue_tid(txq, tid); +			ath_txq_schedule(sc, txq); +		} + +		spin_unlock_bh(&txq->axq_lock); +	} +} +  void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)  {  	struct ath_atx_tid *txtid; @@ -1451,7 +1526,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,  	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;  	struct ieee80211_hdr *hdr;  	struct ath_frame_info *fi = get_frame_info(skb); -	struct ath_node *an; +	struct ath_node *an = NULL;  	struct ath_atx_tid *tid;  	enum ath9k_key_type keytype;  	u16 seqno = 0; @@ -1459,11 +1534,13 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,  	keytype = ath9k_cmn_get_hw_crypto_keytype(skb); +	if (sta) +		an = (struct ath_node *) sta->drv_priv; +  	hdr = (struct ieee80211_hdr *)skb->data; -	if (sta && ieee80211_is_data_qos(hdr->frame_control) && +	if (an && ieee80211_is_data_qos(hdr->frame_control) &&  		conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { -		an = (struct ath_node *) sta->drv_priv;  		tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;  		/* @@ -1479,6 +1556,8 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,  	memset(fi, 0, sizeof(*fi));  	if (hw_key)  		fi->keyix = hw_key->hw_key_idx; +	else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) +		fi->keyix = an->ps_key;  	else  		fi->keyix = ATH9K_TXKEYIX_INVALID;  	fi->keytype = keytype; @@ -1491,7 +1570,6 @@ static int setup_tx_flags(struct sk_buff *skb)  	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);  	int flags = 0; -	flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */  	flags |= ATH9K_TXDESC_INTREQ;  	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) @@ -1754,6 +1832,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,  		if (txctl->paprd)  			bf->bf_state.bfs_paprd_timestamp = jiffies; +		if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) +			ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); +  		ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);  	} diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index 0d4f39cbdca..a61ef3d6d89 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c @@ -483,6 +483,9 @@ int ath_key_config(struct ath_common *common,  	memset(&hk, 0, sizeof(hk));  	switch (key->cipher) { +	case 0: +		hk.kv_type = ATH_CIPHER_CLR; +		break;  	case WLAN_CIPHER_SUITE_WEP40:  	case WLAN_CIPHER_SUITE_WEP104:  		hk.kv_type = ATH_CIPHER_WEP; @@ -498,7 +501,8 @@ int ath_key_config(struct ath_common *common,  	}  	hk.kv_len = key->keylen; -	memcpy(hk.kv_val, key->key, key->keylen); +	if (key->keylen) +		memcpy(hk.kv_val, key->key, key->keylen);  	if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {  		switch (vif->type) { diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 0e1b8793c86..028310f263c 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -97,8 +97,8 @@ static const struct ieee80211_regdomain ath_world_regdom_66_69 = {  	}  }; -/* Can be used by 0x67, 0x6A and 0x68 */ -static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = { +/* Can be used by 0x67, 0x68, 0x6A and 0x6C */ +static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {  	.n_reg_rules = 4,  	.alpha2 =  "99",  	.reg_rules = { @@ -151,7 +151,8 @@ ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)  	case 0x67:  	case 0x68:  	case 0x6A: -		return &ath_world_regdom_67_68_6A; +	case 0x6C: +		return &ath_world_regdom_67_68_6A_6C;  	default:  		WARN_ON(1);  		return ath_default_world_regdomain(); @@ -333,6 +334,7 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy,  	case 0x63:  	case 0x66:  	case 0x67: +	case 0x6C:  		ath_reg_apply_beaconing_flags(wiphy, initiator);  		break;  	case 0x68: diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index 5c2cfe69415..24b53839fc3 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h @@ -86,6 +86,7 @@ enum EnumRd {  	WOR9_WORLD = 0x69,  	WORA_WORLD = 0x6A,  	WORB_WORLD = 0x6B, +	WORC_WORLD = 0x6C,  	MKK3_MKKB = 0x80,  	MKK3_MKKA2 = 0x81, @@ -282,6 +283,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = {  	{WOR9_WORLD, NO_CTL, NO_CTL},  	{WORA_WORLD, NO_CTL, NO_CTL},  	{WORB_WORLD, NO_CTL, NO_CTL}, +	{WORC_WORLD, NO_CTL, NO_CTL},  };  static struct country_code_to_enum_rd allCountries[] = { diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c index 31ac672b64e..89509392ef5 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c @@ -2860,7 +2860,6 @@ static struct rate_control_ops rs_4965_ops = {  int iwl4965_rate_control_register(void)  { -	pr_err("Registering 4965 rate control operations\n");  	return ieee80211_rate_control_register(&rs_4965_ops);  } diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c index d484c367816..f8870543d68 100644 --- a/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -3173,7 +3173,7 @@ static void iwl4965_hw_detect(struct iwl_priv *priv)  {  	priv->hw_rev = _iwl_legacy_read32(priv, CSR_HW_REV);  	priv->hw_wa_rev = _iwl_legacy_read32(priv, CSR_HW_REV_WA_REG); -	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id); +	priv->rev_id = priv->pci_dev->revision;  	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);  } diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 3652931753e..bb6a737de61 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -1,6 +1,6 @@  # AGN  obj-$(CONFIG_IWLAGN)	+= iwlagn.o -iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o +iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o  iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-tx.o  iwlagn-objs		+= iwl-agn-lib.o iwl-agn-calib.o iwl-io.o  iwlagn-objs		+= iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 1b279929183..baf80111efa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -45,7 +45,6 @@  #include "iwl-agn.h"  #include "iwl-helpers.h"  #include "iwl-agn-hw.h" -#include "iwl-agn-led.h"  #include "iwl-agn-debugfs.h"  /* Highest firmware API version supported */ @@ -57,12 +56,10 @@  #define IWL100_UCODE_API_MIN 5  #define IWL1000_FW_PRE "iwlwifi-1000-" -#define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" -#define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api) +#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode"  #define IWL100_FW_PRE "iwlwifi-100-" -#define _IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode" -#define IWL100_MODULE_FIRMWARE(api) _IWL100_MODULE_FIRMWARE(api) +#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode"  /* @@ -184,10 +181,6 @@ static struct iwl_lib_ops iwl1000_lib = {  	.rx_handler_setup = iwlagn_rx_handler_setup,  	.setup_deferred_work = iwlagn_setup_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.dump_nic_event_log = iwl_dump_nic_event_log, -	.dump_nic_error_log = iwl_dump_nic_error_log, -	.dump_csr = iwl_dump_csr, -	.dump_fh = iwl_dump_fh,  	.send_tx_power = iwlagn_send_tx_power,  	.update_chain_flags = iwl_update_chain_flags,  	.apm_ops = { @@ -202,7 +195,7 @@ static struct iwl_lib_ops iwl1000_lib = {  			EEPROM_REG_BAND_4_CHANNELS,  			EEPROM_REG_BAND_5_CHANNELS,  			EEPROM_REG_BAND_24_HT40_CHANNELS, -			EEPROM_REG_BAND_52_HT40_CHANNELS +			EEPROM_REGULATORY_BAND_NO_HT40,  		},  		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,  		.release_semaphore = iwlcore_eeprom_release_semaphore, @@ -221,19 +214,12 @@ static struct iwl_lib_ops iwl1000_lib = {  	},  	.txfifo_flush = iwlagn_txfifo_flush,  	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, -	.tt_ops = { -		.lower_power_detection = iwl_tt_is_low_power_state, -		.tt_power_mode = iwl_tt_current_power_mode, -		.ct_kill_check = iwl_check_for_ct_kill, -	}  };  static const struct iwl_ops iwl1000_ops = {  	.lib = &iwl1000_lib,  	.hcmd = &iwlagn_hcmd,  	.utils = &iwlagn_hcmd_utils, -	.led = &iwlagn_led_ops, -	.ieee80211_ops = &iwlagn_hw_ops,  };  static struct iwl_base_params iwl1000_base_params = { @@ -241,7 +227,6 @@ static struct iwl_base_params iwl1000_base_params = {  	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,  	.eeprom_size = OTP_LOW_IMAGE_SIZE,  	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, -	.set_l0s = true,  	.max_ll_items = OTP_MAX_LL_ITEMS_1000,  	.shadow_ram_support = false,  	.led_compensation = 51, @@ -251,9 +236,6 @@ static struct iwl_base_params iwl1000_base_params = {  	.chain_noise_scale = 1000,  	.wd_timeout = IWL_DEF_WD_TIMEOUT,  	.max_event_log_size = 128, -	.ucode_tracing = true, -	.sensitivity_calib_by_driver = true, -	.chain_noise_calib_by_driver = true,  };  static struct iwl_ht_params iwl1000_ht_params = {  	.ht_greenfield_support = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index f602af4b940..e76e02c2892 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -46,7 +46,6 @@  #include "iwl-helpers.h"  #include "iwl-agn-hw.h"  #include "iwl-6000-hw.h" -#include "iwl-agn-led.h"  #include "iwl-agn-debugfs.h"  /* Highest firmware API version supported */ @@ -60,16 +59,13 @@  #define IWL200_UCODE_API_MIN 5  #define IWL2030_FW_PRE "iwlwifi-2030-" -#define _IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode" -#define IWL2030_MODULE_FIRMWARE(api) _IWL2030_MODULE_FIRMWARE(api) +#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode"  #define IWL2000_FW_PRE "iwlwifi-2000-" -#define _IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode" -#define IWL2000_MODULE_FIRMWARE(api) _IWL2000_MODULE_FIRMWARE(api) +#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode"  #define IWL200_FW_PRE "iwlwifi-200-" -#define _IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode" -#define IWL200_MODULE_FIRMWARE(api) _IWL200_MODULE_FIRMWARE(api) +#define IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode"  static void iwl2000_set_ct_threshold(struct iwl_priv *priv)  { @@ -101,6 +97,8 @@ static void iwl2000_nic_config(struct iwl_priv *priv)  		iwl_set_bit(priv, CSR_GP_DRIVER_REG,  			    CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); +	if (priv->cfg->disable_otp_refresh) +		iwl_write_prph(priv, APMG_ANALOG_SVR_REG, 0x80000010);  }  static struct iwl_sensitivity_ranges iwl2000_sensitivity = { @@ -265,10 +263,6 @@ static struct iwl_lib_ops iwl2000_lib = {  	.setup_deferred_work = iwlagn_bt_setup_deferred_work,  	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.dump_nic_event_log = iwl_dump_nic_event_log, -	.dump_nic_error_log = iwl_dump_nic_error_log, -	.dump_csr = iwl_dump_csr, -	.dump_fh = iwl_dump_fh,  	.send_tx_power = iwlagn_send_tx_power,  	.update_chain_flags = iwl_update_chain_flags,  	.set_channel_switch = iwl2030_hw_channel_switch, @@ -284,7 +278,7 @@ static struct iwl_lib_ops iwl2000_lib = {  			EEPROM_REG_BAND_4_CHANNELS,  			EEPROM_REG_BAND_5_CHANNELS,  			EEPROM_6000_REG_BAND_24_HT40_CHANNELS, -			EEPROM_REG_BAND_52_HT40_CHANNELS +			EEPROM_REGULATORY_BAND_NO_HT40,  		},  		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,  		.release_semaphore = iwlcore_eeprom_release_semaphore, @@ -304,43 +298,30 @@ static struct iwl_lib_ops iwl2000_lib = {  	},  	.txfifo_flush = iwlagn_txfifo_flush,  	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, -	.tt_ops = { -		.lower_power_detection = iwl_tt_is_low_power_state, -		.tt_power_mode = iwl_tt_current_power_mode, -		.ct_kill_check = iwl_check_for_ct_kill, -	}  };  static const struct iwl_ops iwl2000_ops = {  	.lib = &iwl2000_lib,  	.hcmd = &iwlagn_hcmd,  	.utils = &iwlagn_hcmd_utils, -	.led = &iwlagn_led_ops, -	.ieee80211_ops = &iwlagn_hw_ops,  };  static const struct iwl_ops iwl2030_ops = {  	.lib = &iwl2000_lib,  	.hcmd = &iwlagn_bt_hcmd,  	.utils = &iwlagn_hcmd_utils, -	.led = &iwlagn_led_ops, -	.ieee80211_ops = &iwlagn_hw_ops,  };  static const struct iwl_ops iwl200_ops = {  	.lib = &iwl2000_lib,  	.hcmd = &iwlagn_hcmd,  	.utils = &iwlagn_hcmd_utils, -	.led = &iwlagn_led_ops, -	.ieee80211_ops = &iwlagn_hw_ops,  };  static const struct iwl_ops iwl230_ops = {  	.lib = &iwl2000_lib,  	.hcmd = &iwlagn_bt_hcmd,  	.utils = &iwlagn_hcmd_utils, -	.led = &iwlagn_led_ops, -	.ieee80211_ops = &iwlagn_hw_ops,  };  static struct iwl_base_params iwl2000_base_params = { @@ -348,7 +329,6 @@ static struct iwl_base_params iwl2000_base_params = {  	.num_of_queues = IWLAGN_NUM_QUEUES,  	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,  	.pll_cfg_val = 0, -	.set_l0s = true,  	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,  	.shadow_ram_support = true,  	.led_compensation = 51, @@ -359,9 +339,6 @@ static struct iwl_base_params iwl2000_base_params = {  	.chain_noise_scale = 1000,  	.wd_timeout = IWL_DEF_WD_TIMEOUT,  	.max_event_log_size = 512, -	.ucode_tracing = true, -	.sensitivity_calib_by_driver = true, -	.chain_noise_calib_by_driver = true,  	.shadow_reg_enable = true,  }; @@ -371,7 +348,6 @@ static struct iwl_base_params iwl2030_base_params = {  	.num_of_queues = IWLAGN_NUM_QUEUES,  	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,  	.pll_cfg_val = 0, -	.set_l0s = true,  	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,  	.shadow_ram_support = true,  	.led_compensation = 57, @@ -382,9 +358,6 @@ static struct iwl_base_params iwl2030_base_params = {  	.chain_noise_scale = 1000,  	.wd_timeout = IWL_LONG_WD_TIMEOUT,  	.max_event_log_size = 512, -	.ucode_tracing = true, -	.sensitivity_calib_by_driver = true, -	.chain_noise_calib_by_driver = true,  	.shadow_reg_enable = true,  }; @@ -394,7 +367,6 @@ static struct iwl_ht_params iwl2000_ht_params = {  };  static struct iwl_bt_params iwl2030_bt_params = { -	.bt_statistics = true,  	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */  	.advanced_bt_coexist = true,  	.agg_time_limit = BT_AGG_THRESHOLD_DEF, @@ -416,7 +388,8 @@ static struct iwl_bt_params iwl2030_bt_params = {  	.need_dc_calib = true,					\  	.need_temp_offset_calib = true,				\  	.led_mode = IWL_LED_RF_STATE,				\ -	.iq_invert = true					\ +	.iq_invert = true,					\ +	.disable_otp_refresh = true				\  struct iwl_cfg iwl2000_2bgn_cfg = {  	.name = "2000 Series 2x2 BGN", diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 66f5fe8fe1a..655afc19f68 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -45,7 +45,6 @@  #include "iwl-sta.h"  #include "iwl-helpers.h"  #include "iwl-agn.h" -#include "iwl-agn-led.h"  #include "iwl-agn-hw.h"  #include "iwl-5000-hw.h"  #include "iwl-agn-debugfs.h" @@ -59,12 +58,10 @@  #define IWL5150_UCODE_API_MIN 1  #define IWL5000_FW_PRE "iwlwifi-5000-" -#define _IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode" -#define IWL5000_MODULE_FIRMWARE(api) _IWL5000_MODULE_FIRMWARE(api) +#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode"  #define IWL5150_FW_PRE "iwlwifi-5150-" -#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" -#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) +#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"  /* NIC configuration for 5000 series */  static void iwl5000_nic_config(struct iwl_priv *priv) @@ -261,7 +258,7 @@ static void iwl5150_temperature(struct iwl_priv *priv)  	u32 vt = 0;  	s32 offset =  iwl_temp_calib_to_offset(priv); -	vt = le32_to_cpu(priv->_agn.statistics.general.common.temperature); +	vt = le32_to_cpu(priv->statistics.common.temperature);  	vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;  	/* now vt hold the temperature in Kelvin */  	priv->temperature = KELVIN_TO_CELSIUS(vt); @@ -352,10 +349,6 @@ static struct iwl_lib_ops iwl5000_lib = {  	.rx_handler_setup = iwlagn_rx_handler_setup,  	.setup_deferred_work = iwlagn_setup_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.dump_nic_event_log = iwl_dump_nic_event_log, -	.dump_nic_error_log = iwl_dump_nic_error_log, -	.dump_csr = iwl_dump_csr, -	.dump_fh = iwl_dump_fh,  	.send_tx_power = iwlagn_send_tx_power,  	.update_chain_flags = iwl_update_chain_flags,  	.set_channel_switch = iwl5000_hw_channel_switch, @@ -390,11 +383,6 @@ static struct iwl_lib_ops iwl5000_lib = {  	},  	.txfifo_flush = iwlagn_txfifo_flush,  	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, -	.tt_ops = { -		.lower_power_detection = iwl_tt_is_low_power_state, -		.tt_power_mode = iwl_tt_current_power_mode, -		.ct_kill_check = iwl_check_for_ct_kill, -	}  };  static struct iwl_lib_ops iwl5150_lib = { @@ -408,9 +396,6 @@ static struct iwl_lib_ops iwl5150_lib = {  	.rx_handler_setup = iwlagn_rx_handler_setup,  	.setup_deferred_work = iwlagn_setup_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.dump_nic_event_log = iwl_dump_nic_event_log, -	.dump_nic_error_log = iwl_dump_nic_error_log, -	.dump_csr = iwl_dump_csr,  	.send_tx_power = iwlagn_send_tx_power,  	.update_chain_flags = iwl_update_chain_flags,  	.set_channel_switch = iwl5000_hw_channel_switch, @@ -445,27 +430,18 @@ static struct iwl_lib_ops iwl5150_lib = {  	},  	.txfifo_flush = iwlagn_txfifo_flush,  	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, -	.tt_ops = { -		.lower_power_detection = iwl_tt_is_low_power_state, -		.tt_power_mode = iwl_tt_current_power_mode, -		.ct_kill_check = iwl_check_for_ct_kill, -	}  };  static const struct iwl_ops iwl5000_ops = {  	.lib = &iwl5000_lib,  	.hcmd = &iwlagn_hcmd,  	.utils = &iwlagn_hcmd_utils, -	.led = &iwlagn_led_ops, -	.ieee80211_ops = &iwlagn_hw_ops,  };  static const struct iwl_ops iwl5150_ops = {  	.lib = &iwl5150_lib,  	.hcmd = &iwlagn_hcmd,  	.utils = &iwlagn_hcmd_utils, -	.led = &iwlagn_led_ops, -	.ieee80211_ops = &iwlagn_hw_ops,  };  static struct iwl_base_params iwl5000_base_params = { @@ -473,16 +449,12 @@ static struct iwl_base_params iwl5000_base_params = {  	.num_of_queues = IWLAGN_NUM_QUEUES,  	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,  	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, -	.set_l0s = true,  	.led_compensation = 51,  	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,  	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,  	.chain_noise_scale = 1000,  	.wd_timeout = IWL_LONG_WD_TIMEOUT,  	.max_event_log_size = 512, -	.ucode_tracing = true, -	.sensitivity_calib_by_driver = true, -	.chain_noise_calib_by_driver = true,  };  static struct iwl_ht_params iwl5000_ht_params = {  	.ht_greenfield_support = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 24d105b29ae..905eb57f7ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -46,7 +46,6 @@  #include "iwl-helpers.h"  #include "iwl-agn-hw.h"  #include "iwl-6000-hw.h" -#include "iwl-agn-led.h"  #include "iwl-agn-debugfs.h"  /* Highest firmware API version supported */ @@ -60,20 +59,16 @@  #define IWL6000G2_UCODE_API_MIN 4  #define IWL6000_FW_PRE "iwlwifi-6000-" -#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" -#define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) +#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"  #define IWL6050_FW_PRE "iwlwifi-6050-" -#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" -#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) +#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"  #define IWL6005_FW_PRE "iwlwifi-6000g2a-" -#define _IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode" -#define IWL6005_MODULE_FIRMWARE(api) _IWL6005_MODULE_FIRMWARE(api) +#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode"  #define IWL6030_FW_PRE "iwlwifi-6000g2b-" -#define _IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode" -#define IWL6030_MODULE_FIRMWARE(api) _IWL6030_MODULE_FIRMWARE(api) +#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode"  static void iwl6000_set_ct_threshold(struct iwl_priv *priv)  { @@ -293,10 +288,6 @@ static struct iwl_lib_ops iwl6000_lib = {  	.rx_handler_setup = iwlagn_rx_handler_setup,  	.setup_deferred_work = iwlagn_setup_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.dump_nic_event_log = iwl_dump_nic_event_log, -	.dump_nic_error_log = iwl_dump_nic_error_log, -	.dump_csr = iwl_dump_csr, -	.dump_fh = iwl_dump_fh,  	.send_tx_power = iwlagn_send_tx_power,  	.update_chain_flags = iwl_update_chain_flags,  	.set_channel_switch = iwl6000_hw_channel_switch, @@ -332,11 +323,6 @@ static struct iwl_lib_ops iwl6000_lib = {  	},  	.txfifo_flush = iwlagn_txfifo_flush,  	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, -	.tt_ops = { -		.lower_power_detection = iwl_tt_is_low_power_state, -		.tt_power_mode = iwl_tt_current_power_mode, -		.ct_kill_check = iwl_check_for_ct_kill, -	}  };  static struct iwl_lib_ops iwl6030_lib = { @@ -351,10 +337,6 @@ static struct iwl_lib_ops iwl6030_lib = {  	.setup_deferred_work = iwlagn_bt_setup_deferred_work,  	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.dump_nic_event_log = iwl_dump_nic_event_log, -	.dump_nic_error_log = iwl_dump_nic_error_log, -	.dump_csr = iwl_dump_csr, -	.dump_fh = iwl_dump_fh,  	.send_tx_power = iwlagn_send_tx_power,  	.update_chain_flags = iwl_update_chain_flags,  	.set_channel_switch = iwl6000_hw_channel_switch, @@ -390,11 +372,6 @@ static struct iwl_lib_ops iwl6030_lib = {  	},  	.txfifo_flush = iwlagn_txfifo_flush,  	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, -	.tt_ops = { -		.lower_power_detection = iwl_tt_is_low_power_state, -		.tt_power_mode = iwl_tt_current_power_mode, -		.ct_kill_check = iwl_check_for_ct_kill, -	}  };  static struct iwl_nic_ops iwl6050_nic_ops = { @@ -409,34 +386,26 @@ static const struct iwl_ops iwl6000_ops = {  	.lib = &iwl6000_lib,  	.hcmd = &iwlagn_hcmd,  	.utils = &iwlagn_hcmd_utils, -	.led = &iwlagn_led_ops, -	.ieee80211_ops = &iwlagn_hw_ops,  };  static const struct iwl_ops iwl6050_ops = {  	.lib = &iwl6000_lib,  	.hcmd = &iwlagn_hcmd,  	.utils = &iwlagn_hcmd_utils, -	.led = &iwlagn_led_ops,  	.nic = &iwl6050_nic_ops, -	.ieee80211_ops = &iwlagn_hw_ops,  };  static const struct iwl_ops iwl6150_ops = {  	.lib = &iwl6000_lib,  	.hcmd = &iwlagn_hcmd,  	.utils = &iwlagn_hcmd_utils, -	.led = &iwlagn_led_ops,  	.nic = &iwl6150_nic_ops, -	.ieee80211_ops = &iwlagn_hw_ops,  };  static const struct iwl_ops iwl6030_ops = {  	.lib = &iwl6030_lib,  	.hcmd = &iwlagn_bt_hcmd,  	.utils = &iwlagn_hcmd_utils, -	.led = &iwlagn_led_ops, -	.ieee80211_ops = &iwlagn_hw_ops,  };  static struct iwl_base_params iwl6000_base_params = { @@ -444,7 +413,6 @@ static struct iwl_base_params iwl6000_base_params = {  	.num_of_queues = IWLAGN_NUM_QUEUES,  	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,  	.pll_cfg_val = 0, -	.set_l0s = true,  	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,  	.shadow_ram_support = true,  	.led_compensation = 51, @@ -455,9 +423,6 @@ static struct iwl_base_params iwl6000_base_params = {  	.chain_noise_scale = 1000,  	.wd_timeout = IWL_DEF_WD_TIMEOUT,  	.max_event_log_size = 512, -	.ucode_tracing = true, -	.sensitivity_calib_by_driver = true, -	.chain_noise_calib_by_driver = true,  	.shadow_reg_enable = true,  }; @@ -466,7 +431,6 @@ static struct iwl_base_params iwl6050_base_params = {  	.num_of_queues = IWLAGN_NUM_QUEUES,  	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,  	.pll_cfg_val = 0, -	.set_l0s = true,  	.max_ll_items = OTP_MAX_LL_ITEMS_6x50,  	.shadow_ram_support = true,  	.led_compensation = 51, @@ -477,9 +441,6 @@ static struct iwl_base_params iwl6050_base_params = {  	.chain_noise_scale = 1500,  	.wd_timeout = IWL_DEF_WD_TIMEOUT,  	.max_event_log_size = 1024, -	.ucode_tracing = true, -	.sensitivity_calib_by_driver = true, -	.chain_noise_calib_by_driver = true,  	.shadow_reg_enable = true,  };  static struct iwl_base_params iwl6000_g2_base_params = { @@ -487,7 +448,6 @@ static struct iwl_base_params iwl6000_g2_base_params = {  	.num_of_queues = IWLAGN_NUM_QUEUES,  	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,  	.pll_cfg_val = 0, -	.set_l0s = true,  	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,  	.shadow_ram_support = true,  	.led_compensation = 57, @@ -498,9 +458,6 @@ static struct iwl_base_params iwl6000_g2_base_params = {  	.chain_noise_scale = 1000,  	.wd_timeout = IWL_LONG_WD_TIMEOUT,  	.max_event_log_size = 512, -	.ucode_tracing = true, -	.sensitivity_calib_by_driver = true, -	.chain_noise_calib_by_driver = true,  	.shadow_reg_enable = true,  }; @@ -510,7 +467,6 @@ static struct iwl_ht_params iwl6000_ht_params = {  };  static struct iwl_bt_params iwl6000_bt_params = { -	.bt_statistics = true,  	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */  	.advanced_bt_coexist = true,  	.agg_time_limit = BT_AGG_THRESHOLD_DEF, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 7b761de77b0..0f6bb9b2e64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -605,7 +605,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)  	IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);  } -void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp) +void iwl_sensitivity_calibration(struct iwl_priv *priv)  {  	u32 rx_enable_time;  	u32 fa_cck; @@ -631,16 +631,9 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp)  	}  	spin_lock_irqsave(&priv->lock, flags); -	if (iwl_bt_statistics(priv)) { -		rx_info = &(((struct iwl_bt_notif_statistics *)resp)-> -			      rx.general.common); -		ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm); -		cck = &(((struct iwl_bt_notif_statistics *)resp)->rx.cck); -	} else { -		rx_info = &(((struct iwl_notif_statistics *)resp)->rx.general); -		ofdm = &(((struct iwl_notif_statistics *)resp)->rx.ofdm); -		cck = &(((struct iwl_notif_statistics *)resp)->rx.cck); -	} +	rx_info = &priv->statistics.rx_non_phy; +	ofdm = &priv->statistics.rx_ofdm; +	cck = &priv->statistics.rx_cck;  	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {  		IWL_DEBUG_CALIB(priv, "<< invalid data.\n");  		spin_unlock_irqrestore(&priv->lock, flags); @@ -851,7 +844,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,   * 1)  Which antennas are connected.   * 2)  Differential rx gain settings to balance the 3 receivers.   */ -void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) +void iwl_chain_noise_calibration(struct iwl_priv *priv)  {  	struct iwl_chain_noise_data *data = NULL; @@ -896,13 +889,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)  	}  	spin_lock_irqsave(&priv->lock, flags); -	if (iwl_bt_statistics(priv)) { -		rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)-> -			      rx.general.common); -	} else { -		rx_info = &(((struct iwl_notif_statistics *)stat_resp)-> -			      rx.general); -	} + +	rx_info = &priv->statistics.rx_non_phy; +  	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {  		IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");  		spin_unlock_irqrestore(&priv->lock, flags); @@ -911,19 +900,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)  	rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);  	rxon_chnum = le16_to_cpu(ctx->staging.channel); -	if (iwl_bt_statistics(priv)) { -		stat_band24 = !!(((struct iwl_bt_notif_statistics *) -				 stat_resp)->flag & -				 STATISTICS_REPLY_FLG_BAND_24G_MSK); -		stat_chnum = le32_to_cpu(((struct iwl_bt_notif_statistics *) -					 stat_resp)->flag) >> 16; -	} else { -		stat_band24 = !!(((struct iwl_notif_statistics *) -				 stat_resp)->flag & -				 STATISTICS_REPLY_FLG_BAND_24G_MSK); -		stat_chnum = le32_to_cpu(((struct iwl_notif_statistics *) -					 stat_resp)->flag) >> 16; -	} +	stat_band24 = +		!!(priv->statistics.flag & STATISTICS_REPLY_FLG_BAND_24G_MSK); +	stat_chnum = le32_to_cpu(priv->statistics.flag) >> 16;  	/* Make sure we accumulate data for just the associated channel  	 *   (even if scanning). */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h index ef4d5079a7e..4ef4dd93425 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h @@ -66,8 +66,8 @@  #include "iwl-core.h"  #include "iwl-commands.h" -void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp); -void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp); +void iwl_chain_noise_calibration(struct iwl_priv *priv); +void iwl_sensitivity_calibration(struct iwl_priv *priv);  void iwl_init_sensitivity(struct iwl_priv *priv);  void iwl_reset_run_time_calib(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index d1834aa7edf..71a5f31cd7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -39,10 +39,7 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)  	int p = 0;  	u32 flag; -	if (iwl_bt_statistics(priv)) -		flag = le32_to_cpu(priv->_agn.statistics_bt.flag); -	else -		flag = le32_to_cpu(priv->_agn.statistics.flag); +	flag = le32_to_cpu(priv->statistics.flag);  	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);  	if (flag & UCODE_STATISTICS_CLEAR_MSK) @@ -88,43 +85,22 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,  	 * the last statistics notification from uCode  	 * might not reflect the current uCode activity  	 */ -	if (iwl_bt_statistics(priv)) { -		ofdm = &priv->_agn.statistics_bt.rx.ofdm; -		cck = &priv->_agn.statistics_bt.rx.cck; -		general = &priv->_agn.statistics_bt.rx.general.common; -		ht = &priv->_agn.statistics_bt.rx.ofdm_ht; -		accum_ofdm = &priv->_agn.accum_statistics_bt.rx.ofdm; -		accum_cck = &priv->_agn.accum_statistics_bt.rx.cck; -		accum_general = -			&priv->_agn.accum_statistics_bt.rx.general.common; -		accum_ht = &priv->_agn.accum_statistics_bt.rx.ofdm_ht; -		delta_ofdm = &priv->_agn.delta_statistics_bt.rx.ofdm; -		delta_cck = &priv->_agn.delta_statistics_bt.rx.cck; -		delta_general = -			&priv->_agn.delta_statistics_bt.rx.general.common; -		delta_ht = &priv->_agn.delta_statistics_bt.rx.ofdm_ht; -		max_ofdm = &priv->_agn.max_delta_bt.rx.ofdm; -		max_cck = &priv->_agn.max_delta_bt.rx.cck; -		max_general = &priv->_agn.max_delta_bt.rx.general.common; -		max_ht = &priv->_agn.max_delta_bt.rx.ofdm_ht; -	} else { -		ofdm = &priv->_agn.statistics.rx.ofdm; -		cck = &priv->_agn.statistics.rx.cck; -		general = &priv->_agn.statistics.rx.general; -		ht = &priv->_agn.statistics.rx.ofdm_ht; -		accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm; -		accum_cck = &priv->_agn.accum_statistics.rx.cck; -		accum_general = &priv->_agn.accum_statistics.rx.general; -		accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht; -		delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm; -		delta_cck = &priv->_agn.delta_statistics.rx.cck; -		delta_general = &priv->_agn.delta_statistics.rx.general; -		delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht; -		max_ofdm = &priv->_agn.max_delta.rx.ofdm; -		max_cck = &priv->_agn.max_delta.rx.cck; -		max_general = &priv->_agn.max_delta.rx.general; -		max_ht = &priv->_agn.max_delta.rx.ofdm_ht; -	} +	ofdm = &priv->statistics.rx_ofdm; +	cck = &priv->statistics.rx_cck; +	general = &priv->statistics.rx_non_phy; +	ht = &priv->statistics.rx_ofdm_ht; +	accum_ofdm = &priv->accum_stats.rx_ofdm; +	accum_cck = &priv->accum_stats.rx_cck; +	accum_general = &priv->accum_stats.rx_non_phy; +	accum_ht = &priv->accum_stats.rx_ofdm_ht; +	delta_ofdm = &priv->delta_stats.rx_ofdm; +	delta_cck = &priv->delta_stats.rx_cck; +	delta_general = &priv->delta_stats.rx_non_phy; +	delta_ht = &priv->delta_stats.rx_ofdm_ht; +	max_ofdm = &priv->max_delta_stats.rx_ofdm; +	max_cck = &priv->max_delta_stats.rx_cck; +	max_general = &priv->max_delta_stats.rx_non_phy; +	max_ht = &priv->max_delta_stats.rx_ofdm_ht;  	pos += iwl_statistics_flag(priv, buf, bufsz);  	pos += scnprintf(buf + pos, bufsz - pos, @@ -531,20 +507,13 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,  	}  	/* the statistic information display here is based on -	  * the last statistics notification from uCode -	  * might not reflect the current uCode activity -	  */ -	if (iwl_bt_statistics(priv)) { -		tx = &priv->_agn.statistics_bt.tx; -		accum_tx = &priv->_agn.accum_statistics_bt.tx; -		delta_tx = &priv->_agn.delta_statistics_bt.tx; -		max_tx = &priv->_agn.max_delta_bt.tx; -	} else { -		tx = &priv->_agn.statistics.tx; -		accum_tx = &priv->_agn.accum_statistics.tx; -		delta_tx = &priv->_agn.delta_statistics.tx; -		max_tx = &priv->_agn.max_delta.tx; -	} +	 * the last statistics notification from uCode +	 * might not reflect the current uCode activity +	 */ +	tx = &priv->statistics.tx; +	accum_tx = &priv->accum_stats.tx; +	delta_tx = &priv->delta_stats.tx; +	max_tx = &priv->max_delta_stats.tx;  	pos += iwl_statistics_flag(priv, buf, bufsz);  	pos += scnprintf(buf + pos, bufsz - pos, @@ -731,36 +700,21 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,  	}  	/* the statistic information display here is based on -	  * the last statistics notification from uCode -	  * might not reflect the current uCode activity -	  */ -	if (iwl_bt_statistics(priv)) { -		general = &priv->_agn.statistics_bt.general.common; -		dbg = &priv->_agn.statistics_bt.general.common.dbg; -		div = &priv->_agn.statistics_bt.general.common.div; -		accum_general = &priv->_agn.accum_statistics_bt.general.common; -		accum_dbg = &priv->_agn.accum_statistics_bt.general.common.dbg; -		accum_div = &priv->_agn.accum_statistics_bt.general.common.div; -		delta_general = &priv->_agn.delta_statistics_bt.general.common; -		max_general = &priv->_agn.max_delta_bt.general.common; -		delta_dbg = &priv->_agn.delta_statistics_bt.general.common.dbg; -		max_dbg = &priv->_agn.max_delta_bt.general.common.dbg; -		delta_div = &priv->_agn.delta_statistics_bt.general.common.div; -		max_div = &priv->_agn.max_delta_bt.general.common.div; -	} else { -		general = &priv->_agn.statistics.general.common; -		dbg = &priv->_agn.statistics.general.common.dbg; -		div = &priv->_agn.statistics.general.common.div; -		accum_general = &priv->_agn.accum_statistics.general.common; -		accum_dbg = &priv->_agn.accum_statistics.general.common.dbg; -		accum_div = &priv->_agn.accum_statistics.general.common.div; -		delta_general = &priv->_agn.delta_statistics.general.common; -		max_general = &priv->_agn.max_delta.general.common; -		delta_dbg = &priv->_agn.delta_statistics.general.common.dbg; -		max_dbg = &priv->_agn.max_delta.general.common.dbg; -		delta_div = &priv->_agn.delta_statistics.general.common.div; -		max_div = &priv->_agn.max_delta.general.common.div; -	} +	 * the last statistics notification from uCode +	 * might not reflect the current uCode activity +	 */ +	general = &priv->statistics.common; +	dbg = &priv->statistics.common.dbg; +	div = &priv->statistics.common.div; +	accum_general = &priv->accum_stats.common; +	accum_dbg = &priv->accum_stats.common.dbg; +	accum_div = &priv->accum_stats.common.div; +	delta_general = &priv->delta_stats.common; +	max_general = &priv->max_delta_stats.common; +	delta_dbg = &priv->delta_stats.common.dbg; +	max_dbg = &priv->max_delta_stats.common.dbg; +	delta_div = &priv->delta_stats.common.div; +	max_div = &priv->max_delta_stats.common.div;  	pos += iwl_statistics_flag(priv, buf, bufsz);  	pos += scnprintf(buf + pos, bufsz - pos, @@ -876,8 +830,8 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file,  	 * the last statistics notification from uCode  	 * might not reflect the current uCode activity  	 */ -	bt = &priv->_agn.statistics_bt.general.activity; -	accum_bt = &priv->_agn.accum_statistics_bt.general.activity; +	bt = &priv->statistics.bt_activity; +	accum_bt = &priv->accum_stats.bt_activity;  	pos += iwl_statistics_flag(priv, buf, bufsz);  	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n"); @@ -918,10 +872,8 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file,  	pos += scnprintf(buf + pos, bufsz - pos,  			 "(rx)num_bt_kills:\t\t%u\t\t\t%u\n", -			 le32_to_cpu(priv->_agn.statistics_bt.rx. -				general.num_bt_kills), -			 priv->_agn.accum_statistics_bt.rx. -				general.num_bt_kills); +			 le32_to_cpu(priv->statistics.num_bt_kills), +			 priv->statistics.accum_num_bt_kills);  	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);  	kfree(buf); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/drivers/net/wireless/iwlwifi/iwl-agn-led.c deleted file mode 100644 index 4bb877e600c..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-led.c +++ /dev/null @@ -1,73 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - *  Intel Linux Wireless <ilw@linux.intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/delay.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/wireless.h> -#include <net/mac80211.h> -#include <linux/etherdevice.h> -#include <asm/unaligned.h> - -#include "iwl-commands.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-agn-led.h" - -/* Send led command */ -static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) -{ -	struct iwl_host_cmd cmd = { -		.id = REPLY_LEDS_CMD, -		.len = sizeof(struct iwl_led_cmd), -		.data = led_cmd, -		.flags = CMD_ASYNC, -		.callback = NULL, -	}; -	u32 reg; - -	reg = iwl_read32(priv, CSR_LED_REG); -	if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) -		iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); - -	return iwl_send_cmd(priv, &cmd); -} - -/* Set led register off */ -void iwlagn_led_enable(struct iwl_priv *priv) -{ -	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); -} - -const struct iwl_led_ops iwlagn_led_ops = { -	.cmd = iwl_send_led_cmd, -}; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/drivers/net/wireless/iwlwifi/iwl-agn-led.h deleted file mode 100644 index c0b7611b72c..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-led.h +++ /dev/null @@ -1,33 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - *  Intel Linux Wireless <ilw@linux.intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl_agn_led_h__ -#define __iwl_agn_led_h__ - -extern const struct iwl_led_ops iwlagn_led_ops; -void iwlagn_led_enable(struct iwl_priv *priv); - -#endif /* __iwl_agn_led_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 9e47be6a739..e741128842b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -172,6 +172,7 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status)  static void iwlagn_set_tx_status(struct iwl_priv *priv,  				 struct ieee80211_tx_info *info, +				 struct iwl_rxon_context *ctx,  				 struct iwlagn_tx_resp *tx_resp,  				 int txq_id, bool is_agg)  { @@ -186,6 +187,13 @@ static void iwlagn_set_tx_status(struct iwl_priv *priv,  	if (!iwl_is_tx_success(status))  		iwlagn_count_tx_err_status(priv, status); +	if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && +	    iwl_is_associated_ctx(ctx) && ctx->vif && +	    ctx->vif->type == NL80211_IFTYPE_STATION) { +		ctx->last_tx_rejected = true; +		iwl_stop_queue(priv, &priv->txq[txq_id]); +	} +  	IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags "  			   "0x%x retries %d\n",  			   txq_id, @@ -242,15 +250,16 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,  	/* # frames attempted by Tx command */  	if (agg->frame_count == 1) { +		struct iwl_tx_info *txb; +  		/* Only one frame was attempted; no block-ack will arrive */  		idx = start_idx;  		IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",  				   agg->frame_count, agg->start_idx, idx); -		iwlagn_set_tx_status(priv, -				     IEEE80211_SKB_CB( -					priv->txq[txq_id].txb[idx].skb), -				     tx_resp, txq_id, true); +		txb = &priv->txq[txq_id].txb[idx]; +		iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(txb->skb), +				     txb->ctx, tx_resp, txq_id, true);  		agg->wait_for_ba = 0;  	} else {  		/* Two or more frames were attempted; expect block-ack */ @@ -391,7 +400,8 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,  	struct iwl_tx_queue *txq = &priv->txq[txq_id];  	struct ieee80211_tx_info *info;  	struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; -	u32  status = le16_to_cpu(tx_resp->status.status); +	struct iwl_tx_info *txb; +	u32 status = le16_to_cpu(tx_resp->status.status);  	int tid;  	int sta_id;  	int freed; @@ -406,7 +416,8 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,  	}  	txq->time_stamp = jiffies; -	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); +	txb = &txq->txb[txq->q.read_ptr]; +	info = IEEE80211_SKB_CB(txb->skb);  	memset(&info->status, 0, sizeof(info->status));  	tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> @@ -450,12 +461,14 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,  				iwl_wake_queue(priv, txq);  		}  	} else { -		iwlagn_set_tx_status(priv, info, tx_resp, txq_id, false); +		iwlagn_set_tx_status(priv, info, txb->ctx, tx_resp, +				     txq_id, false);  		freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);  		iwl_free_tfds_in_queue(priv, sta_id, tid, freed);  		if (priv->mac80211_registered && -		    (iwl_queue_space(&txq->q) > txq->q.low_mark)) +		    iwl_queue_space(&txq->q) > txq->q.low_mark && +		    status != TX_STATUS_FAIL_PASSIVE_NO_RX)  			iwl_wake_queue(priv, txq);  	} @@ -482,8 +495,10 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv)  void iwlagn_setup_deferred_work(struct iwl_priv *priv)  { -	/* in agn, the tx power calibration is done in uCode */ -	priv->disable_tx_power_cal = 1; +	/* +	 * nothing need to be done here anymore +	 * still keep for future use if needed +	 */  }  int iwlagn_hw_valid_rtc_data_addr(u32 addr) @@ -534,9 +549,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)  void iwlagn_temperature(struct iwl_priv *priv)  {  	/* store temperature from correct statistics (in Celsius) */ -	priv->temperature = le32_to_cpu((iwl_bt_statistics(priv)) ? -		priv->_agn.statistics_bt.general.common.temperature : -		priv->_agn.statistics.general.common.temperature); +	priv->temperature = le32_to_cpu(priv->statistics.common.temperature);  	iwl_tt_handler(priv);  } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 69a29932bab..bdae82e7fa9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -83,7 +83,6 @@ enum {  enum {  	IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, -	IWL39_LAST_OFDM_RATE = IWL_RATE_54M_INDEX,  	IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX,  	IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,  	IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index c335ee6883e..56f46ee3bac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -29,6 +29,7 @@  #include "iwl-sta.h"  #include "iwl-core.h"  #include "iwl-agn-calib.h" +#include "iwl-helpers.h"  static int iwlagn_disable_bss(struct iwl_priv *priv,  			      struct iwl_rxon_context *ctx, @@ -600,6 +601,18 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,  			priv->timestamp = bss_conf->timestamp;  			ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;  		} else { +			/* +			 * If we disassociate while there are pending +			 * frames, just wake up the queues and let the +			 * frames "escape" ... This shouldn't really +			 * be happening to start with, but we should +			 * not get stuck in this case either since it +			 * can happen if userspace gets confused. +			 */ +			if (ctx->last_tx_rejected) { +				ctx->last_tx_rejected = false; +				iwl_wake_any_queue(priv, ctx); +			}  			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;  		}  	} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 01a6d2fc795..5c30f6b19a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -428,6 +428,7 @@ void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)  int iwlagn_alive_notify(struct iwl_priv *priv)  {  	const struct queue_to_fifo_ac *queue_to_fifo; +	struct iwl_rxon_context *ctx;  	u32 a;  	unsigned long flags;  	int i, chan; @@ -501,6 +502,8 @@ int iwlagn_alive_notify(struct iwl_priv *priv)  	memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));  	for (i = 0; i < 4; i++)  		atomic_set(&priv->queue_stop_count[i], 0); +	for_each_context(priv, ctx) +		ctx->last_tx_rejected = false;  	/* reset to 0 to enable all the queue first */  	priv->txq_ctx_active_msk = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 60bfde75ce8..cdeb09eee73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -59,7 +59,6 @@  #include "iwl-sta.h"  #include "iwl-agn-calib.h"  #include "iwl-agn.h" -#include "iwl-agn-led.h"  /****************************************************************************** @@ -254,6 +253,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)  	struct iwl_frame *frame;  	unsigned int frame_size;  	int rc; +	struct iwl_host_cmd cmd = { +		.id = REPLY_TX_BEACON, +		.flags = CMD_SIZE_HUGE, +	};  	frame = iwl_get_free_frame(priv);  	if (!frame) { @@ -269,8 +272,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)  		return -EINVAL;  	} -	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, -			      &frame->u.cmd[0]); +	cmd.len = frame_size; +	cmd.data = &frame->u.cmd[0]; + +	rc = iwl_send_cmd_sync(priv, &cmd);  	iwl_free_frame(priv, frame); @@ -395,7 +400,9 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,  		return -EINVAL;  	} -	BUG_ON(addr & ~DMA_BIT_MASK(36)); +	if (WARN_ON(addr & ~DMA_BIT_MASK(36))) +		return -EINVAL; +  	if (unlikely(addr & ~IWL_TX_DMA_MASK))  		IWL_ERR(priv, "Unaligned address = %llx\n",  			  (unsigned long long)addr); @@ -719,7 +726,10 @@ static void iwl_rx_handle(struct iwl_priv *priv)  		/* If an RXB doesn't have a Rx queue slot associated with it,  		 * then a bug has been introduced in the queue refilling  		 * routines -- catch it here */ -		BUG_ON(rxb == NULL); +		if (WARN_ON(rxb == NULL)) { +			i = (i + 1) & RX_QUEUE_MASK; +			continue; +		}  		rxq->queue[i] = NULL; @@ -1481,7 +1491,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,  					le32_to_cpup((__le32 *)tlv_data);  			break;  		default: -			IWL_WARN(priv, "unknown TLV: %d\n", tlv_type); +			IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type);  			break;  		}  	} @@ -1705,10 +1715,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)  	else  		priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; -	if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BTSTATS || -	    (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics)) -		priv->bt_statistics = true; -  	/* Copy images into buffers for card's bus-master reads ... */  	/* Runtime instructions (first block of data in file) */ @@ -2626,17 +2632,8 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)  	}  	if (priv->start_calib) { -		if (iwl_bt_statistics(priv)) { -			iwl_chain_noise_calibration(priv, -					(void *)&priv->_agn.statistics_bt); -			iwl_sensitivity_calibration(priv, -					(void *)&priv->_agn.statistics_bt); -		} else { -			iwl_chain_noise_calibration(priv, -					(void *)&priv->_agn.statistics); -			iwl_sensitivity_calibration(priv, -					(void *)&priv->_agn.statistics); -		} +		iwl_chain_noise_calibration(priv); +		iwl_sensitivity_calibration(priv);  	}  	mutex_unlock(&priv->mutex); @@ -2828,9 +2825,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,  	hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; -	if (!priv->cfg->base_params->broken_powersave) -		hw->flags |= IEEE80211_HW_SUPPORTS_PS | -			     IEEE80211_HW_SUPPORTS_DYNAMIC_PS; +	hw->flags |= IEEE80211_HW_SUPPORTS_PS | +		     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;  	if (priv->cfg->sku & IWL_SKU_N)  		hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | @@ -3732,6 +3728,28 @@ static const u8 iwlagn_pan_ac_to_queue[] = {  	7, 6, 5, 4,  }; +/* This function both allocates and initializes hw and priv. */ +static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) +{ +	struct iwl_priv *priv; +	/* mac80211 allocates memory for this device instance, including +	 *   space for this driver's private structure */ +	struct ieee80211_hw *hw; + +	hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwlagn_hw_ops); +	if (hw == NULL) { +		pr_err("%s: Can not allocate network device\n", +		       cfg->name); +		goto out; +	} + +	priv = hw->priv; +	priv->hw = hw; + +out: +	return hw; +} +  static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  {  	int err = 0, i; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 016b79e4421..078a23e5d99 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -173,8 +173,6 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv);  int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);  int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);  void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); -void iwl_dump_csr(struct iwl_priv *priv); -int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);  /* rx */  void iwlagn_rx_queue_restock(struct iwl_priv *priv); @@ -222,6 +220,7 @@ static inline u32 iwl_tx_status_to_mac80211(u32 status)  	case TX_STATUS_DIRECT_DONE:  		return IEEE80211_TX_STAT_ACK;  	case TX_STATUS_FAIL_DEST_PS: +	case TX_STATUS_FAIL_PASSIVE_NO_RX:  		return IEEE80211_TX_STAT_TX_FILTERED;  	default:  		return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index a1a5c1b2309..0edba8a6419 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2535,53 +2535,6 @@ struct rate_histogram {  /* statistics command response */ -struct iwl39_statistics_rx_phy { -	__le32 ina_cnt; -	__le32 fina_cnt; -	__le32 plcp_err; -	__le32 crc32_err; -	__le32 overrun_err; -	__le32 early_overrun_err; -	__le32 crc32_good; -	__le32 false_alarm_cnt; -	__le32 fina_sync_err_cnt; -	__le32 sfd_timeout; -	__le32 fina_timeout; -	__le32 unresponded_rts; -	__le32 rxe_frame_limit_overrun; -	__le32 sent_ack_cnt; -	__le32 sent_cts_cnt; -} __packed; - -struct iwl39_statistics_rx_non_phy { -	__le32 bogus_cts;	/* CTS received when not expecting CTS */ -	__le32 bogus_ack;	/* ACK received when not expecting ACK */ -	__le32 non_bssid_frames;	/* number of frames with BSSID that -					 * doesn't belong to the STA BSSID */ -	__le32 filtered_frames;	/* count frames that were dumped in the -				 * filtering process */ -	__le32 non_channel_beacons;	/* beacons with our bss id but not on -					 * our serving channel */ -} __packed; - -struct iwl39_statistics_rx { -	struct iwl39_statistics_rx_phy ofdm; -	struct iwl39_statistics_rx_phy cck; -	struct iwl39_statistics_rx_non_phy general; -} __packed; - -struct iwl39_statistics_tx { -	__le32 preamble_cnt; -	__le32 rx_detected_cnt; -	__le32 bt_prio_defer_cnt; -	__le32 bt_prio_kill_cnt; -	__le32 few_bytes_cnt; -	__le32 cts_timeout; -	__le32 ack_timeout; -	__le32 expected_ack_cnt; -	__le32 actual_ack_cnt; -} __packed; -  struct statistics_dbg {  	__le32 burst_check;  	__le32 burst_count; @@ -2589,23 +2542,6 @@ struct statistics_dbg {  	__le32 reserved[3];  } __packed; -struct iwl39_statistics_div { -	__le32 tx_on_a; -	__le32 tx_on_b; -	__le32 exec_time; -	__le32 probe_time; -} __packed; - -struct iwl39_statistics_general { -	__le32 temperature; -	struct statistics_dbg dbg; -	__le32 sleep_time; -	__le32 slots_out; -	__le32 slots_idle; -	__le32 ttl_timestamp; -	struct iwl39_statistics_div div; -} __packed; -  struct statistics_rx_phy {  	__le32 ina_cnt;  	__le32 fina_cnt; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 45ec5cfe3fc..885167f8168 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -67,30 +67,6 @@ u32 iwl_debug_level;  const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - -/* This function both allocates and initializes hw and priv. */ -struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) -{ -	struct iwl_priv *priv; -	/* mac80211 allocates memory for this device instance, including -	 *   space for this driver's private structure */ -	struct ieee80211_hw *hw; - -	hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), -				cfg->ops->ieee80211_ops); -	if (hw == NULL) { -		pr_err("%s: Can not allocate network device\n", -		       cfg->name); -		goto out; -	} - -	priv = hw->priv; -	priv->hw = hw; - -out: -	return hw; -} -  #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */  #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */  static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, @@ -965,12 +941,10 @@ void iwl_irq_handle_error(struct iwl_priv *priv)  	IWL_ERR(priv, "Loaded firmware version: %s\n",  		priv->hw->wiphy->fw_version); -	priv->cfg->ops->lib->dump_nic_error_log(priv); -	if (priv->cfg->ops->lib->dump_csr) -		priv->cfg->ops->lib->dump_csr(priv); -	if (priv->cfg->ops->lib->dump_fh) -		priv->cfg->ops->lib->dump_fh(priv, NULL, false); -	priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); +	iwl_dump_nic_error_log(priv); +	iwl_dump_csr(priv); +	iwl_dump_fh(priv, NULL, false); +	iwl_dump_nic_event_log(priv, false, NULL, false);  #ifdef CONFIG_IWLWIFI_DEBUG  	if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)  		iwl_print_rx_config_cmd(priv, @@ -1051,7 +1025,6 @@ int iwl_apm_init(struct iwl_priv *priv)  	/*  	 * Enable HAP INTA (interrupt from management bus) to  	 * wake device's PCI Express link L1a -> L0s -	 * NOTE:  This is no-op for 3945 (non-existent bit)  	 */  	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,  				    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); @@ -1064,20 +1037,18 @@ int iwl_apm_init(struct iwl_priv *priv)  	 * If not (unlikely), enable L0S, so there is at least some  	 *    power savings, even without L1.  	 */ -	if (priv->cfg->base_params->set_l0s) { -		lctl = iwl_pcie_link_ctl(priv); -		if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == -					PCI_CFG_LINK_CTRL_VAL_L1_EN) { -			/* L1-ASPM enabled; disable(!) L0S  */ -			iwl_set_bit(priv, CSR_GIO_REG, -					CSR_GIO_REG_VAL_L0S_ENABLED); -			IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n"); -		} else { -			/* L1-ASPM disabled; enable(!) L0S */ -			iwl_clear_bit(priv, CSR_GIO_REG, -					CSR_GIO_REG_VAL_L0S_ENABLED); -			IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n"); -		} +	lctl = iwl_pcie_link_ctl(priv); +	if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == +				PCI_CFG_LINK_CTRL_VAL_L1_EN) { +		/* L1-ASPM enabled; disable(!) L0S  */ +		iwl_set_bit(priv, CSR_GIO_REG, +				CSR_GIO_REG_VAL_L0S_ENABLED); +		IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n"); +	} else { +		/* L1-ASPM disabled; enable(!) L0S */ +		iwl_clear_bit(priv, CSR_GIO_REG, +				CSR_GIO_REG_VAL_L0S_ENABLED); +		IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");  	}  	/* Configure analog phase-lock-loop before activating to D0A */ @@ -1777,6 +1748,15 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	mutex_lock(&priv->mutex); +	if (!ctx->vif || !iwl_is_ready_rf(priv)) { +		/* +		 * Huh? But wait ... this can maybe happen when +		 * we're in the middle of a firmware restart! +		 */ +		err = -EBUSY; +		goto out; +	} +  	interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;  	if (!(interface_modes & BIT(newtype))) { @@ -1804,6 +1784,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	/* success */  	iwl_teardown_interface(priv, vif, true);  	vif->type = newtype; +	vif->p2p = newp2p;  	err = iwl_setup_interface(priv, ctx);  	WARN_ON(err);  	/* diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 82939f851eb..32a990ff09a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -139,12 +139,6 @@ struct iwl_temp_ops {  	void (*temperature)(struct iwl_priv *priv);  }; -struct iwl_tt_ops { -	bool (*lower_power_detection)(struct iwl_priv *priv); -	u8 (*tt_power_mode)(struct iwl_priv *priv); -	bool (*ct_kill_check)(struct iwl_priv *priv); -}; -  struct iwl_lib_ops {  	/* set hw dependent parameters */  	int (*set_hw_params)(struct iwl_priv *priv); @@ -171,12 +165,6 @@ struct iwl_lib_ops {  	void (*cancel_deferred_work)(struct iwl_priv *priv);  	/* check validity of rtc data address */  	int (*is_valid_rtc_data_addr)(u32 addr); - -	int (*dump_nic_event_log)(struct iwl_priv *priv, -				  bool full_log, char **buf, bool display); -	void (*dump_nic_error_log)(struct iwl_priv *priv); -	void (*dump_csr)(struct iwl_priv *priv); -	int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);  	int (*set_channel_switch)(struct iwl_priv *priv,  				  struct ieee80211_channel_switch *ch_switch);  	/* power management */ @@ -196,13 +184,6 @@ struct iwl_lib_ops {  	void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);  	struct iwl_debugfs_ops debugfs_ops; - -	/* thermal throttling */ -	struct iwl_tt_ops tt_ops; -}; - -struct iwl_led_ops { -	int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd);  };  /* NIC specific ops */ @@ -210,23 +191,11 @@ struct iwl_nic_ops {  	void (*additional_nic_config)(struct iwl_priv *priv);  }; -struct iwl_legacy_ops { -	void (*post_associate)(struct iwl_priv *priv); -	void (*config_ap)(struct iwl_priv *priv); -	/* station management */ -	int (*update_bcast_stations)(struct iwl_priv *priv); -	int (*manage_ibss_station)(struct iwl_priv *priv, -				   struct ieee80211_vif *vif, bool add); -}; -  struct iwl_ops {  	const struct iwl_lib_ops *lib;  	const struct iwl_hcmd_ops *hcmd;  	const struct iwl_hcmd_utils_ops *utils; -	const struct iwl_led_ops *led;  	const struct iwl_nic_ops *nic; -	const struct iwl_legacy_ops *legacy; -	const struct ieee80211_ops *ieee80211_ops;  };  struct iwl_mod_params { @@ -256,13 +225,6 @@ struct iwl_mod_params {   * @wd_timeout: TX queues watchdog timeout   * @temperature_kelvin: temperature report by uCode in kelvin   * @max_event_log_size: size of event log buffer size for ucode event logging - * @tx_power_by_driver: tx power calibration performed by driver - *	instead of uCode - * @ucode_tracing: support ucode continuous tracing - * @sensitivity_calib_by_driver: driver has the capability to perform - *	sensitivity calibration operation - * @chain_noise_calib_by_driver: driver has the capability to perform - *	chain noise calibration operation   * @shadow_reg_enable: HW shadhow register bit   */  struct iwl_base_params { @@ -271,12 +233,10 @@ struct iwl_base_params {  	int num_of_ampdu_queues;/* def: HW dependent */  	/* for iwl_apm_init() */  	u32 pll_cfg_val; -	bool set_l0s;  	const u16 max_ll_items;  	const bool shadow_ram_support;  	u16 led_compensation; -	const bool broken_powersave;  	int chain_noise_num_beacons;  	bool adv_thermal_throttle;  	bool support_ct_kill_exit; @@ -286,17 +246,12 @@ struct iwl_base_params {  	unsigned int wd_timeout;  	bool temperature_kelvin;  	u32 max_event_log_size; -	const bool tx_power_by_driver; -	const bool ucode_tracing; -	const bool sensitivity_calib_by_driver; -	const bool chain_noise_calib_by_driver;  	const bool shadow_reg_enable;  };  /*   * @advanced_bt_coexist: support advanced bt coexist   * @bt_init_traffic_load: specify initial bt traffic load   * @bt_prio_boost: default bt priority boost value - * @bt_statistics: use BT version of statistics notification   * @agg_time_limit: maximum number of uSec in aggregation   * @ampdu_factor: Maximum A-MPDU length factor   * @ampdu_density: Minimum A-MPDU spacing @@ -306,7 +261,6 @@ struct iwl_bt_params {  	bool advanced_bt_coexist;  	u8 bt_init_traffic_load;  	u8 bt_prio_boost; -	const bool bt_statistics;  	u16 agg_time_limit;  	u8 ampdu_factor;  	u8 ampdu_density; @@ -337,6 +291,7 @@ struct iwl_ht_params {   * @rx_with_siso_diversity: 1x1 device with rx antenna diversity   * @internal_wimax_coex: internal wifi/wimax combo device   * @iq_invert: I/Q inversion + * @disable_otp_refresh: disable OTP refresh current limit   *   * We enable the driver to be backward compatible wrt API version. The   * driver specifies which APIs it supports (with @ucode_api_max being the @@ -387,13 +342,13 @@ struct iwl_cfg {  	const bool rx_with_siso_diversity;  	const bool internal_wimax_coex;  	const bool iq_invert; +	const bool disable_otp_refresh;  };  /***************************   *   L i b                 *   ***************************/ -struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg);  int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,  		    const struct ieee80211_tx_queue_params *params);  int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); @@ -598,6 +553,8 @@ extern const struct dev_pm_ops iwl_pm_ops;  void iwl_dump_nic_error_log(struct iwl_priv *priv);  int iwl_dump_nic_event_log(struct iwl_priv *priv,  			   bool full_log, char **buf, bool display); +void iwl_dump_csr(struct iwl_priv *priv); +int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display);  #ifdef CONFIG_IWLWIFI_DEBUG  void iwl_print_rx_config_cmd(struct iwl_priv *priv,  			     struct iwl_rxon_context *ctx); @@ -709,11 +666,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)  	       priv->cfg->bt_params->advanced_bt_coexist;  } -static inline bool iwl_bt_statistics(struct iwl_priv *priv) -{ -	return priv->bt_statistics; -} -  extern bool bt_coex_active;  extern bool bt_siso_mode; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 92f6efd2c73..c272204fccf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -437,8 +437,7 @@ static ssize_t iwl_dbgfs_log_event_read(struct file *file,  	int pos = 0;  	ssize_t ret = -ENOMEM; -	ret = pos = priv->cfg->ops->lib->dump_nic_event_log( -					priv, true, &buf, true); +	ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true);  	if (buf) {  		ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);  		kfree(buf); @@ -462,8 +461,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,  	if (sscanf(buf, "%d", &event_log_flag) != 1)  		return -EFAULT;  	if (event_log_flag == 1) -		priv->cfg->ops->lib->dump_nic_event_log(priv, true, -							NULL, false); +		iwl_dump_nic_event_log(priv, true, NULL, false);  	return count;  } @@ -1268,8 +1266,7 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file,  	if (sscanf(buf, "%d", &csr) != 1)  		return -EFAULT; -	if (priv->cfg->ops->lib->dump_csr) -		priv->cfg->ops->lib->dump_csr(priv); +	iwl_dump_csr(priv);  	return count;  } @@ -1359,13 +1356,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,  	int pos = 0;  	ssize_t ret = -EFAULT; -	if (priv->cfg->ops->lib->dump_fh) { -		ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true); -		if (buf) { -			ret = simple_read_from_buffer(user_buf, -						      count, ppos, buf, pos); -			kfree(buf); -		} +	ret = pos = iwl_dump_fh(priv, &buf, true); +	if (buf) { +		ret = simple_read_from_buffer(user_buf, +					      count, ppos, buf, pos); +		kfree(buf);  	}  	return ret; @@ -1728,11 +1723,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)  	DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);  	DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);  	DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); -	if (!priv->cfg->base_params->broken_powersave) { -		DEBUGFS_ADD_FILE(sleep_level_override, dir_data, -				 S_IWUSR | S_IRUSR); -		DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); -	} +	DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); +	DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);  	DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR);  	DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);  	DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); @@ -1755,29 +1747,20 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)  		DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);  	DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR); -	if (priv->cfg->base_params->sensitivity_calib_by_driver) -		DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); -	if (priv->cfg->base_params->chain_noise_calib_by_driver) -		DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); -	if (priv->cfg->base_params->ucode_tracing) -		DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); -	if (iwl_bt_statistics(priv)) -		DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); +	DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); +	DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); +	DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); +	DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR);  	DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR);  	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);  	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);  	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);  	if (iwl_advanced_bt_coexist(priv))  		DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); -	if (priv->cfg->base_params->sensitivity_calib_by_driver) -		DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, -				 &priv->disable_sens_cal); -	if (priv->cfg->base_params->chain_noise_calib_by_driver) -		DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, -				 &priv->disable_chain_noise_cal); -	if (priv->cfg->base_params->tx_power_by_driver) -		DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, -				&priv->disable_tx_power_cal); +	DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, +			 &priv->disable_sens_cal); +	DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, +			 &priv->disable_chain_noise_cal);  	return 0;  err: diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 72133368c1f..e84534c4d95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -543,13 +543,12 @@ enum iwl_ucode_tlv_type {   * enum iwl_ucode_tlv_flag - ucode API flags   * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously   *	was a separate TLV but moved here to save space. - * @IWL_UCODE_TLV_FLAGS_BTSTATS: This uCode image uses BT statistics, which - *	may be true even if the device doesn't have BT. + * @IWL_UCODE_TLV_FLAGS_RESERVED_1: reserved   * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).   */  enum iwl_ucode_tlv_flag {  	IWL_UCODE_TLV_FLAGS_PAN		= BIT(0), -	IWL_UCODE_TLV_FLAGS_BTSTATS	= BIT(1), +	IWL_UCODE_TLV_FLAGS_RESERVED_1	= BIT(1),  	IWL_UCODE_TLV_FLAGS_MFP		= BIT(2),  }; @@ -1170,6 +1169,8 @@ struct iwl_rxon_context {  		bool enabled, is_40mhz;  		u8 extension_chan_offset;  	} ht; + +	bool last_tx_rejected;  };  enum iwl_scan_type { @@ -1355,6 +1356,31 @@ struct iwl_priv {  	u64 timestamp;  	struct { +		__le32 flag; +		struct statistics_general_common common; +		struct statistics_rx_non_phy rx_non_phy; +		struct statistics_rx_phy rx_ofdm; +		struct statistics_rx_ht_phy rx_ofdm_ht; +		struct statistics_rx_phy rx_cck; +		struct statistics_tx tx; +#ifdef CONFIG_IWLWIFI_DEBUGFS +		struct statistics_bt_activity bt_activity; +		__le32 num_bt_kills, accum_num_bt_kills; +#endif +	} statistics; +#ifdef CONFIG_IWLWIFI_DEBUGFS +	struct { +		struct statistics_general_common common; +		struct statistics_rx_non_phy rx_non_phy; +		struct statistics_rx_phy rx_ofdm; +		struct statistics_rx_ht_phy rx_ofdm_ht; +		struct statistics_rx_phy rx_cck; +		struct statistics_tx tx; +		struct statistics_bt_activity bt_activity; +	} accum_stats, delta_stats, max_delta_stats; +#endif + +	struct {  		/* INT ICT Table */  		__le32 *ict_tbl;  		void *ict_tbl_vir; @@ -1385,19 +1411,9 @@ struct iwl_priv {  		u8 phy_calib_chain_noise_reset_cmd;  		u8 phy_calib_chain_noise_gain_cmd; -		struct iwl_notif_statistics statistics; -		struct iwl_bt_notif_statistics statistics_bt;  		/* counts reply_tx error */  		struct reply_tx_error_statistics reply_tx_stats;  		struct reply_agg_tx_error_statistics reply_agg_tx_stats; -#ifdef CONFIG_IWLWIFI_DEBUGFS -		struct iwl_notif_statistics accum_statistics; -		struct iwl_notif_statistics delta_statistics; -		struct iwl_notif_statistics max_delta; -		struct iwl_bt_notif_statistics accum_statistics_bt; -		struct iwl_bt_notif_statistics delta_statistics_bt; -		struct iwl_bt_notif_statistics max_delta_bt; -#endif  		/* notification wait support */  		struct list_head notif_waits;  		spinlock_t notif_wait_lock; @@ -1422,7 +1438,6 @@ struct iwl_priv {  	bool bt_ch_announce;  	bool bt_full_concurrent;  	bool bt_ant_couple_ok; -	bool bt_statistics;  	__le32 kill_ack_mask;  	__le32 kill_cts_mask;  	__le16 bt_valid; @@ -1487,7 +1502,6 @@ struct iwl_priv {  	struct work_struct txpower_work;  	u32 disable_sens_cal;  	u32 disable_chain_noise_cal; -	u32 disable_tx_power_cal;  	struct work_struct run_time_calib_work;  	struct timer_list statistics_periodic;  	struct timer_list ucode_trace; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 859b94a1229..402733638f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -215,12 +215,6 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev)  	return  nvm_type;  } -const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) -{ -	BUG_ON(offset >= priv->cfg->base_params->eeprom_size); -	return &priv->eeprom[offset]; -} -  static int iwl_init_otp_access(struct iwl_priv *priv)  {  	int ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 0e9d9703636..9ce052573c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -309,7 +309,6 @@ int  iwl_eeprom_check_sku(struct iwl_priv *priv);  const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);  int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);  u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); -const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);  int iwl_init_channel_map(struct iwl_priv *priv);  void iwl_free_channel_map(struct iwl_priv *priv);  const struct iwl_channel_info *iwl_get_channel_info( diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index e7a1bc6b76f..6dfa806aefe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -77,14 +77,14 @@  /**   * Keep-Warm (KW) buffer base address.   * - * Driver must allocate a 4KByte buffer that is used by 4965 for keeping the + * Driver must allocate a 4KByte buffer that is for keeping the   * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency - * DRAM access when 4965 is Txing or Rxing.  The dummy accesses prevent host + * DRAM access when doing Txing or Rxing.  The dummy accesses prevent host   * from going into a power-savings mode that would cause higher DRAM latency,   * and possible data over/under-runs, before all Tx/Rx is complete.   *   * Driver loads FH_KW_MEM_ADDR_REG with the physical address (bits 35:4) - * of the buffer, which must be 4K aligned.  Once this is set up, the 4965 + * of the buffer, which must be 4K aligned.  Once this is set up, the device   * automatically invokes keep-warm accesses when normal accesses might not   * be sufficient to maintain fast DRAM response.   * @@ -97,7 +97,7 @@  /**   * TFD Circular Buffers Base (CBBC) addresses   * - * 4965 has 16 base pointer registers, one for each of 16 host-DRAM-resident + * Device has 16 base pointer registers, one for each of 16 host-DRAM-resident   * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs)   * (see struct iwl_tfd_frame).  These 16 pointer registers are offset by 0x04   * bytes from one another.  Each TFD circular buffer in DRAM must be 256-byte @@ -116,16 +116,16 @@  /**   * Rx SRAM Control and Status Registers (RSCSR)   * - * These registers provide handshake between driver and 4965 for the Rx queue + * These registers provide handshake between driver and device for the Rx queue   * (this queue handles *all* command responses, notifications, Rx data, etc. - * sent from 4965 uCode to host driver).  Unlike Tx, there is only one Rx + * sent from uCode to host driver).  Unlike Tx, there is only one Rx   * queue, and only one Rx DMA/FIFO channel.  Also unlike Tx, which can   * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer   * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1   * mapping between RBDs and RBs.   *   * Driver must allocate host DRAM memory for the following, and set the - * physical address of each into 4965 registers: + * physical address of each into device registers:   *   * 1)  Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256   *     entries (although any power of 2, up to 4096, is selectable by driver). @@ -140,20 +140,20 @@   *     Driver sets physical address [35:8] of base of RBD circular buffer   *     into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0].   * - * 2)  Rx status buffer, 8 bytes, in which 4965 indicates which Rx Buffers + * 2)  Rx status buffer, 8 bytes, in which uCode indicates which Rx Buffers   *     (RBs) have been filled, via a "write pointer", actually the index of   *     the RB's corresponding RBD within the circular buffer.  Driver sets   *     physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0].   *   *     Bit fields in lower dword of Rx status buffer (upper dword not used - *     by driver; see struct iwl4965_shared, val0): + *     by driver:   *     31-12:  Not used by driver   *     11- 0:  Index of last filled Rx buffer descriptor - *             (4965 writes, driver reads this value) + *             (device writes, driver reads this value)   * - * As the driver prepares Receive Buffers (RBs) for 4965 to fill, driver must + * As the driver prepares Receive Buffers (RBs) for device to fill, driver must   * enter pointers to these RBs into contiguous RBD circular buffer entries, - * and update the 4965's "write" index register, + * and update the device's "write" index register,   * FH_RSCSR_CHNL0_RBDCB_WPTR_REG.   *   * This "write" index corresponds to the *next* RBD that the driver will make @@ -162,12 +162,12 @@   * RBs), should be 8 after preparing the first 8 RBs (for example), and must   * wrap back to 0 at the end of the circular buffer (but don't wrap before   * "read" index has advanced past 1!  See below). - * NOTE:  4965 EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8. + * NOTE:  DEVICE EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8.   * - * As the 4965 fills RBs (referenced from contiguous RBDs within the circular + * As the device fills RBs (referenced from contiguous RBDs within the circular   * buffer), it updates the Rx status buffer in host DRAM, 2) described above,   * to tell the driver the index of the latest filled RBD.  The driver must - * read this "read" index from DRAM after receiving an Rx interrupt from 4965. + * read this "read" index from DRAM after receiving an Rx interrupt from device   *   * The driver must also internally keep track of a third index, which is the   * next RBD to process.  When receiving an Rx interrupt, driver should process @@ -176,7 +176,7 @@   * driver may process the RB pointed to by RBD 0.  Depending on volume of   * traffic, there may be many RBs to process.   * - * If read index == write index, 4965 thinks there is no room to put new data. + * If read index == write index, device thinks there is no room to put new data.   * Due to this, the maximum number of filled RBs is 255, instead of 256.  To   * be safe, make sure that there is a gap of at least 2 RBDs between "write"   * and "read" indexes; that is, make sure that there are no more than 254 @@ -303,7 +303,7 @@  /**   * Transmit DMA Channel Control/Status Registers (TCSR)   * - * 4965 has one configuration register for each of 8 Tx DMA/FIFO channels + * Device has one configuration register for each of 8 Tx DMA/FIFO channels   * supported in hardware (don't confuse these with the 16 Tx queues in DRAM,   * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes.   * @@ -326,7 +326,6 @@  #define FH_TCSR_UPPER_BOUND  (FH_MEM_LOWER_BOUND + 0xE60)  /* Find Control/Status reg for given Tx DMA/FIFO channel */ -#define FH49_TCSR_CHNL_NUM                            (7)  #define FH50_TCSR_CHNL_NUM                            (8)  /* TCSR: tx_config register values */ @@ -424,7 +423,6 @@  #define RX_LOW_WATERMARK 8  /* Size of one Rx buffer in host DRAM */ -#define IWL_RX_BUF_SIZE_3K (3 * 1000) /* 3945 only */  #define IWL_RX_BUF_SIZE_4K (4 * 1024)  #define IWL_RX_BUF_SIZE_8K (8 * 1024) @@ -443,7 +441,7 @@ struct iwl_rb_status {  	__le16 closed_fr_num;  	__le16 finished_rb_num;  	__le16 finished_fr_nam; -	__le32 __unused; /* 3945 only */ +	__le32 __unused;  } __packed; diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 9177b553fe5..8f0beb992cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -143,10 +143,12 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  {  	int ret; -	BUG_ON(!(cmd->flags & CMD_ASYNC)); +	if (WARN_ON(!(cmd->flags & CMD_ASYNC))) +		return -EINVAL;  	/* An asynchronous command can not expect an SKB to be set. */ -	BUG_ON(cmd->flags & CMD_WANT_SKB); +	if (WARN_ON(cmd->flags & CMD_WANT_SKB)) +		return -EINVAL;  	/* Assign a generic callback if one is not provided */  	if (!cmd->callback) @@ -169,10 +171,12 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  	int cmd_idx;  	int ret; -	lockdep_assert_held(&priv->mutex); +	if (WARN_ON(cmd->flags & CMD_ASYNC)) +		return -EINVAL;  	 /* A synchronous command can not have a callback set. */ -	BUG_ON((cmd->flags & CMD_ASYNC) || cmd->callback); +	if (WARN_ON(cmd->callback)) +		return -EINVAL;  	IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",  			get_cmd_string(cmd->id)); diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 5da5761c74b..9309ff2df4c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -131,6 +131,19 @@ static inline void iwl_stop_queue(struct iwl_priv *priv,  			ieee80211_stop_queue(priv->hw, ac);  } +static inline void iwl_wake_any_queue(struct iwl_priv *priv, +				      struct iwl_rxon_context *ctx) +{ +	u8 ac; + +	for (ac = 0; ac < AC_NUM; ac++) { +		IWL_DEBUG_INFO(priv, "Queue Status: Q[%d] %s\n", +			ac, (atomic_read(&priv->queue_stop_count[ac]) > 0) +			      ? "stopped" : "awake"); +		iwl_wake_queue(priv, &priv->txq[ctx->ac_to_queue[ac]]); +	} +} +  #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue  #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index c2862d4e00e..d798c2a152d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -61,10 +61,16 @@ static const struct ieee80211_tpt_blink iwl_blink[] = {  	{ .throughput = 300 * 1024 - 1, .blink_time = 50 },  }; +/* Set led register off */ +void iwlagn_led_enable(struct iwl_priv *priv) +{ +	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); +} +  /*   * Adjust led blink rate to compensate on a MAC Clock difference on every HW - * Led blink rate analysis showed an average deviation of 0% on 3945, - * 5% on 4965 HW and 20% on 5000 series and up. + * Led blink rate analysis showed an average deviation of 20% on 5000 series + * and up.   * Need to compensate on the led on/off time per HW according to the deviation   * to achieve the desired led frequency   * The calculation is: (100-averageDeviation)/100 * blinkTime @@ -84,6 +90,24 @@ static inline u8 iwl_blink_compensation(struct iwl_priv *priv,  	return (u8)((time * compensation) >> 6);  } +static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) +{ +	struct iwl_host_cmd cmd = { +		.id = REPLY_LEDS_CMD, +		.len = sizeof(struct iwl_led_cmd), +		.data = led_cmd, +		.flags = CMD_ASYNC, +		.callback = NULL, +	}; +	u32 reg; + +	reg = iwl_read32(priv, CSR_LED_REG); +	if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) +		iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); + +	return iwl_send_cmd(priv, &cmd); +} +  /* Set led pattern command */  static int iwl_led_cmd(struct iwl_priv *priv,  		       unsigned long on, @@ -108,7 +132,7 @@ static int iwl_led_cmd(struct iwl_priv *priv,  	led_cmd.off = iwl_blink_compensation(priv, off,  				priv->cfg->base_params->led_compensation); -	ret = priv->cfg->ops->led->cmd(priv, &led_cmd); +	ret = iwl_send_led_cmd(priv, &led_cmd);  	if (!ret) {  		priv->blink_on = on;  		priv->blink_off = off; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 05b8e8f7dd4..1c93dfef693 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -50,6 +50,7 @@ enum iwl_led_mode {  	IWL_LED_BLINK,  }; +void iwlagn_led_enable(struct iwl_priv *priv);  void iwl_leds_init(struct iwl_priv *priv);  void iwl_leds_exit(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index c43c8e66de7..595c930b28a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -188,9 +188,10 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,  			table = range_0;  	} -	BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); - -	*cmd = table[lvl].cmd; +	if (WARN_ON(lvl < 0 || lvl >= IWL_POWER_NUM)) +		memset(cmd, 0, sizeof(*cmd)); +	else +		*cmd = table[lvl].cmd;  	if (period == 0) {  		skip = 0; @@ -354,16 +355,12 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,  	dtimper = priv->hw->conf.ps_dtim_period ?: 1; -	if (priv->cfg->base_params->broken_powersave) -		iwl_power_sleep_cam_cmd(priv, cmd); -	else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) +	if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)  		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); -	else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && -		 priv->cfg->ops->lib->tt_ops.tt_power_mode && -		 priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) { +	else if (iwl_tt_is_low_power_state(priv)) {  		/* in thermal throttling low power state */  		iwl_static_sleep_cmd(priv, cmd, -		    priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper); +		    iwl_tt_current_power_mode(priv), dtimper);  	} else if (!enabled)  		iwl_power_sleep_cam_cmd(priv, cmd);  	else if (priv->power_data.debug_sleep_level_override >= 0) diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index c960195df98..f00d188b2cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -107,17 +107,7 @@   * device.  A queue maps to only one (selectable by driver) Tx DMA channel,   * but one DMA channel may take input from several queues.   * - * Tx DMA FIFOs have dedicated purposes.  For 4965, they are used as follows - * (cf. default_queue_to_tx_fifo in iwl-4965.c): - * - * 0 -- EDCA BK (background) frames, lowest priority - * 1 -- EDCA BE (best effort) frames, normal priority - * 2 -- EDCA VI (video) frames, higher priority - * 3 -- EDCA VO (voice) and management frames, highest priority - * 4 -- Commands (e.g. RXON, etc.) - * 5 -- unused (HCCA) - * 6 -- unused (HCCA) - * 7 -- not used by driver (device-internal only) + * Tx DMA FIFOs have dedicated purposes.   *   * For 5000 series and up, they are used differently   * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c): @@ -151,7 +141,7 @@   *     Tx completion may end up being out-of-order).   *   *     The driver must maintain the queue's Byte Count table in host DRAM - *     (struct iwl4965_sched_queue_byte_cnt_tbl) for this mode. + *     for this mode.   *     This mode does not support fragmentation.   *   * 2)  FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order. @@ -164,7 +154,7 @@   *   * Driver controls scheduler operation via 3 means:   * 1)  Scheduler registers - * 2)  Shared scheduler data base in internal 4956 SRAM + * 2)  Shared scheduler data base in internal SRAM   * 3)  Shared data in host DRAM   *   * Initialization: diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index c421f566982..b49819ca2cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -390,21 +390,16 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,   * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal   * operation state.   */ -static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt) +static bool iwl_good_ack_health(struct iwl_priv *priv, +				struct statistics_tx *cur)  {  	int actual_delta, expected_delta, ba_timeout_delta; -	struct statistics_tx *cur, *old; +	struct statistics_tx *old;  	if (priv->_agn.agg_tids_count)  		return true; -	if (iwl_bt_statistics(priv)) { -		cur = &pkt->u.stats_bt.tx; -		old = &priv->_agn.statistics_bt.tx; -	} else { -		cur = &pkt->u.stats.tx; -		old = &priv->_agn.statistics.tx; -	} +	old = &priv->statistics.tx;  	actual_delta = le32_to_cpu(cur->actual_ack_cnt) -  		       le32_to_cpu(old->actual_ack_cnt); @@ -430,10 +425,10 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt  		 * DEBUG is not, these will just compile out.  		 */  		IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta %d\n", -				priv->_agn.delta_statistics.tx.rx_detected_cnt); +				priv->delta_stats.tx.rx_detected_cnt);  		IWL_DEBUG_RADIO(priv,  				"ack_or_ba_timeout_collision delta %d\n", -				priv->_agn.delta_statistics.tx.ack_or_ba_timeout_collision); +				priv->delta_stats.tx.ack_or_ba_timeout_collision);  #endif  		if (ba_timeout_delta >= BA_TIMEOUT_MAX) @@ -450,7 +445,9 @@ static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt   * to improve the throughput.   */  static bool iwl_good_plcp_health(struct iwl_priv *priv, -				 struct iwl_rx_packet *pkt, unsigned int msecs) +				 struct statistics_rx_phy *cur_ofdm, +				 struct statistics_rx_ht_phy *cur_ofdm_ht, +				 unsigned int msecs)  {  	int delta;  	int threshold = priv->cfg->base_params->plcp_delta_threshold; @@ -460,29 +457,12 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv,  		return true;  	} -	if (iwl_bt_statistics(priv)) { -		struct statistics_rx_bt *cur, *old; - -		cur = &pkt->u.stats_bt.rx; -		old = &priv->_agn.statistics_bt.rx; - -		delta = le32_to_cpu(cur->ofdm.plcp_err) - -			le32_to_cpu(old->ofdm.plcp_err) + -			le32_to_cpu(cur->ofdm_ht.plcp_err) - -			le32_to_cpu(old->ofdm_ht.plcp_err); -	} else { -		struct statistics_rx *cur, *old; - -		cur = &pkt->u.stats.rx; -		old = &priv->_agn.statistics.rx; +	delta = le32_to_cpu(cur_ofdm->plcp_err) - +		le32_to_cpu(priv->statistics.rx_ofdm.plcp_err) + +		le32_to_cpu(cur_ofdm_ht->plcp_err) - +		le32_to_cpu(priv->statistics.rx_ofdm_ht.plcp_err); -		delta = le32_to_cpu(cur->ofdm.plcp_err) - -			le32_to_cpu(old->ofdm.plcp_err) + -			le32_to_cpu(cur->ofdm_ht.plcp_err) - -			le32_to_cpu(old->ofdm_ht.plcp_err); -	} - -	/* Can be negative if firmware reseted statistics */ +	/* Can be negative if firmware reset statistics */  	if (delta <= 0)  		return true; @@ -497,44 +477,36 @@ static bool iwl_good_plcp_health(struct iwl_priv *priv,  }  static void iwl_recover_from_statistics(struct iwl_priv *priv, -					struct iwl_rx_packet *pkt) +					struct statistics_rx_phy *cur_ofdm, +					struct statistics_rx_ht_phy *cur_ofdm_ht, +					struct statistics_tx *tx, +					unsigned long stamp)  {  	const struct iwl_mod_params *mod_params = priv->cfg->mod_params;  	unsigned int msecs; -	unsigned long stamp;  	if (test_bit(STATUS_EXIT_PENDING, &priv->status))  		return; -	stamp = jiffies;  	msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);  	/* Only gather statistics and update time stamp when not associated */  	if (!iwl_is_any_associated(priv)) -		goto out; +		return;  	/* Do not check/recover when do not have enough statistics data */  	if (msecs < 99)  		return; -	if (mod_params->ack_check && !iwl_good_ack_health(priv, pkt)) { +	if (mod_params->ack_check && !iwl_good_ack_health(priv, tx)) {  		IWL_ERR(priv, "low ack count detected, restart firmware\n");  		if (!iwl_force_reset(priv, IWL_FW_RESET, false))  			return;  	} -	if (mod_params->plcp_check && !iwl_good_plcp_health(priv, pkt, msecs)) +	if (mod_params->plcp_check && +	    !iwl_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs))  		iwl_force_reset(priv, IWL_RF_RESET, false); - -out: -	if (iwl_bt_statistics(priv)) -		memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt, -			sizeof(priv->_agn.statistics_bt)); -	else -		memcpy(&priv->_agn.statistics, &pkt->u.stats, -			sizeof(priv->_agn.statistics)); - -	priv->rx_statistics_jiffies = stamp;  }  /* Calculate noise level, based on measurements during network silence just @@ -548,10 +520,8 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv)  	int bcn_silence_a, bcn_silence_b, bcn_silence_c;  	int last_rx_noise; -	if (iwl_bt_statistics(priv)) -		rx_info = &(priv->_agn.statistics_bt.rx.general.common); -	else -		rx_info = &(priv->_agn.statistics.rx.general); +	rx_info = &priv->statistics.rx_non_phy; +  	bcn_silence_a =  		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;  	bcn_silence_b = @@ -583,105 +553,153 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv)  			last_rx_noise);  } +#ifdef CONFIG_IWLWIFI_DEBUGFS  /*   *  based on the assumption of all statistics counter are in DWORD   *  FIXME: This function is for debugging, do not deal with   *  the case of counters roll-over.   */ -static void iwl_accumulative_statistics(struct iwl_priv *priv, -					__le32 *stats) +static void accum_stats(__le32 *prev, __le32 *cur, __le32 *delta, +			__le32 *max_delta, __le32 *accum, int size)  { -#ifdef CONFIG_IWLWIFI_DEBUGFS -	int i, size; -	__le32 *prev_stats; -	u32 *accum_stats; -	u32 *delta, *max_delta; -	struct statistics_general_common *general, *accum_general; -	struct statistics_tx *tx, *accum_tx; +	int i; -	if (iwl_bt_statistics(priv)) { -		prev_stats = (__le32 *)&priv->_agn.statistics_bt; -		accum_stats = (u32 *)&priv->_agn.accum_statistics_bt; -		size = sizeof(struct iwl_bt_notif_statistics); -		general = &priv->_agn.statistics_bt.general.common; -		accum_general = &priv->_agn.accum_statistics_bt.general.common; -		tx = &priv->_agn.statistics_bt.tx; -		accum_tx = &priv->_agn.accum_statistics_bt.tx; -		delta = (u32 *)&priv->_agn.delta_statistics_bt; -		max_delta = (u32 *)&priv->_agn.max_delta_bt; -	} else { -		prev_stats = (__le32 *)&priv->_agn.statistics; -		accum_stats = (u32 *)&priv->_agn.accum_statistics; -		size = sizeof(struct iwl_notif_statistics); -		general = &priv->_agn.statistics.general.common; -		accum_general = &priv->_agn.accum_statistics.general.common; -		tx = &priv->_agn.statistics.tx; -		accum_tx = &priv->_agn.accum_statistics.tx; -		delta = (u32 *)&priv->_agn.delta_statistics; -		max_delta = (u32 *)&priv->_agn.max_delta; -	} -	for (i = sizeof(__le32); i < size; -	     i += sizeof(__le32), stats++, prev_stats++, delta++, -	     max_delta++, accum_stats++) { -		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { -			*delta = (le32_to_cpu(*stats) - -				le32_to_cpu(*prev_stats)); -			*accum_stats += *delta; -			if (*delta > *max_delta) +	for (i = 0; +	     i < size / sizeof(__le32); +	     i++, prev++, cur++, delta++, max_delta++, accum++) { +		if (le32_to_cpu(*cur) > le32_to_cpu(*prev)) { +			*delta = cpu_to_le32( +				le32_to_cpu(*cur) - le32_to_cpu(*prev)); +			le32_add_cpu(accum, le32_to_cpu(*delta)); +			if (le32_to_cpu(*delta) > le32_to_cpu(*max_delta))  				*max_delta = *delta;  		}  	} +} -	/* reset accumulative statistics for "no-counter" type statistics */ -	accum_general->temperature = general->temperature; -	accum_general->temperature_m = general->temperature_m; -	accum_general->ttl_timestamp = general->ttl_timestamp; -	accum_tx->tx_power.ant_a = tx->tx_power.ant_a; -	accum_tx->tx_power.ant_b = tx->tx_power.ant_b; -	accum_tx->tx_power.ant_c = tx->tx_power.ant_c; -#endif +static void +iwl_accumulative_statistics(struct iwl_priv *priv, +			    struct statistics_general_common *common, +			    struct statistics_rx_non_phy *rx_non_phy, +			    struct statistics_rx_phy *rx_ofdm, +			    struct statistics_rx_ht_phy *rx_ofdm_ht, +			    struct statistics_rx_phy *rx_cck, +			    struct statistics_tx *tx, +			    struct statistics_bt_activity *bt_activity) +{ +#define ACCUM(_name)	\ +	accum_stats((__le32 *)&priv->statistics._name,		\ +		    (__le32 *)_name,				\ +		    (__le32 *)&priv->delta_stats._name,		\ +		    (__le32 *)&priv->max_delta_stats._name,	\ +		    (__le32 *)&priv->accum_stats._name,		\ +		    sizeof(*_name)); + +	ACCUM(common); +	ACCUM(rx_non_phy); +	ACCUM(rx_ofdm); +	ACCUM(rx_ofdm_ht); +	ACCUM(rx_cck); +	ACCUM(tx); +	if (bt_activity) +		ACCUM(bt_activity); +#undef ACCUM +} +#else +static inline void +iwl_accumulative_statistics(struct iwl_priv *priv, +			    struct statistics_general_common *common, +			    struct statistics_rx_non_phy *rx_non_phy, +			    struct statistics_rx_phy *rx_ofdm, +			    struct statistics_rx_ht_phy *rx_ofdm_ht, +			    struct statistics_rx_phy *rx_cck, +			    struct statistics_tx *tx, +			    struct statistics_bt_activity *bt_activity) +{  } +#endif  static void iwl_rx_statistics(struct iwl_priv *priv,  			      struct iwl_rx_mem_buffer *rxb)  { +	unsigned long stamp = jiffies;  	const int reg_recalib_period = 60;  	int change;  	struct iwl_rx_packet *pkt = rxb_addr(rxb); +	u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; +	__le32 *flag; +	struct statistics_general_common *common; +	struct statistics_rx_non_phy *rx_non_phy; +	struct statistics_rx_phy *rx_ofdm; +	struct statistics_rx_ht_phy *rx_ofdm_ht; +	struct statistics_rx_phy *rx_cck; +	struct statistics_tx *tx; +	struct statistics_bt_activity *bt_activity; -	if (iwl_bt_statistics(priv)) { -		IWL_DEBUG_RX(priv, -			     "Statistics notification received (%d vs %d).\n", -			     (int)sizeof(struct iwl_bt_notif_statistics), -			     le32_to_cpu(pkt->len_n_flags) & -			     FH_RSCSR_FRAME_SIZE_MSK); +	len -= sizeof(struct iwl_cmd_header); /* skip header */ -		change = ((priv->_agn.statistics_bt.general.common.temperature != -			   pkt->u.stats_bt.general.common.temperature) || -			   ((priv->_agn.statistics_bt.flag & -			   STATISTICS_REPLY_FLG_HT40_MODE_MSK) != -			   (pkt->u.stats_bt.flag & -			   STATISTICS_REPLY_FLG_HT40_MODE_MSK))); +	IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n", +		     len); -		iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt); +	if (len == sizeof(struct iwl_bt_notif_statistics)) { +		struct iwl_bt_notif_statistics *stats; +		stats = &pkt->u.stats_bt; +		flag = &stats->flag; +		common = &stats->general.common; +		rx_non_phy = &stats->rx.general.common; +		rx_ofdm = &stats->rx.ofdm; +		rx_ofdm_ht = &stats->rx.ofdm_ht; +		rx_cck = &stats->rx.cck; +		tx = &stats->tx; +		bt_activity = &stats->general.activity; + +#ifdef CONFIG_IWLWIFI_DEBUGFS +		/* handle this exception directly */ +		priv->statistics.num_bt_kills = stats->rx.general.num_bt_kills; +		le32_add_cpu(&priv->statistics.accum_num_bt_kills, +			     le32_to_cpu(stats->rx.general.num_bt_kills)); +#endif +	} else if (len == sizeof(struct iwl_notif_statistics)) { +		struct iwl_notif_statistics *stats; +		stats = &pkt->u.stats; +		flag = &stats->flag; +		common = &stats->general.common; +		rx_non_phy = &stats->rx.general; +		rx_ofdm = &stats->rx.ofdm; +		rx_ofdm_ht = &stats->rx.ofdm_ht; +		rx_cck = &stats->rx.cck; +		tx = &stats->tx; +		bt_activity = NULL;  	} else { -		IWL_DEBUG_RX(priv, -			     "Statistics notification received (%d vs %d).\n", -			     (int)sizeof(struct iwl_notif_statistics), -			     le32_to_cpu(pkt->len_n_flags) & -			     FH_RSCSR_FRAME_SIZE_MSK); +		WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n", +			  len, sizeof(struct iwl_bt_notif_statistics), +			  sizeof(struct iwl_notif_statistics)); +		return; +	} -		change = ((priv->_agn.statistics.general.common.temperature != -			   pkt->u.stats.general.common.temperature) || -			   ((priv->_agn.statistics.flag & -			   STATISTICS_REPLY_FLG_HT40_MODE_MSK) != -			   (pkt->u.stats.flag & -			   STATISTICS_REPLY_FLG_HT40_MODE_MSK))); +	change = common->temperature != priv->statistics.common.temperature || +		 (*flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK) != +		 (priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK); -		iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); -	} +	iwl_accumulative_statistics(priv, common, rx_non_phy, rx_ofdm, +				    rx_ofdm_ht, rx_cck, tx, bt_activity); + +	iwl_recover_from_statistics(priv, rx_ofdm, rx_ofdm_ht, tx, stamp); + +	priv->statistics.flag = *flag; +	memcpy(&priv->statistics.common, common, sizeof(*common)); +	memcpy(&priv->statistics.rx_non_phy, rx_non_phy, sizeof(*rx_non_phy)); +	memcpy(&priv->statistics.rx_ofdm, rx_ofdm, sizeof(*rx_ofdm)); +	memcpy(&priv->statistics.rx_ofdm_ht, rx_ofdm_ht, sizeof(*rx_ofdm_ht)); +	memcpy(&priv->statistics.rx_cck, rx_cck, sizeof(*rx_cck)); +	memcpy(&priv->statistics.tx, tx, sizeof(*tx)); +#ifdef CONFIG_IWLWIFI_DEBUGFS +	if (bt_activity) +		memcpy(&priv->statistics.bt_activity, bt_activity, +			sizeof(*bt_activity)); +#endif -	iwl_recover_from_statistics(priv, pkt); +	priv->rx_statistics_jiffies = stamp;  	set_bit(STATUS_STATISTICS, &priv->status); @@ -708,18 +726,12 @@ static void iwl_rx_reply_statistics(struct iwl_priv *priv,  	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {  #ifdef CONFIG_IWLWIFI_DEBUGFS -		memset(&priv->_agn.accum_statistics, 0, -			sizeof(struct iwl_notif_statistics)); -		memset(&priv->_agn.delta_statistics, 0, -			sizeof(struct iwl_notif_statistics)); -		memset(&priv->_agn.max_delta, 0, -			sizeof(struct iwl_notif_statistics)); -		memset(&priv->_agn.accum_statistics_bt, 0, -			sizeof(struct iwl_bt_notif_statistics)); -		memset(&priv->_agn.delta_statistics_bt, 0, -			sizeof(struct iwl_bt_notif_statistics)); -		memset(&priv->_agn.max_delta_bt, 0, -			sizeof(struct iwl_bt_notif_statistics)); +		memset(&priv->accum_stats, 0, +			sizeof(priv->accum_stats)); +		memset(&priv->delta_stats, 0, +			sizeof(priv->delta_stats)); +		memset(&priv->max_delta_stats, 0, +			sizeof(priv->max_delta_stats));  #endif  		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");  	} @@ -873,6 +885,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,  {  	struct sk_buff *skb;  	__le16 fc = hdr->frame_control; +	struct iwl_rxon_context *ctx;  	/* We only process data packets if the interface is open */  	if (unlikely(!priv->is_open)) { @@ -895,6 +908,26 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,  	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);  	iwl_update_stats(priv, false, fc, len); + +	/* +	* Wake any queues that were stopped due to a passive channel tx +	* failure. This can happen because the regulatory enforcement in +	* the device waits for a beacon before allowing transmission, +	* sometimes even after already having transmitted frames for the +	* association because the new RXON may reset the information. +	*/ +	if (unlikely(ieee80211_is_beacon(fc))) { +		for_each_context(priv, ctx) { +			if (!ctx->last_tx_rejected) +				continue; +			if (compare_ether_addr(hdr->addr3, +					       ctx->active.bssid_addr)) +				continue; +			ctx->last_tx_rejected = false; +			iwl_wake_any_queue(priv, ctx); +		} +	} +  	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));  	ieee80211_rx(priv->hw, skb); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index c2151564007..3c8cebde16c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -494,7 +494,8 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,  	priv->num_stations--; -	BUG_ON(priv->num_stations < 0); +	if (WARN_ON(priv->num_stations < 0)) +		priv->num_stations = 0;  	spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -679,7 +680,8 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv)  		priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;  		priv->num_stations--; -		BUG_ON(priv->num_stations < 0); +		if (WARN_ON(priv->num_stations < 0)) +			priv->num_stations = 0;  		kfree(priv->stations[i].lq);  		priv->stations[i].lq = NULL;  	} @@ -775,7 +777,8 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,  	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);  	iwl_dump_lq_cmd(priv, lq); -	BUG_ON(init && (cmd.flags & CMD_ASYNC)); +	if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) +		return -EINVAL;  	if (is_lq_table_valid(priv, ctx, lq))  		ret = iwl_send_cmd(priv, &cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 565980fbb59..80c3565a66a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -232,7 +232,6 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)   * reclaiming packets (on 'tx done IRQ), if free space become > high mark,   * Tx queue resumed.   * - * See more detailed info in iwl-4965-hw.h.   ***************************************************/  int iwl_queue_space(const struct iwl_queue *q) @@ -264,11 +263,13 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,  	/* count must be power-of-two size, otherwise iwl_queue_inc_wrap  	 * and iwl_queue_dec_wrap are broken. */ -	BUG_ON(!is_power_of_2(count)); +	if (WARN_ON(!is_power_of_2(count))) +		return -EINVAL;  	/* slots_num must be power-of-two size, otherwise  	 * get_cmd_index is broken. */ -	BUG_ON(!is_power_of_2(slots_num)); +	if (WARN_ON(!is_power_of_2(slots_num))) +		return -EINVAL;  	q->low_mark = q->n_window / 4;  	if (q->low_mark < 4) @@ -385,7 +386,9 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,  	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));  	/* Initialize queue's high/low-water marks, and head/tail indexes */ -	iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); +	ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); +	if (ret) +		return ret;  	/* Tell device where to find queue */  	priv->cfg->ops->lib->txq_init(priv, txq); @@ -447,14 +450,19 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  	cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);  	fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); -	/* If any of the command structures end up being larger than +	/* +	 * If any of the command structures end up being larger than  	 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then  	 * we will need to increase the size of the TFD entries  	 * Also, check to see if command buffer should not exceed the size -	 * of device_cmd and max_cmd_size. */ -	BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && -	       !(cmd->flags & CMD_SIZE_HUGE)); -	BUG_ON(fix_size > IWL_MAX_CMD_SIZE); +	 * of device_cmd and max_cmd_size. +	 */ +	if (WARN_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && +		    !(cmd->flags & CMD_SIZE_HUGE))) +		return -EINVAL; + +	if (WARN_ON(fix_size > IWL_MAX_CMD_SIZE)) +		return -EINVAL;  	if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {  		IWL_WARN(priv, "Not sending command - %s KILL\n", @@ -462,16 +470,21 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  		return -EIO;  	} +	/* +	 * As we only have a single huge buffer, check that the command +	 * is synchronous (otherwise buffers could end up being reused). +	 */ + +	if (WARN_ON((cmd->flags & CMD_ASYNC) && (cmd->flags & CMD_SIZE_HUGE))) +		return -EINVAL; +  	spin_lock_irqsave(&priv->hcmd_lock, flags);  	if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {  		spin_unlock_irqrestore(&priv->hcmd_lock, flags);  		IWL_ERR(priv, "No space in command queue\n"); -		if (priv->cfg->ops->lib->tt_ops.ct_kill_check) { -			is_ct_kill = -				priv->cfg->ops->lib->tt_ops.ct_kill_check(priv); -		} +		is_ct_kill = iwl_check_for_ct_kill(priv);  		if (!is_ct_kill) {  			IWL_ERR(priv, "Restarting adapter due to queue full\n");  			iwlagn_fw_error(priv, false); diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 73a6e62f568..e22d761f2ef 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -115,7 +115,7 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv,  		SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask);  	/* Clear RD responder bit */ -	RESETHT_EXTCAP_RDG(ht_ext_cap); +	ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER;  	ht_cap->ht_cap.cap_info = cpu_to_le16(ht_cap_info);  	ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap); @@ -242,9 +242,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,   *   * Handling includes changing the header fields into CPU format.   */ -int mwifiex_ret_11n_cfg(struct mwifiex_private *priv, -			struct host_cmd_ds_command *resp, -			void *data_buf) +int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)  {  	struct mwifiex_ds_11n_tx_cfg *tx_cfg = NULL;  	struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg; @@ -298,8 +296,7 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,   *      - Setting AMSDU control parameters (for SET only)   *      - Ensuring correct endian-ness   */ -int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv, -				struct host_cmd_ds_command *cmd, +int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,  				int cmd_action, void *data_buf)  {  	struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = @@ -331,8 +328,7 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv,   *   * Handling includes changing the header fields into CPU format.   */ -int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv, -				struct host_cmd_ds_command *resp, +int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,  				void *data_buf)  {  	struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl = NULL; @@ -357,8 +353,7 @@ int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv,   *      - Setting HT Tx capability and HT Tx information fields   *      - Ensuring correct endian-ness   */ -int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, -			struct host_cmd_ds_command *cmd, +int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,  			u16 cmd_action, void *data_buf)  {  	struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg; @@ -541,11 +536,8 @@ mwifiex_cfg_tx_buf(struct mwifiex_private *priv,  	else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_8K)  		curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_8K;  	if (curr_tx_buf_size != tx_buf) -		mwifiex_prepare_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, -			HostCmd_ACT_GEN_SET, 0, -			NULL, &tx_buf); - -	return; +		mwifiex_send_cmd_async(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, +				       HostCmd_ACT_GEN_SET, 0, &tx_buf);  }  /* @@ -583,8 +575,6 @@ void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv,  	list_del(&tx_ba_tsr_tbl->list);  	kfree(tx_ba_tsr_tbl); - -	return;  }  /* @@ -663,8 +653,6 @@ void mwifiex_11n_create_tx_ba_stream_tbl(struct mwifiex_private *priv,  		list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr);  		spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);  	} - -	return;  }  /* @@ -694,8 +682,8 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)  	memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN);  	/* We don't wait for the response of this command */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ, -				  0, 0, NULL, &add_ba_req); +	ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_REQ, +				     0, 0, &add_ba_req);  	return ret;  } @@ -722,8 +710,8 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,  	memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN);  	/* We don't wait for the response of this command */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, -				  HostCmd_ACT_GEN_SET, 0, NULL, &delba); +	ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, +				     HostCmd_ACT_GEN_SET, 0, &delba);  	return ret;  } diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 71a853e61b6..02602ff30cb 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h @@ -28,15 +28,9 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,  			  struct host_cmd_ds_command *resp);  int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,  			      struct host_cmd_ds_command *resp); -int mwifiex_ret_11n_cfg(struct mwifiex_private *priv, -			struct host_cmd_ds_command *resp, +int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,  			void *data_buf); -int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, -			struct host_cmd_ds_command *cmd, -			u16 cmd_action, void *data_buf); - -int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, -			struct host_cmd_ds_command *cmd, +int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,  			u16 cmd_action, void *data_buf);  int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, @@ -67,24 +61,19 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,  			      struct mwifiex_ds_rx_reorder_tbl *buf);  int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,  			       struct mwifiex_ds_tx_ba_stream_tbl *buf); -int mwifiex_ret_amsdu_aggr_ctrl(struct mwifiex_private *priv, -				struct host_cmd_ds_command -				*resp, +int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,  				void *data_buf);  int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,  			     struct host_cmd_ds_command *cmd,  			     int cmd_action, void *data_buf); -int mwifiex_cmd_amsdu_aggr_ctrl(struct mwifiex_private *priv, -				struct host_cmd_ds_command *cmd, -				int cmd_action, -				void *data_buf); +int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, +				int cmd_action, void *data_buf);  /*   * This function checks whether AMPDU is allowed or not for a particular TID.   */  static inline u8 -mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, -			 struct mwifiex_ra_list_tbl *ptr, int tid) +mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, int tid)  {  	return ((priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED)  		? true : false); @@ -94,8 +83,7 @@ mwifiex_is_ampdu_allowed(struct mwifiex_private *priv,   * This function checks whether AMSDU is allowed or not for a particular TID.   */  static inline u8 -mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, -			 struct mwifiex_ra_list_tbl *ptr, int tid) +mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, int tid)  {  	return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)  			&& ((priv->is_data_rate_auto) @@ -104,23 +92,21 @@ mwifiex_is_amsdu_allowed(struct mwifiex_private *priv,  }  /* - * This function checks whether a BA stream is available or not. + * This function checks whether a space is available for new BA stream or not.   */ -static inline u8 -mwifiex_is_ba_stream_avail(struct mwifiex_private *priv) +static inline u8 mwifiex_space_avail_for_new_ba_stream( +					struct mwifiex_adapter *adapter)  { -	struct mwifiex_private *pmpriv = NULL; -	u8 i = 0; +	struct mwifiex_private *priv; +	u8 i;  	u32 ba_stream_num = 0; -	for (i = 0; i < priv->adapter->priv_num; i++) { -		pmpriv = priv->adapter->priv[i]; -		if (pmpriv) -			ba_stream_num += -				mwifiex_wmm_list_len(priv->adapter, -						     (struct list_head -						      *) &pmpriv-> -						     tx_ba_stream_tbl_ptr); +	for (i = 0; i < adapter->priv_num; i++) { +		priv = adapter->priv[i]; +		if (priv) +			ba_stream_num += mwifiex_wmm_list_len( +						(struct list_head *) +						&priv->tx_ba_stream_tbl_ptr);  	}  	return ((ba_stream_num < @@ -133,8 +119,7 @@ mwifiex_is_ba_stream_avail(struct mwifiex_private *priv)   * Upon successfully locating, both the TID and the RA are returned.   */  static inline u8 -mwifiex_find_stream_to_delete(struct mwifiex_private *priv, -			      struct mwifiex_ra_list_tbl *ptr, int ptr_tid, +mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid,  			      int *ptid, u8 *ra)  {  	int tid; diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index c2abced6695..c9fb0627de4 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -44,8 +44,7 @@   * MSDU => |DA|SA|Length|SNAP|......   ..|   */  static int -mwifiex_11n_form_amsdu_pkt(struct mwifiex_adapter *adapter, -			   struct sk_buff *skb_aggr, +mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,  			   struct sk_buff *skb_src, int *pad)  { @@ -324,7 +323,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,  		spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,  				       ra_list_flags); -		mwifiex_11n_form_amsdu_pkt(adapter, skb_aggr, skb_src, &pad); +		mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad);  		mwifiex_write_data_complete(adapter, skb_src, 0); diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 8e94e620e6f..a93c03fdea8 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -27,19 +27,6 @@  #include "11n_rxreorder.h"  /* - * This function processes a received packet and forwards - * it to the kernel/upper layer. - */ -static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload) -{ -	int ret = 0; -	struct mwifiex_adapter *adapter = priv->adapter; - -	ret = mwifiex_process_rx_packet(adapter, (struct sk_buff *) payload); -	return ret; -} - -/*   * This function dispatches all packets in the Rx reorder table.   *   * There could be holes in the buffer, which are skipped by the function. @@ -51,7 +38,7 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,  					 struct mwifiex_rx_reorder_tbl  					 *rx_reor_tbl_ptr, int start_win)  { -	int no_pkt_to_send, i, xchg; +	int no_pkt_to_send, i;  	void *rx_tmp_ptr = NULL;  	unsigned long flags; @@ -68,7 +55,7 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,  		}  		spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);  		if (rx_tmp_ptr) -			mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); +			mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);  	}  	spin_lock_irqsave(&priv->rx_pkt_lock, flags); @@ -76,8 +63,7 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv,  	 * We don't have a circular buffer, hence use rotation to simulate  	 * circular buffer  	 */ -	xchg = rx_reor_tbl_ptr->win_size - no_pkt_to_send; -	for (i = 0; i < xchg; ++i) { +	for (i = 0; i < rx_reor_tbl_ptr->win_size - no_pkt_to_send; ++i) {  		rx_reor_tbl_ptr->rx_reorder_ptr[i] =  			rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i];  		rx_reor_tbl_ptr->rx_reorder_ptr[no_pkt_to_send + i] = NULL; @@ -114,7 +100,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,  		rx_tmp_ptr = rx_reor_tbl_ptr->rx_reorder_ptr[i];  		rx_reor_tbl_ptr->rx_reorder_ptr[i] = NULL;  		spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); -		mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); +		mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);  	}  	spin_lock_irqsave(&priv->rx_pkt_lock, flags); @@ -309,8 +295,6 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,  	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);  	list_add_tail(&new_node->list, &priv->rx_reorder_tbl_ptr);  	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - -	return;  }  /* @@ -321,8 +305,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,   *      - Setting add BA request buffer   *      - Ensuring correct endian-ness   */ -int mwifiex_cmd_11n_addba_req(struct mwifiex_private *priv, -			      struct host_cmd_ds_command *cmd, void *data_buf) +int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf)  {  	struct host_cmd_ds_11n_addba_req *add_ba_req =  		(struct host_cmd_ds_11n_addba_req *) @@ -393,8 +376,7 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,   *      - Setting del BA request buffer   *      - Ensuring correct endian-ness   */ -int mwifiex_cmd_11n_delba(struct mwifiex_private *priv, -			  struct host_cmd_ds_command *cmd, void *data_buf) +int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd, void *data_buf)  {  	struct host_cmd_ds_11n_delba *del_ba = (struct host_cmd_ds_11n_delba *)  		&cmd->params.del_ba; @@ -433,7 +415,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,  						tid, ta);  	if (!rx_reor_tbl_ptr) {  		if (pkt_type != PKT_TYPE_BAR) -			mwifiex_11n_dispatch_pkt(priv, payload); +			mwifiex_process_rx_packet(priv->adapter, payload);  		return 0;  	}  	start_win = rx_reor_tbl_ptr->start_win; @@ -609,9 +591,7 @@ void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv,  	delba.del_ba_param_set |= cpu_to_le16(  		(u16) event->origninator << DELBA_INITIATOR_POS);  	delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); -	mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, NULL, &delba); - -	return; +	mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba);  }  /* diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h index 42f56903574..f3ca8c8c18f 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h @@ -49,14 +49,12 @@ void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv,  int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,  			       struct host_cmd_ds_command  			       *resp); -int mwifiex_cmd_11n_delba(struct mwifiex_private *priv, -			  struct host_cmd_ds_command *cmd, +int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd,  			  void *data_buf);  int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,  				  struct host_cmd_ds_command  				  *cmd, void *data_buf); -int mwifiex_cmd_11n_addba_req(struct mwifiex_private *priv, -			      struct host_cmd_ds_command *cmd, +int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd,  			      void *data_buf);  void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv);  struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct diff --git a/drivers/net/wireless/mwifiex/README b/drivers/net/wireless/mwifiex/README index 338377f7093..b55badef466 100644 --- a/drivers/net/wireless/mwifiex/README +++ b/drivers/net/wireless/mwifiex/README @@ -157,7 +157,7 @@ info  	mp_wr_bitmap = <SDIO multi-port write bitmap>  	cmd_resp_received = <0/1, no cmd response to process/response received and yet to process>  	event_received = <0/1, no event to process/event received and yet to process> -	ioctl_pending = <number of ioctl pending> +	cmd_pending = <number of cmd pending>  	tx_pending = <number of Tx packet pending>  	rx_pending = <number of Rx packet pending> diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index ec0895f4e8d..b99ae2677d7 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -34,22 +34,17 @@ static int  mwifiex_cfg80211_channel_type_to_mwifiex_channels(enum nl80211_channel_type  						  channel_type)  { -	int channel;  	switch (channel_type) {  	case NL80211_CHAN_NO_HT:  	case NL80211_CHAN_HT20: -		channel = NO_SEC_CHANNEL; -		break; +		return NO_SEC_CHANNEL;  	case NL80211_CHAN_HT40PLUS: -		channel = SEC_CHANNEL_ABOVE; -		break; +		return SEC_CHANNEL_ABOVE;  	case NL80211_CHAN_HT40MINUS: -		channel = SEC_CHANNEL_BELOW; -		break; +		return SEC_CHANNEL_BELOW;  	default: -		channel = NO_SEC_CHANNEL; +		return NO_SEC_CHANNEL;  	} -	return channel;  }  /* @@ -64,21 +59,16 @@ mwifiex_cfg80211_channel_type_to_mwifiex_channels(enum nl80211_channel_type  static enum nl80211_channel_type  mwifiex_channels_to_cfg80211_channel_type(int channel_type)  { -	int channel;  	switch (channel_type) {  	case NO_SEC_CHANNEL: -		channel = NL80211_CHAN_HT20; -		break; +		return NL80211_CHAN_HT20;  	case SEC_CHANNEL_ABOVE: -		channel = NL80211_CHAN_HT40PLUS; -		break; +		return NL80211_CHAN_HT40PLUS;  	case SEC_CHANNEL_BELOW: -		channel = NL80211_CHAN_HT40MINUS; -		break; +		return NL80211_CHAN_HT40MINUS;  	default: -		channel = NL80211_CHAN_HT20; +		return NL80211_CHAN_HT20;  	} -	return channel;  }  /* @@ -117,10 +107,8 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,  			 u8 key_index, bool pairwise, const u8 *mac_addr)  {  	struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); -	int ret = 0; -	ret = mwifiex_set_encode(priv, NULL, 0, key_index, 1); -	if (ret) { +	if (mwifiex_set_encode(priv, NULL, 0, key_index, 1)) {  		wiphy_err(wiphy, "deleting the crypto keys\n");  		return -EFAULT;  	} @@ -137,12 +125,17 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,  			      enum nl80211_tx_power_setting type,  			      int dbm)  { -	int ret = 0;  	struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); +	struct mwifiex_power_cfg power_cfg; -	ret = mwifiex_set_tx_power(priv, type, dbm); +	if (type == NL80211_TX_POWER_FIXED) { +		power_cfg.is_power_auto = 0; +		power_cfg.power_level = dbm; +	} else { +		power_cfg.is_power_auto = 1; +	} -	return ret; +	return mwifiex_set_tx_power(priv, &power_cfg);  }  /* @@ -155,17 +148,17 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,  				struct net_device *dev,  				bool enabled, int timeout)  { -	int ret = 0;  	struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); +	u32 ps_mode;  	if (timeout)  		wiphy_dbg(wiphy,  			"info: ignoring the timeout value"  			" for IEEE power save\n"); -	ret = mwifiex_drv_set_power(priv, enabled); +	ps_mode = enabled; -	return ret; +	return mwifiex_drv_set_power(priv, &ps_mode);  }  /* @@ -177,18 +170,15 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,  				 bool multicast)  {  	struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); -	int ret;  	/* Return if WEP key not configured */  	if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED)  		return 0; -	ret = mwifiex_set_encode(priv, NULL, 0, key_index, 0); - -	wiphy_dbg(wiphy, "info: set default Tx key index\n"); - -	if (ret) +	if (mwifiex_set_encode(priv, NULL, 0, key_index, 0)) { +		wiphy_err(wiphy, "set default Tx key index\n");  		return -EFAULT; +	}  	return 0;  } @@ -202,15 +192,12 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,  			 struct key_params *params)  {  	struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); -	int ret = 0; -	ret = mwifiex_set_encode(priv, params->key, params->key_len, -								key_index, 0); - -	wiphy_dbg(wiphy, "info: crypto keys added\n"); - -	if (ret) +	if (mwifiex_set_encode(priv, params->key, params->key_len, +							key_index, 0)) { +		wiphy_err(wiphy, "crypto keys added\n");  		return -EFAULT; +	}  	return 0;  } @@ -235,7 +222,6 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)  	struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);  	struct mwifiex_adapter *adapter = priv->adapter;  	struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg; -	int ret = 0;  	/* Set country code */  	domain_info->country_code[0] = priv->country_code[0]; @@ -290,13 +276,14 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)  	}  	domain_info->no_of_triplet = no_of_triplet; -	/* Send cmd to FW to set domain info */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, -				  HostCmd_ACT_GEN_SET, 0, NULL, NULL); -	if (ret) + +	if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, +				     HostCmd_ACT_GEN_SET, 0, NULL)) {  		wiphy_err(wiphy, "11D: setting domain info in FW\n"); +		return -1; +	} -	return ret; +	return 0;  }  /* @@ -346,8 +333,6 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv,  		       enum nl80211_channel_type channel_type)  {  	struct mwifiex_chan_freq_power cfp; -	int ret = 0; -	int status = 0;  	struct mwifiex_ds_band_cfg band_cfg;  	u32 config_bands = 0;  	struct wiphy *wiphy = priv->wdev->wiphy; @@ -366,15 +351,14 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv,  			band_cfg.config_bands = config_bands;  			band_cfg.adhoc_start_band = config_bands;  		} -		/* Set channel offset */ +  		band_cfg.sec_chan_offset =  			mwifiex_cfg80211_channel_type_to_mwifiex_channels  			(channel_type); -		status = mwifiex_radio_ioctl_band_cfg(priv, HostCmd_ACT_GEN_SET, -						      &band_cfg); -		if (status) +		if (mwifiex_set_radio_band_cfg(priv, &band_cfg))  			return -EFAULT; +  		mwifiex_send_domain_info_cmd_fw(wiphy);  	} @@ -382,20 +366,16 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv,  		"mode %d\n", config_bands, band_cfg.sec_chan_offset,  		priv->bss_mode);  	if (!chan) -		return ret; +		return 0;  	memset(&cfp, 0, sizeof(cfp));  	cfp.freq = chan->center_freq; -	/* Convert frequency to channel */  	cfp.channel = ieee80211_frequency_to_channel(chan->center_freq); -	status = mwifiex_bss_ioctl_channel(priv, HostCmd_ACT_GEN_SET, &cfp); -	if (status) +	if (mwifiex_bss_set_channel(priv, &cfp))  		return -EFAULT; -	ret = mwifiex_drv_change_adhoc_chan(priv, cfp.channel); - -	return ret; +	return mwifiex_drv_change_adhoc_chan(priv, cfp.channel);  }  /* @@ -422,67 +402,41 @@ mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,  /*   * This function sets the fragmentation threshold.   * - * This function creates an IOCTL request, populates it accordingly - * and issues an IOCTL. - * - * The fragmentation threshold value must lies between MWIFIEX_FRAG_MIN_VALUE + * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE   * and MWIFIEX_FRAG_MAX_VALUE.   */  static int  mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr)  {  	int ret = 0; -	int status = 0; -	struct mwifiex_wait_queue *wait = NULL; -	u8 wait_option = MWIFIEX_IOCTL_WAIT;  	if (frag_thr < MWIFIEX_FRAG_MIN_VALUE  	    || frag_thr > MWIFIEX_FRAG_MAX_VALUE)  		return -EINVAL; -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; - -	status = mwifiex_snmp_mib_ioctl(priv, wait, FRAG_THRESH_I, -					HostCmd_ACT_GEN_SET, &frag_thr); - -	if (mwifiex_request_ioctl(priv, wait, status, wait_option)) -		ret = -EFAULT; +	/* Send request to firmware */ +	ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, +				    HostCmd_ACT_GEN_SET, FRAG_THRESH_I, +				    &frag_thr); -	kfree(wait);  	return ret;  }  /*   * This function sets the RTS threshold. - * - * This function creates an IOCTL request, populates it accordingly - * and issues an IOCTL. + + * The rts value must lie between MWIFIEX_RTS_MIN_VALUE + * and MWIFIEX_RTS_MAX_VALUE.   */  static int  mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr)  { -	int ret = 0; -	struct mwifiex_wait_queue *wait = NULL; -	int status = 0; -	u8 wait_option = MWIFIEX_IOCTL_WAIT; -  	if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE)  		rts_thr = MWIFIEX_RTS_MAX_VALUE; -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; - -	status = mwifiex_snmp_mib_ioctl(priv, wait, RTS_THRESH_I, -					HostCmd_ACT_GEN_SET, &rts_thr); - -	if (mwifiex_request_ioctl(priv, wait, status, wait_option)) -		ret = -EFAULT; - -	kfree(wait); -	return ret; +	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, +				    HostCmd_ACT_GEN_SET, RTS_THRESH_I, +				    &rts_thr);  }  /* @@ -498,8 +452,11 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)  	int ret = 0; -	if (changed & WIPHY_PARAM_RTS_THRESHOLD) +	if (changed & WIPHY_PARAM_RTS_THRESHOLD) {  		ret = mwifiex_set_rts(priv, wiphy->rts_threshold); +		if (ret) +			return ret; +	}  	if (changed & WIPHY_PARAM_FRAG_THRESHOLD)  		ret = mwifiex_set_frag(priv, wiphy->frag_threshold); @@ -518,7 +475,6 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,  {  	int ret = 0;  	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); -	struct mwifiex_wait_queue *wait = NULL;  	if (priv->bss_mode == type) {  		wiphy_warn(wiphy, "already set to required type\n"); @@ -545,24 +501,13 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,  		return -EINVAL;  	} -	wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); -	if (!wait) -		return -ENOMEM; - -	mwifiex_deauthenticate(priv, wait, NULL); +	mwifiex_deauthenticate(priv, NULL);  	priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_SET_BSS_MODE, -				  HostCmd_ACT_GEN_SET, 0, wait, NULL); -	if (!ret) -		ret = -EINPROGRESS; - -	ret = mwifiex_request_ioctl(priv, wait, ret, MWIFIEX_IOCTL_WAIT); -	if (ret) -		ret = -EFAULT; +	ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE, +				    HostCmd_ACT_GEN_SET, 0, NULL); -	kfree(wait);  	return ret;  } @@ -592,7 +537,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,  	/* Get signal information from the firmware */  	memset(&signal, 0, sizeof(struct mwifiex_ds_get_signal)); -	if (mwifiex_get_signal_info(priv, MWIFIEX_IOCTL_WAIT, &signal)) { +	if (mwifiex_get_signal_info(priv, &signal)) {  		dev_err(priv->adapter->dev, "getting signal information\n");  		ret = -EFAULT;  	} @@ -623,7 +568,6 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,  			     u8 *mac, struct station_info *sinfo)  {  	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); -	int ret = 0;  	mwifiex_dump_station_info(priv, sinfo); @@ -632,10 +576,7 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,  	if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))  		return -ENOENT; - -	ret = mwifiex_dump_station_info(priv, sinfo); - -	return ret; +	return mwifiex_dump_station_info(priv, sinfo);  }  /* Supported rates to be advertised to the cfg80211 */ @@ -750,7 +691,7 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,  		return -EBUSY;  	priv->disconnect = 1; -	if (mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL)) +	if (mwifiex_deauthenticate(priv, NULL))  		return -EFAULT;  	wiphy_dbg(wiphy, "info: successfully disconnected from %pM:" @@ -774,15 +715,13 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,   */  static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)  { -	int ret = 0;  	struct ieee80211_channel *chan;  	struct mwifiex_bss_info bss_info;  	int ie_len = 0;  	u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; -	ret = mwifiex_get_bss_info(priv, &bss_info); -	if (ret) -		return ret; +	if (mwifiex_get_bss_info(priv, &bss_info)) +		return -1;  	ie_buf[0] = WLAN_EID_SSID;  	ie_buf[1] = bss_info.ssid.ssid_len; @@ -801,7 +740,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)  		0, ie_buf, ie_len, 0, GFP_KERNEL);  	memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); -	return ret; +	return 0;  }  /* @@ -830,16 +769,15 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,  	struct mwifiex_bssdescriptor *scan_table;  	int i, j;  	struct ieee80211_channel *chan; -	u8 *ie, *tmp, *ie_buf; +	u8 *ie, *ie_buf;  	u32 ie_len; -	u64 ts = 0;  	u8 *beacon;  	int beacon_size;  	u8 element_id, element_len;  	memset(&scan_resp, 0, sizeof(scan_resp)); -	if (mwifiex_get_scan_table(priv, MWIFIEX_IOCTL_WAIT, &scan_resp)) -		return -EFAULT; +	scan_resp.scan_table = (u8 *) priv->adapter->scan_table; +	scan_resp.num_in_scan_table = priv->adapter->num_in_scan_table;  #define MAX_IE_BUF	2048  	ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL); @@ -914,9 +852,9 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,  			case WLAN_EID_BSS_AC_ACCESS_DELAY:  				ie[0] = element_id;  				ie[1] = element_len; -				tmp = (u8 *) beacon;  				memcpy(&ie[sizeof(struct ieee_types_header)], -				       tmp + sizeof(struct ieee_types_header), +				       (u8 *) beacon +				       + sizeof(struct ieee_types_header),  				       element_len);  				ie_len += ie[1] +  					sizeof(struct ieee_types_header); @@ -933,7 +871,7 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,  						scan_table[i].freq);  		cfg80211_inform_bss(priv->wdev->wiphy, chan,  					scan_table[i].mac_address, -					ts, scan_table[i].cap_info_bitmap, +					0, scan_table[i].cap_info_bitmap,  					scan_table[i].beacon_period,  					ie_buf, ie_len,  					scan_table[i].rssi, GFP_KERNEL); @@ -966,9 +904,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,  	struct mwifiex_802_11_ssid req_ssid;  	struct mwifiex_ssid_bssid ssid_bssid;  	int ret = 0; -	int auth_type = 0, pairwise_encrypt_mode = 0; -	int group_encrypt_mode = 0; -	int alg_is_wep = 0; +	int auth_type = 0;  	memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid));  	memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); @@ -986,7 +922,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,  	}  	/* disconnect before try to associate */ -	mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL); +	mwifiex_deauthenticate(priv, NULL);  	if (channel)  		ret = mwifiex_set_rf_channel(priv, channel, @@ -1034,9 +970,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,  		ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);  	if (sme->key) { -		alg_is_wep = mwifiex_is_alg_wep(pairwise_encrypt_mode) -			| mwifiex_is_alg_wep(group_encrypt_mode); -		if (alg_is_wep) { +		if (mwifiex_is_alg_wep(0) | mwifiex_is_alg_wep(0)) {  			dev_dbg(priv->adapter->dev,  				"info: setting wep encryption"  				" with key len %d\n", sme->key_len); @@ -1046,7 +980,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,  	}  done:  	/* Do specific SSID scanning */ -	if (mwifiex_request_scan(priv, MWIFIEX_IOCTL_WAIT, &req_ssid)) { +	if (mwifiex_request_scan(priv, &req_ssid)) {  		dev_err(priv->adapter->dev, "scan error\n");  		return -EFAULT;  	} @@ -1055,8 +989,7 @@ done:  	memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid));  	if (mode != NL80211_IFTYPE_ADHOC) { -		if (mwifiex_find_best_bss(priv, MWIFIEX_IOCTL_WAIT, -					  &ssid_bssid)) +		if (mwifiex_find_best_bss(priv, &ssid_bssid))  			return -EFAULT;  		/* Inform the BSS information to kernel, otherwise  		 * kernel will give a panic after successful assoc */ @@ -1072,7 +1005,10 @@ done:  	/* Connect to BSS by ESSID */  	memset(&ssid_bssid.bssid, 0, ETH_ALEN); -	if (mwifiex_bss_start(priv, MWIFIEX_IOCTL_WAIT, &ssid_bssid)) +	if (!netif_queue_stopped(priv->netdev)) +		netif_stop_queue(priv->netdev); + +	if (mwifiex_bss_start(priv, &ssid_bssid))  		return -EFAULT;  	if (mode == NL80211_IFTYPE_ADHOC) { @@ -1176,7 +1112,7 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)  	wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n",  			priv->cfg_bssid); -	if (mwifiex_disconnect(priv, MWIFIEX_IOCTL_WAIT, NULL)) +	if (mwifiex_deauthenticate(priv, NULL))  		return -EFAULT;  	queue_work(priv->workqueue, &priv->cfg_workqueue); @@ -1451,6 +1387,4 @@ done:  		memset(priv->cfg_bssid, 0, ETH_ALEN);  		priv->disconnect = 0;  	} - -	return;  } diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c index 07187a405fe..d0cada5a29a 100644 --- a/drivers/net/wireless/mwifiex/cfp.c +++ b/drivers/net/wireless/mwifiex/cfp.c @@ -75,8 +75,7 @@ u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };   * This function maps an index in supported rates table into   * the corresponding data rate.   */ -u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index, -			       u8 ht_info) +u32 mwifiex_index_to_data_rate(u8 index, u8 ht_info)  {  	u16 mcs_rate[4][8] = {  		{0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e} @@ -126,7 +125,7 @@ u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index,   * This function maps a data rate value into corresponding index in supported   * rates table.   */ -u8 mwifiex_data_rate_to_index(struct mwifiex_adapter *adapter, u32 rate) +u8 mwifiex_data_rate_to_index(u32 rate)  {  	u16 *ptr; @@ -146,16 +145,12 @@ u8 mwifiex_data_rate_to_index(struct mwifiex_adapter *adapter, u32 rate)   */  u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates)  { -	u32 k; -  	if (!priv->media_connected) -		k = mwifiex_get_supported_rates(priv, rates); +		return mwifiex_get_supported_rates(priv, rates);  	else -		k = mwifiex_copy_rates(rates, 0, +		return mwifiex_copy_rates(rates, 0,  				       priv->curr_bss_params.data_rates,  				       priv->curr_bss_params.num_of_rates); - -	return k;  }  /* @@ -265,9 +260,7 @@ mwifiex_is_rate_auto(struct mwifiex_private *priv)  /*   * This function converts rate bitmap into rate index.   */ -int -mwifiex_get_rate_index(struct mwifiex_adapter *adapter, u16 *rate_bitmap, -		       int size) +int mwifiex_get_rate_index(u16 *rate_bitmap, int size)  {  	int i; diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index a9aeb31af45..776146a104e 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -36,11 +36,12 @@  static void  mwifiex_init_cmd_node(struct mwifiex_private *priv,  		      struct cmd_ctrl_node *cmd_node, -		      u32 cmd_oid, void *wait_queue, void *data_buf) +		      u32 cmd_oid, void *data_buf)  {  	cmd_node->priv = priv;  	cmd_node->cmd_oid = cmd_oid; -	cmd_node->wq_buf = wait_queue; +	cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required; +	priv->adapter->cmd_wait_q_required = false;  	cmd_node->data_buf = data_buf;  	cmd_node->cmd_skb = cmd_node->skb;  } @@ -86,39 +87,13 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,  {  	cmd_node->cmd_oid = 0;  	cmd_node->cmd_flag = 0; -	cmd_node->wq_buf = NULL;  	cmd_node->data_buf = NULL; +	cmd_node->wait_q_enabled = false;  	if (cmd_node->resp_skb) {  		mwifiex_recv_complete(adapter, cmd_node->resp_skb, 0);  		cmd_node->resp_skb = NULL;  	} - -	return; -} - -/* - * This function returns a command node from the pending queue which - * matches the given IOCTL request. - */ -static struct cmd_ctrl_node * -mwifiex_get_pending_ioctl_cmd(struct mwifiex_adapter *adapter, -			      struct mwifiex_wait_queue *wait_queue) -{ -	unsigned long flags; -	struct cmd_ctrl_node *cmd_node; - -	spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); -	list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) { -		if (cmd_node->wq_buf == wait_queue) { -			spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, -					       flags); -			return cmd_node; -		} -	} -	spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - -	return NULL;  }  /* @@ -155,7 +130,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,  	struct mwifiex_adapter *adapter = priv->adapter;  	int ret = 0;  	struct host_cmd_ds_command *host_cmd; -	struct mwifiex_wait_queue *wait_queue = NULL;  	uint16_t cmd_code;  	uint16_t cmd_size;  	struct timeval tstamp; @@ -165,15 +139,13 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,  		return -1;  	host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); -	if (cmd_node->wq_buf) -		wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf;  	/* Sanity test */  	if (host_cmd == NULL || host_cmd->size == 0) {  		dev_err(adapter->dev, "DNLD_CMD: host_cmd is null"  			" or cmd size is 0, not sending\n"); -		if (wait_queue) -			wait_queue->status = MWIFIEX_ERROR_CMD_DNLD_FAIL; +		if (cmd_node->wait_q_enabled) +			adapter->cmd_wait_q.status = -1;  		mwifiex_insert_cmd_to_free_q(adapter, cmd_node);  		return -1;  	} @@ -206,10 +178,12 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,  					     cmd_node->cmd_skb->data,  					     cmd_node->cmd_skb->len, NULL); +	skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN); +  	if (ret == -1) {  		dev_err(adapter->dev, "DNLD_CMD: host to card failed\n"); -		if (wait_queue) -			wait_queue->status = MWIFIEX_ERROR_CMD_DNLD_FAIL; +		if (cmd_node->wait_q_enabled) +			adapter->cmd_wait_q.status = -1;  		mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);  		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); @@ -435,7 +409,31 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)  }  /* - * This function prepares a command before sending it to the firmware. + * This function is used to send synchronous command to the firmware. + * + * it allocates a wait queue for the command and wait for the command + * response. + */ +int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, +			  u16 cmd_action, u32 cmd_oid, void *data_buf) +{ +	int ret = 0; +	struct mwifiex_adapter *adapter = priv->adapter; + +	adapter->cmd_wait_q_required = true; +	adapter->cmd_wait_q.condition = false; + +	ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, +				     data_buf); +	if (!ret) +		ret = mwifiex_wait_queue_complete(adapter); + +	return ret; +} + + +/* + * This function prepares a command and asynchronously send it to the firmware.   *   * Preparation includes -   *      - Sanity tests to make sure the card is still present or the FW @@ -445,9 +443,8 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)   *      - Fill up the non-default parameters and buffer pointers   *      - Add the command to pending queue   */ -int mwifiex_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, -			u16 cmd_action, u32 cmd_oid, -			void *wait_queue, void *data_buf) +int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, +			   u16 cmd_action, u32 cmd_oid, void *data_buf)  {  	int ret = 0;  	struct mwifiex_adapter *adapter = priv->adapter; @@ -485,7 +482,7 @@ int mwifiex_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,  	}  	/* Initialize the command node */ -	mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, wait_queue, data_buf); +	mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf);  	if (!cmd_node->cmd_skb) {  		dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n"); @@ -535,18 +532,13 @@ void  mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,  			     struct cmd_ctrl_node *cmd_node)  { -	struct mwifiex_wait_queue *wait_queue = NULL;  	unsigned long flags; -	if (cmd_node == NULL) +	if (!cmd_node)  		return; -	if (cmd_node->wq_buf) { -		wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf; -		if (wait_queue->status != MWIFIEX_ERROR_NO_ERROR) -			mwifiex_ioctl_complete(adapter, wait_queue, -1); -		else -			mwifiex_ioctl_complete(adapter, wait_queue, 0); -	} + +	if (cmd_node->wait_q_enabled) +		mwifiex_complete_cmd(adapter);  	/* Clean the node */  	mwifiex_clean_cmd_node(adapter, cmd_node); @@ -554,8 +546,6 @@ mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,  	spin_lock_irqsave(&adapter->cmd_free_q_lock, flags);  	list_add_tail(&cmd_node->list, &adapter->cmd_free_q);  	spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); - -	return;  }  /* @@ -600,8 +590,6 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter,  	spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);  	dev_dbg(adapter->dev, "cmd: QUEUE_CMD: cmd=%#x is queued\n", command); - -	return;  }  /* @@ -692,7 +680,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)  	uint16_t orig_cmdresp_no;  	uint16_t cmdresp_no;  	uint16_t cmdresp_result; -	struct mwifiex_wait_queue *wait_queue = NULL;  	struct timeval tstamp;  	unsigned long flags; @@ -706,10 +693,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)  		return -1;  	} -	if (adapter->curr_cmd->wq_buf) -		wait_queue = (struct mwifiex_wait_queue *) -				adapter->curr_cmd->wq_buf; -  	adapter->num_cmd_timeout = 0;  	resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; @@ -764,8 +747,8 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)  	if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {  		dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n"); -		if (wait_queue) -			wait_queue->status = MWIFIEX_ERROR_FW_CMDRESP; +		if (adapter->curr_cmd->wait_q_enabled) +			adapter->cmd_wait_q.status = -1;  		mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);  		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); @@ -781,8 +764,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)  			ret = mwifiex_ret_802_11_hs_cfg(priv, resp);  	} else {  		/* handle response */ -		ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp, -						  wait_queue); +		ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp);  	}  	/* Check init command response */ @@ -797,10 +779,10 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)  	}  	if (adapter->curr_cmd) { -		if (wait_queue && (!ret)) -			wait_queue->status = MWIFIEX_ERROR_NO_ERROR; -		else if (wait_queue && (ret == -1)) -			wait_queue->status = MWIFIEX_ERROR_CMD_RESP_FAIL; +		if (adapter->curr_cmd->wait_q_enabled && (!ret)) +			adapter->cmd_wait_q.status = 0; +		else if (adapter->curr_cmd->wait_q_enabled && (ret == -1)) +			adapter->cmd_wait_q.status = -1;  		/* Clean up and put current command back to cmd_free_q */  		mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); @@ -824,7 +806,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)  	struct mwifiex_adapter *adapter =  		(struct mwifiex_adapter *) function_context;  	struct cmd_ctrl_node *cmd_node = NULL; -	struct mwifiex_wait_queue *wait_queue = NULL;  	struct timeval tstamp;  	adapter->num_cmd_timeout++; @@ -834,10 +815,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context)  		return;  	}  	cmd_node = adapter->curr_cmd; -	if (cmd_node->wq_buf) { -		wait_queue = (struct mwifiex_wait_queue *) cmd_node->wq_buf; -		wait_queue->status = MWIFIEX_ERROR_CMD_TIMEOUT; -	} +	if (cmd_node->wait_q_enabled) +		adapter->cmd_wait_q.status = -ETIMEDOUT;  	if (cmd_node) {  		adapter->dbg.timeout_cmd_id = @@ -886,8 +865,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)  	}  	if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)  		mwifiex_init_fw_complete(adapter); - -	return;  }  /* @@ -901,18 +878,15 @@ void  mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)  {  	struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; -	struct mwifiex_wait_queue *wait_queue = NULL;  	unsigned long flags;  	/* Cancel current cmd */ -	if ((adapter->curr_cmd) && (adapter->curr_cmd->wq_buf)) { -		wait_queue = -			(struct mwifiex_wait_queue *) adapter->curr_cmd->wq_buf; +	if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) {  		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); -		adapter->curr_cmd->wq_buf = NULL; +		adapter->curr_cmd->wait_q_enabled = false;  		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -		wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; -		mwifiex_ioctl_complete(adapter, wait_queue, -1); +		adapter->cmd_wait_q.status = -1; +		mwifiex_complete_cmd(adapter);  	}  	/* Cancel all pending command */  	spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); @@ -921,12 +895,10 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)  		list_del(&cmd_node->list);  		spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); -		if (cmd_node->wq_buf) { -			wait_queue = -				(struct mwifiex_wait_queue *) cmd_node->wq_buf; -			wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; -			mwifiex_ioctl_complete(adapter, wait_queue, -1); -			cmd_node->wq_buf = NULL; +		if (cmd_node->wait_q_enabled) { +			adapter->cmd_wait_q.status = -1; +			mwifiex_complete_cmd(adapter); +			cmd_node->wait_q_enabled = false;  		}  		mwifiex_insert_cmd_to_free_q(adapter, cmd_node);  		spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); @@ -940,7 +912,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)  		list_del(&cmd_node->list);  		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); -		cmd_node->wq_buf = NULL; +		cmd_node->wait_q_enabled = false;  		mwifiex_insert_cmd_to_free_q(adapter, cmd_node);  		spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);  	} @@ -962,8 +934,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)   * are cancelled.   */  void -mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter, -			     struct mwifiex_wait_queue *wait_queue) +mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)  {  	struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;  	unsigned long cmd_flags; @@ -972,45 +943,33 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter,  	uint16_t cancel_scan_cmd = false;  	if ((adapter->curr_cmd) && -	    (adapter->curr_cmd->wq_buf == wait_queue)) { +	     (adapter->curr_cmd->wait_q_enabled)) {  		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);  		cmd_node = adapter->curr_cmd; -		cmd_node->wq_buf = NULL; +		cmd_node->wait_q_enabled = false;  		cmd_node->cmd_flag |= CMD_F_CANCELED; -		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); -	} - -	spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); -	while (1) { -		cmd_node = mwifiex_get_pending_ioctl_cmd(adapter, wait_queue); -		if (!cmd_node) -			break; -  		spin_lock_irqsave(&adapter->cmd_pending_q_lock,  				  cmd_pending_q_flags);  		list_del(&cmd_node->list);  		spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,  				       cmd_pending_q_flags); - -		cmd_node->wq_buf = NULL;  		mwifiex_insert_cmd_to_free_q(adapter, cmd_node); +		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);  	} -	spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); +  	/* Cancel all pending scan command */  	spin_lock_irqsave(&adapter->scan_pending_q_lock,  			  scan_pending_q_flags);  	list_for_each_entry_safe(cmd_node, tmp_node,  				 &adapter->scan_pending_q, list) { -		if (cmd_node->wq_buf == wait_queue) { -			list_del(&cmd_node->list); -			spin_unlock_irqrestore(&adapter->scan_pending_q_lock, -					       scan_pending_q_flags); -			cmd_node->wq_buf = NULL; -			mwifiex_insert_cmd_to_free_q(adapter, cmd_node); -			spin_lock_irqsave(&adapter->scan_pending_q_lock, -					  scan_pending_q_flags); -			cancel_scan_cmd = true; -		} +		list_del(&cmd_node->list); +		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, +				       scan_pending_q_flags); +		cmd_node->wait_q_enabled = false; +		mwifiex_insert_cmd_to_free_q(adapter, cmd_node); +		spin_lock_irqsave(&adapter->scan_pending_q_lock, +				  scan_pending_q_flags); +		cancel_scan_cmd = true;  	}  	spin_unlock_irqrestore(&adapter->scan_pending_q_lock,  			       scan_pending_q_flags); @@ -1020,10 +979,8 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter,  		adapter->scan_processing = false;  		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);  	} -	wait_queue->status = MWIFIEX_ERROR_CMD_CANCEL; -	mwifiex_ioctl_complete(adapter, wait_queue, -1); - -	return; +	adapter->cmd_wait_q.status = -1; +	mwifiex_complete_cmd(adapter);  }  /* @@ -1127,7 +1084,6 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter)  	adapter->is_hs_configured = false;  	mwifiex_hs_activated_event(mwifiex_get_priv(adapter,  				   MWIFIEX_BSS_ROLE_ANY), false); -	return;  }  /* diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 63b09692f27..7ddcb062f10 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -129,8 +129,8 @@ static struct mwifiex_debug_data items[] = {  	 item_addr(event_received), 1},  	/* variables defined in struct mwifiex_adapter */ -	{"ioctl_pending", adapter_item_size(ioctl_pending), -	 adapter_item_addr(ioctl_pending), 1}, +	{"cmd_pending", adapter_item_size(cmd_pending), +	 adapter_item_addr(cmd_pending), 1},  	{"tx_pending", adapter_item_size(tx_pending),  	 adapter_item_addr(tx_pending), 1},  	{"rx_pending", adapter_item_size(rx_pending), @@ -735,8 +735,6 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv)  	MWIFIEX_DFS_ADD_FILE(getlog);  	MWIFIEX_DFS_ADD_FILE(regrdwr);  	MWIFIEX_DFS_ADD_FILE(rdeeprom); - -	return;  }  /* @@ -749,7 +747,6 @@ mwifiex_dev_debugfs_remove(struct mwifiex_private *priv)  		return;  	debugfs_remove_recursive(priv->dfs_dev_dir); -	return;  }  /* diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index c3c15f9e757..0e90b0986ed 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -61,23 +61,6 @@  #define MWIFIEX_BUF_FLAG_REQUEUED_PKT      BIT(0) -enum mwifiex_error_code { -	MWIFIEX_ERROR_NO_ERROR = 0, -	MWIFIEX_ERROR_FW_NOT_READY = 0x00000001, -	MWIFIEX_ERROR_FW_BUSY, -	MWIFIEX_ERROR_FW_CMDRESP, -	MWIFIEX_ERROR_PKT_SIZE_INVALID = 0x80000001, -	MWIFIEX_ERROR_PKT_TIMEOUT, -	MWIFIEX_ERROR_CMD_INVALID, -	MWIFIEX_ERROR_CMD_TIMEOUT, -	MWIFIEX_ERROR_CMD_DNLD_FAIL, -	MWIFIEX_ERROR_CMD_CANCEL, -	MWIFIEX_ERROR_CMD_RESP_FAIL, -	MWIFIEX_ERROR_ASSOC_FAIL, -	MWIFIEX_ERROR_EVENT_UNKNOWN, -	MWIFIEX_ERROR_INVALID_PARAMETER, -}; -  enum mwifiex_bss_type {  	MWIFIEX_BSS_TYPE_STA = 0,  	MWIFIEX_BSS_TYPE_UAP = 1, @@ -112,12 +95,9 @@ struct mwifiex_802_11_ssid {  };  struct mwifiex_wait_queue { -	u32 bss_index; -	wait_queue_head_t *wait; -	u16 *condition; -	u32 start_time; +	wait_queue_head_t wait; +	u16 condition;  	int status; -	u32 enabled;  };  struct mwifiex_rxinfo { @@ -133,11 +113,11 @@ struct mwifiex_txinfo {  };  struct mwifiex_bss_attr { -	u32 bss_type; -	u32 frame_type; -	u32 active; -	u32 bss_priority; -	u32 bss_num; +	u8 bss_type; +	u8 frame_type; +	u8 active; +	u8 bss_priority; +	u8 bss_num;  };  enum mwifiex_wmm_ac_e { @@ -146,8 +126,4 @@ enum mwifiex_wmm_ac_e {  	WMM_AC_VI,  	WMM_AC_VO  } __packed; - -struct mwifiex_device { -	struct mwifiex_bss_attr bss_attr[MWIFIEX_MAX_BSS_NUM]; -};  #endif /* !_MWIFIEX_DECL_H_ */ diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 2b938115b26..6d1c4545eda 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -72,33 +72,12 @@ enum KEY_TYPE_ID {  	KEY_TYPE_ID_AES,  	KEY_TYPE_ID_WAPI,  }; - -enum KEY_INFO_WEP { -	KEY_INFO_WEP_MCAST = 0x01, -	KEY_INFO_WEP_UNICAST = 0x02, -	KEY_INFO_WEP_ENABLED = 0x04 -}; - -enum KEY_INFO_TKIP { -	KEY_INFO_TKIP_MCAST = 0x01, -	KEY_INFO_TKIP_UNICAST = 0x02, -	KEY_INFO_TKIP_ENABLED = 0x04 -}; - -enum KEY_INFO_AES { -	KEY_INFO_AES_MCAST = 0x01, -	KEY_INFO_AES_UNICAST = 0x02, -	KEY_INFO_AES_ENABLED = 0x04 -}; +#define KEY_MCAST	BIT(0) +#define KEY_UNICAST	BIT(1) +#define KEY_ENABLED	BIT(2)  #define WAPI_KEY_LEN			50 -enum KEY_INFO_WAPI { -	KEY_INFO_WAPI_MCAST = 0x01, -	KEY_INFO_WAPI_UNICAST = 0x02, -	KEY_INFO_WAPI_ENABLED = 0x04 -}; -  #define MAX_POLL_TRIES			100  #define MAX_MULTI_INTERFACE_POLL_TRIES  1000 @@ -155,7 +134,6 @@ enum MWIFIEX_802_11_WEP_STATUS {  #define MWIFIEX_TX_DATA_BUF_SIZE_4K        4096  #define MWIFIEX_TX_DATA_BUF_SIZE_8K        8192 -#define NON_GREENFIELD_STAS     0x04  #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) @@ -180,7 +158,6 @@ enum MWIFIEX_802_11_WEP_STATUS {  #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29))  #define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f) -#define RESETHT_EXTCAP_RDG(HTExtCap) (HTExtCap &= ~BIT(11))  #define SETHT_MCS32(x) (x[4] |= 1)  #define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4)) diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 8189862da1f..fc2c0c5728d 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -35,7 +35,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)  {  	struct mwifiex_adapter *adapter = priv->adapter;  	struct mwifiex_bss_prio_node *bss_prio; -	int status = 0;  	unsigned long flags;  	bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL); @@ -59,7 +58,7 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)  	spin_unlock_irqrestore(&adapter->bss_prio_tbl[priv->bss_priority]  			.bss_prio_lock, flags); -	return status; +	return 0;  }  /* @@ -72,7 +71,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)  static int mwifiex_init_priv(struct mwifiex_private *priv)  {  	u32 i; -	int ret = 0;  	priv->media_connected = false;  	memset(priv->curr_addr, 0xff, ETH_ALEN); @@ -140,9 +138,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)  	priv->scan_block = false; -	ret = mwifiex_add_bss_prio_tbl(priv); - -	return ret; +	return mwifiex_add_bss_prio_tbl(priv);  }  /* @@ -300,8 +296,6 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)  	adapter->adhoc_awake_period = 0;  	memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));  	adapter->arp_filter_size = 0; - -	return;  }  /* @@ -340,8 +334,6 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter)  	adapter->if_ops.cleanup_if(adapter);  	dev_kfree_skb_any(adapter->sleep_cfm); - -	return;  }  /* @@ -429,8 +421,6 @@ void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)  			list_del(&priv->rx_reorder_tbl_ptr);  		}  	} - -	return;  }  /* diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 703a6d12ebf..5488e111fd2 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -268,14 +268,13 @@ struct mwifiex_debug_info {  };  #define MWIFIEX_KEY_INDEX_UNICAST	0x40000000 -#define MWIFIEX_MAX_KEY_LENGTH		32  #define WAPI_RXPN_LEN			16  struct mwifiex_ds_encrypt_key {  	u32 key_disable;  	u32 key_index;  	u32 key_len; -	u8 key_material[MWIFIEX_MAX_KEY_LENGTH]; +	u8 key_material[WLAN_MAX_KEY_LEN];  	u8 mac_addr[ETH_ALEN];  	u32 is_wapi_key;  	u8 wapi_rxpn[WAPI_RXPN_LEN]; diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 7a9e0b5962e..23d2d0b9a52 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -590,11 +590,10 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,   * an association success (0) or failure (non-zero).   */  int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, -			     struct host_cmd_ds_command *resp, void *wq_buf) +			     struct host_cmd_ds_command *resp)  { +	struct mwifiex_adapter *adapter = priv->adapter;  	int ret = 0; -	struct mwifiex_wait_queue *wait_queue = -		(struct mwifiex_wait_queue *) wq_buf;  	struct ieee_types_assoc_rsp *assoc_rsp;  	struct mwifiex_bssdescriptor *bss_desc;  	u8 enable_data = true; @@ -718,16 +717,11 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,  done:  	/* Need to indicate IOCTL complete */ -	if (wait_queue) { -		if (ret) { -			if (assoc_rsp->status_code) -				wait_queue->status = -					le16_to_cpu(assoc_rsp->status_code); -			else -				wait_queue->status = MWIFIEX_ERROR_ASSOC_FAIL; -		} else { -			wait_queue->status = MWIFIEX_ERROR_NO_ERROR; -		} +	if (adapter->curr_cmd->wait_q_enabled) { +		if (ret) +			adapter->cmd_wait_q.status = -1; +		else +			adapter->cmd_wait_q.status = 0;  	}  	return ret; @@ -755,7 +749,7 @@ int  mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,  				struct host_cmd_ds_command *cmd, void *data_buf)  { -	int ret = 0, rsn_ie_len = 0; +	int rsn_ie_len = 0;  	struct mwifiex_adapter *adapter = priv->adapter;  	struct host_cmd_ds_802_11_ad_hoc_start *adhoc_start =  		&cmd->params.adhoc_start; @@ -885,11 +879,9 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,  	mwifiex_get_active_data_rates(priv, adhoc_start->DataRate);  	if ((adapter->adhoc_start_band & BAND_G) &&  	    (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) { -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, -					  HostCmd_ACT_GEN_SET, -					  0, NULL, &priv->curr_pkt_filter); - -		if (ret) { +		if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, +					     HostCmd_ACT_GEN_SET, 0, +					     &priv->curr_pkt_filter)) {  			dev_err(adapter->dev,  			       "ADHOC_S_CMD: G Protection config failed\n");  			return -1; @@ -1003,7 +995,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,  					IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;  			}  			ht_info->ht_info.operation_mode = -				cpu_to_le16(NON_GREENFIELD_STAS); +			     cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);  			ht_info->ht_info.basic_set[0] = 0xff;  			pos += sizeof(struct mwifiex_ie_types_htinfo);  			cmd_append_size += @@ -1045,7 +1037,7 @@ int  mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,  			       struct host_cmd_ds_command *cmd, void *data_buf)  { -	int ret = 0, rsn_ie_len = 0; +	int rsn_ie_len = 0;  	struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join =  		&cmd->params.adhoc_join;  	struct mwifiex_bssdescriptor *bss_desc = @@ -1066,10 +1058,9 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,  			priv->  			curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, -					  HostCmd_ACT_GEN_SET, 0, NULL, -					  &curr_pkt_filter); -		if (ret) { +		if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, +					     HostCmd_ACT_GEN_SET, 0, +					     &curr_pkt_filter)) {  			dev_err(priv->adapter->dev,  			       "ADHOC_J_CMD: G Protection config failed\n");  			return -1; @@ -1180,7 +1171,7 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,  	adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap); -	return ret; +	return 0;  }  /* @@ -1192,22 +1183,19 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,   * saves the beacon buffer.   */  int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, -			      struct host_cmd_ds_command *resp, void *wq_buf) +			      struct host_cmd_ds_command *resp)  {  	int ret = 0; -	struct mwifiex_wait_queue *wait_queue = -		(struct mwifiex_wait_queue *) wq_buf; +	struct mwifiex_adapter *adapter = priv->adapter;  	struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result;  	struct mwifiex_bssdescriptor *bss_desc; -	u16 command = le16_to_cpu(resp->command); -	u16 result = le16_to_cpu(resp->result);  	adhoc_result = &resp->params.adhoc_result;  	bss_desc = priv->attempted_bss_desc;  	/* Join result code 0 --> SUCCESS */ -	if (result) { +	if (le16_to_cpu(resp->result)) {  		dev_err(priv->adapter->dev, "ADHOC_RESP: failed\n");  		if (priv->media_connected)  			mwifiex_reset_connect_state(priv); @@ -1222,7 +1210,7 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,  	/* Send a Media Connected event, according to the Spec */  	priv->media_connected = true; -	if (command == HostCmd_CMD_802_11_AD_HOC_START) { +	if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) {  		dev_dbg(priv->adapter->dev, "info: ADHOC_S_RESP %s\n",  				bss_desc->ssid.ssid); @@ -1264,11 +1252,11 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,  done:  	/* Need to indicate IOCTL complete */ -	if (wait_queue) { +	if (adapter->curr_cmd->wait_q_enabled) {  		if (ret) -			wait_queue->status = MWIFIEX_ERROR_ASSOC_FAIL; +			adapter->cmd_wait_q.status = -1;  		else -			wait_queue->status = MWIFIEX_ERROR_NO_ERROR; +			adapter->cmd_wait_q.status = 0;  	} @@ -1283,9 +1271,8 @@ done:   * command to firmware.   */  int mwifiex_associate(struct mwifiex_private *priv, -		      void *wait_queue, struct mwifiex_bssdescriptor *bss_desc) +		      struct mwifiex_bssdescriptor *bss_desc)  { -	int ret = 0;  	u8 current_bssid[ETH_ALEN];  	/* Return error if the adapter or table entry is not marked as infra */ @@ -1301,11 +1288,8 @@ int mwifiex_associate(struct mwifiex_private *priv,  	   retrieval */  	priv->assoc_rsp_size = 0; -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE, -				  HostCmd_ACT_GEN_SET, 0, wait_queue, -				  bss_desc); - -	return ret; +	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_ASSOCIATE, +				    HostCmd_ACT_GEN_SET, 0, bss_desc);  }  /* @@ -1315,10 +1299,8 @@ int mwifiex_associate(struct mwifiex_private *priv,   */  int  mwifiex_adhoc_start(struct mwifiex_private *priv, -		    void *wait_queue, struct mwifiex_802_11_ssid *adhoc_ssid) +		    struct mwifiex_802_11_ssid *adhoc_ssid)  { -	int ret = 0; -  	dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n",  		priv->adhoc_channel);  	dev_dbg(priv->adapter->dev, "info: curr_bss_params.channel = %d\n", @@ -1326,11 +1308,8 @@ mwifiex_adhoc_start(struct mwifiex_private *priv,  	dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %d\n",  	       priv->curr_bss_params.band); -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START, -				  HostCmd_ACT_GEN_SET, 0, wait_queue, -				  adhoc_ssid); - -	return ret; +	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START, +				    HostCmd_ACT_GEN_SET, 0, adhoc_ssid);  }  /* @@ -1340,10 +1319,8 @@ mwifiex_adhoc_start(struct mwifiex_private *priv,   * if already not connected to the requested SSID.   */  int mwifiex_adhoc_join(struct mwifiex_private *priv, -		       void *wait_queue, struct mwifiex_bssdescriptor *bss_desc) +		       struct mwifiex_bssdescriptor *bss_desc)  { -	int ret = 0; -  	dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid =%s\n",  	       priv->curr_bss_params.bss_descriptor.ssid.ssid);  	dev_dbg(priv->adapter->dev, "info: adhoc join: curr_bss ssid_len =%u\n", @@ -1369,20 +1346,15 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,  	dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n",  	       priv->curr_bss_params.band); -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, -				  HostCmd_ACT_GEN_SET, 0, wait_queue, -				  bss_desc); - -	return ret; +	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, +				    HostCmd_ACT_GEN_SET, 0, bss_desc);  }  /*   * This function deauthenticates/disconnects from infra network by sending   * deauthentication request.   */ -static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, -					struct mwifiex_wait_queue *wait, -					u8 *mac) +static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac)  {  	u8 mac_address[ETH_ALEN];  	int ret = 0; @@ -1400,11 +1372,8 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv,  		       bss_descriptor.mac_address, ETH_ALEN);  	} -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, -				  HostCmd_ACT_GEN_SET, 0, wait, &mac_address); - -	if (!ret && wait) -		ret = -EINPROGRESS; +	ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, +				    HostCmd_ACT_GEN_SET, 0, &mac_address);  	return ret;  } @@ -1415,26 +1384,23 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv,   * In case of infra made, it sends deauthentication request, and   * in case of ad-hoc mode, a stop network request is sent to the firmware.   */ -int mwifiex_deauthenticate(struct mwifiex_private *priv, -			   struct mwifiex_wait_queue *wait, u8 *mac) +int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)  {  	int ret = 0;  	if (priv->media_connected) {  		if (priv->bss_mode == NL80211_IFTYPE_STATION) { -			ret = mwifiex_deauthenticate_infra(priv, wait, mac); +			ret = mwifiex_deauthenticate_infra(priv, mac);  		} else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { -			ret = mwifiex_prepare_cmd(priv, -					HostCmd_CMD_802_11_AD_HOC_STOP, -					HostCmd_ACT_GEN_SET, 0, wait, NULL); - -			if (!ret && wait) -				ret = -EINPROGRESS; +			ret = mwifiex_send_cmd_sync(priv, +						HostCmd_CMD_802_11_AD_HOC_STOP, +						HostCmd_ACT_GEN_SET, 0, NULL);  		}  	}  	return ret;  } +EXPORT_SYMBOL_GPL(mwifiex_deauthenticate);  /*   * This function converts band to radio type used in channel TLV. @@ -1442,21 +1408,15 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv,  u8  mwifiex_band_to_radio_type(u8 band)  { -	u8 ret_radio_type; -  	switch (band) {  	case BAND_A:  	case BAND_AN:  	case BAND_A | BAND_AN: -		ret_radio_type = HostCmd_SCAN_RADIO_TYPE_A; -		break; +		return HostCmd_SCAN_RADIO_TYPE_A;  	case BAND_B:  	case BAND_G:  	case BAND_B | BAND_G:  	default: -		ret_radio_type = HostCmd_SCAN_RADIO_TYPE_BG; -		break; +		return HostCmd_SCAN_RADIO_TYPE_BG;  	} - -	return ret_radio_type;  } diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index ed89ca41a90..c5971880e7b 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -40,14 +40,10 @@ static char fw_name[32] = DEFAULT_FW_NAME;  /* Supported drv_mode table */  static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {  	{ -	 /* drv_mode */ -	 .drv_mode = DRV_MODE_STA, -	 /* intf number */ -	 .intf_num = ARRAY_SIZE(mwifiex_bss_sta), -	 /* bss_attr */ -	 .bss_attr = mwifiex_bss_sta, -	 } -	, +		.drv_mode = DRV_MODE_STA, +		.intf_num = ARRAY_SIZE(mwifiex_bss_sta), +		.bss_attr = mwifiex_bss_sta, +	},  };  /* @@ -66,14 +62,12 @@ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {   * proper cleanup before exiting.   */  static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, -			    struct mwifiex_device *mdevice, void **padapter) +			    struct mwifiex_drv_mode *drv_mode_ptr)  { -	int ret = 0; -	struct mwifiex_adapter *adapter = NULL; -	u8 i = 0; +	struct mwifiex_adapter *adapter; +	int i;  	adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL); -	/* Allocate memory for adapter structure */  	if (!adapter)  		return -1; @@ -84,19 +78,17 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,  	memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops));  	/* card specific initialization has been deferred until now .. */ -	ret = adapter->if_ops.init_if(adapter); -	if (ret) +	if (adapter->if_ops.init_if(adapter))  		goto error;  	adapter->priv_num = 0; -	for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) { +	for (i = 0; i < drv_mode_ptr->intf_num; i++) {  		adapter->priv[i] = NULL; -		if (!mdevice->bss_attr[i].active) +		if (!drv_mode_ptr->bss_attr[i].active)  			continue; -		/* For valid bss_attr, -		   allocate memory for private structure */ +		/* Allocate memory for private structure */  		adapter->priv[i] = kzalloc(sizeof(struct mwifiex_private),  				GFP_KERNEL);  		if (!adapter->priv[i]) { @@ -106,26 +98,26 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,  		}  		adapter->priv_num++; -		memset(adapter->priv[i], 0, -		       sizeof(struct mwifiex_private));  		adapter->priv[i]->adapter = adapter;  		/* Save bss_type, frame_type & bss_priority */ -		adapter->priv[i]->bss_type = (u8) mdevice->bss_attr[i].bss_type; +		adapter->priv[i]->bss_type = drv_mode_ptr->bss_attr[i].bss_type;  		adapter->priv[i]->frame_type = -			(u8) mdevice->bss_attr[i].frame_type; +					drv_mode_ptr->bss_attr[i].frame_type;  		adapter->priv[i]->bss_priority = -			(u8) mdevice->bss_attr[i].bss_priority; -		if (mdevice->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA) +					drv_mode_ptr->bss_attr[i].bss_priority; + +		if (drv_mode_ptr->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA)  			adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_STA; -		else if (mdevice->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_UAP) +		else if (drv_mode_ptr->bss_attr[i].bss_type == +							MWIFIEX_BSS_TYPE_UAP)  			adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_UAP;  		/* Save bss_index & bss_num */  		adapter->priv[i]->bss_index = i; -		adapter->priv[i]->bss_num = mdevice->bss_attr[i].bss_num; +		adapter->priv[i]->bss_num = drv_mode_ptr->bss_attr[i].bss_num;  	} +	adapter->drv_mode = drv_mode_ptr; -	/* Initialize lock variables */  	if (mwifiex_init_lock_list(adapter))  		goto error; @@ -133,16 +125,13 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,  	adapter->cmd_timer.function = mwifiex_cmd_timeout_func;  	adapter->cmd_timer.data = (unsigned long) adapter; -	/* Return pointer of struct mwifiex_adapter */ -	*padapter = adapter;  	return 0;  error:  	dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n"); -	/* Free lock variables */  	mwifiex_free_lock_list(adapter); -	for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) +	for (i = 0; i < drv_mode_ptr->intf_num; i++)  		kfree(adapter->priv[i]);  	kfree(adapter); @@ -337,10 +326,9 @@ exit_main_proc:   * and initializing the private structures.   */  static int -mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **pmwifiex) +mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops)  {  	int i; -	struct mwifiex_device device;  	struct mwifiex_drv_mode *drv_mode_ptr;  	/* find mwifiex_drv_mode entry from mwifiex_drv_mode_tbl */ @@ -357,20 +345,7 @@ mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **pmwifiex)  		return -1;  	} -	memset(&device, 0, sizeof(struct mwifiex_device)); - -	for (i = 0; i < drv_mode_ptr->intf_num; i++) { -		device.bss_attr[i].bss_type = -			drv_mode_ptr->bss_attr[i].bss_type; -		device.bss_attr[i].frame_type = -			drv_mode_ptr->bss_attr[i].frame_type; -		device.bss_attr[i].active = drv_mode_ptr->bss_attr[i].active; -		device.bss_attr[i].bss_priority = -			drv_mode_ptr->bss_attr[i].bss_priority; -		device.bss_attr[i].bss_num = drv_mode_ptr->bss_attr[i].bss_num; -	} - -	if (mwifiex_register(card, if_ops, &device, pmwifiex)) +	if (mwifiex_register(card, if_ops, drv_mode_ptr))  		return -1;  	return 0; @@ -505,7 +480,6 @@ mwifiex_fill_buffer(struct sk_buff *skb)  	 */  	do_gettimeofday(&tv);  	skb->tstamp = timeval_to_ktime(tv); -	return;  }  /* @@ -597,16 +571,23 @@ mwifiex_set_mac_address(struct net_device *dev, void *addr)  {  	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);  	struct sockaddr *hw_addr = (struct sockaddr *) addr; +	int ret = 0;  	memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); -	if (mwifiex_request_set_mac_address(priv)) { -		dev_err(priv->adapter->dev, "set MAC address failed\n"); -		return -EFAULT; -	} +	/* Send request to firmware */ +	ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_MAC_ADDRESS, +				    HostCmd_ACT_GEN_SET, 0, NULL); + +	if (!ret) +		memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN); +	else +		dev_err(priv->adapter->dev, "set mac address failed: ret=%d" +					    "\n", ret); +  	memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); -	return 0; +	return ret;  }  /* @@ -615,7 +596,20 @@ mwifiex_set_mac_address(struct net_device *dev, void *addr)  static void mwifiex_set_multicast_list(struct net_device *dev)  {  	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); -	mwifiex_request_set_multicast_list(priv, dev); +	struct mwifiex_multicast_list mcast_list; + +	if (dev->flags & IFF_PROMISC) { +		mcast_list.mode = MWIFIEX_PROMISC_MODE; +	} else if (dev->flags & IFF_ALLMULTI || +		   netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) { +		mcast_list.mode = MWIFIEX_ALL_MULTI_MODE; +	} else { +		mcast_list.mode = MWIFIEX_MULTICAST_MODE; +		if (netdev_mc_count(dev)) +			mcast_list.num_multicast_addr = +				mwifiex_copy_mcast_addr(&mcast_list, dev); +	} +	mwifiex_request_set_multicast_list(priv, &mcast_list);  }  /* @@ -677,9 +671,6 @@ mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev)  {  	dev->netdev_ops = &mwifiex_netdev_ops;  	/* Initialize private structure */ -	init_waitqueue_head(&priv->ioctl_wait_q); -	init_waitqueue_head(&priv->cmd_wait_q); -	init_waitqueue_head(&priv->w_stats_wait_q);  	priv->current_key_index = 0;  	priv->media_connected = false;  	memset(&priv->nick_name, 0, sizeof(priv->nick_name)); @@ -803,37 +794,9 @@ mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index)  	wiphy_unregister(priv->wdev->wiphy);  	wiphy_free(priv->wdev->wiphy);  	kfree(priv->wdev); - -	return;  }  /* - * Sends IOCTL request to shutdown firmware. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_shutdown_fw(struct mwifiex_private *priv, u8 wait_option) -{ -	struct mwifiex_wait_queue *wait = NULL; -	int status = 0; - -	/* Allocate an IOCTL request buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; - -	status = mwifiex_misc_ioctl_init_shutdown(priv->adapter, wait, -						  MWIFIEX_FUNC_SHUTDOWN); - -	status = mwifiex_request_ioctl(priv, wait, status, wait_option); - -	kfree(wait); -	return status; -} -EXPORT_SYMBOL_GPL(mwifiex_shutdown_fw); - -/*   * This function check if command is pending.   */  int is_command_pending(struct mwifiex_adapter *adapter) @@ -905,30 +868,30 @@ int  mwifiex_add_card(void *card, struct semaphore *sem,  		 struct mwifiex_if_ops *if_ops)  { -	int status = 0;  	int i; -	struct mwifiex_adapter *adapter = NULL; -	struct mwifiex_drv_mode *drv_mode_info = &mwifiex_drv_mode_tbl[0]; +	struct mwifiex_adapter *adapter;  	if (down_interruptible(sem))  		goto exit_sem_err; -	if (mwifiex_init_sw(card, if_ops, (void **) &adapter)) { +	if (mwifiex_init_sw(card, if_ops)) {  		pr_err("%s: software init failed\n", __func__);  		goto err_init_sw;  	} -	adapter->drv_mode = drv_mode_info; +	adapter = g_adapter;  	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; -	/* PnP and power profile */  	adapter->surprise_removed = false;  	init_waitqueue_head(&adapter->init_wait_q);  	adapter->is_suspended = false;  	adapter->hs_activated = false;  	init_waitqueue_head(&adapter->hs_activate_wait_q); +	adapter->cmd_wait_q_required = false; +	init_waitqueue_head(&adapter->cmd_wait_q.wait); +	adapter->cmd_wait_q.condition = false; +	adapter->cmd_wait_q.status = 0; -	/* Create workqueue */  	adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE");  	if (!adapter->workqueue)  		goto err_kmalloc; @@ -942,21 +905,18 @@ mwifiex_add_card(void *card, struct semaphore *sem,  		goto err_registerdev;  	} -	/* Init FW and HW */  	if (mwifiex_init_hw_fw(adapter)) {  		pr_err("%s: firmware init failed\n", __func__);  		goto err_init_fw;  	} +  	/* Add interfaces */ -	for (i = 0; i < drv_mode_info->intf_num; i++) { +	for (i = 0; i < adapter->drv_mode->intf_num; i++) {  		if (!mwifiex_add_interface(adapter, i,  				adapter->drv_mode->bss_attr[i].bss_type)) { -			status = -1; -			break; +			goto err_add_intf;  		}  	} -	if (status) -		goto err_add_intf;  	up(sem); @@ -966,7 +926,6 @@ err_add_intf:  	for (i = 0; i < adapter->priv_num; i++)  		mwifiex_remove_interface(adapter, i);  err_init_fw: -	/* Unregister device */  	pr_debug("info: %s: unregister device\n", __func__);  	adapter->if_ops.unregister_dev(adapter);  err_registerdev: @@ -977,8 +936,8 @@ err_kmalloc:  	    (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) {  		pr_debug("info: %s: shutdown mwifiex\n", __func__);  		adapter->init_wait_q_woken = false; -		status = mwifiex_shutdown_drv(adapter); -		if (status == -EINPROGRESS) + +		if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)  			wait_event_interruptible(adapter->init_wait_q,  						 adapter->init_wait_q_woken);  	} @@ -1007,7 +966,6 @@ EXPORT_SYMBOL_GPL(mwifiex_add_card);  int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)  {  	struct mwifiex_private *priv = NULL; -	int status;  	int i;  	if (down_interruptible(sem)) @@ -1031,19 +989,19 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)  	dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n");  	adapter->init_wait_q_woken = false; -	status = mwifiex_shutdown_drv(adapter); -	if (status == -EINPROGRESS) + +	if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)  		wait_event_interruptible(adapter->init_wait_q,  					 adapter->init_wait_q_woken);  	dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n");  	if (atomic_read(&adapter->rx_pending) ||  	    atomic_read(&adapter->tx_pending) || -	    atomic_read(&adapter->ioctl_pending)) { +	    atomic_read(&adapter->cmd_pending)) {  		dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, " -		       "ioctl_pending=%d\n", +		       "cmd_pending=%d\n",  		       atomic_read(&adapter->rx_pending),  		       atomic_read(&adapter->tx_pending), -		       atomic_read(&adapter->ioctl_pending)); +		       atomic_read(&adapter->cmd_pending));  	}  	/* Remove interface */ diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 43ff149de9d..1b503038270 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -42,11 +42,8 @@ extern const char driver_version[];  extern struct mwifiex_adapter *g_adapter;  enum { -	MWIFIEX_NO_WAIT, -	MWIFIEX_IOCTL_WAIT, -	MWIFIEX_CMD_WAIT, -	MWIFIEX_PROC_WAIT, -	MWIFIEX_WSTATS_WAIT +	MWIFIEX_ASYNC_CMD, +	MWIFIEX_SYNC_CMD  };  #define DRV_MODE_STA       0x1 @@ -468,10 +465,6 @@ struct mwifiex_private {  	u32 curr_bcn_size;  	/* spin lock for beacon buffer */  	spinlock_t curr_bcn_buf_lock; -	u16 ioctl_wait_q_woken; -	wait_queue_head_t ioctl_wait_q; -	u16 cmd_wait_q_woken; -	wait_queue_head_t cmd_wait_q;  	struct wireless_dev *wdev;  	struct mwifiex_chan_freq_power cfp;  	char version_str[128]; @@ -480,8 +473,6 @@ struct mwifiex_private {  #endif  	u8 nick_name[16];  	struct iw_statistics w_stats; -	u16 w_stats_wait_q_woken; -	wait_queue_head_t w_stats_wait_q;  	u16 current_key_index;  	struct semaphore async_sem;  	u8 scan_pending_on_block; @@ -552,7 +543,7 @@ struct cmd_ctrl_node {  	struct sk_buff *cmd_skb;  	struct sk_buff *resp_skb;  	void *data_buf; -	void *wq_buf; +	u32 wait_q_enabled;  	struct sk_buff *skb;  }; @@ -590,7 +581,7 @@ struct mwifiex_adapter {  	struct mwifiex_if_ops if_ops;  	atomic_t rx_pending;  	atomic_t tx_pending; -	atomic_t ioctl_pending; +	atomic_t cmd_pending;  	struct workqueue_struct *workqueue;  	struct work_struct main_work;  	struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM]; @@ -684,6 +675,8 @@ struct mwifiex_adapter {  	struct mwifiex_dbg dbg;  	u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE];  	u32 arp_filter_size; +	u16 cmd_wait_q_required; +	struct mwifiex_wait_queue cmd_wait_q;  };  int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); @@ -707,29 +700,23 @@ int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb);  int mwifiex_process_event(struct mwifiex_adapter *adapter); -int mwifiex_ioctl_complete(struct mwifiex_adapter *adapter, -			   struct mwifiex_wait_queue *ioctl_wq, -			   int status); +int mwifiex_complete_cmd(struct mwifiex_adapter *adapter); -int mwifiex_prepare_cmd(struct mwifiex_private *priv, -			uint16_t cmd_no, -			u16 cmd_action, -			u32 cmd_oid, -			void *wait_queue, void *data_buf); +int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, +			   u16 cmd_action, u32 cmd_oid, void *data_buf); + +int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, +			  u16 cmd_action, u32 cmd_oid, void *data_buf);  void mwifiex_cmd_timeout_func(unsigned long function_context); -int mwifiex_misc_ioctl_init_shutdown(struct mwifiex_adapter *adapter, -				     struct mwifiex_wait_queue *wait_queue, -				     u32 func_init_shutdown);  int mwifiex_get_debug_info(struct mwifiex_private *,  			   struct mwifiex_debug_info *);  int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter);  int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter);  void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter); -void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter, -				  struct mwifiex_wait_queue *ioctl_wq); +void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter);  void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter,  				  struct cmd_ctrl_node *cmd_node); @@ -772,24 +759,20 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,  			    u16 cmd_action, u32 cmd_oid,  			    void *data_buf, void *cmd_buf);  int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, -				void *cmd_buf, void *ioctl); +				void *cmd_buf);  int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,  				  struct sk_buff *skb);  int mwifiex_process_sta_event(struct mwifiex_private *);  void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);  int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta); -int mwifiex_scan_networks(struct mwifiex_private *priv, void *wait_queue, -			  u16 action, -			  const struct mwifiex_user_scan_cfg -			  *user_scan_in, struct mwifiex_scan_resp *); -int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv, -			    struct host_cmd_ds_command *cmd, +int mwifiex_scan_networks(struct mwifiex_private *priv, +			  const struct mwifiex_user_scan_cfg *user_scan_in); +int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,  			    void *data_buf);  void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,  			    struct cmd_ctrl_node *cmd_node);  int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, -			    struct host_cmd_ds_command *resp, -			    void *wait_queue); +			    struct host_cmd_ds_command *resp);  s32 mwifiex_find_ssid_in_list(struct mwifiex_private *priv,  				struct mwifiex_802_11_ssid *ssid, u8 *bssid,  				u32 mode); @@ -799,23 +782,20 @@ int mwifiex_find_best_network(struct mwifiex_private *priv,  			      struct mwifiex_ssid_bssid *req_ssid_bssid);  s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,  		       struct mwifiex_802_11_ssid *ssid2); -int mwifiex_associate(struct mwifiex_private *priv, void *wait_queue, +int mwifiex_associate(struct mwifiex_private *priv,  		      struct mwifiex_bssdescriptor *bss_desc);  int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,  				 struct host_cmd_ds_command  				 *cmd, void *data_buf);  int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, -				 struct host_cmd_ds_command *resp, -				 void *wait_queue); +				 struct host_cmd_ds_command *resp);  void mwifiex_reset_connect_state(struct mwifiex_private *priv);  void mwifiex_2040_coex_event(struct mwifiex_private *priv);  u8 mwifiex_band_to_radio_type(u8 band); -int mwifiex_deauthenticate(struct mwifiex_private *priv, -			   struct mwifiex_wait_queue *wait_queue, -			   u8 *mac); -int mwifiex_adhoc_start(struct mwifiex_private *priv, void *wait_queue, +int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac); +int mwifiex_adhoc_start(struct mwifiex_private *priv,  			struct mwifiex_802_11_ssid *adhoc_ssid); -int mwifiex_adhoc_join(struct mwifiex_private *priv, void *wait_queue, +int mwifiex_adhoc_join(struct mwifiex_private *priv,  		       struct mwifiex_bssdescriptor *bss_desc);  int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,  				    struct host_cmd_ds_command *cmd, @@ -824,11 +804,8 @@ int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,  				   struct host_cmd_ds_command *cmd,  				   void *data_buf);  int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, -			      struct host_cmd_ds_command *resp, -			      void *wait_queue); -int mwifiex_cmd_802_11_bg_scan_query(struct mwifiex_private *priv, -				     struct host_cmd_ds_command *cmd, -				     void *data_buf); +			      struct host_cmd_ds_command *resp); +int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd);  struct mwifiex_chan_freq_power *  			mwifiex_get_cfp_by_band_and_channel_from_cfg80211(  						struct mwifiex_private *priv, @@ -836,20 +813,16 @@ struct mwifiex_chan_freq_power *  struct mwifiex_chan_freq_power *mwifiex_get_cfp_by_band_and_freq_from_cfg80211(  						struct mwifiex_private *priv,  						u8 band, u32 freq); -u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index, -				 u8 ht_info); +u32 mwifiex_index_to_data_rate(u8 index, u8 ht_info);  u32 mwifiex_find_freq_from_band_chan(u8, u8);  int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask,  				u8 **buffer); -u32 mwifiex_index_to_data_rate(struct mwifiex_adapter *adapter, u8 index, -				 u8 ht_info);  u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv,  				    u8 *rates);  u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates); -u8 mwifiex_data_rate_to_index(struct mwifiex_adapter *adapter, u32 rate); +u8 mwifiex_data_rate_to_index(u32 rate);  u8 mwifiex_is_rate_auto(struct mwifiex_private *priv); -int mwifiex_get_rate_index(struct mwifiex_adapter *adapter, -			   u16 *rateBitmap, int size); +int mwifiex_get_rate_index(u16 *rateBitmap, int size);  extern u16 region_code_index[MWIFIEX_MAX_REGION_CODE];  void mwifiex_save_curr_bcn(struct mwifiex_private *priv);  void mwifiex_free_curr_bcn(struct mwifiex_private *priv); @@ -899,7 +872,7 @@ mwifiex_copy_rates(u8 *dest, u32 pos, u8 *src, int len)   */  static inline struct mwifiex_private *  mwifiex_get_priv_by_id(struct mwifiex_adapter *adapter, -		       u32 bss_num, u32 bss_type) +		       u8 bss_num, u8 bss_type)  {  	int i; @@ -943,52 +916,34 @@ mwifiex_netdev_get_priv(struct net_device *dev)  	return (struct mwifiex_private *) (*(unsigned long *) netdev_priv(dev));  } -struct mwifiex_wait_queue *mwifiex_alloc_fill_wait_queue( -				struct mwifiex_private *, -				u8 wait_option);  struct mwifiex_private *mwifiex_bss_index_to_priv(struct mwifiex_adapter  						*adapter, u8 bss_index); -int mwifiex_shutdown_fw(struct mwifiex_private *, u8); - +int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, +			     u32 func_init_shutdown);  int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *);  int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *);  void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version,  			 int maxlen); -int mwifiex_request_set_mac_address(struct mwifiex_private *priv); -void mwifiex_request_set_multicast_list(struct mwifiex_private *priv, -					struct net_device *dev); -int mwifiex_request_ioctl(struct mwifiex_private *priv, -			  struct mwifiex_wait_queue *req, -			  int, u8 wait_option); -int mwifiex_disconnect(struct mwifiex_private *, u8, u8 *); +int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, +			struct mwifiex_multicast_list *mcast_list); +int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, +			    struct net_device *dev); +int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);  int mwifiex_bss_start(struct mwifiex_private *priv, -		      u8 wait_option,  		      struct mwifiex_ssid_bssid *ssid_bssid);  int mwifiex_set_hs_params(struct mwifiex_private *priv, -			      u16 action, u8 wait_option, +			      u16 action, int cmd_type,  			      struct mwifiex_ds_hs_cfg *hscfg); -int mwifiex_cancel_hs(struct mwifiex_private *priv, u8 wait_option); +int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);  int mwifiex_enable_hs(struct mwifiex_adapter *adapter); -void mwifiex_process_ioctl_resp(struct mwifiex_private *priv, -				struct mwifiex_wait_queue *req); -u32 mwifiex_get_mode(struct mwifiex_private *priv, u8 wait_option);  int mwifiex_get_signal_info(struct mwifiex_private *priv, -			    u8 wait_option,  			    struct mwifiex_ds_get_signal *signal);  int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,  			      struct mwifiex_rate_cfg *rate); -int mwifiex_get_channel_list(struct mwifiex_private *priv, -			     u8 wait_option, -			     struct mwifiex_chan_list *chanlist); -int mwifiex_get_scan_table(struct mwifiex_private *priv, -			   u8 wait_option, -			   struct mwifiex_scan_resp *scanresp); -int mwifiex_enable_wep_key(struct mwifiex_private *priv, u8 wait_option); -int mwifiex_find_best_bss(struct mwifiex_private *priv, u8 wait_option, +int mwifiex_find_best_bss(struct mwifiex_private *priv,  			  struct mwifiex_ssid_bssid *ssid_bssid);  int mwifiex_request_scan(struct mwifiex_private *priv, -			 u8 wait_option,  			 struct mwifiex_802_11_ssid *req_ssid);  int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,  				struct mwifiex_user_scan_cfg *scan_req); @@ -1024,27 +979,22 @@ int mwifiex_set_tx_rate_cfg(struct mwifiex_private *priv, int tx_rate_index);  int mwifiex_get_tx_rate_cfg(struct mwifiex_private *priv, int *tx_rate_index); -int mwifiex_drv_set_power(struct mwifiex_private *priv, bool power_on); +int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode);  int mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter,  				   char *version, int max_len); -int mwifiex_set_tx_power(struct mwifiex_private *priv, int type, int dbm); +int mwifiex_set_tx_power(struct mwifiex_private *priv, +			 struct mwifiex_power_cfg *power_cfg);  int mwifiex_main_process(struct mwifiex_adapter *); -int mwifiex_bss_ioctl_channel(struct mwifiex_private *, -			      u16 action, -			      struct mwifiex_chan_freq_power *cfp); +int mwifiex_bss_set_channel(struct mwifiex_private *, +			    struct mwifiex_chan_freq_power *cfp);  int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *, -			       struct mwifiex_wait_queue *,  			       struct mwifiex_ssid_bssid *); -int mwifiex_radio_ioctl_band_cfg(struct mwifiex_private *, -				 u16 action, -				 struct mwifiex_ds_band_cfg *); -int mwifiex_snmp_mib_ioctl(struct mwifiex_private *, -			   struct mwifiex_wait_queue *, -			   u32 cmd_oid, u16 action, u32 *value); +int mwifiex_set_radio_band_cfg(struct mwifiex_private *, +			 struct mwifiex_ds_band_cfg *);  int mwifiex_get_bss_info(struct mwifiex_private *,  			 struct mwifiex_bss_info *); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 6bb52d0e6cf..68d905d5860 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -178,35 +178,27 @@ mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,   * with requisite parameters and calls the IOCTL handler.   */  int mwifiex_find_best_bss(struct mwifiex_private *priv, -			  u8 wait_option, struct mwifiex_ssid_bssid *ssid_bssid) +			  struct mwifiex_ssid_bssid *ssid_bssid)  { -	struct mwifiex_wait_queue *wait = NULL;  	struct mwifiex_ssid_bssid tmp_ssid_bssid; -	int ret = 0;  	u8 *mac = NULL;  	if (!ssid_bssid)  		return -1; -	/* Allocate wait request buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; -  	memcpy(&tmp_ssid_bssid, ssid_bssid,  	       sizeof(struct mwifiex_ssid_bssid)); -	ret = mwifiex_bss_ioctl_find_bss(priv, wait, &tmp_ssid_bssid); -	if (!ret) { +	if (!mwifiex_bss_ioctl_find_bss(priv, &tmp_ssid_bssid)) {  		memcpy(ssid_bssid, &tmp_ssid_bssid,  		       sizeof(struct mwifiex_ssid_bssid));  		mac = (u8 *) &ssid_bssid->bssid;  		dev_dbg(priv->adapter->dev, "cmd: found network: ssid=%s,"  				" %pM\n", ssid_bssid->ssid.ssid, mac); +		return 0;  	} -	kfree(wait); -	return ret; +	return -1;  }  /* @@ -221,22 +213,14 @@ int mwifiex_find_best_bss(struct mwifiex_private *priv,  int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,  				struct mwifiex_user_scan_cfg *scan_req)  { -	struct mwifiex_wait_queue *wait = NULL;  	int status = 0; -	u8 wait_option = MWIFIEX_IOCTL_WAIT; -	/* Allocate an IOCTL request buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; +	priv->adapter->cmd_wait_q.condition = false; -	status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_SET, -				       scan_req, NULL); +	status = mwifiex_scan_networks(priv, scan_req); +	if (!status) +		status = mwifiex_wait_queue_complete(priv->adapter); -	status = mwifiex_request_ioctl(priv, wait, status, wait_option); - -	if (wait && (status != -EINPROGRESS)) -		kfree(wait);  	return status;  } @@ -674,7 +658,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,   * along with the other TLVs, to the firmware.   */  static int -mwifiex_scan_channel_list(struct mwifiex_private *priv, void *wait_buf, +mwifiex_scan_channel_list(struct mwifiex_private *priv,  			  u32 max_chan_per_scan, u8 filtered_scan,  			  struct mwifiex_scan_cmd_config *scan_cfg_out,  			  struct mwifiex_ie_types_chan_list_param_set @@ -808,9 +792,9 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, void *wait_buf,  		/* Send the scan command to the firmware with the specified  		   cfg */ -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN, -					  HostCmd_ACT_GEN_SET, -					  0, wait_buf, scan_cfg_out); +		ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SCAN, +					     HostCmd_ACT_GEN_SET, 0, +					     scan_cfg_out);  		if (ret)  			break;  	} @@ -2076,19 +2060,13 @@ mwifiex_process_scan_results(struct mwifiex_private *priv)  static u8  mwifiex_radio_type_to_band(u8 radio_type)  { -	u8 ret_band; -  	switch (radio_type) {  	case HostCmd_SCAN_RADIO_TYPE_A: -		ret_band = BAND_A; -		break; +		return BAND_A;  	case HostCmd_SCAN_RADIO_TYPE_BG:  	default: -		ret_band = BAND_G; -		break; +		return BAND_G;  	} - -	return ret_band;  }  /* @@ -2241,8 +2219,7 @@ static int  mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,  				     struct mwifiex_802_11_ssid *del_ssid)  { -	int ret = -1; -	s32 table_idx; +	s32 table_idx = -1;  	dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n",  			del_ssid->ssid); @@ -2255,11 +2232,10 @@ mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,  		dev_dbg(priv->adapter->dev,  			"info: Scan: Delete SSID Entry: Found Idx = %d\n",  		       table_idx); -		ret = 0;  		mwifiex_scan_delete_table_entry(priv, table_idx);  	} -	return ret; +	return table_idx == -1 ? -1 : 0;  }  /* @@ -2271,9 +2247,7 @@ mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,   * update the internal driver scan table.   */  int mwifiex_scan_networks(struct mwifiex_private *priv, -			  void *wait_buf, u16 action, -			  const struct mwifiex_user_scan_cfg *user_scan_in, -			  struct mwifiex_scan_resp *scan_resp) +			  const struct mwifiex_user_scan_cfg *user_scan_in)  {  	int ret = 0;  	struct mwifiex_adapter *adapter = priv->adapter; @@ -2288,18 +2262,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,  	u8 max_chan_per_scan;  	unsigned long flags; -	if (action == HostCmd_ACT_GEN_GET) { -		if (scan_resp) { -			scan_resp->scan_table = (u8 *) adapter->scan_table; -			scan_resp->num_in_scan_table = -				adapter->num_in_scan_table; -		} else { -			ret = -1; -		} -		return ret; -	} - -	if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) { +	if (adapter->scan_processing) {  		dev_dbg(adapter->dev, "cmd: Scan already in process...\n");  		return ret;  	} @@ -2308,7 +2271,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,  	adapter->scan_processing = true;  	spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -	if (priv->scan_block && action == HostCmd_ACT_GEN_SET) { +	if (priv->scan_block) {  		dev_dbg(adapter->dev,  			"cmd: Scan is blocked during association...\n");  		return ret; @@ -2348,9 +2311,9 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,  		adapter->bcn_buf_end = adapter->bcn_buf;  	} -	ret = mwifiex_scan_channel_list(priv, wait_buf, max_chan_per_scan, -					filtered_scan, &scan_cfg_out->config, -					chan_list_out, scan_chan_list); +	ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan, +					&scan_cfg_out->config, chan_list_out, +					scan_chan_list);  	/* Get scan command from scan_pending_q and put to cmd_pending_q */  	if (!ret) { @@ -2367,7 +2330,6 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,  			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,  					       flags);  		} -		ret = -EINPROGRESS;  	} else {  		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);  		adapter->scan_processing = true; @@ -2393,8 +2355,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,   *      - Setting command ID, and proper size   *      - Ensuring correct endian-ness   */ -int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv, -			    struct host_cmd_ds_command *cmd, void *data_buf) +int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf)  {  	struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;  	struct mwifiex_scan_cmd_config *scan_cfg; @@ -2437,11 +2398,10 @@ int mwifiex_cmd_802_11_scan(struct mwifiex_private *priv,   *      .-------------------------------------------------------------.   */  int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, -			    struct host_cmd_ds_command *resp, void *wq_buf) +			    struct host_cmd_ds_command *resp)  {  	int ret = 0;  	struct mwifiex_adapter *adapter = priv->adapter; -	struct mwifiex_wait_queue *wait_queue = NULL;  	struct cmd_ctrl_node *cmd_node = NULL;  	struct host_cmd_ds_802_11_scan_rsp *scan_rsp = NULL;  	struct mwifiex_bssdescriptor *bss_new_entry = NULL; @@ -2653,13 +2613,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,  		mwifiex_process_scan_results(priv);  		/* Need to indicate IOCTL complete */ -		wait_queue = (struct mwifiex_wait_queue *) wq_buf; -		if (wait_queue) { -			wait_queue->status = MWIFIEX_ERROR_NO_ERROR; - -			/* Indicate ioctl complete */ -			mwifiex_ioctl_complete(adapter, -			       (struct mwifiex_wait_queue *) wait_queue, 0); +		if (adapter->curr_cmd->wait_q_enabled) { +			adapter->cmd_wait_q.status = 0; +			mwifiex_complete_cmd(adapter);  		}  		if (priv->report_scan_result)  			priv->report_scan_result = false; @@ -2692,9 +2648,7 @@ done:   *      - Setting background scan flush parameter   *      - Ensuring correct endian-ness   */ -int mwifiex_cmd_802_11_bg_scan_query(struct mwifiex_private *priv, -				     struct host_cmd_ds_command *cmd, -				     void *data_buf) +int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)  {  	struct host_cmd_ds_802_11_bg_scan_query *bg_query =  		&cmd->params.bg_scan_query; @@ -2853,6 +2807,7 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv,  	struct mwifiex_adapter *adapter = priv->adapter;  	unsigned long flags; +	cmd_node->wait_q_enabled = true;  	spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);  	list_add_tail(&cmd_node->list, &adapter->scan_pending_q);  	spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); @@ -2899,9 +2854,7 @@ int mwifiex_find_best_network(struct mwifiex_private *priv,   * firmware, filtered on a specific SSID.   */  static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, -				      void *wait_buf, u16 action, -				      struct mwifiex_802_11_ssid *req_ssid, -				      struct mwifiex_scan_resp *scan_resp) +				      struct mwifiex_802_11_ssid *req_ssid)  {  	struct mwifiex_adapter *adapter = priv->adapter;  	int ret = 0; @@ -2910,24 +2863,12 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,  	if (!req_ssid)  		return -1; -	if (action == HostCmd_ACT_GEN_GET) { -		if (scan_resp) { -			scan_resp->scan_table = -				(u8 *) &priv->curr_bss_params.bss_descriptor; -			scan_resp->num_in_scan_table = -				adapter->num_in_scan_table; -		} else { -			ret = -1; -		} -		return ret; -	} - -	if (adapter->scan_processing && action == HostCmd_ACT_GEN_SET) { +	if (adapter->scan_processing) {  		dev_dbg(adapter->dev, "cmd: Scan already in process...\n");  		return ret;  	} -	if (priv->scan_block && action == HostCmd_ACT_GEN_SET) { +	if (priv->scan_block) {  		dev_dbg(adapter->dev,  			"cmd: Scan is blocked during association...\n");  		return ret; @@ -2945,7 +2886,7 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,  	       req_ssid->ssid_len);  	scan_cfg->keep_previous_scan = true; -	ret = mwifiex_scan_networks(priv, wait_buf, action, scan_cfg, NULL); +	ret = mwifiex_scan_networks(priv, scan_cfg);  	kfree(scan_cfg);  	return ret; @@ -2960,12 +2901,10 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,   * Scan command can be issued for both normal scan and specific SSID   * scan, depending upon whether an SSID is provided or not.   */ -int mwifiex_request_scan(struct mwifiex_private *priv, u8 wait_option, +int mwifiex_request_scan(struct mwifiex_private *priv,  			 struct mwifiex_802_11_ssid *req_ssid)  {  	int ret = 0; -	struct mwifiex_wait_queue *wait = NULL; -	int status = 0;  	if (down_interruptible(&priv->async_sem)) {  		dev_err(priv->adapter->dev, "%s: acquire semaphore\n", @@ -2974,32 +2913,23 @@ int mwifiex_request_scan(struct mwifiex_private *priv, u8 wait_option,  	}  	priv->scan_pending_on_block = true; -	/* Allocate wait request buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) { -		ret = -1; -		goto done; -	} +	priv->adapter->cmd_wait_q.condition = false;  	if (req_ssid && req_ssid->ssid_len != 0)  		/* Specific SSID scan */ -		status = mwifiex_scan_specific_ssid(priv, wait, -						    HostCmd_ACT_GEN_SET, -						    req_ssid, NULL); +		ret = mwifiex_scan_specific_ssid(priv, req_ssid);  	else  		/* Normal scan */ -		status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_SET, -					       NULL, NULL); -	status = mwifiex_request_ioctl(priv, wait, status, wait_option); -	if (status == -1) -		ret = -1; -done: -	if ((wait) && (status != -EINPROGRESS)) -		kfree(wait); +		ret = mwifiex_scan_networks(priv, NULL); + +	if (!ret) +		ret = mwifiex_wait_queue_complete(priv->adapter); +  	if (ret == -1) {  		priv->scan_pending_on_block = false;  		up(&priv->async_sem);  	} +  	return ret;  } diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index f21e5cd1983..5148d0e0fad 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -208,7 +208,7 @@ static int mwifiex_sdio_resume(struct device *dev)  	/* Disable Host Sleep */  	mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), -			      MWIFIEX_NO_WAIT); +			  MWIFIEX_ASYNC_CMD);  	return 0;  } @@ -282,7 +282,7 @@ mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u32 *data)   */  static int  mwifiex_write_data_sync(struct mwifiex_adapter *adapter, -			u8 *buffer, u32 pkt_len, u32 port, u32 timeout) +			u8 *buffer, u32 pkt_len, u32 port)  {  	struct sdio_mmc_card *card = adapter->card;  	int ret = -1; @@ -314,9 +314,8 @@ mwifiex_write_data_sync(struct mwifiex_adapter *adapter,  /*   * This function reads multiple data from SDIO card memory.   */ -static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, -				  u8 *buffer, u32 len, -		       u32 port, u32 timeout, u8 claim) +static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer, +				  u32 len, u32 port, u8 claim)  {  	struct sdio_mmc_card *card = adapter->card;  	int ret = -1; @@ -348,12 +347,9 @@ static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter,   */  static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)  { -	int ret; -  	dev_dbg(adapter->dev, "event: wakeup device...\n"); -	ret = mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP); -	return ret; +	return mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP);  }  /* @@ -363,12 +359,9 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)   */  static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)  { -	int ret; -  	dev_dbg(adapter->dev, "cmd: wakeup device completed\n"); -	ret = mwifiex_write_reg(adapter, CONFIGURATION_REG, 0); -	return ret; +	return mwifiex_write_reg(adapter, CONFIGURATION_REG, 0);  }  /* @@ -430,8 +423,7 @@ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter,  	int ret = 0;  	do { -		ret = mwifiex_write_data_sync(adapter, payload, pkt_len, -								port, 0); +		ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port);  		if (ret) {  			i++;  			dev_err(adapter->dev, "host_to_card, write iomem" @@ -630,7 +622,7 @@ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter,  		return -1;  	} -	ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 0, 1); +	ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 1);  	if (ret) {  		dev_err(adapter->dev, "%s: read iomem failed: %d\n", __func__, @@ -769,7 +761,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,  		ret = mwifiex_write_data_sync(adapter, fwbuf, tx_blocks *  					      MWIFIEX_SDIO_BLOCK_SIZE, -					      adapter->ioport, 0); +					      adapter->ioport);  		if (ret) {  			dev_err(adapter->dev, "FW download, write iomem (%d)"  					" failed @ %d\n", i, offset); @@ -842,7 +834,7 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)  	unsigned long flags;  	if (mwifiex_read_data_sync(adapter, card->mp_regs, MAX_MP_REGS, -				   REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0, +				   REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK,  				   0)) {  		dev_err(adapter->dev, "read mp_regs failed\n");  		return; @@ -859,8 +851,6 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)  		adapter->int_status |= sdio_ireg;  		spin_unlock_irqrestore(&adapter->int_lock, flags);  	} - -	return;  }  /* @@ -891,8 +881,6 @@ mwifiex_sdio_interrupt(struct sdio_func *func)  	mwifiex_interrupt_status(adapter);  	queue_work(adapter->workqueue, &adapter->main_work); - -	return;  }  /* @@ -1054,7 +1042,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,  					   card->mpa_rx.buf_len,  					   (adapter->ioport | 0x1000 |  					    (card->mpa_rx.ports << 4)) + -					   card->mpa_rx.start_port, 0, 1)) +					   card->mpa_rx.start_port, 1))  			return -1;  		curr_ptr = card->mpa_rx.buf; @@ -1709,13 +1697,9 @@ static struct mwifiex_if_ops sdio_ops = {  static int  mwifiex_sdio_init_module(void)  { -	int ret; -  	sema_init(&add_remove_card_sem, 1); -	ret = sdio_register_driver(&mwifiex_sdio); - -	return ret; +	return sdio_register_driver(&mwifiex_sdio);  }  /* @@ -1745,13 +1729,12 @@ mwifiex_sdio_cleanup_module(void)  	for (i = 0; i < adapter->priv_num; i++)  		if ((GET_BSS_ROLE(adapter->priv[i]) == MWIFIEX_BSS_ROLE_STA) &&  		    adapter->priv[i]->media_connected) -			mwifiex_disconnect(adapter->priv[i], MWIFIEX_CMD_WAIT, -					   NULL); +			mwifiex_deauthenticate(adapter->priv[i], NULL);  	if (!adapter->surprise_removed) -		mwifiex_shutdown_fw(mwifiex_get_priv -				    (adapter, MWIFIEX_BSS_ROLE_ANY), -				    MWIFIEX_CMD_WAIT); +		mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, +							  MWIFIEX_BSS_ROLE_ANY), +					 MWIFIEX_FUNC_SHUTDOWN);  exit:  	up(&add_remove_card_sem); diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 6fff26153e2..33c8ba1f5e3 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -190,8 +190,7 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,   *      - Ensuring correct endian-ness   */  static int -mwifiex_cmd_802_11_get_log(struct mwifiex_private *priv, -			   struct host_cmd_ds_command *cmd) +mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd)  {  	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_GET_LOG);  	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) + @@ -272,8 +271,7 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,   *        (as required)   *      - Ensuring correct endian-ness   */ -static int mwifiex_cmd_tx_power_cfg(struct mwifiex_private *priv, -				    struct host_cmd_ds_command *cmd, +static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,  				    u16 cmd_action, void *data_buf)  {  	struct mwifiex_types_power_group *pg_tlv = NULL; @@ -407,8 +405,7 @@ static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv,   *      - Setting MAC multicast address   *      - Ensuring correct endian-ness   */ -static int mwifiex_cmd_mac_multicast_adr(struct mwifiex_private *priv, -					 struct host_cmd_ds_command *cmd, +static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,  					 u16 cmd_action, void *data_buf)  {  	struct mwifiex_multicast_list *mcast_list = @@ -463,8 +460,7 @@ static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,   *      - Setting command ID and proper size   *      - Ensuring correct endian-ness   */ -static int mwifiex_cmd_802_11_ad_hoc_stop(struct mwifiex_private *priv, -					  struct host_cmd_ds_command *cmd) +static int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command *cmd)  {  	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP);  	cmd->size = cpu_to_le16(S_DS_GEN); @@ -500,9 +496,8 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,  			key_param_set->key_type_id =  				cpu_to_le16(KEY_TYPE_ID_WEP);  			key_param_set->key_info = -				cpu_to_le16(KEY_INFO_WEP_ENABLED | -					    KEY_INFO_WEP_UNICAST | -					    KEY_INFO_WEP_MCAST); +				cpu_to_le16(KEY_ENABLED | KEY_UNICAST | +					    KEY_MCAST);  			key_param_set->key_len =  				cpu_to_le16(priv->wep_key[i].key_length);  			/* Set WEP key index */ @@ -589,10 +584,10 @@ static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,  			cpu_to_le16(KEY_TYPE_ID_WAPI);  		if (cmd_oid == KEY_INFO_ENABLED)  			key_material->key_param_set.key_info = -				cpu_to_le16(KEY_INFO_WAPI_ENABLED); +				cpu_to_le16(KEY_ENABLED);  		else  			key_material->key_param_set.key_info = -				cpu_to_le16(!KEY_INFO_WAPI_ENABLED); +				cpu_to_le16(!KEY_ENABLED);  		key_material->key_param_set.key[0] = enc_key->key_index;  		if (!priv->sec_info.wapi_key_on) @@ -604,10 +599,10 @@ static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,  		if (0 != memcmp(enc_key->mac_addr, bc_mac, sizeof(bc_mac))) {  			/* WAPI pairwise key: unicast */  			key_material->key_param_set.key_info |= -				cpu_to_le16(KEY_INFO_WAPI_UNICAST); +				cpu_to_le16(KEY_UNICAST);  		} else {	/* WAPI group key: multicast */  			key_material->key_param_set.key_info |= -				cpu_to_le16(KEY_INFO_WAPI_MCAST); +				cpu_to_le16(KEY_MCAST);  			priv->sec_info.wapi_key_on = true;  		} @@ -634,32 +629,32 @@ static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,  			cpu_to_le16(KEY_TYPE_ID_AES);  		if (cmd_oid == KEY_INFO_ENABLED)  			key_material->key_param_set.key_info = -				cpu_to_le16(KEY_INFO_AES_ENABLED); +				cpu_to_le16(KEY_ENABLED);  		else  			key_material->key_param_set.key_info = -				cpu_to_le16(!KEY_INFO_AES_ENABLED); +				cpu_to_le16(!KEY_ENABLED);  		if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)  				/* AES pairwise key: unicast */  			key_material->key_param_set.key_info |= -				cpu_to_le16(KEY_INFO_AES_UNICAST); +				cpu_to_le16(KEY_UNICAST);  		else		/* AES group key: multicast */  			key_material->key_param_set.key_info |= -				cpu_to_le16(KEY_INFO_AES_MCAST); +				cpu_to_le16(KEY_MCAST);  	} else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {  		dev_dbg(priv->adapter->dev, "cmd: WPA_TKIP\n");  		key_material->key_param_set.key_type_id =  			cpu_to_le16(KEY_TYPE_ID_TKIP);  		key_material->key_param_set.key_info = -			cpu_to_le16(KEY_INFO_TKIP_ENABLED); +			cpu_to_le16(KEY_ENABLED);  		if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)  				/* TKIP pairwise key: unicast */  			key_material->key_param_set.key_info |= -				cpu_to_le16(KEY_INFO_TKIP_UNICAST); +				cpu_to_le16(KEY_UNICAST);  		else		/* TKIP group key: multicast */  			key_material->key_param_set.key_info |= -				cpu_to_le16(KEY_INFO_TKIP_MCAST); +				cpu_to_le16(KEY_MCAST);  	}  	if (key_material->key_param_set.key_type_id) { @@ -778,8 +773,7 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,   *      - Setting status to enable or disable (for SET only)   *      - Ensuring correct endian-ness   */ -static int mwifiex_cmd_ibss_coalescing_status(struct mwifiex_private *priv, -					      struct host_cmd_ds_command *cmd, +static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,  					      u16 cmd_action, void *data_buf)  {  	struct host_cmd_ds_802_11_ibss_status *ibss_coal = @@ -947,7 +941,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,  						     cmd_action);  		break;  	case HostCmd_CMD_MAC_MULTICAST_ADR: -		ret = mwifiex_cmd_mac_multicast_adr(priv, cmd_ptr, cmd_action, +		ret = mwifiex_cmd_mac_multicast_adr(cmd_ptr, cmd_action,  						    data_buf);  		break;  	case HostCmd_CMD_TX_RATE_CFG: @@ -955,7 +949,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,  					      data_buf);  		break;  	case HostCmd_CMD_TXPWR_CFG: -		ret = mwifiex_cmd_tx_power_cfg(priv, cmd_ptr, cmd_action, +		ret = mwifiex_cmd_tx_power_cfg(cmd_ptr, cmd_action,  					       data_buf);  		break;  	case HostCmd_CMD_802_11_PS_MODE_ENH: @@ -967,11 +961,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,  				(struct mwifiex_hs_config_param *) data_buf);  		break;  	case HostCmd_CMD_802_11_SCAN: -		ret = mwifiex_cmd_802_11_scan(priv, cmd_ptr, data_buf); +		ret = mwifiex_cmd_802_11_scan(cmd_ptr, data_buf);  		break;  	case HostCmd_CMD_802_11_BG_SCAN_QUERY: -		ret = mwifiex_cmd_802_11_bg_scan_query(priv, cmd_ptr, -						       data_buf); +		ret = mwifiex_cmd_802_11_bg_scan_query(cmd_ptr);  		break;  	case HostCmd_CMD_802_11_ASSOCIATE:  		ret = mwifiex_cmd_802_11_associate(priv, cmd_ptr, data_buf); @@ -985,14 +978,14 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,  						      data_buf);  		break;  	case HostCmd_CMD_802_11_GET_LOG: -		ret = mwifiex_cmd_802_11_get_log(priv, cmd_ptr); +		ret = mwifiex_cmd_802_11_get_log(cmd_ptr);  		break;  	case HostCmd_CMD_802_11_AD_HOC_JOIN:  		ret = mwifiex_cmd_802_11_ad_hoc_join(priv, cmd_ptr,  						     data_buf);  		break;  	case HostCmd_CMD_802_11_AD_HOC_STOP: -		ret = mwifiex_cmd_802_11_ad_hoc_stop(priv, cmd_ptr); +		ret = mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr);  		break;  	case HostCmd_CMD_RSSI_INFO:  		ret = mwifiex_cmd_802_11_rssi_info(priv, cmd_ptr, cmd_action); @@ -1037,10 +1030,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,  		cmd_ptr->size = cpu_to_le16(S_DS_GEN);  		break;  	case HostCmd_CMD_11N_ADDBA_REQ: -		ret = mwifiex_cmd_11n_addba_req(priv, cmd_ptr, data_buf); +		ret = mwifiex_cmd_11n_addba_req(cmd_ptr, data_buf);  		break;  	case HostCmd_CMD_11N_DELBA: -		ret = mwifiex_cmd_11n_delba(priv, cmd_ptr, data_buf); +		ret = mwifiex_cmd_11n_delba(cmd_ptr, data_buf);  		break;  	case HostCmd_CMD_11N_ADDBA_RSP:  		ret = mwifiex_cmd_11n_addba_rsp_gen(priv, cmd_ptr, data_buf); @@ -1059,11 +1052,11 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,  					       data_buf);  		break;  	case HostCmd_CMD_AMSDU_AGGR_CTRL: -		ret = mwifiex_cmd_amsdu_aggr_ctrl(priv, cmd_ptr, cmd_action, +		ret = mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr, cmd_action,  						  data_buf);  		break;  	case HostCmd_CMD_11N_CFG: -		ret = mwifiex_cmd_11n_cfg(priv, cmd_ptr, cmd_action, +		ret = mwifiex_cmd_11n_cfg(cmd_ptr, cmd_action,  					  data_buf);  		break;  	case HostCmd_CMD_WMM_GET_STATUS: @@ -1076,8 +1069,8 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,  		ret = 0;  		break;  	case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: -		ret = mwifiex_cmd_ibss_coalescing_status(priv, cmd_ptr, -							 cmd_action, data_buf); +		ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action, +							 data_buf);  		break;  	case HostCmd_CMD_MAC_REG_ACCESS:  	case HostCmd_CMD_BBP_REG_ACCESS: @@ -1136,65 +1129,66 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)  	if (first_sta) { -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_FUNC_INIT, -					  HostCmd_ACT_GEN_SET, 0, NULL, NULL); +		ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_FUNC_INIT, +					     HostCmd_ACT_GEN_SET, 0, NULL);  		if (ret)  			return -1;  		/* Read MAC address from HW */ -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_GET_HW_SPEC, -					  HostCmd_ACT_GEN_GET, 0, NULL, NULL); +		ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_GET_HW_SPEC, +					     HostCmd_ACT_GEN_GET, 0, NULL);  		if (ret)  			return -1;  		/* Reconfigure tx buf size */ -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, -					  HostCmd_ACT_GEN_SET, 0, NULL, -					  &priv->adapter->tx_buf_size); +		ret = mwifiex_send_cmd_async(priv, +					     HostCmd_CMD_RECONFIGURE_TX_BUFF, +					     HostCmd_ACT_GEN_SET, 0, +					     &priv->adapter->tx_buf_size);  		if (ret)  			return -1;  		/* Enable IEEE PS by default */  		priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, -					  EN_AUTO_PS, BITMAP_STA_PS, NULL, -					  NULL); +		ret = mwifiex_send_cmd_async(priv, +					     HostCmd_CMD_802_11_PS_MODE_ENH, +					     EN_AUTO_PS, BITMAP_STA_PS, NULL);  		if (ret)  			return -1;  	}  	/* get tx rate */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TX_RATE_CFG, -				  HostCmd_ACT_GEN_GET, 0, NULL, NULL); +	ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TX_RATE_CFG, +				     HostCmd_ACT_GEN_GET, 0, NULL);  	if (ret)  		return -1;  	priv->data_rate = 0;  	/* get tx power */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TXPWR_CFG, -				  HostCmd_ACT_GEN_GET, 0, NULL, NULL); +	ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TXPWR_CFG, +				     HostCmd_ACT_GEN_GET, 0, NULL);  	if (ret)  		return -1;  	/* set ibss coalescing_status */ -	ret = mwifiex_prepare_cmd(priv, -				  HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, -				  HostCmd_ACT_GEN_SET, 0, NULL, &enable); +	ret = mwifiex_send_cmd_async(priv, +				     HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, +				     HostCmd_ACT_GEN_SET, 0, &enable);  	if (ret)  		return -1;  	memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl));  	amsdu_aggr_ctrl.enable = true;  	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, -				  HostCmd_ACT_GEN_SET, 0, NULL, -				  (void *) &amsdu_aggr_ctrl); +	ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, +				     HostCmd_ACT_GEN_SET, 0, +				     (void *) &amsdu_aggr_ctrl);  	if (ret)  		return -1;  	/* MAC Control must be the last command in init_fw */  	/* set MAC Control */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, -				  HostCmd_ACT_GEN_SET, 0, NULL, -				  &priv->curr_pkt_filter); +	ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, +				     HostCmd_ACT_GEN_SET, 0, +				     &priv->curr_pkt_filter);  	if (ret)  		return -1; @@ -1202,19 +1196,18 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)  		/* Enable auto deep sleep */  		auto_ds.auto_ds = DEEP_SLEEP_ON;  		auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; -		ret = mwifiex_prepare_cmd(priv, -				HostCmd_CMD_802_11_PS_MODE_ENH, -				EN_AUTO_PS, BITMAP_AUTO_DS, NULL, -				&auto_ds); +		ret = mwifiex_send_cmd_async(priv, +					     HostCmd_CMD_802_11_PS_MODE_ENH, +					     EN_AUTO_PS, BITMAP_AUTO_DS, +					     &auto_ds);  		if (ret)  			return -1;  	}  	/* Send cmd to FW to enable/disable 11D function */  	state_11d = ENABLE_11D; -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, -				  HostCmd_ACT_GEN_SET, DOT11D_I, -				  NULL, &state_11d); +	ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB, +				     HostCmd_ACT_GEN_SET, DOT11D_I, &state_11d);  	if (ret)  		dev_err(priv->adapter->dev, "11D: failed to enable 11D\n"); diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 74add45b99b..7f4f10b752f 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -41,8 +41,7 @@   */  static void  mwifiex_process_cmdresp_error(struct mwifiex_private *priv, -			      struct host_cmd_ds_command *resp, -			      struct mwifiex_wait_queue *wq_buf) +			      struct host_cmd_ds_command *resp)  {  	struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;  	struct mwifiex_adapter *adapter = priv->adapter; @@ -51,8 +50,9 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,  	dev_err(adapter->dev, "CMD_RESP: cmd %#x error, result=%#x\n",  			resp->command, resp->result); -	if (wq_buf) -		wq_buf->status = MWIFIEX_ERROR_FW_CMDRESP; + +	if (adapter->curr_cmd->wait_q_enabled) +		adapter->cmd_wait_q.status = -1;  	switch (le16_to_cpu(resp->command)) {  	case HostCmd_CMD_802_11_PS_MODE_ENH: @@ -103,8 +103,6 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,  	spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);  	adapter->curr_cmd = NULL;  	spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - -	return;  }  /* @@ -282,7 +280,6 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,  				   struct host_cmd_ds_command *resp,  				   void *data_buf)  { -	struct mwifiex_adapter *adapter = priv->adapter;  	struct mwifiex_rate_cfg *ds_rate = NULL;  	struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;  	struct mwifiex_rate_scope *rate_scope; @@ -328,9 +325,9 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,  	if (priv->is_data_rate_auto)  		priv->data_rate = 0;  	else -		ret = mwifiex_prepare_cmd(priv, +		ret = mwifiex_send_cmd_async(priv,  					  HostCmd_CMD_802_11_TX_RATE_QUERY, -					  HostCmd_ACT_GEN_GET, 0, NULL, NULL); +					  HostCmd_ACT_GEN_GET, 0, NULL);  	if (data_buf) {  		ds_rate = (struct mwifiex_rate_cfg *) data_buf; @@ -338,9 +335,7 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,  			if (priv->is_data_rate_auto) {  				ds_rate->is_rate_auto = 1;  			} else { -				ds_rate->rate = -					mwifiex_get_rate_index(adapter, -							       priv-> +				ds_rate->rate = mwifiex_get_rate_index(priv->  							       bitmap_rates,  							       sizeof(priv->  							       bitmap_rates)); @@ -516,13 +511,11 @@ static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv,  static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv,  					    struct host_cmd_ds_command *resp)  { -	struct mwifiex_adapter *adapter = priv->adapter; -  	priv->tx_rate = resp->params.tx_rate.tx_rate;  	priv->tx_htinfo = resp->params.tx_rate.ht_info;  	if (!priv->is_data_rate_auto)  		priv->data_rate = -			mwifiex_index_to_data_rate(adapter, priv->tx_rate, +			mwifiex_index_to_data_rate(priv->tx_rate,  						   priv->tx_htinfo);  	return 0; @@ -574,8 +567,7 @@ static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv,  		&resp->params.key_material;  	if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) { -		if ((le16_to_cpu(key->key_param_set.key_info) & -		     KEY_INFO_TKIP_MCAST)) { +		if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {  			dev_dbg(priv->adapter->dev, "info: key: GTK is set\n");  			priv->wpa_is_gtk_set = true;  			priv->scan_block = false; @@ -834,19 +826,17 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,   * response handlers based on the command ID.   */  int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, -				u16 cmdresp_no, void *cmd_buf, void *wq_buf) +				u16 cmdresp_no, void *cmd_buf)  {  	int ret = 0;  	struct mwifiex_adapter *adapter = priv->adapter;  	struct host_cmd_ds_command *resp =  		(struct host_cmd_ds_command *) cmd_buf; -	struct mwifiex_wait_queue *wait_queue = -		(struct mwifiex_wait_queue *) wq_buf;  	void *data_buf = adapter->curr_cmd->data_buf;  	/* If the command is not successful, cleanup and return failure */  	if (resp->result != HostCmd_RESULT_OK) { -		mwifiex_process_cmdresp_error(priv, resp, wait_queue); +		mwifiex_process_cmdresp_error(priv, resp);  		return -1;  	}  	/* Command successful, handle response */ @@ -866,12 +856,11 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,  		ret = mwifiex_ret_tx_rate_cfg(priv, resp, data_buf);  		break;  	case HostCmd_CMD_802_11_SCAN: -		ret = mwifiex_ret_802_11_scan(priv, resp, wait_queue); -		wait_queue = NULL; -		adapter->curr_cmd->wq_buf = NULL; +		ret = mwifiex_ret_802_11_scan(priv, resp); +		adapter->curr_cmd->wait_q_enabled = false;  		break;  	case HostCmd_CMD_802_11_BG_SCAN_QUERY: -		ret = mwifiex_ret_802_11_scan(priv, resp, wait_queue); +		ret = mwifiex_ret_802_11_scan(priv, resp);  		dev_dbg(adapter->dev,  			"info: CMD_RESP: BG_SCAN result is ready!\n");  		break; @@ -885,14 +874,14 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,  		ret = mwifiex_ret_802_11_hs_cfg(priv, resp);  		break;  	case HostCmd_CMD_802_11_ASSOCIATE: -		ret = mwifiex_ret_802_11_associate(priv, resp, wait_queue); +		ret = mwifiex_ret_802_11_associate(priv, resp);  		break;  	case HostCmd_CMD_802_11_DEAUTHENTICATE:  		ret = mwifiex_ret_802_11_deauthenticate(priv, resp);  		break;  	case HostCmd_CMD_802_11_AD_HOC_START:  	case HostCmd_CMD_802_11_AD_HOC_JOIN: -		ret = mwifiex_ret_802_11_ad_hoc(priv, resp, wait_queue); +		ret = mwifiex_ret_802_11_ad_hoc(priv, resp);  		break;  	case HostCmd_CMD_802_11_AD_HOC_STOP:  		ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp); @@ -952,7 +941,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,  						mp_end_port));  		break;  	case HostCmd_CMD_AMSDU_AGGR_CTRL: -		ret = mwifiex_ret_amsdu_aggr_ctrl(priv, resp, data_buf); +		ret = mwifiex_ret_amsdu_aggr_ctrl(resp, data_buf);  		break;  	case HostCmd_CMD_WMM_GET_STATUS:  		ret = mwifiex_ret_wmm_get_status(priv, resp); @@ -971,7 +960,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,  	case HostCmd_CMD_SET_BSS_MODE:  		break;  	case HostCmd_CMD_11N_CFG: -		ret = mwifiex_ret_11n_cfg(priv, resp, data_buf); +		ret = mwifiex_ret_11n_cfg(resp, data_buf);  		break;  	default:  		dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 936d7c175e7..fc265cab090 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -271,8 +271,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)  	case EVENT_HS_ACT_REQ:  		dev_dbg(adapter->dev, "event: HS_ACT_REQ\n"); -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH, -					  0, 0, NULL, NULL); +		ret = mwifiex_send_cmd_async(priv, +					     HostCmd_CMD_802_11_HS_CFG_ENH, +					     0, 0, NULL);  		break;  	case EVENT_MIC_ERR_UNICAST: @@ -303,9 +304,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)  		       sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP);  		adapter->num_in_scan_table = 0;  		adapter->bcn_buf_end = adapter->bcn_buf; -		ret = mwifiex_prepare_cmd(priv, -					  HostCmd_CMD_802_11_BG_SCAN_QUERY, -					  HostCmd_ACT_GEN_GET, 0, NULL, NULL); +		ret = mwifiex_send_cmd_async(priv, +					     HostCmd_CMD_802_11_BG_SCAN_QUERY, +					     HostCmd_ACT_GEN_GET, 0, NULL);  		break;  	case EVENT_PORT_RELEASE: @@ -314,8 +315,8 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)  	case EVENT_WMM_STATUS_CHANGE:  		dev_dbg(adapter->dev, "event: WMM status changed\n"); -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, -					  0, 0, NULL, NULL); +		ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_WMM_GET_STATUS, +					     0, 0, NULL);  		break;  	case EVENT_RSSI_LOW: @@ -353,15 +354,15 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)  		break;  	case EVENT_IBSS_COALESCED:  		dev_dbg(adapter->dev, "event: IBSS_COALESCED\n"); -		ret = mwifiex_prepare_cmd(priv, +		ret = mwifiex_send_cmd_async(priv,  				HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, -				HostCmd_ACT_GEN_GET, 0, NULL, NULL); +				HostCmd_ACT_GEN_GET, 0, NULL);  		break;  	case EVENT_ADDBA:  		dev_dbg(adapter->dev, "event: ADDBA Request\n"); -		mwifiex_prepare_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP, -				    HostCmd_ACT_GEN_SET, 0, NULL, -				    adapter->event_body); +		mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP, +				       HostCmd_ACT_GEN_SET, 0, +				       adapter->event_body);  		break;  	case EVENT_DELBA:  		dev_dbg(adapter->dev, "event: DELBA Request\n"); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index b163507b1fe..e7adaab3522 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -33,9 +33,8 @@   * size, and the calling function must ensure enough memory is   * available.   */ -static int -mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, -			struct net_device *dev) +int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, +			    struct net_device *dev)  {  	int i = 0;  	struct netdev_hw_addr *ha; @@ -47,216 +46,51 @@ mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,  }  /* - * Allocate and fills a wait queue with proper parameters. - * - * This function needs to be called before an IOCTL request can be made. - * It can handle the following wait options: - *      MWIFIEX_NO_WAIT     - Waiting is disabled - *      MWIFIEX_IOCTL_WAIT  - Waiting is done on IOCTL wait queue - *      MWIFIEX_CMD_WAIT    - Waiting is done on command wait queue - *      MWIFIEX_WSTATS_WAIT - Waiting is done on stats wait queue - */ -struct mwifiex_wait_queue * -mwifiex_alloc_fill_wait_queue(struct mwifiex_private *priv, -			      u8 wait_option) -{ -	struct mwifiex_wait_queue *wait = NULL; - -	wait = (struct mwifiex_wait_queue *) -		kzalloc(sizeof(struct mwifiex_wait_queue), GFP_ATOMIC); -	if (!wait) { -		dev_err(priv->adapter->dev, "%s: fail to alloc buffer\n", -						__func__); -		return wait; -	} - -	wait->bss_index = priv->bss_index; - -	switch (wait_option) { -	case MWIFIEX_NO_WAIT: -		wait->enabled = 0; -		break; -	case MWIFIEX_IOCTL_WAIT: -		priv->ioctl_wait_q_woken = false; -		wait->start_time = jiffies; -		wait->wait = &priv->ioctl_wait_q; -		wait->condition = &priv->ioctl_wait_q_woken; -		wait->enabled = 1; -		break; -	case MWIFIEX_CMD_WAIT: -		priv->cmd_wait_q_woken = false; -		wait->start_time = jiffies; -		wait->wait = &priv->cmd_wait_q; -		wait->condition = &priv->cmd_wait_q_woken; -		wait->enabled = 1; -		break; -	case MWIFIEX_WSTATS_WAIT: -		priv->w_stats_wait_q_woken = false; -		wait->start_time = jiffies; -		wait->wait = &priv->w_stats_wait_q; -		wait->condition = &priv->w_stats_wait_q_woken; -		wait->enabled = 1; -		break; -	} - -	return wait; -} - -/*   * Wait queue completion handler.   * - * This function waits on a particular wait queue. - * For NO_WAIT option, it returns immediately. It also cancels the - * pending IOCTL request after waking up, in case of errors. + * This function waits on a cmd wait queue. It also cancels the pending + * request after waking up, in case of errors.   */ -static void -mwifiex_wait_ioctl_complete(struct mwifiex_private *priv, -			    struct mwifiex_wait_queue *wait, -			    u8 wait_option) +int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)  {  	bool cancel_flag = false; +	int status = adapter->cmd_wait_q.status; -	switch (wait_option) { -	case MWIFIEX_NO_WAIT: -		break; -	case MWIFIEX_IOCTL_WAIT: -		wait_event_interruptible(priv->ioctl_wait_q, -					 priv->ioctl_wait_q_woken); -		if (!priv->ioctl_wait_q_woken) -			cancel_flag = true; -		break; -	case MWIFIEX_CMD_WAIT: -		wait_event_interruptible(priv->cmd_wait_q, -					 priv->cmd_wait_q_woken); -		if (!priv->cmd_wait_q_woken) -			cancel_flag = true; -		break; -	case MWIFIEX_WSTATS_WAIT: -		wait_event_interruptible(priv->w_stats_wait_q, -					 priv->w_stats_wait_q_woken); -		if (!priv->w_stats_wait_q_woken) -			cancel_flag = true; -		break; -	} -	if (cancel_flag) { -		mwifiex_cancel_pending_ioctl(priv->adapter, wait); -		dev_dbg(priv->adapter->dev, "cmd: IOCTL cancel: wait=%p, wait_option=%d\n", -			wait, wait_option); -	} - -	return; -} - -/* - * The function waits for the request to complete and issues the - * completion handler, if required. - */ -int mwifiex_request_ioctl(struct mwifiex_private *priv, -			  struct mwifiex_wait_queue *wait, -			  int status, u8 wait_option) -{ -	switch (status) { -	case -EINPROGRESS: -		dev_dbg(priv->adapter->dev, "cmd: IOCTL pending: wait=%p, wait_option=%d\n", -				wait, wait_option); -		atomic_inc(&priv->adapter->ioctl_pending); -		/* Status pending, wake up main process */ -		queue_work(priv->adapter->workqueue, &priv->adapter->main_work); +	dev_dbg(adapter->dev, "cmd pending\n"); +	atomic_inc(&adapter->cmd_pending); -		/* Wait for completion */ -		if (wait_option) { -			mwifiex_wait_ioctl_complete(priv, wait, wait_option); -			status = wait->status; -		} -		break; -	case 0: -	case -1: -	case -EBUSY: -	default: -		break; -	} -	return status; -} -EXPORT_SYMBOL_GPL(mwifiex_request_ioctl); +	/* Status pending, wake up main process */ +	queue_work(adapter->workqueue, &adapter->main_work); -/* - * IOCTL request handler to set/get MAC address. - * - * This function prepares the correct firmware command and - * issues it to get the extended version information. - */ -static int mwifiex_bss_ioctl_mac_address(struct mwifiex_private *priv, -					 struct mwifiex_wait_queue *wait, -					 u8 action, u8 *mac) -{ -	int ret = 0; +	/* Wait for completion */ +	wait_event_interruptible(adapter->cmd_wait_q.wait, +					adapter->cmd_wait_q.condition); +	if (!adapter->cmd_wait_q.condition) +		cancel_flag = true; -	if ((action == HostCmd_ACT_GEN_GET) && mac) { -		memcpy(mac, priv->curr_addr, ETH_ALEN); -		return 0; +	if (cancel_flag) { +		mwifiex_cancel_pending_ioctl(adapter); +		dev_dbg(adapter->dev, "cmd cancel\n");  	} +	adapter->cmd_wait_q.status = 0; -	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_MAC_ADDRESS, -				  action, 0, wait, mac); -	if (!ret) -		ret = -EINPROGRESS; - -	return ret; -} - -/* - * Sends IOCTL request to set MAC address. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_request_set_mac_address(struct mwifiex_private *priv) -{ -	struct mwifiex_wait_queue *wait = NULL; -	int status = 0; -	u8 wait_option = MWIFIEX_CMD_WAIT; - -	/* Allocate wait buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; - -	status = mwifiex_bss_ioctl_mac_address(priv, wait, HostCmd_ACT_GEN_SET, -					       NULL); - -	status = mwifiex_request_ioctl(priv, wait, status, wait_option); -	if (!status) -		memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN); -	else -		dev_err(priv->adapter->dev, "set mac address failed: status=%d" -				" error_code=%#x\n", status, wait->status); - -	kfree(wait);  	return status;  }  /* - * IOCTL request handler to set multicast list. - *   * This function prepares the correct firmware command and   * issues it to set the multicast list.   *   * This function can be used to enable promiscuous mode, or enable all   * multicast packets, or to enable selective multicast.   */ -static int -mwifiex_bss_ioctl_multicast_list(struct mwifiex_private *priv, -				 struct mwifiex_wait_queue *wait, -				 u16 action, -				 struct mwifiex_multicast_list *mcast_list) +int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, +				struct mwifiex_multicast_list *mcast_list)  {  	int ret = 0;  	u16 old_pkt_filter;  	old_pkt_filter = priv->curr_pkt_filter; -	if (action == HostCmd_ACT_GEN_GET) -		return -1;  	if (mcast_list->mode == MWIFIEX_PROMISC_MODE) {  		dev_dbg(priv->adapter->dev, "info: Enable Promiscuous mode\n"); @@ -281,16 +115,15 @@ mwifiex_bss_ioctl_multicast_list(struct mwifiex_private *priv,  				/* Set multicast addresses to firmware */  				if (old_pkt_filter == priv->curr_pkt_filter) {  					/* Send request to firmware */ -					ret = mwifiex_prepare_cmd(priv, +					ret = mwifiex_send_cmd_async(priv,  						HostCmd_CMD_MAC_MULTICAST_ADR, -						action, 0, wait, mcast_list); -					if (!ret) -						ret = -EINPROGRESS; +						HostCmd_ACT_GEN_SET, 0, +						mcast_list);  				} else {  					/* Send request to firmware */ -					ret = mwifiex_prepare_cmd(priv, +					ret = mwifiex_send_cmd_async(priv,  						HostCmd_CMD_MAC_MULTICAST_ADR, -						action, 0, NULL, +						HostCmd_ACT_GEN_SET, 0,  						mcast_list);  				}  			} @@ -300,101 +133,21 @@ mwifiex_bss_ioctl_multicast_list(struct mwifiex_private *priv,  		"info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n",  	       old_pkt_filter, priv->curr_pkt_filter);  	if (old_pkt_filter != priv->curr_pkt_filter) { -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, action, -					  0, wait, &priv->curr_pkt_filter); -		if (!ret) -			ret = -EINPROGRESS; +		ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, +					     HostCmd_ACT_GEN_SET, +					     0, &priv->curr_pkt_filter);  	}  	return ret;  }  /* - * Sends IOCTL request to set multicast list. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -void -mwifiex_request_set_multicast_list(struct mwifiex_private *priv, -				   struct net_device *dev) -{ -	struct mwifiex_wait_queue *wait = NULL; -	struct mwifiex_multicast_list mcast_list; -	u8 wait_option = MWIFIEX_NO_WAIT; -	int status = 0; - -	/* Allocate wait buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return; - -	if (dev->flags & IFF_PROMISC) { -		mcast_list.mode = MWIFIEX_PROMISC_MODE; -	} else if (dev->flags & IFF_ALLMULTI || -		   netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) { -		mcast_list.mode = MWIFIEX_ALL_MULTI_MODE; -	} else { -		mcast_list.mode = MWIFIEX_MULTICAST_MODE; -		if (netdev_mc_count(dev)) -			mcast_list.num_multicast_addr = -				mwifiex_copy_mcast_addr(&mcast_list, dev); -	} -	status = mwifiex_bss_ioctl_multicast_list(priv, wait, -						  HostCmd_ACT_GEN_SET, -						  &mcast_list); - -	status = mwifiex_request_ioctl(priv, wait, status, wait_option); -	if (wait && status != -EINPROGRESS) -		kfree(wait); - -	return; -} - -/* - * IOCTL request handler to disconnect from a BSS/IBSS. - */ -static int mwifiex_bss_ioctl_stop(struct mwifiex_private *priv, -				  struct mwifiex_wait_queue *wait, u8 *mac) -{ -	return mwifiex_deauthenticate(priv, wait, mac); -} - -/* - * Sends IOCTL request to disconnect from a BSS. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_disconnect(struct mwifiex_private *priv, u8 wait_option, u8 *mac) -{ -	struct mwifiex_wait_queue *wait = NULL; -	int status = 0; - -	/* Allocate wait buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; - -	status = mwifiex_bss_ioctl_stop(priv, wait, mac); - -	status = mwifiex_request_ioctl(priv, wait, status, wait_option); - -	kfree(wait); -	return status; -} -EXPORT_SYMBOL_GPL(mwifiex_disconnect); - -/* - * IOCTL request handler to join a BSS/IBSS. - *   * In Ad-Hoc mode, the IBSS is created if not found in scan list.   * In both Ad-Hoc and infra mode, an deauthentication is performed   * first.   */ -static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv, -				   struct mwifiex_wait_queue *wait, -				   struct mwifiex_ssid_bssid *ssid_bssid) +int mwifiex_bss_start(struct mwifiex_private *priv, +		      struct mwifiex_ssid_bssid *ssid_bssid)  {  	int ret = 0;  	struct mwifiex_adapter *adapter = priv->adapter; @@ -406,7 +159,7 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv,  	if (priv->bss_mode == NL80211_IFTYPE_STATION) {  		/* Infra mode */ -		ret = mwifiex_deauthenticate(priv, NULL, NULL); +		ret = mwifiex_deauthenticate(priv, NULL);  		if (ret)  			return ret; @@ -427,7 +180,7 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv,  		/* Clear any past association response stored for  		 * application retrieval */  		priv->assoc_rsp_size = 0; -		ret = mwifiex_associate(priv, wait, &adapter->scan_table[i]); +		ret = mwifiex_associate(priv, &adapter->scan_table[i]);  		if (ret)  			return ret;  	} else { @@ -441,7 +194,7 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv,  		/* Exit Adhoc mode first */  		dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n"); -		ret = mwifiex_deauthenticate(priv, NULL, NULL); +		ret = mwifiex_deauthenticate(priv, NULL);  		if (ret)  			return ret; @@ -460,75 +213,39 @@ static int mwifiex_bss_ioctl_start(struct mwifiex_private *priv,  		if (i >= 0) {  			dev_dbg(adapter->dev, "info: network found in scan"  							" list. Joining...\n"); -			ret = mwifiex_adhoc_join(priv, wait, -						 &adapter->scan_table[i]); +			ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]);  			if (ret)  				return ret; -		} else {	/* i >= 0 */ +		} else {  			dev_dbg(adapter->dev, "info: Network not found in "  				"the list, creating adhoc with ssid = %s\n",  			       ssid_bssid->ssid.ssid); -			ret = mwifiex_adhoc_start(priv, wait, -						  &ssid_bssid->ssid); +			ret = mwifiex_adhoc_start(priv, &ssid_bssid->ssid);  			if (ret)  				return ret;  		}  	} -	if (!ret) -		ret = -EINPROGRESS; -  	return ret;  }  /* - * Sends IOCTL request to connect with a BSS. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_bss_start(struct mwifiex_private *priv, u8 wait_option, -		      struct mwifiex_ssid_bssid *ssid_bssid) -{ -	struct mwifiex_wait_queue *wait = NULL; -	struct mwifiex_ssid_bssid tmp_ssid_bssid; -	int status = 0; - -	/* Stop the O.S. TX queue if needed */ -	if (!netif_queue_stopped(priv->netdev)) -		netif_stop_queue(priv->netdev); - -	/* Allocate wait buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; - -	if (ssid_bssid) -		memcpy(&tmp_ssid_bssid, ssid_bssid, -		       sizeof(struct mwifiex_ssid_bssid)); -	status = mwifiex_bss_ioctl_start(priv, wait, &tmp_ssid_bssid); - -	status = mwifiex_request_ioctl(priv, wait, status, wait_option); - -	kfree(wait); -	return status; -} - -/*   * IOCTL request handler to set host sleep configuration.   *   * This function prepares the correct firmware command and   * issues it.   */ -static int -mwifiex_pm_ioctl_hs_cfg(struct mwifiex_private *priv, -			struct mwifiex_wait_queue *wait, -			u16 action, struct mwifiex_ds_hs_cfg *hs_cfg) +int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, +			  int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg) +  {  	struct mwifiex_adapter *adapter = priv->adapter;  	int status = 0;  	u32 prev_cond = 0; +	if (!hs_cfg) +		return -ENOMEM; +  	switch (action) {  	case HostCmd_ACT_GEN_SET:  		if (adapter->pps_uapsd_mode) { @@ -561,12 +278,16 @@ mwifiex_pm_ioctl_hs_cfg(struct mwifiex_private *priv,  				status = -1;  				break;  			} -			status = mwifiex_prepare_cmd(priv, -					HostCmd_CMD_802_11_HS_CFG_ENH, -					HostCmd_ACT_GEN_SET, -					0, wait, &adapter->hs_cfg); -			if (!status) -				status = -EINPROGRESS; +			if (cmd_type == MWIFIEX_SYNC_CMD) +				status = mwifiex_send_cmd_sync(priv, +						HostCmd_CMD_802_11_HS_CFG_ENH, +						HostCmd_ACT_GEN_SET, 0, +						&adapter->hs_cfg); +			else +				status = mwifiex_send_cmd_async(priv, +						HostCmd_CMD_802_11_HS_CFG_ENH, +						HostCmd_ACT_GEN_SET, 0, +						&adapter->hs_cfg);  			if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL)  				/* Restore previous condition */  				adapter->hs_cfg.conditions = @@ -592,53 +313,20 @@ mwifiex_pm_ioctl_hs_cfg(struct mwifiex_private *priv,  }  /* - * Sends IOCTL request to set Host Sleep parameters. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, -			      u8 wait_option, -			      struct mwifiex_ds_hs_cfg *hscfg) -{ -	int ret = 0; -	struct mwifiex_wait_queue *wait = NULL; - -	if (!hscfg) -		return -ENOMEM; - -	/* Allocate wait buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; - -	ret = mwifiex_pm_ioctl_hs_cfg(priv, wait, action, hscfg); - -	ret = mwifiex_request_ioctl(priv, wait, ret, wait_option); - -	if (wait && (ret != -EINPROGRESS)) -		kfree(wait); -	return ret; -} - -/*   * Sends IOCTL request to cancel the existing Host Sleep configuration.   *   * This function allocates the IOCTL request buffer, fills it   * with requisite parameters and calls the IOCTL handler.   */ -int mwifiex_cancel_hs(struct mwifiex_private *priv, u8 wait_option) +int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type)  { -	int ret = 0;  	struct mwifiex_ds_hs_cfg hscfg; -	/* Cancel Host Sleep */  	hscfg.conditions = HOST_SLEEP_CFG_CANCEL;  	hscfg.is_invoke_hostcmd = true; -	ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, -					wait_option, &hscfg); -	return ret; +	return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, +				    cmd_type, &hscfg);  }  EXPORT_SYMBOL_GPL(mwifiex_cancel_hs); @@ -657,7 +345,6 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)  		return true;  	} -	/* Enable Host Sleep */  	adapter->hs_activate_wait_q_woken = false;  	memset(&hscfg, 0, sizeof(struct mwifiex_hs_config_param)); @@ -665,8 +352,8 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)  	if (mwifiex_set_hs_params(mwifiex_get_priv(adapter,  						       MWIFIEX_BSS_ROLE_STA), -				      HostCmd_ACT_GEN_SET, -				      MWIFIEX_IOCTL_WAIT, &hscfg)) { +				  HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, +				  &hscfg)) {  		dev_err(adapter->dev, "IOCTL request HS enable failed\n");  		return false;  	} @@ -679,69 +366,6 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)  EXPORT_SYMBOL_GPL(mwifiex_enable_hs);  /* - * IOCTL request handler to get signal information. - * - * This function prepares the correct firmware command and - * issues it to get the signal (RSSI) information. - * - * This only works in the connected mode. - */ -static int mwifiex_get_info_signal(struct mwifiex_private *priv, -				   struct mwifiex_wait_queue *wait, -				   struct mwifiex_ds_get_signal *signal) -{ -	int ret = 0; - -	if (!wait) { -		dev_err(priv->adapter->dev, "WAIT information is not present\n"); -		return -1; -	} - -	/* Signal info can be obtained only if connected */ -	if (!priv->media_connected) { -		dev_dbg(priv->adapter->dev, -			"info: Can not get signal in disconnected state\n"); -		return -1; -	} - -	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_RSSI_INFO, -				  HostCmd_ACT_GEN_GET, 0, wait, signal); - -	if (!ret) -		ret = -EINPROGRESS; - -	return ret; -} - -/* - * IOCTL request handler to get statistics. - * - * This function prepares the correct firmware command and - * issues it to get the statistics (RSSI) information. - */ -static int mwifiex_get_info_stats(struct mwifiex_private *priv, -			   struct mwifiex_wait_queue *wait, -			   struct mwifiex_ds_get_stats *log) -{ -	int ret = 0; - -	if (!wait) { -		dev_err(priv->adapter->dev, "MWIFIEX IOCTL information is not present\n"); -		return -1; -	} - -	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_GET_LOG, -				  HostCmd_ACT_GEN_GET, 0, wait, log); - -	if (!ret) -		ret = -EINPROGRESS; - -	return ret; -} - -/*   * IOCTL request handler to get BSS information.   *   * This function collates the information from different driver structures @@ -757,23 +381,17 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,  	if (!info)  		return -1; -	/* Get current BSS info */  	bss_desc = &priv->curr_bss_params.bss_descriptor; -	/* BSS mode */  	info->bss_mode = priv->bss_mode; -	/* SSID */  	memcpy(&info->ssid, &bss_desc->ssid,  	       sizeof(struct mwifiex_802_11_ssid)); -	/* BSSID */  	memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN); -	/* Channel */  	info->bss_chan = bss_desc->channel; -	/* Region code */  	info->region_code = adapter->region_code;  	/* Scan table index if connected */ @@ -787,20 +405,15 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,  			info->scan_table_idx = tbl_idx;  	} -	/* Connection status */  	info->media_connected = priv->media_connected; -	/* Tx power information */  	info->max_power_level = priv->max_tx_power_level;  	info->min_power_level = priv->min_tx_power_level; -	/* AdHoc state */  	info->adhoc_state = priv->adhoc_state; -	/* Last beacon NF */  	info->bcn_nf_last = priv->bcn_nf_last; -	/* wep status */  	if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_ENABLED)  		info->wep_status = true;  	else @@ -813,90 +426,20 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,  }  /* - * IOCTL request handler to get extended version information. + * The function sets band configurations.   * - * This function prepares the correct firmware command and - * issues it to get the extended version information. - */ -static int mwifiex_get_info_ver_ext(struct mwifiex_private *priv, -				    struct mwifiex_wait_queue *wait, -				    struct mwifiex_ver_ext *ver_ext) -{ -	int ret = 0; - -	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_VERSION_EXT, -				  HostCmd_ACT_GEN_GET, 0, wait, ver_ext); -	if (!ret) -		ret = -EINPROGRESS; - -	return ret; -} - -/* - * IOCTL request handler to set/get SNMP MIB parameters. - * - * This function prepares the correct firmware command and - * issues it. - * - * Currently the following parameters are supported - - *      Set/get RTS Threshold - *      Set/get fragmentation threshold - *      Set/get retry count - */ -int mwifiex_snmp_mib_ioctl(struct mwifiex_private *priv, -			   struct mwifiex_wait_queue *wait, -			   u32 cmd_oid, u16 action, u32 *value) -{ -	int ret = 0; - -	if (!value) -		return -1; - -	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, -				  action, cmd_oid, wait, value); - -	if (!ret) -		ret = -EINPROGRESS; - -	return ret; -} - -/* - * IOCTL request handler to set/get band configurations. - * - * For SET operation, it performs extra checks to make sure the Ad-Hoc + * it performs extra checks to make sure the Ad-Hoc   * band and channel are compatible. Otherwise it returns an error.   * - * For GET operation, this function retrieves the following information - - *      - Infra bands - *      - Ad-hoc band - *      - Ad-hoc channel - *      - Secondary channel offset   */ -int mwifiex_radio_ioctl_band_cfg(struct mwifiex_private *priv, -				 u16 action, -				 struct mwifiex_ds_band_cfg *radio_cfg) +int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv, +			       struct mwifiex_ds_band_cfg *radio_cfg)  {  	struct mwifiex_adapter *adapter = priv->adapter;  	u8 infra_band = 0;  	u8 adhoc_band = 0;  	u32 adhoc_channel = 0; -	if (action == HostCmd_ACT_GEN_GET) { -		/* Infra Bands */ -		radio_cfg->config_bands = adapter->config_bands; -		/* Adhoc Band */ -		radio_cfg->adhoc_start_band = adapter->adhoc_start_band; -		/* Adhoc channel */ -		radio_cfg->adhoc_channel = priv->adhoc_channel; -		/* Secondary channel offset */ -		radio_cfg->sec_chan_offset = adapter->chan_offset; -		return 0; -	} - -	/* For action = SET */  	infra_band = (u8) radio_cfg->config_bands;  	adhoc_band = (u8) radio_cfg->adhoc_start_band;  	adhoc_channel = radio_cfg->adhoc_channel; @@ -950,8 +493,8 @@ int mwifiex_radio_ioctl_band_cfg(struct mwifiex_private *priv,   * This function performs validity checking on channel/frequency   * compatibility and returns failure if not valid.   */ -int mwifiex_bss_ioctl_channel(struct mwifiex_private *priv, u16 action, -			      struct mwifiex_chan_freq_power *chan) +int mwifiex_bss_set_channel(struct mwifiex_private *priv, +			    struct mwifiex_chan_freq_power *chan)  {  	struct mwifiex_adapter *adapter = priv->adapter;  	struct mwifiex_chan_freq_power *cfp = NULL; @@ -959,16 +502,6 @@ int mwifiex_bss_ioctl_channel(struct mwifiex_private *priv, u16 action,  	if (!chan)  		return -1; -	if (action == HostCmd_ACT_GEN_GET) { -		cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, -				priv->curr_bss_params.band, -				(u16) priv->curr_bss_params.bss_descriptor. -					channel); -		chan->channel = cfp->channel; -		chan->freq = cfp->freq; - -		return 0; -	}  	if (!chan->channel && !chan->freq)  		return -1;  	if (adapter->adhoc_start_band & BAND_AN) @@ -1024,27 +557,19 @@ int mwifiex_bss_ioctl_channel(struct mwifiex_private *priv, u16 action,   * issues it to set or get the ad-hoc channel.   */  static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv, -					  struct mwifiex_wait_queue *wait,  					  u16 action, u16 *channel)  { -	int ret = 0; -  	if (action == HostCmd_ACT_GEN_GET) {  		if (!priv->media_connected) {  			*channel = priv->adhoc_channel; -			return ret; +			return 0;  		}  	} else {  		priv->adhoc_channel = (u8) *channel;  	} -	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_RF_CHANNEL, -				  action, 0, wait, channel); -	if (!ret) -		ret = -EINPROGRESS; - -	return ret; +	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_RF_CHANNEL, +				    action, 0, channel);  }  /* @@ -1054,11 +579,9 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv,   * these are provided, just the best BSS (best RSSI) is returned.   */  int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv, -			       struct mwifiex_wait_queue *wait,  			       struct mwifiex_ssid_bssid *ssid_bssid)  {  	struct mwifiex_adapter *adapter = priv->adapter; -	int ret = 0;  	struct mwifiex_bssdescriptor *bss_desc;  	u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };  	u8 mac[ETH_ALEN]; @@ -1087,10 +610,10 @@ int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv,  		bss_desc = &adapter->scan_table[i];  		memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN);  	} else { -		ret = mwifiex_find_best_network(priv, ssid_bssid); +		return mwifiex_find_best_network(priv, ssid_bssid);  	} -	return ret; +	return 0;  }  /* @@ -1114,10 +637,7 @@ int  mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)  {  	int ret = 0; -	int status = 0;  	struct mwifiex_bss_info bss_info; -	struct mwifiex_wait_queue *wait = NULL; -	u8 wait_option = MWIFIEX_IOCTL_WAIT;  	struct mwifiex_ssid_bssid ssid_bssid;  	u16 curr_chan = 0; @@ -1127,19 +647,10 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)  	if (mwifiex_get_bss_info(priv, &bss_info))  		return -1; -	/* Allocate wait buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; -  	/* Get current channel */ -	status = mwifiex_bss_ioctl_ibss_channel(priv, wait, HostCmd_ACT_GEN_GET, -						&curr_chan); +	ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_GET, +					     &curr_chan); -	if (mwifiex_request_ioctl(priv, wait, status, wait_option)) { -		ret = -1; -		goto done; -	}  	if (curr_chan == channel) {  		ret = 0;  		goto done; @@ -1154,23 +665,13 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)  	/* Do disonnect */  	memset(&ssid_bssid, 0, ETH_ALEN); -	status = mwifiex_bss_ioctl_stop(priv, wait, ssid_bssid.bssid); - -	if (mwifiex_request_ioctl(priv, wait, status, wait_option)) { -		ret = -1; -		goto done; -	} +	ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid); -	status = mwifiex_bss_ioctl_ibss_channel(priv, wait, HostCmd_ACT_GEN_SET, -						(u16 *) &channel); - -	if (mwifiex_request_ioctl(priv, wait, status, wait_option)) { -		ret = -1; -		goto done; -	} +	ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET, +					     (u16 *) &channel);  	/* Do specific SSID scanning */ -	if (mwifiex_request_scan(priv, wait_option, &bss_info.ssid)) { +	if (mwifiex_request_scan(priv, &bss_info.ssid)) {  		ret = -1;  		goto done;  	} @@ -1179,13 +680,8 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)  	memcpy(&ssid_bssid.ssid, &bss_info.ssid,  	       sizeof(struct mwifiex_802_11_ssid)); -	status = mwifiex_bss_ioctl_start(priv, wait, &ssid_bssid); - -	if (mwifiex_request_ioctl(priv, wait, status, wait_option)) -		ret = -1; - +	ret = mwifiex_bss_start(priv, &ssid_bssid);  done: -	kfree(wait);  	return ret;  } @@ -1198,11 +694,9 @@ done:   * for the band.   */  static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, -					     struct mwifiex_wait_queue *wait,  					     struct mwifiex_rate_cfg *rate_cfg)  {  	struct mwifiex_adapter *adapter = priv->adapter; -	int ret = 0;  	rate_cfg->is_rate_auto = priv->is_data_rate_auto;  	if (!priv->media_connected) { @@ -1241,15 +735,12 @@ static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv,  			break;  		}  	} else { -		/* Send request to firmware */ -		ret = mwifiex_prepare_cmd(priv, -					  HostCmd_CMD_802_11_TX_RATE_QUERY, -					  HostCmd_ACT_GEN_GET, 0, wait, NULL); -		if (!ret) -			ret = -EINPROGRESS; +		return mwifiex_send_cmd_sync(priv, +					    HostCmd_CMD_802_11_TX_RATE_QUERY, +					    HostCmd_ACT_GEN_GET, 0, NULL);  	} -	return ret; +	return 0;  }  /* @@ -1261,7 +752,6 @@ static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv,   * The function also performs validation checking on the supplied value.   */  static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, -					     struct mwifiex_wait_queue *wait,  					     struct mwifiex_rate_cfg *rate_cfg)  {  	u8 rates[MWIFIEX_SUPPORTED_RATES]; @@ -1299,8 +789,7 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,  		}  		memset(bitmap_rates, 0, sizeof(bitmap_rates)); -		rate_index = -			mwifiex_data_rate_to_index(adapter, rate_cfg->rate); +		rate_index = mwifiex_data_rate_to_index(rate_cfg->rate);  		/* Only allow b/g rates to be set */  		if (rate_index >= MWIFIEX_RATE_INDEX_HRDSSS0 && @@ -1315,11 +804,8 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,  		}  	} -	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TX_RATE_CFG, -				  HostCmd_ACT_GEN_SET, 0, wait, bitmap_rates); -	if (!ret) -		ret = -EINPROGRESS; +	ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, +				    HostCmd_ACT_GEN_SET, 0, bitmap_rates);  	return ret;  } @@ -1331,7 +817,6 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,   * rate index.   */  static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv, -				  struct mwifiex_wait_queue *wait,  				  struct mwifiex_rate_cfg *rate_cfg)  {  	int status = 0; @@ -1340,11 +825,9 @@ static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv,  		return -1;  	if (rate_cfg->action == HostCmd_ACT_GEN_GET) -		status = mwifiex_rate_ioctl_get_rate_value( -				priv, wait, rate_cfg); +		status = mwifiex_rate_ioctl_get_rate_value(priv, rate_cfg);  	else -		status = mwifiex_rate_ioctl_set_rate_value( -				priv, wait, rate_cfg); +		status = mwifiex_rate_ioctl_set_rate_value(priv, rate_cfg);  	return status;  } @@ -1359,30 +842,21 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,  			      struct mwifiex_rate_cfg *rate)  {  	int ret = 0; -	struct mwifiex_wait_queue *wait = NULL; -	u8 wait_option = MWIFIEX_IOCTL_WAIT; - -	/* Allocate wait buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM;  	memset(rate, 0, sizeof(struct mwifiex_rate_cfg));  	rate->action = HostCmd_ACT_GEN_GET; -	ret = mwifiex_rate_ioctl_cfg(priv, wait, rate); +	ret = mwifiex_rate_ioctl_cfg(priv, rate); -	ret = mwifiex_request_ioctl(priv, wait, ret, wait_option);  	if (!ret) {  		if (rate && rate->is_rate_auto) -			rate->rate = mwifiex_index_to_data_rate(priv->adapter, -					priv->tx_rate, priv->tx_htinfo); +			rate->rate = mwifiex_index_to_data_rate(priv->tx_rate, +							priv->tx_htinfo);  		else if (rate)  			rate->rate = priv->data_rate;  	} else {  		ret = -1;  	} -	kfree(wait);  	return ret;  } @@ -1398,9 +872,8 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,   *      - Modulation class HTBW20   *      - Modulation class HTBW40   */ -static int mwifiex_power_ioctl_set_power(struct mwifiex_private *priv, -					 struct mwifiex_wait_queue *wait, -					 struct mwifiex_power_cfg *power_cfg) +int mwifiex_set_tx_power(struct mwifiex_private *priv, +			 struct mwifiex_power_cfg *power_cfg)  {  	int ret = 0;  	struct host_cmd_ds_txpwr_cfg *txp_cfg = NULL; @@ -1472,13 +945,10 @@ static int mwifiex_power_ioctl_set_power(struct mwifiex_private *priv,  		pg->power_max = (s8) dbm;  		pg->ht_bandwidth = HT_BW_40;  	} -	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_TXPWR_CFG, -				  HostCmd_ACT_GEN_SET, 0, wait, buf); -	if (!ret) -		ret = -EINPROGRESS; -	kfree(buf); +	ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TXPWR_CFG, +				    HostCmd_ACT_GEN_SET, 0, buf); +	kfree(buf);  	return ret;  } @@ -1488,33 +958,23 @@ static int mwifiex_power_ioctl_set_power(struct mwifiex_private *priv,   * This function prepares the correct firmware command and   * issues it.   */ -static int mwifiex_pm_ioctl_ps_mode(struct mwifiex_private *priv, -				    struct mwifiex_wait_queue *wait, -				    u32 *ps_mode, u16 action) +int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode)  {  	int ret = 0;  	struct mwifiex_adapter *adapter = priv->adapter;  	u16 sub_cmd; -	if (action == HostCmd_ACT_GEN_SET) { -		if (*ps_mode) -			adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; -		else -			adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; -		sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, -					  sub_cmd, BITMAP_STA_PS, wait, NULL); -		if ((!ret) && (sub_cmd == DIS_AUTO_PS)) -			ret = mwifiex_prepare_cmd(priv, -					HostCmd_CMD_802_11_PS_MODE_ENH, GET_PS, -					0, NULL, NULL); -	} else { -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, -					  GET_PS, 0, wait, NULL); -	} - -	if (!ret) -		ret = -EINPROGRESS; +	if (*ps_mode) +		adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; +	else +		adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; +	sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; +	ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH, +				    sub_cmd, BITMAP_STA_PS, NULL); +	if ((!ret) && (sub_cmd == DIS_AUTO_PS)) +		ret = mwifiex_send_cmd_async(priv, +				HostCmd_CMD_802_11_PS_MODE_ENH, GET_PS, +				0, NULL);  	return ret;  } @@ -1600,20 +1060,13 @@ static int mwifiex_set_wapi_ie(struct mwifiex_private *priv,   * This function prepares the correct firmware command and   * issues it.   */ -static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_adapter *adapter, -			       struct mwifiex_wait_queue *wait, +static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv,  			       struct mwifiex_ds_encrypt_key *encrypt_key)  { -	int ret = 0; -	struct mwifiex_private *priv = adapter->priv[wait->bss_index]; -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, -				  HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, -				  wait, encrypt_key); -	if (!ret) -		ret = -EINPROGRESS; - -	return ret; +	return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL, +				    HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, +				    encrypt_key);  }  /* @@ -1622,12 +1075,10 @@ static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_adapter *adapter,   * This function prepares the correct firmware command and   * issues it, after validation checks.   */ -static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter, -			      struct mwifiex_wait_queue *wait, +static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv,  			      struct mwifiex_ds_encrypt_key *encrypt_key)  {  	int ret = 0; -	struct mwifiex_private *priv = adapter->priv[wait->bss_index];  	struct mwifiex_wep_key *wep_key = NULL;  	int index; @@ -1641,7 +1092,7 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter,  		/* Copy the required key as the current key */  		wep_key = &priv->wep_key[index];  		if (!wep_key->key_length) { -			dev_err(adapter->dev, +			dev_err(priv->adapter->dev,  				"key not set, so cannot enable it\n");  			return -1;  		} @@ -1649,7 +1100,6 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter,  		priv->sec_info.wep_status = MWIFIEX_802_11_WEP_ENABLED;  	} else {  		wep_key = &priv->wep_key[index]; -		/* Cleanup */  		memset(wep_key, 0, sizeof(struct mwifiex_wep_key));  		/* Copy the key in the driver */  		memcpy(wep_key->key_material, @@ -1661,8 +1111,9 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter,  	}  	if (wep_key->key_length) {  		/* Send request to firmware */ -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, -					  HostCmd_ACT_GEN_SET, 0, NULL, NULL); +		ret = mwifiex_send_cmd_async(priv, +					     HostCmd_CMD_802_11_KEY_MATERIAL, +					     HostCmd_ACT_GEN_SET, 0, NULL);  		if (ret)  			return ret;  	} @@ -1671,12 +1122,9 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter,  	else  		priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; -	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_MAC_CONTROL, -				  HostCmd_ACT_GEN_SET, 0, wait, -				  &priv->curr_pkt_filter); -	if (!ret) -		ret = -EINPROGRESS; +	ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, +				    HostCmd_ACT_GEN_SET, 0, +				    &priv->curr_pkt_filter);  	return ret;  } @@ -1691,18 +1139,16 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_adapter *adapter,   *   * This function can also be used to disable a currently set key.   */ -static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter, -			      struct mwifiex_wait_queue *wait, +static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv,  			      struct mwifiex_ds_encrypt_key *encrypt_key)  {  	int ret = 0; -	struct mwifiex_private *priv = adapter->priv[wait->bss_index];  	u8 remove_key = false;  	struct host_cmd_ds_802_11_key_material *ibss_key;  	/* Current driver only supports key length of up to 32 bytes */ -	if (encrypt_key->key_len > MWIFIEX_MAX_KEY_LENGTH) { -		dev_err(adapter->dev, "key length too long\n"); +	if (encrypt_key->key_len > WLAN_MAX_KEY_LEN) { +		dev_err(priv->adapter->dev, "key length too long\n");  		return -1;  	} @@ -1713,9 +1159,10 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter,  		 */  		/* Send the key as PTK to firmware */  		encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, -					  HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, -					  NULL, encrypt_key); +		ret = mwifiex_send_cmd_async(priv, +					HostCmd_CMD_802_11_KEY_MATERIAL, +					HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, +					encrypt_key);  		if (ret)  			return ret; @@ -1729,8 +1176,7 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter,  		       sizeof(ibss_key->key_param_set.key_len));  		ibss_key->key_param_set.key_type_id  			= cpu_to_le16(KEY_TYPE_ID_TKIP); -		ibss_key->key_param_set.key_info -			= cpu_to_le16(KEY_INFO_TKIP_ENABLED); +		ibss_key->key_param_set.key_info = cpu_to_le16(KEY_ENABLED);  		/* Send the key as GTK to firmware */  		encrypt_key->key_index = ~MWIFIEX_KEY_INDEX_UNICAST; @@ -1740,19 +1186,15 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter,  		encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST;  	if (remove_key) -		/* Send request to firmware */ -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, -					  HostCmd_ACT_GEN_SET, -					  !(KEY_INFO_ENABLED), -					  wait, encrypt_key); +		ret = mwifiex_send_cmd_sync(priv, +				       HostCmd_CMD_802_11_KEY_MATERIAL, +				       HostCmd_ACT_GEN_SET, !(KEY_INFO_ENABLED), +				       encrypt_key);  	else -		/* Send request to firmware */ -		ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, -					  HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, -					  wait, encrypt_key); - -	if (!ret) -		ret = -EINPROGRESS; +		ret = mwifiex_send_cmd_sync(priv, +					HostCmd_CMD_802_11_KEY_MATERIAL, +					HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, +					encrypt_key);  	return ret;  } @@ -1765,21 +1207,16 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_adapter *adapter,   */  static int  mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv, -			      struct mwifiex_wait_queue *wait,  			      struct mwifiex_ds_encrypt_key *encrypt_key)  {  	int status = 0; -	struct mwifiex_adapter *adapter = priv->adapter;  	if (encrypt_key->is_wapi_key) -		status = mwifiex_sec_ioctl_set_wapi_key(adapter, wait, -							encrypt_key); +		status = mwifiex_sec_ioctl_set_wapi_key(priv, encrypt_key);  	else if (encrypt_key->key_len > WLAN_KEY_LEN_WEP104) -		status = mwifiex_sec_ioctl_set_wpa_key(adapter, wait, -						       encrypt_key); +		status = mwifiex_sec_ioctl_set_wpa_key(priv, encrypt_key);  	else -		status = mwifiex_sec_ioctl_set_wep_key(adapter, wait, -						       encrypt_key); +		status = mwifiex_sec_ioctl_set_wep_key(priv, encrypt_key);  	return status;  } @@ -1807,94 +1244,30 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version,  }  /* - * Sends IOCTL request to set Tx power. It can be set to either auto - * or a fixed value. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_set_tx_power(struct mwifiex_private *priv, int type, int dbm) -{ -	struct mwifiex_power_cfg power_cfg; -	struct mwifiex_wait_queue *wait = NULL; -	int status = 0; -	int ret = 0; - -	wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); -	if (!wait) -		return -ENOMEM; - -	if (type == NL80211_TX_POWER_FIXED) { -		power_cfg.is_power_auto = 0; -		power_cfg.power_level = dbm; -	} else { -		power_cfg.is_power_auto = 1; -	} -	status = mwifiex_power_ioctl_set_power(priv, wait, &power_cfg); - -	ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); - -	kfree(wait); -	return ret; -} - -/* - * Sends IOCTL request to get scan table. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_get_scan_table(struct mwifiex_private *priv, u8 wait_option, -			   struct mwifiex_scan_resp *scan_resp) -{ -	struct mwifiex_wait_queue *wait = NULL; -	struct mwifiex_scan_resp scan; -	int status = 0; - -	/* Allocate wait buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; - -	status = mwifiex_scan_networks(priv, wait, HostCmd_ACT_GEN_GET, -				       NULL, &scan); - -	status = mwifiex_request_ioctl(priv, wait, status, wait_option); -	if (!status) { -		if (scan_resp) -			memcpy(scan_resp, &scan, -			       sizeof(struct mwifiex_scan_resp)); -	} - -	if (wait && (status != -EINPROGRESS)) -		kfree(wait); -	return status; -} - -/*   * Sends IOCTL request to get signal information.   *   * This function allocates the IOCTL request buffer, fills it   * with requisite parameters and calls the IOCTL handler.   */ -int mwifiex_get_signal_info(struct mwifiex_private *priv, u8 wait_option, +int mwifiex_get_signal_info(struct mwifiex_private *priv,  			    struct mwifiex_ds_get_signal *signal)  {  	struct mwifiex_ds_get_signal info; -	struct mwifiex_wait_queue *wait = NULL;  	int status = 0; -	/* Allocate wait buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; - +	memset(&info, 0, sizeof(struct mwifiex_ds_get_signal));  	info.selector = ALL_RSSI_INFO_MASK; -	status = mwifiex_get_info_signal(priv, wait, &info); +	/* Signal info can be obtained only if connected */ +	if (!priv->media_connected) { +		dev_dbg(priv->adapter->dev, +			"info: Can not get signal in disconnected state\n"); +		return -1; +	} + +	status = mwifiex_send_cmd_sync(priv, HostCmd_CMD_RSSI_INFO, +				       HostCmd_ACT_GEN_GET, 0, signal); -	status = mwifiex_request_ioctl(priv, wait, status, wait_option);  	if (!status) {  		if (signal)  			memcpy(signal, &info, @@ -1905,8 +1278,6 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, u8 wait_option,  			priv->w_stats.qual.noise = info.bcn_nf_avg;  	} -	if (wait && (status != -EINPROGRESS)) -		kfree(wait);  	return status;  } @@ -1919,14 +1290,7 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, u8 wait_option,  int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,  			int key_len, u8 key_index, int disable)  { -	struct mwifiex_wait_queue *wait = NULL;  	struct mwifiex_ds_encrypt_key encrypt_key; -	int status = 0; -	int ret = 0; - -	wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); -	if (!wait) -		return -ENOMEM;  	memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key));  	encrypt_key.key_len = key_len; @@ -1938,41 +1302,7 @@ int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,  		encrypt_key.key_disable = true;  	} -	status = mwifiex_sec_ioctl_encrypt_key(priv, wait, &encrypt_key); - -	if (mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT)) -		ret = -EFAULT; - -	kfree(wait); -	return ret; -} - -/* - * Sends IOCTL request to set power management parameters. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_drv_set_power(struct mwifiex_private *priv, bool power_on) -{ -	int ret = 0; -	int status = 0; -	struct mwifiex_wait_queue *wait = NULL; -	u32 ps_mode; - -	wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); -	if (!wait) -		return -ENOMEM; - -	ps_mode = power_on; -	status = mwifiex_pm_ioctl_ps_mode(priv, wait, &ps_mode, -					  HostCmd_ACT_GEN_SET); - -	ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); - -	kfree(wait); -	return ret; +	return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key);  }  /* @@ -1985,27 +1315,13 @@ int  mwifiex_get_ver_ext(struct mwifiex_private *priv)  {  	struct mwifiex_ver_ext ver_ext; -	struct mwifiex_wait_queue *wait = NULL; -	int status = 0; -	int ret = 0; -	u8 wait_option = MWIFIEX_IOCTL_WAIT; -	/* Allocate wait buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM; - -	/* get fw version */  	memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); -	status = mwifiex_get_info_ver_ext(priv, wait, &ver_ext); - -	ret = mwifiex_request_ioctl(priv, wait, status, wait_option); - -	if (ret) -		ret = -1; +	if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_VERSION_EXT, +				    HostCmd_ACT_GEN_GET, 0, &ver_ext)) +		return -1; -	kfree(wait); -	return ret; +	return 0;  }  /* @@ -2019,21 +1335,12 @@ mwifiex_get_stats_info(struct mwifiex_private *priv,  		       struct mwifiex_ds_get_stats *log)  {  	int ret = 0; -	int status = 0; -	struct mwifiex_wait_queue *wait = NULL;  	struct mwifiex_ds_get_stats get_log; -	u8 wait_option = MWIFIEX_IOCTL_WAIT; - -	/* Allocate wait buffer */ -	wait = mwifiex_alloc_fill_wait_queue(priv, wait_option); -	if (!wait) -		return -ENOMEM;  	memset(&get_log, 0, sizeof(struct mwifiex_ds_get_stats)); -	status = mwifiex_get_info_stats(priv, wait, &get_log); +	ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG, +				    HostCmd_ACT_GEN_GET, 0, &get_log); -	/* Send IOCTL request to MWIFIEX */ -	ret = mwifiex_request_ioctl(priv, wait, status, wait_option);  	if (!ret) {  		if (log)  			memcpy(log, &get_log, sizeof(struct @@ -2043,7 +1350,6 @@ mwifiex_get_stats_info(struct mwifiex_private *priv,  		priv->w_stats.discard.misc = get_log.ack_failure;  	} -	kfree(wait);  	return ret;  } @@ -2061,11 +1367,9 @@ mwifiex_get_stats_info(struct mwifiex_private *priv,   *      - CAU   */  static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, -					struct mwifiex_wait_queue *wait,  					struct mwifiex_ds_reg_rw *reg_rw,  					u16 action)  { -	int ret = 0;  	u16 cmd_no;  	switch (le32_to_cpu(reg_rw->type)) { @@ -2088,13 +1392,8 @@ static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv,  		return -1;  	} -	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, cmd_no, action, 0, wait, reg_rw); - -	if (!ret) -		ret = -EINPROGRESS; +	return mwifiex_send_cmd_sync(priv, cmd_no, action, 0, reg_rw); -	return ret;  }  /* @@ -2107,25 +1406,13 @@ int  mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type,  		  u32 reg_offset, u32 reg_value)  { -	int ret = 0; -	int status = 0; -	struct mwifiex_wait_queue *wait = NULL;  	struct mwifiex_ds_reg_rw reg_rw; -	wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); -	if (!wait) -		return -ENOMEM; -  	reg_rw.type = cpu_to_le32(reg_type);  	reg_rw.offset = cpu_to_le32(reg_offset);  	reg_rw.value = cpu_to_le32(reg_value); -	status = mwifiex_reg_mem_ioctl_reg_rw(priv, wait, ®_rw, -					      HostCmd_ACT_GEN_SET); - -	ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); -	kfree(wait); -	return ret; +	return mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_SET);  }  /* @@ -2139,50 +1426,18 @@ mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type,  		 u32 reg_offset, u32 *value)  {  	int ret = 0; -	int status = 0; -	struct mwifiex_wait_queue *wait = NULL;  	struct mwifiex_ds_reg_rw reg_rw; -	wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); -	if (!wait) -		return -ENOMEM; -  	reg_rw.type = cpu_to_le32(reg_type);  	reg_rw.offset = cpu_to_le32(reg_offset); -	status = mwifiex_reg_mem_ioctl_reg_rw(priv, wait, ®_rw, -					      HostCmd_ACT_GEN_GET); +	ret = mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_GET); -	ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT);  	if (ret)  		goto done;  	*value = le32_to_cpu(reg_rw.value);  done: -	kfree(wait); -	return ret; -} - -/* - * IOCTL request handler to read EEPROM. - * - * This function prepares the correct firmware command and - * issues it. - */ -static int -mwifiex_reg_mem_ioctl_read_eeprom(struct mwifiex_private *priv, -				  struct mwifiex_wait_queue *wait, -				  struct mwifiex_ds_read_eeprom *rd_eeprom) -{ -	int ret = 0; - -	/* Send request to firmware */ -	ret = mwifiex_prepare_cmd(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, -				  HostCmd_ACT_GEN_GET, 0, wait, rd_eeprom); - -	if (!ret) -		ret = -EINPROGRESS; -  	return ret;  } @@ -2197,25 +1452,17 @@ mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes,  		    u8 *value)  {  	int ret = 0; -	int status = 0; -	struct mwifiex_wait_queue *wait = NULL;  	struct mwifiex_ds_read_eeprom rd_eeprom; -	wait = mwifiex_alloc_fill_wait_queue(priv, MWIFIEX_IOCTL_WAIT); -	if (!wait) -		return -ENOMEM; -  	rd_eeprom.offset = cpu_to_le16((u16) offset);  	rd_eeprom.byte_count = cpu_to_le16((u16) bytes); -	status = mwifiex_reg_mem_ioctl_read_eeprom(priv, wait, &rd_eeprom); -	ret = mwifiex_request_ioctl(priv, wait, status, MWIFIEX_IOCTL_WAIT); -	if (ret) -		goto done; +	/* Send request to firmware */ +	ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, +				    HostCmd_ACT_GEN_GET, 0, &rd_eeprom); -	memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA); -done: -	kfree(wait); +	if (!ret) +		memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA);  	return ret;  } @@ -2344,7 +1591,6 @@ int  mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len)  {  	struct mwifiex_ds_misc_gen_ie gen_ie; -	int status = 0;  	if (ie_len > IW_CUSTOM_MAX)  		return -EFAULT; @@ -2352,8 +1598,7 @@ mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len)  	gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE;  	gen_ie.len = ie_len;  	memcpy(gen_ie.ie_data, ie, ie_len); -	status = mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET); -	if (status) +	if (mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET))  		return -EFAULT;  	return 0; diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index e8db6bd021c..5d37ef16012 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -51,7 +51,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,  	if (!skb->len) {  		dev_err(adapter->dev, "Tx: bad packet length: %d\n",  		       skb->len); -		tx_info->status_code = MWIFIEX_ERROR_PKT_SIZE_INVALID; +		tx_info->status_code = -1;  		return skb->data;  	} @@ -180,15 +180,11 @@ mwifiex_check_last_packet_indication(struct mwifiex_private *priv)  {  	struct mwifiex_adapter *adapter = priv->adapter;  	u8 ret = false; -	u8 prop_ps = true;  	if (!adapter->sleep_period.period)  		return ret; -	if (mwifiex_wmm_lists_empty(adapter)) { -		if ((priv->curr_bss_params.wmm_uapsd_enabled && -		     priv->wmm_qosinfo) || prop_ps) +	if (mwifiex_wmm_lists_empty(adapter))  			ret = true; -	}  	if (ret && !adapter->cmd_sent && !adapter->curr_cmd  	    && !is_command_pending(adapter)) { diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index f06923cb1c4..ce772e078db 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -36,7 +36,6 @@  int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,  			     struct sk_buff *skb)  { -	int ret = 0;  	struct mwifiex_private *priv =  		mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);  	struct rxpd *local_rx_pd; @@ -50,9 +49,8 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,  		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);  	rx_info->bss_index = priv->bss_index; -	ret = mwifiex_process_sta_rx_packet(adapter, skb); -	return ret; +	return mwifiex_process_sta_rx_packet(adapter, skb);  }  EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 205022aa52f..7ab4fb279f8 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c @@ -55,18 +55,12 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter)  }  /* - * IOCTL request handler to send function init/shutdown command + * This function sends init/shutdown command   * to firmware. - * - * This function prepares the correct firmware command and - * issues it.   */ -int mwifiex_misc_ioctl_init_shutdown(struct mwifiex_adapter *adapter, -				     struct mwifiex_wait_queue *wait, -				     u32 func_init_shutdown) +int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, +			     u32 func_init_shutdown)  { -	struct mwifiex_private *priv = adapter->priv[wait->bss_index]; -	int ret;  	u16 cmd;  	if (func_init_shutdown == MWIFIEX_FUNC_INIT) { @@ -74,19 +68,13 @@ int mwifiex_misc_ioctl_init_shutdown(struct mwifiex_adapter *adapter,  	} else if (func_init_shutdown == MWIFIEX_FUNC_SHUTDOWN) {  		cmd = HostCmd_CMD_FUNC_SHUTDOWN;  	} else { -		dev_err(adapter->dev, "unsupported parameter\n"); +		dev_err(priv->adapter->dev, "unsupported parameter\n");  		return -1;  	} -	/* Send command to firmware */ -	ret = mwifiex_prepare_cmd(priv, cmd, HostCmd_ACT_GEN_SET, -				  0, wait, NULL); - -	if (!ret) -		ret = -EINPROGRESS; - -	return ret; +	return mwifiex_send_cmd_sync(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL);  } +EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw);  /*   * IOCTL request handler to set/get debug information. @@ -222,31 +210,18 @@ int mwifiex_recv_complete(struct mwifiex_adapter *adapter,   * corresponding waiting function. Otherwise, it processes the   * IOCTL response and frees the response buffer.   */ -int mwifiex_ioctl_complete(struct mwifiex_adapter *adapter, -			   struct mwifiex_wait_queue *wait_queue, -			   int status) +int mwifiex_complete_cmd(struct mwifiex_adapter *adapter)  { -	enum mwifiex_error_code status_code = -		(enum mwifiex_error_code) wait_queue->status; - -	atomic_dec(&adapter->ioctl_pending); +	atomic_dec(&adapter->cmd_pending); +	dev_dbg(adapter->dev, "cmd completed: status=%d\n", +					adapter->cmd_wait_q.status); -	dev_dbg(adapter->dev, "cmd: IOCTL completed: status=%d," -			" status_code=%#x\n", status, status_code); +	adapter->cmd_wait_q.condition = true; -	if (wait_queue->enabled) { -		*wait_queue->condition = true; -		wait_queue->status = status; -		if (status && (status_code == MWIFIEX_ERROR_CMD_TIMEOUT)) -			dev_err(adapter->dev, "cmd timeout\n"); -		else -			wake_up_interruptible(wait_queue->wait); -	} else { -		if (status) -			dev_err(adapter->dev, "cmd failed: status_code=%#x\n", -			       status_code); -		kfree(wait_queue); -	} +	if (adapter->cmd_wait_q.status == -ETIMEDOUT) +		dev_err(adapter->dev, "cmd timeout\n"); +	else +		wake_up_interruptible(&adapter->cmd_wait_q.wait);  	return 0;  } diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 1cfbc6bed69..c009370f309 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -177,8 +177,7 @@ static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv)   * This function map ACs to TIDs.   */  static void -mwifiex_wmm_queue_priorities_tid(struct mwifiex_private *priv, -				 u8 queue_priority[]) +mwifiex_wmm_queue_priorities_tid(u8 queue_priority[])  {  	int i; @@ -247,7 +246,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,  		}  	} -	mwifiex_wmm_queue_priorities_tid(priv, priv->wmm.queue_priority); +	mwifiex_wmm_queue_priorities_tid(priv->wmm.queue_priority);  }  /* @@ -416,7 +415,7 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter)  		priv = adapter->priv[j];  		if (priv) {  			for (i = 0; i < MAX_NUM_TID; i++) -				if (!mwifiex_wmm_is_ra_list_empty(adapter, +				if (!mwifiex_wmm_is_ra_list_empty(  					     &priv->wmm.tid_tbl_ptr[i].ra_list))  					return false;  		} @@ -974,7 +973,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,  	struct sk_buff *skb, *skb_next;  	struct mwifiex_tx_param tx_param;  	struct mwifiex_adapter *adapter = priv->adapter; -	int status = 0;  	struct mwifiex_txinfo *tx_info;  	if (skb_queue_empty(&ptr->skb_head)) { @@ -1001,9 +999,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,  	tx_param.next_pkt_len = ((skb_next) ? skb_next->len +  				sizeof(struct txpd) : 0); -	status = mwifiex_process_tx(priv, skb, &tx_param); - -	if (status == -EBUSY) { +	if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) {  		/* Queue the packet back at the head */  		spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); @@ -1161,7 +1157,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)  	if (!ptr)  		return -1; -	tid = mwifiex_get_tid(priv->adapter, ptr); +	tid = mwifiex_get_tid(ptr);  	dev_dbg(adapter->dev, "data: tid=%d\n", tid); @@ -1186,14 +1182,14 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)  		/* ra_list_spinlock has been freed in  		   mwifiex_send_single_packet() */  	} else { -		if (mwifiex_is_ampdu_allowed(priv, ptr, tid)) { -			if (mwifiex_is_ba_stream_avail(priv)) { +		if (mwifiex_is_ampdu_allowed(priv, tid)) { +			if (mwifiex_space_avail_for_new_ba_stream(adapter)) {  				mwifiex_11n_create_tx_ba_stream_tbl(priv,  						ptr->ra, tid,  						BA_STREAM_SETUP_INPROGRESS);  				mwifiex_send_addba(priv, tid, ptr->ra);  			} else if (mwifiex_find_stream_to_delete -				   (priv, ptr, tid, &tid_del, ra)) { +				   (priv, tid, &tid_del, ra)) {  				mwifiex_11n_create_tx_ba_stream_tbl(priv,  						ptr->ra, tid,  						BA_STREAM_SETUP_INPROGRESS); @@ -1202,7 +1198,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)  		}  /* Minimum number of AMSDU */  #define MIN_NUM_AMSDU 2 -		if (mwifiex_is_amsdu_allowed(priv, ptr, tid) && +		if (mwifiex_is_amsdu_allowed(priv, tid) &&  		    (mwifiex_num_pkts_in_txq(priv, ptr, adapter->tx_buf_size) >=  		     MIN_NUM_AMSDU))  			mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, @@ -1232,6 +1228,4 @@ mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter)  		if (mwifiex_dequeue_tx_packet(adapter))  			break;  	} while (true); - -	return;  } diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h index 241f1b0b77f..fcea1f68792 100644 --- a/drivers/net/wireless/mwifiex/wmm.h +++ b/drivers/net/wireless/mwifiex/wmm.h @@ -35,8 +35,7 @@ enum ieee_types_wmm_ecw_bitmasks {   * This function retrieves the TID of the given RA list.   */  static inline int -mwifiex_get_tid(struct mwifiex_adapter *adapter, -		struct mwifiex_ra_list_tbl *ptr) +mwifiex_get_tid(struct mwifiex_ra_list_tbl *ptr)  {  	struct sk_buff *skb; @@ -52,7 +51,7 @@ mwifiex_get_tid(struct mwifiex_adapter *adapter,   * This function gets the length of a list.   */  static inline int -mwifiex_wmm_list_len(struct mwifiex_adapter *adapter, struct list_head *head) +mwifiex_wmm_list_len(struct list_head *head)  {  	struct list_head *pos;  	int count = 0; @@ -67,8 +66,7 @@ mwifiex_wmm_list_len(struct mwifiex_adapter *adapter, struct list_head *head)   * This function checks if a RA list is empty or not.   */  static inline u8 -mwifiex_wmm_is_ra_list_empty(struct mwifiex_adapter *adapter, -			     struct list_head *ra_list_hhead) +mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead)  {  	struct mwifiex_ra_list_tbl *ra_list;  	int is_list_empty; diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 8913180a7bd..28ebaec80be 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -289,10 +289,17 @@ struct mwl8k_vif {  #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))  #define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8)) +struct tx_traffic_info { +	u32 start_time; +	u32 pkts; +}; + +#define MWL8K_MAX_TID 8  struct mwl8k_sta {  	/* Index into station database. Returned by UPDATE_STADB.  */  	u8 peer_id;  	u8 is_ampdu_allowed; +	struct tx_traffic_info tx_stats[MWL8K_MAX_TID];  };  #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) @@ -701,7 +708,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)  			       "helper image\n", pci_name(priv->pdev));  			return rc;  		} -		msleep(5); +		msleep(20);  		rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);  	} else { @@ -823,8 +830,8 @@ static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb)  	/*  	 * Make sure the packet header is in the DMA header format (4-address  	 * without QoS), the necessary crypto padding between the header and the -	 * payload has already been provided by mac80211, but it doesn't add tail -	 * padding when HW crypto is enabled. +	 * payload has already been provided by mac80211, but it doesn't add +	 * tail padding when HW crypto is enabled.  	 *  	 * We have the following trailer padding requirements:  	 * - WEP: 4 trailer bytes (ICV) @@ -1487,9 +1494,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)  		if (timeout) {  			WARN_ON(priv->pending_tx_pkts); -			if (retry) { +			if (retry)  				wiphy_notice(hw->wiphy, "tx rings drained\n"); -			}  			break;  		} @@ -1649,8 +1655,8 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)  		/* Rate control is happening in the firmware.  		 * Ensure no tx rate is being reported.  		 */ -                info->status.rates[0].idx = -1; -                info->status.rates[0].count = 1; +		info->status.rates[0].idx = -1; +		info->status.rates[0].count = 1;  		if (MWL8K_TXD_SUCCESS(status))  			info->flags |= IEEE80211_TX_STAT_ACK; @@ -1688,7 +1694,7 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)  }  /* caller must hold priv->stream_lock when calling the stream functions */ -struct mwl8k_ampdu_stream * +static struct mwl8k_ampdu_stream *  mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid)  {  	struct mwl8k_ampdu_stream *stream; @@ -1755,6 +1761,41 @@ mwl8k_lookup_stream(struct ieee80211_hw *hw, u8 *addr, u8 tid)  	return NULL;  } +#define MWL8K_AMPDU_PACKET_THRESHOLD 64 +static inline bool mwl8k_ampdu_allowed(struct ieee80211_sta *sta, u8 tid) +{ +	struct mwl8k_sta *sta_info = MWL8K_STA(sta); +	struct tx_traffic_info *tx_stats; + +	BUG_ON(tid >= MWL8K_MAX_TID); +	tx_stats = &sta_info->tx_stats[tid]; + +	return sta_info->is_ampdu_allowed && +		tx_stats->pkts > MWL8K_AMPDU_PACKET_THRESHOLD; +} + +static inline void mwl8k_tx_count_packet(struct ieee80211_sta *sta, u8 tid) +{ +	struct mwl8k_sta *sta_info = MWL8K_STA(sta); +	struct tx_traffic_info *tx_stats; + +	BUG_ON(tid >= MWL8K_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 void  mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)  { @@ -1841,6 +1882,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)  	    skb->protocol != cpu_to_be16(ETH_P_PAE) &&  	    sta->ht_cap.ht_supported && priv->ap_fw) {  		tid = qos & 0xf; +		mwl8k_tx_count_packet(sta, tid);  		spin_lock(&priv->stream_lock);  		stream = mwl8k_lookup_stream(hw, sta->addr, tid);  		if (stream != NULL) { @@ -1881,7 +1923,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)  			 * prevents sequence number mismatch at the recepient  			 * as described above.  			 */ -			if (MWL8K_STA(sta)->is_ampdu_allowed) { +			if (mwl8k_ampdu_allowed(sta, tid)) {  				stream = mwl8k_add_stream(hw, sta, tid);  				if (stream != NULL)  					start_ba_session = true; @@ -2657,7 +2699,7 @@ struct mwl8k_cmd_tx_power {  	__le16 bw;  	__le16 sub_ch;  	__le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; -} __attribute__((packed)); +} __packed;  static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,  				     struct ieee80211_conf *conf, @@ -3520,13 +3562,13 @@ static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw,  #define BASTREAM_FLAG_DIRECTION_UPSTREAM	0x00  #define BASTREAM_FLAG_IMMEDIATE_TYPE		0x01 -enum { +enum ba_stream_action_type {  	MWL8K_BA_CREATE,  	MWL8K_BA_UPDATE,  	MWL8K_BA_DESTROY,  	MWL8K_BA_FLUSH,  	MWL8K_BA_CHECK, -} ba_stream_action_type; +};  struct mwl8k_create_ba_stream { @@ -3780,7 +3822,7 @@ struct mwl8k_cmd_update_encryption {  	__u8 mac_addr[6];  	__u8 encr_type; -} __attribute__((packed)); +} __packed;  struct mwl8k_cmd_set_key {  	struct mwl8k_cmd_pkt header; @@ -3800,7 +3842,7 @@ struct mwl8k_cmd_set_key {  	__le16 tkip_tsc_low;  	__le32 tkip_tsc_high;  	__u8 mac_addr[6]; -} __attribute__((packed)); +} __packed;  enum {  	MWL8K_ENCR_ENABLE, @@ -4285,6 +4327,8 @@ static int mwl8k_start(struct ieee80211_hw *hw)  	/* Enable interrupts */  	iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); +	iowrite32(MWL8K_A2H_EVENTS, +		  priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);  	rc = mwl8k_fw_lock(hw);  	if (!rc) { @@ -4502,7 +4546,7 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  			   struct ieee80211_bss_conf *info, u32 changed)  {  	struct mwl8k_priv *priv = hw->priv; -	u32 ap_legacy_rates; +	u32 ap_legacy_rates = 0;  	u8 ap_mcs_rates[16];  	int rc; @@ -5283,7 +5327,8 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw)  	iowrite32(MWL8K_A2H_INT_TX_DONE|MWL8K_A2H_INT_RX_READY|  		  MWL8K_A2H_INT_BA_WATCHDOG,  		  priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); -	iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); +	iowrite32(MWL8K_A2H_INT_OPC_DONE, +		  priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);  	rc = request_irq(priv->pdev->irq, mwl8k_interrupt,  			 IRQF_SHARED, MWL8K_NAME, hw); diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index f630552427b..c4577310828 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -59,7 +59,6 @@ config RT2800PCI  	select RT2800_LIB  	select RT2X00_LIB_PCI if PCI  	select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X -	select RT2X00_LIB_HT  	select RT2X00_LIB_FIRMWARE  	select RT2X00_LIB_CRYPTO  	select CRC_CCITT @@ -74,17 +73,13 @@ config RT2800PCI  if RT2800PCI  config RT2800PCI_RT33XX -	bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)" -	depends on EXPERIMENTAL -	default n +	bool "rt2800pci - Include support for rt33xx devices" +	default y  	---help---  	  This adds support for rt33xx wireless chipset family to the  	  rt2800pci driver.  	  Supported chips: RT3390 -	  Support for these devices is non-functional at the moment and is -	  intended for testers and developers. -  config RT2800PCI_RT35XX  	bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"  	depends on EXPERIMENTAL @@ -100,15 +95,12 @@ config RT2800PCI_RT35XX  config RT2800PCI_RT53XX         bool "rt2800-pci - Include support for rt53xx devices (EXPERIMENTAL)"         depends on EXPERIMENTAL -       default n +       default y         ---help---           This adds support for rt53xx wireless chipset family to the           rt2800pci driver.           Supported chips: RT5390 -         Support for these devices is non-functional at the moment and is -         intended for testers and developers. -  endif  config RT2500USB @@ -140,7 +132,6 @@ config RT2800USB  	depends on USB  	select RT2800_LIB  	select RT2X00_LIB_USB -	select RT2X00_LIB_HT  	select RT2X00_LIB_FIRMWARE  	select RT2X00_LIB_CRYPTO  	select CRC_CCITT @@ -153,17 +144,13 @@ config RT2800USB  if RT2800USB  config RT2800USB_RT33XX -	bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)" -	depends on EXPERIMENTAL -	default n +	bool "rt2800usb - Include support for rt33xx devices" +	default y  	---help---  	  This adds support for rt33xx wireless chipset family to the  	  rt2800usb driver.  	  Supported chips: RT3370 -	  Support for these devices is non-functional at the moment and is -	  intended for testers and developers. -  config RT2800USB_RT35XX  	bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"  	depends on EXPERIMENTAL @@ -207,9 +194,6 @@ config RT2X00_LIB_USB  config RT2X00_LIB  	tristate -config RT2X00_LIB_HT -	boolean -  config RT2X00_LIB_FIRMWARE  	boolean  	select FW_LOADER diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index 97133985829..349d5b8284a 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile @@ -7,7 +7,6 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS)	+= rt2x00debug.o  rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO)	+= rt2x00crypto.o  rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)	+= rt2x00firmware.o  rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)	+= rt2x00leds.o -rt2x00lib-$(CONFIG_RT2X00_LIB_HT)	+= rt2x00ht.o  obj-$(CONFIG_RT2X00_LIB)		+= rt2x00lib.o  obj-$(CONFIG_RT2X00_LIB_PCI)		+= rt2x00pci.o diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 137a24e520d..937f9e8bf05 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1314,8 +1314,8 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,  	}  } -static void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, -				       struct rt2x00_field32 irq_field) +static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, +					      struct rt2x00_field32 irq_field)  {  	u32 reg; @@ -1536,13 +1536,13 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Detect if this device has an hardware controlled radio.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);  	/*  	 * Check if the BBP tuning should be enabled.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING)) -		__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); +		__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);  	return 0;  } @@ -1640,9 +1640,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)  	/*  	 * This device requires the atim queue and DMA-mapped skbs.  	 */ -	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags); +	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);  	/*  	 * Set the rssi offset. @@ -1720,6 +1720,9 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {  	.tx_last_beacon		= rt2400pci_tx_last_beacon,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.flush			= rt2x00mac_flush, +	.set_antenna		= rt2x00mac_set_antenna, +	.get_antenna		= rt2x00mac_get_antenna, +	.get_ringparam		= rt2x00mac_get_ringparam,  };  static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { @@ -1740,6 +1743,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {  	.start_queue		= rt2400pci_start_queue,  	.kick_queue		= rt2400pci_kick_queue,  	.stop_queue		= rt2400pci_stop_queue, +	.flush_queue		= rt2x00pci_flush_queue,  	.write_tx_desc		= rt2400pci_write_tx_desc,  	.write_beacon		= rt2400pci_write_beacon,  	.fill_rxdone		= rt2400pci_fill_rxdone, @@ -1801,10 +1805,11 @@ static const struct rt2x00_ops rt2400pci_ops = {   * RT2400pci module information.   */  static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = { -	{ PCI_DEVICE(0x1814, 0x0101), PCI_DEVICE_DATA(&rt2400pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0101) },  	{ 0, }  }; +  MODULE_AUTHOR(DRV_PROJECT);  MODULE_VERSION(DRV_VERSION);  MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver."); @@ -1812,10 +1817,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards");  MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);  MODULE_LICENSE("GPL"); +static int rt2400pci_probe(struct pci_dev *pci_dev, +			   const struct pci_device_id *id) +{ +	return rt2x00pci_probe(pci_dev, &rt2400pci_ops); +} +  static struct pci_driver rt2400pci_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt2400pci_device_table, -	.probe		= rt2x00pci_probe, +	.probe		= rt2400pci_probe,  	.remove		= __devexit_p(rt2x00pci_remove),  	.suspend	= rt2x00pci_suspend,  	.resume		= rt2x00pci_resume, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 198fc0a0d77..d27d7b8ba3b 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1446,8 +1446,8 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,  	}  } -static void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, -				       struct rt2x00_field32 irq_field) +static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, +					      struct rt2x00_field32 irq_field)  {  	u32 reg; @@ -1687,14 +1687,14 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Detect if this device has an hardware controlled radio.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);  	/*  	 * Check if the BBP tuning should be enabled.  	 */  	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);  	if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE)) -		__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); +		__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);  	/*  	 * Read the RSSI <-> dBm offset information. @@ -1958,9 +1958,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)  	/*  	 * This device requires the atim queue and DMA-mapped skbs.  	 */ -	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags); +	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);  	/*  	 * Set the rssi offset. @@ -2013,6 +2013,9 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {  	.tx_last_beacon		= rt2500pci_tx_last_beacon,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.flush			= rt2x00mac_flush, +	.set_antenna		= rt2x00mac_set_antenna, +	.get_antenna		= rt2x00mac_get_antenna, +	.get_ringparam		= rt2x00mac_get_ringparam,  };  static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { @@ -2033,6 +2036,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {  	.start_queue		= rt2500pci_start_queue,  	.kick_queue		= rt2500pci_kick_queue,  	.stop_queue		= rt2500pci_stop_queue, +	.flush_queue		= rt2x00pci_flush_queue,  	.write_tx_desc		= rt2500pci_write_tx_desc,  	.write_beacon		= rt2500pci_write_beacon,  	.fill_rxdone		= rt2500pci_fill_rxdone, @@ -2094,7 +2098,7 @@ static const struct rt2x00_ops rt2500pci_ops = {   * RT2500pci module information.   */  static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = { -	{ PCI_DEVICE(0x1814, 0x0201), PCI_DEVICE_DATA(&rt2500pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0201) },  	{ 0, }  }; @@ -2105,10 +2109,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards");  MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);  MODULE_LICENSE("GPL"); +static int rt2500pci_probe(struct pci_dev *pci_dev, +			   const struct pci_device_id *id) +{ +	return rt2x00pci_probe(pci_dev, &rt2500pci_ops); +} +  static struct pci_driver rt2500pci_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt2500pci_device_table, -	.probe		= rt2x00pci_probe, +	.probe		= rt2500pci_probe,  	.remove		= __devexit_p(rt2x00pci_remove),  	.suspend	= rt2x00pci_suspend,  	.resume		= rt2x00pci_resume, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index eac788160f5..b21f81231a0 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1519,7 +1519,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Detect if this device has an hardware controlled radio.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);  	/*  	 * Read the RSSI <-> dBm offset information. @@ -1790,13 +1790,13 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)  	/*  	 * This device requires the atim queue  	 */ -	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); +	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags);  	if (!modparam_nohwcrypt) { -		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); -		__set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); +		__set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags);  	} -	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags); +	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);  	/*  	 * Set the rssi offset. @@ -1823,6 +1823,9 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {  	.conf_tx		= rt2x00mac_conf_tx,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.flush			= rt2x00mac_flush, +	.set_antenna		= rt2x00mac_set_antenna, +	.get_antenna		= rt2x00mac_get_antenna, +	.get_ringparam		= rt2x00mac_get_ringparam,  };  static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { @@ -1904,54 +1907,54 @@ static const struct rt2x00_ops rt2500usb_ops = {   */  static struct usb_device_id rt2500usb_device_table[] = {  	/* ASUS */ -	{ USB_DEVICE(0x0b05, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1707), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0b05, 0x1706) }, +	{ USB_DEVICE(0x0b05, 0x1707) },  	/* Belkin */ -	{ USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x050d, 0x7051), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x050d, 0x7050) }, +	{ USB_DEVICE(0x050d, 0x7051) },  	/* Cisco Systems */ -	{ USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x13b1, 0x000d) }, +	{ USB_DEVICE(0x13b1, 0x0011) }, +	{ USB_DEVICE(0x13b1, 0x001a) },  	/* Conceptronic */ -	{ USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x14b2, 0x3c02) },  	/* D-LINK */ -	{ USB_DEVICE(0x2001, 0x3c00), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x2001, 0x3c00) },  	/* Gigabyte */ -	{ USB_DEVICE(0x1044, 0x8001), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x1044, 0x8007), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x1044, 0x8001) }, +	{ USB_DEVICE(0x1044, 0x8007) },  	/* Hercules */ -	{ USB_DEVICE(0x06f8, 0xe000), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x06f8, 0xe000) },  	/* Melco */ -	{ USB_DEVICE(0x0411, 0x005e), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0066), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0067), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x0411, 0x008b), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0097), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0411, 0x005e) }, +	{ USB_DEVICE(0x0411, 0x0066) }, +	{ USB_DEVICE(0x0411, 0x0067) }, +	{ USB_DEVICE(0x0411, 0x008b) }, +	{ USB_DEVICE(0x0411, 0x0097) },  	/* MSI */ -	{ USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x6869), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0db0, 0x6861) }, +	{ USB_DEVICE(0x0db0, 0x6865) }, +	{ USB_DEVICE(0x0db0, 0x6869) },  	/* Ralink */ -	{ USB_DEVICE(0x148f, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x148f, 0x1706) }, +	{ USB_DEVICE(0x148f, 0x2570) }, +	{ USB_DEVICE(0x148f, 0x9020) },  	/* Sagem */ -	{ USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x079b, 0x004b) },  	/* Siemens */ -	{ USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0681, 0x3c06) },  	/* SMC */ -	{ USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0707, 0xee13) },  	/* Spairon */ -	{ USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x114b, 0x0110) },  	/* SURECOM */ -	{ USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0769, 0x11f3) },  	/* Trust */ -	{ USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0eb0, 0x9020) },  	/* VTech */ -	{ USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0f88, 0x3012) },  	/* Zinwell */ -	{ USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x5a57, 0x0260) },  	{ 0, }  }; @@ -1962,10 +1965,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards");  MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);  MODULE_LICENSE("GPL"); +static int rt2500usb_probe(struct usb_interface *usb_intf, +			   const struct usb_device_id *id) +{ +	return rt2x00usb_probe(usb_intf, &rt2500usb_ops); +} +  static struct usb_driver rt2500usb_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt2500usb_device_table, -	.probe		= rt2x00usb_probe, +	.probe		= rt2500usb_probe,  	.disconnect	= rt2x00usb_disconnect,  	.suspend	= rt2x00usb_suspend,  	.resume		= rt2x00usb_resume, diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 6331c61957a..5cd096e2ae3 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -730,34 +730,20 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)  	struct data_queue *queue;  	struct queue_entry *entry;  	u32 reg; -	u8 pid; -	int i; +	u8 qid; -	/* -	 * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO -	 * at most X times and also stop processing once the TX_STA_FIFO_VALID -	 * flag is not set anymore. -	 * -	 * The legacy drivers use X=TX_RING_SIZE but state in a comment -	 * that the TX_STA_FIFO stack has a size of 16. We stick to our -	 * tx ring size for now. -	 */ -	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { -		rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); -		if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) -			break; +	while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { -		/* -		 * Skip this entry when it contains an invalid -		 * queue identication number. +		/* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus +		 * qid is guaranteed to be one of the TX QIDs  		 */ -		pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); -		if (pid >= QID_RX) -			continue; - -		queue = rt2x00queue_get_tx_queue(rt2x00dev, pid); -		if (unlikely(!queue)) +		qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); +		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); +		if (unlikely(!queue)) { +			WARNING(rt2x00dev, "Got TX status for an unavailable " +					   "queue %u, dropping\n", qid);  			continue; +		}  		/*  		 * Inside each queue, we process each entry in a chronological @@ -949,25 +935,49 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,  	unsigned int ledmode =  		rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,  				   EEPROM_FREQ_LED_MODE); +	u32 reg; -	if (led->type == LED_TYPE_RADIO) { -		rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, -				      enabled ? 0x20 : 0); -	} else if (led->type == LED_TYPE_ASSOC) { -		rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, -				      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); -	} else if (led->type == LED_TYPE_QUALITY) { -		/* -		 * The brightness is divided into 6 levels (0 - 5), -		 * The specs tell us the following levels: -		 *	0, 1 ,3, 7, 15, 31 -		 * to determine the level in a simple way we can simply -		 * work with bitshifting: -		 *	(1 << level) - 1 -		 */ -		rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, -				      (1 << brightness / (LED_FULL / 6)) - 1, -				      polarity); +	/* Check for SoC (SOC devices don't support MCU requests) */ +	if (rt2x00_is_soc(led->rt2x00dev)) { +		rt2800_register_read(led->rt2x00dev, LED_CFG, ®); + +		/* Set LED Polarity */ +		rt2x00_set_field32(®, LED_CFG_LED_POLAR, polarity); + +		/* Set LED Mode */ +		if (led->type == LED_TYPE_RADIO) { +			rt2x00_set_field32(®, LED_CFG_G_LED_MODE, +					   enabled ? 3 : 0); +		} else if (led->type == LED_TYPE_ASSOC) { +			rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, +					   enabled ? 3 : 0); +		} else if (led->type == LED_TYPE_QUALITY) { +			rt2x00_set_field32(®, LED_CFG_R_LED_MODE, +					   enabled ? 3 : 0); +		} + +		rt2800_register_write(led->rt2x00dev, LED_CFG, reg); + +	} else { +		if (led->type == LED_TYPE_RADIO) { +			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, +					      enabled ? 0x20 : 0); +		} else if (led->type == LED_TYPE_ASSOC) { +			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, +					      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); +		} else if (led->type == LED_TYPE_QUALITY) { +			/* +			 * The brightness is divided into 6 levels (0 - 5), +			 * The specs tell us the following levels: +			 *	0, 1 ,3, 7, 15, 31 +			 * to determine the level in a simple way we can simply +			 * work with bitshifting: +			 *	(1 << level) - 1 +			 */ +			rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, +					      (1 << brightness / (LED_FULL / 6)) - 1, +					      polarity); +		}  	}  } @@ -1221,6 +1231,25 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,  		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®);  		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync);  		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + +		if (conf->sync == TSF_SYNC_AP_NONE) { +			/* +			 * Tune beacon queue transmit parameters for AP mode +			 */ +			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 0); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 1); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 0); +			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); +		} else { +			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 4); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 2); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 16); +			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); +		}  	}  	if (flags & CONFIG_UPDATE_MAC) { @@ -1739,8 +1768,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	if (rf->channel <= 14) {  		if (!rt2x00_rt(rt2x00dev, RT5390)) { -			if (test_bit(CONFIG_EXTERNAL_LNA_BG, -				     &rt2x00dev->flags)) { +			if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, +				     &rt2x00dev->cap_flags)) {  				rt2800_bbp_write(rt2x00dev, 82, 0x62);  				rt2800_bbp_write(rt2x00dev, 75, 0x46);  			} else { @@ -1751,7 +1780,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	} else {  		rt2800_bbp_write(rt2x00dev, 82, 0xf2); -		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) +		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))  			rt2800_bbp_write(rt2x00dev, 75, 0x46);  		else  			rt2800_bbp_write(rt2x00dev, 75, 0x50); @@ -1984,7 +2013,7 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,  	if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))  		return txpower; -	if (test_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags)) { +	if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {  		/*  		 * Check if eirp txpower exceed txpower_limit.  		 * We use OFDM 6M as criterion and its eirp txpower @@ -2384,7 +2413,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	} else if (rt2800_is_305x_soc(rt2x00dev)) {  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); -		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f); +		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);  	} else if (rt2x00_rt(rt2x00dev, RT5390)) {  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); @@ -3285,8 +3314,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  		    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||  		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||  		    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { -			if (!test_bit(CONFIG_EXTERNAL_LNA_BG, -				      &rt2x00dev->flags)) +			if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG, +				      &rt2x00dev->cap_flags))  				rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);  		}  		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); @@ -3709,15 +3738,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)  	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);  	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G)) -		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); +		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);  	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G)) -		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); +		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);  	/*  	 * Detect if this device has an hardware controlled radio.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);  	/*  	 * Store led settings, for correct led behaviour. @@ -3737,7 +3766,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)  	if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <  					EIRP_MAX_TX_POWER_LIMIT) -		__set_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags); +		__set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);  	return 0;  } diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index adc3534254d..08d3947fcb2 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -66,7 +66,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)  		return;  	for (i = 0; i < 200; i++) { -		rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); +		rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, ®);  		if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||  		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || @@ -80,8 +80,8 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)  	if (i == 200)  		ERROR(rt2x00dev, "MCU request failed, no response from hardware\n"); -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); +	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); +	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);  }  #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) @@ -105,7 +105,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)  	struct rt2x00_dev *rt2x00dev = eeprom->data;  	u32 reg; -	rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); +	rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®);  	eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);  	eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); @@ -127,7 +127,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)  	rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT,  			   !!eeprom->reg_chip_select); -	rt2800_register_write(rt2x00dev, E2PROM_CSR, reg); +	rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg);  }  static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) @@ -135,7 +135,7 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)  	struct eeprom_93cx6 eeprom;  	u32 reg; -	rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); +	rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®);  	eeprom.data = rt2x00dev;  	eeprom.register_read = rt2800pci_eepromregister_read; @@ -195,9 +195,9 @@ static void rt2800pci_start_queue(struct data_queue *queue)  	switch (queue->qid) {  	case QID_RX: -		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); +		rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®);  		rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); -		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +		rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);  		break;  	case QID_BEACON:  		/* @@ -207,15 +207,15 @@ static void rt2800pci_start_queue(struct data_queue *queue)  		tasklet_enable(&rt2x00dev->tbtt_tasklet);  		tasklet_enable(&rt2x00dev->pretbtt_tasklet); -		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); +		rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®);  		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1);  		rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1);  		rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); -		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); +		rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); -		rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); +		rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, ®);  		rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); -		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); +		rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);  		break;  	default:  		break; @@ -233,11 +233,13 @@ static void rt2800pci_kick_queue(struct data_queue *queue)  	case QID_AC_BE:  	case QID_AC_BK:  		entry = rt2x00queue_get_entry(queue, Q_INDEX); -		rt2800_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), entry->entry_idx); +		rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), +					 entry->entry_idx);  		break;  	case QID_MGMT:  		entry = rt2x00queue_get_entry(queue, Q_INDEX); -		rt2800_register_write(rt2x00dev, TX_CTX_IDX(5), entry->entry_idx); +		rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(5), +					 entry->entry_idx);  		break;  	default:  		break; @@ -251,20 +253,20 @@ static void rt2800pci_stop_queue(struct data_queue *queue)  	switch (queue->qid) {  	case QID_RX: -		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); +		rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®);  		rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); -		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +		rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);  		break;  	case QID_BEACON: -		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); +		rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®);  		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0);  		rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0);  		rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); -		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); +		rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); -		rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); +		rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, ®);  		rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); -		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); +		rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);  		/*  		 * Wait for tbtt tasklets to finish. @@ -295,7 +297,7 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,  	 */  	reg = 0;  	rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg); +	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg);  	/*  	 * Write firmware to device. @@ -303,11 +305,11 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,  	rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,  				   data, len); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); +	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); +	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); -	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +	rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); +	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);  	return 0;  } @@ -351,7 +353,7 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)  		 * Set RX IDX in register to inform hardware that we have  		 * handled this entry and it is available for reuse again.  		 */ -		rt2800_register_write(rt2x00dev, RX_CRX_IDX, +		rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,  				      entry->entry_idx);  	} else {  		rt2x00_desc_read(entry_priv->desc, 1, &word); @@ -369,45 +371,51 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)  	 * Initialize registers.  	 */  	entry_priv = rt2x00dev->tx[0].entries[0].priv_data; -	rt2800_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); -	rt2800_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit); -	rt2800_register_write(rt2x00dev, TX_CTX_IDX0, 0); -	rt2800_register_write(rt2x00dev, TX_DTX_IDX0, 0); +	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); +	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0, +				 rt2x00dev->tx[0].limit); +	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0); +	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0);  	entry_priv = rt2x00dev->tx[1].entries[0].priv_data; -	rt2800_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); -	rt2800_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit); -	rt2800_register_write(rt2x00dev, TX_CTX_IDX1, 0); -	rt2800_register_write(rt2x00dev, TX_DTX_IDX1, 0); +	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); +	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1, +				 rt2x00dev->tx[1].limit); +	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0); +	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0);  	entry_priv = rt2x00dev->tx[2].entries[0].priv_data; -	rt2800_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); -	rt2800_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit); -	rt2800_register_write(rt2x00dev, TX_CTX_IDX2, 0); -	rt2800_register_write(rt2x00dev, TX_DTX_IDX2, 0); +	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); +	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2, +				 rt2x00dev->tx[2].limit); +	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0); +	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0);  	entry_priv = rt2x00dev->tx[3].entries[0].priv_data; -	rt2800_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); -	rt2800_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit); -	rt2800_register_write(rt2x00dev, TX_CTX_IDX3, 0); -	rt2800_register_write(rt2x00dev, TX_DTX_IDX3, 0); +	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); +	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3, +				 rt2x00dev->tx[3].limit); +	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0); +	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0);  	entry_priv = rt2x00dev->rx->entries[0].priv_data; -	rt2800_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); -	rt2800_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit); -	rt2800_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1); -	rt2800_register_write(rt2x00dev, RX_DRX_IDX, 0); +	rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); +	rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT, +				 rt2x00dev->rx[0].limit); +	rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, +				 rt2x00dev->rx[0].limit - 1); +	rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0);  	/*  	 * Enable global DMA configuration  	 */ -	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); +	rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);  	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);  	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);  	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); -	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); +	rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); -	rt2800_register_write(rt2x00dev, DELAY_INT_CFG, 0); +	rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0);  	return 0;  } @@ -427,8 +435,8 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,  	 * should clear the register to assure a clean state.  	 */  	if (state == STATE_RADIO_IRQ_ON) { -		rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); -		rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); +		rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); +		rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);  		/*  		 * Enable tasklets. The beacon related tasklets are @@ -440,7 +448,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,  	}  	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); -	rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); +	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®);  	rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, 0);  	rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, 0);  	rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, mask); @@ -459,7 +467,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(®, INT_MASK_CSR_GPTIMER, 0);  	rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, 0);  	rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, 0); -	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); +	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);  	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);  	if (state == STATE_RADIO_IRQ_OFF) { @@ -480,7 +488,7 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)  	/*  	 * Reset DMA indexes  	 */ -	rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); +	rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®);  	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1);  	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1);  	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); @@ -488,26 +496,26 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1);  	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1);  	rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); -	rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); +	rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); +	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); +	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);  	if (rt2x00_rt(rt2x00dev, RT5390)) { -		rt2800_register_read(rt2x00dev, AUX_CTRL, ®); +		rt2x00pci_register_read(rt2x00dev, AUX_CTRL, ®);  		rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1);  		rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); -		rt2800_register_write(rt2x00dev, AUX_CTRL, reg); +		rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg);  	} -	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); +	rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); -	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); +	rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®);  	rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1);  	rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); -	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +	rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); -	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); +	rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);  	return 0;  } @@ -525,8 +533,8 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)  {  	if (rt2x00_is_soc(rt2x00dev)) {  		rt2800_disable_radio(rt2x00dev); -		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); -		rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); +		rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0); +		rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);  	}  } @@ -537,8 +545,10 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,  		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02);  		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);  	} else if (state == STATE_SLEEP) { -		rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff); -		rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff); +		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, +					 0xffffffff); +		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, +					 0xffffffff);  		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01);  	} @@ -768,8 +778,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)  	return !max_tx_done;  } -static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, -				       struct rt2x00_field32 irq_field) +static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, +					      struct rt2x00_field32 irq_field)  {  	u32 reg; @@ -778,9 +788,9 @@ static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,  	 * access needs locking.  	 */  	spin_lock_irq(&rt2x00dev->irqmask_lock); -	rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); +	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®);  	rt2x00_set_field32(®, irq_field, 1); -	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); +	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);  	spin_unlock_irq(&rt2x00dev->irqmask_lock);  } @@ -851,7 +861,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)  	 * need to lock the kfifo.  	 */  	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { -		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status); +		rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &status);  		if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))  			break; @@ -873,8 +883,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)  	u32 reg, mask;  	/* Read status and ACK all interrupts */ -	rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); -	rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); +	rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); +	rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);  	if (!reg)  		return IRQ_NONE; @@ -914,9 +924,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)  	 * the tasklet will reenable the appropriate interrupts.  	 */  	spin_lock(&rt2x00dev->irqmask_lock); -	rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); +	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®);  	reg &= mask; -	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); +	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);  	spin_unlock(&rt2x00dev->irqmask_lock);  	return IRQ_HANDLED; @@ -966,28 +976,28 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)  	 * This device has multiple filters for control frames  	 * and has a separate filter for PS Poll frames.  	 */ -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); +	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);  	/*  	 * This device has a pre tbtt interrupt and thus fetches  	 * a new beacon directly prior to transmission.  	 */ -	__set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags); +	__set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags);  	/*  	 * This device requires firmware.  	 */  	if (!rt2x00_is_soc(rt2x00dev)) -		__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags); +		__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);  	if (!modparam_nohwcrypt) -		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);  	/*  	 * Set the rssi offset. @@ -1018,6 +1028,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {  	.ampdu_action		= rt2800_ampdu_action,  	.flush			= rt2x00mac_flush,  	.get_survey		= rt2800_get_survey, +	.get_ringparam		= rt2x00mac_get_ringparam,  };  static const struct rt2800_ops rt2800pci_rt2800_ops = { @@ -1057,6 +1068,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {  	.start_queue		= rt2800pci_start_queue,  	.kick_queue		= rt2800pci_kick_queue,  	.stop_queue		= rt2800pci_stop_queue, +	.flush_queue		= rt2x00pci_flush_queue,  	.write_tx_desc		= rt2800pci_write_tx_desc,  	.write_tx_data		= rt2800_write_tx_data,  	.write_beacon		= rt2800_write_beacon, @@ -1116,36 +1128,36 @@ static const struct rt2x00_ops rt2800pci_ops = {   */  #ifdef CONFIG_PCI  static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { -	{ PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7738), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0601) }, +	{ PCI_DEVICE(0x1814, 0x0681) }, +	{ PCI_DEVICE(0x1814, 0x0701) }, +	{ PCI_DEVICE(0x1814, 0x0781) }, +	{ PCI_DEVICE(0x1814, 0x3090) }, +	{ PCI_DEVICE(0x1814, 0x3091) }, +	{ PCI_DEVICE(0x1814, 0x3092) }, +	{ PCI_DEVICE(0x1432, 0x7708) }, +	{ PCI_DEVICE(0x1432, 0x7727) }, +	{ PCI_DEVICE(0x1432, 0x7728) }, +	{ PCI_DEVICE(0x1432, 0x7738) }, +	{ PCI_DEVICE(0x1432, 0x7748) }, +	{ PCI_DEVICE(0x1432, 0x7758) }, +	{ PCI_DEVICE(0x1432, 0x7768) }, +	{ PCI_DEVICE(0x1462, 0x891a) }, +	{ PCI_DEVICE(0x1a3b, 0x1059) },  #ifdef CONFIG_RT2800PCI_RT33XX -	{ PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x3390) },  #endif  #ifdef CONFIG_RT2800PCI_RT35XX -	{ PCI_DEVICE(0x1432, 0x7711), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7722), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) }, +	{ PCI_DEVICE(0x1432, 0x7711) }, +	{ PCI_DEVICE(0x1432, 0x7722) }, +	{ PCI_DEVICE(0x1814, 0x3060) }, +	{ PCI_DEVICE(0x1814, 0x3062) }, +	{ PCI_DEVICE(0x1814, 0x3562) }, +	{ PCI_DEVICE(0x1814, 0x3592) }, +	{ PCI_DEVICE(0x1814, 0x3593) },  #endif  #ifdef CONFIG_RT2800PCI_RT53XX -	{ PCI_DEVICE(0x1814, 0x5390), PCI_DEVICE_DATA(&rt2800pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x5390) },  #endif  	{ 0, }  }; @@ -1181,10 +1193,16 @@ static struct platform_driver rt2800soc_driver = {  #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */  #ifdef CONFIG_PCI +static int rt2800pci_probe(struct pci_dev *pci_dev, +			   const struct pci_device_id *id) +{ +	return rt2x00pci_probe(pci_dev, &rt2800pci_ops); +} +  static struct pci_driver rt2800pci_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt2800pci_device_table, -	.probe		= rt2x00pci_probe, +	.probe		= rt2800pci_probe,  	.remove		= __devexit_p(rt2x00pci_remove),  	.suspend	= rt2x00pci_suspend,  	.resume		= rt2x00pci_resume, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6ba31a0e8f7..0d4e8fa3e1f 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -59,16 +59,16 @@ static void rt2800usb_start_queue(struct data_queue *queue)  	switch (queue->qid) {  	case QID_RX: -		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); +		rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®);  		rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); -		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +		rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);  		break;  	case QID_BEACON: -		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); +		rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®);  		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1);  		rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1);  		rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); -		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); +		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);  		break;  	default:  		break; @@ -82,16 +82,16 @@ static void rt2800usb_stop_queue(struct data_queue *queue)  	switch (queue->qid) {  	case QID_RX: -		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); +		rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®);  		rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); -		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +		rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);  		break;  	case QID_BEACON: -		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); +		rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®);  		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0);  		rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0);  		rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); -		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); +		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);  		break;  	default:  		break; @@ -99,6 +99,62 @@ static void rt2800usb_stop_queue(struct data_queue *queue)  }  /* + * test if there is an entry in any TX queue for which DMA is done + * but the TX status has not been returned yet + */ +static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue; + +	tx_queue_for_each(rt2x00dev, queue) { +		if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) != +		    rt2x00queue_get_entry(queue, Q_INDEX_DONE)) +			return true; +	} +	return false; +} + +static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, +						 int urb_status, u32 tx_status) +{ +	if (urb_status) { +		WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status); +		return; +	} + +	/* try to read all TX_STA_FIFO entries before scheduling txdone_work */ +	if (rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID)) { +		if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status)) { +			WARNING(rt2x00dev, "TX status FIFO overrun, " +				"drop tx status report.\n"); +			queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); +		} else +			rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, +						      rt2800usb_tx_sta_fifo_read_completed); +	} else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) { +		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); +	} else if (rt2800usb_txstatus_pending(rt2x00dev)) { +		mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20)); +	} +} + +static void rt2800usb_tx_dma_done(struct queue_entry *entry) +{ +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + +	rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, +				      rt2800usb_tx_sta_fifo_read_completed); +} + +static void rt2800usb_tx_sta_fifo_timeout(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; + +	rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, +				      rt2800usb_tx_sta_fifo_read_completed); +} + +/*   * Firmware functions   */  static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) @@ -129,11 +185,11 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,  	/*  	 * Write firmware to device.  	 */ -	rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, -				   data + offset, length); +	rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, +				      data + offset, length); -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); +	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); +	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);  	/*  	 * Send firmware request to device to load firmware, @@ -148,7 +204,7 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,  	}  	msleep(10); -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);  	return 0;  } @@ -166,22 +222,22 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)  	if (rt2800_wait_csr_ready(rt2x00dev))  		return -EBUSY; -	rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); +	rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); +	rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); -	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); +	rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); -	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); +	rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®);  	rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1);  	rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); -	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); -	rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); +	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);  	rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,  				    USB_MODE_RESET, REGISTER_TIMEOUT); -	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); +	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);  	return 0;  } @@ -193,7 +249,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)  	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))  		return -EIO; -	rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); +	rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, ®);  	rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0);  	rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0);  	rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); @@ -206,7 +262,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)  			    / 1024) - 3);  	rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1);  	rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); -	rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg); +	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);  	return rt2800_enable_radio(rt2x00dev);  } @@ -282,12 +338,12 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)  	unsigned int i;  	u32 reg; -	rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); +	rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®);  	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {  		WARNING(rt2x00dev, "TX HW queue 0 timed out,"  			" invoke forced kick\n"); -		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012); +		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);  		for (i = 0; i < 10; i++) {  			udelay(10); @@ -295,15 +351,15 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)  				break;  		} -		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); +		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);  	} -	rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); +	rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®);  	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {  		WARNING(rt2x00dev, "TX HW queue 1 timed out,"  			" invoke forced kick\n"); -		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a); +		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);  		for (i = 0; i < 10; i++) {  			udelay(10); @@ -311,7 +367,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)  				break;  		} -		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); +		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);  	}  	rt2x00usb_watchdog(rt2x00dev); @@ -420,13 +476,24 @@ static void rt2800usb_work_txdone(struct work_struct *work)  		while (!rt2x00queue_empty(queue)) {  			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); -			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || -			    !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) +			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) +				break; +			if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) +				rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); +			else if (rt2x00queue_status_timeout(entry)) +				rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); +			else  				break; - -			rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);  		}  	} + +	/* +	 * The hw may delay sending the packet after DMA complete +	 * if the medium is busy, thus the TX_STA_FIFO entry is +	 * also delayed -> use a timer to retrieve it. +	 */ +	if (rt2800usb_txstatus_pending(rt2x00dev)) +		mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));  }  /* @@ -553,18 +620,23 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)  	 * This device has multiple filters for control frames  	 * and has a separate filter for PS Poll frames.  	 */ -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); +	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);  	/*  	 * This device requires firmware.  	 */ -	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); +	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);  	if (!modparam_nohwcrypt) -		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); + +	setup_timer(&rt2x00dev->txstatus_timer, +		    rt2800usb_tx_sta_fifo_timeout, +		    (unsigned long) rt2x00dev);  	/*  	 * Set the rssi offset. @@ -601,6 +673,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {  	.ampdu_action		= rt2800_ampdu_action,  	.flush			= rt2x00mac_flush,  	.get_survey		= rt2800_get_survey, +	.get_ringparam		= rt2x00mac_get_ringparam,  };  static const struct rt2800_ops rt2800usb_rt2800_ops = { @@ -635,6 +708,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {  	.kick_queue		= rt2x00usb_kick_queue,  	.stop_queue		= rt2800usb_stop_queue,  	.flush_queue		= rt2x00usb_flush_queue, +	.tx_dma_done		= rt2800usb_tx_dma_done,  	.write_tx_desc		= rt2800usb_write_tx_desc,  	.write_tx_data		= rt2800usb_write_tx_data,  	.write_beacon		= rt2800_write_beacon, @@ -695,295 +769,332 @@ static const struct rt2x00_ops rt2800usb_ops = {   */  static struct usb_device_id rt2800usb_device_table[] = {  	/* Abocom */ -	{ USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07b8, 0x2870) }, +	{ USB_DEVICE(0x07b8, 0x2770) }, +	{ USB_DEVICE(0x07b8, 0x3070) }, +	{ USB_DEVICE(0x07b8, 0x3071) }, +	{ USB_DEVICE(0x07b8, 0x3072) }, +	{ USB_DEVICE(0x1482, 0x3c09) },  	/* AirTies */ -	{ USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1eda, 0x2012) }, +	{ USB_DEVICE(0x1eda, 0x2310) },  	/* Allwin */ -	{ USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x8516, 0x2070) }, +	{ USB_DEVICE(0x8516, 0x2770) }, +	{ USB_DEVICE(0x8516, 0x2870) }, +	{ USB_DEVICE(0x8516, 0x3070) }, +	{ USB_DEVICE(0x8516, 0x3071) }, +	{ USB_DEVICE(0x8516, 0x3072) }, +	/* Alpha Networks */ +	{ USB_DEVICE(0x14b2, 0x3c06) }, +	{ USB_DEVICE(0x14b2, 0x3c07) }, +	{ USB_DEVICE(0x14b2, 0x3c09) }, +	{ USB_DEVICE(0x14b2, 0x3c12) }, +	{ USB_DEVICE(0x14b2, 0x3c23) }, +	{ USB_DEVICE(0x14b2, 0x3c25) }, +	{ USB_DEVICE(0x14b2, 0x3c27) }, +	{ USB_DEVICE(0x14b2, 0x3c28) }, +	{ USB_DEVICE(0x14b2, 0x3c2c) },  	/* Amit */ -	{ USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x15c5, 0x0008) },  	/* Askey */ -	{ USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1690, 0x0740) },  	/* ASUS */ -	{ USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0b05, 0x1731) }, +	{ USB_DEVICE(0x0b05, 0x1732) }, +	{ USB_DEVICE(0x0b05, 0x1742) }, +	{ USB_DEVICE(0x0b05, 0x1784) }, +	{ USB_DEVICE(0x1761, 0x0b05) },  	/* AzureWave */ -	{ USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x13d3, 0x3247) }, +	{ USB_DEVICE(0x13d3, 0x3273) }, +	{ USB_DEVICE(0x13d3, 0x3305) }, +	{ USB_DEVICE(0x13d3, 0x3307) }, +	{ USB_DEVICE(0x13d3, 0x3321) },  	/* Belkin */ -	{ USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x050d, 0x825b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x050d, 0x935a), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x050d, 0x935b), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x050d, 0x8053) }, +	{ USB_DEVICE(0x050d, 0x805c) }, +	{ USB_DEVICE(0x050d, 0x815c) }, +	{ USB_DEVICE(0x050d, 0x825b) }, +	{ USB_DEVICE(0x050d, 0x935a) }, +	{ USB_DEVICE(0x050d, 0x935b) },  	/* Buffalo */ -	{ USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0411, 0x016f), USB_DEVICE_DATA(&rt2800usb_ops) }, -	/* Conceptronic */ -	{ USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0411, 0x00e8) }, +	{ USB_DEVICE(0x0411, 0x016f) }, +	{ USB_DEVICE(0x0411, 0x01a2) },  	/* Corega */ -	{ USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07aa, 0x002f) }, +	{ USB_DEVICE(0x07aa, 0x003c) }, +	{ USB_DEVICE(0x07aa, 0x003f) }, +	{ USB_DEVICE(0x18c5, 0x0012) },  	/* D-Link */ -	{ USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07d1, 0x3c09) }, +	{ USB_DEVICE(0x07d1, 0x3c0a) }, +	{ USB_DEVICE(0x07d1, 0x3c0d) }, +	{ USB_DEVICE(0x07d1, 0x3c0e) }, +	{ USB_DEVICE(0x07d1, 0x3c0f) }, +	{ USB_DEVICE(0x07d1, 0x3c11) }, +	{ USB_DEVICE(0x07d1, 0x3c16) },  	/* Draytek */ -	{ USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07fa, 0x7712) },  	/* Edimax */ -	{ USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x7392, 0x7711) }, +	{ USB_DEVICE(0x7392, 0x7717) }, +	{ USB_DEVICE(0x7392, 0x7718) },  	/* Encore */ -	{ USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x203d, 0x1480) }, +	{ USB_DEVICE(0x203d, 0x14a9) },  	/* EnGenius */ -	{ USB_DEVICE(0x1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1740, 0x9701) }, +	{ USB_DEVICE(0x1740, 0x9702) }, +	{ USB_DEVICE(0x1740, 0x9703) }, +	{ USB_DEVICE(0x1740, 0x9705) }, +	{ USB_DEVICE(0x1740, 0x9706) }, +	{ USB_DEVICE(0x1740, 0x9707) }, +	{ USB_DEVICE(0x1740, 0x9708) }, +	{ USB_DEVICE(0x1740, 0x9709) }, +	/* Gemtek */ +	{ USB_DEVICE(0x15a9, 0x0012) },  	/* Gigabyte */ -	{ USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1044, 0x800b) }, +	{ USB_DEVICE(0x1044, 0x800d) },  	/* Hawking */ -	{ USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0e66, 0x0001) }, +	{ USB_DEVICE(0x0e66, 0x0003) }, +	{ USB_DEVICE(0x0e66, 0x0009) }, +	{ USB_DEVICE(0x0e66, 0x000b) }, +	{ USB_DEVICE(0x0e66, 0x0013) }, +	{ USB_DEVICE(0x0e66, 0x0017) }, +	{ USB_DEVICE(0x0e66, 0x0018) },  	/* I-O DATA */ -	{ USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x04bb, 0x0945) }, +	{ USB_DEVICE(0x04bb, 0x0947) }, +	{ USB_DEVICE(0x04bb, 0x0948) },  	/* Linksys */ -	{ USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x13b1, 0x0031) }, +	{ USB_DEVICE(0x1737, 0x0070) }, +	{ USB_DEVICE(0x1737, 0x0071) },  	/* Logitec */ -	{ USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0789, 0x0162) }, +	{ USB_DEVICE(0x0789, 0x0163) }, +	{ USB_DEVICE(0x0789, 0x0164) }, +	{ USB_DEVICE(0x0789, 0x0166) },  	/* Motorola */ -	{ USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x100d, 0x9031) },  	/* MSI */ -	{ USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0db0, 0x3820) }, +	{ USB_DEVICE(0x0db0, 0x3821) }, +	{ USB_DEVICE(0x0db0, 0x3822) }, +	{ USB_DEVICE(0x0db0, 0x3870) }, +	{ USB_DEVICE(0x0db0, 0x3871) }, +	{ USB_DEVICE(0x0db0, 0x6899) }, +	{ USB_DEVICE(0x0db0, 0x821a) }, +	{ USB_DEVICE(0x0db0, 0x822a) }, +	{ USB_DEVICE(0x0db0, 0x822b) }, +	{ USB_DEVICE(0x0db0, 0x822c) }, +	{ USB_DEVICE(0x0db0, 0x870a) }, +	{ USB_DEVICE(0x0db0, 0x871a) }, +	{ USB_DEVICE(0x0db0, 0x871b) }, +	{ USB_DEVICE(0x0db0, 0x871c) }, +	{ USB_DEVICE(0x0db0, 0x899a) },  	/* Para */ -	{ USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x20b8, 0x8888) },  	/* Pegatron */ -	{ USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1d4d, 0x000c) }, +	{ USB_DEVICE(0x1d4d, 0x000e) }, +	{ USB_DEVICE(0x1d4d, 0x0011) },  	/* Philips */ -	{ USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0471, 0x200f) },  	/* Planex */ -	{ USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x2019, 0xab25) }, +	{ USB_DEVICE(0x2019, 0xed06) },  	/* Quanta */ -	{ USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1a32, 0x0304) },  	/* Ralink */ -	{ USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x148f, 0x2070) }, +	{ USB_DEVICE(0x148f, 0x2770) }, +	{ USB_DEVICE(0x148f, 0x2870) }, +	{ USB_DEVICE(0x148f, 0x3070) }, +	{ USB_DEVICE(0x148f, 0x3071) }, +	{ USB_DEVICE(0x148f, 0x3072) },  	/* Samsung */ -	{ USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x04e8, 0x2018) },  	/* Siemens */ -	{ USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x129b, 0x1828) },  	/* Sitecom */ -	{ USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0df6, 0x0017) }, +	{ USB_DEVICE(0x0df6, 0x002b) }, +	{ USB_DEVICE(0x0df6, 0x002c) }, +	{ USB_DEVICE(0x0df6, 0x002d) }, +	{ USB_DEVICE(0x0df6, 0x0039) }, +	{ USB_DEVICE(0x0df6, 0x003b) }, +	{ USB_DEVICE(0x0df6, 0x003d) }, +	{ USB_DEVICE(0x0df6, 0x003e) }, +	{ USB_DEVICE(0x0df6, 0x003f) }, +	{ USB_DEVICE(0x0df6, 0x0040) }, +	{ USB_DEVICE(0x0df6, 0x0042) }, +	{ USB_DEVICE(0x0df6, 0x0047) }, +	{ USB_DEVICE(0x0df6, 0x0048) }, +	{ USB_DEVICE(0x0df6, 0x0051) }, +	{ USB_DEVICE(0x0df6, 0x005f) },  	/* SMC */ -	{ USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x083a, 0x6618) }, +	{ USB_DEVICE(0x083a, 0x7511) }, +	{ USB_DEVICE(0x083a, 0x7512) }, +	{ USB_DEVICE(0x083a, 0x7522) }, +	{ USB_DEVICE(0x083a, 0x8522) }, +	{ USB_DEVICE(0x083a, 0xa618) }, +	{ USB_DEVICE(0x083a, 0xa701) }, +	{ USB_DEVICE(0x083a, 0xa702) }, +	{ USB_DEVICE(0x083a, 0xa703) }, +	{ USB_DEVICE(0x083a, 0xb522) },  	/* Sparklan */ -	{ USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x15a9, 0x0006) },  	/* Sweex */ -	{ USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, -	/* U-Media*/ -	{ USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x177f, 0x0302) }, +	/* U-Media */ +	{ USB_DEVICE(0x157e, 0x300e) }, +	{ USB_DEVICE(0x157e, 0x3013) },  	/* ZCOM */ -	{ USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0cde, 0x0022) }, +	{ USB_DEVICE(0x0cde, 0x0025) },  	/* Zinwell */ -	{ USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x5a57, 0x0280) }, +	{ USB_DEVICE(0x5a57, 0x0282) }, +	{ USB_DEVICE(0x5a57, 0x0283) }, +	{ USB_DEVICE(0x5a57, 0x5257) },  	/* Zyxel */ -	{ USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0586, 0x3418), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0586, 0x3416) }, +	{ USB_DEVICE(0x0586, 0x3418) }, +	{ USB_DEVICE(0x0586, 0x341e) }, +	{ USB_DEVICE(0x0586, 0x343e) },  #ifdef CONFIG_RT2800USB_RT33XX  	/* Ralink */ -	{ USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x148f, 0x3370) }, +	{ USB_DEVICE(0x148f, 0x8070) },  	/* Sitecom */ -	{ USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0df6, 0x0050) },  #endif  #ifdef CONFIG_RT2800USB_RT35XX  	/* Allwin */ -	{ USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x8516, 0x3572) },  	/* Askey */ -	{ USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1690, 0x0744) },  	/* Cisco */ -	{ USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x167b, 0x4001) },  	/* EnGenius */ -	{ USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1740, 0x9801) },  	/* I-O DATA */ -	{ USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x04bb, 0x0944) }, +	/* Linksys */ +	{ USB_DEVICE(0x13b1, 0x002f) }, +	{ USB_DEVICE(0x1737, 0x0079) },  	/* Ralink */ -	{ USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x148f, 0x3572) },  	/* Sitecom */ -	{ USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0df6, 0x0041) },  	/* Toshiba */ -	{ USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0930, 0x0a07) },  	/* Zinwell */ -	{ USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x5a57, 0x0284) },  #endif  #ifdef CONFIG_RT2800USB_UNKNOWN  	/*  	 * Unclear what kind of devices these are (they aren't supported by the  	 * vendor linux driver).  	 */ +	/* Abocom */ +	{ USB_DEVICE(0x07b8, 0x3073) }, +	{ USB_DEVICE(0x07b8, 0x3074) }, +	/* Alpha Networks */ +	{ USB_DEVICE(0x14b2, 0x3c08) }, +	{ USB_DEVICE(0x14b2, 0x3c11) },  	/* Amigo */ -	{ USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0e0b, 0x9031) }, +	{ USB_DEVICE(0x0e0b, 0x9041) },  	/* ASUS */ -	{ USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0b05, 0x166a) }, +	{ USB_DEVICE(0x0b05, 0x1760) }, +	{ USB_DEVICE(0x0b05, 0x1761) }, +	{ USB_DEVICE(0x0b05, 0x1790) }, +	{ USB_DEVICE(0x0b05, 0x179d) },  	/* AzureWave */ -	{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x13d3, 0x3262) }, +	{ USB_DEVICE(0x13d3, 0x3284) }, +	{ USB_DEVICE(0x13d3, 0x3322) },  	/* Belkin */ -	{ USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x050d, 0x1003) }, +	{ USB_DEVICE(0x050d, 0x825a) },  	/* Buffalo */ -	{ USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) }, -	/* Conceptronic */ -	{ USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0411, 0x012e) }, +	{ USB_DEVICE(0x0411, 0x0148) }, +	{ USB_DEVICE(0x0411, 0x0150) }, +	{ USB_DEVICE(0x0411, 0x015d) },  	/* Corega */ -	{ USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07aa, 0x0041) }, +	{ USB_DEVICE(0x07aa, 0x0042) }, +	{ USB_DEVICE(0x18c5, 0x0008) },  	/* D-Link */ -	{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07d1, 0x3c0b) }, +	{ USB_DEVICE(0x07d1, 0x3c13) }, +	{ USB_DEVICE(0x07d1, 0x3c15) }, +	{ USB_DEVICE(0x07d1, 0x3c17) }, +	{ USB_DEVICE(0x2001, 0x3c17) },  	/* Edimax */ -	{ USB_DEVICE(0x7392, 0x4085), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x7392, 0x4085) }, +	{ USB_DEVICE(0x7392, 0x7722) },  	/* Encore */ -	{ USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x203d, 0x14a1) },  	/* Gemtek */ -	{ USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x15a9, 0x0010) },  	/* Gigabyte */ -	{ USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1044, 0x800c) }, +	/* Huawei */ +	{ USB_DEVICE(0x148f, 0xf101) }, +	/* I-O DATA */ +	{ USB_DEVICE(0x04bb, 0x094b) },  	/* LevelOne */ -	{ USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1740, 0x0605) }, +	{ USB_DEVICE(0x1740, 0x0615) },  	/* Linksys */ -	{ USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1737, 0x0077) }, +	{ USB_DEVICE(0x1737, 0x0078) }, +	/* Logitec */ +	{ USB_DEVICE(0x0789, 0x0168) }, +	{ USB_DEVICE(0x0789, 0x0169) },  	/* Motorola */ -	{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x100d, 0x9032) },  	/* Ovislink */ -	{ USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1b75, 0x3071) }, +	{ USB_DEVICE(0x1b75, 0x3072) },  	/* Pegatron */ -	{ USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x05a6, 0x0101) }, +	{ USB_DEVICE(0x1d4d, 0x0002) }, +	{ USB_DEVICE(0x1d4d, 0x0010) },  	/* Planex */ -	{ USB_DEVICE(0x2019, 0x5201), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x2019, 0x5201) }, +	{ USB_DEVICE(0x2019, 0xab24) },  	/* Qcom */ -	{ USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x18e8, 0x6259) }, +	/* RadioShack */ +	{ USB_DEVICE(0x08b9, 0x1197) }, +	/* Sitecom */ +	{ USB_DEVICE(0x0df6, 0x003c) }, +	{ USB_DEVICE(0x0df6, 0x004a) }, +	{ USB_DEVICE(0x0df6, 0x004d) }, +	{ USB_DEVICE(0x0df6, 0x0053) }, +	{ USB_DEVICE(0x0df6, 0x0060) }, +	{ USB_DEVICE(0x0df6, 0x0062) },  	/* SMC */ -	{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x083a, 0xa512) }, +	{ USB_DEVICE(0x083a, 0xc522) }, +	{ USB_DEVICE(0x083a, 0xd522) }, +	{ USB_DEVICE(0x083a, 0xf511) },  	/* Sweex */ -	{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x177f, 0x0153) }, +	{ USB_DEVICE(0x177f, 0x0313) },  	/* Zyxel */ -	{ USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0586, 0x341a) },  #endif  	{ 0, }  }; @@ -996,10 +1107,16 @@ MODULE_DEVICE_TABLE(usb, rt2800usb_device_table);  MODULE_FIRMWARE(FIRMWARE_RT2870);  MODULE_LICENSE("GPL"); +static int rt2800usb_probe(struct usb_interface *usb_intf, +			   const struct usb_device_id *id) +{ +	return rt2x00usb_probe(usb_intf, &rt2800usb_ops); +} +  static struct usb_driver rt2800usb_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt2800usb_device_table, -	.probe		= rt2x00usb_probe, +	.probe		= rt2800usb_probe,  	.disconnect	= rt2x00usb_disconnect,  	.suspend	= rt2x00usb_suspend,  	.resume		= rt2x00usb_resume, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index a2bd5feb9d5..9d1a158e2c3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -37,6 +37,7 @@  #include <linux/etherdevice.h>  #include <linux/input-polldev.h>  #include <linux/kfifo.h> +#include <linux/timer.h>  #include <net/mac80211.h> @@ -570,7 +571,8 @@ struct rt2x00lib_ops {  	void (*start_queue) (struct data_queue *queue);  	void (*kick_queue) (struct data_queue *queue);  	void (*stop_queue) (struct data_queue *queue); -	void (*flush_queue) (struct data_queue *queue); +	void (*flush_queue) (struct data_queue *queue, bool drop); +	void (*tx_dma_done) (struct queue_entry *entry);  	/*  	 * TX control handlers @@ -643,11 +645,11 @@ struct rt2x00_ops {  };  /* - * rt2x00 device flags + * rt2x00 state flags   */ -enum rt2x00_flags { +enum rt2x00_state_flags {  	/* -	 * Device state flags +	 * Device flags  	 */  	DEVICE_STATE_PRESENT,  	DEVICE_STATE_REGISTERED_HW, @@ -657,39 +659,44 @@ enum rt2x00_flags {  	DEVICE_STATE_SCANNING,  	/* -	 * Driver requirements +	 * Driver configuration  	 */ -	DRIVER_REQUIRE_FIRMWARE, -	DRIVER_REQUIRE_BEACON_GUARD, -	DRIVER_REQUIRE_ATIM_QUEUE, -	DRIVER_REQUIRE_DMA, -	DRIVER_REQUIRE_COPY_IV, -	DRIVER_REQUIRE_L2PAD, -	DRIVER_REQUIRE_TXSTATUS_FIFO, -	DRIVER_REQUIRE_TASKLET_CONTEXT, -	DRIVER_REQUIRE_SW_SEQNO, -	DRIVER_REQUIRE_HT_TX_DESC, +	CONFIG_CHANNEL_HT40, +}; +/* + * rt2x00 capability flags + */ +enum rt2x00_capability_flags {  	/* -	 * Driver features +	 * Requirements  	 */ -	CONFIG_SUPPORT_HW_BUTTON, -	CONFIG_SUPPORT_HW_CRYPTO, -	CONFIG_SUPPORT_POWER_LIMIT, -	DRIVER_SUPPORT_CONTROL_FILTERS, -	DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, -	DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, -	DRIVER_SUPPORT_LINK_TUNING, +	REQUIRE_FIRMWARE, +	REQUIRE_BEACON_GUARD, +	REQUIRE_ATIM_QUEUE, +	REQUIRE_DMA, +	REQUIRE_COPY_IV, +	REQUIRE_L2PAD, +	REQUIRE_TXSTATUS_FIFO, +	REQUIRE_TASKLET_CONTEXT, +	REQUIRE_SW_SEQNO, +	REQUIRE_HT_TX_DESC,  	/* -	 * Driver configuration +	 * Capabilities  	 */ -	CONFIG_FRAME_TYPE, -	CONFIG_RF_SEQUENCE, -	CONFIG_EXTERNAL_LNA_A, -	CONFIG_EXTERNAL_LNA_BG, -	CONFIG_DOUBLE_ANTENNA, -	CONFIG_CHANNEL_HT40, +	CAPABILITY_HW_BUTTON, +	CAPABILITY_HW_CRYPTO, +	CAPABILITY_POWER_LIMIT, +	CAPABILITY_CONTROL_FILTERS, +	CAPABILITY_CONTROL_FILTER_PSPOLL, +	CAPABILITY_PRE_TBTT_INTERRUPT, +	CAPABILITY_LINK_TUNING, +	CAPABILITY_FRAME_TYPE, +	CAPABILITY_RF_SEQUENCE, +	CAPABILITY_EXTERNAL_LNA_A, +	CAPABILITY_EXTERNAL_LNA_BG, +	CAPABILITY_DOUBLE_ANTENNA,  };  /* @@ -738,13 +745,20 @@ struct rt2x00_dev {  #endif /* CONFIG_RT2X00_LIB_LEDS */  	/* -	 * Device flags. -	 * In these flags the current status and some -	 * of the device capabilities are stored. +	 * Device state flags. +	 * In these flags the current status is stored. +	 * Access to these flags should occur atomically.  	 */  	unsigned long flags;  	/* +	 * Device capabiltiy flags. +	 * In these flags the device/driver capabilities are stored. +	 * Access to these flags should occur non-atomically. +	 */ +	unsigned long cap_flags; + +	/*  	 * Device information, Bus IRQ and name (PCI, SoC)  	 */  	int irq; @@ -911,6 +925,11 @@ struct rt2x00_dev {  	DECLARE_KFIFO_PTR(txstatus_fifo, u32);  	/* +	 * Timer to ensure tx status reports are read (rt2800usb). +	 */ +	struct timer_list txstatus_timer; + +	/*  	 * Tasklet for processing tx status reports (rt2800pci).  	 */  	struct tasklet_struct txstatus_tasklet; @@ -1235,6 +1254,10 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,  		      const struct ieee80211_tx_queue_params *params);  void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);  void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); +int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant); +int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); +void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, +			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);  /*   * Driver allocation handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 9416e36de29..f7872640459 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -109,15 +109,6 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,  	rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);  } -static inline -enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant, -					    enum antenna default_ant) -{ -	if (current_ant != ANTENNA_SW_DIVERSITY) -		return current_ant; -	return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B; -} -  void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,  			      struct antenna_setup config)  { @@ -126,19 +117,35 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,  	struct antenna_setup *active = &rt2x00dev->link.ant.active;  	/* -	 * Failsafe: Make sure we are not sending the -	 * ANTENNA_SW_DIVERSITY state to the driver. -	 * If that happens, fallback to hardware defaults, -	 * or our own default. +	 * When the caller tries to send the SW diversity, +	 * we must update the ANTENNA_RX_DIVERSITY flag to +	 * enable the antenna diversity in the link tuner. +	 * +	 * Secondly, we must guarentee we never send the +	 * software antenna diversity command to the driver.  	 */ -	if (!(ant->flags & ANTENNA_RX_DIVERSITY)) -		config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); -	else if (config.rx == ANTENNA_SW_DIVERSITY) +	if (!(ant->flags & ANTENNA_RX_DIVERSITY)) { +		if (config.rx == ANTENNA_SW_DIVERSITY) { +			ant->flags |= ANTENNA_RX_DIVERSITY; + +			if (def->rx == ANTENNA_SW_DIVERSITY) +				config.rx = ANTENNA_B; +			else +				config.rx = def->rx; +		} +	} else if (config.rx == ANTENNA_SW_DIVERSITY)  		config.rx = active->rx; -	if (!(ant->flags & ANTENNA_TX_DIVERSITY)) -		config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx); -	else if (config.tx == ANTENNA_SW_DIVERSITY) +	if (!(ant->flags & ANTENNA_TX_DIVERSITY)) { +		if (config.tx == ANTENNA_SW_DIVERSITY) { +			ant->flags |= ANTENNA_TX_DIVERSITY; + +			if (def->tx == ANTENNA_SW_DIVERSITY) +				config.tx = ANTENNA_B; +			else +				config.tx = def->tx; +		} +	} else if (config.tx == ANTENNA_SW_DIVERSITY)  		config.tx = active->tx;  	/* @@ -163,6 +170,34 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,  		rt2x00queue_start_queue(rt2x00dev->rx);  } +static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, +				   struct ieee80211_conf *conf) +{ +	struct hw_mode_spec *spec = &rt2x00dev->spec; +	int center_channel; +	u16 i; + +	/* +	 * Initialize center channel to current channel. +	 */ +	center_channel = spec->channels[conf->channel->hw_value].channel; + +	/* +	 * Adjust center channel to HT40+ and HT40- operation. +	 */ +	if (conf_is_ht40_plus(conf)) +		center_channel += 2; +	else if (conf_is_ht40_minus(conf)) +		center_channel -= (center_channel == 14) ? 1 : 2; + +	for (i = 0; i < spec->num_channels; i++) +		if (spec->channels[i].channel == center_channel) +			return i; + +	WARN_ON(1); +	return conf->channel->hw_value; +} +  void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,  		      struct ieee80211_conf *conf,  		      unsigned int ieee80211_flags) @@ -176,10 +211,10 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,  	if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {  		if (conf_is_ht40(conf)) { -			__set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); +			set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);  			hw_value = rt2x00ht_center_channel(rt2x00dev, conf);  		} else { -			__clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); +			clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);  			hw_value = conf->channel->hw_value;  		} diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 3f5688fbf3f..1bb9d46077f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -52,7 +52,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,  	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);  	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; -	if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !hw_key) +	if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key)  		return;  	__set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); @@ -80,7 +80,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,  	struct ieee80211_key_conf *key = tx_info->control.hw_key;  	unsigned int overhead = 0; -	if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !key) +	if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !key)  		return overhead;  	/* diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 66166ef037f..78787fcc919 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -63,7 +63,8 @@ struct rt2x00debug_intf {  	 * - driver folder  	 *   - driver file  	 *   - chipset file -	 *   - device flags file +	 *   - device state flags file +	 *   - device capability flags file  	 *   - register folder  	 *     - csr offset/value files  	 *     - eeprom offset/value files @@ -78,6 +79,7 @@ struct rt2x00debug_intf {  	struct dentry *driver_entry;  	struct dentry *chipset_entry;  	struct dentry *dev_flags; +	struct dentry *cap_flags;  	struct dentry *register_folder;  	struct dentry *csr_off_entry;  	struct dentry *csr_val_entry; @@ -553,6 +555,35 @@ static const struct file_operations rt2x00debug_fop_dev_flags = {  	.llseek		= default_llseek,  }; +static ssize_t rt2x00debug_read_cap_flags(struct file *file, +					  char __user *buf, +					  size_t length, +					  loff_t *offset) +{ +	struct rt2x00debug_intf *intf =	file->private_data; +	char line[16]; +	size_t size; + +	if (*offset) +		return 0; + +	size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags); + +	if (copy_to_user(buf, line, size)) +		return -EFAULT; + +	*offset += size; +	return size; +} + +static const struct file_operations rt2x00debug_fop_cap_flags = { +	.owner		= THIS_MODULE, +	.read		= rt2x00debug_read_cap_flags, +	.open		= rt2x00debug_file_open, +	.release	= rt2x00debug_file_release, +	.llseek		= default_llseek, +}; +  static struct dentry *rt2x00debug_create_file_driver(const char *name,  						     struct rt2x00debug_intf  						     *intf, @@ -652,6 +683,12 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)  	if (IS_ERR(intf->dev_flags) || !intf->dev_flags)  		goto exit; +	intf->cap_flags = debugfs_create_file("cap_flags", S_IRUSR, +					      intf->driver_folder, intf, +					      &rt2x00debug_fop_cap_flags); +	if (IS_ERR(intf->cap_flags) || !intf->cap_flags) +		goto exit; +  	intf->register_folder =  	    debugfs_create_dir("register", intf->driver_folder);  	if (IS_ERR(intf->register_folder) || !intf->register_folder) @@ -705,7 +742,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)  				intf, &rt2x00debug_fop_queue_stats);  #ifdef CONFIG_RT2X00_LIB_CRYPTO -	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) +	if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))  		intf->crypto_stats_entry =  		    debugfs_create_file("crypto", S_IRUGO, intf->queue_folder,  					intf, &rt2x00debug_fop_crypto_stats); @@ -743,6 +780,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)  	debugfs_remove(intf->csr_off_entry);  	debugfs_remove(intf->register_folder);  	debugfs_remove(intf->dev_flags); +	debugfs_remove(intf->cap_flags);  	debugfs_remove(intf->chipset_entry);  	debugfs_remove(intf->driver_entry);  	debugfs_remove(intf->driver_folder); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 9bffe8438d1..7776d9f1f29 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -200,7 +200,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)  	 * here as they will fetch the next beacon directly prior to  	 * transmission.  	 */ -	if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags)) +	if (test_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags))  		return;  	/* fetch next beacon */ @@ -225,7 +225,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);  void rt2x00lib_dmastart(struct queue_entry *entry)  {  	set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); -	rt2x00queue_index_inc(entry->queue, Q_INDEX); +	rt2x00queue_index_inc(entry, Q_INDEX);  }  EXPORT_SYMBOL_GPL(rt2x00lib_dmastart); @@ -233,7 +233,7 @@ void rt2x00lib_dmadone(struct queue_entry *entry)  {  	set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);  	clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); -	rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE); +	rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE);  }  EXPORT_SYMBOL_GPL(rt2x00lib_dmadone); @@ -271,7 +271,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	/*  	 * Remove L2 padding which was added during  	 */ -	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) +	if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))  		rt2x00queue_remove_l2pad(entry->skb, header_length);  	/* @@ -280,7 +280,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	 * mac80211 will expect the same data to be present it the  	 * frame as it was passed to us.  	 */ -	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) +	if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))  		rt2x00crypto_tx_insert_iv(entry->skb, header_length);  	/* @@ -377,7 +377,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	 * send the status report back.  	 */  	if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) { -		if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags)) +		if (test_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags))  			ieee80211_tx_status(rt2x00dev->hw, entry->skb);  		else  			ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb); @@ -392,7 +392,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	rt2x00dev->ops->lib->clear_entry(entry); -	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); +	rt2x00queue_index_inc(entry, Q_INDEX_DONE);  	/*  	 * If the data queue was below the threshold before the txdone @@ -559,7 +559,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)  submit_entry:  	entry->flags = 0; -	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); +	rt2x00queue_index_inc(entry, Q_INDEX_DONE);  	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&  	    test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))  		rt2x00dev->ops->lib->clear_entry(entry); @@ -806,15 +806,15 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)  	/*  	 * Take TX headroom required for alignment into account.  	 */ -	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) +	if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))  		rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE; -	else if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) +	else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))  		rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;  	/*  	 * Allocate tx status FIFO for driver use.  	 */ -	if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags)) { +	if (test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags)) {  		/*  		 * Allocate the txstatus fifo. In the worst case the tx  		 * status fifo has to hold the tx status of all entries @@ -1071,6 +1071,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)  	/*  	 * Stop all work.  	 */ +	del_timer_sync(&rt2x00dev->txstatus_timer);  	cancel_work_sync(&rt2x00dev->intf_work);  	if (rt2x00_is_usb(rt2x00dev)) {  		cancel_work_sync(&rt2x00dev->rxdone_work); diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index be0ff78c1b1..f316aad3061 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -99,7 +99,7 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)  {  	int retval; -	if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) +	if (!test_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags))  		return 0;  	if (!rt2x00dev->fw) { diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c deleted file mode 100644 index e8c0c3e92c2..00000000000 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ /dev/null @@ -1,136 +0,0 @@ -/* -	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> -	<http://rt2x00.serialmonkey.com> - -	This program is free software; you can redistribute it and/or modify -	it under the terms of the GNU General Public License as published by -	the Free Software Foundation; either version 2 of the License, or -	(at your option) any later version. - -	This program is distributed in the hope that it will be useful, -	but WITHOUT ANY WARRANTY; without even the implied warranty of -	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -	GNU General Public License for more details. - -	You should have received a copy of the GNU General Public License -	along with this program; if not, write to the -	Free Software Foundation, Inc., -	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* -	Module: rt2x00lib -	Abstract: rt2x00 HT specific routines. - */ - -#include <linux/kernel.h> -#include <linux/module.h> - -#include "rt2x00.h" -#include "rt2x00lib.h" - -void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, -				   struct txentry_desc *txdesc, -				   const struct rt2x00_rate *hwrate) -{ -	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); -	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; -	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; - -	if (tx_info->control.sta) -		txdesc->u.ht.mpdu_density = -		    tx_info->control.sta->ht_cap.ampdu_density; - -	txdesc->u.ht.ba_size = 7;	/* FIXME: What value is needed? */ - -	/* -	 * Only one STBC stream is supported for now. -	 */ -	if (tx_info->flags & IEEE80211_TX_CTL_STBC) -		txdesc->u.ht.stbc = 1; - -	/* -	 * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the -	 * mcs rate to be used -	 */ -	if (txrate->flags & IEEE80211_TX_RC_MCS) { -		txdesc->u.ht.mcs = txrate->idx; - -		/* -		 * MIMO PS should be set to 1 for STA's using dynamic SM PS -		 * when using more then one tx stream (>MCS7). -		 */ -		if (tx_info->control.sta && txdesc->u.ht.mcs > 7 && -		    ((tx_info->control.sta->ht_cap.cap & -		      IEEE80211_HT_CAP_SM_PS) >> -		     IEEE80211_HT_CAP_SM_PS_SHIFT) == -		    WLAN_HT_CAP_SM_PS_DYNAMIC) -			__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); -	} else { -		txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs); -		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) -			txdesc->u.ht.mcs |= 0x08; -	} - -	/* -	 * This frame is eligible for an AMPDU, however, don't aggregate -	 * frames that are intended to probe a specific tx rate. -	 */ -	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU && -	    !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) -		__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); - -	/* -	 * Set 40Mhz mode if necessary (for legacy rates this will -	 * duplicate the frame to both channels). -	 */ -	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH || -	    txrate->flags & IEEE80211_TX_RC_DUP_DATA) -		__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); -	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) -		__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); - -	/* -	 * Determine IFS values -	 * - Use TXOP_BACKOFF for management frames -	 * - Use TXOP_SIFS for fragment bursts -	 * - Use TXOP_HTTXOP for everything else -	 * -	 * Note: rt2800 devices won't use CTS protection (if used) -	 * for frames not transmitted with TXOP_HTTXOP -	 */ -	if (ieee80211_is_mgmt(hdr->frame_control)) -		txdesc->u.ht.txop = TXOP_BACKOFF; -	else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) -		txdesc->u.ht.txop = TXOP_SIFS; -	else -		txdesc->u.ht.txop = TXOP_HTTXOP; -} - -u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, -			    struct ieee80211_conf *conf) -{ -	struct hw_mode_spec *spec = &rt2x00dev->spec; -	int center_channel; -	u16 i; - -	/* -	 * Initialize center channel to current channel. -	 */ -	center_channel = spec->channels[conf->channel->hw_value].channel; - -	/* -	 * Adjust center channel to HT40+ and HT40- operation. -	 */ -	if (conf_is_ht40_plus(conf)) -		center_channel += 2; -	else if (conf_is_ht40_minus(conf)) -		center_channel -= (center_channel == 14) ? 1 : 2; - -	for (i = 0; i < spec->num_channels; i++) -		if (spec->channels[i].channel == center_channel) -			return i; - -	WARN_ON(1); -	return conf->channel->hw_value; -} diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 88f2f927552..322cc4f3de5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -175,14 +175,14 @@ int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,  /**   * rt2x00queue_index_inc - Index incrementation function - * @queue: Queue (&struct data_queue) to perform the action on. + * @entry: Queue entry (&struct queue_entry) to perform the action on.   * @index: Index type (&enum queue_index) to perform the action on.   * - * This function will increase the requested index on the queue, + * This function will increase the requested index on the entry's queue,   * it will grab the appropriate locks and handle queue overflow events by   * resetting the index to the start of the queue.   */ -void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); +void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index);  /**   * rt2x00queue_init_queues - Initialize all data queues @@ -388,41 +388,17 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,  #endif /* CONFIG_RT2X00_LIB_CRYPTO */  /* - * HT handlers. - */ -#ifdef CONFIG_RT2X00_LIB_HT -void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, -				   struct txentry_desc *txdesc, -				   const struct rt2x00_rate *hwrate); - -u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, -			    struct ieee80211_conf *conf); -#else -static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, -						 struct txentry_desc *txdesc, -						 const struct rt2x00_rate *hwrate) -{ -} - -static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, -					  struct ieee80211_conf *conf) -{ -	return conf->channel->hw_value; -} -#endif /* CONFIG_RT2X00_LIB_HT */ - -/*   * RFkill handlers.   */  static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)  { -	if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) +	if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))  		wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy);  }  static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)  { -	if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) +	if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))  		wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy);  } diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 1435976b877..ea10b0068f8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -192,17 +192,7 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)  	/*  	 * Determine if software diversity is enabled for  	 * either the TX or RX antenna (or both). -	 * Always perform this check since within the link -	 * tuner interval the configuration might have changed.  	 */ -	ant->flags &= ~ANTENNA_RX_DIVERSITY; -	ant->flags &= ~ANTENNA_TX_DIVERSITY; - -	if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) -		ant->flags |= ANTENNA_RX_DIVERSITY; -	if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) -		ant->flags |= ANTENNA_TX_DIVERSITY; -  	if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&  	    !(ant->flags & ANTENNA_TX_DIVERSITY)) {  		ant->flags = 0; @@ -383,7 +373,7 @@ static void rt2x00link_tuner(struct work_struct *work)  	 * do not support link tuning at all, while other devices can disable  	 * the feature from the EEPROM.  	 */ -	if (test_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags)) +	if (test_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags))  		rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);  	/* diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 661c6baad2b..93bec140e59 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -119,7 +119,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  	 * Use the ATIM queue if appropriate and present.  	 */  	if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && -	    test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) +	    test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags))  		qid = QID_ATIM;  	queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); @@ -158,7 +158,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  	return;   exit_fail: -	ieee80211_stop_queue(rt2x00dev->hw, qid); +	rt2x00queue_pause_queue(queue);  	dev_kfree_skb_any(skb);  }  EXPORT_SYMBOL_GPL(rt2x00mac_tx); @@ -411,11 +411,11 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,  	 * of different types, but has no a separate filter for PS Poll frames,  	 * FIF_CONTROL flag implies FIF_PSPOLL.  	 */ -	if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags)) { +	if (!test_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags)) {  		if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL)  			*total_flags |= FIF_CONTROL | FIF_PSPOLL;  	} -	if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags)) { +	if (!test_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags)) {  		if (*total_flags & FIF_CONTROL)  			*total_flags |= FIF_PSPOLL;  	} @@ -496,7 +496,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,  	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))  		return 0; -	else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) +	else if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))  		return -EOPNOTSUPP;  	else if (key->keylen > 32)  		return -ENOSPC; @@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_set_key);  void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)  {  	struct rt2x00_dev *rt2x00dev = hw->priv; -	__set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); +	set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);  	rt2x00link_stop_tuner(rt2x00dev);  }  EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); @@ -570,7 +570,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);  void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw)  {  	struct rt2x00_dev *rt2x00dev = hw->priv; -	__clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); +	clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);  	rt2x00link_start_tuner(rt2x00dev);  }  EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete); @@ -737,3 +737,84 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)  		rt2x00queue_flush_queue(queue, drop);  }  EXPORT_SYMBOL_GPL(rt2x00mac_flush); + +int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct link_ant *ant = &rt2x00dev->link.ant; +	struct antenna_setup *def = &rt2x00dev->default_ant; +	struct antenna_setup setup; + +	// The antenna value is not supposed to be 0, +	// or exceed the maximum number of antenna's. +	if (!tx_ant || (tx_ant & ~3) || !rx_ant || (rx_ant & ~3)) +		return -EINVAL; + +	// When the client tried to configure the antenna to or from +	// diversity mode, we must reset the default antenna as well +	// as that controls the diversity switch. +	if (ant->flags & ANTENNA_TX_DIVERSITY && tx_ant != 3) +		ant->flags &= ~ANTENNA_TX_DIVERSITY; +	if (ant->flags & ANTENNA_RX_DIVERSITY && rx_ant != 3) +		ant->flags &= ~ANTENNA_RX_DIVERSITY; + +	// If diversity is being enabled, check if we need hardware +	// or software diversity. In the latter case, reset the value, +	// and make sure we update the antenna flags to have the +	// link tuner pick up the diversity tuning. +	if (tx_ant == 3 && def->tx == ANTENNA_SW_DIVERSITY) { +		tx_ant = ANTENNA_SW_DIVERSITY; +		ant->flags |= ANTENNA_TX_DIVERSITY; +	} + +	if (rx_ant == 3 && def->rx == ANTENNA_SW_DIVERSITY) { +		rx_ant = ANTENNA_SW_DIVERSITY; +		ant->flags |= ANTENNA_RX_DIVERSITY; +	} + +	setup.tx = tx_ant; +	setup.rx = rx_ant; + +	rt2x00lib_config_antenna(rt2x00dev, setup); + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2x00mac_set_antenna); + +int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct link_ant *ant = &rt2x00dev->link.ant; +	struct antenna_setup *active = &rt2x00dev->link.ant.active; + +	// When software diversity is active, we must report this to the +	// client and not the current active antenna state. +	if (ant->flags & ANTENNA_TX_DIVERSITY) +		*tx_ant = ANTENNA_HW_DIVERSITY; +	else +		*tx_ant = active->tx; + +	if (ant->flags & ANTENNA_RX_DIVERSITY) +		*rx_ant = ANTENNA_HW_DIVERSITY; +	else +		*rx_ant = active->rx; + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2x00mac_get_antenna); + +void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, +			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct data_queue *queue; + +	tx_queue_for_each(rt2x00dev, queue) { +		*tx += queue->length; +		*tx_max += queue->limit; +	} + +	*rx = rt2x00dev->rx->length; +	*rx_max = rt2x00dev->rx->limit; +} +EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 9649bd0cd71..17148bb2442 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -99,6 +99,15 @@ bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)  }  EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); +void rt2x00pci_flush_queue(struct data_queue *queue, bool drop) +{ +	unsigned int i; + +	for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++) +		msleep(10); +} +EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue); +  /*   * Device initialization handlers.   */ @@ -242,9 +251,8 @@ exit:  	return -ENOMEM;  } -int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) +int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)  { -	struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data;  	struct ieee80211_hw *hw;  	struct rt2x00_dev *rt2x00dev;  	int retval; diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 07961b8b369..e2c99f2b9a1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -107,6 +107,16 @@ struct queue_entry_priv_pci {   */  bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); +/** + * rt2x00pci_flush_queue - Flush data queue + * @queue: Data queue to stop + * @drop: True to drop all pending frames. + * + * This will wait for a maximum of 100ms, waiting for the queues + * to become empty. + */ +void rt2x00pci_flush_queue(struct data_queue *queue, bool drop); +  /*   * Device initialization handlers.   */ @@ -116,7 +126,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);  /*   * PCI driver handlers.   */ -int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id); +int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops);  void rt2x00pci_remove(struct pci_dev *pci_dev);  #ifdef CONFIG_PM  int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 94b8bbb7ad8..ab8c16f8bca 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -60,7 +60,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)  	 * at least 8 bytes bytes available in headroom for IV/EIV  	 * and 8 bytes for ICV data as tailroon.  	 */ -	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { +	if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) {  		head_size += 8;  		tail_size += 8;  	} @@ -86,7 +86,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)  	memset(skbdesc, 0, sizeof(*skbdesc));  	skbdesc->entry = entry; -	if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) { +	if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) {  		skbdesc->skb_dma = dma_map_single(rt2x00dev->dev,  						  skb->data,  						  skb->len, @@ -213,7 +213,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,  	__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); -	if (!test_bit(DRIVER_REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->flags)) +	if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags))  		return;  	/* @@ -302,6 +302,85 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,  	}  } +static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry, +						struct txentry_desc *txdesc, +						const struct rt2x00_rate *hwrate) +{ +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); +	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; + +	if (tx_info->control.sta) +		txdesc->u.ht.mpdu_density = +		    tx_info->control.sta->ht_cap.ampdu_density; + +	txdesc->u.ht.ba_size = 7;	/* FIXME: What value is needed? */ + +	/* +	 * Only one STBC stream is supported for now. +	 */ +	if (tx_info->flags & IEEE80211_TX_CTL_STBC) +		txdesc->u.ht.stbc = 1; + +	/* +	 * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the +	 * mcs rate to be used +	 */ +	if (txrate->flags & IEEE80211_TX_RC_MCS) { +		txdesc->u.ht.mcs = txrate->idx; + +		/* +		 * MIMO PS should be set to 1 for STA's using dynamic SM PS +		 * when using more then one tx stream (>MCS7). +		 */ +		if (tx_info->control.sta && txdesc->u.ht.mcs > 7 && +		    ((tx_info->control.sta->ht_cap.cap & +		      IEEE80211_HT_CAP_SM_PS) >> +		     IEEE80211_HT_CAP_SM_PS_SHIFT) == +		    WLAN_HT_CAP_SM_PS_DYNAMIC) +			__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); +	} else { +		txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs); +		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) +			txdesc->u.ht.mcs |= 0x08; +	} + +	/* +	 * This frame is eligible for an AMPDU, however, don't aggregate +	 * frames that are intended to probe a specific tx rate. +	 */ +	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU && +	    !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) +		__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); + +	/* +	 * Set 40Mhz mode if necessary (for legacy rates this will +	 * duplicate the frame to both channels). +	 */ +	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH || +	    txrate->flags & IEEE80211_TX_RC_DUP_DATA) +		__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); +	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) +		__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); + +	/* +	 * Determine IFS values +	 * - Use TXOP_BACKOFF for management frames except beacons +	 * - Use TXOP_SIFS for fragment bursts +	 * - Use TXOP_HTTXOP for everything else +	 * +	 * Note: rt2800 devices won't use CTS protection (if used) +	 * for frames not transmitted with TXOP_HTTXOP +	 */ +	if (ieee80211_is_mgmt(hdr->frame_control) && +	    !ieee80211_is_beacon(hdr->frame_control)) +		txdesc->u.ht.txop = TXOP_BACKOFF; +	else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) +		txdesc->u.ht.txop = TXOP_SIFS; +	else +		txdesc->u.ht.txop = TXOP_HTTXOP; +} +  static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,  					     struct txentry_desc *txdesc)  { @@ -396,8 +475,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,  	rt2x00crypto_create_tx_descriptor(entry, txdesc);  	rt2x00queue_create_tx_descriptor_seq(entry, txdesc); -	if (test_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags)) -		rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate); +	if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags)) +		rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate);  	else  		rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);  } @@ -436,7 +515,7 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,  	/*  	 * Map the skb to DMA.  	 */ -	if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) +	if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))  		rt2x00queue_map_txskb(entry);  	return 0; @@ -529,7 +608,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	 */  	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&  	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { -		if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags)) +		if (test_bit(REQUIRE_COPY_IV, &queue->rt2x00dev->cap_flags))  			rt2x00crypto_tx_copy_iv(skb, &txdesc);  		else  			rt2x00crypto_tx_remove_iv(skb, &txdesc); @@ -543,9 +622,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	 * PCI and USB devices, while header alignment only is valid  	 * for PCI devices.  	 */ -	if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) +	if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags))  		rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length); -	else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) +	else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))  		rt2x00queue_align_frame(entry->skb);  	/* @@ -561,7 +640,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	set_bit(ENTRY_DATA_PENDING, &entry->flags); -	rt2x00queue_index_inc(queue, Q_INDEX); +	rt2x00queue_index_inc(entry, Q_INDEX);  	rt2x00queue_write_tx_descriptor(entry, &txdesc);  	rt2x00queue_kick_tx_queue(queue, &txdesc); @@ -650,10 +729,12 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,  	return ret;  } -void rt2x00queue_for_each_entry(struct data_queue *queue, +bool rt2x00queue_for_each_entry(struct data_queue *queue,  				enum queue_index start,  				enum queue_index end, -				void (*fn)(struct queue_entry *entry)) +				void *data, +				bool (*fn)(struct queue_entry *entry, +					   void *data))  {  	unsigned long irqflags;  	unsigned int index_start; @@ -664,7 +745,7 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,  		ERROR(queue->rt2x00dev,  		      "Entry requested from invalid index range (%d - %d)\n",  		      start, end); -		return; +		return true;  	}  	/* @@ -683,15 +764,23 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,  	 * send out all frames in the correct order.  	 */  	if (index_start < index_end) { -		for (i = index_start; i < index_end; i++) -			fn(&queue->entries[i]); +		for (i = index_start; i < index_end; i++) { +			if (fn(&queue->entries[i], data)) +				return true; +		}  	} else { -		for (i = index_start; i < queue->limit; i++) -			fn(&queue->entries[i]); +		for (i = index_start; i < queue->limit; i++) { +			if (fn(&queue->entries[i], data)) +				return true; +		} -		for (i = 0; i < index_end; i++) -			fn(&queue->entries[i]); +		for (i = 0; i < index_end; i++) { +			if (fn(&queue->entries[i], data)) +				return true; +		}  	} + +	return false;  }  EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry); @@ -717,8 +806,9 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,  }  EXPORT_SYMBOL_GPL(rt2x00queue_get_entry); -void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) +void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)  { +	struct data_queue *queue = entry->queue;  	unsigned long irqflags;  	if (unlikely(index >= Q_INDEX_MAX)) { @@ -733,7 +823,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)  	if (queue->index[index] >= queue->limit)  		queue->index[index] = 0; -	queue->last_action[index] = jiffies; +	entry->last_action = jiffies;  	if (index == Q_INDEX) {  		queue->length++; @@ -838,7 +928,6 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue);  void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)  { -	unsigned int i;  	bool started;  	bool tx_queue =  		(queue->qid == QID_AC_VO) || @@ -873,20 +962,12 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)  	}  	/* -	 * Check if driver supports flushing, we can only guarantee -	 * full support for flushing if the driver is able -	 * to cancel all pending frames (drop = true). +	 * Check if driver supports flushing, if that is the case we can +	 * defer the flushing to the driver. Otherwise we must use the +	 * alternative which just waits for the queue to become empty.  	 */ -	if (drop && queue->rt2x00dev->ops->lib->flush_queue) -		queue->rt2x00dev->ops->lib->flush_queue(queue); - -	/* -	 * When we don't want to drop any frames, or when -	 * the driver doesn't fully flush the queue correcly, -	 * we must wait for the queue to become empty. -	 */ -	for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++) -		msleep(10); +	if (likely(queue->rt2x00dev->ops->lib->flush_queue)) +		queue->rt2x00dev->ops->lib->flush_queue(queue, drop);  	/*  	 * The queue flush has failed... @@ -959,10 +1040,8 @@ static void rt2x00queue_reset(struct data_queue *queue)  	queue->count = 0;  	queue->length = 0; -	for (i = 0; i < Q_INDEX_MAX; i++) { +	for (i = 0; i < Q_INDEX_MAX; i++)  		queue->index[i] = 0; -		queue->last_action[i] = jiffies; -	}  	spin_unlock_irqrestore(&queue->index_lock, irqflags);  } @@ -1069,7 +1148,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)  	if (status)  		goto exit; -	if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) { +	if (test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) {  		status = rt2x00queue_alloc_entries(rt2x00dev->atim,  						   rt2x00dev->ops->atim);  		if (status) @@ -1121,7 +1200,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)  	struct data_queue *queue;  	enum data_queue_qid qid;  	unsigned int req_atim = -	    !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); +	    !!test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);  	/*  	 * We need the following queues: diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 5db6a99fce7..167d45873dc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -364,6 +364,7 @@ enum queue_entry_flags {   * struct queue_entry: Entry inside the &struct data_queue   *   * @flags: Entry flags, see &enum queue_entry_flags. + * @last_action: Timestamp of last change.   * @queue: The data queue (&struct data_queue) to which this entry belongs.   * @skb: The buffer which is currently being transmitted (for TX queue),   *	or used to directly receive data in (for RX queue). @@ -373,6 +374,7 @@ enum queue_entry_flags {   */  struct queue_entry {  	unsigned long flags; +	unsigned long last_action;  	struct data_queue *queue; @@ -463,7 +465,6 @@ struct data_queue {  	unsigned short threshold;  	unsigned short length;  	unsigned short index[Q_INDEX_MAX]; -	unsigned long last_action[Q_INDEX_MAX];  	unsigned short txop;  	unsigned short aifs; @@ -580,16 +581,22 @@ struct data_queue_desc {   * @queue: Pointer to @data_queue   * @start: &enum queue_index Pointer to start index   * @end: &enum queue_index Pointer to end index + * @data: Data to pass to the callback function   * @fn: The function to call for each &struct queue_entry   *   * This will walk through all entries in the queue, in chronological   * order. This means it will start at the current @start pointer   * and will walk through the queue until it reaches the @end pointer. + * + * If fn returns true for an entry rt2x00queue_for_each_entry will stop + * processing and return true as well.   */ -void rt2x00queue_for_each_entry(struct data_queue *queue, +bool rt2x00queue_for_each_entry(struct data_queue *queue,  				enum queue_index start,  				enum queue_index end, -				void (*fn)(struct queue_entry *entry)); +				void *data, +				bool (*fn)(struct queue_entry *entry, +					   void *data));  /**   * rt2x00queue_empty - Check if the queue is empty. @@ -629,22 +636,24 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)  /**   * rt2x00queue_status_timeout - Check if a timeout occurred for STATUS reports - * @queue: Queue to check. + * @entry: Queue entry to check.   */ -static inline int rt2x00queue_status_timeout(struct data_queue *queue) +static inline int rt2x00queue_status_timeout(struct queue_entry *entry)  { -	return time_after(queue->last_action[Q_INDEX_DMA_DONE], -			  queue->last_action[Q_INDEX_DONE] + (HZ / 10)); +	if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) +		return false; +	return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));  }  /** - * rt2x00queue_timeout - Check if a timeout occurred for DMA transfers - * @queue: Queue to check. + * rt2x00queue_dma_timeout - Check if a timeout occurred for DMA transfers + * @entry: Queue entry to check.   */ -static inline int rt2x00queue_dma_timeout(struct data_queue *queue) +static inline int rt2x00queue_dma_timeout(struct queue_entry *entry)  { -	return time_after(queue->last_action[Q_INDEX], -			  queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10)); +	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) +		return false; +	return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));  }  /** diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 36f388f97d6..cb208d589ff 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -165,6 +165,56 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,  }  EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); + +struct rt2x00_async_read_data { +	__le32 reg; +	struct usb_ctrlrequest cr; +	struct rt2x00_dev *rt2x00dev; +	void (*callback)(struct rt2x00_dev *,int,u32); +}; + +static void rt2x00usb_register_read_async_cb(struct urb *urb) +{ +	struct rt2x00_async_read_data *rd = urb->context; +	rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg)); +	kfree(urb->context); +} + +void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, +				   const unsigned int offset, +				   void (*callback)(struct rt2x00_dev*,int,u32)) +{ +	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); +	struct urb *urb; +	struct rt2x00_async_read_data *rd; + +	rd = kmalloc(sizeof(*rd), GFP_ATOMIC); +	if (!rd) +		return; + +	urb = usb_alloc_urb(0, GFP_ATOMIC); +	if (!urb) { +		kfree(rd); +		return; +	} + +	rd->rt2x00dev = rt2x00dev; +	rd->callback = callback; +	rd->cr.bRequestType = USB_VENDOR_REQUEST_IN; +	rd->cr.bRequest = USB_MULTI_READ; +	rd->cr.wValue = 0; +	rd->cr.wIndex = cpu_to_le16(offset); +	rd->cr.wLength = cpu_to_le16(sizeof(u32)); + +	usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0), +			     (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg), +			     rt2x00usb_register_read_async_cb, rd); +	if (usb_submit_urb(urb, GFP_ATOMIC) < 0) +		kfree(rd); +	usb_free_urb(urb); +} +EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async); +  /*   * TX data handlers.   */ @@ -212,6 +262,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)  	if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))  		return; +	if (rt2x00dev->ops->lib->tx_dma_done) +		rt2x00dev->ops->lib->tx_dma_done(entry); +  	/*  	 * Report the frame as DMA done  	 */ @@ -227,10 +280,12 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)  	 * Schedule the delayed work for reading the TX status  	 * from the device.  	 */ -	queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); +	if (!test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags) || +	    !kfifo_is_empty(&rt2x00dev->txstatus_fifo)) +		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);  } -static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) +static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); @@ -240,7 +295,7 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)  	if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||  	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) -		return; +		return true;  	/*  	 * USB devices cannot blindly pass the skb->len as the @@ -261,6 +316,8 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)  		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);  		rt2x00lib_dmadone(entry);  	} + +	return false;  }  /* @@ -323,7 +380,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)  	queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);  } -static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) +static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); @@ -332,7 +389,7 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)  	if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||  	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) -		return; +		return true;  	rt2x00lib_dmastart(entry); @@ -348,6 +405,8 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)  		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);  		rt2x00lib_dmadone(entry);  	} + +	return false;  }  void rt2x00usb_kick_queue(struct data_queue *queue) @@ -358,12 +417,18 @@ void rt2x00usb_kick_queue(struct data_queue *queue)  	case QID_AC_BE:  	case QID_AC_BK:  		if (!rt2x00queue_empty(queue)) -			rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, +			rt2x00queue_for_each_entry(queue, +						   Q_INDEX_DONE, +						   Q_INDEX, +						   NULL,  						   rt2x00usb_kick_tx_entry);  		break;  	case QID_RX:  		if (!rt2x00queue_full(queue)) -			rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, +			rt2x00queue_for_each_entry(queue, +						   Q_INDEX_DONE, +						   Q_INDEX, +						   NULL,  						   rt2x00usb_kick_rx_entry);  		break;  	default: @@ -372,14 +437,14 @@ void rt2x00usb_kick_queue(struct data_queue *queue)  }  EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); -static void rt2x00usb_flush_entry(struct queue_entry *entry) +static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct queue_entry_priv_usb *entry_priv = entry->priv_data;  	struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;  	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) -		return; +		return true;  	usb_kill_urb(entry_priv->urb); @@ -387,17 +452,20 @@ static void rt2x00usb_flush_entry(struct queue_entry *entry)  	 * Kill guardian urb (if required by driver).  	 */  	if ((entry->queue->qid == QID_BEACON) && -	    (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) +	    (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)))  		usb_kill_urb(bcn_priv->guardian_urb); + +	return false;  } -void rt2x00usb_flush_queue(struct data_queue *queue) +void rt2x00usb_flush_queue(struct data_queue *queue, bool drop)  {  	struct work_struct *completion;  	unsigned int i; -	rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, -				   rt2x00usb_flush_entry); +	if (drop) +		rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, +					   rt2x00usb_flush_entry);  	/*  	 * Obtain the queue completion handler @@ -416,7 +484,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue)  		return;  	} -	for (i = 0; i < 20; i++) { +	for (i = 0; i < 10; i++) {  		/*  		 * Check if the driver is already done, otherwise we  		 * have to sleep a little while to give the driver/hw @@ -456,15 +524,31 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)  	queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work);  } +static int rt2x00usb_status_timeout(struct data_queue *queue) +{ +	struct queue_entry *entry; + +	entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); +	return rt2x00queue_status_timeout(entry); +} + +static int rt2x00usb_dma_timeout(struct data_queue *queue) +{ +	struct queue_entry *entry; + +	entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE); +	return rt2x00queue_dma_timeout(entry); +} +  void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)  {  	struct data_queue *queue;  	tx_queue_for_each(rt2x00dev, queue) {  		if (!rt2x00queue_empty(queue)) { -			if (rt2x00queue_dma_timeout(queue)) +			if (rt2x00usb_dma_timeout(queue))  				rt2x00usb_watchdog_tx_dma(queue); -			if (rt2x00queue_status_timeout(queue)) +			if (rt2x00usb_status_timeout(queue))  				rt2x00usb_watchdog_tx_status(queue);  		}  	} @@ -489,7 +573,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)  	entry->flags = 0;  	if (entry->queue->qid == QID_RX) -		rt2x00usb_kick_rx_entry(entry); +		rt2x00usb_kick_rx_entry(entry, NULL);  }  EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); @@ -583,7 +667,7 @@ static int rt2x00usb_alloc_entries(struct data_queue *queue)  	 * then we are done.  	 */  	if (queue->qid != QID_BEACON || -	    !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) +	    !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))  		return 0;  	for (i = 0; i < queue->limit; i++) { @@ -618,7 +702,7 @@ static void rt2x00usb_free_entries(struct data_queue *queue)  	 * then we are done.  	 */  	if (queue->qid != QID_BEACON || -	    !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) +	    !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))  		return;  	for (i = 0; i < queue->limit; i++) { @@ -707,10 +791,9 @@ exit:  }  int rt2x00usb_probe(struct usb_interface *usb_intf, -		    const struct usb_device_id *id) +		    const struct rt2x00_ops *ops)  {  	struct usb_device *usb_dev = interface_to_usbdev(usb_intf); -	struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info;  	struct ieee80211_hw *hw;  	struct rt2x00_dev *rt2x00dev;  	int retval; @@ -735,6 +818,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,  	INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);  	INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone); +	init_timer(&rt2x00dev->txstatus_timer);  	retval = rt2x00usb_alloc_reg(rt2x00dev);  	if (retval) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index e11c759ac9e..64be34f612f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -35,12 +35,6 @@  })  /* - * This variable should be used with the - * usb_driver structure initialization. - */ -#define USB_DEVICE_DATA(__ops)	.driver_info = (kernel_ulong_t)(__ops) - -/*   * For USB vendor requests we need to pass a timeout   * time in ms, for this we use the REGISTER_TIMEOUT,   * however when loading firmware a higher value is @@ -345,6 +339,21 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,  			   const struct rt2x00_field32 field,  			   u32 *reg); +/** + * rt2x00usb_register_read_async - Asynchronously read 32bit register word + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @callback: Functon to call when read completes. + * + * Submit a control URB to read a 32bit register. This safe to + * be called from atomic context.  The callback will be called + * when the URB completes. Otherwise the function is similar + * to rt2x00usb_register_read(). + */ +void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, +				   const unsigned int offset, +				   void (*callback)(struct rt2x00_dev*,int,u32)); +  /*   * Radio handlers   */ @@ -389,11 +398,13 @@ void rt2x00usb_kick_queue(struct data_queue *queue);  /**   * rt2x00usb_flush_queue - Flush data queue   * @queue: Data queue to stop + * @drop: True to drop all pending frames.   * - * This will walk through all entries of the queue and kill all - * URB's which were send to the device. + * This will walk through all entries of the queue and will optionally + * kill all URB's which were send to the device, or at least wait until + * they have been returned from the device..   */ -void rt2x00usb_flush_queue(struct data_queue *queue); +void rt2x00usb_flush_queue(struct data_queue *queue, bool drop);  /**   * rt2x00usb_watchdog - Watchdog for USB communication @@ -416,7 +427,7 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);   * USB driver handlers.   */  int rt2x00usb_probe(struct usb_interface *usb_intf, -		    const struct usb_device_id *id); +		    const struct rt2x00_ops *ops);  void rt2x00usb_disconnect(struct usb_interface *usb_intf);  #ifdef CONFIG_PM  int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 8ee1514a794..9d35ec16a3a 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -683,7 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));  	rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, -			  !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); +			  !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags));  	/*  	 * Configure the RX antenna. @@ -811,10 +811,10 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,  	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {  		sel = antenna_sel_a; -		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); +		lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);  	} else {  		sel = antenna_sel_bg; -		lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); +		lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);  	}  	for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) @@ -834,7 +834,7 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,  	else if (rt2x00_rf(rt2x00dev, RF2527))  		rt61pci_config_antenna_2x(rt2x00dev, ant);  	else if (rt2x00_rf(rt2x00dev, RF2529)) { -		if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) +		if (test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags))  			rt61pci_config_antenna_2x(rt2x00dev, ant);  		else  			rt61pci_config_antenna_2529(rt2x00dev, ant); @@ -848,13 +848,13 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,  	short lna_gain = 0;  	if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) { -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) +		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))  			lna_gain += 14;  		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);  		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);  	} else { -		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) +		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))  			lna_gain += 14;  		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); @@ -1050,14 +1050,14 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,  	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {  		low_bound = 0x28;  		up_bound = 0x48; -		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { +		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {  			low_bound += 0x10;  			up_bound += 0x10;  		}  	} else {  		low_bound = 0x20;  		up_bound = 0x40; -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { +		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) {  			low_bound += 0x10;  			up_bound += 0x10;  		} @@ -2260,8 +2260,8 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)  	rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);  } -static void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, -				     struct rt2x00_field32 irq_field) +static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, +					    struct rt2x00_field32 irq_field)  {  	u32 reg; @@ -2537,7 +2537,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Determine number of antennas.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2) -		__set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags); +		__set_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags);  	/*  	 * Identify default antenna configuration. @@ -2551,20 +2551,20 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Read the Frame type.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE)) -		__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags); +		__set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);  	/*  	 * Detect if this device has a hardware controlled radio.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);  	/*  	 * Read frequency offset and RF programming sequence.  	 */  	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);  	if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ)) -		__set_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags); +		__set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags);  	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); @@ -2574,9 +2574,9 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);  	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) -		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); +		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);  	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) -		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); +		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);  	/*  	 * When working with a RF2529 chip without double antenna, @@ -2584,7 +2584,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * eeprom word.  	 */  	if (rt2x00_rf(rt2x00dev, RF2529) && -	    !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { +	    !test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) {  		rt2x00dev->default_ant.rx =  		    ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);  		rt2x00dev->default_ant.tx = @@ -2799,7 +2799,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	spec->supported_bands = SUPPORT_BAND_2GHZ;  	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; -	if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) { +	if (!test_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags)) {  		spec->num_channels = 14;  		spec->channels = rf_vals_noseq;  	} else { @@ -2869,16 +2869,16 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)  	 * This device has multiple filters for control frames,  	 * but has no a separate filter for PS Poll frames.  	 */ -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); +	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);  	/*  	 * This device requires firmware and DMA mapped skbs.  	 */ -	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); +	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);  	if (!modparam_nohwcrypt) -		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);  	/*  	 * Set the rssi offset. @@ -2979,6 +2979,9 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {  	.get_tsf		= rt61pci_get_tsf,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.flush			= rt2x00mac_flush, +	.set_antenna		= rt2x00mac_set_antenna, +	.get_antenna		= rt2x00mac_get_antenna, +	.get_ringparam		= rt2x00mac_get_ringparam,  };  static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { @@ -3003,6 +3006,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {  	.start_queue		= rt61pci_start_queue,  	.kick_queue		= rt61pci_kick_queue,  	.stop_queue		= rt61pci_stop_queue, +	.flush_queue		= rt2x00pci_flush_queue,  	.write_tx_desc		= rt61pci_write_tx_desc,  	.write_beacon		= rt61pci_write_beacon,  	.clear_beacon		= rt61pci_clear_beacon, @@ -3060,11 +3064,11 @@ static const struct rt2x00_ops rt61pci_ops = {   */  static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = {  	/* RT2561s */ -	{ PCI_DEVICE(0x1814, 0x0301), PCI_DEVICE_DATA(&rt61pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0301) },  	/* RT2561 v2 */ -	{ PCI_DEVICE(0x1814, 0x0302), PCI_DEVICE_DATA(&rt61pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0302) },  	/* RT2661 */ -	{ PCI_DEVICE(0x1814, 0x0401), PCI_DEVICE_DATA(&rt61pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0401) },  	{ 0, }  }; @@ -3079,10 +3083,16 @@ MODULE_FIRMWARE(FIRMWARE_RT2561s);  MODULE_FIRMWARE(FIRMWARE_RT2661);  MODULE_LICENSE("GPL"); +static int rt61pci_probe(struct pci_dev *pci_dev, +			 const struct pci_device_id *id) +{ +	return rt2x00pci_probe(pci_dev, &rt61pci_ops); +} +  static struct pci_driver rt61pci_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt61pci_device_table, -	.probe		= rt2x00pci_probe, +	.probe		= rt61pci_probe,  	.remove		= __devexit_p(rt2x00pci_remove),  	.suspend	= rt2x00pci_suspend,  	.resume		= rt2x00pci_resume, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6593059f9c7..a6ce7d6cbdf 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -595,7 +595,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,  	switch (ant->rx) {  	case ANTENNA_HW_DIVERSITY:  		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); -		temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags) +		temp = !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)  		       && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);  		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);  		break; @@ -636,7 +636,7 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);  	rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, -			  !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); +			  !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags));  	/*  	 * Configure the RX antenna. @@ -709,10 +709,10 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,  	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {  		sel = antenna_sel_a; -		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); +		lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);  	} else {  		sel = antenna_sel_bg; -		lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); +		lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);  	}  	for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) @@ -740,7 +740,7 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,  	short lna_gain = 0;  	if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) { -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) +		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))  			lna_gain += 14;  		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); @@ -930,7 +930,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,  		low_bound = 0x28;  		up_bound = 0x48; -		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { +		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {  			low_bound += 0x10;  			up_bound += 0x10;  		} @@ -946,7 +946,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,  			up_bound = 0x1c;  		} -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { +		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) {  			low_bound += 0x14;  			up_bound += 0x10;  		} @@ -1661,7 +1661,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)  	}  	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { -		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { +		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {  			if (lna == 3 || lna == 2)  				offset += 10;  		} else { @@ -1899,13 +1899,13 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Read the Frame type.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE)) -		__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags); +		__set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);  	/*  	 * Detect if this device has an hardware controlled radio.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);  	/*  	 * Read frequency offset. @@ -1919,8 +1919,8 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)  	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);  	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) { -		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); -		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); +		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); +		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);  	}  	/* @@ -2200,15 +2200,15 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)  	 * This device has multiple filters for control frames,  	 * but has no a separate filter for PS Poll frames.  	 */ -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); +	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);  	/*  	 * This device requires firmware.  	 */ -	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); +	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);  	if (!modparam_nohwcrypt) -		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);  	/*  	 * Set the rssi offset. @@ -2310,6 +2310,9 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {  	.get_tsf		= rt73usb_get_tsf,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.flush			= rt2x00mac_flush, +	.set_antenna		= rt2x00mac_set_antenna, +	.get_antenna		= rt2x00mac_get_antenna, +	.get_ringparam		= rt2x00mac_get_ringparam,  };  static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { @@ -2388,113 +2391,113 @@ static const struct rt2x00_ops rt73usb_ops = {   */  static struct usb_device_id rt73usb_device_table[] = {  	/* AboCom */ -	{ USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x07b8, 0xb21b) }, +	{ USB_DEVICE(0x07b8, 0xb21c) }, +	{ USB_DEVICE(0x07b8, 0xb21d) }, +	{ USB_DEVICE(0x07b8, 0xb21e) }, +	{ USB_DEVICE(0x07b8, 0xb21f) },  	/* AL */ -	{ USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x14b2, 0x3c10) },  	/* Amigo */ -	{ USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x148f, 0x9021) }, +	{ USB_DEVICE(0x0eb0, 0x9021) },  	/* AMIT  */ -	{ USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x18c5, 0x0002) },  	/* Askey */ -	{ USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1690, 0x0722) },  	/* ASUS */ -	{ USB_DEVICE(0x0b05, 0x1723), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1724), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0b05, 0x1723) }, +	{ USB_DEVICE(0x0b05, 0x1724) },  	/* Belkin */ -	{ USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x050d, 0x705a) }, +	{ USB_DEVICE(0x050d, 0x905b) }, +	{ USB_DEVICE(0x050d, 0x905c) },  	/* Billionton */ -	{ USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1631, 0xc019) }, +	{ USB_DEVICE(0x08dd, 0x0120) },  	/* Buffalo */ -	{ USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0137), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0411, 0x00d8) }, +	{ USB_DEVICE(0x0411, 0x00d9) }, +	{ USB_DEVICE(0x0411, 0x00f4) }, +	{ USB_DEVICE(0x0411, 0x0116) }, +	{ USB_DEVICE(0x0411, 0x0119) }, +	{ USB_DEVICE(0x0411, 0x0137) },  	/* CEIVA */ -	{ USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x178d, 0x02be) },  	/* CNet */ -	{ USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1371, 0x9022) }, +	{ USB_DEVICE(0x1371, 0x9032) },  	/* Conceptronic */ -	{ USB_DEVICE(0x14b2, 0x3c22), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x14b2, 0x3c22) },  	/* Corega */ -	{ USB_DEVICE(0x07aa, 0x002e), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x07aa, 0x002e) },  	/* D-Link */ -	{ USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x07d1, 0x3c03) }, +	{ USB_DEVICE(0x07d1, 0x3c04) }, +	{ USB_DEVICE(0x07d1, 0x3c06) }, +	{ USB_DEVICE(0x07d1, 0x3c07) },  	/* Edimax */ -	{ USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x7392, 0x7318) }, +	{ USB_DEVICE(0x7392, 0x7618) },  	/* EnGenius */ -	{ USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1740, 0x3701) },  	/* Gemtek */ -	{ USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x15a9, 0x0004) },  	/* Gigabyte */ -	{ USB_DEVICE(0x1044, 0x8008), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x1044, 0x800a), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1044, 0x8008) }, +	{ USB_DEVICE(0x1044, 0x800a) },  	/* Huawei-3Com */ -	{ USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1472, 0x0009) },  	/* Hercules */ -	{ USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x06f8, 0xe002) }, +	{ USB_DEVICE(0x06f8, 0xe010) }, +	{ USB_DEVICE(0x06f8, 0xe020) },  	/* Linksys */ -	{ USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x13b1, 0x0020) }, +	{ USB_DEVICE(0x13b1, 0x0023) }, +	{ USB_DEVICE(0x13b1, 0x0028) },  	/* MSI */ -	{ USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0db0, 0x4600) }, +	{ USB_DEVICE(0x0db0, 0x6877) }, +	{ USB_DEVICE(0x0db0, 0x6874) }, +	{ USB_DEVICE(0x0db0, 0xa861) }, +	{ USB_DEVICE(0x0db0, 0xa874) },  	/* Ovislink */ -	{ USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1b75, 0x7318) },  	/* Ralink */ -	{ USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x04bb, 0x093d) }, +	{ USB_DEVICE(0x148f, 0x2573) }, +	{ USB_DEVICE(0x148f, 0x2671) }, +	{ USB_DEVICE(0x0812, 0x3101) },  	/* Qcom */ -	{ USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x18e8, 0x6238), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x18e8, 0x6196) }, +	{ USB_DEVICE(0x18e8, 0x6229) }, +	{ USB_DEVICE(0x18e8, 0x6238) },  	/* Samsung */ -	{ USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x04e8, 0x4471) },  	/* Senao */ -	{ USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1740, 0x7100) },  	/* Sitecom */ -	{ USB_DEVICE(0x0df6, 0x0024), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0027), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x002f), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0df6, 0x0024) }, +	{ USB_DEVICE(0x0df6, 0x0027) }, +	{ USB_DEVICE(0x0df6, 0x002f) }, +	{ USB_DEVICE(0x0df6, 0x90ac) }, +	{ USB_DEVICE(0x0df6, 0x9712) },  	/* Surecom */ -	{ USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0769, 0x31f3) },  	/* Tilgin */ -	{ USB_DEVICE(0x6933, 0x5001), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x6933, 0x5001) },  	/* Philips */ -	{ USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0471, 0x200a) },  	/* Planex */ -	{ USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x2019, 0xab01) }, +	{ USB_DEVICE(0x2019, 0xab50) },  	/* WideTell */ -	{ USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x7167, 0x3840) },  	/* Zcom */ -	{ USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0cde, 0x001c) },  	/* ZyXEL */ -	{ USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0586, 0x3415) },  	{ 0, }  }; @@ -2506,10 +2509,16 @@ MODULE_DEVICE_TABLE(usb, rt73usb_device_table);  MODULE_FIRMWARE(FIRMWARE_RT2571);  MODULE_LICENSE("GPL"); +static int rt73usb_probe(struct usb_interface *usb_intf, +			 const struct usb_device_id *id) +{ +	return rt2x00usb_probe(usb_intf, &rt73usb_ops); +} +  static struct usb_driver rt73usb_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt73usb_device_table, -	.probe		= rt2x00usb_probe, +	.probe		= rt73usb_probe,  	.disconnect	= rt2x00usb_disconnect,  	.suspend	= rt2x00usb_suspend,  	.resume		= rt2x00usb_resume, diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 4803f54842e..b259f807ad2 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -251,14 +251,16 @@ void rtl_init_rfkill(struct ieee80211_hw *hw)  	bool blocked;  	u8 valid = 0; -	radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); +	/*set init state to on */ +	rtlpriv->rfkill.rfkill_state = 1; +	wiphy_rfkill_set_hw_state(hw->wiphy, 0); -	/*set init state to that of switch */ -	rtlpriv->rfkill.rfkill_state = radio_state; -	printk(KERN_INFO "rtlwifi: wireless switch is %s\n", -	       rtlpriv->rfkill.rfkill_state ? "on" : "off"); +	radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid);  	if (valid) { +		printk(KERN_INFO "rtlwifi: wireless switch is %s\n", +				rtlpriv->rfkill.rfkill_state ? "on" : "off"); +  		rtlpriv->rfkill.rfkill_state = radio_state;  		blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1; diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index fbde52d8342..c3dd4cc678b 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1785,7 +1785,8 @@ void rtl_pci_disconnect(struct pci_dev *pdev)  	rtl_pci_deinit(hw);  	rtl_deinit_core(hw); -	rtlpriv->cfg->ops->deinit_sw_leds(hw); +	if (rtlpriv->cfg->ops->deinit_sw_leds) +		rtlpriv->cfg->ops->deinit_sw_leds(hw);  	_rtl_pci_io_handler_release(hw);  	rtlpriv->cfg->ops->deinit_sw_vars(hw); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index bb023274414..c228b9ee371 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -634,7 +634,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw  	u8 thermalvalue, delta, delta_lck, delta_iqk;  	long ele_a, ele_d, temp_cck, val_x, value32;  	long val_y, ele_c; -	u8 ofdm_index[2], cck_index, ofdm_index_old[2], cck_index_old; +	u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0;  	int i;  	bool is2t = IS_92C_SERIAL(rtlhal->version);  	u8 txpwr_level[2] = {0, 0}; diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index f107660f545..bc9d24134ac 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -293,7 +293,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));  	u8 boxnum; -	u16 box_reg, box_extreg; +	u16 box_reg = 0, box_extreg = 0;  	u8 u1b_tmp;  	bool isfw_read = false;  	bool bwrite_sucess = false; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c index 7b1da8d7508..d21b934b5c3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c @@ -32,6 +32,14 @@  #include "reg.h"  #include "led.h" +static void _rtl92ce_init_led(struct ieee80211_hw *hw, +			      struct rtl_led *pled, enum rtl_led_pin ledpin) +{ +	pled->hw = hw; +	pled->ledpin = ledpin; +	pled->ledon = false; +} +  void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)  {  	u8 ledcfg; @@ -97,10 +105,10 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)  void rtl92ce_init_sw_leds(struct ieee80211_hw *hw)  { -} +	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); -void rtl92ce_deinit_sw_leds(struct ieee80211_hw *hw) -{ +	_rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); +	_rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);  }  void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/rtlwifi/rtl8192ce/led.h index 10da3018f4b..94332b3af5b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.h @@ -31,7 +31,6 @@  #define __RTL92CE_LED_H__  void rtl92ce_init_sw_leds(struct ieee80211_hw *hw); -void rtl92ce_deinit_sw_leds(struct ieee80211_hw *hw);  void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);  void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);  void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c index 669b1168dbe..e301b12e281 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c @@ -202,7 +202,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_phy *rtlphy = &(rtlpriv->phy);  	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -	u8 i, chnlgroup, pwr_diff_limit[4]; +	u8 i, chnlgroup = 0, pwr_diff_limit[4];  	u32 writeVal, customer_limit, rf;  	for (rf = 0; rf < 2; rf++) { @@ -447,7 +447,7 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_phy *rtlphy = &(rtlpriv->phy); -	u32 u4_regvalue; +	u32 u4_regvalue = 0;  	u8 rfpath;  	bool rtstatus;  	struct bb_reg_def *pphyreg; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index b1cc4d44f53..f4e2f3dccca 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -131,7 +131,6 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = {  	.enable_hw_sec = rtl92ce_enable_hw_security_config,  	.set_key = rtl92ce_set_key,  	.init_sw_leds = rtl92ce_init_sw_leds, -	.deinit_sw_leds = rtl92ce_deinit_sw_leds,  	.get_bbreg = rtl92c_phy_query_bb_reg,  	.set_bbreg = rtl92c_phy_set_bb_reg,  	.get_rfreg = rtl92ce_phy_query_rf_reg, diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 9444e76838c..e43be254782 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -921,7 +921,7 @@ static void _rtl92cu_init_chipT_queue_priority(struct ieee80211_hw *hw,  					       u8 out_ep_num,  					       u8 queue_sel)  { -	u8	hq_sele; +	u8 hq_sele = 0;  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	switch (out_ep_num) { diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 1832c27c520..216b1d8a862 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -410,6 +410,16 @@   *	notification. This event is used to indicate that an unprotected   *	disassociation frame was dropped when MFP is in use.   * + * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a + *      beacon or probe response from a compatible mesh peer.  This is only + *      sent while no station information (sta_info) exists for the new peer + *      candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set.  On + *      reception of this notification, userspace may decide to create a new + *      station (@NL80211_CMD_NEW_STATION).  To stop this notification from + *      reoccurring, the userspace authentication daemon may want to create the + *      new station with the AUTHENTICATED flag unset and maybe change it later + *      depending on the authentication result. + *   * @NL80211_CMD_MAX: highest used command number   * @__NL80211_CMD_AFTER_LAST: internal use   */ @@ -522,6 +532,8 @@ enum nl80211_commands {  	NL80211_CMD_UNPROT_DEAUTHENTICATE,  	NL80211_CMD_UNPROT_DISASSOCIATE, +	NL80211_CMD_NEW_PEER_CANDIDATE, +  	/* add new commands above here */  	/* used to define NL80211_CMD_MAX below */ @@ -545,6 +557,7 @@ enum nl80211_commands {  /* source-level API compatibility */  #define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG  #define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG +#define NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE NL80211_MESH_SETUP_IE  /**   * enum nl80211_attrs - nl80211 netlink attributes @@ -886,6 +899,9 @@ enum nl80211_commands {   *	changed once the mesh is active.   * @NL80211_ATTR_MESH_CONFIG: Mesh configuration parameters, a nested attribute   *	containing attributes from &enum nl80211_meshconf_params. + * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver + *	allows auth frames in a mesh to be passed to userspace for processing via + *	the @NL80211_MESH_SETUP_USERSPACE_AUTH flag.   *   * @NL80211_ATTR_MAX: highest attribute number currently defined   * @__NL80211_ATTR_AFTER_LAST: internal use @@ -1074,6 +1090,8 @@ enum nl80211_attrs {  	NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,  	NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, +	NL80211_ATTR_SUPPORT_MESH_AUTH, +  	/* add attributes here, update the policy in nl80211.c */  	__NL80211_ATTR_AFTER_LAST, @@ -1168,6 +1186,7 @@ enum nl80211_iftype {   *	with short barker preamble   * @NL80211_STA_FLAG_WME: station is WME/QoS capable   * @NL80211_STA_FLAG_MFP: station uses management frame protection + * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated   * @NL80211_STA_FLAG_MAX: highest station flag number currently defined   * @__NL80211_STA_FLAG_AFTER_LAST: internal use   */ @@ -1177,6 +1196,7 @@ enum nl80211_sta_flags {  	NL80211_STA_FLAG_SHORT_PREAMBLE,  	NL80211_STA_FLAG_WME,  	NL80211_STA_FLAG_MFP, +	NL80211_STA_FLAG_AUTHENTICATED,  	/* keep last */  	__NL80211_STA_FLAG_AFTER_LAST, @@ -1277,6 +1297,7 @@ enum nl80211_sta_bss_param {   *	attribute, like NL80211_STA_INFO_TX_BITRATE.   * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute   *     containing info as possible, see &enum nl80211_sta_bss_param + * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected   * @__NL80211_STA_INFO_AFTER_LAST: internal   * @NL80211_STA_INFO_MAX: highest possible station info attribute   */ @@ -1297,6 +1318,7 @@ enum nl80211_sta_info {  	NL80211_STA_INFO_SIGNAL_AVG,  	NL80211_STA_INFO_RX_BITRATE,  	NL80211_STA_INFO_BSS_PARAM, +	NL80211_STA_INFO_CONNECTED_TIME,  	/* keep last */  	__NL80211_STA_INFO_AFTER_LAST, @@ -1719,9 +1741,12 @@ enum nl80211_meshconf_params {   * vendor specific path metric or disable it to use the default Airtime   * metric.   * - * @NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE: A vendor specific information - * element that vendors will use to identify the path selection methods and - * metrics in use. + * @NL80211_MESH_SETUP_IE: Information elements for this mesh, for instance, a + * robust security network ie, or a vendor specific information element that + * vendors will use to identify the path selection methods and metrics in use. + * + * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication + * daemon will be authenticating mesh candidates.   *   * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number   * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use @@ -1730,7 +1755,8 @@ enum nl80211_mesh_setup_params {  	__NL80211_MESH_SETUP_INVALID,  	NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL,  	NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC, -	NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE, +	NL80211_MESH_SETUP_IE, +	NL80211_MESH_SETUP_USERSPACE_AUTH,  	/* keep last */  	__NL80211_MESH_SETUP_ATTR_AFTER_LAST, diff --git a/include/linux/rfkill-regulator.h b/include/linux/rfkill-regulator.h new file mode 100644 index 00000000000..aca36bc8331 --- /dev/null +++ b/include/linux/rfkill-regulator.h @@ -0,0 +1,48 @@ +/* + * rfkill-regulator.c - Regulator consumer driver for rfkill + * + * Copyright (C) 2009  Guiming Zhuo <gmzhuo@gmail.com> + * Copyright (C) 2011  Antonio Ospite <ospite@studenti.unina.it> + * + * 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. + * + */ + +#ifndef __LINUX_RFKILL_REGULATOR_H +#define __LINUX_RFKILL_REGULATOR_H + +/* + * Use "vrfkill" as supply id when declaring the regulator consumer: + * + * static struct regulator_consumer_supply pcap_regulator_V6_consumers [] = { + * 	{ .dev_name = "rfkill-regulator.0", .supply = "vrfkill" }, + * }; + * + * If you have several regulator driven rfkill, you can append a numerical id to + * .dev_name as done above, and use the same id when declaring the platform + * device: + * + * static struct rfkill_regulator_platform_data ezx_rfkill_bt_data = { + * 	.name  = "ezx-bluetooth", + * 	.type  = RFKILL_TYPE_BLUETOOTH, + * }; + * + * static struct platform_device a910_rfkill = { + * 	.name  = "rfkill-regulator", + * 	.id    = 0, + * 	.dev   = { + * 		.platform_data = &ezx_rfkill_bt_data, + * 	}, + * }; + */ + +#include <linux/rfkill.h> + +struct rfkill_regulator_platform_data { +	char *name;             /* the name for the rfkill switch */ +	enum rfkill_type type;  /* the type as specified in rfkill.h */ +}; + +#endif /* __LINUX_RFKILL_REGULATOR_H */ diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 2b9ca0d5c4a..7a215a7f9e3 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -276,10 +276,52 @@ struct l2cap_conn_param_update_rsp {  #define L2CAP_CONN_PARAM_ACCEPTED	0x0000  #define L2CAP_CONN_PARAM_REJECTED	0x0001 -/* ----- L2CAP connections ----- */ -struct l2cap_chan_list { -	struct sock	*head; -	rwlock_t	lock; +/* ----- L2CAP channels and connections ----- */ +struct srej_list { +	__u8	tx_seq; +	struct list_head list; +}; + +struct l2cap_chan { +	struct sock *sk; +	__u8		ident; + +	__u8		conf_req[64]; +	__u8		conf_len; +	__u8		num_conf_req; +	__u8		num_conf_rsp; + +	__u16		conn_state; + +	__u8		next_tx_seq; +	__u8		expected_ack_seq; +	__u8		expected_tx_seq; +	__u8		buffer_seq; +	__u8		buffer_seq_srej; +	__u8		srej_save_reqseq; +	__u8		frames_sent; +	__u8		unacked_frames; +	__u8		retry_count; +	__u8		num_acked; +	__u16		sdu_len; +	__u16		partial_sdu_len; +	struct sk_buff	*sdu; + +	__u8		remote_tx_win; +	__u8		remote_max_tx; +	__u16		remote_mps; + +	struct timer_list	retrans_timer; +	struct timer_list	monitor_timer; +	struct timer_list	ack_timer; +	struct sk_buff		*tx_send_head; +	struct sk_buff_head	tx_q; +	struct sk_buff_head	srej_q; +	struct sk_buff_head	busy_q; +	struct work_struct	busy_work; +	struct list_head	srej_l; + +	struct list_head list;  };  struct l2cap_conn { @@ -305,29 +347,16 @@ struct l2cap_conn {  	__u8		disc_reason; -	struct l2cap_chan_list chan_list; -}; - -struct sock_del_list { -	struct sock *sk; -	struct list_head list; +	struct list_head chan_l; +	rwlock_t	chan_lock;  };  #define L2CAP_INFO_CL_MTU_REQ_SENT	0x01  #define L2CAP_INFO_FEAT_MASK_REQ_SENT	0x04  #define L2CAP_INFO_FEAT_MASK_REQ_DONE	0x08 -/* ----- L2CAP channel and socket info ----- */ +/* ----- L2CAP socket info ----- */  #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) -#define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue) -#define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue) -#define BUSY_QUEUE(sk) (&l2cap_pi(sk)->busy_queue) -#define SREJ_LIST(sk) (&l2cap_pi(sk)->srej_l.list) - -struct srej_list { -	__u8	tx_seq; -	struct list_head list; -};  struct l2cap_pinfo {  	struct bt_sock	bt; @@ -339,8 +368,6 @@ struct l2cap_pinfo {  	__u16		omtu;  	__u16		flush_to;  	__u8		mode; -	__u8		num_conf_req; -	__u8		num_conf_rsp;  	__u8		fcs;  	__u8		sec_level; @@ -348,49 +375,18 @@ struct l2cap_pinfo {  	__u8		force_reliable;  	__u8		flushable; -	__u8		conf_req[64]; -	__u8		conf_len;  	__u8		conf_state; -	__u16		conn_state; - -	__u8		next_tx_seq; -	__u8		expected_ack_seq; -	__u8		expected_tx_seq; -	__u8		buffer_seq; -	__u8		buffer_seq_srej; -	__u8		srej_save_reqseq; -	__u8		frames_sent; -	__u8		unacked_frames; -	__u8		retry_count; -	__u8		num_acked; -	__u16		sdu_len; -	__u16		partial_sdu_len; -	struct sk_buff	*sdu; - -	__u8		ident;  	__u8		tx_win;  	__u8		max_tx; -	__u8		remote_tx_win; -	__u8		remote_max_tx;  	__u16		retrans_timeout;  	__u16		monitor_timeout; -	__u16		remote_mps;  	__u16		mps;  	__le16		sport; -	struct timer_list	retrans_timer; -	struct timer_list	monitor_timer; -	struct timer_list	ack_timer; -	struct sk_buff_head	tx_queue; -	struct sk_buff_head	srej_queue; -	struct sk_buff_head	busy_queue; -	struct work_struct	busy_work; -	struct srej_list	srej_l;  	struct l2cap_conn	*conn; -	struct sock		*next_c; -	struct sock		*prev_c; +	struct l2cap_chan	*chan;  };  #define L2CAP_CONF_REQ_SENT       0x01 @@ -417,24 +413,23 @@ struct l2cap_pinfo {  #define L2CAP_CONN_RNR_SENT        0x0200  #define L2CAP_CONN_SAR_RETRY       0x0400 -#define __mod_retrans_timer() mod_timer(&l2cap_pi(sk)->retrans_timer, \ +#define __mod_retrans_timer() mod_timer(&chan->retrans_timer, \  		jiffies +  msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); -#define __mod_monitor_timer() mod_timer(&l2cap_pi(sk)->monitor_timer, \ +#define __mod_monitor_timer() mod_timer(&chan->monitor_timer, \  		jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO)); -#define __mod_ack_timer() mod_timer(&l2cap_pi(sk)->ack_timer, \ +#define __mod_ack_timer() mod_timer(&chan->ack_timer, \  		jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); -static inline int l2cap_tx_window_full(struct sock *sk) +static inline int l2cap_tx_window_full(struct l2cap_chan *ch)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk);  	int sub; -	sub = (pi->next_tx_seq - pi->expected_ack_seq) % 64; +	sub = (ch->next_tx_seq - ch->expected_ack_seq) % 64;  	if (sub < 0)  		sub += 64; -	return sub == pi->remote_tx_win; +	return sub == ch->remote_tx_win;  }  #define __get_txseq(ctrl)	(((ctrl) & L2CAP_CTRL_TXSEQ) >> 1) @@ -450,18 +445,17 @@ extern struct bt_sock_list l2cap_sk_list;  int l2cap_init_sockets(void);  void l2cap_cleanup_sockets(void); -u8 l2cap_get_ident(struct l2cap_conn *conn);  void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data); -int l2cap_build_conf_req(struct sock *sk, void *data); +void __l2cap_connect_rsp_defer(struct sock *sk);  int __l2cap_wait_ack(struct sock *sk);  struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len);  struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len);  struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen); -int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len); +int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);  void l2cap_do_send(struct sock *sk, struct sk_buff *skb); -void l2cap_streaming_send(struct sock *sk); -int l2cap_ertm_send(struct sock *sk); +void l2cap_streaming_send(struct l2cap_chan *chan); +int l2cap_ertm_send(struct l2cap_chan *chan);  void l2cap_sock_set_timer(struct sock *sk, long timeout);  void l2cap_sock_clear_timer(struct sock *sk); @@ -470,8 +464,8 @@ void l2cap_sock_kill(struct sock *sk);  void l2cap_sock_init(struct sock *sk, struct sock *parent);  struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,  							int proto, gfp_t prio); -void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err); -void l2cap_chan_del(struct sock *sk, int err); +void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); +void l2cap_chan_del(struct l2cap_chan *chan, int err);  int l2cap_do_connect(struct sock *sk);  #endif /* __L2CAP_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index ba7384acf4e..d30eada7c6c 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -423,6 +423,7 @@ struct station_parameters {   * @STATION_INFO_SIGNAL_AVG: @signal_avg filled   * @STATION_INFO_RX_BITRATE: @rxrate fields are filled   * @STATION_INFO_BSS_PARAM: @bss_param filled + * @STATION_INFO_CONNECTED_TIME: @connected_time filled   */  enum station_info_flags {  	STATION_INFO_INACTIVE_TIME	= 1<<0, @@ -441,6 +442,7 @@ enum station_info_flags {  	STATION_INFO_SIGNAL_AVG		= 1<<13,  	STATION_INFO_RX_BITRATE		= 1<<14,  	STATION_INFO_BSS_PARAM          = 1<<15, +	STATION_INFO_CONNECTED_TIME	= 1<<16  };  /** @@ -511,6 +513,7 @@ struct sta_bss_parameters {   * Station information filled by driver for get_station() and dump_station.   *   * @filled: bitflag of flags from &enum station_info_flags + * @connected_time: time(in secs) since a station is last connected   * @inactive_time: time since last station activity (tx/rx) in milliseconds   * @rx_bytes: bytes received from this station   * @tx_bytes: bytes transmitted to this station @@ -533,6 +536,7 @@ struct sta_bss_parameters {   */  struct station_info {  	u32 filled; +	u32 connected_time;  	u32 inactive_time;  	u32 rx_bytes;  	u32 tx_bytes; @@ -689,8 +693,9 @@ struct mesh_config {   * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes   * @path_sel_proto: which path selection protocol to use   * @path_metric: which metric to use - * @vendor_ie: vendor information elements (optional) - * @vendor_ie_len: length of vendor information elements + * @ie: vendor information elements (optional) + * @ie_len: length of vendor information elements + * @is_secure: or not   *   * These parameters are fixed when the mesh is created.   */ @@ -699,8 +704,9 @@ struct mesh_setup {  	u8 mesh_id_len;  	u8  path_sel_proto;  	u8  path_metric; -	const u8 *vendor_ie; -	u8 vendor_ie_len; +	const u8 *ie; +	u8 ie_len; +	bool is_secure;  };  /** @@ -1451,6 +1457,8 @@ struct cfg80211_ops {   * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN.   * @WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS: The device supports separate   *	unicast and multicast TX keys. + * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing + *	auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH.   */  enum wiphy_flags {  	WIPHY_FLAG_CUSTOM_REGULATORY		= BIT(0), @@ -1463,6 +1471,7 @@ enum wiphy_flags {  	WIPHY_FLAG_CONTROL_PORT_PROTOCOL	= BIT(7),  	WIPHY_FLAG_IBSS_RSN			= BIT(8),  	WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9), +	WIPHY_FLAG_MESH_AUTH			= BIT(10),  };  struct mac_address { @@ -2484,6 +2493,22 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,  void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);  /** + * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate + * + * @dev: network device + * @macaddr: the MAC address of the new candidate + * @ie: information elements advertised by the peer candidate + * @ie_len: lenght of the information elements buffer + * @gfp: allocation flags + * + * This function notifies cfg80211 that the mesh peer candidate has been + * detected, most likely via a beacon or, less likely, via a probe response. + * cfg80211 then sends a notification to userspace. + */ +void cfg80211_notify_new_peer_candidate(struct net_device *dev, +		const u8 *macaddr, const u8 *ie, u8 ie_len, gfp_t gfp); + +/**   * DOC: RFkill integration   *   * RFkill integration in cfg80211 is almost invisible to drivers, diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 025d4cc7bbf..d23dd6c1329 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1819,6 +1819,9 @@ enum ieee80211_ampdu_mlme_action {   * @set_ringparam: Set tx and rx ring sizes.   *   * @get_ringparam: Get tx and rx ring current and maximum sizes. + * + * @tx_frames_pending: Check if there is any pending frame in the hardware + *	queues before entering power save.   */  struct ieee80211_ops {  	void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); @@ -1906,6 +1909,7 @@ struct ieee80211_ops {  	int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);  	void (*get_ringparam)(struct ieee80211_hw *hw,  			      u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); +	bool (*tx_frames_pending)(struct ieee80211_hw *hw);  };  /** @@ -2223,6 +2227,18 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,  #define IEEE80211_TX_STATUS_HEADROOM	13  /** + * ieee80211_sta_set_tim - set the TIM bit for a sleeping station + * + * If a driver buffers frames for a powersave station instead of passing + * them back to mac80211 for retransmission, the station needs to be told + * to wake up using the TIM bitmap in the beacon. + * + * This function sets the station's TIM bit - it will be cleared when the + * station wakes up. + */ +void ieee80211_sta_set_tim(struct ieee80211_sta *sta); + +/**   * ieee80211_tx_status - transmit status callback   *   * Call this function for all transmitted frames after they have been diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 7a3398d9cd6..c7eb073fe63 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2497,6 +2497,9 @@ static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,  	hci_dev_lock(hdev); +	if (!test_bit(HCI_MGMT, &hdev->flags)) +		goto unlock; +  	data = hci_find_remote_oob_data(hdev, &ev->bdaddr);  	if (data) {  		struct hci_cp_remote_oob_data_reply cp; @@ -2515,6 +2518,7 @@ static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,  									&cp);  	} +unlock:  	hci_dev_unlock(hdev);  } diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c3cebed205c..d47de2b04b2 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -70,108 +70,101 @@ static void l2cap_busy_work(struct work_struct *work);  static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,  				u8 code, u8 ident, u16 dlen, void *data); +static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);  static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);  /* ---- L2CAP channels ---- */ -static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) +static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)  { -	struct sock *s; -	for (s = l->head; s; s = l2cap_pi(s)->next_c) { +	struct l2cap_chan *c; + +	list_for_each_entry(c, &conn->chan_l, list) { +		struct sock *s = c->sk;  		if (l2cap_pi(s)->dcid == cid) -			break; +			return c;  	} -	return s; +	return NULL; +  } -static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) +static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)  { -	struct sock *s; -	for (s = l->head; s; s = l2cap_pi(s)->next_c) { +	struct l2cap_chan *c; + +	list_for_each_entry(c, &conn->chan_l, list) { +		struct sock *s = c->sk;  		if (l2cap_pi(s)->scid == cid) -			break; +			return c;  	} -	return s; +	return NULL;  }  /* Find channel with given SCID.   * Returns locked socket */ -static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid) +static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid)  { -	struct sock *s; -	read_lock(&l->lock); -	s = __l2cap_get_chan_by_scid(l, cid); -	if (s) -		bh_lock_sock(s); -	read_unlock(&l->lock); -	return s; +	struct l2cap_chan *c; + +	read_lock(&conn->chan_lock); +	c = __l2cap_get_chan_by_scid(conn, cid); +	if (c) +		bh_lock_sock(c->sk); +	read_unlock(&conn->chan_lock); +	return c;  } -static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) +static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)  { -	struct sock *s; -	for (s = l->head; s; s = l2cap_pi(s)->next_c) { -		if (l2cap_pi(s)->ident == ident) -			break; +	struct l2cap_chan *c; + +	list_for_each_entry(c, &conn->chan_l, list) { +		if (c->ident == ident) +			return c;  	} -	return s; +	return NULL;  } -static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident) +static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident)  { -	struct sock *s; -	read_lock(&l->lock); -	s = __l2cap_get_chan_by_ident(l, ident); -	if (s) -		bh_lock_sock(s); -	read_unlock(&l->lock); -	return s; +	struct l2cap_chan *c; + +	read_lock(&conn->chan_lock); +	c = __l2cap_get_chan_by_ident(conn, ident); +	if (c) +		bh_lock_sock(c->sk); +	read_unlock(&conn->chan_lock); +	return c;  } -static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) +static u16 l2cap_alloc_cid(struct l2cap_conn *conn)  {  	u16 cid = L2CAP_CID_DYN_START;  	for (; cid < L2CAP_CID_DYN_END; cid++) { -		if (!__l2cap_get_chan_by_scid(l, cid)) +		if (!__l2cap_get_chan_by_scid(conn, cid))  			return cid;  	}  	return 0;  } -static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk) +static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)  { -	sock_hold(sk); +	struct l2cap_chan *chan; -	if (l->head) -		l2cap_pi(l->head)->prev_c = sk; - -	l2cap_pi(sk)->next_c = l->head; -	l2cap_pi(sk)->prev_c = NULL; -	l->head = sk; -} - -static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk) -{ -	struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c; - -	write_lock_bh(&l->lock); -	if (sk == l->head) -		l->head = next; +	chan = kzalloc(sizeof(*chan), GFP_ATOMIC); +	if (!chan) +		return NULL; -	if (next) -		l2cap_pi(next)->prev_c = prev; -	if (prev) -		l2cap_pi(prev)->next_c = next; -	write_unlock_bh(&l->lock); +	chan->sk = sk; -	__sock_put(sk); +	return chan;  } -static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) +static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)  { -	struct l2cap_chan_list *l = &conn->chan_list; +	struct sock *sk = chan->sk;  	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,  			l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid); @@ -188,7 +181,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk)  			l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;  		} else {  			/* Alloc CID for connection-oriented socket */ -			l2cap_pi(sk)->scid = l2cap_alloc_cid(l); +			l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);  			l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;  		}  	} else if (sk->sk_type == SOCK_DGRAM) { @@ -203,23 +196,30 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk)  		l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;  	} -	__l2cap_chan_link(l, sk); +	sock_hold(sk); + +	list_add(&chan->list, &conn->chan_l);  }  /* Delete channel.   * Must be called on the locked socket. */ -void l2cap_chan_del(struct sock *sk, int err) +void l2cap_chan_del(struct l2cap_chan *chan, int err)  { +	struct sock *sk = chan->sk;  	struct l2cap_conn *conn = l2cap_pi(sk)->conn;  	struct sock *parent = bt_sk(sk)->parent;  	l2cap_sock_clear_timer(sk); -	BT_DBG("sk %p, conn %p, err %d", sk, conn, err); +	BT_DBG("chan %p, conn %p, err %d", chan, conn, err);  	if (conn) { -		/* Unlink from channel list */ -		l2cap_chan_unlink(&conn->chan_list, sk); +		/* Delete from channel list */ +		write_lock_bh(&conn->chan_lock); +		list_del(&chan->list); +		write_unlock_bh(&conn->chan_lock); +		__sock_put(sk); +  		l2cap_pi(sk)->conn = NULL;  		hci_conn_put(conn->hcon);  	} @@ -236,23 +236,30 @@ void l2cap_chan_del(struct sock *sk, int err)  	} else  		sk->sk_state_change(sk); -	skb_queue_purge(TX_QUEUE(sk)); +	if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE && +			l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE)) +		goto free; + +	skb_queue_purge(&chan->tx_q);  	if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {  		struct srej_list *l, *tmp; -		del_timer(&l2cap_pi(sk)->retrans_timer); -		del_timer(&l2cap_pi(sk)->monitor_timer); -		del_timer(&l2cap_pi(sk)->ack_timer); +		del_timer(&chan->retrans_timer); +		del_timer(&chan->monitor_timer); +		del_timer(&chan->ack_timer); -		skb_queue_purge(SREJ_QUEUE(sk)); -		skb_queue_purge(BUSY_QUEUE(sk)); +		skb_queue_purge(&chan->srej_q); +		skb_queue_purge(&chan->busy_q); -		list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { +		list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {  			list_del(&l->list);  			kfree(l);  		}  	} + +free: +	kfree(chan);  }  static inline u8 l2cap_get_auth_type(struct sock *sk) @@ -338,10 +345,11 @@ void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *d  	hci_send_acl(conn->hcon, skb, flags);  } -static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) +static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)  {  	struct sk_buff *skb;  	struct l2cap_hdr *lh; +	struct l2cap_pinfo *pi = l2cap_pi(chan->sk);  	struct l2cap_conn *conn = pi->conn;  	struct sock *sk = (struct sock *)pi;  	int count, hlen = L2CAP_HDR_SIZE + 2; @@ -353,19 +361,19 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)  	if (pi->fcs == L2CAP_FCS_CRC16)  		hlen += 2; -	BT_DBG("pi %p, control 0x%2.2x", pi, control); +	BT_DBG("chan %p, control 0x%2.2x", chan, control);  	count = min_t(unsigned int, conn->mtu, hlen);  	control |= L2CAP_CTRL_FRAME_TYPE; -	if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { +	if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {  		control |= L2CAP_CTRL_FINAL; -		pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; +		chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;  	} -	if (pi->conn_state & L2CAP_CONN_SEND_PBIT) { +	if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {  		control |= L2CAP_CTRL_POLL; -		pi->conn_state &= ~L2CAP_CONN_SEND_PBIT; +		chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;  	}  	skb = bt_skb_alloc(count, GFP_ATOMIC); @@ -390,17 +398,17 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)  	hci_send_acl(pi->conn->hcon, skb, flags);  } -static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) +static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)  { -	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { +	if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {  		control |= L2CAP_SUPER_RCV_NOT_READY; -		pi->conn_state |= L2CAP_CONN_RNR_SENT; +		chan->conn_state |= L2CAP_CONN_RNR_SENT;  	} else  		control |= L2CAP_SUPER_RCV_READY; -	control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; +	control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; -	l2cap_send_sframe(pi, control); +	l2cap_send_sframe(chan, control);  }  static inline int __l2cap_no_conn_pending(struct sock *sk) @@ -408,8 +416,9 @@ static inline int __l2cap_no_conn_pending(struct sock *sk)  	return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);  } -static void l2cap_do_start(struct sock *sk) +static void l2cap_do_start(struct l2cap_chan *chan)  { +	struct sock *sk = chan->sk;  	struct l2cap_conn *conn = l2cap_pi(sk)->conn;  	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { @@ -421,11 +430,11 @@ static void l2cap_do_start(struct sock *sk)  			req.scid = cpu_to_le16(l2cap_pi(sk)->scid);  			req.psm  = l2cap_pi(sk)->psm; -			l2cap_pi(sk)->ident = l2cap_get_ident(conn); +			chan->ident = l2cap_get_ident(conn);  			l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; -			l2cap_send_cmd(conn, l2cap_pi(sk)->ident, -					L2CAP_CONN_REQ, sizeof(req), &req); +			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, +							sizeof(req), &req);  		}  	} else {  		struct l2cap_info_req req; @@ -458,19 +467,20 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)  	}  } -void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err) +void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)  { +	struct sock *sk;  	struct l2cap_disconn_req req;  	if (!conn)  		return; -	skb_queue_purge(TX_QUEUE(sk)); +	sk = chan->sk;  	if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { -		del_timer(&l2cap_pi(sk)->retrans_timer); -		del_timer(&l2cap_pi(sk)->monitor_timer); -		del_timer(&l2cap_pi(sk)->ack_timer); +		del_timer(&chan->retrans_timer); +		del_timer(&chan->monitor_timer); +		del_timer(&chan->ack_timer);  	}  	req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid); @@ -485,17 +495,15 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)  /* ---- L2CAP connections ---- */  static void l2cap_conn_start(struct l2cap_conn *conn)  { -	struct l2cap_chan_list *l = &conn->chan_list; -	struct sock_del_list del, *tmp1, *tmp2; -	struct sock *sk; +	struct l2cap_chan *chan, *tmp;  	BT_DBG("conn %p", conn); -	INIT_LIST_HEAD(&del.list); +	read_lock(&conn->chan_lock); -	read_lock(&l->lock); +	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { +		struct sock *sk = chan->sk; -	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {  		bh_lock_sock(sk);  		if (sk->sk_type != SOCK_SEQPACKET && @@ -517,10 +525,11 @@ static void l2cap_conn_start(struct l2cap_conn *conn)  					conn->feat_mask)  					&& l2cap_pi(sk)->conf_state &  					L2CAP_CONF_STATE2_DEVICE) { -				tmp1 = kzalloc(sizeof(struct sock_del_list), -						GFP_ATOMIC); -				tmp1->sk = sk; -				list_add_tail(&tmp1->list, &del.list); +				/* __l2cap_sock_close() calls list_del(chan) +				 * so release the lock */ +				read_unlock_bh(&conn->chan_lock); +				 __l2cap_sock_close(sk, ECONNRESET); +				read_lock_bh(&conn->chan_lock);  				bh_unlock_sock(sk);  				continue;  			} @@ -528,11 +537,11 @@ static void l2cap_conn_start(struct l2cap_conn *conn)  			req.scid = cpu_to_le16(l2cap_pi(sk)->scid);  			req.psm  = l2cap_pi(sk)->psm; -			l2cap_pi(sk)->ident = l2cap_get_ident(conn); +			chan->ident = l2cap_get_ident(conn);  			l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; -			l2cap_send_cmd(conn, l2cap_pi(sk)->ident, -				L2CAP_CONN_REQ, sizeof(req), &req); +			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, +							sizeof(req), &req);  		} else if (sk->sk_state == BT_CONNECT2) {  			struct l2cap_conn_rsp rsp; @@ -557,8 +566,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn)  				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);  			} -			l2cap_send_cmd(conn, l2cap_pi(sk)->ident, -					L2CAP_CONN_RSP, sizeof(rsp), &rsp); +			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, +							sizeof(rsp), &rsp);  			if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||  					rsp.result != L2CAP_CR_SUCCESS) { @@ -568,22 +577,14 @@ static void l2cap_conn_start(struct l2cap_conn *conn)  			l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;  			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, -						l2cap_build_conf_req(sk, buf), buf); -			l2cap_pi(sk)->num_conf_req++; +						l2cap_build_conf_req(chan, buf), buf); +			chan->num_conf_req++;  		}  		bh_unlock_sock(sk);  	} -	read_unlock(&l->lock); - -	list_for_each_entry_safe(tmp1, tmp2, &del.list, list) { -		bh_lock_sock(tmp1->sk); -		__l2cap_sock_close(tmp1->sk, ECONNRESET); -		bh_unlock_sock(tmp1->sk); -		list_del(&tmp1->list); -		kfree(tmp1); -	} +	read_unlock(&conn->chan_lock);  }  /* Find socket with cid and source bdaddr. @@ -591,7 +592,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)   */  static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)  { -	struct sock *s, *sk = NULL, *sk1 = NULL; +	struct sock *sk = NULL, *sk1 = NULL;  	struct hlist_node *node;  	read_lock(&l2cap_sk_list.lock); @@ -610,18 +611,16 @@ static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)  				sk1 = sk;  		}  	} -	s = node ? sk : sk1; -	if (s) -		bh_lock_sock(s); +  	read_unlock(&l2cap_sk_list.lock); -	return s; +	return node ? sk : sk1;  }  static void l2cap_le_conn_ready(struct l2cap_conn *conn)  { -	struct l2cap_chan_list *list = &conn->chan_list; -	struct sock *parent, *uninitialized_var(sk); +	struct sock *parent, *sk; +	struct l2cap_chan *chan;  	BT_DBG(""); @@ -631,6 +630,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)  	if (!parent)  		return; +	bh_lock_sock(parent); +  	/* Check for backlog size */  	if (sk_acceptq_is_full(parent)) {  		BT_DBG("backlog full %d", parent->sk_ack_backlog); @@ -641,24 +642,33 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)  	if (!sk)  		goto clean; -	write_lock_bh(&list->lock); +	chan = l2cap_chan_alloc(sk); +	if (!chan) { +		l2cap_sock_kill(sk); +		goto clean; +	} + +	write_lock_bh(&conn->chan_lock);  	hci_conn_hold(conn->hcon);  	l2cap_sock_init(sk, parent); +  	bacpy(&bt_sk(sk)->src, conn->src);  	bacpy(&bt_sk(sk)->dst, conn->dst);  	bt_accept_enqueue(parent, sk); -	__l2cap_chan_add(conn, sk); +	__l2cap_chan_add(conn, chan); + +	l2cap_pi(sk)->chan = chan;  	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);  	sk->sk_state = BT_CONNECTED;  	parent->sk_data_ready(parent, 0); -	write_unlock_bh(&list->lock); +	write_unlock_bh(&conn->chan_lock);  clean:  	bh_unlock_sock(parent); @@ -666,17 +676,18 @@ clean:  static void l2cap_conn_ready(struct l2cap_conn *conn)  { -	struct l2cap_chan_list *l = &conn->chan_list; -	struct sock *sk; +	struct l2cap_chan *chan;  	BT_DBG("conn %p", conn);  	if (!conn->hcon->out && conn->hcon->type == LE_LINK)  		l2cap_le_conn_ready(conn); -	read_lock(&l->lock); +	read_lock(&conn->chan_lock); + +	list_for_each_entry(chan, &conn->chan_l, list) { +		struct sock *sk = chan->sk; -	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {  		bh_lock_sock(sk);  		if (conn->hcon->type == LE_LINK) { @@ -691,30 +702,31 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)  			sk->sk_state = BT_CONNECTED;  			sk->sk_state_change(sk);  		} else if (sk->sk_state == BT_CONNECT) -			l2cap_do_start(sk); +			l2cap_do_start(chan);  		bh_unlock_sock(sk);  	} -	read_unlock(&l->lock); +	read_unlock(&conn->chan_lock);  }  /* Notify sockets that we cannot guaranty reliability anymore */  static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)  { -	struct l2cap_chan_list *l = &conn->chan_list; -	struct sock *sk; +	struct l2cap_chan *chan;  	BT_DBG("conn %p", conn); -	read_lock(&l->lock); +	read_lock(&conn->chan_lock); + +	list_for_each_entry(chan, &conn->chan_l, list) { +		struct sock *sk = chan->sk; -	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {  		if (l2cap_pi(sk)->force_reliable)  			sk->sk_err = err;  	} -	read_unlock(&l->lock); +	read_unlock(&conn->chan_lock);  }  static void l2cap_info_timeout(unsigned long arg) @@ -754,7 +766,9 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)  	conn->feat_mask = 0;  	spin_lock_init(&conn->lock); -	rwlock_init(&conn->chan_list.lock); +	rwlock_init(&conn->chan_lock); + +	INIT_LIST_HEAD(&conn->chan_l);  	if (hcon->type != LE_LINK)  		setup_timer(&conn->info_timer, l2cap_info_timeout, @@ -768,6 +782,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)  static void l2cap_conn_del(struct hci_conn *hcon, int err)  {  	struct l2cap_conn *conn = hcon->l2cap_data; +	struct l2cap_chan *chan, *l;  	struct sock *sk;  	if (!conn) @@ -778,9 +793,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)  	kfree_skb(conn->rx_skb);  	/* Kill channels */ -	while ((sk = conn->chan_list.head)) { +	list_for_each_entry_safe(chan, l, &conn->chan_l, list) { +		sk = chan->sk;  		bh_lock_sock(sk); -		l2cap_chan_del(sk, err); +		l2cap_chan_del(chan, err);  		bh_unlock_sock(sk);  		l2cap_sock_kill(sk);  	} @@ -792,12 +808,11 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)  	kfree(conn);  } -static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk) +static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)  { -	struct l2cap_chan_list *l = &conn->chan_list; -	write_lock_bh(&l->lock); -	__l2cap_chan_add(conn, sk); -	write_unlock_bh(&l->lock); +	write_lock_bh(&conn->chan_lock); +	__l2cap_chan_add(conn, chan); +	write_unlock_bh(&conn->chan_lock);  }  /* ---- Socket interface ---- */ @@ -837,6 +852,7 @@ int l2cap_do_connect(struct sock *sk)  	bdaddr_t *src = &bt_sk(sk)->src;  	bdaddr_t *dst = &bt_sk(sk)->dst;  	struct l2cap_conn *conn; +	struct l2cap_chan *chan;  	struct hci_conn *hcon;  	struct hci_dev *hdev;  	__u8 auth_type; @@ -872,10 +888,19 @@ int l2cap_do_connect(struct sock *sk)  		goto done;  	} +	chan = l2cap_chan_alloc(sk); +	if (!chan) { +		hci_conn_put(hcon); +		err = -ENOMEM; +		goto done; +	} +  	/* Update source addr of the socket */  	bacpy(src, conn->src); -	l2cap_chan_add(conn, sk); +	l2cap_chan_add(conn, chan); + +	l2cap_pi(sk)->chan = chan;  	sk->sk_state = BT_CONNECT;  	l2cap_sock_set_timer(sk, sk->sk_sndtimeo); @@ -887,7 +912,7 @@ int l2cap_do_connect(struct sock *sk)  			if (l2cap_check_security(sk))  				sk->sk_state = BT_CONNECTED;  		} else -			l2cap_do_start(sk); +			l2cap_do_start(chan);  	}  	err = 0; @@ -905,7 +930,7 @@ int __l2cap_wait_ack(struct sock *sk)  	int timeo = HZ/5;  	add_wait_queue(sk_sleep(sk), &wait); -	while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) { +	while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {  		set_current_state(TASK_INTERRUPTIBLE);  		if (!timeo) @@ -931,57 +956,59 @@ int __l2cap_wait_ack(struct sock *sk)  static void l2cap_monitor_timeout(unsigned long arg)  { -	struct sock *sk = (void *) arg; +	struct l2cap_chan *chan = (void *) arg; +	struct sock *sk = chan->sk; -	BT_DBG("sk %p", sk); +	BT_DBG("chan %p", chan);  	bh_lock_sock(sk); -	if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) { -		l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED); +	if (chan->retry_count >= chan->remote_max_tx) { +		l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);  		bh_unlock_sock(sk);  		return;  	} -	l2cap_pi(sk)->retry_count++; +	chan->retry_count++;  	__mod_monitor_timer(); -	l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); +	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);  	bh_unlock_sock(sk);  }  static void l2cap_retrans_timeout(unsigned long arg)  { -	struct sock *sk = (void *) arg; +	struct l2cap_chan *chan = (void *) arg; +	struct sock *sk = chan->sk; -	BT_DBG("sk %p", sk); +	BT_DBG("chan %p", chan);  	bh_lock_sock(sk); -	l2cap_pi(sk)->retry_count = 1; +	chan->retry_count = 1;  	__mod_monitor_timer(); -	l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; +	chan->conn_state |= L2CAP_CONN_WAIT_F; -	l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL); +	l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);  	bh_unlock_sock(sk);  } -static void l2cap_drop_acked_frames(struct sock *sk) +static void l2cap_drop_acked_frames(struct l2cap_chan *chan)  {  	struct sk_buff *skb; -	while ((skb = skb_peek(TX_QUEUE(sk))) && -			l2cap_pi(sk)->unacked_frames) { -		if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq) +	while ((skb = skb_peek(&chan->tx_q)) && +			chan->unacked_frames) { +		if (bt_cb(skb)->tx_seq == chan->expected_ack_seq)  			break; -		skb = skb_dequeue(TX_QUEUE(sk)); +		skb = skb_dequeue(&chan->tx_q);  		kfree_skb(skb); -		l2cap_pi(sk)->unacked_frames--; +		chan->unacked_frames--;  	} -	if (!l2cap_pi(sk)->unacked_frames) -		del_timer(&l2cap_pi(sk)->retrans_timer); +	if (!chan->unacked_frames) +		del_timer(&chan->retrans_timer);  }  void l2cap_do_send(struct sock *sk, struct sk_buff *skb) @@ -1000,15 +1027,16 @@ void l2cap_do_send(struct sock *sk, struct sk_buff *skb)  	hci_send_acl(hcon, skb, flags);  } -void l2cap_streaming_send(struct sock *sk) +void l2cap_streaming_send(struct l2cap_chan *chan)  { +	struct sock *sk = chan->sk;  	struct sk_buff *skb;  	struct l2cap_pinfo *pi = l2cap_pi(sk);  	u16 control, fcs; -	while ((skb = skb_dequeue(TX_QUEUE(sk)))) { +	while ((skb = skb_dequeue(&chan->tx_q))) {  		control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE); -		control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; +		control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;  		put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);  		if (pi->fcs == L2CAP_FCS_CRC16) { @@ -1018,17 +1046,18 @@ void l2cap_streaming_send(struct sock *sk)  		l2cap_do_send(sk, skb); -		pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; +		chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;  	}  } -static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq) +static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)  { +	struct sock *sk = chan->sk;  	struct l2cap_pinfo *pi = l2cap_pi(sk);  	struct sk_buff *skb, *tx_skb;  	u16 control, fcs; -	skb = skb_peek(TX_QUEUE(sk)); +	skb = skb_peek(&chan->tx_q);  	if (!skb)  		return; @@ -1036,14 +1065,14 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)  		if (bt_cb(skb)->tx_seq == tx_seq)  			break; -		if (skb_queue_is_last(TX_QUEUE(sk), skb)) +		if (skb_queue_is_last(&chan->tx_q, skb))  			return; -	} while ((skb = skb_queue_next(TX_QUEUE(sk), skb))); +	} while ((skb = skb_queue_next(&chan->tx_q, skb))); -	if (pi->remote_max_tx && -			bt_cb(skb)->retries == pi->remote_max_tx) { -		l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED); +	if (chan->remote_max_tx && +			bt_cb(skb)->retries == chan->remote_max_tx) { +		l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);  		return;  	} @@ -1051,12 +1080,12 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)  	bt_cb(skb)->retries++;  	control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); -	if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { +	if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {  		control |= L2CAP_CTRL_FINAL; -		pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; +		chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;  	} -	control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) +	control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)  			| (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);  	put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); @@ -1069,9 +1098,10 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)  	l2cap_do_send(sk, tx_skb);  } -int l2cap_ertm_send(struct sock *sk) +int l2cap_ertm_send(struct l2cap_chan *chan)  {  	struct sk_buff *skb, *tx_skb; +	struct sock *sk = chan->sk;  	struct l2cap_pinfo *pi = l2cap_pi(sk);  	u16 control, fcs;  	int nsent = 0; @@ -1079,11 +1109,11 @@ int l2cap_ertm_send(struct sock *sk)  	if (sk->sk_state != BT_CONNECTED)  		return -ENOTCONN; -	while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) { +	while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) { -		if (pi->remote_max_tx && -				bt_cb(skb)->retries == pi->remote_max_tx) { -			l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED); +		if (chan->remote_max_tx && +				bt_cb(skb)->retries == chan->remote_max_tx) { +			l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);  			break;  		} @@ -1094,12 +1124,12 @@ int l2cap_ertm_send(struct sock *sk)  		control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);  		control &= L2CAP_CTRL_SAR; -		if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { +		if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {  			control |= L2CAP_CTRL_FINAL; -			pi->conn_state &= ~L2CAP_CONN_SEND_FBIT; +			chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;  		} -		control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) -				| (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT); +		control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT) +				| (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);  		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); @@ -1112,18 +1142,18 @@ int l2cap_ertm_send(struct sock *sk)  		__mod_retrans_timer(); -		bt_cb(skb)->tx_seq = pi->next_tx_seq; -		pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; +		bt_cb(skb)->tx_seq = chan->next_tx_seq; +		chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;  		if (bt_cb(skb)->retries == 1) -			pi->unacked_frames++; +			chan->unacked_frames++; -		pi->frames_sent++; +		chan->frames_sent++; -		if (skb_queue_is_last(TX_QUEUE(sk), skb)) -			sk->sk_send_head = NULL; +		if (skb_queue_is_last(&chan->tx_q, skb)) +			chan->tx_send_head = NULL;  		else -			sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb); +			chan->tx_send_head = skb_queue_next(&chan->tx_q, skb);  		nsent++;  	} @@ -1131,41 +1161,39 @@ int l2cap_ertm_send(struct sock *sk)  	return nsent;  } -static int l2cap_retransmit_frames(struct sock *sk) +static int l2cap_retransmit_frames(struct l2cap_chan *chan)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk);  	int ret; -	if (!skb_queue_empty(TX_QUEUE(sk))) -		sk->sk_send_head = TX_QUEUE(sk)->next; +	if (!skb_queue_empty(&chan->tx_q)) +		chan->tx_send_head = chan->tx_q.next; -	pi->next_tx_seq = pi->expected_ack_seq; -	ret = l2cap_ertm_send(sk); +	chan->next_tx_seq = chan->expected_ack_seq; +	ret = l2cap_ertm_send(chan);  	return ret;  } -static void l2cap_send_ack(struct l2cap_pinfo *pi) +static void l2cap_send_ack(struct l2cap_chan *chan)  { -	struct sock *sk = (struct sock *)pi;  	u16 control = 0; -	control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; +	control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; -	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { +	if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {  		control |= L2CAP_SUPER_RCV_NOT_READY; -		pi->conn_state |= L2CAP_CONN_RNR_SENT; -		l2cap_send_sframe(pi, control); +		chan->conn_state |= L2CAP_CONN_RNR_SENT; +		l2cap_send_sframe(chan, control);  		return;  	} -	if (l2cap_ertm_send(sk) > 0) +	if (l2cap_ertm_send(chan) > 0)  		return;  	control |= L2CAP_SUPER_RCV_READY; -	l2cap_send_sframe(pi, control); +	l2cap_send_sframe(chan, control);  } -static void l2cap_send_srejtail(struct sock *sk) +static void l2cap_send_srejtail(struct l2cap_chan *chan)  {  	struct srej_list *tail;  	u16 control; @@ -1173,10 +1201,10 @@ static void l2cap_send_srejtail(struct sock *sk)  	control = L2CAP_SUPER_SELECT_REJECT;  	control |= L2CAP_CTRL_FINAL; -	tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list); +	tail = list_entry((&chan->srej_l)->prev, struct srej_list, list);  	control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; -	l2cap_send_sframe(l2cap_pi(sk), control); +	l2cap_send_sframe(chan, control);  }  static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb) @@ -1313,9 +1341,9 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz  	return skb;  } -int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len) +int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk); +	struct sock *sk = chan->sk;  	struct sk_buff *skb;  	struct sk_buff_head sar_queue;  	u16 control; @@ -1323,20 +1351,20 @@ int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)  	skb_queue_head_init(&sar_queue);  	control = L2CAP_SDU_START; -	skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len); +	skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);  	if (IS_ERR(skb))  		return PTR_ERR(skb);  	__skb_queue_tail(&sar_queue, skb); -	len -= pi->remote_mps; -	size += pi->remote_mps; +	len -= chan->remote_mps; +	size += chan->remote_mps;  	while (len > 0) {  		size_t buflen; -		if (len > pi->remote_mps) { +		if (len > chan->remote_mps) {  			control = L2CAP_SDU_CONTINUE; -			buflen = pi->remote_mps; +			buflen = chan->remote_mps;  		} else {  			control = L2CAP_SDU_END;  			buflen = len; @@ -1352,9 +1380,9 @@ int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)  		len -= buflen;  		size += buflen;  	} -	skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk)); -	if (sk->sk_send_head == NULL) -		sk->sk_send_head = sar_queue.next; +	skb_queue_splice_tail(&sar_queue, &chan->tx_q); +	if (chan->tx_send_head == NULL) +		chan->tx_send_head = sar_queue.next;  	return size;  } @@ -1385,14 +1413,14 @@ static void l2cap_chan_ready(struct sock *sk)  /* Copy frame to all raw sockets on that connection */  static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)  { -	struct l2cap_chan_list *l = &conn->chan_list;  	struct sk_buff *nskb; -	struct sock *sk; +	struct l2cap_chan *chan;  	BT_DBG("conn %p", conn); -	read_lock(&l->lock); -	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { +	read_lock(&conn->chan_lock); +	list_for_each_entry(chan, &conn->chan_l, list) { +		struct sock *sk = chan->sk;  		if (sk->sk_type != SOCK_RAW)  			continue; @@ -1406,7 +1434,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)  		if (sock_queue_rcv_skb(sk, nskb))  			kfree_skb(nskb);  	} -	read_unlock(&l->lock); +	read_unlock(&conn->chan_lock);  }  /* ---- L2CAP signalling commands ---- */ @@ -1538,32 +1566,35 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)  static void l2cap_ack_timeout(unsigned long arg)  { -	struct sock *sk = (void *) arg; +	struct l2cap_chan *chan = (void *) arg; -	bh_lock_sock(sk); -	l2cap_send_ack(l2cap_pi(sk)); -	bh_unlock_sock(sk); +	bh_lock_sock(chan->sk); +	l2cap_send_ack(chan); +	bh_unlock_sock(chan->sk);  } -static inline void l2cap_ertm_init(struct sock *sk) +static inline void l2cap_ertm_init(struct l2cap_chan *chan)  { -	l2cap_pi(sk)->expected_ack_seq = 0; -	l2cap_pi(sk)->unacked_frames = 0; -	l2cap_pi(sk)->buffer_seq = 0; -	l2cap_pi(sk)->num_acked = 0; -	l2cap_pi(sk)->frames_sent = 0; +	struct sock *sk = chan->sk; + +	chan->expected_ack_seq = 0; +	chan->unacked_frames = 0; +	chan->buffer_seq = 0; +	chan->num_acked = 0; +	chan->frames_sent = 0; + +	setup_timer(&chan->retrans_timer, l2cap_retrans_timeout, +							(unsigned long) chan); +	setup_timer(&chan->monitor_timer, l2cap_monitor_timeout, +							(unsigned long) chan); +	setup_timer(&chan->ack_timer, l2cap_ack_timeout, (unsigned long) chan); -	setup_timer(&l2cap_pi(sk)->retrans_timer, -			l2cap_retrans_timeout, (unsigned long) sk); -	setup_timer(&l2cap_pi(sk)->monitor_timer, -			l2cap_monitor_timeout, (unsigned long) sk); -	setup_timer(&l2cap_pi(sk)->ack_timer, -			l2cap_ack_timeout, (unsigned long) sk); +	skb_queue_head_init(&chan->srej_q); +	skb_queue_head_init(&chan->busy_q); -	__skb_queue_head_init(SREJ_QUEUE(sk)); -	__skb_queue_head_init(BUSY_QUEUE(sk)); +	INIT_LIST_HEAD(&chan->srej_l); -	INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work); +	INIT_WORK(&chan->busy_work, l2cap_busy_work);  	sk->sk_backlog_rcv = l2cap_ertm_data_rcv;  } @@ -1581,16 +1612,16 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)  	}  } -int l2cap_build_conf_req(struct sock *sk, void *data) +static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk); +	struct l2cap_pinfo *pi = l2cap_pi(chan->sk);  	struct l2cap_conf_req *req = data;  	struct l2cap_conf_rfc rfc = { .mode = pi->mode };  	void *ptr = req->data; -	BT_DBG("sk %p", sk); +	BT_DBG("chan %p", chan); -	if (pi->num_conf_req || pi->num_conf_rsp) +	if (chan->num_conf_req || chan->num_conf_rsp)  		goto done;  	switch (pi->mode) { @@ -1679,20 +1710,20 @@ done:  	return ptr - data;  } -static int l2cap_parse_conf_req(struct sock *sk, void *data) +static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk); +	struct l2cap_pinfo *pi = l2cap_pi(chan->sk);  	struct l2cap_conf_rsp *rsp = data;  	void *ptr = rsp->data; -	void *req = pi->conf_req; -	int len = pi->conf_len; +	void *req = chan->conf_req; +	int len = chan->conf_len;  	int type, hint, olen;  	unsigned long val;  	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };  	u16 mtu = L2CAP_DEFAULT_MTU;  	u16 result = L2CAP_CONF_SUCCESS; -	BT_DBG("sk %p", sk); +	BT_DBG("chan %p", chan);  	while (len >= L2CAP_CONF_OPT_SIZE) {  		len -= l2cap_get_conf_opt(&req, &type, &olen, &val); @@ -1733,7 +1764,7 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)  		}  	} -	if (pi->num_conf_rsp || pi->num_conf_req > 1) +	if (chan->num_conf_rsp || chan->num_conf_req > 1)  		goto done;  	switch (pi->mode) { @@ -1756,7 +1787,7 @@ done:  		result = L2CAP_CONF_UNACCEPT;  		rfc.mode = pi->mode; -		if (pi->num_conf_rsp == 1) +		if (chan->num_conf_rsp == 1)  			return -ECONNREFUSED;  		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, @@ -1783,13 +1814,13 @@ done:  			break;  		case L2CAP_MODE_ERTM: -			pi->remote_tx_win = rfc.txwin_size; -			pi->remote_max_tx = rfc.max_transmit; +			chan->remote_tx_win = rfc.txwin_size; +			chan->remote_max_tx = rfc.max_transmit;  			if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)  				rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); -			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); +			chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);  			rfc.retrans_timeout =  				le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO); @@ -1807,7 +1838,7 @@ done:  			if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)  				rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10); -			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size); +			chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);  			pi->conf_state |= L2CAP_CONF_MODE_DONE; @@ -1916,6 +1947,31 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla  	return ptr - data;  } +void __l2cap_connect_rsp_defer(struct sock *sk) +{ +	struct l2cap_conn_rsp rsp; +	struct l2cap_conn *conn = l2cap_pi(sk)->conn; +	struct l2cap_chan *chan = l2cap_pi(sk)->chan; +	u8 buf[128]; + +	sk->sk_state = BT_CONFIG; + +	rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid); +	rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid); +	rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); +	rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); +	l2cap_send_cmd(conn, chan->ident, +				L2CAP_CONN_RSP, sizeof(rsp), &rsp); + +	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) +		return; + +	l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; +	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, +			l2cap_build_conf_req(chan, buf), buf); +	chan->num_conf_req++; +} +  static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)  {  	struct l2cap_pinfo *pi = l2cap_pi(sk); @@ -1973,9 +2029,9 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd  static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)  { -	struct l2cap_chan_list *list = &conn->chan_list;  	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;  	struct l2cap_conn_rsp rsp; +	struct l2cap_chan *chan = NULL;  	struct sock *parent, *sk = NULL;  	int result, status = L2CAP_CS_NO_INFO; @@ -2013,11 +2069,17 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd  	if (!sk)  		goto response; -	write_lock_bh(&list->lock); +	chan = l2cap_chan_alloc(sk); +	if (!chan) { +		l2cap_sock_kill(sk); +		goto response; +	} + +	write_lock_bh(&conn->chan_lock);  	/* Check if we already have channel with that dcid */ -	if (__l2cap_get_chan_by_dcid(list, scid)) { -		write_unlock_bh(&list->lock); +	if (__l2cap_get_chan_by_dcid(conn, scid)) { +		write_unlock_bh(&conn->chan_lock);  		sock_set_flag(sk, SOCK_ZAPPED);  		l2cap_sock_kill(sk);  		goto response; @@ -2033,12 +2095,15 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd  	bt_accept_enqueue(parent, sk); -	__l2cap_chan_add(conn, sk); +	__l2cap_chan_add(conn, chan); + +	l2cap_pi(sk)->chan = chan; +  	dcid = l2cap_pi(sk)->scid;  	l2cap_sock_set_timer(sk, sk->sk_sndtimeo); -	l2cap_pi(sk)->ident = cmd->ident; +	chan->ident = cmd->ident;  	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {  		if (l2cap_check_security(sk)) { @@ -2063,7 +2128,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd  		status = L2CAP_CS_NO_INFO;  	} -	write_unlock_bh(&list->lock); +	write_unlock_bh(&conn->chan_lock);  response:  	bh_unlock_sock(parent); @@ -2089,13 +2154,13 @@ sendresp:  					L2CAP_INFO_REQ, sizeof(info), &info);  	} -	if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) && +	if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&  				result == L2CAP_CR_SUCCESS) {  		u8 buf[128];  		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;  		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, -					l2cap_build_conf_req(sk, buf), buf); -		l2cap_pi(sk)->num_conf_req++; +					l2cap_build_conf_req(chan, buf), buf); +		chan->num_conf_req++;  	}  	return 0; @@ -2105,6 +2170,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd  {  	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;  	u16 scid, dcid, result, status; +	struct l2cap_chan *chan;  	struct sock *sk;  	u8 req[128]; @@ -2116,19 +2182,21 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd  	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);  	if (scid) { -		sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); -		if (!sk) +		chan = l2cap_get_chan_by_scid(conn, scid); +		if (!chan)  			return -EFAULT;  	} else { -		sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident); -		if (!sk) +		chan = l2cap_get_chan_by_ident(conn, cmd->ident); +		if (!chan)  			return -EFAULT;  	} +	sk = chan->sk; +  	switch (result) {  	case L2CAP_CR_SUCCESS:  		sk->sk_state = BT_CONFIG; -		l2cap_pi(sk)->ident = 0; +		chan->ident = 0;  		l2cap_pi(sk)->dcid = dcid;  		l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND; @@ -2138,8 +2206,8 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd  		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;  		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, -					l2cap_build_conf_req(sk, req), req); -		l2cap_pi(sk)->num_conf_req++; +					l2cap_build_conf_req(chan, req), req); +		chan->num_conf_req++;  		break;  	case L2CAP_CR_PEND: @@ -2155,7 +2223,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd  			break;  		} -		l2cap_chan_del(sk, ECONNREFUSED); +		l2cap_chan_del(chan, ECONNREFUSED);  		break;  	} @@ -2179,6 +2247,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr  	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;  	u16 dcid, flags;  	u8 rsp[64]; +	struct l2cap_chan *chan;  	struct sock *sk;  	int len; @@ -2187,10 +2256,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr  	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); -	sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid); -	if (!sk) +	chan = l2cap_get_chan_by_scid(conn, dcid); +	if (!chan)  		return -ENOENT; +	sk = chan->sk; +  	if (sk->sk_state != BT_CONFIG) {  		struct l2cap_cmd_rej rej; @@ -2202,7 +2273,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr  	/* Reject if config buffer is too small. */  	len = cmd_len - sizeof(*req); -	if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) { +	if (chan->conf_len + len > sizeof(chan->conf_req)) {  		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,  				l2cap_build_conf_rsp(sk, rsp,  					L2CAP_CONF_REJECT, flags), rsp); @@ -2210,8 +2281,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr  	}  	/* Store config. */ -	memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len); -	l2cap_pi(sk)->conf_len += len; +	memcpy(chan->conf_req + chan->conf_len, req->data, len); +	chan->conf_len += len;  	if (flags & 0x0001) {  		/* Incomplete config. Send empty response. */ @@ -2222,17 +2293,17 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr  	}  	/* Complete config. */ -	len = l2cap_parse_conf_req(sk, rsp); +	len = l2cap_parse_conf_req(chan, rsp);  	if (len < 0) { -		l2cap_send_disconn_req(conn, sk, ECONNRESET); +		l2cap_send_disconn_req(conn, chan, ECONNRESET);  		goto unlock;  	}  	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp); -	l2cap_pi(sk)->num_conf_rsp++; +	chan->num_conf_rsp++;  	/* Reset config buffer. */ -	l2cap_pi(sk)->conf_len = 0; +	chan->conf_len = 0;  	if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))  		goto unlock; @@ -2242,11 +2313,11 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr  		sk->sk_state = BT_CONNECTED; -		l2cap_pi(sk)->next_tx_seq = 0; -		l2cap_pi(sk)->expected_tx_seq = 0; -		__skb_queue_head_init(TX_QUEUE(sk)); +		chan->next_tx_seq = 0; +		chan->expected_tx_seq = 0; +		skb_queue_head_init(&chan->tx_q);  		if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) -			l2cap_ertm_init(sk); +			l2cap_ertm_init(chan);  		l2cap_chan_ready(sk);  		goto unlock; @@ -2256,8 +2327,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr  		u8 buf[64];  		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;  		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, -					l2cap_build_conf_req(sk, buf), buf); -		l2cap_pi(sk)->num_conf_req++; +					l2cap_build_conf_req(chan, buf), buf); +		chan->num_conf_req++;  	}  unlock: @@ -2269,6 +2340,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr  {  	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;  	u16 scid, flags, result; +	struct l2cap_chan *chan;  	struct sock *sk;  	int len = cmd->len - sizeof(*rsp); @@ -2279,21 +2351,23 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr  	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",  			scid, flags, result); -	sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); -	if (!sk) +	chan = l2cap_get_chan_by_scid(conn, scid); +	if (!chan)  		return 0; +	sk = chan->sk; +  	switch (result) {  	case L2CAP_CONF_SUCCESS:  		l2cap_conf_rfc_get(sk, rsp->data, len);  		break;  	case L2CAP_CONF_UNACCEPT: -		if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { +		if (chan->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {  			char req[64];  			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { -				l2cap_send_disconn_req(conn, sk, ECONNRESET); +				l2cap_send_disconn_req(conn, chan, ECONNRESET);  				goto done;  			} @@ -2302,13 +2376,13 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr  			len = l2cap_parse_conf_rsp(sk, rsp->data,  							len, req, &result);  			if (len < 0) { -				l2cap_send_disconn_req(conn, sk, ECONNRESET); +				l2cap_send_disconn_req(conn, chan, ECONNRESET);  				goto done;  			}  			l2cap_send_cmd(conn, l2cap_get_ident(conn),  						L2CAP_CONF_REQ, len, req); -			l2cap_pi(sk)->num_conf_req++; +			chan->num_conf_req++;  			if (result != L2CAP_CONF_SUCCESS)  				goto done;  			break; @@ -2317,7 +2391,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr  	default:  		sk->sk_err = ECONNRESET;  		l2cap_sock_set_timer(sk, HZ * 5); -		l2cap_send_disconn_req(conn, sk, ECONNRESET); +		l2cap_send_disconn_req(conn, chan, ECONNRESET);  		goto done;  	} @@ -2330,11 +2404,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr  		set_default_fcs(l2cap_pi(sk));  		sk->sk_state = BT_CONNECTED; -		l2cap_pi(sk)->next_tx_seq = 0; -		l2cap_pi(sk)->expected_tx_seq = 0; -		__skb_queue_head_init(TX_QUEUE(sk)); +		chan->next_tx_seq = 0; +		chan->expected_tx_seq = 0; +		skb_queue_head_init(&chan->tx_q);  		if (l2cap_pi(sk)->mode ==  L2CAP_MODE_ERTM) -			l2cap_ertm_init(sk); +			l2cap_ertm_init(chan);  		l2cap_chan_ready(sk);  	} @@ -2349,6 +2423,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd  	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;  	struct l2cap_disconn_rsp rsp;  	u16 dcid, scid; +	struct l2cap_chan *chan;  	struct sock *sk;  	scid = __le16_to_cpu(req->scid); @@ -2356,10 +2431,12 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd  	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); -	sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid); -	if (!sk) +	chan = l2cap_get_chan_by_scid(conn, dcid); +	if (!chan)  		return 0; +	sk = chan->sk; +  	rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);  	rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);  	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); @@ -2375,7 +2452,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd  		return 0;  	} -	l2cap_chan_del(sk, ECONNRESET); +	l2cap_chan_del(chan, ECONNRESET);  	bh_unlock_sock(sk);  	l2cap_sock_kill(sk); @@ -2386,6 +2463,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd  {  	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;  	u16 dcid, scid; +	struct l2cap_chan *chan;  	struct sock *sk;  	scid = __le16_to_cpu(rsp->scid); @@ -2393,10 +2471,12 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd  	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); -	sk = l2cap_get_chan_by_scid(&conn->chan_list, scid); -	if (!sk) +	chan = l2cap_get_chan_by_scid(conn, scid); +	if (!chan)  		return 0; +	sk = chan->sk; +  	/* don't delete l2cap channel if sk is owned by user */  	if (sock_owned_by_user(sk)) {  		sk->sk_state = BT_DISCONN; @@ -2406,7 +2486,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd  		return 0;  	} -	l2cap_chan_del(sk, 0); +	l2cap_chan_del(chan, 0);  	bh_unlock_sock(sk);  	l2cap_sock_kill(sk); @@ -2709,49 +2789,47 @@ static int l2cap_check_fcs(struct l2cap_pinfo *pi,  struct sk_buff *skb)  	return 0;  } -static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk) +static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk);  	u16 control = 0; -	pi->frames_sent = 0; +	chan->frames_sent = 0; -	control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; +	control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; -	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { +	if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {  		control |= L2CAP_SUPER_RCV_NOT_READY; -		l2cap_send_sframe(pi, control); -		pi->conn_state |= L2CAP_CONN_RNR_SENT; +		l2cap_send_sframe(chan, control); +		chan->conn_state |= L2CAP_CONN_RNR_SENT;  	} -	if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY) -		l2cap_retransmit_frames(sk); +	if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY) +		l2cap_retransmit_frames(chan); -	l2cap_ertm_send(sk); +	l2cap_ertm_send(chan); -	if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) && -			pi->frames_sent == 0) { +	if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) && +			chan->frames_sent == 0) {  		control |= L2CAP_SUPER_RCV_READY; -		l2cap_send_sframe(pi, control); +		l2cap_send_sframe(chan, control);  	}  } -static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar) +static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, u8 tx_seq, u8 sar)  {  	struct sk_buff *next_skb; -	struct l2cap_pinfo *pi = l2cap_pi(sk);  	int tx_seq_offset, next_tx_seq_offset;  	bt_cb(skb)->tx_seq = tx_seq;  	bt_cb(skb)->sar = sar; -	next_skb = skb_peek(SREJ_QUEUE(sk)); +	next_skb = skb_peek(&chan->srej_q);  	if (!next_skb) { -		__skb_queue_tail(SREJ_QUEUE(sk), skb); +		__skb_queue_tail(&chan->srej_q, skb);  		return 0;  	} -	tx_seq_offset = (tx_seq - pi->buffer_seq) % 64; +	tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;  	if (tx_seq_offset < 0)  		tx_seq_offset += 64; @@ -2760,53 +2838,53 @@ static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_s  			return -EINVAL;  		next_tx_seq_offset = (bt_cb(next_skb)->tx_seq - -						pi->buffer_seq) % 64; +						chan->buffer_seq) % 64;  		if (next_tx_seq_offset < 0)  			next_tx_seq_offset += 64;  		if (next_tx_seq_offset > tx_seq_offset) { -			__skb_queue_before(SREJ_QUEUE(sk), next_skb, skb); +			__skb_queue_before(&chan->srej_q, next_skb, skb);  			return 0;  		} -		if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb)) +		if (skb_queue_is_last(&chan->srej_q, next_skb))  			break; -	} while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb))); +	} while ((next_skb = skb_queue_next(&chan->srej_q, next_skb))); -	__skb_queue_tail(SREJ_QUEUE(sk), skb); +	__skb_queue_tail(&chan->srej_q, skb);  	return 0;  } -static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) +static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk); +	struct l2cap_pinfo *pi = l2cap_pi(chan->sk);  	struct sk_buff *_skb;  	int err;  	switch (control & L2CAP_CTRL_SAR) {  	case L2CAP_SDU_UNSEGMENTED: -		if (pi->conn_state & L2CAP_CONN_SAR_SDU) +		if (chan->conn_state & L2CAP_CONN_SAR_SDU)  			goto drop; -		err = sock_queue_rcv_skb(sk, skb); +		err = sock_queue_rcv_skb(chan->sk, skb);  		if (!err)  			return err;  		break;  	case L2CAP_SDU_START: -		if (pi->conn_state & L2CAP_CONN_SAR_SDU) +		if (chan->conn_state & L2CAP_CONN_SAR_SDU)  			goto drop; -		pi->sdu_len = get_unaligned_le16(skb->data); +		chan->sdu_len = get_unaligned_le16(skb->data); -		if (pi->sdu_len > pi->imtu) +		if (chan->sdu_len > pi->imtu)  			goto disconnect; -		pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); -		if (!pi->sdu) +		chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC); +		if (!chan->sdu)  			return -ENOMEM;  		/* pull sdu_len bytes only after alloc, because of Local Busy @@ -2814,63 +2892,63 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c  		 * only once, i.e., when alloc does not fail */  		skb_pull(skb, 2); -		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); +		memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); -		pi->conn_state |= L2CAP_CONN_SAR_SDU; -		pi->partial_sdu_len = skb->len; +		chan->conn_state |= L2CAP_CONN_SAR_SDU; +		chan->partial_sdu_len = skb->len;  		break;  	case L2CAP_SDU_CONTINUE: -		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) +		if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))  			goto disconnect; -		if (!pi->sdu) +		if (!chan->sdu)  			goto disconnect; -		pi->partial_sdu_len += skb->len; -		if (pi->partial_sdu_len > pi->sdu_len) +		chan->partial_sdu_len += skb->len; +		if (chan->partial_sdu_len > chan->sdu_len)  			goto drop; -		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); +		memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);  		break;  	case L2CAP_SDU_END: -		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) +		if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))  			goto disconnect; -		if (!pi->sdu) +		if (!chan->sdu)  			goto disconnect; -		if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) { -			pi->partial_sdu_len += skb->len; +		if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) { +			chan->partial_sdu_len += skb->len; -			if (pi->partial_sdu_len > pi->imtu) +			if (chan->partial_sdu_len > pi->imtu)  				goto drop; -			if (pi->partial_sdu_len != pi->sdu_len) +			if (chan->partial_sdu_len != chan->sdu_len)  				goto drop; -			memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); +			memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);  		} -		_skb = skb_clone(pi->sdu, GFP_ATOMIC); +		_skb = skb_clone(chan->sdu, GFP_ATOMIC);  		if (!_skb) { -			pi->conn_state |= L2CAP_CONN_SAR_RETRY; +			chan->conn_state |= L2CAP_CONN_SAR_RETRY;  			return -ENOMEM;  		} -		err = sock_queue_rcv_skb(sk, _skb); +		err = sock_queue_rcv_skb(chan->sk, _skb);  		if (err < 0) {  			kfree_skb(_skb); -			pi->conn_state |= L2CAP_CONN_SAR_RETRY; +			chan->conn_state |= L2CAP_CONN_SAR_RETRY;  			return err;  		} -		pi->conn_state &= ~L2CAP_CONN_SAR_RETRY; -		pi->conn_state &= ~L2CAP_CONN_SAR_SDU; +		chan->conn_state &= ~L2CAP_CONN_SAR_RETRY; +		chan->conn_state &= ~L2CAP_CONN_SAR_SDU; -		kfree_skb(pi->sdu); +		kfree_skb(chan->sdu);  		break;  	} @@ -2878,51 +2956,50 @@ static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 c  	return 0;  drop: -	kfree_skb(pi->sdu); -	pi->sdu = NULL; +	kfree_skb(chan->sdu); +	chan->sdu = NULL;  disconnect: -	l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); +	l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);  	kfree_skb(skb);  	return 0;  } -static int l2cap_try_push_rx_skb(struct sock *sk) +static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk);  	struct sk_buff *skb;  	u16 control;  	int err; -	while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) { +	while ((skb = skb_dequeue(&chan->busy_q))) {  		control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; -		err = l2cap_ertm_reassembly_sdu(sk, skb, control); +		err = l2cap_ertm_reassembly_sdu(chan, skb, control);  		if (err < 0) { -			skb_queue_head(BUSY_QUEUE(sk), skb); +			skb_queue_head(&chan->busy_q, skb);  			return -EBUSY;  		} -		pi->buffer_seq = (pi->buffer_seq + 1) % 64; +		chan->buffer_seq = (chan->buffer_seq + 1) % 64;  	} -	if (!(pi->conn_state & L2CAP_CONN_RNR_SENT)) +	if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))  		goto done; -	control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; +	control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;  	control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL; -	l2cap_send_sframe(pi, control); -	l2cap_pi(sk)->retry_count = 1; +	l2cap_send_sframe(chan, control); +	chan->retry_count = 1; -	del_timer(&pi->retrans_timer); +	del_timer(&chan->retrans_timer);  	__mod_monitor_timer(); -	l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F; +	chan->conn_state |= L2CAP_CONN_WAIT_F;  done: -	pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY; -	pi->conn_state &= ~L2CAP_CONN_RNR_SENT; +	chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY; +	chan->conn_state &= ~L2CAP_CONN_RNR_SENT; -	BT_DBG("sk %p, Exit local busy", sk); +	BT_DBG("chan %p, Exit local busy", chan);  	return 0;  } @@ -2930,21 +3007,21 @@ done:  static void l2cap_busy_work(struct work_struct *work)  {  	DECLARE_WAITQUEUE(wait, current); -	struct l2cap_pinfo *pi = -		container_of(work, struct l2cap_pinfo, busy_work); -	struct sock *sk = (struct sock *)pi; +	struct l2cap_chan *chan = +		container_of(work, struct l2cap_chan, busy_work); +	struct sock *sk = chan->sk;  	int n_tries = 0, timeo = HZ/5, err;  	struct sk_buff *skb;  	lock_sock(sk);  	add_wait_queue(sk_sleep(sk), &wait); -	while ((skb = skb_peek(BUSY_QUEUE(sk)))) { +	while ((skb = skb_peek(&chan->busy_q))) {  		set_current_state(TASK_INTERRUPTIBLE);  		if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {  			err = -EBUSY; -			l2cap_send_disconn_req(pi->conn, sk, EBUSY); +			l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);  			break;  		} @@ -2964,7 +3041,7 @@ static void l2cap_busy_work(struct work_struct *work)  		if (err)  			break; -		if (l2cap_try_push_rx_skb(sk) == 0) +		if (l2cap_try_push_rx_skb(chan) == 0)  			break;  	} @@ -2974,48 +3051,47 @@ static void l2cap_busy_work(struct work_struct *work)  	release_sock(sk);  } -static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control) +static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk);  	int sctrl, err; -	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { +	if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {  		bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; -		__skb_queue_tail(BUSY_QUEUE(sk), skb); -		return l2cap_try_push_rx_skb(sk); +		__skb_queue_tail(&chan->busy_q, skb); +		return l2cap_try_push_rx_skb(chan);  	} -	err = l2cap_ertm_reassembly_sdu(sk, skb, control); +	err = l2cap_ertm_reassembly_sdu(chan, skb, control);  	if (err >= 0) { -		pi->buffer_seq = (pi->buffer_seq + 1) % 64; +		chan->buffer_seq = (chan->buffer_seq + 1) % 64;  		return err;  	}  	/* Busy Condition */ -	BT_DBG("sk %p, Enter local busy", sk); +	BT_DBG("chan %p, Enter local busy", chan); -	pi->conn_state |= L2CAP_CONN_LOCAL_BUSY; +	chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;  	bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT; -	__skb_queue_tail(BUSY_QUEUE(sk), skb); +	__skb_queue_tail(&chan->busy_q, skb); -	sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; +	sctrl = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;  	sctrl |= L2CAP_SUPER_RCV_NOT_READY; -	l2cap_send_sframe(pi, sctrl); +	l2cap_send_sframe(chan, sctrl); -	pi->conn_state |= L2CAP_CONN_RNR_SENT; +	chan->conn_state |= L2CAP_CONN_RNR_SENT; -	del_timer(&pi->ack_timer); +	del_timer(&chan->ack_timer); -	queue_work(_busy_wq, &pi->busy_work); +	queue_work(_busy_wq, &chan->busy_work);  	return err;  } -static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control) +static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk); +	struct l2cap_pinfo *pi = l2cap_pi(chan->sk);  	struct sk_buff *_skb;  	int err = -EINVAL; @@ -3026,80 +3102,80 @@ static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb,  	switch (control & L2CAP_CTRL_SAR) {  	case L2CAP_SDU_UNSEGMENTED: -		if (pi->conn_state & L2CAP_CONN_SAR_SDU) { -			kfree_skb(pi->sdu); +		if (chan->conn_state & L2CAP_CONN_SAR_SDU) { +			kfree_skb(chan->sdu);  			break;  		} -		err = sock_queue_rcv_skb(sk, skb); +		err = sock_queue_rcv_skb(chan->sk, skb);  		if (!err)  			return 0;  		break;  	case L2CAP_SDU_START: -		if (pi->conn_state & L2CAP_CONN_SAR_SDU) { -			kfree_skb(pi->sdu); +		if (chan->conn_state & L2CAP_CONN_SAR_SDU) { +			kfree_skb(chan->sdu);  			break;  		} -		pi->sdu_len = get_unaligned_le16(skb->data); +		chan->sdu_len = get_unaligned_le16(skb->data);  		skb_pull(skb, 2); -		if (pi->sdu_len > pi->imtu) { +		if (chan->sdu_len > pi->imtu) {  			err = -EMSGSIZE;  			break;  		} -		pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC); -		if (!pi->sdu) { +		chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC); +		if (!chan->sdu) {  			err = -ENOMEM;  			break;  		} -		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); +		memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); -		pi->conn_state |= L2CAP_CONN_SAR_SDU; -		pi->partial_sdu_len = skb->len; +		chan->conn_state |= L2CAP_CONN_SAR_SDU; +		chan->partial_sdu_len = skb->len;  		err = 0;  		break;  	case L2CAP_SDU_CONTINUE: -		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) +		if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))  			break; -		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); +		memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); -		pi->partial_sdu_len += skb->len; -		if (pi->partial_sdu_len > pi->sdu_len) -			kfree_skb(pi->sdu); +		chan->partial_sdu_len += skb->len; +		if (chan->partial_sdu_len > chan->sdu_len) +			kfree_skb(chan->sdu);  		else  			err = 0;  		break;  	case L2CAP_SDU_END: -		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU)) +		if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))  			break; -		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len); +		memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len); -		pi->conn_state &= ~L2CAP_CONN_SAR_SDU; -		pi->partial_sdu_len += skb->len; +		chan->conn_state &= ~L2CAP_CONN_SAR_SDU; +		chan->partial_sdu_len += skb->len; -		if (pi->partial_sdu_len > pi->imtu) +		if (chan->partial_sdu_len > pi->imtu)  			goto drop; -		if (pi->partial_sdu_len == pi->sdu_len) { -			_skb = skb_clone(pi->sdu, GFP_ATOMIC); -			err = sock_queue_rcv_skb(sk, _skb); +		if (chan->partial_sdu_len == chan->sdu_len) { +			_skb = skb_clone(chan->sdu, GFP_ATOMIC); +			err = sock_queue_rcv_skb(chan->sk, _skb);  			if (err < 0)  				kfree_skb(_skb);  		}  		err = 0;  drop: -		kfree_skb(pi->sdu); +		kfree_skb(chan->sdu);  		break;  	} @@ -3107,31 +3183,30 @@ drop:  	return err;  } -static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq) +static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)  {  	struct sk_buff *skb;  	u16 control; -	while ((skb = skb_peek(SREJ_QUEUE(sk)))) { +	while ((skb = skb_peek(&chan->srej_q))) {  		if (bt_cb(skb)->tx_seq != tx_seq)  			break; -		skb = skb_dequeue(SREJ_QUEUE(sk)); +		skb = skb_dequeue(&chan->srej_q);  		control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT; -		l2cap_ertm_reassembly_sdu(sk, skb, control); -		l2cap_pi(sk)->buffer_seq_srej = -			(l2cap_pi(sk)->buffer_seq_srej + 1) % 64; +		l2cap_ertm_reassembly_sdu(chan, skb, control); +		chan->buffer_seq_srej = +			(chan->buffer_seq_srej + 1) % 64;  		tx_seq = (tx_seq + 1) % 64;  	}  } -static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq) +static void l2cap_resend_srejframe(struct l2cap_chan *chan, u8 tx_seq)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk);  	struct srej_list *l, *tmp;  	u16 control; -	list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) { +	list_for_each_entry_safe(l, tmp, &chan->srej_l, list) {  		if (l->tx_seq == tx_seq) {  			list_del(&l->list);  			kfree(l); @@ -3139,34 +3214,33 @@ static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)  		}  		control = L2CAP_SUPER_SELECT_REJECT;  		control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; -		l2cap_send_sframe(pi, control); +		l2cap_send_sframe(chan, control);  		list_del(&l->list); -		list_add_tail(&l->list, SREJ_LIST(sk)); +		list_add_tail(&l->list, &chan->srej_l);  	}  } -static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq) +static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk);  	struct srej_list *new;  	u16 control; -	while (tx_seq != pi->expected_tx_seq) { +	while (tx_seq != chan->expected_tx_seq) {  		control = L2CAP_SUPER_SELECT_REJECT; -		control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; -		l2cap_send_sframe(pi, control); +		control |= chan->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; +		l2cap_send_sframe(chan, control);  		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); -		new->tx_seq = pi->expected_tx_seq; -		pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; -		list_add_tail(&new->list, SREJ_LIST(sk)); +		new->tx_seq = chan->expected_tx_seq; +		chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; +		list_add_tail(&new->list, &chan->srej_l);  	} -	pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; +	chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;  } -static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) +static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk); +	struct l2cap_pinfo *pi = l2cap_pi(chan->sk);  	u8 tx_seq = __get_txseq(rx_control);  	u8 req_seq = __get_reqseq(rx_control);  	u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT; @@ -3174,72 +3248,72 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str  	int num_to_ack = (pi->tx_win/6) + 1;  	int err = 0; -	BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq, -								rx_control); +	BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len, +							tx_seq, rx_control);  	if (L2CAP_CTRL_FINAL & rx_control && -			l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { -		del_timer(&pi->monitor_timer); -		if (pi->unacked_frames > 0) +			chan->conn_state & L2CAP_CONN_WAIT_F) { +		del_timer(&chan->monitor_timer); +		if (chan->unacked_frames > 0)  			__mod_retrans_timer(); -		pi->conn_state &= ~L2CAP_CONN_WAIT_F; +		chan->conn_state &= ~L2CAP_CONN_WAIT_F;  	} -	pi->expected_ack_seq = req_seq; -	l2cap_drop_acked_frames(sk); +	chan->expected_ack_seq = req_seq; +	l2cap_drop_acked_frames(chan); -	if (tx_seq == pi->expected_tx_seq) +	if (tx_seq == chan->expected_tx_seq)  		goto expected; -	tx_seq_offset = (tx_seq - pi->buffer_seq) % 64; +	tx_seq_offset = (tx_seq - chan->buffer_seq) % 64;  	if (tx_seq_offset < 0)  		tx_seq_offset += 64;  	/* invalid tx_seq */  	if (tx_seq_offset >= pi->tx_win) { -		l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); +		l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);  		goto drop;  	} -	if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY) +	if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)  		goto drop; -	if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { +	if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {  		struct srej_list *first; -		first = list_first_entry(SREJ_LIST(sk), +		first = list_first_entry(&chan->srej_l,  				struct srej_list, list);  		if (tx_seq == first->tx_seq) { -			l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); -			l2cap_check_srej_gap(sk, tx_seq); +			l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); +			l2cap_check_srej_gap(chan, tx_seq);  			list_del(&first->list);  			kfree(first); -			if (list_empty(SREJ_LIST(sk))) { -				pi->buffer_seq = pi->buffer_seq_srej; -				pi->conn_state &= ~L2CAP_CONN_SREJ_SENT; -				l2cap_send_ack(pi); -				BT_DBG("sk %p, Exit SREJ_SENT", sk); +			if (list_empty(&chan->srej_l)) { +				chan->buffer_seq = chan->buffer_seq_srej; +				chan->conn_state &= ~L2CAP_CONN_SREJ_SENT; +				l2cap_send_ack(chan); +				BT_DBG("chan %p, Exit SREJ_SENT", chan);  			}  		} else {  			struct srej_list *l;  			/* duplicated tx_seq */ -			if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0) +			if (l2cap_add_to_srej_queue(chan, skb, tx_seq, sar) < 0)  				goto drop; -			list_for_each_entry(l, SREJ_LIST(sk), list) { +			list_for_each_entry(l, &chan->srej_l, list) {  				if (l->tx_seq == tx_seq) { -					l2cap_resend_srejframe(sk, tx_seq); +					l2cap_resend_srejframe(chan, tx_seq);  					return 0;  				}  			} -			l2cap_send_srejframe(sk, tx_seq); +			l2cap_send_srejframe(chan, tx_seq);  		}  	} else {  		expected_tx_seq_offset = -			(pi->expected_tx_seq - pi->buffer_seq) % 64; +			(chan->expected_tx_seq - chan->buffer_seq) % 64;  		if (expected_tx_seq_offset < 0)  			expected_tx_seq_offset += 64; @@ -3247,51 +3321,51 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str  		if (tx_seq_offset < expected_tx_seq_offset)  			goto drop; -		pi->conn_state |= L2CAP_CONN_SREJ_SENT; +		chan->conn_state |= L2CAP_CONN_SREJ_SENT; -		BT_DBG("sk %p, Enter SREJ", sk); +		BT_DBG("chan %p, Enter SREJ", chan); -		INIT_LIST_HEAD(SREJ_LIST(sk)); -		pi->buffer_seq_srej = pi->buffer_seq; +		INIT_LIST_HEAD(&chan->srej_l); +		chan->buffer_seq_srej = chan->buffer_seq; -		__skb_queue_head_init(SREJ_QUEUE(sk)); -		__skb_queue_head_init(BUSY_QUEUE(sk)); -		l2cap_add_to_srej_queue(sk, skb, tx_seq, sar); +		__skb_queue_head_init(&chan->srej_q); +		__skb_queue_head_init(&chan->busy_q); +		l2cap_add_to_srej_queue(chan, skb, tx_seq, sar); -		pi->conn_state |= L2CAP_CONN_SEND_PBIT; +		chan->conn_state |= L2CAP_CONN_SEND_PBIT; -		l2cap_send_srejframe(sk, tx_seq); +		l2cap_send_srejframe(chan, tx_seq); -		del_timer(&pi->ack_timer); +		del_timer(&chan->ack_timer);  	}  	return 0;  expected: -	pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; +	chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64; -	if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { +	if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {  		bt_cb(skb)->tx_seq = tx_seq;  		bt_cb(skb)->sar = sar; -		__skb_queue_tail(SREJ_QUEUE(sk), skb); +		__skb_queue_tail(&chan->srej_q, skb);  		return 0;  	} -	err = l2cap_push_rx_skb(sk, skb, rx_control); +	err = l2cap_push_rx_skb(chan, skb, rx_control);  	if (err < 0)  		return 0;  	if (rx_control & L2CAP_CTRL_FINAL) { -		if (pi->conn_state & L2CAP_CONN_REJ_ACT) -			pi->conn_state &= ~L2CAP_CONN_REJ_ACT; +		if (chan->conn_state & L2CAP_CONN_REJ_ACT) +			chan->conn_state &= ~L2CAP_CONN_REJ_ACT;  		else -			l2cap_retransmit_frames(sk); +			l2cap_retransmit_frames(chan);  	}  	__mod_ack_timer(); -	pi->num_acked = (pi->num_acked + 1) % num_to_ack; -	if (pi->num_acked == num_to_ack - 1) -		l2cap_send_ack(pi); +	chan->num_acked = (chan->num_acked + 1) % num_to_ack; +	if (chan->num_acked == num_to_ack - 1) +		l2cap_send_ack(chan);  	return 0; @@ -3300,165 +3374,160 @@ drop:  	return 0;  } -static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_control)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk); - -	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control), +	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, __get_reqseq(rx_control),  						rx_control); -	pi->expected_ack_seq = __get_reqseq(rx_control); -	l2cap_drop_acked_frames(sk); +	chan->expected_ack_seq = __get_reqseq(rx_control); +	l2cap_drop_acked_frames(chan);  	if (rx_control & L2CAP_CTRL_POLL) { -		pi->conn_state |= L2CAP_CONN_SEND_FBIT; -		if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { -			if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && -					(pi->unacked_frames > 0)) +		chan->conn_state |= L2CAP_CONN_SEND_FBIT; +		if (chan->conn_state & L2CAP_CONN_SREJ_SENT) { +			if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && +					(chan->unacked_frames > 0))  				__mod_retrans_timer(); -			pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; -			l2cap_send_srejtail(sk); +			chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; +			l2cap_send_srejtail(chan);  		} else { -			l2cap_send_i_or_rr_or_rnr(sk); +			l2cap_send_i_or_rr_or_rnr(chan);  		}  	} else if (rx_control & L2CAP_CTRL_FINAL) { -		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; +		chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; -		if (pi->conn_state & L2CAP_CONN_REJ_ACT) -			pi->conn_state &= ~L2CAP_CONN_REJ_ACT; +		if (chan->conn_state & L2CAP_CONN_REJ_ACT) +			chan->conn_state &= ~L2CAP_CONN_REJ_ACT;  		else -			l2cap_retransmit_frames(sk); +			l2cap_retransmit_frames(chan);  	} else { -		if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && -				(pi->unacked_frames > 0)) +		if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && +				(chan->unacked_frames > 0))  			__mod_retrans_timer(); -		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; -		if (pi->conn_state & L2CAP_CONN_SREJ_SENT) -			l2cap_send_ack(pi); +		chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; +		if (chan->conn_state & L2CAP_CONN_SREJ_SENT) +			l2cap_send_ack(chan);  		else -			l2cap_ertm_send(sk); +			l2cap_ertm_send(chan);  	}  } -static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_control)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk);  	u8 tx_seq = __get_reqseq(rx_control); -	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control); +	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); -	pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; +	chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; -	pi->expected_ack_seq = tx_seq; -	l2cap_drop_acked_frames(sk); +	chan->expected_ack_seq = tx_seq; +	l2cap_drop_acked_frames(chan);  	if (rx_control & L2CAP_CTRL_FINAL) { -		if (pi->conn_state & L2CAP_CONN_REJ_ACT) -			pi->conn_state &= ~L2CAP_CONN_REJ_ACT; +		if (chan->conn_state & L2CAP_CONN_REJ_ACT) +			chan->conn_state &= ~L2CAP_CONN_REJ_ACT;  		else -			l2cap_retransmit_frames(sk); +			l2cap_retransmit_frames(chan);  	} else { -		l2cap_retransmit_frames(sk); +		l2cap_retransmit_frames(chan); -		if (pi->conn_state & L2CAP_CONN_WAIT_F) -			pi->conn_state |= L2CAP_CONN_REJ_ACT; +		if (chan->conn_state & L2CAP_CONN_WAIT_F) +			chan->conn_state |= L2CAP_CONN_REJ_ACT;  	}  } -static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk);  	u8 tx_seq = __get_reqseq(rx_control); -	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control); +	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); -	pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; +	chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;  	if (rx_control & L2CAP_CTRL_POLL) { -		pi->expected_ack_seq = tx_seq; -		l2cap_drop_acked_frames(sk); +		chan->expected_ack_seq = tx_seq; +		l2cap_drop_acked_frames(chan); -		pi->conn_state |= L2CAP_CONN_SEND_FBIT; -		l2cap_retransmit_one_frame(sk, tx_seq); +		chan->conn_state |= L2CAP_CONN_SEND_FBIT; +		l2cap_retransmit_one_frame(chan, tx_seq); -		l2cap_ertm_send(sk); +		l2cap_ertm_send(chan); -		if (pi->conn_state & L2CAP_CONN_WAIT_F) { -			pi->srej_save_reqseq = tx_seq; -			pi->conn_state |= L2CAP_CONN_SREJ_ACT; +		if (chan->conn_state & L2CAP_CONN_WAIT_F) { +			chan->srej_save_reqseq = tx_seq; +			chan->conn_state |= L2CAP_CONN_SREJ_ACT;  		}  	} else if (rx_control & L2CAP_CTRL_FINAL) { -		if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) && -				pi->srej_save_reqseq == tx_seq) -			pi->conn_state &= ~L2CAP_CONN_SREJ_ACT; +		if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) && +				chan->srej_save_reqseq == tx_seq) +			chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;  		else -			l2cap_retransmit_one_frame(sk, tx_seq); +			l2cap_retransmit_one_frame(chan, tx_seq);  	} else { -		l2cap_retransmit_one_frame(sk, tx_seq); -		if (pi->conn_state & L2CAP_CONN_WAIT_F) { -			pi->srej_save_reqseq = tx_seq; -			pi->conn_state |= L2CAP_CONN_SREJ_ACT; +		l2cap_retransmit_one_frame(chan, tx_seq); +		if (chan->conn_state & L2CAP_CONN_WAIT_F) { +			chan->srej_save_reqseq = tx_seq; +			chan->conn_state |= L2CAP_CONN_SREJ_ACT;  		}  	}  } -static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control) +static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_control)  { -	struct l2cap_pinfo *pi = l2cap_pi(sk);  	u8 tx_seq = __get_reqseq(rx_control); -	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control); +	BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control); -	pi->conn_state |= L2CAP_CONN_REMOTE_BUSY; -	pi->expected_ack_seq = tx_seq; -	l2cap_drop_acked_frames(sk); +	chan->conn_state |= L2CAP_CONN_REMOTE_BUSY; +	chan->expected_ack_seq = tx_seq; +	l2cap_drop_acked_frames(chan);  	if (rx_control & L2CAP_CTRL_POLL) -		pi->conn_state |= L2CAP_CONN_SEND_FBIT; +		chan->conn_state |= L2CAP_CONN_SEND_FBIT; -	if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) { -		del_timer(&pi->retrans_timer); +	if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) { +		del_timer(&chan->retrans_timer);  		if (rx_control & L2CAP_CTRL_POLL) -			l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL); +			l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);  		return;  	}  	if (rx_control & L2CAP_CTRL_POLL) -		l2cap_send_srejtail(sk); +		l2cap_send_srejtail(chan);  	else -		l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY); +		l2cap_send_sframe(chan, L2CAP_SUPER_RCV_READY);  } -static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb) +static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)  { -	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len); +	BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);  	if (L2CAP_CTRL_FINAL & rx_control && -			l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) { -		del_timer(&l2cap_pi(sk)->monitor_timer); -		if (l2cap_pi(sk)->unacked_frames > 0) +			chan->conn_state & L2CAP_CONN_WAIT_F) { +		del_timer(&chan->monitor_timer); +		if (chan->unacked_frames > 0)  			__mod_retrans_timer(); -		l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F; +		chan->conn_state &= ~L2CAP_CONN_WAIT_F;  	}  	switch (rx_control & L2CAP_CTRL_SUPERVISE) {  	case L2CAP_SUPER_RCV_READY: -		l2cap_data_channel_rrframe(sk, rx_control); +		l2cap_data_channel_rrframe(chan, rx_control);  		break;  	case L2CAP_SUPER_REJECT: -		l2cap_data_channel_rejframe(sk, rx_control); +		l2cap_data_channel_rejframe(chan, rx_control);  		break;  	case L2CAP_SUPER_SELECT_REJECT: -		l2cap_data_channel_srejframe(sk, rx_control); +		l2cap_data_channel_srejframe(chan, rx_control);  		break;  	case L2CAP_SUPER_RCV_NOT_READY: -		l2cap_data_channel_rnrframe(sk, rx_control); +		l2cap_data_channel_rnrframe(chan, rx_control);  		break;  	} @@ -3468,6 +3537,7 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str  static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)  { +	struct l2cap_chan *chan = l2cap_pi(sk)->chan;  	struct l2cap_pinfo *pi = l2cap_pi(sk);  	u16 control;  	u8 req_seq; @@ -3492,41 +3562,41 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)  		len -= 2;  	if (len > pi->mps) { -		l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); +		l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);  		goto drop;  	}  	req_seq = __get_reqseq(control); -	req_seq_offset = (req_seq - pi->expected_ack_seq) % 64; +	req_seq_offset = (req_seq - chan->expected_ack_seq) % 64;  	if (req_seq_offset < 0)  		req_seq_offset += 64;  	next_tx_seq_offset = -		(pi->next_tx_seq - pi->expected_ack_seq) % 64; +		(chan->next_tx_seq - chan->expected_ack_seq) % 64;  	if (next_tx_seq_offset < 0)  		next_tx_seq_offset += 64;  	/* check for invalid req-seq */  	if (req_seq_offset > next_tx_seq_offset) { -		l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); +		l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);  		goto drop;  	}  	if (__is_iframe(control)) {  		if (len < 0) { -			l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); +			l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);  			goto drop;  		} -		l2cap_data_channel_iframe(sk, control, skb); +		l2cap_data_channel_iframe(chan, control, skb);  	} else {  		if (len != 0) {  			BT_ERR("%d", len); -			l2cap_send_disconn_req(pi->conn, sk, ECONNRESET); +			l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);  			goto drop;  		} -		l2cap_data_channel_sframe(sk, control, skb); +		l2cap_data_channel_sframe(chan, control, skb);  	}  	return 0; @@ -3538,21 +3608,23 @@ drop:  static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)  { +	struct l2cap_chan *chan;  	struct sock *sk;  	struct l2cap_pinfo *pi;  	u16 control;  	u8 tx_seq;  	int len; -	sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); -	if (!sk) { +	chan = l2cap_get_chan_by_scid(conn, cid); +	if (!chan) {  		BT_DBG("unknown cid 0x%4.4x", cid);  		goto drop;  	} +	sk = chan->sk;  	pi = l2cap_pi(sk); -	BT_DBG("sk %p, len %d", sk, skb->len); +	BT_DBG("chan %p, len %d", chan, skb->len);  	if (sk->sk_state != BT_CONNECTED)  		goto drop; @@ -3600,17 +3672,17 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk  		tx_seq = __get_txseq(control); -		if (pi->expected_tx_seq == tx_seq) -			pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; +		if (chan->expected_tx_seq == tx_seq) +			chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;  		else -			pi->expected_tx_seq = (tx_seq + 1) % 64; +			chan->expected_tx_seq = (tx_seq + 1) % 64; -		l2cap_streaming_reassembly_sdu(sk, skb, control); +		l2cap_streaming_reassembly_sdu(chan, skb, control);  		goto done;  	default: -		BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode); +		BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode);  		break;  	} @@ -3654,6 +3726,36 @@ done:  	return 0;  } +static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) +{ +	struct sock *sk; + +	sk = l2cap_get_sock_by_scid(0, cid, conn->src); +	if (!sk) +		goto drop; + +	bh_lock_sock(sk); + +	BT_DBG("sk %p, len %d", sk, skb->len); + +	if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) +		goto drop; + +	if (l2cap_pi(sk)->imtu < skb->len) +		goto drop; + +	if (!sock_queue_rcv_skb(sk, skb)) +		goto done; + +drop: +	kfree_skb(skb); + +done: +	if (sk) +		bh_unlock_sock(sk); +	return 0; +} +  static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)  {  	struct l2cap_hdr *lh = (void *) skb->data; @@ -3683,6 +3785,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)  		l2cap_conless_channel(conn, psm, skb);  		break; +	case L2CAP_CID_LE_DATA: +		l2cap_att_channel(conn, cid, skb); +		break; +  	default:  		l2cap_data_channel(conn, cid, skb);  		break; @@ -3786,20 +3892,19 @@ static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)  static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)  { -	struct l2cap_chan_list *l;  	struct l2cap_conn *conn = hcon->l2cap_data; -	struct sock *sk; +	struct l2cap_chan *chan;  	if (!conn)  		return 0; -	l = &conn->chan_list; -  	BT_DBG("conn %p", conn); -	read_lock(&l->lock); +	read_lock(&conn->chan_lock); + +	list_for_each_entry(chan, &conn->chan_l, list) { +		struct sock *sk = chan->sk; -	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {  		bh_lock_sock(sk);  		if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) { @@ -3820,10 +3925,10 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)  				req.scid = cpu_to_le16(l2cap_pi(sk)->scid);  				req.psm  = l2cap_pi(sk)->psm; -				l2cap_pi(sk)->ident = l2cap_get_ident(conn); +				chan->ident = l2cap_get_ident(conn);  				l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND; -				l2cap_send_cmd(conn, l2cap_pi(sk)->ident, +				l2cap_send_cmd(conn, chan->ident,  					L2CAP_CONN_REQ, sizeof(req), &req);  			} else {  				l2cap_sock_clear_timer(sk); @@ -3846,14 +3951,14 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)  			rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);  			rsp.result = cpu_to_le16(result);  			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); -			l2cap_send_cmd(conn, l2cap_pi(sk)->ident, -					L2CAP_CONN_RSP, sizeof(rsp), &rsp); +			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, +							sizeof(rsp), &rsp);  		}  		bh_unlock_sock(sk);  	} -	read_unlock(&l->lock); +	read_unlock(&conn->chan_lock);  	return 0;  } @@ -3872,7 +3977,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl  	if (!(flags & ACL_CONT)) {  		struct l2cap_hdr *hdr; -		struct sock *sk; +		struct l2cap_chan *chan;  		u16 cid;  		int len; @@ -3910,18 +4015,21 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl  			goto drop;  		} -		sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); +		chan = l2cap_get_chan_by_scid(conn, cid); -		if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) { -			BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)", -					len, l2cap_pi(sk)->imtu); -			bh_unlock_sock(sk); -			l2cap_conn_unreliable(conn, ECOMM); -			goto drop; -		} +		if (chan && chan->sk) { +			struct sock *sk = chan->sk; -		if (sk) +			if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) { +				BT_ERR("Frame exceeding recv MTU (len %d, " +							"MTU %d)", len, +							l2cap_pi(sk)->imtu); +				bh_unlock_sock(sk); +				l2cap_conn_unreliable(conn, ECOMM); +				goto drop; +			}  			bh_unlock_sock(sk); +		}  		/* Allocate skb for the complete frame (with header) */  		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 299fe56a966..47394a178bd 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -269,7 +269,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)  		goto done;  	} -	if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->dcid) { +	if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->scid) {  		bdaddr_t *src = &bt_sk(sk)->src;  		u16 psm; @@ -757,36 +757,38 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms  	case L2CAP_MODE_ERTM:  	case L2CAP_MODE_STREAMING:  		/* Entire SDU fits into one PDU */ -		if (len <= pi->remote_mps) { +		if (len <= pi->chan->remote_mps) {  			control = L2CAP_SDU_UNSEGMENTED;  			skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);  			if (IS_ERR(skb)) {  				err = PTR_ERR(skb);  				goto done;  			} -			__skb_queue_tail(TX_QUEUE(sk), skb); +			__skb_queue_tail(&pi->chan->tx_q, skb); -			if (sk->sk_send_head == NULL) -				sk->sk_send_head = skb; +			if (pi->chan->tx_send_head == NULL) +				pi->chan->tx_send_head = skb;  		} else {  		/* Segment SDU into multiples PDUs */ -			err = l2cap_sar_segment_sdu(sk, msg, len); +			err = l2cap_sar_segment_sdu(pi->chan, msg, len);  			if (err < 0)  				goto done;  		}  		if (pi->mode == L2CAP_MODE_STREAMING) { -			l2cap_streaming_send(sk); -		} else { -			if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) && -					(pi->conn_state & L2CAP_CONN_WAIT_F)) { -				err = len; -				break; -			} -			err = l2cap_ertm_send(sk); +			l2cap_streaming_send(pi->chan); +			err = len; +			break;  		} +		if ((pi->chan->conn_state & L2CAP_CONN_REMOTE_BUSY) && +				(pi->chan->conn_state & L2CAP_CONN_WAIT_F)) { +			err = len; +			break; +		} +		err = l2cap_ertm_send(pi->chan); +  		if (err >= 0)  			err = len;  		break; @@ -808,29 +810,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms  	lock_sock(sk);  	if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { -		struct l2cap_conn_rsp rsp; -		struct l2cap_conn *conn = l2cap_pi(sk)->conn; -		u8 buf[128]; - -		sk->sk_state = BT_CONFIG; - -		rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid); -		rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid); -		rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); -		rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); -		l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident, -					L2CAP_CONN_RSP, sizeof(rsp), &rsp); - -		if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) { -			release_sock(sk); -			return 0; -		} - -		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; -		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, -				l2cap_build_conf_req(sk, buf), buf); -		l2cap_pi(sk)->num_conf_req++; - +		__l2cap_connect_rsp_defer(sk);  		release_sock(sk);  		return 0;  	} @@ -886,6 +866,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)  void __l2cap_sock_close(struct sock *sk, int reason)  {  	struct l2cap_conn *conn = l2cap_pi(sk)->conn; +	struct l2cap_chan *chan = l2cap_pi(sk)->chan;  	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); @@ -900,9 +881,9 @@ void __l2cap_sock_close(struct sock *sk, int reason)  					sk->sk_type == SOCK_STREAM) &&  					conn->hcon->type == ACL_LINK) {  			l2cap_sock_set_timer(sk, sk->sk_sndtimeo); -			l2cap_send_disconn_req(conn, sk, reason); +			l2cap_send_disconn_req(conn, chan, reason);  		} else -			l2cap_chan_del(sk, reason); +			l2cap_chan_del(chan, reason);  		break;  	case BT_CONNECT2: @@ -921,16 +902,16 @@ void __l2cap_sock_close(struct sock *sk, int reason)  			rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);  			rsp.result = cpu_to_le16(result);  			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); -			l2cap_send_cmd(conn, l2cap_pi(sk)->ident, -					L2CAP_CONN_RSP, sizeof(rsp), &rsp); +			l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, +							sizeof(rsp), &rsp);  		} -		l2cap_chan_del(sk, reason); +		l2cap_chan_del(chan, reason);  		break;  	case BT_CONNECT:  	case BT_DISCONN: -		l2cap_chan_del(sk, reason); +		l2cap_chan_del(chan, reason);  		break;  	default: @@ -1035,12 +1016,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)  	}  	/* Default config options */ -	pi->conf_len = 0;  	pi->flush_to = L2CAP_DEFAULT_FLUSH_TO; -	skb_queue_head_init(TX_QUEUE(sk)); -	skb_queue_head_init(SREJ_QUEUE(sk)); -	skb_queue_head_init(BUSY_QUEUE(sk)); -	INIT_LIST_HEAD(SREJ_LIST(sk));  }  static struct proto l2cap_proto = { diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index bf5d28da46e..a6d191f2a0f 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -330,6 +330,7 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in  static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)  {  	struct ieee80211_sub_if_data *sdata = sta->sdata; +	struct timespec uptime;  	sinfo->generation = sdata->local->sta_generation; @@ -343,7 +344,11 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)  			STATION_INFO_TX_BITRATE |  			STATION_INFO_RX_BITRATE |  			STATION_INFO_RX_DROP_MISC | -			STATION_INFO_BSS_PARAM; +			STATION_INFO_BSS_PARAM | +			STATION_INFO_CONNECTED_TIME; + +	do_posix_clock_monotonic_gettime(&uptime); +	sinfo->connected_time = uptime.tv_sec - sta->last_connected;  	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);  	sinfo->rx_bytes = sta->rx_bytes; @@ -686,6 +691,12 @@ static void sta_apply_parameters(struct ieee80211_local *local,  		if (set & BIT(NL80211_STA_FLAG_MFP))  			sta->flags |= WLAN_STA_MFP;  	} + +	if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { +		sta->flags &= ~WLAN_STA_AUTH; +		if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) +			sta->flags |= WLAN_STA_AUTH; +	}  	spin_unlock_irqrestore(&sta->flaglock, flags);  	/* @@ -1034,26 +1045,26 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,  	u8 *new_ie;  	const u8 *old_ie; -	/* first allocate the new vendor information element */ +	/* allocate information elements */  	new_ie = NULL; -	old_ie = ifmsh->vendor_ie; +	old_ie = ifmsh->ie; -	ifmsh->vendor_ie_len = setup->vendor_ie_len; -	if (setup->vendor_ie_len) { -		new_ie = kmemdup(setup->vendor_ie, setup->vendor_ie_len, +	if (setup->ie_len) { +		new_ie = kmemdup(setup->ie, setup->ie_len,  				GFP_KERNEL);  		if (!new_ie)  			return -ENOMEM;  	} +	ifmsh->ie_len = setup->ie_len; +	ifmsh->ie = new_ie; +	kfree(old_ie);  	/* now copy the rest of the setup parameters */  	ifmsh->mesh_id_len = setup->mesh_id_len;  	memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len);  	ifmsh->mesh_pp_id = setup->path_sel_proto;  	ifmsh->mesh_pm_id = setup->path_metric; -	ifmsh->vendor_ie = new_ie; - -	kfree(old_ie); +	ifmsh->is_secure = setup->is_secure;  	return 0;  } diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index c04a1396cf8..a01d2137fdd 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -92,6 +92,31 @@ static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,  }  STA_OPS(inactive_ms); + +static ssize_t sta_connected_time_read(struct file *file, char __user *userbuf, +					size_t count, loff_t *ppos) +{ +	struct sta_info *sta = file->private_data; +	struct timespec uptime; +	struct tm result; +	long connected_time_secs; +	char buf[100]; +	int res; +	do_posix_clock_monotonic_gettime(&uptime); +	connected_time_secs = uptime.tv_sec - sta->last_connected; +	time_to_tm(connected_time_secs, 0, &result); +	result.tm_year -= 70; +	result.tm_mday -= 1; +	res = scnprintf(buf, sizeof(buf), +		"years  - %ld\nmonths - %d\ndays   - %d\nclock  - %d:%d:%d\n\n", +			result.tm_year, result.tm_mon, result.tm_mday, +			result.tm_hour, result.tm_min, result.tm_sec); +	return simple_read_from_buffer(userbuf, count, ppos, buf, res); +} +STA_OPS(connected_time); + + +  static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,  				      size_t count, loff_t *ppos)  { @@ -324,6 +349,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)  	DEBUGFS_ADD(flags);  	DEBUGFS_ADD(num_ps_buf_frames);  	DEBUGFS_ADD(inactive_ms); +	DEBUGFS_ADD(connected_time);  	DEBUGFS_ADD(last_seq_ctrl);  	DEBUGFS_ADD(agg_status);  	DEBUGFS_ADD(dev); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 9c0d62bb0ea..00a0685f240 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -552,4 +552,17 @@ static inline void drv_get_ringparam(struct ieee80211_local *local,  	trace_drv_return_void(local);  } +static inline bool drv_tx_frames_pending(struct ieee80211_local *local) +{ +	bool ret = false; + +	might_sleep(); + +	trace_drv_tx_frames_pending(local); +	if (local->ops->tx_frames_pending) +		ret = local->ops->tx_frames_pending(&local->hw); +	trace_drv_return_bool(local, ret); + +	return ret; +}  #endif /* __MAC80211_DRIVER_OPS */ diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 45aab80738e..c8c934d48b7 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -74,6 +74,21 @@ TRACE_EVENT(drv_return_int,  	TP_printk(LOCAL_PR_FMT " - %d", LOCAL_PR_ARG, __entry->ret)  ); +TRACE_EVENT(drv_return_bool, +	TP_PROTO(struct ieee80211_local *local, bool ret), +	TP_ARGS(local, ret), +	TP_STRUCT__entry( +		LOCAL_ENTRY +		__field(bool, ret) +	), +	TP_fast_assign( +		LOCAL_ASSIGN; +		__entry->ret = ret; +	), +	TP_printk(LOCAL_PR_FMT " - %s", LOCAL_PR_ARG, (__entry->ret) ? +		  "true" : "false") +); +  TRACE_EVENT(drv_return_u64,  	TP_PROTO(struct ieee80211_local *local, u64 ret),  	TP_ARGS(local, ret), @@ -964,6 +979,11 @@ TRACE_EVENT(drv_get_ringparam,  	)  ); +DEFINE_EVENT(local_only_evt, drv_tx_frames_pending, +	TP_PROTO(struct ieee80211_local *local), +	TP_ARGS(local) +); +  DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait,  	TP_PROTO(struct ieee80211_local *local),  	TP_ARGS(local) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 89ce1e329b5..a7784997091 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -488,8 +488,9 @@ struct ieee80211_if_mesh {  	struct mesh_config mshcfg;  	u32 mesh_seqnum;  	bool accepting_plinks; -	const u8 *vendor_ie; -	u8 vendor_ie_len; +	const u8 *ie; +	u8 ie_len; +	bool is_secure;  };  #ifdef CONFIG_MAC80211_MESH diff --git a/net/mac80211/main.c b/net/mac80211/main.c index dc50fc3153e..0ab2a8df312 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -545,7 +545,9 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {  	},  	[NL80211_IFTYPE_MESH_POINT] = {  		.tx = 0xffff, -		.rx = BIT(IEEE80211_STYPE_ACTION >> 4), +		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) | +			BIT(IEEE80211_STYPE_AUTH >> 4) | +			BIT(IEEE80211_STYPE_DEAUTH >> 4),  	},  }; @@ -760,6 +762,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)  	local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);  #endif +	/* if the underlying driver supports mesh, mac80211 will (at least) +	 * provide routing of mesh authentication frames to userspace */ +	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT)) +		local->hw.wiphy->flags |= WIPHY_FLAG_MESH_AUTH; +  	/* mac80211 supports control port protocol changing */  	local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 2a57cc02c61..11207979e2e 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -279,9 +279,9 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)  	    MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00;  	*pos++ = 0x00; -	if (sdata->u.mesh.vendor_ie) { -		int len = sdata->u.mesh.vendor_ie_len; -		const u8 *data = sdata->u.mesh.vendor_ie; +	if (sdata->u.mesh.ie) { +		int len = sdata->u.mesh.ie_len; +		const u8 *data = sdata->u.mesh.ie;  		if (skb_tailroom(skb) > len)  			memcpy(skb_put(skb, len), data, len);  	} @@ -573,6 +573,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,  	ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,  			       &elems); +	/* ignore beacons from secure mesh peers if our security is off */ +	if (elems.rsn_len && !sdata->u.mesh.is_secure) +		return; +  	if (elems.ds_params && elems.ds_params_len == 1)  		freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);  	else @@ -586,9 +590,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,  	if (elems.mesh_id && elems.mesh_config &&  	    mesh_matches_local(&elems, sdata)) {  		supp_rates = ieee80211_sta_get_rates(local, &elems, band); - -		mesh_neighbour_update(mgmt->sa, supp_rates, sdata, -				      mesh_peer_accepts_plinks(&elems)); +		mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems);  	}  } diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index b99e230fe31..10acf1cc808 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -226,7 +226,8 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,  int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata);  /* Mesh plinks */  void mesh_neighbour_update(u8 *hw_addr, u32 rates, -		struct ieee80211_sub_if_data *sdata, bool add); +		struct ieee80211_sub_if_data *sdata, +		struct ieee802_11_elems *ie);  bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);  void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);  void mesh_plink_broken(struct sta_info *sta); diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 336ca9d0c5c..35c715adaae 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -65,42 +65,37 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs)  	__mesh_table_free(tbl);  } -static struct mesh_table *mesh_table_grow(struct mesh_table *tbl) +static int mesh_table_grow(struct mesh_table *oldtbl, +		struct mesh_table *newtbl)  { -	struct mesh_table *newtbl;  	struct hlist_head *oldhash;  	struct hlist_node *p, *q;  	int i; -	if (atomic_read(&tbl->entries) -			< tbl->mean_chain_len * (tbl->hash_mask + 1)) -		goto endgrow; +	if (atomic_read(&oldtbl->entries) +			< oldtbl->mean_chain_len * (oldtbl->hash_mask + 1)) +		return -EAGAIN; -	newtbl = mesh_table_alloc(tbl->size_order + 1); -	if (!newtbl) -		goto endgrow; -	newtbl->free_node = tbl->free_node; -	newtbl->mean_chain_len = tbl->mean_chain_len; -	newtbl->copy_node = tbl->copy_node; -	atomic_set(&newtbl->entries, atomic_read(&tbl->entries)); +	newtbl->free_node = oldtbl->free_node; +	newtbl->mean_chain_len = oldtbl->mean_chain_len; +	newtbl->copy_node = oldtbl->copy_node; +	atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries)); -	oldhash = tbl->hash_buckets; -	for (i = 0; i <= tbl->hash_mask; i++) +	oldhash = oldtbl->hash_buckets; +	for (i = 0; i <= oldtbl->hash_mask; i++)  		hlist_for_each(p, &oldhash[i]) -			if (tbl->copy_node(p, newtbl) < 0) +			if (oldtbl->copy_node(p, newtbl) < 0)  				goto errcopy; -	return newtbl; +	return 0;  errcopy:  	for (i = 0; i <= newtbl->hash_mask; i++) {  		hlist_for_each_safe(p, q, &newtbl->hash_buckets[i]) -			tbl->free_node(p, 0); +			oldtbl->free_node(p, 0);  	} -	__mesh_table_free(newtbl); -endgrow: -	return NULL; +	return -ENOMEM;  } @@ -334,10 +329,13 @@ void mesh_mpath_table_grow(void)  {  	struct mesh_table *oldtbl, *newtbl; +	newtbl = mesh_table_alloc(mesh_paths->size_order + 1); +	if (!newtbl) +		return;  	write_lock(&pathtbl_resize_lock);  	oldtbl = mesh_paths; -	newtbl = mesh_table_grow(mesh_paths); -	if (!newtbl) { +	if (mesh_table_grow(mesh_paths, newtbl) < 0) { +		__mesh_table_free(newtbl);  		write_unlock(&pathtbl_resize_lock);  		return;  	} @@ -352,10 +350,13 @@ void mesh_mpp_table_grow(void)  {  	struct mesh_table *oldtbl, *newtbl; +	newtbl = mesh_table_alloc(mpp_paths->size_order + 1); +	if (!newtbl) +		return;  	write_lock(&pathtbl_resize_lock);  	oldtbl = mpp_paths; -	newtbl = mesh_table_grow(mpp_paths); -	if (!newtbl) { +	if (mesh_table_grow(mpp_paths, newtbl) < 0) { +		__mesh_table_free(newtbl);  		write_unlock(&pathtbl_resize_lock);  		return;  	} diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 44b53931ba5..84e5b056af0 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -105,7 +105,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,  	if (!sta)  		return NULL; -	sta->flags = WLAN_STA_AUTHORIZED; +	sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH;  	sta->sta.supp_rates[local->hw.conf.channel->band] = rates;  	rate_control_rate_init(sta); @@ -161,7 +161,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,  		__le16 reason) {  	struct ieee80211_local *local = sdata->local;  	struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + -			sdata->u.mesh.vendor_ie_len); +			sdata->u.mesh.ie_len);  	struct ieee80211_mgmt *mgmt;  	bool include_plid = false;  	static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; @@ -237,8 +237,9 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,  	return 0;  } -void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, -			   bool peer_accepting_plinks) +void mesh_neighbour_update(u8 *hw_addr, u32 rates, +		struct ieee80211_sub_if_data *sdata, +		struct ieee802_11_elems *elems)  {  	struct ieee80211_local *local = sdata->local;  	struct sta_info *sta; @@ -248,8 +249,14 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data  	sta = sta_info_get(sdata, hw_addr);  	if (!sta) {  		rcu_read_unlock(); - -		sta = mesh_plink_alloc(sdata, hw_addr, rates); +		/* Userspace handles peer allocation when security is enabled +		 * */ +		if (sdata->u.mesh.is_secure) +			cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr, +					elems->ie_start, elems->total_len, +					GFP_KERNEL); +		else +			sta = mesh_plink_alloc(sdata, hw_addr, rates);  		if (!sta)  			return;  		if (sta_info_insert_rcu(sta)) { @@ -260,7 +267,8 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data  	sta->last_rx = jiffies;  	sta->sta.supp_rates[local->hw.conf.channel->band] = rates; -	if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && +	if (mesh_peer_accepts_plinks(elems) && +			sta->plink_state == PLINK_LISTEN &&  			sdata->u.mesh.accepting_plinks &&  			sdata->u.mesh.mshcfg.auto_open_plinks)  		mesh_plink_open(sta); @@ -372,6 +380,9 @@ int mesh_plink_open(struct sta_info *sta)  	__le16 llid;  	struct ieee80211_sub_if_data *sdata = sta->sdata; +	if (!test_sta_flags(sta, WLAN_STA_AUTH)) +		return -EPERM; +  	spin_lock_bh(&sta->lock);  	get_random_bytes(&llid, 2);  	sta->llid = llid; @@ -449,6 +460,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  		mpl_dbg("Mesh plink: missing necessary peer link ie\n");  		return;  	} +	if (elems.rsn_len && !sdata->u.mesh.is_secure) { +		mpl_dbg("Mesh plink: can't establish link with secure peer\n"); +		return; +	}  	ftype = mgmt->u.action.u.plink_action.action_code;  	ie_len = elems.peer_link_len; @@ -480,6 +495,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  		return;  	} +	if (sta && !test_sta_flags(sta, WLAN_STA_AUTH)) { +		mpl_dbg("Mesh plink: Action frame from non-authed peer\n"); +		rcu_read_unlock(); +		return; +	} +  	if (sta && sta->plink_state == PLINK_BLOCKED) {  		rcu_read_unlock();  		return; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 865fed4cc18..a41f234bd48 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -761,15 +761,16 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)  	if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&  	    (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) {  		netif_tx_stop_all_queues(sdata->dev); -		/* -		 * Flush all the frames queued in the driver before -		 * going to power save -		 */ -		drv_flush(local, false); -		ieee80211_send_nullfunc(local, sdata, 1); -		/* Flush once again to get the tx status of nullfunc frame */ -		drv_flush(local, false); +		if (drv_tx_frames_pending(local)) +			mod_timer(&local->dynamic_ps_timer, jiffies + +				  msecs_to_jiffies( +				  local->hw.conf.dynamic_ps_timeout)); +		else { +			ieee80211_send_nullfunc(local, sdata, 1); +			/* Flush to get the tx status of nullfunc frame */ +			drv_flush(local, false); +		}  	}  	if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 1f0b010904b..a864890e4d0 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -143,7 +143,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,  	if (status->flag & RX_FLAG_HT) {  		/*  		 * MCS information is a separate field in radiotap, -		 * added below. +		 * added below. The byte here is needed as padding +		 * for the channel though, so initialise it to 0.  		 */  		*pos = 0;  	} else { @@ -502,7 +503,8 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)  		if (ieee80211_is_probe_req(hdr->frame_control) ||  		    ieee80211_is_probe_resp(hdr->frame_control) || -		    ieee80211_is_beacon(hdr->frame_control)) +		    ieee80211_is_beacon(hdr->frame_control) || +		    ieee80211_is_auth(hdr->frame_control))  			return RX_CONTINUE;  		return RX_DROP_MONITOR; @@ -1585,7 +1587,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)  }  static int -__ieee80211_data_to_8023(struct ieee80211_rx_data *rx) +__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)  {  	struct ieee80211_sub_if_data *sdata = rx->sdata;  	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; @@ -1593,6 +1595,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)  	struct ethhdr *ehdr;  	int ret; +	*port_control = false;  	if (ieee80211_has_a4(hdr->frame_control) &&  	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)  		return -1; @@ -1611,11 +1614,13 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)  		return -1;  	ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); -	if (ret < 0 || !check_port_control) +	if (ret < 0)  		return ret;  	ehdr = (struct ethhdr *) rx->skb->data; -	if (ehdr->h_proto != rx->sdata->control_port_protocol) +	if (ehdr->h_proto == rx->sdata->control_port_protocol) +		*port_control = true; +	else if (check_port_control)  		return -1;  	return 0; @@ -1916,6 +1921,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)  	struct net_device *dev = sdata->dev;  	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;  	__le16 fc = hdr->frame_control; +	bool port_control;  	int err;  	if (unlikely(!ieee80211_is_data(hdr->frame_control))) @@ -1932,13 +1938,21 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)  	    sdata->vif.type == NL80211_IFTYPE_AP)  		return RX_DROP_MONITOR; -	err = __ieee80211_data_to_8023(rx); +	err = __ieee80211_data_to_8023(rx, &port_control);  	if (unlikely(err))  		return RX_DROP_UNUSABLE;  	if (!ieee80211_frame_allowed(rx, fc))  		return RX_DROP_MONITOR; +	if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && +	    unlikely(port_control) && sdata->bss) { +		sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, +				     u.ap); +		dev = sdata->dev; +		rx->sdata = sdata; +	} +  	rx->skb->dev = dev;  	dev->stats.rx_packets++; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 52d4b1a695c..a03d8a31287 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -228,6 +228,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,  {  	struct ieee80211_local *local = sdata->local;  	struct sta_info *sta; +	struct timespec uptime;  	int i;  	sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); @@ -245,6 +246,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,  	sta->sdata = sdata;  	sta->last_rx = jiffies; +	do_posix_clock_monotonic_gettime(&uptime); +	sta->last_connected = uptime.tv_sec;  	ewma_init(&sta->avg_signal, 1024, 8);  	if (sta_prepare_rate_control(local, sta, gfp)) { @@ -609,7 +612,8 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,  #endif  		dev_kfree_skb(skb); -		if (skb_queue_empty(&sta->ps_tx_buf)) +		if (skb_queue_empty(&sta->ps_tx_buf) && +		    !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF))  			sta_info_clear_tim_bit(sta);  	} @@ -893,6 +897,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)  	struct ieee80211_local *local = sdata->local;  	int sent, buffered; +	clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);  	if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))  		drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); @@ -985,3 +990,12 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,  		ieee80211_queue_work(hw, &sta->drv_unblock_wk);  }  EXPORT_SYMBOL(ieee80211_sta_block_awake); + +void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta) +{ +	struct sta_info *sta = container_of(pubsta, struct sta_info, sta); + +	set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); +	sta_info_set_tim_bit(sta); +} +EXPORT_SYMBOL(ieee80211_sta_set_tim); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 87b18ba1e0e..aa0adcbf3a9 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -43,6 +43,8 @@   *	be in the queues   * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping   *	station in power-save mode, reply when the driver unblocks. + * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal + *	buffers. Automatically cleared on station wake-up.   */  enum ieee80211_sta_info_flags {  	WLAN_STA_AUTH		= 1<<0, @@ -58,6 +60,7 @@ enum ieee80211_sta_info_flags {  	WLAN_STA_BLOCK_BA	= 1<<11,  	WLAN_STA_PS_DRIVER	= 1<<12,  	WLAN_STA_PSPOLL		= 1<<13, +	WLAN_STA_PS_DRIVER_BUF	= 1<<14,  };  #define STA_TID_NUM 16 @@ -226,6 +229,7 @@ enum plink_state {   * @rx_bytes: Number of bytes received from this STA   * @wep_weak_iv_count: number of weak WEP IVs received from this station   * @last_rx: time (in jiffies) when last frame was received from this STA + * @last_connected: time (in seconds) when a station got connected   * @num_duplicates: number of duplicate frames received from this STA   * @rx_fragments: number of received MPDUs   * @rx_dropped: number of dropped MPDUs from this STA @@ -295,6 +299,7 @@ struct sta_info {  	unsigned long rx_packets, rx_bytes;  	unsigned long wep_weak_iv_count;  	unsigned long last_rx; +	long last_connected;  	unsigned long num_duplicates;  	unsigned long rx_fragments;  	unsigned long rx_dropped; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ce4596ed126..17b10be31f5 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2262,7 +2262,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,  		/* headroom, head length, tail length and maximum TIM length */  		skb = dev_alloc_skb(local->tx_headroom + 400 + -				sdata->u.mesh.vendor_ie_len); +				sdata->u.mesh.ie_len);  		if (!skb)  			goto out; diff --git a/net/rfkill/Kconfig b/net/rfkill/Kconfig index 7fce6dfd218..48464ca13b2 100644 --- a/net/rfkill/Kconfig +++ b/net/rfkill/Kconfig @@ -22,3 +22,14 @@ config RFKILL_INPUT  	depends on RFKILL  	depends on INPUT = y || RFKILL = INPUT  	default y if !EXPERT + +config RFKILL_REGULATOR +	tristate "Generic rfkill regulator driver" +	depends on RFKILL || !RFKILL +	depends on REGULATOR +	help +          This options enable controlling radio transmitters connected to +          voltage regulator using the regulator framework. + +          To compile this driver as a module, choose M here: the module will +          be called rfkill-regulator. diff --git a/net/rfkill/Makefile b/net/rfkill/Makefile index 66210535269..d9a5a58ffd8 100644 --- a/net/rfkill/Makefile +++ b/net/rfkill/Makefile @@ -5,3 +5,4 @@  rfkill-y			+= core.o  rfkill-$(CONFIG_RFKILL_INPUT)	+= input.o  obj-$(CONFIG_RFKILL)		+= rfkill.o +obj-$(CONFIG_RFKILL_REGULATOR)	+= rfkill-regulator.o diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c new file mode 100644 index 00000000000..18dc512a10f --- /dev/null +++ b/net/rfkill/rfkill-regulator.c @@ -0,0 +1,164 @@ +/* + * rfkill-regulator.c - Regulator consumer driver for rfkill + * + * Copyright (C) 2009  Guiming Zhuo <gmzhuo@gmail.com> + * Copyright (C) 2011  Antonio Ospite <ospite@studenti.unina.it> + * + * Implementation inspired by leds-regulator driver. + * + * 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. + * + */ + +#include <linux/module.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> +#include <linux/rfkill.h> +#include <linux/rfkill-regulator.h> + +struct rfkill_regulator_data { +	struct rfkill *rf_kill; +	bool reg_enabled; + +	struct regulator *vcc; +}; + +static int rfkill_regulator_set_block(void *data, bool blocked) +{ +	struct rfkill_regulator_data *rfkill_data = data; + +	pr_debug("%s: blocked: %d\n", __func__, blocked); + +	if (blocked) { +		if (rfkill_data->reg_enabled) { +			regulator_disable(rfkill_data->vcc); +			rfkill_data->reg_enabled = 0; +		} +	} else { +		if (!rfkill_data->reg_enabled) { +			regulator_enable(rfkill_data->vcc); +			rfkill_data->reg_enabled = 1; +		} +	} + +	pr_debug("%s: regulator_is_enabled after set_block: %d\n", __func__, +		regulator_is_enabled(rfkill_data->vcc)); + +	return 0; +} + +struct rfkill_ops rfkill_regulator_ops = { +	.set_block = rfkill_regulator_set_block, +}; + +static int __devinit rfkill_regulator_probe(struct platform_device *pdev) +{ +	struct rfkill_regulator_platform_data *pdata = pdev->dev.platform_data; +	struct rfkill_regulator_data *rfkill_data; +	struct regulator *vcc; +	struct rfkill *rf_kill; +	int ret = 0; + +	if (pdata == NULL) { +		dev_err(&pdev->dev, "no platform data\n"); +		return -ENODEV; +	} + +	if (pdata->name == NULL || pdata->type == 0) { +		dev_err(&pdev->dev, "invalid name or type in platform data\n"); +		return -EINVAL; +	} + +	vcc = regulator_get_exclusive(&pdev->dev, "vrfkill"); +	if (IS_ERR(vcc)) { +		dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name); +		ret = PTR_ERR(vcc); +		goto out; +	} + +	rfkill_data = kzalloc(sizeof(*rfkill_data), GFP_KERNEL); +	if (rfkill_data == NULL) { +		ret = -ENOMEM; +		goto err_data_alloc; +	} + +	rf_kill = rfkill_alloc(pdata->name, &pdev->dev, +				pdata->type, +				&rfkill_regulator_ops, rfkill_data); +	if (rf_kill == NULL) { +		dev_err(&pdev->dev, "Cannot alloc rfkill device\n"); +		ret = -ENOMEM; +		goto err_rfkill_alloc; +	} + +	if (regulator_is_enabled(vcc)) { +		dev_dbg(&pdev->dev, "Regulator already enabled\n"); +		rfkill_data->reg_enabled = 1; +	} +	rfkill_data->vcc = vcc; +	rfkill_data->rf_kill = rf_kill; + +	ret = rfkill_register(rf_kill); +	if (ret) { +		dev_err(&pdev->dev, "Cannot register rfkill device\n"); +		goto err_rfkill_register; +	} + +	platform_set_drvdata(pdev, rfkill_data); +	dev_info(&pdev->dev, "%s initialized\n", pdata->name); + +	return 0; + +err_rfkill_register: +	rfkill_destroy(rf_kill); +err_rfkill_alloc: +	kfree(rfkill_data); +err_data_alloc: +	regulator_put(vcc); +out: +	return ret; +} + +static int __devexit rfkill_regulator_remove(struct platform_device *pdev) +{ +	struct rfkill_regulator_data *rfkill_data = platform_get_drvdata(pdev); +	struct rfkill *rf_kill = rfkill_data->rf_kill; + +	rfkill_unregister(rf_kill); +	rfkill_destroy(rf_kill); +	regulator_put(rfkill_data->vcc); +	kfree(rfkill_data); + +	return 0; +} + +static struct platform_driver rfkill_regulator_driver = { +	.probe = rfkill_regulator_probe, +	.remove = __devexit_p(rfkill_regulator_remove), +	.driver = { +		.name = "rfkill-regulator", +		.owner = THIS_MODULE, +	}, +}; + +static int __init rfkill_regulator_init(void) +{ +	return platform_driver_register(&rfkill_regulator_driver); +} +module_init(rfkill_regulator_init); + +static void __exit rfkill_regulator_exit(void) +{ +	platform_driver_unregister(&rfkill_regulator_driver); +} +module_exit(rfkill_regulator_exit); + +MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>"); +MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); +MODULE_DESCRIPTION("Regulator consumer driver for rfkill"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rfkill-regulator"); diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 73e39c171ff..5c116083eec 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -1,5 +1,6 @@  #include <linux/ieee80211.h>  #include <net/cfg80211.h> +#include "nl80211.h"  #include "core.h"  /* Default values, timeouts in ms */ @@ -53,8 +54,9 @@ const struct mesh_config default_mesh_config = {  const struct mesh_setup default_mesh_setup = {  	.path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP,  	.path_metric = IEEE80211_PATH_METRIC_AIRTIME, -	.vendor_ie = NULL, -	.vendor_ie_len = 0, +	.ie = NULL, +	.ie_len = 0, +	.is_secure = false,  };  int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, @@ -72,6 +74,10 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,  	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)  		return -EOPNOTSUPP; +	if (!(rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && +	      setup->is_secure) +		return -EOPNOTSUPP; +  	if (wdev->mesh_id_len)  		return -EALREADY; @@ -105,6 +111,19 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,  	return err;  } +void cfg80211_notify_new_peer_candidate(struct net_device *dev, +		const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp) +{ +	struct wireless_dev *wdev = dev->ieee80211_ptr; + +	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) +		return; + +	nl80211_send_new_peer_candidate(wiphy_to_dev(wdev->wiphy), dev, +			macaddr, ie, ie_len, gfp); +} +EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate); +  static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,  				 struct net_device *dev)  { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 297d7ce4117..0efa7fd0115 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -124,6 +124,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {  	[NL80211_ATTR_BSS_HT_OPMODE] = { .type = NLA_U16 },  	[NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED }, +	[NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },  	[NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,  					 .len = NL80211_HT_CAPABILITY_LEN }, @@ -594,6 +595,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,  	if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)  		NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); +	if (dev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) +		NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH);  	NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,  		sizeof(u32) * dev->wiphy.n_cipher_suites, @@ -1922,6 +1925,7 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {  	[NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },  	[NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },  	[NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, +	[NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },  };  static int parse_station_flags(struct genl_info *info, @@ -2016,6 +2020,9 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,  	sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);  	if (!sinfoattr)  		goto nla_put_failure; +	if (sinfo->filled & STATION_INFO_CONNECTED_TIME) +		NLA_PUT_U32(msg, NL80211_STA_INFO_CONNECTED_TIME, +			    sinfo->connected_time);  	if (sinfo->filled & STATION_INFO_INACTIVE_TIME)  		NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME,  			    sinfo->inactive_time); @@ -2281,7 +2288,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)  			err = -EINVAL;  		if (params.supported_rates)  			err = -EINVAL; -		if (params.sta_flags_mask) +		if (params.sta_flags_mask & +				~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | +				  BIT(NL80211_STA_FLAG_AUTHORIZED)))  			err = -EINVAL;  		break;  	default: @@ -2343,11 +2352,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)  		params.ht_capa =  			nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); +	if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) +		params.plink_action = +		    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); +  	if (parse_station_flags(info, ¶ms))  		return -EINVAL;  	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&  	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && +	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&  	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)  		return -EINVAL; @@ -2823,7 +2837,8 @@ static const struct nla_policy  	nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {  	[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },  	[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, -	[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE] = { .type = NLA_BINARY, +	[NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, +	[NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,  		.len = IEEE80211_MAX_DATA_LEN },  }; @@ -2925,14 +2940,16 @@ static int nl80211_parse_mesh_setup(struct genl_info *info,  		 IEEE80211_PATH_METRIC_VENDOR :  		 IEEE80211_PATH_METRIC_AIRTIME; -	if (tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]) { + +	if (tb[NL80211_MESH_SETUP_IE]) {  		struct nlattr *ieattr = -			tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]; +			tb[NL80211_MESH_SETUP_IE];  		if (!is_valid_ie_attr(ieattr))  			return -EINVAL; -		setup->vendor_ie = nla_data(ieattr); -		setup->vendor_ie_len = nla_len(ieattr); +		setup->ie = nla_data(ieattr); +		setup->ie_len = nla_len(ieattr);  	} +	setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);  	return 0;  } @@ -5804,6 +5821,44 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,  	nlmsg_free(msg);  } +void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, +		struct net_device *netdev, +		const u8 *macaddr, const u8* ie, u8 ie_len, +		gfp_t gfp) +{ +	struct sk_buff *msg; +	void *hdr; + +	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); +	if (!msg) +		return; + +	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE); +	if (!hdr) { +		nlmsg_free(msg); +		return; +	} + +	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); +	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); +	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, macaddr); +	if (ie_len && ie) +		NLA_PUT(msg, NL80211_ATTR_IE, ie_len , ie); + +	if (genlmsg_end(msg, hdr) < 0) { +		nlmsg_free(msg); +		return; +	} + +	genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, +				nl80211_mlme_mcgrp.id, gfp); +	return; + + nla_put_failure: +	genlmsg_cancel(msg, hdr); +	nlmsg_free(msg); +} +  void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,  				 struct net_device *netdev, const u8 *addr,  				 enum nl80211_key_type key_type, int key_id, diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index dcac5cd6f01..f2af6955a66 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -50,6 +50,10 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,  			       struct net_device *netdev, u16 reason,  			       const u8 *ie, size_t ie_len, bool from_ap); +void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev, +				     struct net_device *netdev, +				     const u8 *macaddr, const u8* ie, u8 ie_len, +				     gfp_t gfp);  void  nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,  			    struct net_device *netdev, const u8 *addr,  |