diff options
author | David S. Miller <davem@davemloft.net> | 2013-03-21 11:16:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-03-21 11:16:35 -0400 |
commit | b34870fc9ff15fe46c4066faeeec437a4e63e2d8 (patch) | |
tree | 0accc0dd931ffc1c9dd38862c14719bcfd66d502 /drivers/net/wireless/mwl8k.c | |
parent | chelsio: use netdev_alloc_skb_ip_align (diff) | |
parent | Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem (diff) | |
download | linux-dev-b34870fc9ff15fe46c4066faeeec437a4e63e2d8.tar.xz linux-dev-b34870fc9ff15fe46c4066faeeec437a4e63e2d8.zip |
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into wireless
John W. Linville says:
====================
This is a big pull request for new features intended for the 3.10
stream...
Regarding mac80211, Johannes says:
"First, I merged mac80211/master to avoid some conflicts. This brings in
a bunch of fixes you're already familiar with. For real -next material,
I have a whole bunch of minstrel work, minstrel_ht from Felix and legacy
minstrel from Thomas (Huehn). The other Thomas (Pedersen) did a number
of changes in mesh to allow userspace peering management even when the
mesh isn't secured. Stanislaw changes suspend/resume to always
disconnect the networks. This is typically already done by
network-manager so won't make a huge difference for most users, but
fixes a number problems, particularly with USB drivers that can easily
disconnect while suspended. Ilan has a small change to allow mac80211
drivers to differentiate remain-on-channel reasons, and Jouni extends
nl80211 to allow fast roaming with full-MAC devices. I have a fairly
large number of patches as well, many of them fairly simple cleanups,
but also allowing split wiphy dumps and adding back the full wiphy
information in nl80211, station entry change checking and more VHT work
including VHT capability overrides (mostly for testing purposes)."
And for iwlwifi, Johannes says:
"Here, I also merged iwlwifi-fixes to avoid conflicts, and otherwise have
various cleanups and improvements on the MVM driver, along with a few
throughout the driver. Other than Bluetooth Coexistence from Emmanuel
there's no over-arching theme, so listing them would pretty much
reproduce the shortlog."
Regarding NFC, Samuel says:
"The 2 features we have with this one are:
- An LLCP Service Name Lookup (SNL) netlink interface for querying LLCP
service availability from user space.
Along the way, Thierry also improved the existing SNL interface for
aggregating SNL responses.
- An initial LLCP socket options implementation, for setting the Receive
Window (RW) and the Maximum Information Unit Extension (MIUX) per socket.
This is need for the LLCP validation tests.
We also have a microread MEI build failure here: I am not sending this one to
3.9 because the MEI bus code is not there yet, so it won't break for anyone
else than me."
And for ath6kl, Kalle says:
"I added tracing support to ath6kl, along with a new Kconfig option. Now
there's also a workaround to reset USB devices when the firmware upload
fails, this happened when host was warm rebooted. There are also quite a
few small fixes or cleanup."
On top of all that, there is the usual bundle of driver updates
with new features, new hardware support and the like mixed-in.
The ath9k, b43, brcmfmac, mwifiex, rt2800, and wil6210 drivers
are all well-represented, and a few other drivers are hit as well.
I also pulled-in the wireless fixes tree in order to resolve some
pending merge conflicts.
Please let me know if there are problems!
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 111 |
1 files changed, 70 insertions, 41 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 091d9a64080a..0640e7d7f0c2 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -232,6 +232,7 @@ struct mwl8k_priv { u16 num_mcaddrs; u8 hw_rev; u32 fw_rev; + u32 caps; /* * Running count of TX packets in flight, to avoid @@ -284,6 +285,7 @@ struct mwl8k_priv { unsigned fw_state; char *fw_pref; char *fw_alt; + bool is_8764; struct completion firmware_loading_complete; /* bitmap of running BSSes */ @@ -600,13 +602,18 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) loops = 1000; do { u32 int_code; - - int_code = ioread32(regs + MWL8K_HIU_INT_CODE); - if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { - iowrite32(0, regs + MWL8K_HIU_INT_CODE); - break; + if (priv->is_8764) { + int_code = ioread32(regs + + MWL8K_HIU_H2A_INTERRUPT_STATUS); + if (int_code == 0) + break; + } else { + int_code = ioread32(regs + MWL8K_HIU_INT_CODE); + if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { + iowrite32(0, regs + MWL8K_HIU_INT_CODE); + break; + } } - cond_resched(); udelay(1); } while (--loops); @@ -724,7 +731,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) int rc; int loops; - if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { + if (!memcmp(fw->data, "\x01\x00\x00\x00", 4) && !priv->is_8764) { const struct firmware *helper = priv->fw_helper; if (helper == NULL) { @@ -743,7 +750,10 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); } else { - rc = mwl8k_load_fw_image(priv, fw->data, fw->size); + if (priv->is_8764) + rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); + else + rc = mwl8k_load_fw_image(priv, fw->data, fw->size); } if (rc) { @@ -908,9 +918,9 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, } /* - * Packet reception for 88w8366 AP firmware. + * Packet reception for 88w8366/88w8764 AP firmware. */ -struct mwl8k_rxd_8366_ap { +struct mwl8k_rxd_ap { __le16 pkt_len; __u8 sq2; __u8 rate; @@ -928,30 +938,30 @@ struct mwl8k_rxd_8366_ap { __u8 rx_ctrl; } __packed; -#define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80 -#define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40 -#define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) +#define MWL8K_AP_RATE_INFO_MCS_FORMAT 0x80 +#define MWL8K_AP_RATE_INFO_40MHZ 0x40 +#define MWL8K_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) -#define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 +#define MWL8K_AP_RX_CTRL_OWNED_BY_HOST 0x80 -/* 8366 AP rx_status bits */ -#define MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK 0x80 -#define MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF -#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02 -#define MWL8K_8366_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04 -#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08 +/* 8366/8764 AP rx_status bits */ +#define MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK 0x80 +#define MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF +#define MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02 +#define MWL8K_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04 +#define MWL8K_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08 -static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) +static void mwl8k_rxd_ap_init(void *_rxd, dma_addr_t next_dma_addr) { - struct mwl8k_rxd_8366_ap *rxd = _rxd; + struct mwl8k_rxd_ap *rxd = _rxd; rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); - rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST; + rxd->rx_ctrl = MWL8K_AP_RX_CTRL_OWNED_BY_HOST; } -static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) +static void mwl8k_rxd_ap_refill(void *_rxd, dma_addr_t addr, int len) { - struct mwl8k_rxd_8366_ap *rxd = _rxd; + struct mwl8k_rxd_ap *rxd = _rxd; rxd->pkt_len = cpu_to_le16(len); rxd->pkt_phys_addr = cpu_to_le32(addr); @@ -960,12 +970,12 @@ static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) } static int -mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, - __le16 *qos, s8 *noise) +mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status, + __le16 *qos, s8 *noise) { - struct mwl8k_rxd_8366_ap *rxd = _rxd; + struct mwl8k_rxd_ap *rxd = _rxd; - if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST)) + if (!(rxd->rx_ctrl & MWL8K_AP_RX_CTRL_OWNED_BY_HOST)) return -1; rmb(); @@ -974,11 +984,11 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, status->signal = -rxd->rssi; *noise = -rxd->noise_floor; - if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) { + if (rxd->rate & MWL8K_AP_RATE_INFO_MCS_FORMAT) { status->flag |= RX_FLAG_HT; - if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ) + if (rxd->rate & MWL8K_AP_RATE_INFO_40MHZ) status->flag |= RX_FLAG_40MHZ; - status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate); + status->rate_idx = MWL8K_AP_RATE_INFO_RATEID(rxd->rate); } else { int i; @@ -1002,19 +1012,19 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, *qos = rxd->qos_control; - if ((rxd->rx_status != MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR) && - (rxd->rx_status & MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK) && - (rxd->rx_status & MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR)) + if ((rxd->rx_status != MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR) && + (rxd->rx_status & MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK) && + (rxd->rx_status & MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR)) status->flag |= RX_FLAG_MMIC_ERROR; return le16_to_cpu(rxd->pkt_len); } -static struct rxd_ops rxd_8366_ap_ops = { - .rxd_size = sizeof(struct mwl8k_rxd_8366_ap), - .rxd_init = mwl8k_rxd_8366_ap_init, - .rxd_refill = mwl8k_rxd_8366_ap_refill, - .rxd_process = mwl8k_rxd_8366_ap_process, +static struct rxd_ops rxd_ap_ops = { + .rxd_size = sizeof(struct mwl8k_rxd_ap), + .rxd_init = mwl8k_rxd_ap_init, + .rxd_refill = mwl8k_rxd_ap_refill, + .rxd_process = mwl8k_rxd_ap_process, }; /* @@ -2401,6 +2411,9 @@ mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps) { struct mwl8k_priv *priv = hw->priv; + if (priv->caps) + return; + if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) { mwl8k_setup_2ghz_band(hw); if (caps & MWL8K_CAP_MIMO) @@ -2412,6 +2425,8 @@ mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps) if (caps & MWL8K_CAP_MIMO) mwl8k_set_ht_caps(hw, &priv->band_50, caps); } + + priv->caps = caps; } static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) @@ -5429,12 +5444,17 @@ enum { MWL8363 = 0, MWL8687, MWL8366, + MWL8764, }; #define MWL8K_8366_AP_FW_API 3 #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) +#define MWL8K_8764_AP_FW_API 1 +#define _MWL8K_8764_AP_FW(api) "mwl8k/fmimage_8764_ap-" #api ".fw" +#define MWL8K_8764_AP_FW(api) _MWL8K_8764_AP_FW(api) + static struct mwl8k_device_info mwl8k_info_tbl[] = { [MWL8363] = { .part_name = "88w8363", @@ -5452,7 +5472,13 @@ static struct mwl8k_device_info mwl8k_info_tbl[] = { .fw_image_sta = "mwl8k/fmimage_8366.fw", .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API), .fw_api_ap = MWL8K_8366_AP_FW_API, - .ap_rxd_ops = &rxd_8366_ap_ops, + .ap_rxd_ops = &rxd_ap_ops, + }, + [MWL8764] = { + .part_name = "88w8764", + .fw_image_ap = MWL8K_8764_AP_FW(MWL8K_8764_AP_FW_API), + .fw_api_ap = MWL8K_8764_AP_FW_API, + .ap_rxd_ops = &rxd_ap_ops, }, }; @@ -5474,6 +5500,7 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { { PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, }, { PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, }, { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, + { PCI_VDEVICE(MARVELL, 0x2b36), .driver_data = MWL8764, }, { }, }; MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); @@ -5995,6 +6022,8 @@ static int mwl8k_probe(struct pci_dev *pdev, priv->pdev = pdev; priv->device_info = &mwl8k_info_tbl[id->driver_data]; + if (id->driver_data == MWL8764) + priv->is_8764 = true; priv->sram = pci_iomap(pdev, 0, 0x10000); if (priv->sram == NULL) { |