summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/bluetooth/ath3k.c2
-rw-r--r--drivers/bluetooth/btusb.c41
-rw-r--r--drivers/bluetooth/hci_h4.c3
-rw-r--r--drivers/bluetooth/hci_ldisc.c15
-rw-r--r--drivers/net/wireless/adm8211.c3
-rw-r--r--drivers/net/wireless/at76c50x-usb.c4
-rw-r--r--drivers/net/wireless/ath/ar5523/ar5523.c14
-rw-r--r--drivers/net/wireless/ath/ath5k/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/trace.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c92
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c19
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c43
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pri_detector.c49
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pri_detector.h27
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_beacon.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h13
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c19
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c170
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c137
-rw-r--r--drivers/net/wireless/ath/carl9170/debug.c4
-rw-r--r--drivers/net/wireless/ath/carl9170/mac.c8
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c9
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.c4
-rw-r--r--drivers/net/wireless/ath/hw.c6
-rw-r--r--drivers/net/wireless/ath/reg.h4
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c29
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.h49
-rw-r--r--drivers/net/wireless/b43/b43.h2
-rw-r--r--drivers/net/wireless/b43/main.c8
-rw-r--r--drivers/net/wireless/b43/phy_ht.c124
-rw-r--r--drivers/net/wireless/b43/phy_ht.h6
-rw-r--r--drivers/net/wireless/b43/phy_lcn.c5
-rw-r--r--drivers/net/wireless/b43/phy_lp.c4
-rw-r--r--drivers/net/wireless/b43/phy_n.c710
-rw-r--r--drivers/net/wireless/b43/phy_n.h146
-rw-r--r--drivers/net/wireless/b43/radio_2059.c39
-rw-r--r--drivers/net/wireless/b43/radio_2059.h14
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c97
-rw-r--r--drivers/net/wireless/b43/tables_nphy.h29
-rw-r--r--drivers/net/wireless/b43legacy/main.c9
-rw-r--r--drivers/net/wireless/brcm80211/Kconfig9
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/Makefile3
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c243
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c118
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/btcoex.c497
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/btcoex.h29
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c11
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c659
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c256
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.c98
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c369
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h101
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h32
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c197
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h14
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/Makefile11
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/channel.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c6
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmutil/Makefile9
-rw-r--r--drivers/net/wireless/brcm80211/brcmutil/d11.c162
-rw-r--r--drivers/net/wireless/brcm80211/brcmutil/utils.c12
-rw-r--r--drivers/net/wireless/brcm80211/include/brcm_hw_ids.h2
-rw-r--r--drivers/net/wireless/brcm80211/include/brcmu_d11.h145
-rw-r--r--drivers/net/wireless/brcm80211/include/chipcommon.h14
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c32
-rw-r--r--drivers/net/wireless/iwlegacy/3945-rs.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965-mac.c32
-rw-r--r--drivers/net/wireless/iwlegacy/4965-rs.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965.c2
-rw-r--r--drivers/net/wireless/iwlegacy/common.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/agn.h6
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/devices.c10
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/lib.c16
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c27
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rs.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rxon.c11
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/tx.c45
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/bt-coex.c333
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c9
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c119
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-power.h64
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h33
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c12
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c31
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h27
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c115
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c36
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c10
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c14
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c2
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/drv.c1
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c2
-rw-r--r--drivers/net/wireless/libertas_tf/main.c8
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c114
-rw-r--r--drivers/net/wireless/mwifiex/11ac.c2
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.c14
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c2
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c25
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c2
-rw-r--r--drivers/net/wireless/mwifiex/init.c21
-rw-r--r--drivers/net/wireless/mwifiex/main.h1
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c4
-rw-r--r--drivers/net/wireless/mwifiex/scan.c37
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c17
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c160
-rw-r--r--drivers/net/wireless/mwifiex/wmm.h3
-rw-r--r--drivers/net/wireless/mwl8k.c46
-rw-r--r--drivers/net/wireless/p54/fwio.c4
-rw-r--r--drivers/net/wireless/p54/main.c4
-rw-r--r--drivers/net/wireless/p54/txrx.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c323
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c353
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c35
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c636
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c277
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c66
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h72
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c24
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00firmware.c25
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00leds.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c17
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mmio.c52
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mmio.h52
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c14
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c47
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00soc.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c24
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c550
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c32
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c4
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/grf5101.c3
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/max2820.c2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/rtl8225.c3
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/sa2400.c3
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/dev.c4
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/rtl8225.c3
-rw-r--r--drivers/net/wireless/rtlwifi/base.c8
-rw-r--r--drivers/net/wireless/rtlwifi/core.c6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/hw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/trx.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/trx.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/trx.c8
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/trx.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/trx.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/trx.c4
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c5
-rw-r--r--drivers/net/wireless/ti/wl12xx/cmd.c2
-rw-r--r--drivers/net/wireless/ti/wl18xx/cmd.c6
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c4
-rw-r--r--drivers/nfc/Kconfig10
-rw-r--r--drivers/nfc/Makefile1
-rw-r--r--drivers/nfc/mei_phy.c164
-rw-r--r--drivers/nfc/mei_phy.h30
-rw-r--r--drivers/nfc/microread/Kconfig2
-rw-r--r--drivers/nfc/microread/mei.c139
-rw-r--r--drivers/nfc/pn533.c653
-rw-r--r--drivers/nfc/pn544/Kconfig13
-rw-r--r--drivers/nfc/pn544/Makefile2
-rw-r--r--drivers/nfc/pn544/mei.c121
-rw-r--r--include/linux/bcma/bcma.h1
-rw-r--r--include/linux/bcma/bcma_driver_chipcommon.h3
-rw-r--r--include/linux/bcma/bcma_regs.h1
-rw-r--r--include/linux/ieee80211.h73
-rw-r--r--include/linux/platform_data/brcmfmac-sdio.h124
-rw-r--r--include/net/bluetooth/bluetooth.h5
-rw-r--r--include/net/bluetooth/hci.h9
-rw-r--r--include/net/bluetooth/hci_core.h98
-rw-r--r--include/net/bluetooth/l2cap.h15
-rw-r--r--include/net/cfg80211.h38
-rw-r--r--include/net/mac80211.h127
-rw-r--r--include/net/nfc/nfc.h2
-rw-r--r--include/uapi/linux/nfc.h7
-rw-r--r--include/uapi/linux/nl80211.h39
-rw-r--r--include/uapi/linux/rfkill.h2
-rw-r--r--net/bluetooth/hci_conn.c38
-rw-r--r--net/bluetooth/hci_core.c239
-rw-r--r--net/bluetooth/hci_event.c184
-rw-r--r--net/bluetooth/hci_sysfs.c17
-rw-r--r--net/bluetooth/hidp/core.c992
-rw-r--r--net/bluetooth/hidp/hidp.h67
-rw-r--r--net/bluetooth/hidp/sock.c22
-rw-r--r--net/bluetooth/l2cap_core.c127
-rw-r--r--net/bluetooth/l2cap_sock.c6
-rw-r--r--net/bluetooth/mgmt.c17
-rw-r--r--net/bluetooth/sco.c49
-rw-r--r--net/bluetooth/smp.c2
-rw-r--r--net/mac80211/cfg.c57
-rw-r--r--net/mac80211/chan.c54
-rw-r--r--net/mac80211/debugfs_netdev.c11
-rw-r--r--net/mac80211/debugfs_sta.c2
-rw-r--r--net/mac80211/ibss.c146
-rw-r--r--net/mac80211/ieee80211_i.h49
-rw-r--r--net/mac80211/iface.c121
-rw-r--r--net/mac80211/main.c82
-rw-r--r--net/mac80211/mesh.c6
-rw-r--r--net/mac80211/mesh.h3
-rw-r--r--net/mac80211/mesh_hwmp.c28
-rw-r--r--net/mac80211/mesh_pathtbl.c56
-rw-r--r--net/mac80211/mesh_plink.c6
-rw-r--r--net/mac80211/mlme.c442
-rw-r--r--net/mac80211/offchannel.c6
-rw-r--r--net/mac80211/pm.c11
-rw-r--r--net/mac80211/rate.c324
-rw-r--r--net/mac80211/rc80211_minstrel.c206
-rw-r--r--net/mac80211/rc80211_minstrel.h7
-rw-r--r--net/mac80211/rc80211_minstrel_debugfs.c4
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c172
-rw-r--r--net/mac80211/rc80211_minstrel_ht.h2
-rw-r--r--net/mac80211/rx.c24
-rw-r--r--net/mac80211/scan.c13
-rw-r--r--net/mac80211/trace.h51
-rw-r--r--net/mac80211/tx.c153
-rw-r--r--net/mac80211/util.c103
-rw-r--r--net/nfc/core.c43
-rw-r--r--net/nfc/llcp/commands.c30
-rw-r--r--net/nfc/llcp/llcp.c127
-rw-r--r--net/nfc/llcp/llcp.h5
-rw-r--r--net/nfc/llcp/sock.c43
-rw-r--r--net/rfkill/core.c4
-rw-r--r--net/rfkill/rfkill-gpio.c7
-rw-r--r--net/wireless/core.h3
-rw-r--r--net/wireless/mlme.c5
-rw-r--r--net/wireless/nl80211.c285
-rw-r--r--net/wireless/rdev-ops.h24
-rw-r--r--net/wireless/reg.c2
-rw-r--r--net/wireless/trace.h35
-rw-r--r--net/wireless/util.c28
257 files changed, 9897 insertions, 5629 deletions
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 6aab00ef4379..11f467c00d0a 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -90,6 +90,7 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x13d3, 0x3393) },
{ USB_DEVICE(0x0489, 0xe04e) },
{ USB_DEVICE(0x0489, 0xe056) },
+ { USB_DEVICE(0x0489, 0xe04d) },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) },
@@ -126,6 +127,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU22 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 2cc5f774a29c..3d684d20b584 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -148,6 +148,7 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -926,6 +927,22 @@ static void btusb_waker(struct work_struct *work)
usb_autopm_put_interface(data->intf);
}
+static int btusb_setup_bcm92035(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+ u8 val = 0x00;
+
+ BT_DBG("%s", hdev->name);
+
+ skb = __hci_cmd_sync(hdev, 0xfc3b, 1, &val, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb))
+ BT_ERR("BCM92035 command failed (%ld)", -PTR_ERR(skb));
+ else
+ kfree_skb(skb);
+
+ return 0;
+}
+
static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1022,11 +1039,14 @@ static int btusb_probe(struct usb_interface *intf,
SET_HCIDEV_DEV(hdev, &intf->dev);
- hdev->open = btusb_open;
- hdev->close = btusb_close;
- hdev->flush = btusb_flush;
- hdev->send = btusb_send_frame;
- hdev->notify = btusb_notify;
+ hdev->open = btusb_open;
+ hdev->close = btusb_close;
+ hdev->flush = btusb_flush;
+ hdev->send = btusb_send_frame;
+ hdev->notify = btusb_notify;
+
+ if (id->driver_info & BTUSB_BCM92035)
+ hdev->setup = btusb_setup_bcm92035;
/* Interface numbers are hardcoded in the specification */
data->isoc = usb_ifnum_to_if(data->udev, 1);
@@ -1065,17 +1085,6 @@ static int btusb_probe(struct usb_interface *intf,
data->isoc = NULL;
}
- if (id->driver_info & BTUSB_BCM92035) {
- unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
- struct sk_buff *skb;
-
- skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
- if (skb) {
- memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
- skb_queue_tail(&hdev->driver_init, skb);
- }
- }
-
if (data->isoc) {
err = usb_driver_claim_interface(&btusb_driver,
data->isoc, data);
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index c60623f206d4..8ae9f1ea2bb5 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -153,6 +153,9 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
{
int ret;
+ if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
+ return -EUNATCH;
+
ret = hci_recv_stream_fragment(hu->hdev, data, count);
if (ret < 0) {
BT_ERR("Frame Reassembly Failed");
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index ed0fade46aed..bc68a440d432 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -260,12 +260,12 @@ static int hci_uart_send_frame(struct sk_buff *skb)
/* ------ LDISC part ------ */
/* hci_uart_tty_open
- *
+ *
* Called when line discipline changed to HCI_UART.
*
* Arguments:
* tty pointer to tty info structure
- * Return Value:
+ * Return Value:
* 0 if success, otherwise error code
*/
static int hci_uart_tty_open(struct tty_struct *tty)
@@ -365,15 +365,15 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
}
/* hci_uart_tty_receive()
- *
+ *
* Called by tty low level driver when receive data is
* available.
- *
+ *
* Arguments: tty pointer to tty isntance data
* data pointer to received data
* flags pointer to flags for data
* count count of received data in bytes
- *
+ *
* Return Value: None
*/
static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
@@ -388,7 +388,10 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
spin_lock(&hu->rx_lock);
hu->proto->recv(hu, (void *) data, count);
- hu->hdev->stat.byte_rx += count;
+
+ if (hu->hdev)
+ hu->hdev->stat.byte_rx += count;
+
spin_unlock(&hu->rx_lock);
tty_unthrottle(tty);
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 3d339e04efb7..f9a24e599dee 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -1293,7 +1293,8 @@ static int adm8211_config(struct ieee80211_hw *dev, u32 changed)
{
struct adm8211_priv *priv = dev->priv;
struct ieee80211_conf *conf = &dev->conf;
- int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ int channel =
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
if (channel != priv->channel) {
priv->channel = channel;
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 5ac5f7ae2721..34c8a33cac06 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1943,12 +1943,12 @@ static int at76_config(struct ieee80211_hw *hw, u32 changed)
struct at76_priv *priv = hw->priv;
at76_dbg(DBG_MAC80211, "%s(): channel %d",
- __func__, hw->conf.channel->hw_value);
+ __func__, hw->conf.chandef.chan->hw_value);
at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:");
mutex_lock(&priv->mtx);
- priv->channel = hw->conf.channel->hw_value;
+ priv->channel = hw->conf.chandef.chan->hw_value;
if (is_valid_ether_addr(priv->bssid))
at76_join(priv);
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c
index afd1e36d308f..17d7fece35d2 100644
--- a/drivers/net/wireless/ath/ar5523/ar5523.c
+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -457,14 +457,14 @@ static int ar5523_set_chan(struct ar5523 *ar)
memset(&reset, 0, sizeof(reset));
reset.flags |= cpu_to_be32(UATH_CHAN_2GHZ);
reset.flags |= cpu_to_be32(UATH_CHAN_OFDM);
- reset.freq = cpu_to_be32(conf->channel->center_freq);
+ reset.freq = cpu_to_be32(conf->chandef.chan->center_freq);
reset.maxrdpower = cpu_to_be32(50); /* XXX */
reset.channelchange = cpu_to_be32(1);
reset.keeprccontent = cpu_to_be32(0);
ar5523_dbg(ar, "set chan flags 0x%x freq %d\n",
be32_to_cpu(reset.flags),
- conf->channel->center_freq);
+ conf->chandef.chan->center_freq);
return ar5523_cmd_write(ar, WDCMSG_RESET, &reset, sizeof(reset), 0);
}
@@ -594,7 +594,7 @@ static void ar5523_data_rx_cb(struct urb *urb)
rx_status = IEEE80211_SKB_RXCB(data->skb);
memset(rx_status, 0, sizeof(*rx_status));
rx_status->freq = be32_to_cpu(desc->channel);
- rx_status->band = hw->conf.channel->band;
+ rx_status->band = hw->conf.chandef.chan->band;
rx_status->signal = -95 + be32_to_cpu(desc->rssi);
ieee80211_rx_irqsafe(hw, data->skb);
@@ -1153,13 +1153,13 @@ static int ar5523_get_wlan_mode(struct ar5523 *ar,
struct ieee80211_sta *sta;
u32 sta_rate_set;
- band = ar->hw->wiphy->bands[ar->hw->conf.channel->band];
+ band = ar->hw->wiphy->bands[ar->hw->conf.chandef.chan->band];
sta = ieee80211_find_sta(ar->vif, bss_conf->bssid);
if (!sta) {
ar5523_info(ar, "STA not found!\n");
return WLAN_MODE_11b;
}
- sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
+ sta_rate_set = sta->supp_rates[ar->hw->conf.chandef.chan->band];
for (bit = 0; bit < band->n_bitrates; bit++) {
if (sta_rate_set & 1) {
@@ -1197,11 +1197,11 @@ static void ar5523_create_rateset(struct ar5523 *ar,
ar5523_info(ar, "STA not found. Cannot set rates\n");
sta_rate_set = bss_conf->basic_rates;
} else
- sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band];
+ sta_rate_set = sta->supp_rates[ar->hw->conf.chandef.chan->band];
ar5523_dbg(ar, "sta rate_set = %08x\n", sta_rate_set);
- band = ar->hw->wiphy->bands[ar->hw->conf.channel->band];
+ band = ar->hw->wiphy->bands[ar->hw->conf.chandef.chan->band];
for (bit = 0; bit < band->n_bitrates; bit++) {
BUG_ON(i >= AR5523_MAX_NRATES);
ar5523_dbg(ar, "Considering rate %d : %d\n",
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile
index f60b3899afc4..1b3a34f7f224 100644
--- a/drivers/net/wireless/ath/ath5k/Makefile
+++ b/drivers/net/wireless/ath/ath5k/Makefile
@@ -10,6 +10,7 @@ ath5k-y += phy.o
ath5k-y += reset.o
ath5k-y += attach.o
ath5k-y += base.o
+CFLAGS_base.o += -I$(src)
ath5k-y += led.o
ath5k-y += rfkill.o
ath5k-y += ani.o
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 1d264c0f5a9b..9b20d9ee2719 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2639,7 +2639,7 @@ int ath5k_start(struct ieee80211_hw *hw)
* be followed by initialization of the appropriate bits
* and then setup of the interrupt mask.
*/
- ah->curchan = ah->hw->conf.channel;
+ ah->curchan = ah->hw->conf.chandef.chan;
ah->imask = AR5K_INT_RXOK
| AR5K_INT_RXERR
| AR5K_INT_RXEOL
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 4264341533ea..06f86f435711 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -202,7 +202,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&ah->lock);
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- ret = ath5k_chan_set(ah, conf->channel);
+ ret = ath5k_chan_set(ah, conf->chandef.chan);
if (ret < 0)
goto unlock;
}
@@ -678,7 +678,7 @@ ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
memcpy(survey, &ah->survey, sizeof(*survey));
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->noise = ah->ah_noise_floor;
survey->filled = SURVEY_INFO_NOISE_DBM |
SURVEY_INFO_CHANNEL_TIME |
diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h
index 00f015819344..c6eef519bb61 100644
--- a/drivers/net/wireless/ath/ath5k/trace.h
+++ b/drivers/net/wireless/ath/ath5k/trace.h
@@ -97,7 +97,7 @@ TRACE_EVENT(ath5k_tx_complete,
#if defined(CONFIG_ATH5K_TRACER) && !defined(__CHECKER__)
#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH ../../drivers/net/wireless/ath/ath5k
+#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index fd69376ecc83..391da5ad6a99 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -18,6 +18,7 @@
#include "hw-ops.h"
#include "../regd.h"
#include "ar9002_phy.h"
+#include "ar5008_initvals.h"
/* All code below is for AR5008, AR9001, AR9002 */
@@ -43,23 +44,16 @@ static const int m2ThreshLowExt_off = 127;
static const int m1ThreshExt_off = 127;
static const int m2ThreshExt_off = 127;
+static const struct ar5416IniArray bank0 = STATIC_INI_ARRAY(ar5416Bank0);
+static const struct ar5416IniArray bank1 = STATIC_INI_ARRAY(ar5416Bank1);
+static const struct ar5416IniArray bank2 = STATIC_INI_ARRAY(ar5416Bank2);
+static const struct ar5416IniArray bank3 = STATIC_INI_ARRAY(ar5416Bank3);
+static const struct ar5416IniArray bank7 = STATIC_INI_ARRAY(ar5416Bank7);
-static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array,
- int col)
-{
- int i;
-
- for (i = 0; i < array->ia_rows; i++)
- bank[i] = INI_RA(array, i, col);
-}
-
-
-#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \
- ar5008_write_rf_array(ah, iniarray, regData, &(regWr))
-
-static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array,
- u32 *data, unsigned int *writecnt)
+static void ar5008_write_bank6(struct ath_hw *ah, unsigned int *writecnt)
{
+ struct ar5416IniArray *array = &ah->iniBank6;
+ u32 *data = ah->analogBank6Data;
int r;
ENABLE_REGWRITE_BUFFER(ah);
@@ -165,7 +159,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3);
/* write Bank 6 with new params */
- REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes);
+ ar5008_write_bank6(ah, &reg_writes);
}
/**
@@ -469,31 +463,16 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
*/
static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
{
-#define ATH_ALLOC_BANK(bank, size) do { \
- bank = devm_kzalloc(ah->dev, sizeof(u32) * size, GFP_KERNEL); \
- if (!bank) \
- goto error; \
- } while (0);
-
- struct ath_common *common = ath9k_hw_common(ah);
+ int size = ah->iniBank6.ia_rows * sizeof(u32);
if (AR_SREV_9280_20_OR_LATER(ah))
return 0;
- ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows);
- ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows);
- ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows);
+ ah->analogBank6Data = devm_kzalloc(ah->dev, size, GFP_KERNEL);
+ if (!ah->analogBank6Data)
+ return -ENOMEM;
return 0;
-#undef ATH_ALLOC_BANK
-error:
- ath_err(common, "Cannot allocate RF banks\n");
- return -ENOMEM;
}
@@ -517,6 +496,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
u32 ob5GHz = 0, db5GHz = 0;
u32 ob2GHz = 0, db2GHz = 0;
int regWrites = 0;
+ int i;
/*
* Software does not need to program bank data
@@ -529,25 +509,8 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
/* Setup rf parameters */
eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
- /* Setup Bank 0 Write */
- ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1);
-
- /* Setup Bank 1 Write */
- ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1);
-
- /* Setup Bank 2 Write */
- ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1);
-
- /* Setup Bank 6 Write */
- ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3,
- modesIndex);
- {
- int i;
- for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) {
- ah->analogBank6Data[i] =
- INI_RA(&ah->iniBank6TPC, i, modesIndex);
- }
- }
+ for (i = 0; i < ah->iniBank6.ia_rows; i++)
+ ah->analogBank6Data[i] = INI_RA(&ah->iniBank6, i, modesIndex);
/* Only the 5 or 2 GHz OB/DB need to be set for a mode */
if (eepMinorRev >= 2) {
@@ -568,22 +531,13 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,
}
}
- /* Setup Bank 7 Setup */
- ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1);
-
/* Write Analog registers */
- REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data,
- regWrites);
- REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data,
- regWrites);
+ REG_WRITE_ARRAY(&bank0, 1, regWrites);
+ REG_WRITE_ARRAY(&bank1, 1, regWrites);
+ REG_WRITE_ARRAY(&bank2, 1, regWrites);
+ REG_WRITE_ARRAY(&bank3, modesIndex, regWrites);
+ ar5008_write_bank6(ah, &regWrites);
+ REG_WRITE_ARRAY(&bank7, 1, regWrites);
return true;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index f053d978540e..830daa12feb6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -67,12 +67,10 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
} else if (AR_SREV_9100_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100);
- INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100);
} else {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common);
- INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac);
}
@@ -80,20 +78,11 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
/* Common for AR5416, AR913x, AR9160 */
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain);
- INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0);
- INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1);
- INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2);
- INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3);
- INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7);
-
- /* Common for AR5416, AR9160 */
- if (!AR_SREV_9100(ah))
- INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6);
-
/* Common for AR913x, AR9160 */
if (!AR_SREV_5416(ah))
- INIT_INI_ARRAY(&ah->iniBank6TPC,
- ar5416Bank6TPC_9100);
+ INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100);
+ else
+ INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC);
}
/* iniAddac needs to be modified for these chips */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index a56b2416e2f9..8a1888d02070 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -234,6 +234,7 @@ struct ath_buf {
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
bool bf_stale;
+ struct ieee80211_tx_rate rates[4];
struct ath_buf_state bf_state;
};
@@ -311,6 +312,7 @@ struct ath_rx_edma {
struct ath_rx {
u8 defant;
u8 rxotherant;
+ bool discard_next;
u32 *rxlink;
u32 num_pkts;
unsigned int rxfilter;
@@ -657,11 +659,10 @@ enum sc_op_flags {
struct ath_rate_table;
struct ath9k_vif_iter_data {
- const u8 *hw_macaddr; /* phy's hardware address, set
- * before starting iteration for
- * valid bssid mask.
- */
+ u8 hw_macaddr[ETH_ALEN]; /* address of the first vif */
u8 mask[ETH_ALEN]; /* bssid mask */
+ bool has_hw_macaddr;
+
int naps; /* number of AP vifs */
int nmeshes; /* number of mesh vifs */
int nstations; /* number of station vifs */
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 5f05c26d1ec4..2ff570f7f8ff 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -79,7 +79,7 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
u8 chainmask = ah->txchainmask;
u8 rate = 0;
- sband = &sc->sbands[common->hw->conf.channel->band];
+ sband = &sc->sbands[common->hw->conf.chandef.chan->band];
rate = sband->bitrates[rateidx].hw_value;
if (vif->bss_conf.use_short_preamble)
rate |= sband->bitrates[rateidx].hw_value_short;
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 7bdd726c7a8f..7304e7585009 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -208,7 +208,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
return true;
ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n",
- currCal->calData->calType, conf->channel->center_freq);
+ currCal->calData->calType, conf->chandef.chan->center_freq);
ah->caldata->CalValid &= ~currCal->calData->calType;
currCal->calState = CAL_WAITING;
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 60dcb6c22db9..3d70b8c2bcdd 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -33,6 +33,12 @@ struct ar5416IniArray {
u32 ia_columns;
};
+#define STATIC_INI_ARRAY(array) { \
+ .ia_array = (u32 *)(array), \
+ .ia_rows = ARRAY_SIZE(array), \
+ .ia_columns = ARRAY_SIZE(array[0]), \
+ }
+
#define INIT_INI_ARRAY(iniarray, array) do { \
(iniarray)->ia_array = (u32 *)(array); \
(iniarray)->ia_rows = ARRAY_SIZE(array); \
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 905f1b313961..344fdde1d7a3 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -27,20 +27,6 @@ MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
MODULE_LICENSE("Dual BSD/GPL");
-int ath9k_cmn_padpos(__le16 frame_control)
-{
- int padpos = 24;
- if (ieee80211_has_a4(frame_control)) {
- padpos += ETH_ALEN;
- }
- if (ieee80211_is_data_qos(frame_control)) {
- padpos += IEEE80211_QOS_CTL_LEN;
- }
-
- return padpos;
-}
-EXPORT_SYMBOL(ath9k_cmn_padpos);
-
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -133,13 +119,14 @@ EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
struct ath_hw *ah)
{
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
struct ath9k_channel *channel;
u8 chan_idx;
chan_idx = curchan->hw_value;
channel = &ah->channels[chan_idx];
- ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type);
+ ath9k_cmn_update_ichannel(channel, curchan,
+ cfg80211_get_chandef_type(&hw->conf.chandef));
return channel;
}
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 6102476a65de..207d06995b15 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -42,7 +42,6 @@
#define ATH_EP_RND(x, mul) \
(((x) + ((mul)/2)) / (mul))
-int ath9k_cmn_padpos(__le16 frame_control);
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
struct ieee80211_channel *chan,
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c
index 508f8b33f0ef..7187d3671512 100644
--- a/drivers/net/wireless/ath/ath9k/dfs.c
+++ b/drivers/net/wireless/ath/ath9k/dfs.c
@@ -55,12 +55,6 @@ ath9k_postprocess_radar_event(struct ath_softc *sc,
u8 rssi;
u16 dur;
- ath_dbg(ath9k_hw_common(sc->sc_ah), DFS,
- "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n",
- ard->pulse_bw_info,
- ard->pulse_length_pri, ard->rssi,
- ard->pulse_length_ext, ard->ext_rssi);
-
/*
* Only the last 2 bits of the BW info are relevant, they indicate
* which channel the radar was detected in.
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
index 73fe8d6db566..491305c81fce 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
@@ -19,6 +19,7 @@
#include "dfs_pattern_detector.h"
#include "dfs_pri_detector.h"
+#include "ath9k.h"
/*
* tolerated deviation of radar time stamp in usecs on both sides
@@ -142,6 +143,7 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
{
u32 sz, i;
struct channel_detector *cd;
+ struct ath_common *common = ath9k_hw_common(dpd->ah);
cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
if (cd == NULL)
@@ -165,7 +167,8 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
return cd;
fail:
- pr_err("failed to allocate channel_detector for freq=%d\n", freq);
+ ath_dbg(common, DFS,
+ "failed to allocate channel_detector for freq=%d\n", freq);
channel_detector_exit(dpd, cd);
return NULL;
}
@@ -216,34 +219,34 @@ static bool
dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event)
{
u32 i;
- bool ts_wraparound;
struct channel_detector *cd;
- if (dpd->region == NL80211_DFS_UNSET) {
- /*
- * pulses received for a non-supported or un-initialized
- * domain are treated as detected radars
- */
+ /*
+ * pulses received for a non-supported or un-initialized
+ * domain are treated as detected radars for fail-safety
+ */
+ if (dpd->region == NL80211_DFS_UNSET)
return true;
- }
cd = channel_detector_get(dpd, event->freq);
if (cd == NULL)
return false;
- ts_wraparound = (event->ts < dpd->last_pulse_ts);
dpd->last_pulse_ts = event->ts;
- if (ts_wraparound) {
- /*
- * reset detector on time stamp wraparound
- * with monotonic time stamps, this should never happen
- */
- pr_warn("DFS: time stamp wraparound detected, resetting\n");
+ /* reset detector on time stamp wraparound, caused by TSF reset */
+ if (event->ts < dpd->last_pulse_ts)
dpd_reset(dpd);
- }
+
/* do type individual pattern matching */
for (i = 0; i < dpd->num_radar_types; i++) {
- if (cd->detectors[i]->add_pulse(cd->detectors[i], event) != 0) {
+ struct pri_detector *pd = cd->detectors[i];
+ struct pri_sequence *ps = pd->add_pulse(pd, event);
+ if (ps != NULL) {
+ ath_dbg(ath9k_hw_common(dpd->ah), DFS,
+ "DFS: radar found on freq=%d: id=%d, pri=%d, "
+ "count=%d, count_false=%d\n",
+ event->freq, pd->rs->type_id,
+ ps->pri, ps->count, ps->count_falses);
channel_detector_reset(dpd, cd);
return true;
}
@@ -285,9 +288,10 @@ static struct dfs_pattern_detector default_dpd = {
};
struct dfs_pattern_detector *
-dfs_pattern_detector_init(enum nl80211_dfs_regions region)
+dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region)
{
struct dfs_pattern_detector *dpd;
+ struct ath_common *common = ath9k_hw_common(ah);
dpd = kmalloc(sizeof(*dpd), GFP_KERNEL);
if (dpd == NULL)
@@ -296,10 +300,11 @@ dfs_pattern_detector_init(enum nl80211_dfs_regions region)
*dpd = default_dpd;
INIT_LIST_HEAD(&dpd->channel_detectors);
+ dpd->ah = ah;
if (dpd->set_dfs_domain(dpd, region))
return dpd;
- pr_err("Could not set DFS domain to %d. ", region);
+ ath_dbg(common, DFS,"Could not set DFS domain to %d", region);
kfree(dpd);
return NULL;
}
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
index cda52f39f28a..90a5abcc4265 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
+++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
@@ -80,6 +80,8 @@ struct dfs_pattern_detector {
enum nl80211_dfs_regions region;
u8 num_radar_types;
u64 last_pulse_ts;
+ /* needed for ath_dbg() */
+ struct ath_hw *ah;
const struct radar_detector_specs *radar_spec;
struct list_head channel_detectors;
@@ -92,10 +94,10 @@ struct dfs_pattern_detector {
*/
#if defined(CONFIG_ATH9K_DFS_CERTIFIED)
extern struct dfs_pattern_detector *
-dfs_pattern_detector_init(enum nl80211_dfs_regions region);
+dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region);
#else
static inline struct dfs_pattern_detector *
-dfs_pattern_detector_init(enum nl80211_dfs_regions region)
+dfs_pattern_detector_init(struct ath_hw *ah, enum nl80211_dfs_regions region)
{
return NULL;
}
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
index 5e48c5515b8c..5ba4b6fe37c0 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
@@ -23,28 +23,6 @@
#include "dfs_debug.h"
/**
- * struct pri_sequence - sequence of pulses matching one PRI
- * @head: list_head
- * @pri: pulse repetition interval (PRI) in usecs
- * @dur: duration of sequence in usecs
- * @count: number of pulses in this sequence
- * @count_falses: number of not matching pulses in this sequence
- * @first_ts: time stamp of first pulse in usecs
- * @last_ts: time stamp of last pulse in usecs
- * @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur)
- */
-struct pri_sequence {
- struct list_head head;
- u32 pri;
- u32 dur;
- u32 count;
- u32 count_falses;
- u64 first_ts;
- u64 last_ts;
- u64 deadline_ts;
-};
-
-/**
* struct pulse_elem - elements in pulse queue
* @ts: time stamp in usecs
*/
@@ -393,8 +371,8 @@ static void pri_detector_exit(struct pri_detector *de)
kfree(de);
}
-static bool pri_detector_add_pulse(struct pri_detector *de,
- struct pulse_event *event)
+static struct pri_sequence *pri_detector_add_pulse(struct pri_detector *de,
+ struct pulse_event *event)
{
u32 max_updated_seq;
struct pri_sequence *ps;
@@ -403,38 +381,33 @@ static bool pri_detector_add_pulse(struct pri_detector *de,
/* ignore pulses not within width range */
if ((rs->width_min > event->width) || (rs->width_max < event->width))
- return false;
+ return NULL;
if ((ts - de->last_ts) < rs->max_pri_tolerance)
/* if delta to last pulse is too short, don't use this pulse */
- return false;
+ return NULL;
de->last_ts = ts;
max_updated_seq = pseq_handler_add_to_existing_seqs(de, ts);
if (!pseq_handler_create_sequences(de, ts, max_updated_seq)) {
- pr_err("failed to create pulse sequences\n");
pri_detector_reset(de, ts);
return false;
}
ps = pseq_handler_check_detection(de);
- if (ps != NULL) {
- pr_info("DFS: radar found: pri=%d, count=%d, count_false=%d\n",
- ps->pri, ps->count, ps->count_falses);
- pri_detector_reset(de, ts);
- return true;
- }
- pulse_queue_enqueue(de, ts);
- return false;
+ if (ps == NULL)
+ pulse_queue_enqueue(de, ts);
+
+ return ps;
}
-struct pri_detector *
-pri_detector_init(const struct radar_detector_specs *rs)
+struct pri_detector *pri_detector_init(const struct radar_detector_specs *rs)
{
struct pri_detector *de;
- de = kzalloc(sizeof(*de), GFP_KERNEL);
+
+ de = kzalloc(sizeof(*de), GFP_ATOMIC);
if (de == NULL)
return NULL;
de->exit = pri_detector_exit;
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h
index 81cde9f28e44..723962d1abc6 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h
+++ b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h
@@ -20,9 +20,31 @@
#include <linux/list.h>
/**
+ * struct pri_sequence - sequence of pulses matching one PRI
+ * @head: list_head
+ * @pri: pulse repetition interval (PRI) in usecs
+ * @dur: duration of sequence in usecs
+ * @count: number of pulses in this sequence
+ * @count_falses: number of not matching pulses in this sequence
+ * @first_ts: time stamp of first pulse in usecs
+ * @last_ts: time stamp of last pulse in usecs
+ * @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur)
+ */
+struct pri_sequence {
+ struct list_head head;
+ u32 pri;
+ u32 dur;
+ u32 count;
+ u32 count_falses;
+ u64 first_ts;
+ u64 last_ts;
+ u64 deadline_ts;
+};
+
+/**
* struct pri_detector - PRI detector element for a dedicated radar type
* @exit(): destructor
- * @add_pulse(): add pulse event, returns true if pattern was detected
+ * @add_pulse(): add pulse event, returns pri_sequence if pattern was detected
* @reset(): clear states and reset to given time stamp
* @rs: detector specs for this detector element
* @last_ts: last pulse time stamp considered for this element in usecs
@@ -34,7 +56,8 @@
*/
struct pri_detector {
void (*exit) (struct pri_detector *de);
- bool (*add_pulse)(struct pri_detector *de, struct pulse_event *e);
+ struct pri_sequence *
+ (*add_pulse)(struct pri_detector *de, struct pulse_event *e);
void (*reset) (struct pri_detector *de, u64 ts);
/* private: internal use only */
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index d0ce1f5bba10..f13f458dd656 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -308,7 +308,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv,
while(skb) {
hdr = (struct ieee80211_hdr *) skb->data;
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len > padpos) {
if (skb_headroom(skb) < padsize) {
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index a8016d70088a..0743a47cef8f 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -190,7 +190,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
{
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *channel = priv->hw->conf.channel;
+ struct ieee80211_channel *channel = priv->hw->conf.chandef.chan;
struct ath9k_hw_cal_data *caldata = NULL;
enum htc_phymode mode;
__be16 htc_mode;
@@ -250,7 +250,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
bool fastcc;
- struct ieee80211_channel *channel = hw->conf.channel;
+ struct ieee80211_channel *channel = hw->conf.chandef.chan;
struct ath9k_hw_cal_data *caldata = NULL;
enum htc_phymode mode;
__be16 htc_mode;
@@ -602,7 +602,7 @@ static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv,
u32 caps = 0;
int i, j;
- sband = priv->hw->wiphy->bands[priv->hw->conf.channel->band];
+ sband = priv->hw->wiphy->bands[priv->hw->conf.chandef.chan->band];
for (i = 0, j = 0; i < sband->n_bitrates; i++) {
if (sta->supp_rates[sband->band] & BIT(i)) {
@@ -866,7 +866,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw,
hdr = (struct ieee80211_hdr *) skb->data;
/* Add the padding after the header if this is not already done */
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len > padpos) {
if (skb_headroom(skb) < padsize) {
@@ -904,7 +904,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
struct ath9k_channel *init_channel;
int ret = 0;
enum htc_phymode mode;
@@ -1193,15 +1193,17 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
}
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) {
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&hw->conf.chandef);
int pos = curchan->hw_value;
ath_dbg(common, CONFIG, "Set channel: %d MHz\n",
curchan->center_freq);
ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
- hw->conf.channel,
- hw->conf.channel_type);
+ hw->conf.chandef.chan,
+ channel_type);
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
ath_err(common, "Unable to set channel\n");
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index bd8251c1c749..6bd0e92ea2aa 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -490,7 +490,7 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv,
if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI)
rate->flags |= IEEE80211_TX_RC_SHORT_GI;
} else {
- if (cur_conf->channel->band == IEEE80211_BAND_5GHZ)
+ if (cur_conf->chandef.chan->band == IEEE80211_BAND_5GHZ)
rate->idx += 4; /* No CCK rates */
}
@@ -939,7 +939,7 @@ static void ath9k_process_rate(struct ieee80211_hw *hw,
return;
}
- band = hw->conf.channel->band;
+ band = hw->conf.chandef.chan->band;
sband = hw->wiphy->bands[band];
for (i = 0; i < sband->n_bitrates; i++) {
@@ -966,7 +966,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
struct sk_buff *skb = rxbuf->skb;
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ath_htc_rx_status *rxstatus;
- int hdrlen, padpos, padsize;
+ int hdrlen, padsize;
int last_rssi = ATH_RSSI_DUMMY_MARKER;
__le16 fc;
@@ -996,11 +996,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
fc = hdr->frame_control;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- padpos = ath9k_cmn_padpos(fc);
-
- padsize = padpos & 3;
- if (padsize && skb->len >= padpos+padsize+FCS_LEN) {
- memmove(skb->data + padsize, skb->data, padpos);
+ padsize = hdrlen & 3;
+ if (padsize && skb->len >= hdrlen+padsize+FCS_LEN) {
+ memmove(skb->data + padsize, skb->data, hdrlen);
skb_pull(skb, padsize);
}
@@ -1082,8 +1080,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
}
rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
- rx_status->band = hw->conf.channel->band;
- rx_status->freq = hw->conf.channel->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
rx_status->antenna = rxbuf->rxstatus.rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_END;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 3473a797651a..7f25da8444fe 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -139,7 +139,7 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
clockrate = 117;
else if (!ah->curchan) /* should really check for CCK instead */
clockrate = ATH9K_CLOCK_RATE_CCK;
- else if (conf->channel->band == IEEE80211_BAND_2GHZ)
+ else if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ)
clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
@@ -1100,7 +1100,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
}
/* As defined by IEEE 802.11-2007 17.3.8.6 */
- acktimeout = slottime + sifstime + 3 * ah->coverage_class + ack_offset;
+ slottime += 3 * ah->coverage_class;
+ acktimeout = slottime + sifstime + ack_offset;
ctstimeout = acktimeout;
/*
@@ -1110,7 +1111,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
* BA frames in some implementations, but it has been found to fix ACK
* timeout issues in other cases as well.
*/
- if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ &&
+ if (conf->chandef.chan &&
+ conf->chandef.chan->band == IEEE80211_BAND_2GHZ &&
!IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) {
acktimeout += 64 - sifstime - ah->slottime;
ctstimeout += 48 - sifstime - ah->slottime;
@@ -1697,12 +1699,11 @@ static void ath9k_hw_reset_opmode(struct ath_hw *ah,
ENABLE_REGWRITE_BUFFER(ah);
- REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
- REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
- | macStaId1
+ REG_RMW(ah, AR_STA_ID1, macStaId1
| AR_STA_ID1_RTS_USE_DEF
| (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
- | ah->sta_id1_defaults);
+ | ah->sta_id1_defaults,
+ ~AR_STA_ID1_SADH_MASK);
ath_hw_setbssidmask(common);
REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
ath9k_hw_write_associd(ah);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 30e62d92d46d..ae3034374bc4 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -847,14 +847,7 @@ struct ath_hw {
struct ath_hw_ops ops;
/* Used to program the radio on non single-chip devices */
- u32 *analogBank0Data;
- u32 *analogBank1Data;
- u32 *analogBank2Data;
- u32 *analogBank3Data;
u32 *analogBank6Data;
- u32 *analogBank6TPCData;
- u32 *analogBank7Data;
- u32 *bank6Temp;
int coverage_class;
u32 slottime;
@@ -885,14 +878,8 @@ struct ath_hw {
struct ar5416IniArray iniModes;
struct ar5416IniArray iniCommon;
- struct ar5416IniArray iniBank0;
struct ar5416IniArray iniBB_RfGain;
- struct ar5416IniArray iniBank1;
- struct ar5416IniArray iniBank2;
- struct ar5416IniArray iniBank3;
struct ar5416IniArray iniBank6;
- struct ar5416IniArray iniBank6TPC;
- struct ar5416IniArray iniBank7;
struct ar5416IniArray iniAddac;
struct ar5416IniArray iniPcieSerdes;
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 3be2eb0da84a..0237b2868961 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -577,7 +577,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
atomic_set(&ah->intr_ref_cnt, -1);
sc->sc_ah = ah;
- sc->dfs_detector = dfs_pattern_detector_init(NL80211_DFS_UNSET);
+ sc->dfs_detector = dfs_pattern_detector_init(ah, NL80211_DFS_UNSET);
if (!pdata) {
ah->ah_flags |= AH_USE_EEPROM;
@@ -766,7 +766,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
IEEE80211_HW_SPECTRUM_MGMT |
- IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+ IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+ IEEE80211_HW_SUPPORTS_RC_TABLE;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 7fdac6c7b3ea..849259b07370 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -214,7 +214,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
memset(tx_info, 0, sizeof(*tx_info));
- tx_info->band = hw->conf.channel->band;
+ tx_info->band = hw->conf.chandef.chan->band;
tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
tx_info->control.rates[0].idx = 0;
tx_info->control.rates[0].count = 1;
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 811007ec07a7..498fee04afa0 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -615,6 +615,14 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
rs->rs_status |= ATH9K_RXERR_DECRYPT;
else if (ads.ds_rxstatus8 & AR_MichaelErr)
rs->rs_status |= ATH9K_RXERR_MIC;
+ } else {
+ if (ads.ds_rxstatus8 &
+ (AR_CRCErr | AR_PHYErr | AR_DecryptCRCErr | AR_MichaelErr))
+ rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;
+
+ /* Only up to MCS16 supported, everything above is invalid */
+ if (rs->rs_rate >= 0x90)
+ rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;
}
if (ads.ds_rxstatus8 & AR_KeyMiss)
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 1ff817061ebc..5865f92998e1 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -183,6 +183,7 @@ struct ath_htc_rx_status {
#define ATH9K_RXERR_DECRYPT 0x08
#define ATH9K_RXERR_MIC 0x10
#define ATH9K_RXERR_KEYMISS 0x20
+#define ATH9K_RXERR_CORRUPT_DESC 0x40
#define ATH9K_RX_MORE 0x01
#define ATH9K_RX_MORE_AGGR 0x02
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 1bf52c88004a..6963862a1872 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -589,7 +589,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
struct ath9k_channel *init_channel;
int r;
@@ -839,10 +839,14 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
struct ath9k_vif_iter_data *iter_data = data;
int i;
- if (iter_data->hw_macaddr)
+ if (iter_data->has_hw_macaddr) {
for (i = 0; i < ETH_ALEN; i++)
iter_data->mask[i] &=
~(iter_data->hw_macaddr[i] ^ mac[i]);
+ } else {
+ memcpy(iter_data->hw_macaddr, mac, ETH_ALEN);
+ iter_data->has_hw_macaddr = true;
+ }
switch (vif->type) {
case NL80211_IFTYPE_AP:
@@ -891,7 +895,6 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
* together with the BSSID mask when matching addresses.
*/
memset(iter_data, 0, sizeof(*iter_data));
- iter_data->hw_macaddr = common->macaddr;
memset(&iter_data->mask, 0xff, ETH_ALEN);
if (vif)
@@ -901,6 +904,8 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
ieee80211_iterate_active_interfaces_atomic(
sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
ath9k_vif_iter, iter_data);
+
+ memcpy(common->macaddr, iter_data->hw_macaddr, ETH_ALEN);
}
/* Called with sc->mutex held. */
@@ -1188,7 +1193,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
}
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
- struct ieee80211_channel *curchan = hw->conf.channel;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&conf->chandef);
int pos = curchan->hw_value;
int old_pos = -1;
unsigned long flags;
@@ -1197,7 +1204,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
old_pos = ah->curchan - &ah->channels[0];
ath_dbg(common, CONFIG, "Set channel: %d MHz type: %d\n",
- curchan->center_freq, conf->channel_type);
+ curchan->center_freq, channel_type);
/* update survey stats for the old channel before switching */
spin_lock_irqsave(&common->cc_lock, flags);
@@ -1212,7 +1219,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
ath9k_hw_getnf(ah, ah->curchan);
ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
- curchan, conf->channel_type);
+ curchan, channel_type);
/*
* If the operating channel changes, change the survey in-use flags
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 96ac433ba7f6..aa4d368d8d3d 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -814,7 +814,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
* So, set fourth rate in series to be same as third one for
* above conditions.
*/
- if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
+ if ((sc->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) &&
(conf_is_ht(&sc->hw->conf))) {
u8 dot11rate = rate_table->info[rix].dot11rate;
u8 phy = rate_table->info[rix].phy;
@@ -1328,7 +1328,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG,
"Operating HT Bandwidth changed to: %d\n",
- sc->hw->conf.channel_type);
+ cfg80211_get_chandef_type(&sc->hw->conf.chandef));
}
}
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index ee7ca5aecdb0..8be2b5d8c155 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -124,13 +124,13 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc,
SKB_CB_ATHBUF(skb) = bf;
ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype);
- skb_queue_tail(&rx_edma->rx_fifo, skb);
+ __skb_queue_tail(&rx_edma->rx_fifo, skb);
return true;
}
static void ath_rx_addbuffer_edma(struct ath_softc *sc,
- enum ath9k_rx_qtype qtype, int size)
+ enum ath9k_rx_qtype qtype)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_buf *bf, *tbf;
@@ -155,7 +155,7 @@ static void ath_rx_remove_buffer(struct ath_softc *sc,
rx_edma = &sc->rx.rx_edma[qtype];
- while ((skb = skb_dequeue(&rx_edma->rx_fifo)) != NULL) {
+ while ((skb = __skb_dequeue(&rx_edma->rx_fifo)) != NULL) {
bf = SKB_CB_ATHBUF(skb);
BUG_ON(!bf);
list_add_tail(&bf->list, &sc->rx.rxbuf);
@@ -250,15 +250,9 @@ rx_init_fail:
static void ath_edma_start_recv(struct ath_softc *sc)
{
ath9k_hw_rxena(sc->sc_ah);
-
- ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP,
- sc->rx.rx_edma[ATH9K_RX_QUEUE_HP].rx_fifo_hwsize);
-
- ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
- sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
-
+ ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP);
+ ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP);
ath_opmode_init(sc);
-
ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
}
@@ -280,49 +274,47 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
sc->sc_ah->caps.rx_status_len;
- if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
return ath_rx_edma_init(sc, nbufs);
- } else {
- ath_dbg(common, CONFIG, "cachelsz %u rxbufsize %u\n",
- common->cachelsz, common->rx_bufsize);
- /* Initialize rx descriptors */
+ ath_dbg(common, CONFIG, "cachelsz %u rxbufsize %u\n",
+ common->cachelsz, common->rx_bufsize);
- error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
- "rx", nbufs, 1, 0);
- if (error != 0) {
- ath_err(common,
- "failed to allocate rx descriptors: %d\n",
- error);
+ /* Initialize rx descriptors */
+
+ error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
+ "rx", nbufs, 1, 0);
+ if (error != 0) {
+ ath_err(common,
+ "failed to allocate rx descriptors: %d\n",
+ error);
+ goto err;
+ }
+
+ list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+ skb = ath_rxbuf_alloc(common, common->rx_bufsize,
+ GFP_KERNEL);
+ if (skb == NULL) {
+ error = -ENOMEM;
goto err;
}
- list_for_each_entry(bf, &sc->rx.rxbuf, list) {
- skb = ath_rxbuf_alloc(common, common->rx_bufsize,
- GFP_KERNEL);
- if (skb == NULL) {
- error = -ENOMEM;
- goto err;
- }
-
- bf->bf_mpdu = skb;
- bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
- common->rx_bufsize,
- DMA_FROM_DEVICE);
- if (unlikely(dma_mapping_error(sc->dev,
- bf->bf_buf_addr))) {
- dev_kfree_skb_any(skb);
- bf->bf_mpdu = NULL;
- bf->bf_buf_addr = 0;
- ath_err(common,
- "dma_mapping_error() on RX init\n");
- error = -ENOMEM;
- goto err;
- }
+ bf->bf_mpdu = skb;
+ bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+ common->rx_bufsize,
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(sc->dev,
+ bf->bf_buf_addr))) {
+ dev_kfree_skb_any(skb);
+ bf->bf_mpdu = NULL;
+ bf->bf_buf_addr = 0;
+ ath_err(common,
+ "dma_mapping_error() on RX init\n");
+ error = -ENOMEM;
+ goto err;
}
- sc->rx.rxlink = NULL;
}
-
+ sc->rx.rxlink = NULL;
err:
if (error)
ath_rx_cleanup(sc);
@@ -340,17 +332,17 @@ void ath_rx_cleanup(struct ath_softc *sc)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
ath_rx_edma_cleanup(sc);
return;
- } else {
- list_for_each_entry(bf, &sc->rx.rxbuf, list) {
- skb = bf->bf_mpdu;
- if (skb) {
- dma_unmap_single(sc->dev, bf->bf_buf_addr,
- common->rx_bufsize,
- DMA_FROM_DEVICE);
- dev_kfree_skb(skb);
- bf->bf_buf_addr = 0;
- bf->bf_mpdu = NULL;
- }
+ }
+
+ list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+ skb = bf->bf_mpdu;
+ if (skb) {
+ dma_unmap_single(sc->dev, bf->bf_buf_addr,
+ common->rx_bufsize,
+ DMA_FROM_DEVICE);
+ dev_kfree_skb(skb);
+ bf->bf_buf_addr = 0;
+ bf->bf_mpdu = NULL;
}
}
}
@@ -727,6 +719,13 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
ret = ath9k_hw_rxprocdesc(ah, tds, &trs);
if (ret == -EINPROGRESS)
return NULL;
+
+ /*
+ * mark descriptor as zero-length and set the 'more'
+ * flag to ensure that both buffers get discarded
+ */
+ rs->rs_datalen = 0;
+ rs->rs_more = true;
}
list_del(&bf->list);
@@ -863,7 +862,7 @@ static int ath9k_process_rate(struct ath_common *common,
unsigned int i = 0;
struct ath_softc __maybe_unused *sc = common->priv;
- band = hw->conf.channel->band;
+ band = hw->conf.chandef.chan->band;
sband = hw->wiphy->bands[band];
if (rx_stats->rs_rate & 0x80) {
@@ -933,14 +932,20 @@ static void ath9k_process_rssi(struct ath_common *common,
* up the frame up to let mac80211 handle the actual error case, be it no
* decryption key or real decryption error. This let us keep statistics there.
*/
-static int ath9k_rx_skb_preprocess(struct ath_common *common,
- struct ieee80211_hw *hw,
+static int ath9k_rx_skb_preprocess(struct ath_softc *sc,
struct ieee80211_hdr *hdr,
struct ath_rx_status *rx_stats,
struct ieee80211_rx_status *rx_status,
bool *decrypt_error)
{
- struct ath_hw *ah = common->ah;
+ struct ieee80211_hw *hw = sc->hw;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ bool discard_current = sc->rx.discard_next;
+
+ sc->rx.discard_next = rx_stats->rs_more;
+ if (discard_current)
+ return -EINVAL;
/*
* everything but the rate is checked here, the rate check is done
@@ -958,14 +963,15 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
if (ath9k_process_rate(common, hw, rx_stats, rx_status))
return -EINVAL;
- rx_status->band = hw->conf.channel->band;
- rx_status->freq = hw->conf.channel->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
rx_status->signal = ah->noise + rx_stats->rs_rssi;
rx_status->antenna = rx_stats->rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_END;
if (rx_stats->rs_moreaggr)
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+ sc->rx.discard_next = false;
return 0;
}
@@ -985,7 +991,7 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
hdr = (struct ieee80211_hdr *) skb->data;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
fc = hdr->frame_control;
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(fc);
/* The MAC header is padded to have 32-bit boundary if the
* packet payload is non-zero. The general calculation for
@@ -1166,6 +1172,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
u64 tsf = 0;
u32 tsf_lower = 0;
unsigned long flags;
+ dma_addr_t new_buf_addr;
if (edma)
dma_type = DMA_BIDIRECTIONAL;
@@ -1242,8 +1249,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
}
}
- retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
- rxs, &decrypt_error);
+ retval = ath9k_rx_skb_preprocess(sc, hdr, &rs, rxs,
+ &decrypt_error);
if (retval)
goto requeue_drop_frag;
@@ -1264,10 +1271,20 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
goto requeue_drop_frag;
}
+ /* We will now give hardware our shiny new allocated skb */
+ new_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
+ common->rx_bufsize, dma_type);
+ if (unlikely(dma_mapping_error(sc->dev, new_buf_addr))) {
+ dev_kfree_skb_any(requeue_skb);
+ goto requeue_drop_frag;
+ }
+
/* Unmap the frame */
dma_unmap_single(sc->dev, bf->bf_buf_addr,
- common->rx_bufsize,
- dma_type);
+ common->rx_bufsize, dma_type);
+
+ bf->bf_mpdu = requeue_skb;
+ bf->bf_buf_addr = new_buf_addr;
skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len);
if (ah->caps.rx_status_len)
@@ -1277,21 +1294,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
rxs, decrypt_error);
- /* We will now give hardware our shiny new allocated skb */
- bf->bf_mpdu = requeue_skb;
- bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
- common->rx_bufsize,
- dma_type);
- if (unlikely(dma_mapping_error(sc->dev,
- bf->bf_buf_addr))) {
- dev_kfree_skb_any(requeue_skb);
- bf->bf_mpdu = NULL;
- bf->bf_buf_addr = 0;
- ath_err(common, "dma_mapping_error() on RX\n");
- ieee80211_rx(hw, skb);
- break;
- }
-
if (rs.rs_more) {
RX_STAT_INC(rx_frags);
/*
@@ -1309,6 +1311,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
sc->rx.frag = skb;
goto requeue;
}
+ if (rs.rs_status & ATH9K_RXERR_CORRUPT_DESC)
+ goto requeue_drop_frag;
if (sc->rx.frag) {
int space = skb->len - skb_tailroom(hdr_skb);
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 5929850649f0..5c4ab5026dca 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -1493,9 +1493,6 @@ enum {
#define AR9271_RADIO_RF_RST 0x20
#define AR9271_GATE_MAC_CTL 0x4000
-#define AR_STA_ID0 0x8000
-#define AR_STA_ID1 0x8004
-#define AR_STA_ID1_SADH_MASK 0x0000FFFF
#define AR_STA_ID1_STA_AP 0x00010000
#define AR_STA_ID1_ADHOC 0x00020000
#define AR_STA_ID1_PWR_SAV 0x00040000
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 89a64411b82e..eab0fcb7ded6 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -157,6 +157,13 @@ static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
seqno << IEEE80211_SEQ_SEQ_SHIFT);
}
+static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ath_buf *bf)
+{
+ ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
+ ARRAY_SIZE(bf->rates));
+}
+
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
struct ath_txq *txq = tid->ac->txq;
@@ -189,6 +196,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
sendbar = true;
} else {
+ ath_set_rates(tid->an->vif, tid->an->sta, bf);
ath_tx_send_normal(sc, txq, NULL, skb);
}
}
@@ -407,7 +415,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
tx_info = IEEE80211_SKB_CB(skb);
- memcpy(rates, tx_info->control.rates, sizeof(rates));
+ memcpy(rates, bf->rates, sizeof(rates));
retries = ts->ts_longretry + 1;
for (i = 0; i < ts->ts_rateindex; i++)
@@ -516,8 +524,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* not a holding desc.
*/
INIT_LIST_HEAD(&bf_head);
- if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
- bf_next != NULL || !bf_last->bf_stale)
+ if (bf_next != NULL || !bf_last->bf_stale)
list_move_tail(&bf->list, &bf_head);
if (!txpending || (tid->state & AGGR_CLEANUP)) {
@@ -537,8 +544,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
!txfail);
} else {
/* retry the un-acked ones */
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
- bf->bf_next == NULL && bf_last->bf_stale) {
+ if (bf->bf_next == NULL && bf_last->bf_stale) {
struct ath_buf *tbf;
tbf = ath_clone_txbuf(sc, bf_last);
@@ -738,8 +744,6 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
bool first_subfrm)
{
#define FIRST_DESC_NDELIMS 60
- struct sk_buff *skb = bf->bf_mpdu;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
u32 nsymbits, nsymbols;
u16 minlen;
u8 flags, rix;
@@ -780,8 +784,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
if (tid->an->mpdudensity == 0)
return ndelim;
- rix = tx_info->control.rates[0].idx;
- flags = tx_info->control.rates[0].flags;
+ rix = bf->rates[0].idx;
+ flags = bf->rates[0].flags;
width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
@@ -860,6 +864,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
bf_first = bf;
if (!rl) {
+ ath_set_rates(tid->an->vif, tid->an->sta, bf);
aggr_limit = ath_lookup_rate(sc, bf, tid);
rl = 1;
}
@@ -1000,14 +1005,14 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
skb = bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
- rates = tx_info->control.rates;
+ rates = bf->rates;
hdr = (struct ieee80211_hdr *)skb->data;
/* set dur_update_en for l-sig computation except for PS-Poll frames */
info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
info->rtscts_rate = fi->rtscts_rate;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < ARRAY_SIZE(bf->rates); i++) {
bool is_40, is_sgi, is_sp;
int phy;
@@ -1745,6 +1750,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
return;
}
+ ath_set_rates(tid->an->vif, tid->an->sta, bf);
bf->bf_state.bf_type = BUF_AMPDU;
INIT_LIST_HEAD(&bf_head);
list_add(&bf->list, &bf_head);
@@ -1894,49 +1900,6 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
return bf;
}
-/* FIXME: tx power */
-static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
- struct ath_tx_control *txctl)
-{
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ath_atx_tid *tid = NULL;
- struct ath_buf *bf;
- u8 tidno;
-
- if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) {
- tidno = ieee80211_get_qos_ctl(hdr)[0] &
- IEEE80211_QOS_CTL_TID_MASK;
- tid = ATH_AN_2_TID(txctl->an, tidno);
-
- WARN_ON(tid->ac->txq != txctl->txq);
- }
-
- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
- /*
- * Try aggregation if it's a unicast data frame
- * and the destination is HT capable.
- */
- ath_tx_send_ampdu(sc, tid, skb, txctl);
- } else {
- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
- if (!bf) {
- if (txctl->paprd)
- dev_kfree_skb_any(skb);
- else
- ieee80211_free_txskb(sc->hw, skb);
- return;
- }
-
- bf->bf_state.bfs_paprd = txctl->paprd;
-
- if (txctl->paprd)
- bf->bf_state.bfs_paprd_timestamp = jiffies;
-
- ath_tx_send_normal(sc, txctl->txq, tid, skb);
- }
-}
-
/* Upon failure caller should free skb */
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_tx_control *txctl)
@@ -1947,8 +1910,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_vif *vif = info->control.vif;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
+ struct ath_atx_tid *tid = NULL;
+ struct ath_buf *bf;
int padpos, padsize;
int frmlen = skb->len + FCS_LEN;
+ u8 tidno;
int q;
/* NOTE: sta can be NULL according to net/mac80211.h */
@@ -1971,7 +1937,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
}
/* Add the padding after the header if this is not already done */
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len > padpos) {
if (skb_headroom(skb) < padsize)
@@ -2004,8 +1970,41 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
txq->stopped = true;
}
- ath_tx_start_dma(sc, skb, txctl);
+ if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) {
+ tidno = ieee80211_get_qos_ctl(hdr)[0] &
+ IEEE80211_QOS_CTL_TID_MASK;
+ tid = ATH_AN_2_TID(txctl->an, tidno);
+
+ WARN_ON(tid->ac->txq != txctl->txq);
+ }
+
+ if ((info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
+ /*
+ * Try aggregation if it's a unicast data frame
+ * and the destination is HT capable.
+ */
+ ath_tx_send_ampdu(sc, tid, skb, txctl);
+ goto out;
+ }
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+ if (!bf) {
+ if (txctl->paprd)
+ dev_kfree_skb_any(skb);
+ else
+ ieee80211_free_txskb(sc->hw, skb);
+ goto out;
+ }
+
+ bf->bf_state.bfs_paprd = txctl->paprd;
+
+ if (txctl->paprd)
+ bf->bf_state.bfs_paprd_timestamp = jiffies;
+
+ ath_set_rates(vif, sta, bf);
+ ath_tx_send_normal(sc, txctl->txq, tid, skb);
+
+out:
ath_txq_unlock(sc, txq);
return 0;
@@ -2033,7 +2032,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
/* Frame was ACKed */
tx_info->flags |= IEEE80211_TX_STAT_ACK;
- padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len>padpos+padsize) {
/*
@@ -2264,6 +2263,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
struct ath_txq *txq;
struct ath_buf *bf, *lastbf;
struct list_head bf_head;
+ struct list_head *fifo_list;
int status;
for (;;) {
@@ -2291,20 +2291,24 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
TX_STAT_INC(txq->axq_qnum, txprocdesc);
- if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+ fifo_list = &txq->txq_fifo[txq->txq_tailidx];
+ if (list_empty(fifo_list)) {
ath_txq_unlock(sc, txq);
return;
}
- bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
- struct ath_buf, list);
+ bf = list_first_entry(fifo_list, struct ath_buf, list);
+ if (bf->bf_stale) {
+ list_del(&bf->list);
+ ath_tx_return_buffer(sc, bf);
+ bf = list_first_entry(fifo_list, struct ath_buf, list);
+ }
+
lastbf = bf->bf_lastbf;
INIT_LIST_HEAD(&bf_head);
- list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
- &lastbf->list);
-
- if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+ if (list_is_last(&lastbf->list, fifo_list)) {
+ list_splice_tail_init(fifo_list, &bf_head);
INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
if (!list_empty(&txq->axq_q)) {
@@ -2315,6 +2319,11 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
list_splice_tail_init(&txq->axq_q, &bf_q);
ath_tx_txqaddbuf(sc, txq, &bf_q, true);
}
+ } else {
+ lastbf->bf_stale = true;
+ if (bf != lastbf)
+ list_cut_position(&bf_head, fifo_list,
+ lastbf->list.prev);
}
ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
index 40109be81f7c..3d70cd277fd7 100644
--- a/drivers/net/wireless/ath/carl9170/debug.c
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -654,8 +654,8 @@ static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
goto out;
case 'P':
- err = carl9170_set_channel(ar, ar->hw->conf.channel,
- ar->hw->conf.channel_type);
+ err = carl9170_set_channel(ar, ar->hw->conf.chandef.chan,
+ cfg80211_get_chandef_type(&ar->hw->conf.chandef));
if (err < 0)
count = err;
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
index 24d75ab94f0d..a2f005703c04 100644
--- a/drivers/net/wireless/ath/carl9170/mac.c
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -48,7 +48,7 @@ int carl9170_set_dyn_sifs_ack(struct ar9170 *ar)
if (conf_is_ht40(&ar->hw->conf))
val = 0x010a;
else {
- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
val = 0x105;
else
val = 0x104;
@@ -66,7 +66,7 @@ int carl9170_set_rts_cts_rate(struct ar9170 *ar)
rts_rate = 0x1da;
cts_rate = 0x10a;
} else {
- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) {
/* 11 mbit CCK */
rts_rate = 033;
cts_rate = 003;
@@ -93,7 +93,7 @@ int carl9170_set_slot_time(struct ar9170 *ar)
return 0;
}
- if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) ||
+ if ((ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ) ||
vif->bss_conf.use_short_slot)
slottime = 9;
@@ -120,7 +120,7 @@ int carl9170_set_mac_rates(struct ar9170 *ar)
basic |= (vif->bss_conf.basic_rates & 0xff0) << 4;
rcu_read_unlock();
- if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ)
mandatory = 0xff00; /* OFDM 6/9/12/18/24/36/48/54 */
else
mandatory = 0xff0f; /* OFDM (6/9../54) + CCK (1/2/5.5/11) */
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 699c557bc2c7..e9010a481dfd 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -929,6 +929,9 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&hw->conf.chandef);
+
/* adjust slot time for 5 GHz */
err = carl9170_set_slot_time(ar);
if (err)
@@ -938,8 +941,8 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
if (err)
goto out;
- err = carl9170_set_channel(ar, hw->conf.channel,
- hw->conf.channel_type);
+ err = carl9170_set_channel(ar, hw->conf.chandef.chan,
+ channel_type);
if (err)
goto out;
@@ -957,7 +960,7 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_POWER) {
- err = carl9170_set_mac_tpc(ar, ar->hw->conf.channel);
+ err = carl9170_set_mac_tpc(ar, ar->hw->conf.chandef.chan);
if (err)
goto out;
}
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index 07f82234c860..ab4ee7d39ad3 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -1331,7 +1331,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
* CTL_ETSI for 2GHz and CTL_FCC for 5GHz.
*/
ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory,
- ar->hw->conf.channel->band);
+ ar->hw->conf.chandef.chan->band);
/* ctl group not found - either invalid band (NO_CTL) or ww roaming */
if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL)
@@ -1341,7 +1341,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
/* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */
return;
- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) {
modes = mode_list_2ghz;
nr_modes = ARRAY_SIZE(mode_list_2ghz);
} else {
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c
index 39e8a590d7fc..eae9abf540a7 100644
--- a/drivers/net/wireless/ath/hw.c
+++ b/drivers/net/wireless/ath/hw.c
@@ -118,6 +118,12 @@
void ath_hw_setbssidmask(struct ath_common *common)
{
void *ah = common->ah;
+ u32 id1;
+
+ REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
+ id1 = REG_READ(ah, AR_STA_ID1) & ~AR_STA_ID1_SADH_MASK;
+ id1 |= get_unaligned_le16(common->macaddr + 4);
+ REG_WRITE(ah, AR_STA_ID1, id1);
REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask));
REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4));
diff --git a/drivers/net/wireless/ath/reg.h b/drivers/net/wireless/ath/reg.h
index 298e53f3fa48..3ad4c774bd22 100644
--- a/drivers/net/wireless/ath/reg.h
+++ b/drivers/net/wireless/ath/reg.h
@@ -23,6 +23,10 @@
#define AR_MIBC_CMC 0x00000004
#define AR_MIBC_MCS 0x00000008
+#define AR_STA_ID0 0x8000
+#define AR_STA_ID1 0x8004
+#define AR_STA_ID1_SADH_MASK 0x0000ffff
+
/*
* BSSID mask registers. See ath_hw_set_bssid_mask()
* for detailed documentation about these registers.
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 79d4e3271b00..797024507c71 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -191,8 +191,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
* - Phy info
*/
static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
- struct sk_buff *skb,
- volatile struct vring_rx_desc *d)
+ struct sk_buff *skb)
{
struct wireless_dev *wdev = wil->wdev;
struct wil6210_rtap {
@@ -216,6 +215,7 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
__le16 vendor_skip;
u8 vendor_data[0];
} __packed;
+ struct vring_rx_desc *d = wil_skb_rxdesc(skb);
struct wil6210_rtap_vendor *rtap_vendor;
int rtap_len = sizeof(struct wil6210_rtap);
int phy_length = 0; /* phy info header size, bytes */
@@ -312,6 +312,8 @@ static void wil_swap_ethaddr(void *data)
/**
* reap 1 frame from @swhead
*
+ * Rx descriptor copied to skb->cb
+ *
* Safe to call from IRQ
*/
static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
@@ -320,12 +322,15 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
struct device *dev = wil_to_dev(wil);
struct net_device *ndev = wil_to_ndev(wil);
volatile struct vring_rx_desc *d;
+ struct vring_rx_desc *d1;
struct sk_buff *skb;
dma_addr_t pa;
unsigned int sz = RX_BUF_LEN;
u8 ftype;
u8 ds_bits;
+ BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb));
+
if (wil_vring_is_empty(vring))
return NULL;
@@ -340,11 +345,14 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE);
skb_trim(skb, d->dma.length);
- wil->stats.last_mcs_rx = wil_rxdesc_mcs(d);
+ d1 = wil_skb_rxdesc(skb);
+ *d1 = *d;
+
+ wil->stats.last_mcs_rx = wil_rxdesc_mcs(d1);
/* use radiotap header only if required */
if (ndev->type == ARPHRD_IEEE80211_RADIOTAP)
- wil_rx_add_radiotap_header(wil, skb, d);
+ wil_rx_add_radiotap_header(wil, skb);
wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length);
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4,
@@ -360,7 +368,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
* Driver should recognize it by frame type, that is found
* in Rx descriptor. If type is not data, it is 802.11 frame as is
*/
- ftype = wil_rxdesc_ftype(d) << 2;
+ ftype = wil_rxdesc_ftype(d1) << 2;
if (ftype != IEEE80211_FTYPE_DATA) {
wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype);
/* TODO: process it */
@@ -375,7 +383,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
return NULL;
}
- ds_bits = wil_rxdesc_ds_bits(d);
+ ds_bits = wil_rxdesc_ds_bits(d1);
if (ds_bits == 1) {
/*
* HW bug - in ToDS mode, i.e. Rx on AP side,
@@ -517,6 +525,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
.vring_cfg = {
.tx_sw_ring = {
.max_mpdu_size = cpu_to_le16(TX_BUF_LEN),
+ .ring_size = cpu_to_le16(size),
},
.ringid = id,
.cidxtid = (cid & 0xf) | ((tid & 0xf) << 4),
@@ -548,7 +557,6 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
goto out;
cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
- cmd.vring_cfg.tx_sw_ring.ring_size = cpu_to_le16(vring->size);
rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd),
WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
@@ -779,9 +787,14 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid);
while (!wil_vring_is_empty(vring)) {
- volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx;
+ volatile struct vring_tx_desc *d1 =
+ &vring->va[vring->swtail].tx;
+ struct vring_tx_desc dd, *d = &dd;
dma_addr_t pa;
struct sk_buff *skb;
+
+ dd = *d1;
+
if (!(d->dma.status & TX_DMA_STATUS_DU))
break;
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
index 45a61f597c5c..adef12fb2aee 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.h
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -339,24 +339,59 @@ union vring_desc {
struct vring_rx_desc rx;
} __packed;
-static inline int wil_rxdesc_phy_length(volatile struct vring_rx_desc *d)
+static inline int wil_rxdesc_tid(struct vring_rx_desc *d)
{
- return WIL_GET_BITS(d->dma.d0, 16, 29);
+ return WIL_GET_BITS(d->mac.d0, 0, 3);
}
-static inline int wil_rxdesc_mcs(volatile struct vring_rx_desc *d)
+static inline int wil_rxdesc_cid(struct vring_rx_desc *d)
{
- return WIL_GET_BITS(d->mac.d1, 21, 24);
+ return WIL_GET_BITS(d->mac.d0, 4, 6);
}
-static inline int wil_rxdesc_ds_bits(volatile struct vring_rx_desc *d)
+static inline int wil_rxdesc_mid(struct vring_rx_desc *d)
{
- return WIL_GET_BITS(d->mac.d1, 8, 9);
+ return WIL_GET_BITS(d->mac.d0, 8, 9);
}
-static inline int wil_rxdesc_ftype(volatile struct vring_rx_desc *d)
+static inline int wil_rxdesc_ftype(struct vring_rx_desc *d)
{
return WIL_GET_BITS(d->mac.d0, 10, 11);
}
+static inline int wil_rxdesc_subtype(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d0, 12, 15);
+}
+
+static inline int wil_rxdesc_seq(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d0, 16, 27);
+}
+
+static inline int wil_rxdesc_ext_subtype(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d0, 28, 31);
+}
+
+static inline int wil_rxdesc_ds_bits(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d1, 8, 9);
+}
+
+static inline int wil_rxdesc_mcs(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d1, 21, 24);
+}
+
+static inline int wil_rxdesc_phy_length(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->dma.d0, 16, 29);
+}
+
+static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb)
+{
+ return (void *)skb->cb;
+}
+
#endif /* WIL6210_TXRX_H */
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index f5e840104f4b..7f3d461f7e8d 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -980,7 +980,7 @@ static inline int b43_is_mode(struct b43_wl *wl, int type)
*/
static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)
{
- return wl->hw->conf.channel->band;
+ return wl->hw->conf.chandef.chan->band;
}
static inline int b43_bus_may_powerdown(struct b43_wldev *wldev)
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 4ac73d2f8605..d377f77d30b5 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3852,7 +3852,7 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
dev = wl->current_dev;
/* Switch the band (if necessary). This might change the active core. */
- err = b43_switch_band(wl, conf->channel);
+ err = b43_switch_band(wl, conf->chandef.chan);
if (err)
goto out_unlock_mutex;
@@ -3882,8 +3882,8 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
/* Switch to the requested channel.
* The firmware takes care of races with the TX handler. */
- if (conf->channel->hw_value != phy->channel)
- b43_switch_channel(dev, conf->channel->hw_value);
+ if (conf->chandef.chan->hw_value != phy->channel)
+ b43_switch_channel(dev, conf->chandef.chan->hw_value);
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
@@ -5006,7 +5006,7 @@ static int b43_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = dev->stats.link_noise;
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
index b8667706fc27..5d6833f18498 100644
--- a/drivers/net/wireless/b43/phy_ht.c
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -30,6 +30,17 @@
#include "radio_2059.h"
#include "main.h"
+/* Force values to keep compatibility with wl */
+enum ht_rssi_type {
+ HT_RSSI_W1 = 0,
+ HT_RSSI_W2 = 1,
+ HT_RSSI_NB = 2,
+ HT_RSSI_IQ = 3,
+ HT_RSSI_TSSI_2G = 4,
+ HT_RSSI_TSSI_5G = 5,
+ HT_RSSI_TBD = 6,
+};
+
/**************************************************
* Radio 2059.
**************************************************/
@@ -37,8 +48,9 @@
static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
const struct b43_phy_ht_channeltab_e_radio2059 *e)
{
- u8 i;
- u16 routing;
+ static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, };
+ u16 r;
+ int core;
b43_radio_write(dev, 0x16, e->radio_syn16);
b43_radio_write(dev, 0x17, e->radio_syn17);
@@ -53,25 +65,17 @@ static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
b43_radio_write(dev, 0x41, e->radio_syn41);
b43_radio_write(dev, 0x43, e->radio_syn43);
b43_radio_write(dev, 0x47, e->radio_syn47);
- b43_radio_write(dev, 0x4a, e->radio_syn4a);
- b43_radio_write(dev, 0x58, e->radio_syn58);
- b43_radio_write(dev, 0x5a, e->radio_syn5a);
- b43_radio_write(dev, 0x6a, e->radio_syn6a);
- b43_radio_write(dev, 0x6d, e->radio_syn6d);
- b43_radio_write(dev, 0x6e, e->radio_syn6e);
- b43_radio_write(dev, 0x92, e->radio_syn92);
- b43_radio_write(dev, 0x98, e->radio_syn98);
-
- for (i = 0; i < 2; i++) {
- routing = i ? R2059_RXRX1 : R2059_TXRX0;
- b43_radio_write(dev, routing | 0x4a, e->radio_rxtx4a);
- b43_radio_write(dev, routing | 0x58, e->radio_rxtx58);
- b43_radio_write(dev, routing | 0x5a, e->radio_rxtx5a);
- b43_radio_write(dev, routing | 0x6a, e->radio_rxtx6a);
- b43_radio_write(dev, routing | 0x6d, e->radio_rxtx6d);
- b43_radio_write(dev, routing | 0x6e, e->radio_rxtx6e);
- b43_radio_write(dev, routing | 0x92, e->radio_rxtx92);
- b43_radio_write(dev, routing | 0x98, e->radio_rxtx98);
+
+ for (core = 0; core < 3; core++) {
+ r = routing[core];
+ b43_radio_write(dev, r | 0x4a, e->radio_rxtx4a);
+ b43_radio_write(dev, r | 0x58, e->radio_rxtx58);
+ b43_radio_write(dev, r | 0x5a, e->radio_rxtx5a);
+ b43_radio_write(dev, r | 0x6a, e->radio_rxtx6a);
+ b43_radio_write(dev, r | 0x6d, e->radio_rxtx6d);
+ b43_radio_write(dev, r | 0x6e, e->radio_rxtx6e);
+ b43_radio_write(dev, r | 0x92, e->radio_rxtx92);
+ b43_radio_write(dev, r | 0x98, e->radio_rxtx98);
}
udelay(50);
@@ -87,7 +91,7 @@ static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
static void b43_radio_2059_init(struct b43_wldev *dev)
{
- const u16 routing[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1 };
+ const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3 };
const u16 radio_values[3][2] = {
{ 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
};
@@ -106,17 +110,17 @@ static void b43_radio_2059_init(struct b43_wldev *dev)
b43_radio_mask(dev, 0xc0, ~0x0080);
if (1) { /* FIXME */
- b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x1);
+ b43_radio_set(dev, R2059_C3 | 0x4, 0x1);
udelay(10);
- b43_radio_set(dev, R2059_RXRX1 | 0x0BF, 0x1);
- b43_radio_maskset(dev, R2059_RXRX1 | 0x19B, 0x3, 0x2);
+ b43_radio_set(dev, R2059_C3 | 0x0BF, 0x1);
+ b43_radio_maskset(dev, R2059_C3 | 0x19B, 0x3, 0x2);
- b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x2);
+ b43_radio_set(dev, R2059_C3 | 0x4, 0x2);
udelay(100);
- b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x2);
+ b43_radio_mask(dev, R2059_C3 | 0x4, ~0x2);
for (i = 0; i < 10000; i++) {
- if (b43_radio_read(dev, R2059_RXRX1 | 0x145) & 1) {
+ if (b43_radio_read(dev, R2059_C3 | 0x145) & 1) {
i = 0;
break;
}
@@ -125,7 +129,7 @@ static void b43_radio_2059_init(struct b43_wldev *dev)
if (i)
b43err(dev->wl, "radio 0x945 timeout\n");
- b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x1);
+ b43_radio_mask(dev, R2059_C3 | 0x4, ~0x1);
b43_radio_set(dev, 0xa, 0x60);
for (i = 0; i < 3; i++) {
@@ -390,14 +394,14 @@ static void b43_phy_ht_tx_tone(struct b43_wldev *dev)
**************************************************/
static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
- u8 rssi_type)
+ enum ht_rssi_type rssi_type)
{
static const u16 ctl_regs[3][2] = {
{ B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, },
{ B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, },
{ B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, },
};
- static const u16 radio_r[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1, };
+ static const u16 radio_r[] = { R2059_C1, R2059_C2, R2059_C3, };
int core;
if (core_sel == 0) {
@@ -411,13 +415,13 @@ static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
continue;
switch (rssi_type) {
- case 4:
+ case HT_RSSI_TSSI_2G:
b43_phy_set(dev, ctl_regs[core][0], 0x3 << 8);
b43_phy_set(dev, ctl_regs[core][0], 0x3 << 10);
b43_phy_set(dev, ctl_regs[core][1], 0x1 << 9);
b43_phy_set(dev, ctl_regs[core][1], 0x1 << 10);
- b43_radio_set(dev, R2059_RXRX1 | 0xbf, 0x1);
+ b43_radio_set(dev, R2059_C3 | 0xbf, 0x1);
b43_radio_write(dev, radio_r[core] | 0x159,
0x11);
break;
@@ -429,8 +433,8 @@ static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
}
}
-static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
- u8 nsamp)
+static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, enum ht_rssi_type type,
+ s32 *buf, u8 nsamp)
{
u16 phy_regs_values[12];
static const u16 phy_regs_to_save[] = {
@@ -504,15 +508,17 @@ static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable)
static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1,
B43_PHY_HT_TXPCTL_CMD_C2,
B43_PHY_HT_TXPCTL_CMD_C3 };
+ static const u16 status_regs[3] = { B43_PHY_HT_TX_PCTL_STATUS_C1,
+ B43_PHY_HT_TX_PCTL_STATUS_C2,
+ B43_PHY_HT_TX_PCTL_STATUS_C3 };
int i;
if (!enable) {
if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) {
/* We disable enabled TX pwr ctl, save it's state */
- /*
- * TODO: find the registers. On N-PHY they were 0x1ed
- * and 0x1ee, we need 3 such a registers for HT-PHY
- */
+ for (i = 0; i < 3; i++)
+ phy_ht->tx_pwr_idx[i] =
+ b43_phy_read(dev, status_regs[i]);
}
b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~en_bits);
} else {
@@ -536,13 +542,25 @@ static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable)
static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
{
struct b43_phy_ht *phy_ht = dev->phy.ht;
+ static const u16 base[] = { 0x840, 0x860, 0x880 };
+ u16 save_regs[3][3];
s32 rssi_buf[6];
+ int core;
+
+ for (core = 0; core < 3; core++) {
+ save_regs[core][1] = b43_phy_read(dev, base[core] + 6);
+ save_regs[core][2] = b43_phy_read(dev, base[core] + 7);
+ save_regs[core][0] = b43_phy_read(dev, base[core] + 0);
- /* TODO */
+ b43_phy_write(dev, base[core] + 6, 0);
+ b43_phy_mask(dev, base[core] + 7, ~0xF); /* 0xF? Or just 0x6? */
+ b43_phy_set(dev, base[core] + 0, 0x0400);
+ b43_phy_set(dev, base[core] + 0, 0x1000);
+ }
b43_phy_ht_tx_tone(dev);
udelay(20);
- b43_phy_ht_poll_rssi(dev, 4, rssi_buf, 1);
+ b43_phy_ht_poll_rssi(dev, HT_RSSI_TSSI_2G, rssi_buf, 1);
b43_phy_ht_stop_playback(dev);
b43_phy_ht_reset_cca(dev);
@@ -550,7 +568,23 @@ static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
phy_ht->idle_tssi[1] = rssi_buf[2] & 0xff;
phy_ht->idle_tssi[2] = rssi_buf[4] & 0xff;
- /* TODO */
+ for (core = 0; core < 3; core++) {
+ b43_phy_write(dev, base[core] + 0, save_regs[core][0]);
+ b43_phy_write(dev, base[core] + 6, save_regs[core][1]);
+ b43_phy_write(dev, base[core] + 7, save_regs[core][2]);
+ }
+}
+
+static void b43_phy_ht_tssi_setup(struct b43_wldev *dev)
+{
+ static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, };
+ int core;
+
+ /* 0x159 is probably TX_SSI_MUX or TSSIG (by comparing to N-PHY) */
+ for (core = 0; core < 3; core++) {
+ b43_radio_set(dev, 0x8bf, 0x1);
+ b43_radio_write(dev, routing[core] | 0x0159, 0x0011);
+ }
}
static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev)
@@ -946,6 +980,7 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev)
b43_phy_ht_tx_power_ctl(dev, false);
b43_phy_ht_tx_power_ctl_idle_tssi(dev);
b43_phy_ht_tx_power_ctl_setup(dev);
+ b43_phy_ht_tssi_setup(dev);
b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl);
return 0;
@@ -1011,8 +1046,9 @@ static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on)
static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel)
{
- struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
- enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+ struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if ((new_channel < 1) || (new_channel > 14))
diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h
index 9b2408efb224..6cae370d1018 100644
--- a/drivers/net/wireless/b43/phy_ht.h
+++ b/drivers/net/wireless/b43/phy_ht.h
@@ -23,6 +23,9 @@
#define B43_PHY_HT_SAMP_WAIT_CNT 0x0C5 /* Sample wait count */
#define B43_PHY_HT_SAMP_DEP_CNT 0x0C6 /* Sample depth count */
#define B43_PHY_HT_SAMP_STAT 0x0C7 /* Sample status */
+#define B43_PHY_HT_EST_PWR_C1 0x118
+#define B43_PHY_HT_EST_PWR_C2 0x119
+#define B43_PHY_HT_EST_PWR_C3 0x11A
#define B43_PHY_HT_TSSIMODE 0x122 /* TSSI mode */
#define B43_PHY_HT_TSSIMODE_EN 0x0001 /* TSSI enable */
#define B43_PHY_HT_TSSIMODE_PDEN 0x0002 /* Power det enable */
@@ -53,6 +56,8 @@
#define B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT 0
#define B43_PHY_HT_TXPCTL_TARG_PWR_C2 0xFF00 /* Power 1 */
#define B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT 8
+#define B43_PHY_HT_TX_PCTL_STATUS_C1 0x1ED
+#define B43_PHY_HT_TX_PCTL_STATUS_C2 0x1EE
#define B43_PHY_HT_TXPCTL_CMD_C2 0x222
#define B43_PHY_HT_TXPCTL_CMD_C2_INIT 0x007F
#define B43_PHY_HT_RSSI_C1 0x219
@@ -97,6 +102,7 @@
#define B43_PHY_HT_TXPCTL_TARG_PWR2 B43_PHY_EXTG(0x166) /* TX power control target power */
#define B43_PHY_HT_TXPCTL_TARG_PWR2_C3 0x00FF
#define B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT 0
+#define B43_PHY_HT_TX_PCTL_STATUS_C3 B43_PHY_EXTG(0x169)
#define B43_PHY_HT_TEST B43_PHY_N_BMODE(0x00A)
diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
index a13e28ef6246..0bafa3b17035 100644
--- a/drivers/net/wireless/b43/phy_lcn.c
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -808,8 +808,9 @@ static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel)
{
- struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
- enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+ struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if ((new_channel < 1) || (new_channel > 14))
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 5ed352ddae9e..92190dacf689 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -281,8 +281,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);
} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ ||
- (dev->dev->board_type == 0x048A) || ((dev->phy.rev == 0) &&
- (sprom->boardflags_lo & B43_BFL_FEM))) {
+ (dev->dev->board_type == SSB_BOARD_BU4312) ||
+ (dev->phy.rev == 0 && (sprom->boardflags_lo & B43_BFL_FEM))) {
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);
b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001);
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 63cca9c2bf97..7c970d3ae358 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -69,14 +69,27 @@ enum b43_nphy_rf_sequence {
B43_RFSEQ_UPDATE_GAINU,
};
-enum b43_nphy_rssi_type {
- B43_NPHY_RSSI_X = 0,
- B43_NPHY_RSSI_Y,
- B43_NPHY_RSSI_Z,
- B43_NPHY_RSSI_PWRDET,
- B43_NPHY_RSSI_TSSI_I,
- B43_NPHY_RSSI_TSSI_Q,
- B43_NPHY_RSSI_TBD,
+enum n_intc_override {
+ N_INTC_OVERRIDE_OFF = 0,
+ N_INTC_OVERRIDE_TRSW = 1,
+ N_INTC_OVERRIDE_PA = 2,
+ N_INTC_OVERRIDE_EXT_LNA_PU = 3,
+ N_INTC_OVERRIDE_EXT_LNA_GAIN = 4,
+};
+
+enum n_rssi_type {
+ N_RSSI_W1 = 0,
+ N_RSSI_W2,
+ N_RSSI_NB,
+ N_RSSI_IQ,
+ N_RSSI_TSSI_2G,
+ N_RSSI_TSSI_5G,
+ N_RSSI_TBD,
+};
+
+enum n_rail_type {
+ N_RAIL_I = 0,
+ N_RAIL_Q = 1,
};
static inline bool b43_nphy_ipa(struct b43_wldev *dev)
@@ -94,7 +107,7 @@ static u8 b43_nphy_get_rx_core_state(struct b43_wldev *dev)
}
/**************************************************
- * RF (just without b43_nphy_rf_control_intc_override)
+ * RF (just without b43_nphy_rf_ctl_intc_override)
**************************************************/
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
@@ -128,9 +141,9 @@ ok:
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
-static void b43_nphy_rf_control_override_rev7(struct b43_wldev *dev, u16 field,
- u16 value, u8 core, bool off,
- u8 override)
+static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
+ u16 value, u8 core, bool off,
+ u8 override)
{
const struct nphy_rf_control_override_rev7 *e;
u16 en_addrs[3][2] = {
@@ -168,8 +181,8 @@ static void b43_nphy_rf_control_override_rev7(struct b43_wldev *dev, u16 field,
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
-static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
- u16 value, u8 core, bool off)
+static void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field,
+ u16 value, u8 core, bool off)
{
int i;
u8 index = fls(field);
@@ -244,14 +257,14 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
-static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
- u16 value, u8 core)
+static void b43_nphy_rf_ctl_intc_override(struct b43_wldev *dev,
+ enum n_intc_override intc_override,
+ u16 value, u8 core)
{
u8 i, j;
u16 reg, tmp, val;
B43_WARN_ON(dev->phy.rev < 3);
- B43_WARN_ON(field > 4);
for (i = 0; i < 2; i++) {
if ((core == 1 && i == 1) || (core == 2 && !i))
@@ -261,12 +274,12 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
b43_phy_set(dev, reg, 0x400);
- switch (field) {
- case 0:
+ switch (intc_override) {
+ case N_INTC_OVERRIDE_OFF:
b43_phy_write(dev, reg, 0);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
break;
- case 1:
+ case N_INTC_OVERRIDE_TRSW:
if (!i) {
b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
0xFC3F, (value << 6));
@@ -307,7 +320,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
0xFFFE);
}
break;
- case 2:
+ case N_INTC_OVERRIDE_PA:
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
tmp = 0x0020;
val = value << 5;
@@ -317,7 +330,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
}
b43_phy_maskset(dev, reg, ~tmp, val);
break;
- case 3:
+ case N_INTC_OVERRIDE_EXT_LNA_PU:
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
tmp = 0x0001;
val = value;
@@ -327,7 +340,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
}
b43_phy_maskset(dev, reg, ~tmp, val);
break;
- case 4:
+ case N_INTC_OVERRIDE_EXT_LNA_GAIN:
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
tmp = 0x0002;
val = value << 1;
@@ -1011,7 +1024,7 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
if (sprom->revision < 4)
workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
- && dev->dev->board_type == 0x46D
+ && dev->dev->board_type == SSB_BOARD_CB2_4321
&& dev->dev->board_rev >= 0x41);
else
workaround =
@@ -1207,8 +1220,9 @@ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
- s8 offset, u8 core, u8 rail,
- enum b43_nphy_rssi_type type)
+ s8 offset, u8 core,
+ enum n_rail_type rail,
+ enum n_rssi_type rssi_type)
{
u16 tmp;
bool core1or5 = (core == 1) || (core == 5);
@@ -1217,63 +1231,74 @@ static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
offset = clamp_val(offset, -32, 31);
tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
-
- if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
- if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
-
- if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
- if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
+ switch (rssi_type) {
+ case N_RSSI_NB:
+ if (core1or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
+ if (core1or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
+ if (core2or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
+ if (core2or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
+ break;
+ case N_RSSI_W1:
+ if (core1or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
+ if (core1or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
+ if (core2or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
+ if (core2or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
+ break;
+ case N_RSSI_W2:
+ if (core1or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
+ if (core1or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
+ if (core2or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
+ if (core2or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
+ break;
+ case N_RSSI_TBD:
+ if (core1or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
+ if (core1or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
+ if (core2or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
+ if (core2or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
+ break;
+ case N_RSSI_IQ:
+ if (core1or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
+ if (core1or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
+ if (core2or5 && rail == N_RAIL_I)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
+ if (core2or5 && rail == N_RAIL_Q)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
+ break;
+ case N_RSSI_TSSI_2G:
+ if (core1or5)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
+ if (core2or5)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
+ break;
+ case N_RSSI_TSSI_5G:
+ if (core1or5)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
+ if (core2or5)
+ b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
+ break;
+ }
}
-static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
+static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code,
+ enum n_rssi_type rssi_type)
{
u8 i;
u16 reg, val;
@@ -1296,7 +1321,9 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
- if (type < 3) {
+ if (rssi_type == N_RSSI_W1 ||
+ rssi_type == N_RSSI_W2 ||
+ rssi_type == N_RSSI_NB) {
reg = (i == 0) ?
B43_NPHY_AFECTL_C1 :
B43_NPHY_AFECTL_C2;
@@ -1307,9 +1334,9 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
B43_NPHY_RFCTL_LUT_TRSW_UP2;
b43_phy_maskset(dev, reg, 0xFFC3, 0);
- if (type == 0)
+ if (rssi_type == N_RSSI_W1)
val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8;
- else if (type == 1)
+ else if (rssi_type == N_RSSI_W2)
val = 16;
else
val = 32;
@@ -1320,9 +1347,9 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
B43_NPHY_TXF_40CO_B32S1;
b43_phy_set(dev, reg, 0x0020);
} else {
- if (type == 6)
+ if (rssi_type == N_RSSI_TBD)
val = 0x0100;
- else if (type == 3)
+ else if (rssi_type == N_RSSI_IQ)
val = 0x0200;
else
val = 0x0300;
@@ -1334,7 +1361,8 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
b43_phy_maskset(dev, reg, 0xFCFF, val);
b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
- if (type != 3 && type != 6) {
+ if (rssi_type != N_RSSI_IQ &&
+ rssi_type != N_RSSI_TBD) {
enum ieee80211_band band =
b43_current_band(dev->wl);
@@ -1344,7 +1372,7 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
val = 0x11;
reg = (i == 0) ? 0x2000 : 0x3000;
reg |= B2055_PADDRV;
- b43_radio_write16(dev, reg, val);
+ b43_radio_write(dev, reg, val);
reg = (i == 0) ?
B43_NPHY_AFECTL_OVER1 :
@@ -1356,33 +1384,43 @@ static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
}
}
-static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
+static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code,
+ enum n_rssi_type rssi_type)
{
u16 val;
+ bool rssi_w1_w2_nb = false;
- if (type < 3)
+ switch (rssi_type) {
+ case N_RSSI_W1:
+ case N_RSSI_W2:
+ case N_RSSI_NB:
val = 0;
- else if (type == 6)
+ rssi_w1_w2_nb = true;
+ break;
+ case N_RSSI_TBD:
val = 1;
- else if (type == 3)
+ break;
+ case N_RSSI_IQ:
val = 2;
- else
+ break;
+ default:
val = 3;
+ }
val = (val << 12) | (val << 14);
b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
- if (type < 3) {
+ if (rssi_w1_w2_nb) {
b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
- (type + 1) << 4);
+ (rssi_type + 1) << 4);
b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
- (type + 1) << 4);
+ (rssi_type + 1) << 4);
}
if (code == 0) {
b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
- if (type < 3) {
+ if (rssi_w1_w2_nb) {
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
~(B43_NPHY_RFCTL_CMD_RXEN |
B43_NPHY_RFCTL_CMD_CORESEL));
@@ -1398,7 +1436,7 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
}
} else {
b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
- if (type < 3) {
+ if (rssi_w1_w2_nb) {
b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
~(B43_NPHY_RFCTL_CMD_RXEN |
B43_NPHY_RFCTL_CMD_CORESEL),
@@ -1418,7 +1456,8 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
-static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
+static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code,
+ enum n_rssi_type type)
{
if (dev->phy.rev >= 3)
b43_nphy_rev3_rssi_select(dev, code, type);
@@ -1427,11 +1466,12 @@ static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
-static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
+static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev,
+ enum n_rssi_type rssi_type, u8 *buf)
{
int i;
for (i = 0; i < 2; i++) {
- if (type == 2) {
+ if (rssi_type == N_RSSI_NB) {
if (i == 0) {
b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
0xFC, buf[0]);
@@ -1455,8 +1495,8 @@ static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
-static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
- u8 nsamp)
+static int b43_nphy_poll_rssi(struct b43_wldev *dev, enum n_rssi_type rssi_type,
+ s32 *buf, u8 nsamp)
{
int i;
int out;
@@ -1487,7 +1527,7 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
save_regs_phy[8] = 0;
}
- b43_nphy_rssi_select(dev, 5, type);
+ b43_nphy_rssi_select(dev, 5, rssi_type);
if (dev->phy.rev < 2) {
save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
@@ -1574,7 +1614,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
u16 r; /* routing */
u8 rx_core_state;
- u8 core, i, j;
+ int core, i, j, vcm;
class = b43_nphy_classifier(dev, 0, 0);
b43_nphy_classifier(dev, 7, 4);
@@ -1586,19 +1626,19 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
for (i = 0; i < ARRAY_SIZE(regs_to_store); i++)
saved_regs_phy[i] = b43_phy_read(dev, regs_to_store[i]);
- b43_nphy_rf_control_intc_override(dev, 0, 0, 7);
- b43_nphy_rf_control_intc_override(dev, 1, 1, 7);
- b43_nphy_rf_control_override(dev, 0x1, 0, 0, false);
- b43_nphy_rf_control_override(dev, 0x2, 1, 0, false);
- b43_nphy_rf_control_override(dev, 0x80, 1, 0, false);
- b43_nphy_rf_control_override(dev, 0x40, 1, 0, false);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_OFF, 0, 7);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7);
+ b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x2, 1, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x80, 1, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x40, 1, 0, false);
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- b43_nphy_rf_control_override(dev, 0x20, 0, 0, false);
- b43_nphy_rf_control_override(dev, 0x10, 1, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x20, 0, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x10, 1, 0, false);
} else {
- b43_nphy_rf_control_override(dev, 0x10, 0, 0, false);
- b43_nphy_rf_control_override(dev, 0x20, 1, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x10, 0, 0, false);
+ b43_nphy_rf_ctl_override(dev, 0x20, 1, 0, false);
}
rx_core_state = b43_nphy_get_rx_core_state(dev);
@@ -1606,35 +1646,44 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
if (!(rx_core_state & (1 << core)))
continue;
r = core ? B2056_RX1 : B2056_RX0;
- b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 0, 2);
- b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, 2);
- for (i = 0; i < 8; i++) {
+ b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_I,
+ N_RSSI_NB);
+ b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_Q,
+ N_RSSI_NB);
+
+ /* Grab RSSI results for every possible VCM */
+ for (vcm = 0; vcm < 8; vcm++) {
b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 0xE3,
- i << 2);
- b43_nphy_poll_rssi(dev, 2, results[i], 8);
+ vcm << 2);
+ b43_nphy_poll_rssi(dev, N_RSSI_NB, results[vcm], 8);
}
+
+ /* Find out which VCM got the best results */
for (i = 0; i < 4; i += 2) {
- s32 curr;
+ s32 currd;
s32 mind = 0x100000;
s32 minpoll = 249;
u8 minvcm = 0;
if (2 * core != i)
continue;
- for (j = 0; j < 8; j++) {
- curr = results[j][i] * results[j][i] +
- results[j][i + 1] * results[j][i];
- if (curr < mind) {
- mind = curr;
- minvcm = j;
+ for (vcm = 0; vcm < 8; vcm++) {
+ currd = results[vcm][i] * results[vcm][i] +
+ results[vcm][i + 1] * results[vcm][i];
+ if (currd < mind) {
+ mind = currd;
+ minvcm = vcm;
}
- if (results[j][i] < minpoll)
- minpoll = results[j][i];
+ if (results[vcm][i] < minpoll)
+ minpoll = results[vcm][i];
}
vcm_final = minvcm;
results_min[i] = minpoll;
}
+
+ /* Select the best VCM */
b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 0xE3,
vcm_final << 2);
+
for (i = 0; i < 4; i++) {
if (core != i / 2)
continue;
@@ -1647,16 +1696,19 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
offset[i] = -32;
b43_nphy_scale_offset_rssi(dev, 0, offset[i],
(i / 2 == 0) ? 1 : 2,
- (i % 2 == 0) ? 0 : 1,
- 2);
+ (i % 2 == 0) ? N_RAIL_I : N_RAIL_Q,
+ N_RSSI_NB);
}
}
+
for (core = 0; core < 2; core++) {
if (!(rx_core_state & (1 << core)))
continue;
for (i = 0; i < 2; i++) {
- b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 0, i);
- b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, i);
+ b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1,
+ N_RAIL_I, i);
+ b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1,
+ N_RAIL_Q, i);
b43_nphy_poll_rssi(dev, i, poll_results, 8);
for (j = 0; j < 4; j++) {
if (j / 2 == core) {
@@ -1696,8 +1748,13 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
}
- rssical_radio_regs[0] = b43_radio_read(dev, 0x602B);
- rssical_radio_regs[0] = b43_radio_read(dev, 0x702B);
+ if (dev->phy.rev >= 7) {
+ } else {
+ rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 |
+ B2056_RX_RSSI_MISC);
+ rssical_radio_regs[1] = b43_radio_read(dev, B2056_RX1 |
+ B2056_RX_RSSI_MISC);
+ }
rssical_phy_regs[0] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Z);
rssical_phy_regs[1] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z);
rssical_phy_regs[2] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Z);
@@ -1723,9 +1780,9 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
-static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
+static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, enum n_rssi_type type)
{
- int i, j;
+ int i, j, vcm;
u8 state[4];
u8 code, val;
u16 class, override;
@@ -1743,10 +1800,10 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
s32 results[4][4] = { };
s32 miniq[4][2] = { };
- if (type == 2) {
+ if (type == N_RSSI_NB) {
code = 0;
val = 6;
- } else if (type < 2) {
+ } else if (type == N_RSSI_W1 || type == N_RSSI_W2) {
code = 25;
val = 4;
} else {
@@ -1765,63 +1822,63 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
override = 0x110;
regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
- regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX);
+ regs_save_radio[0] = b43_radio_read(dev, B2055_C1_PD_RXTX);
b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
- b43_radio_write16(dev, B2055_C1_PD_RXTX, val);
+ b43_radio_write(dev, B2055_C1_PD_RXTX, val);
regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
- regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX);
+ regs_save_radio[1] = b43_radio_read(dev, B2055_C2_PD_RXTX);
b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
- b43_radio_write16(dev, B2055_C2_PD_RXTX, val);
+ b43_radio_write(dev, B2055_C2_PD_RXTX, val);
- state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07;
- state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07;
+ state[0] = b43_radio_read(dev, B2055_C1_PD_RSSIMISC) & 0x07;
+ state[1] = b43_radio_read(dev, B2055_C2_PD_RSSIMISC) & 0x07;
b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
- state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07;
- state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07;
+ state[2] = b43_radio_read(dev, B2055_C1_SP_RSSI) & 0x07;
+ state[3] = b43_radio_read(dev, B2055_C2_SP_RSSI) & 0x07;
b43_nphy_rssi_select(dev, 5, type);
- b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type);
- b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type);
+ b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_I, type);
+ b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_Q, type);
- for (i = 0; i < 4; i++) {
+ for (vcm = 0; vcm < 4; vcm++) {
u8 tmp[4];
for (j = 0; j < 4; j++)
- tmp[j] = i;
- if (type != 1)
+ tmp[j] = vcm;
+ if (type != N_RSSI_W2)
b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
- b43_nphy_poll_rssi(dev, type, results[i], 8);
- if (type < 2)
+ b43_nphy_poll_rssi(dev, type, results[vcm], 8);
+ if (type == N_RSSI_W1 || type == N_RSSI_W2)
for (j = 0; j < 2; j++)
- miniq[i][j] = min(results[i][2 * j],
- results[i][2 * j + 1]);
+ miniq[vcm][j] = min(results[vcm][2 * j],
+ results[vcm][2 * j + 1]);
}
for (i = 0; i < 4; i++) {
s32 mind = 0x100000;
u8 minvcm = 0;
s32 minpoll = 249;
- s32 curr;
- for (j = 0; j < 4; j++) {
- if (type == 2)
- curr = abs(results[j][i]);
+ s32 currd;
+ for (vcm = 0; vcm < 4; vcm++) {
+ if (type == N_RSSI_NB)
+ currd = abs(results[vcm][i] - code * 8);
else
- curr = abs(miniq[j][i / 2] - code * 8);
+ currd = abs(miniq[vcm][i / 2] - code * 8);
- if (curr < mind) {
- mind = curr;
- minvcm = j;
+ if (currd < mind) {
+ mind = currd;
+ minvcm = vcm;
}
- if (results[j][i] < minpoll)
- minpoll = results[j][i];
+ if (results[vcm][i] < minpoll)
+ minpoll = results[vcm][i];
}
results_min[i] = minpoll;
vcm_final[i] = minvcm;
}
- if (type != 1)
+ if (type != N_RSSI_W2)
b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
for (i = 0; i < 4; i++) {
@@ -1836,7 +1893,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
offset[i] = code - 32;
core = (i / 2) ? 2 : 1;
- rail = (i % 2) ? 1 : 0;
+ rail = (i % 2) ? N_RAIL_Q : N_RAIL_I;
b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail,
type);
@@ -1847,37 +1904,37 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
switch (state[2]) {
case 1:
- b43_nphy_rssi_select(dev, 1, 2);
+ b43_nphy_rssi_select(dev, 1, N_RSSI_NB);
break;
case 4:
- b43_nphy_rssi_select(dev, 1, 0);
+ b43_nphy_rssi_select(dev, 1, N_RSSI_W1);
break;
case 2:
- b43_nphy_rssi_select(dev, 1, 1);
+ b43_nphy_rssi_select(dev, 1, N_RSSI_W2);
break;
default:
- b43_nphy_rssi_select(dev, 1, 1);
+ b43_nphy_rssi_select(dev, 1, N_RSSI_W2);
break;
}
switch (state[3]) {
case 1:
- b43_nphy_rssi_select(dev, 2, 2);
+ b43_nphy_rssi_select(dev, 2, N_RSSI_NB);
break;
case 4:
- b43_nphy_rssi_select(dev, 2, 0);
+ b43_nphy_rssi_select(dev, 2, N_RSSI_W1);
break;
default:
- b43_nphy_rssi_select(dev, 2, 1);
+ b43_nphy_rssi_select(dev, 2, N_RSSI_W2);
break;
}
b43_nphy_rssi_select(dev, 0, type);
b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
- b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
+ b43_radio_write(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
- b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
+ b43_radio_write(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
b43_nphy_classifier(dev, 7, class);
b43_nphy_write_clip_detection(dev, clip_state);
@@ -1895,9 +1952,9 @@ static void b43_nphy_rssi_cal(struct b43_wldev *dev)
if (dev->phy.rev >= 3) {
b43_nphy_rev3_rssi_cal(dev);
} else {
- b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z);
- b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X);
- b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y);
+ b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB);
+ b43_nphy_rev2_rssi_cal(dev, N_RSSI_W1);
+ b43_nphy_rev2_rssi_cal(dev, N_RSSI_W2);
}
}
@@ -1930,10 +1987,8 @@ static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev)
b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
/* Set Clip 2 detect */
- b43_phy_set(dev, B43_NPHY_C1_CGAINI,
- B43_NPHY_C1_CGAINI_CL2DETECT);
- b43_phy_set(dev, B43_NPHY_C2_CGAINI,
- B43_NPHY_C2_CGAINI_CL2DETECT);
+ b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);
+ b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);
b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
0x17);
@@ -1967,22 +2022,22 @@ static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev)
b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
- b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
- b43_phy_write(dev, 0x2A7, e->init_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C1_INITGAIN_A, e->init_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C2_INITGAIN_A, e->init_gain);
+
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
e->rfseq_init);
- /* TODO: check defines. Do not match variables names */
- b43_phy_write(dev, B43_NPHY_C1_CLIP1_MEDGAIN, e->cliphi_gain);
- b43_phy_write(dev, 0x2A9, e->cliphi_gain);
- b43_phy_write(dev, B43_NPHY_C1_CLIP2_GAIN, e->clipmd_gain);
- b43_phy_write(dev, 0x2AB, e->clipmd_gain);
- b43_phy_write(dev, B43_NPHY_C2_CLIP1_HIGAIN, e->cliplo_gain);
- b43_phy_write(dev, 0x2AD, e->cliplo_gain);
-
- b43_phy_maskset(dev, 0x27D, 0xFF00, e->crsmin);
- b43_phy_maskset(dev, 0x280, 0xFF00, e->crsminl);
- b43_phy_maskset(dev, 0x283, 0xFF00, e->crsminu);
+ b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_HIGAIN_A, e->cliphi_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_HIGAIN_A, e->cliphi_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_MEDGAIN_A, e->clipmd_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_MEDGAIN_A, e->clipmd_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_A, e->cliplo_gain);
+ b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_A, e->cliplo_gain);
+
+ b43_phy_maskset(dev, B43_NPHY_CRSMINPOWER0, 0xFF00, e->crsmin);
+ b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERL0, 0xFF00, e->crsminl);
+ b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERU0, 0xFF00, e->crsminu);
b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);
b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);
b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
@@ -2164,8 +2219,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
}
if (phy->rev <= 8) {
- b43_phy_write(dev, 0x23F, 0x1B0);
- b43_phy_write(dev, 0x240, 0x1B0);
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0);
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0);
}
if (phy->rev >= 8)
b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
@@ -2182,8 +2237,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
- b43_phy_maskset(dev, 0x299, 0x3FFF, 0x4000);
- b43_phy_maskset(dev, 0x29D, 0x3FFF, 0x4000);
+ b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000);
+ b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000);
lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154);
lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159);
@@ -2260,11 +2315,11 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
rx2tx_lut_40_11n);
}
- b43_nphy_rf_control_override_rev7(dev, 16, 1, 3, false, 2);
+ b43_nphy_rf_ctl_override_rev7(dev, 16, 1, 3, false, 2);
}
b43_phy_write(dev, 0x32F, 0x3);
if (phy->radio_rev == 4 || phy->radio_rev == 6)
- b43_nphy_rf_control_override_rev7(dev, 4, 1, 3, false, 0);
+ b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0);
if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) {
if (sprom->revision &&
@@ -2450,8 +2505,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
u16 tmp16;
u32 tmp32;
- b43_phy_write(dev, 0x23f, 0x1f8);
- b43_phy_write(dev, 0x240, 0x1f8);
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1f8);
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1f8);
tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
tmp32 &= 0xffffff;
@@ -2464,8 +2519,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
- b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
- b43_phy_write(dev, 0x2AE, 0x000C);
+ b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_B, 0x000C);
+ b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_B, 0x000C);
/* TX to RX */
b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
@@ -2490,7 +2545,7 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
0x2 : 0x9C40;
b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
- b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
+ b43_phy_maskset(dev, B43_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700);
if (!dev->phy.is_40mhz) {
b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
@@ -2542,18 +2597,18 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
}
/* Dropped probably-always-true condition */
- b43_phy_write(dev, 0x224, 0x03eb);
- b43_phy_write(dev, 0x225, 0x03eb);
- b43_phy_write(dev, 0x226, 0x0341);
- b43_phy_write(dev, 0x227, 0x0341);
- b43_phy_write(dev, 0x228, 0x042b);
- b43_phy_write(dev, 0x229, 0x042b);
- b43_phy_write(dev, 0x22a, 0x0381);
- b43_phy_write(dev, 0x22b, 0x0381);
- b43_phy_write(dev, 0x22c, 0x042b);
- b43_phy_write(dev, 0x22d, 0x042b);
- b43_phy_write(dev, 0x22e, 0x0381);
- b43_phy_write(dev, 0x22f, 0x0381);
+ b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH0, 0x03eb);
+ b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH1, 0x03eb);
+ b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341);
+ b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH0, 0x042b);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH1, 0x042b);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH0, 0x0381);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH1, 0x0381);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH0, 0x042b);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH1, 0x042b);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH0, 0x0381);
+ b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH1, 0x0381);
if (dev->phy.rev >= 6 && sprom->boardflags2_lo & B43_BFL2_SINGLEANT_CCK)
; /* TODO: 0x0080000000000000 HF */
@@ -2572,7 +2627,7 @@ static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
- dev->dev->board_type == 0x8B) {
+ dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93) {
delays1[0] = 0x1;
delays1[5] = 0x14;
}
@@ -3120,21 +3175,21 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
b43_nphy_ipa_internal_tssi_setup(dev);
if (phy->rev >= 7)
- b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, false, 0);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, false, 0);
else if (phy->rev >= 3)
- b43_nphy_rf_control_override(dev, 0x2000, 0, 3, false);
+ b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false);
b43_nphy_stop_playback(dev);
b43_nphy_tx_tone(dev, 0xFA0, 0, false, false);
udelay(20);
- tmp = b43_nphy_poll_rssi(dev, 4, rssi, 1);
+ tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1);
b43_nphy_stop_playback(dev);
- b43_nphy_rssi_select(dev, 0, 0);
+ b43_nphy_rssi_select(dev, 0, N_RSSI_W1);
if (phy->rev >= 7)
- b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, true, 0);
+ b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, true, 0);
else if (phy->rev >= 3)
- b43_nphy_rf_control_override(dev, 0x2000, 0, 3, true);
+ b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true);
if (phy->rev >= 3) {
nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;
@@ -3573,8 +3628,8 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
}
- b43_nphy_rf_control_intc_override(dev, 2, 0, 3);
- b43_nphy_rf_control_override(dev, 8, 0, 3, false);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 0, 3);
+ b43_nphy_rf_ctl_override(dev, 8, 0, 3, false);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
if (core == 0) {
@@ -3584,8 +3639,10 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
rxval = 4;
txval = 2;
}
- b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1));
- b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core));
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, rxval,
+ core + 1);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, txval,
+ 2 - core);
}
#endif
@@ -3847,9 +3904,13 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
}
- /* TODO use some definitions */
- b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]);
- b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]);
+ if (dev->phy.rev >= 7) {
+ } else {
+ b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3,
+ rssical_radio_regs[0]);
+ b43_radio_maskset(dev, B2056_RX1 | B2056_RX_RSSI_MISC, 0xE3,
+ rssical_radio_regs[1]);
+ }
b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
@@ -3880,75 +3941,75 @@ static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
tmp = (i == 0) ? 0x2000 : 0x3000;
offset = i * 11;
- save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL);
- save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL);
- save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS);
- save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS);
- save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS);
- save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV);
- save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1);
- save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2);
- save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL);
- save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC);
- save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1);
+ save[offset + 0] = b43_radio_read(dev, B2055_CAL_RVARCTL);
+ save[offset + 1] = b43_radio_read(dev, B2055_CAL_LPOCTL);
+ save[offset + 2] = b43_radio_read(dev, B2055_CAL_TS);
+ save[offset + 3] = b43_radio_read(dev, B2055_CAL_RCCALRTS);
+ save[offset + 4] = b43_radio_read(dev, B2055_CAL_RCALRTS);
+ save[offset + 5] = b43_radio_read(dev, B2055_PADDRV);
+ save[offset + 6] = b43_radio_read(dev, B2055_XOCTL1);
+ save[offset + 7] = b43_radio_read(dev, B2055_XOCTL2);
+ save[offset + 8] = b43_radio_read(dev, B2055_XOREGUL);
+ save[offset + 9] = b43_radio_read(dev, B2055_XOMISC);
+ save[offset + 10] = b43_radio_read(dev, B2055_PLL_LFC1);
if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
- b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
- b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
- b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
+ b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
+ b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);
+ b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);
+ b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);
+ b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);
if (nphy->ipa5g_on) {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 4);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 1);
+ b43_radio_write(dev, tmp | B2055_PADDRV, 4);
+ b43_radio_write(dev, tmp | B2055_XOCTL1, 1);
} else {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F);
+ b43_radio_write(dev, tmp | B2055_PADDRV, 0);
+ b43_radio_write(dev, tmp | B2055_XOCTL1, 0x2F);
}
- b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
+ b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
} else {
- b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06);
- b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
- b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
- b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 0);
+ b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x06);
+ b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);
+ b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);
+ b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);
+ b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);
+ b43_radio_write(dev, tmp | B2055_XOCTL1, 0);
if (nphy->ipa2g_on) {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 6);
- b43_radio_write16(dev, tmp | B2055_XOCTL2,
+ b43_radio_write(dev, tmp | B2055_PADDRV, 6);
+ b43_radio_write(dev, tmp | B2055_XOCTL2,
(dev->phy.rev < 5) ? 0x11 : 0x01);
} else {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
+ b43_radio_write(dev, tmp | B2055_PADDRV, 0);
+ b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
}
}
- b43_radio_write16(dev, tmp | B2055_XOREGUL, 0);
- b43_radio_write16(dev, tmp | B2055_XOMISC, 0);
- b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 0);
+ b43_radio_write(dev, tmp | B2055_XOREGUL, 0);
+ b43_radio_write(dev, tmp | B2055_XOMISC, 0);
+ b43_radio_write(dev, tmp | B2055_PLL_LFC1, 0);
}
} else {
- save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1);
- b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
+ save[0] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL1);
+ b43_radio_write(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
- save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2);
- b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
+ save[1] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL2);
+ b43_radio_write(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
- save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1);
- b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
+ save[2] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL1);
+ b43_radio_write(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
- save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2);
- b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
+ save[3] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL2);
+ b43_radio_write(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
- save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX);
- save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX);
+ save[3] = b43_radio_read(dev, B2055_C1_PWRDET_RXTX);
+ save[4] = b43_radio_read(dev, B2055_C2_PWRDET_RXTX);
if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &
B43_NPHY_BANDCTL_5GHZ)) {
- b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x04);
- b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04);
+ b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x04);
+ b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x04);
} else {
- b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20);
- b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20);
+ b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x20);
+ b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x20);
}
if (dev->phy.rev < 2) {
@@ -4144,9 +4205,9 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
- b43_nphy_rf_control_intc_override(dev, 2, 1, 3);
- b43_nphy_rf_control_intc_override(dev, 1, 2, 1);
- b43_nphy_rf_control_intc_override(dev, 1, 8, 2);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 1, 3);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2);
regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
@@ -4679,7 +4740,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
(cur_lna << 2));
- b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3,
+ b43_nphy_rf_ctl_override(dev, 0x400, tmp[0], 3,
false);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
b43_nphy_stop_playback(dev);
@@ -4728,7 +4789,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
break;
}
- b43_nphy_rf_control_override(dev, 0x400, 0, 3, true);
+ b43_nphy_rf_ctl_override(dev, 0x400, 0, 3, true);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
@@ -4797,18 +4858,6 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
* N-PHY init
**************************************************/
-/*
- * Upload the N-PHY tables.
- * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
- */
-static void b43_nphy_tables_init(struct b43_wldev *dev)
-{
- if (dev->phy.rev < 3)
- b43_nphy_rev0_1_2_tables_init(dev);
- else
- b43_nphy_rev3plus_tables_init(dev);
-}
-
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
{
@@ -4958,7 +5007,7 @@ static int b43_phy_initn(struct b43_wldev *dev)
if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
(dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
- dev->dev->board_type == 0x8B))
+ dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93))
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
else
b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
@@ -5100,63 +5149,11 @@ static void b43_chantab_phy_upload(struct b43_wldev *dev,
/* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
{
- struct bcma_drv_cc __maybe_unused *cc;
- u32 __maybe_unused pmu_ctl;
-
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
- cc = &dev->dev->bdev->bus->drv_cc;
- if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
- if (avoid) {
- bcma_chipco_pll_write(cc, 0x0, 0x11500010);
- bcma_chipco_pll_write(cc, 0x1, 0x000C0C06);
- bcma_chipco_pll_write(cc, 0x2, 0x0F600a08);
- bcma_chipco_pll_write(cc, 0x3, 0x00000000);
- bcma_chipco_pll_write(cc, 0x4, 0x2001E920);
- bcma_chipco_pll_write(cc, 0x5, 0x88888815);
- } else {
- bcma_chipco_pll_write(cc, 0x0, 0x11100010);
- bcma_chipco_pll_write(cc, 0x1, 0x000c0c06);
- bcma_chipco_pll_write(cc, 0x2, 0x03000a08);
- bcma_chipco_pll_write(cc, 0x3, 0x00000000);
- bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
- bcma_chipco_pll_write(cc, 0x5, 0x88888815);
- }
- pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
- } else if (dev->dev->chip_id == 0x4716) {
- if (avoid) {
- bcma_chipco_pll_write(cc, 0x0, 0x11500060);
- bcma_chipco_pll_write(cc, 0x1, 0x080C0C06);
- bcma_chipco_pll_write(cc, 0x2, 0x0F600000);
- bcma_chipco_pll_write(cc, 0x3, 0x00000000);
- bcma_chipco_pll_write(cc, 0x4, 0x2001E924);
- bcma_chipco_pll_write(cc, 0x5, 0x88888815);
- } else {
- bcma_chipco_pll_write(cc, 0x0, 0x11100060);
- bcma_chipco_pll_write(cc, 0x1, 0x080c0c06);
- bcma_chipco_pll_write(cc, 0x2, 0x03000000);
- bcma_chipco_pll_write(cc, 0x3, 0x00000000);
- bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
- bcma_chipco_pll_write(cc, 0x5, 0x88888815);
- }
- pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD |
- BCMA_CC_PMU_CTL_NOILPONW;
- } else if (dev->dev->chip_id == 0x4322 ||
- dev->dev->chip_id == 0x4340 ||
- dev->dev->chip_id == 0x4341) {
- bcma_chipco_pll_write(cc, 0x0, 0x11100070);
- bcma_chipco_pll_write(cc, 0x1, 0x1014140a);
- bcma_chipco_pll_write(cc, 0x5, 0x88888854);
- if (avoid)
- bcma_chipco_pll_write(cc, 0x2, 0x05201828);
- else
- bcma_chipco_pll_write(cc, 0x2, 0x05001828);
- pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
- } else {
- return;
- }
- bcma_cc_set32(cc, BCMA_CC_PMU_CTL, pmu_ctl);
+ bcma_pmu_spuravoid_pllupdate(&dev->dev->bdev->bus->drv_cc,
+ avoid);
break;
#endif
#ifdef CONFIG_B43_SSB
@@ -5527,8 +5524,9 @@ static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
unsigned int new_channel)
{
- struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
- enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+ struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
if ((new_channel < 1) || (new_channel > 14))
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h
index 092c0140c249..9a5b6bc27d24 100644
--- a/drivers/net/wireless/b43/phy_n.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -54,10 +54,15 @@
#define B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT 7
#define B43_NPHY_C1_INITGAIN_TRRX 0x1000 /* TR RX index */
#define B43_NPHY_C1_INITGAIN_TRTX 0x2000 /* TR TX index */
+#define B43_NPHY_REV3_C1_INITGAIN_A B43_PHY_N(0x020)
#define B43_NPHY_C1_CLIP1_HIGAIN B43_PHY_N(0x021) /* Core 1 clip1 high gain code */
+#define B43_NPHY_REV3_C1_INITGAIN_B B43_PHY_N(0x021)
#define B43_NPHY_C1_CLIP1_MEDGAIN B43_PHY_N(0x022) /* Core 1 clip1 medium gain code */
+#define B43_NPHY_REV3_C1_CLIP_HIGAIN_A B43_PHY_N(0x022)
#define B43_NPHY_C1_CLIP1_LOGAIN B43_PHY_N(0x023) /* Core 1 clip1 low gain code */
+#define B43_NPHY_REV3_C1_CLIP_HIGAIN_B B43_PHY_N(0x023)
#define B43_NPHY_C1_CLIP2_GAIN B43_PHY_N(0x024) /* Core 1 clip2 gain code */
+#define B43_NPHY_REV3_C1_CLIP_MEDGAIN_A B43_PHY_N(0x024)
#define B43_NPHY_C1_FILTERGAIN B43_PHY_N(0x025) /* Core 1 filter gain */
#define B43_NPHY_C1_LPF_QHPF_BW B43_PHY_N(0x026) /* Core 1 LPF Q HP F bandwidth */
#define B43_NPHY_C1_CLIPWBTHRES B43_PHY_N(0x027) /* Core 1 clip wideband threshold */
@@ -107,10 +112,15 @@
#define B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT 7
#define B43_NPHY_C2_INITGAIN_TRRX 0x1000 /* TR RX index */
#define B43_NPHY_C2_INITGAIN_TRTX 0x2000 /* TR TX index */
+#define B43_NPHY_REV3_C1_CLIP_MEDGAIN_B B43_PHY_N(0x036)
#define B43_NPHY_C2_CLIP1_HIGAIN B43_PHY_N(0x037) /* Core 2 clip1 high gain code */
+#define B43_NPHY_REV3_C1_CLIP_LOGAIN_A B43_PHY_N(0x037)
#define B43_NPHY_C2_CLIP1_MEDGAIN B43_PHY_N(0x038) /* Core 2 clip1 medium gain code */
+#define B43_NPHY_REV3_C1_CLIP_LOGAIN_B B43_PHY_N(0x038)
#define B43_NPHY_C2_CLIP1_LOGAIN B43_PHY_N(0x039) /* Core 2 clip1 low gain code */
+#define B43_NPHY_REV3_C1_CLIP2_GAIN_A B43_PHY_N(0x039)
#define B43_NPHY_C2_CLIP2_GAIN B43_PHY_N(0x03A) /* Core 2 clip2 gain code */
+#define B43_NPHY_REV3_C1_CLIP2_GAIN_B B43_PHY_N(0x03A)
#define B43_NPHY_C2_FILTERGAIN B43_PHY_N(0x03B) /* Core 2 filter gain */
#define B43_NPHY_C2_LPF_QHPF_BW B43_PHY_N(0x03C) /* Core 2 LPF Q HP F bandwidth */
#define B43_NPHY_C2_CLIPWBTHRES B43_PHY_N(0x03D) /* Core 2 clip wideband threshold */
@@ -706,10 +716,146 @@
#define B43_NPHY_TXPCTL_INIT B43_PHY_N(0x222) /* TX power control init */
#define B43_NPHY_TXPCTL_INIT_PIDXI1 0x00FF /* Power index init 1 */
#define B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT 0
+#define B43_NPHY_ED_CRSEN B43_PHY_N(0x223)
+#define B43_NPHY_ED_CRS40ASSERTTHRESH0 B43_PHY_N(0x224)
+#define B43_NPHY_ED_CRS40ASSERTTHRESH1 B43_PHY_N(0x225)
+#define B43_NPHY_ED_CRS40DEASSERTTHRESH0 B43_PHY_N(0x226)
+#define B43_NPHY_ED_CRS40DEASSERTTHRESH1 B43_PHY_N(0x227)
+#define B43_NPHY_ED_CRS20LASSERTTHRESH0 B43_PHY_N(0x228)
+#define B43_NPHY_ED_CRS20LASSERTTHRESH1 B43_PHY_N(0x229)
+#define B43_NPHY_ED_CRS20LDEASSERTTHRESH0 B43_PHY_N(0x22A)
+#define B43_NPHY_ED_CRS20LDEASSERTTHRESH1 B43_PHY_N(0x22B)
+#define B43_NPHY_ED_CRS20UASSERTTHRESH0 B43_PHY_N(0x22C)
+#define B43_NPHY_ED_CRS20UASSERTTHRESH1 B43_PHY_N(0x22D)
+#define B43_NPHY_ED_CRS20UDEASSERTTHRESH0 B43_PHY_N(0x22E)
+#define B43_NPHY_ED_CRS20UDEASSERTTHRESH1 B43_PHY_N(0x22F)
+#define B43_NPHY_ED_CRS B43_PHY_N(0x230)
+#define B43_NPHY_TIMEOUTEN B43_PHY_N(0x231)
+#define B43_NPHY_OFDMPAYDECODETIMEOUTLEN B43_PHY_N(0x232)
+#define B43_NPHY_CCKPAYDECODETIMEOUTLEN B43_PHY_N(0x233)
+#define B43_NPHY_NONPAYDECODETIMEOUTLEN B43_PHY_N(0x234)
+#define B43_NPHY_TIMEOUTSTATUS B43_PHY_N(0x235)
+#define B43_NPHY_RFCTRLCORE0GPIO0 B43_PHY_N(0x236)
+#define B43_NPHY_RFCTRLCORE0GPIO1 B43_PHY_N(0x237)
+#define B43_NPHY_RFCTRLCORE0GPIO2 B43_PHY_N(0x238)
+#define B43_NPHY_RFCTRLCORE0GPIO3 B43_PHY_N(0x239)
+#define B43_NPHY_RFCTRLCORE1GPIO0 B43_PHY_N(0x23A)
+#define B43_NPHY_RFCTRLCORE1GPIO1 B43_PHY_N(0x23B)
+#define B43_NPHY_RFCTRLCORE1GPIO2 B43_PHY_N(0x23C)
+#define B43_NPHY_RFCTRLCORE1GPIO3 B43_PHY_N(0x23D)
+#define B43_NPHY_BPHYTESTCONTROL B43_PHY_N(0x23E)
+/* REV3+ */
+#define B43_NPHY_FORCEFRONT0 B43_PHY_N(0x23F)
+#define B43_NPHY_FORCEFRONT1 B43_PHY_N(0x240)
+#define B43_NPHY_NORMVARHYSTTH B43_PHY_N(0x241)
+#define B43_NPHY_TXCCKERROR B43_PHY_N(0x242)
+#define B43_NPHY_AFESEQINITDACGAIN B43_PHY_N(0x243)
+#define B43_NPHY_TXANTSWLUT B43_PHY_N(0x244)
+#define B43_NPHY_CORECONFIG B43_PHY_N(0x245)
+#define B43_NPHY_ANTENNADIVDWELLTIME B43_PHY_N(0x246)
+#define B43_NPHY_ANTENNACCKDIVDWELLTIME B43_PHY_N(0x247)
+#define B43_NPHY_ANTENNADIVBACKOFFGAIN B43_PHY_N(0x248)
+#define B43_NPHY_ANTENNADIVMINGAIN B43_PHY_N(0x249)
+#define B43_NPHY_BRDSEL_NORMVARHYSTTH B43_PHY_N(0x24A)
+#define B43_NPHY_RXANTSWITCHCTRL B43_PHY_N(0x24B)
+#define B43_NPHY_ENERGYDROPTIMEOUTLEN2 B43_PHY_N(0x24C)
+#define B43_NPHY_ML_LOG_TXEVM0 B43_PHY_N(0x250)
+#define B43_NPHY_ML_LOG_TXEVM1 B43_PHY_N(0x251)
+#define B43_NPHY_ML_LOG_TXEVM2 B43_PHY_N(0x252)
+#define B43_NPHY_ML_LOG_TXEVM3 B43_PHY_N(0x253)
+#define B43_NPHY_ML_LOG_TXEVM4 B43_PHY_N(0x254)
+#define B43_NPHY_ML_LOG_TXEVM5 B43_PHY_N(0x255)
+#define B43_NPHY_ML_LOG_TXEVM6 B43_PHY_N(0x256)
+#define B43_NPHY_ML_LOG_TXEVM7 B43_PHY_N(0x257)
+#define B43_NPHY_ML_SCALE_TWEAK B43_PHY_N(0x258)
+#define B43_NPHY_MLUA B43_PHY_N(0x259)
+#define B43_NPHY_ZFUA B43_PHY_N(0x25A)
+#define B43_NPHY_CHANUPSYM01 B43_PHY_N(0x25B)
+#define B43_NPHY_CHANUPSYM2 B43_PHY_N(0x25C)
+#define B43_NPHY_RXSTRNFILT20NUM00 B43_PHY_N(0x25D)
+#define B43_NPHY_RXSTRNFILT20NUM01 B43_PHY_N(0x25E)
+#define B43_NPHY_RXSTRNFILT20NUM02 B43_PHY_N(0x25F)
+#define B43_NPHY_RXSTRNFILT20DEN00 B43_PHY_N(0x260)
+#define B43_NPHY_RXSTRNFILT20DEN01 B43_PHY_N(0x261)
+#define B43_NPHY_RXSTRNFILT20NUM10 B43_PHY_N(0x262)
+#define B43_NPHY_RXSTRNFILT20NUM11 B43_PHY_N(0x263)
+#define B43_NPHY_RXSTRNFILT20NUM12 B43_PHY_N(0x264)
+#define B43_NPHY_RXSTRNFILT20DEN10 B43_PHY_N(0x265)
+#define B43_NPHY_RXSTRNFILT20DEN11 B43_PHY_N(0x266)
+#define B43_NPHY_RXSTRNFILT40NUM00 B43_PHY_N(0x267)
+#define B43_NPHY_RXSTRNFILT40NUM01 B43_PHY_N(0x268)
+#define B43_NPHY_RXSTRNFILT40NUM02 B43_PHY_N(0x269)
+#define B43_NPHY_RXSTRNFILT40DEN00 B43_PHY_N(0x26A)
+#define B43_NPHY_RXSTRNFILT40DEN01 B43_PHY_N(0x26B)
+#define B43_NPHY_RXSTRNFILT40NUM10 B43_PHY_N(0x26C)
+#define B43_NPHY_RXSTRNFILT40NUM11 B43_PHY_N(0x26D)
+#define B43_NPHY_RXSTRNFILT40NUM12 B43_PHY_N(0x26E)
+#define B43_NPHY_RXSTRNFILT40DEN10 B43_PHY_N(0x26F)
+#define B43_NPHY_RXSTRNFILT40DEN11 B43_PHY_N(0x270)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD1 B43_PHY_N(0x271)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD2 B43_PHY_N(0x272)
+#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLD B43_PHY_N(0x273)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD1L B43_PHY_N(0x274)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD2L B43_PHY_N(0x275)
+#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLDL B43_PHY_N(0x276)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD1U B43_PHY_N(0x277)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD2U B43_PHY_N(0x278)
+#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLDU B43_PHY_N(0x279)
+#define B43_NPHY_CRSACIDETECTTHRESH B43_PHY_N(0x27A)
+#define B43_NPHY_CRSACIDETECTTHRESHL B43_PHY_N(0x27B)
+#define B43_NPHY_CRSACIDETECTTHRESHU B43_PHY_N(0x27C)
+#define B43_NPHY_CRSMINPOWER0 B43_PHY_N(0x27D)
+#define B43_NPHY_CRSMINPOWER1 B43_PHY_N(0x27E)
+#define B43_NPHY_CRSMINPOWER2 B43_PHY_N(0x27F)
+#define B43_NPHY_CRSMINPOWERL0 B43_PHY_N(0x280)
+#define B43_NPHY_CRSMINPOWERL1 B43_PHY_N(0x281)
+#define B43_NPHY_CRSMINPOWERL2 B43_PHY_N(0x282)
+#define B43_NPHY_CRSMINPOWERU0 B43_PHY_N(0x283)
+#define B43_NPHY_CRSMINPOWERU1 B43_PHY_N(0x284)
+#define B43_NPHY_CRSMINPOWERU2 B43_PHY_N(0x285)
+#define B43_NPHY_STRPARAM B43_PHY_N(0x286)
+#define B43_NPHY_STRPARAML B43_PHY_N(0x287)
+#define B43_NPHY_STRPARAMU B43_PHY_N(0x288)
+#define B43_NPHY_BPHYCRSMINPOWER0 B43_PHY_N(0x289)
+#define B43_NPHY_BPHYCRSMINPOWER1 B43_PHY_N(0x28A)
+#define B43_NPHY_BPHYCRSMINPOWER2 B43_PHY_N(0x28B)
+#define B43_NPHY_BPHYFILTDEN0COEF B43_PHY_N(0x28C)
+#define B43_NPHY_BPHYFILTDEN1COEF B43_PHY_N(0x28D)
+#define B43_NPHY_BPHYFILTDEN2COEF B43_PHY_N(0x28E)
+#define B43_NPHY_BPHYFILTNUM0COEF B43_PHY_N(0x28F)
+#define B43_NPHY_BPHYFILTNUM1COEF B43_PHY_N(0x290)
+#define B43_NPHY_BPHYFILTNUM2COEF B43_PHY_N(0x291)
+#define B43_NPHY_BPHYFILTNUM01COEF2 B43_PHY_N(0x292)
+#define B43_NPHY_BPHYFILTBYPASS B43_PHY_N(0x293)
+#define B43_NPHY_SGILTRNOFFSET B43_PHY_N(0x294)
+#define B43_NPHY_RADAR_T2_MIN B43_PHY_N(0x295)
+#define B43_NPHY_TXPWRCTRLDAMPING B43_PHY_N(0x296)
#define B43_NPHY_PAPD_EN0 B43_PHY_N(0x297) /* PAPD Enable0 TBD */
#define B43_NPHY_EPS_TABLE_ADJ0 B43_PHY_N(0x298) /* EPS Table Adj0 TBD */
+#define B43_NPHY_EPS_OVERRIDEI_0 B43_PHY_N(0x299)
+#define B43_NPHY_EPS_OVERRIDEQ_0 B43_PHY_N(0x29A)
#define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */
#define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */
+#define B43_NPHY_EPS_OVERRIDEI_1 B43_PHY_N(0x29D)
+#define B43_NPHY_EPS_OVERRIDEQ_1 B43_PHY_N(0x29E)
+#define B43_NPHY_PAPD_CAL_ADDRESS B43_PHY_N(0x29F)
+#define B43_NPHY_PAPD_CAL_YREFEPSILON B43_PHY_N(0x2A0)
+#define B43_NPHY_PAPD_CAL_SETTLE B43_PHY_N(0x2A1)
+#define B43_NPHY_PAPD_CAL_CORRELATE B43_PHY_N(0x2A2)
+#define B43_NPHY_PAPD_CAL_SHIFTS0 B43_PHY_N(0x2A3)
+#define B43_NPHY_PAPD_CAL_SHIFTS1 B43_PHY_N(0x2A4)
+#define B43_NPHY_SAMPLE_START_ADDR B43_PHY_N(0x2A5)
+#define B43_NPHY_RADAR_ADC_TO_DBM B43_PHY_N(0x2A6)
+#define B43_NPHY_REV3_C2_INITGAIN_A B43_PHY_N(0x2A7)
+#define B43_NPHY_REV3_C2_INITGAIN_B B43_PHY_N(0x2A8)
+#define B43_NPHY_REV3_C2_CLIP_HIGAIN_A B43_PHY_N(0x2A9)
+#define B43_NPHY_REV3_C2_CLIP_HIGAIN_B B43_PHY_N(0x2AA)
+#define B43_NPHY_REV3_C2_CLIP_MEDGAIN_A B43_PHY_N(0x2AB)
+#define B43_NPHY_REV3_C2_CLIP_MEDGAIN_B B43_PHY_N(0x2AC)
+#define B43_NPHY_REV3_C2_CLIP_LOGAIN_A B43_PHY_N(0x2AD)
+#define B43_NPHY_REV3_C2_CLIP_LOGAIN_B B43_PHY_N(0x2AE)
+#define B43_NPHY_REV3_C2_CLIP2_GAIN_A B43_PHY_N(0x2AF)
+#define B43_NPHY_REV3_C2_CLIP2_GAIN_B B43_PHY_N(0x2B0)
#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */
#define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A)
diff --git a/drivers/net/wireless/b43/radio_2059.c b/drivers/net/wireless/b43/radio_2059.c
index d4ce8a12ff9a..38e31d857e3e 100644
--- a/drivers/net/wireless/b43/radio_2059.c
+++ b/drivers/net/wireless/b43/radio_2059.c
@@ -27,7 +27,7 @@
#define RADIOREGS(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
- r20, r21, r22, r23, r24, r25, r26, r27, r28) \
+ r20) \
.radio_syn16 = r00, \
.radio_syn17 = r01, \
.radio_syn22 = r02, \
@@ -41,22 +41,14 @@
.radio_syn41 = r10, \
.radio_syn43 = r11, \
.radio_syn47 = r12, \
- .radio_syn4a = r13, \
- .radio_syn58 = r14, \
- .radio_syn5a = r15, \
- .radio_syn6a = r16, \
- .radio_syn6d = r17, \
- .radio_syn6e = r18, \
- .radio_syn92 = r19, \
- .radio_syn98 = r20, \
- .radio_rxtx4a = r21, \
- .radio_rxtx58 = r22, \
- .radio_rxtx5a = r23, \
- .radio_rxtx6a = r24, \
- .radio_rxtx6d = r25, \
- .radio_rxtx6e = r26, \
- .radio_rxtx92 = r27, \
- .radio_rxtx98 = r28
+ .radio_rxtx4a = r13, \
+ .radio_rxtx58 = r14, \
+ .radio_rxtx5a = r15, \
+ .radio_rxtx6a = r16, \
+ .radio_rxtx6d = r17, \
+ .radio_rxtx6e = r18, \
+ .radio_rxtx92 = r19, \
+ .radio_rxtx98 = r20
#define PHYREGS(r0, r1, r2, r3, r4, r5) \
.phy_regs.bw1 = r0, \
@@ -70,91 +62,78 @@ static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radi
{ .freq = 2412,
RADIOREGS(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
},
{ .freq = 2417,
RADIOREGS(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
},
{ .freq = 2422,
RADIOREGS(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
},
{ .freq = 2427,
RADIOREGS(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
},
{ .freq = 2432,
RADIOREGS(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
},
{ .freq = 2437,
RADIOREGS(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
},
{ .freq = 2442,
RADIOREGS(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
},
{ .freq = 2447,
RADIOREGS(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
},
{ .freq = 2452,
RADIOREGS(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
},
{ .freq = 2457,
RADIOREGS(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
},
{ .freq = 2462,
RADIOREGS(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
},
{ .freq = 2467,
RADIOREGS(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
},
{ .freq = 2472,
RADIOREGS(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03,
- 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03,
0x00, 0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
},
diff --git a/drivers/net/wireless/b43/radio_2059.h b/drivers/net/wireless/b43/radio_2059.h
index e4d69e55e9fe..40a82d7f510c 100644
--- a/drivers/net/wireless/b43/radio_2059.h
+++ b/drivers/net/wireless/b43/radio_2059.h
@@ -5,9 +5,9 @@
#include "phy_ht.h"
-#define R2059_SYN 0x000
-#define R2059_TXRX0 0x400
-#define R2059_RXRX1 0x800
+#define R2059_C1 0x000
+#define R2059_C2 0x400
+#define R2059_C3 0x800
#define R2059_ALL 0xC00
/* Values for various registers uploaded on channel switching */
@@ -28,14 +28,6 @@ struct b43_phy_ht_channeltab_e_radio2059 {
u8 radio_syn41;
u8 radio_syn43;
u8 radio_syn47;
- u8 radio_syn4a;
- u8 radio_syn58;
- u8 radio_syn5a;
- u8 radio_syn6a;
- u8 radio_syn6d;
- u8 radio_syn6e;
- u8 radio_syn92;
- u8 radio_syn98;
u8 radio_rxtx4a;
u8 radio_rxtx58;
u8 radio_rxtx5a;
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index 110510d53958..94c755fdda14 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -2174,7 +2174,7 @@ static const u16 b43_ntab_loftlt1_r3[] = {
/* volatile tables, PHY revision >= 3 */
/* indexed by antswctl2g */
-static const u16 b43_ntab_antswctl2g_r3[4][32] = {
+static const u16 b43_ntab_antswctl_r3[4][32] = {
{
0x0082, 0x0082, 0x0211, 0x0222, 0x0328,
0x0000, 0x0000, 0x0000, 0x0144, 0x0000,
@@ -3095,9 +3095,55 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
}
#define ntab_upload(dev, offset, data) do { \
- b43_ntab_write_bulk(dev, offset, offset##_SIZE, data); \
+ b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
} while (0)
-void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
+
+static void b43_nphy_tables_init_rev3(struct b43_wldev *dev)
+{
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
+ u8 antswlut;
+
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
+ antswlut = sprom->fem.ghz5.antswlut;
+ else
+ antswlut = sprom->fem.ghz2.antswlut;
+
+ /* Static tables */
+ ntab_upload(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
+ ntab_upload(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
+ ntab_upload(dev, B43_NTAB_TMAP_R3, b43_ntab_tmap_r3);
+ ntab_upload(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
+ ntab_upload(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
+ ntab_upload(dev, B43_NTAB_NOISEVAR0_R3, b43_ntab_noisevar0_r3);
+ ntab_upload(dev, B43_NTAB_NOISEVAR1_R3, b43_ntab_noisevar1_r3);
+ ntab_upload(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
+ ntab_upload(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
+ ntab_upload(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
+ ntab_upload(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
+ ntab_upload(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
+ ntab_upload(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
+ ntab_upload(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
+ ntab_upload(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
+ ntab_upload(dev, B43_NTAB_C0_ESTPLT_R3, b43_ntab_estimatepowerlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_ESTPLT_R3, b43_ntab_estimatepowerlt1_r3);
+ ntab_upload(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
+ ntab_upload(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
+ ntab_upload(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
+ ntab_upload(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
+ ntab_upload(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
+ ntab_upload(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
+
+ /* Volatile tables */
+ if (antswlut < ARRAY_SIZE(b43_ntab_antswctl_r3))
+ ntab_upload(dev, B43_NTAB_ANT_SW_CTL_R3,
+ b43_ntab_antswctl_r3[antswlut]);
+ else
+ B43_WARN_ON(1);
+}
+
+static void b43_nphy_tables_init_rev0(struct b43_wldev *dev)
{
/* Static tables */
ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct);
@@ -3130,48 +3176,13 @@ void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
}
-#define ntab_upload_r3(dev, offset, data) do { \
- b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
- } while (0)
-void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables */
+void b43_nphy_tables_init(struct b43_wldev *dev)
{
- struct ssb_sprom *sprom = dev->dev->bus_sprom;
-
- /* Static tables */
- ntab_upload_r3(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
- ntab_upload_r3(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
- ntab_upload_r3(dev, B43_NTAB_TMAP_R3, b43_ntab_tmap_r3);
- ntab_upload_r3(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
- ntab_upload_r3(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
- ntab_upload_r3(dev, B43_NTAB_NOISEVAR0_R3, b43_ntab_noisevar0_r3);
- ntab_upload_r3(dev, B43_NTAB_NOISEVAR1_R3, b43_ntab_noisevar1_r3);
- ntab_upload_r3(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
- ntab_upload_r3(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
- ntab_upload_r3(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
- ntab_upload_r3(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
- ntab_upload_r3(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
- ntab_upload_r3(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
- ntab_upload_r3(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
- ntab_upload_r3(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
- ntab_upload_r3(dev, B43_NTAB_C0_ESTPLT_R3,
- b43_ntab_estimatepowerlt0_r3);
- ntab_upload_r3(dev, B43_NTAB_C1_ESTPLT_R3,
- b43_ntab_estimatepowerlt1_r3);
- ntab_upload_r3(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
- ntab_upload_r3(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
- ntab_upload_r3(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
- ntab_upload_r3(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
- ntab_upload_r3(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
- ntab_upload_r3(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
- ntab_upload_r3(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
- ntab_upload_r3(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
-
- /* Volatile tables */
- if (sprom->fem.ghz2.antswlut < ARRAY_SIZE(b43_ntab_antswctl2g_r3))
- ntab_upload_r3(dev, B43_NTAB_ANT_SW_CTL_R3,
- b43_ntab_antswctl2g_r3[sprom->fem.ghz2.antswlut]);
+ if (dev->phy.rev >= 3)
+ b43_nphy_tables_init_rev3(dev);
else
- B43_WARN_ON(1);
+ b43_nphy_tables_init_rev0(dev);
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index c600700ceedc..9ff33adcff89 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -115,22 +115,22 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
#define B43_NTAB_NOISEVAR11_SIZE 256
#define B43_NTAB_C0_ESTPLT B43_NTAB8 (0x1A, 0x000) /* Estimate Power Lookup Table Core 0 */
#define B43_NTAB_C0_ESTPLT_SIZE 64
-#define B43_NTAB_C1_ESTPLT B43_NTAB8 (0x1B, 0x000) /* Estimate Power Lookup Table Core 1 */
-#define B43_NTAB_C1_ESTPLT_SIZE 64
#define B43_NTAB_C0_ADJPLT B43_NTAB8 (0x1A, 0x040) /* Adjust Power Lookup Table Core 0 */
#define B43_NTAB_C0_ADJPLT_SIZE 128
-#define B43_NTAB_C1_ADJPLT B43_NTAB8 (0x1B, 0x040) /* Adjust Power Lookup Table Core 1 */
-#define B43_NTAB_C1_ADJPLT_SIZE 128
#define B43_NTAB_C0_GAINCTL B43_NTAB32(0x1A, 0x0C0) /* Gain Control Lookup Table Core 0 */
#define B43_NTAB_C0_GAINCTL_SIZE 128
-#define B43_NTAB_C1_GAINCTL B43_NTAB32(0x1B, 0x0C0) /* Gain Control Lookup Table Core 1 */
-#define B43_NTAB_C1_GAINCTL_SIZE 128
#define B43_NTAB_C0_IQLT B43_NTAB32(0x1A, 0x140) /* IQ Lookup Table Core 0 */
#define B43_NTAB_C0_IQLT_SIZE 128
-#define B43_NTAB_C1_IQLT B43_NTAB32(0x1B, 0x140) /* IQ Lookup Table Core 1 */
-#define B43_NTAB_C1_IQLT_SIZE 128
#define B43_NTAB_C0_LOFEEDTH B43_NTAB16(0x1A, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 0 */
#define B43_NTAB_C0_LOFEEDTH_SIZE 128
+#define B43_NTAB_C1_ESTPLT B43_NTAB8 (0x1B, 0x000) /* Estimate Power Lookup Table Core 1 */
+#define B43_NTAB_C1_ESTPLT_SIZE 64
+#define B43_NTAB_C1_ADJPLT B43_NTAB8 (0x1B, 0x040) /* Adjust Power Lookup Table Core 1 */
+#define B43_NTAB_C1_ADJPLT_SIZE 128
+#define B43_NTAB_C1_GAINCTL B43_NTAB32(0x1B, 0x0C0) /* Gain Control Lookup Table Core 1 */
+#define B43_NTAB_C1_GAINCTL_SIZE 128
+#define B43_NTAB_C1_IQLT B43_NTAB32(0x1B, 0x140) /* IQ Lookup Table Core 1 */
+#define B43_NTAB_C1_IQLT_SIZE 128
#define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */
#define B43_NTAB_C1_LOFEEDTH_SIZE 128
@@ -154,15 +154,17 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
#define B43_NTAB_CHANEST_R3 B43_NTAB32(22, 0) /* channel estimate */
#define B43_NTAB_FRAMELT_R3 B43_NTAB8(24, 0) /* frame lookup */
#define B43_NTAB_C0_ESTPLT_R3 B43_NTAB8(26, 0) /* estimated power lookup 0 */
-#define B43_NTAB_C1_ESTPLT_R3 B43_NTAB8(27, 0) /* estimated power lookup 1 */
#define B43_NTAB_C0_ADJPLT_R3 B43_NTAB8(26, 64) /* adjusted power lookup 0 */
-#define B43_NTAB_C1_ADJPLT_R3 B43_NTAB8(27, 64) /* adjusted power lookup 1 */
#define B43_NTAB_C0_GAINCTL_R3 B43_NTAB32(26, 192) /* gain control lookup 0 */
-#define B43_NTAB_C1_GAINCTL_R3 B43_NTAB32(27, 192) /* gain control lookup 1 */
#define B43_NTAB_C0_IQLT_R3 B43_NTAB32(26, 320) /* I/Q lookup 0 */
-#define B43_NTAB_C1_IQLT_R3 B43_NTAB32(27, 320) /* I/Q lookup 1 */
#define B43_NTAB_C0_LOFEEDTH_R3 B43_NTAB16(26, 448) /* Local Oscillator Feed Through lookup 0 */
+#define B43_NTAB_C0_PAPD_COMP_R3 B43_NTAB16(26, 576)
+#define B43_NTAB_C1_ESTPLT_R3 B43_NTAB8(27, 0) /* estimated power lookup 1 */
+#define B43_NTAB_C1_ADJPLT_R3 B43_NTAB8(27, 64) /* adjusted power lookup 1 */
+#define B43_NTAB_C1_GAINCTL_R3 B43_NTAB32(27, 192) /* gain control lookup 1 */
+#define B43_NTAB_C1_IQLT_R3 B43_NTAB32(27, 320) /* I/Q lookup 1 */
#define B43_NTAB_C1_LOFEEDTH_R3 B43_NTAB16(27, 448) /* Local Oscillator Feed Through lookup 1 */
+#define B43_NTAB_C1_PAPD_COMP_R3 B43_NTAB16(27, 576)
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE 18
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE 18
@@ -182,8 +184,7 @@ void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value);
void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data);
-void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev);
-void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev);
+void b43_nphy_tables_init(struct b43_wldev *dev);
const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev);
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 8c3f70e1a013..572668821862 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -2720,7 +2720,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
goto out_unlock_mutex;
/* Switch the PHY mode (if necessary). */
- switch (conf->channel->band) {
+ switch (conf->chandef.chan->band) {
case IEEE80211_BAND_2GHZ:
if (phy->type == B43legacy_PHYTYPE_B)
new_phymode = B43legacy_PHYMODE_B;
@@ -2748,8 +2748,9 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
/* Switch to the requested channel.
* The firmware takes care of races with the TX handler. */
- if (conf->channel->hw_value != phy->channel)
- b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
+ if (conf->chandef.chan->hw_value != phy->channel)
+ b43legacy_radio_selectchannel(dev, conf->chandef.chan->hw_value,
+ 0);
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
@@ -3558,7 +3559,7 @@ static int b43legacy_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = dev->stats.link_noise;
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index 747e9317dabd..fc8a0fa6d3b2 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -37,15 +37,6 @@ config BRCMFMAC_SDIO
IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
use the driver for a SDIO wireless card.
-config BRCMFMAC_SDIO_OOB
- bool "Out of band interrupt support for SDIO interface chipset"
- depends on BRCMFMAC_SDIO
- ---help---
- This option enables out-of-band interrupt support for Broadcom
- SDIO Wifi chipset using fullmac in order to gain better
- performance and deep sleep wake up capability on certain
- platforms. Say N if you are unsure.
-
config BRCMFMAC_USB
bool "USB bus interface support for FullMAC driver"
depends on USB
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 598c8e2f8d2b..8e9b1221b32c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -30,7 +30,8 @@ brcmfmac-objs += \
p2p.o \
dhd_cdc.o \
dhd_common.o \
- dhd_linux.o
+ dhd_linux.o \
+ btcoex.o
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
dhd_sdio.o \
bcmsdh.o \
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index f3149debede0..4891e3df2058 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -25,6 +25,7 @@
#include <linux/mmc/sdio.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/card.h>
+#include <linux/platform_data/brcmfmac-sdio.h>
#include <defs.h>
#include <brcm_hw_ids.h>
@@ -37,16 +38,15 @@
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
-static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
+
+static irqreturn_t brcmf_sdio_oob_irqhandler(int irq, void *dev_id)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- brcmf_dbg(INTR, "oob intr triggered\n");
+ brcmf_dbg(INTR, "OOB intr triggered\n");
- /*
- * out-of-band interrupt is level-triggered which won't
+ /* out-of-band interrupt is level-triggered which won't
* be cleared until dpc
*/
if (sdiodev->irq_en) {
@@ -59,72 +59,12 @@ static irqreturn_t brcmf_sdio_irqhandler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
-{
- int ret = 0;
- u8 data;
- unsigned long flags;
-
- brcmf_dbg(SDIO, "Entering: irq %d\n", sdiodev->irq);
-
- ret = request_irq(sdiodev->irq, brcmf_sdio_irqhandler,
- sdiodev->irq_flags, "brcmf_oob_intr",
- &sdiodev->func[1]->dev);
- if (ret != 0)
- return ret;
- spin_lock_init(&sdiodev->irq_en_lock);
- spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
- sdiodev->irq_en = true;
- spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
-
- ret = enable_irq_wake(sdiodev->irq);
- if (ret != 0)
- return ret;
- sdiodev->irq_wake = true;
-
- sdio_claim_host(sdiodev->func[1]);
-
- /* must configure SDIO_CCCR_IENx to enable irq */
- data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
- data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
- brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
-
- /* redirect, configure and enable io for interrupt signal */
- data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
- if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH)
- data |= SDIO_SEPINT_ACT_HI;
- brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
-
- sdio_release_host(sdiodev->func[1]);
-
- return 0;
-}
-
-int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
-{
- brcmf_dbg(SDIO, "Entering\n");
-
- sdio_claim_host(sdiodev->func[1]);
- brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
- brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
- sdio_release_host(sdiodev->func[1]);
-
- if (sdiodev->irq_wake) {
- disable_irq_wake(sdiodev->irq);
- sdiodev->irq_wake = false;
- }
- free_irq(sdiodev->irq, &sdiodev->func[1]->dev);
- sdiodev->irq_en = false;
-
- return 0;
-}
-#else /* CONFIG_BRCMFMAC_SDIO_OOB */
-static void brcmf_sdio_irqhandler(struct sdio_func *func)
+static void brcmf_sdio_ib_irqhandler(struct sdio_func *func)
{
struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- brcmf_dbg(INTR, "ib intr triggered\n");
+ brcmf_dbg(INTR, "IB intr triggered\n");
brcmf_sdbrcm_isr(sdiodev->bus);
}
@@ -136,12 +76,56 @@ static void brcmf_sdio_dummy_irqhandler(struct sdio_func *func)
int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev)
{
- brcmf_dbg(SDIO, "Entering\n");
+ int ret = 0;
+ u8 data;
+ unsigned long flags;
- sdio_claim_host(sdiodev->func[1]);
- sdio_claim_irq(sdiodev->func[1], brcmf_sdio_irqhandler);
- sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
- sdio_release_host(sdiodev->func[1]);
+ if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
+ brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
+ sdiodev->pdata->oob_irq_nr);
+ ret = request_irq(sdiodev->pdata->oob_irq_nr,
+ brcmf_sdio_oob_irqhandler,
+ sdiodev->pdata->oob_irq_flags,
+ "brcmf_oob_intr",
+ &sdiodev->func[1]->dev);
+ if (ret != 0) {
+ brcmf_err("request_irq failed %d\n", ret);
+ return ret;
+ }
+ sdiodev->oob_irq_requested = true;
+ spin_lock_init(&sdiodev->irq_en_lock);
+ spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
+ sdiodev->irq_en = true;
+ spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
+
+ ret = enable_irq_wake(sdiodev->pdata->oob_irq_nr);
+ if (ret != 0) {
+ brcmf_err("enable_irq_wake failed %d\n", ret);
+ return ret;
+ }
+ sdiodev->irq_wake = true;
+
+ sdio_claim_host(sdiodev->func[1]);
+
+ /* must configure SDIO_CCCR_IENx to enable irq */
+ data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
+ data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
+ brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
+
+ /* redirect, configure and enable io for interrupt signal */
+ data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
+ if (sdiodev->pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
+ data |= SDIO_SEPINT_ACT_HI;
+ brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
+
+ sdio_release_host(sdiodev->func[1]);
+ } else {
+ brcmf_dbg(SDIO, "Entering\n");
+ sdio_claim_host(sdiodev->func[1]);
+ sdio_claim_irq(sdiodev->func[1], brcmf_sdio_ib_irqhandler);
+ sdio_claim_irq(sdiodev->func[2], brcmf_sdio_dummy_irqhandler);
+ sdio_release_host(sdiodev->func[1]);
+ }
return 0;
}
@@ -150,14 +134,31 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
{
brcmf_dbg(SDIO, "Entering\n");
- sdio_claim_host(sdiodev->func[1]);
- sdio_release_irq(sdiodev->func[2]);
- sdio_release_irq(sdiodev->func[1]);
- sdio_release_host(sdiodev->func[1]);
+ if ((sdiodev->pdata) && (sdiodev->pdata->oob_irq_supported)) {
+ sdio_claim_host(sdiodev->func[1]);
+ brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
+ brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+ sdio_release_host(sdiodev->func[1]);
+
+ if (sdiodev->oob_irq_requested) {
+ sdiodev->oob_irq_requested = false;
+ if (sdiodev->irq_wake) {
+ disable_irq_wake(sdiodev->pdata->oob_irq_nr);
+ sdiodev->irq_wake = false;
+ }
+ free_irq(sdiodev->pdata->oob_irq_nr,
+ &sdiodev->func[1]->dev);
+ sdiodev->irq_en = false;
+ }
+ } else {
+ sdio_claim_host(sdiodev->func[1]);
+ sdio_release_irq(sdiodev->func[2]);
+ sdio_release_irq(sdiodev->func[1]);
+ sdio_release_host(sdiodev->func[1]);
+ }
return 0;
}
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
int
brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
@@ -457,36 +458,80 @@ done:
return err;
}
-int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
- u8 *buf, uint nbytes)
+int
+brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
+ u8 *data, uint size)
{
- struct sk_buff *mypkt;
- bool write = rw ? SDIOH_WRITE : SDIOH_READ;
- int err;
+ int bcmerror = 0;
+ struct sk_buff *pkt;
+ u32 sdaddr;
+ uint dsize;
+
+ dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
+ pkt = dev_alloc_skb(dsize);
+ if (!pkt) {
+ brcmf_err("dev_alloc_skb failed: len %d\n", dsize);
+ return -EIO;
+ }
+ pkt->priority = 0;
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+ /* Determine initial transfer parameters */
+ sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
+ if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
+ dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
+ else
+ dsize = size;
- mypkt = brcmu_pkt_buf_get_skb(nbytes);
- if (!mypkt) {
- brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
- nbytes);
- return -EIO;
+ sdio_claim_host(sdiodev->func[1]);
+
+ /* Do the transfer(s) */
+ while (size) {
+ /* Set the backplane window to include the start address */
+ bcmerror = brcmf_sdcard_set_sbaddr_window(sdiodev, address);
+ if (bcmerror)
+ break;
+
+ brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
+ write ? "write" : "read", dsize,
+ sdaddr, address & SBSDIO_SBWINDOW_MASK);
+
+ sdaddr &= SBSDIO_SB_OFT_ADDR_MASK;
+ sdaddr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+ skb_put(pkt, dsize);
+ if (write)
+ memcpy(pkt->data, data, dsize);
+ bcmerror = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC,
+ write, SDIO_FUNC_1,
+ sdaddr, pkt);
+ if (bcmerror) {
+ brcmf_err("membytes transfer failed\n");
+ break;
+ }
+ if (!write)
+ memcpy(data, pkt->data, dsize);
+ skb_trim(pkt, dsize);
+
+ /* Adjust for next transfer (if any) */
+ size -= dsize;
+ if (size) {
+ data += dsize;
+ address += dsize;
+ sdaddr = 0;
+ dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
+ }
}
- /* For a write, copy the buffer data into the packet. */
- if (write)
- memcpy(mypkt->data, buf, nbytes);
+ dev_kfree_skb(pkt);
- err = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, write,
- SDIO_FUNC_1, addr, mypkt);
+ /* Return the window to backplane enumeration space for core access */
+ if (brcmf_sdcard_set_sbaddr_window(sdiodev, sdiodev->sbwad))
+ brcmf_err("FAILED to set window back to 0x%x\n",
+ sdiodev->sbwad);
- /* For a read, copy the packet data back to the buffer. */
- if (!err && !write)
- memcpy(buf, mypkt->data, nbytes);
+ sdio_release_host(sdiodev->func[1]);
- brcmu_pkt_buf_free_skb(mypkt);
- return err;
+ return bcmerror;
}
int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 716548989e4f..44fa0cdbf97b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -26,6 +26,7 @@
#include <linux/sched.h> /* request_irq() */
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/platform_data/brcmfmac-sdio.h>
#include <net/cfg80211.h>
#include <defs.h>
@@ -40,32 +41,30 @@
#define DMA_ALIGN_MASK 0x03
+#define SDIO_DEVICE_ID_BROADCOM_43143 43143
#define SDIO_DEVICE_ID_BROADCOM_43241 0x4324
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
+#define SDIO_DEVICE_ID_BROADCOM_4335 0x4335
#define SDIO_FUNC1_BLOCKSIZE 64
#define SDIO_FUNC2_BLOCKSIZE 512
/* devices we support, null terminated */
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
+ {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4335)},
{ /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
-static struct list_head oobirq_lh;
-struct brcmf_sdio_oobirq {
- unsigned int irq;
- unsigned long flags;
- struct list_head list;
-};
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
+static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
+
static bool
brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev)
@@ -424,33 +423,6 @@ void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev)
}
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
-static int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
-{
- struct brcmf_sdio_oobirq *oobirq_entry;
-
- if (list_empty(&oobirq_lh)) {
- brcmf_err("no valid oob irq resource\n");
- return -ENXIO;
- }
-
- oobirq_entry = list_first_entry(&oobirq_lh, struct brcmf_sdio_oobirq,
- list);
-
- sdiodev->irq = oobirq_entry->irq;
- sdiodev->irq_flags = oobirq_entry->flags;
- list_del(&oobirq_entry->list);
- kfree(oobirq_entry);
-
- return 0;
-}
-#else
-static inline int brcmf_sdio_getintrcfg(struct brcmf_sdio_dev *sdiodev)
-{
- return 0;
-}
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
-
static int brcmf_ops_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
@@ -491,15 +463,13 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
dev_set_drvdata(&func->dev, bus_if);
dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
sdiodev->dev = &sdiodev->func[1]->dev;
+ sdiodev->pdata = brcmfmac_sdio_pdata;
atomic_set(&sdiodev->suspend, false);
init_waitqueue_head(&sdiodev->request_byte_wait);
init_waitqueue_head(&sdiodev->request_word_wait);
init_waitqueue_head(&sdiodev->request_chain_wait);
init_waitqueue_head(&sdiodev->request_buffer_wait);
- err = brcmf_sdio_getintrcfg(sdiodev);
- if (err)
- goto fail;
brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n");
err = brcmf_sdio_probe(sdiodev);
@@ -594,7 +564,7 @@ static const struct dev_pm_ops brcmf_sdio_pm_ops = {
static struct sdio_driver brcmf_sdmmc_driver = {
.probe = brcmf_ops_sdio_probe,
.remove = brcmf_ops_sdio_remove,
- .name = "brcmfmac",
+ .name = BRCMFMAC_SDIO_PDATA_NAME,
.id_table = brcmf_sdmmc_ids,
#ifdef CONFIG_PM_SLEEP
.drv = {
@@ -603,72 +573,51 @@ static struct sdio_driver brcmf_sdmmc_driver = {
#endif /* CONFIG_PM_SLEEP */
};
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
static int brcmf_sdio_pd_probe(struct platform_device *pdev)
{
- struct resource *res;
- struct brcmf_sdio_oobirq *oobirq_entry;
- int i, ret;
+ int ret;
- INIT_LIST_HEAD(&oobirq_lh);
+ brcmf_dbg(SDIO, "Enter\n");
- for (i = 0; ; i++) {
- res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
- if (!res)
- break;
+ brcmfmac_sdio_pdata = pdev->dev.platform_data;
- oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),
- GFP_KERNEL);
- if (!oobirq_entry)
- return -ENOMEM;
- oobirq_entry->irq = res->start;
- oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;
- list_add_tail(&oobirq_entry->list, &oobirq_lh);
- }
- if (i == 0)
- return -ENXIO;
+ if (brcmfmac_sdio_pdata->power_on)
+ brcmfmac_sdio_pdata->power_on();
ret = sdio_register_driver(&brcmf_sdmmc_driver);
-
if (ret)
brcmf_err("sdio_register_driver failed: %d\n", ret);
return ret;
}
-static struct platform_driver brcmf_sdio_pd = {
- .probe = brcmf_sdio_pd_probe,
- .driver = {
- .name = "brcmf_sdio_pd"
- }
-};
-
-void brcmf_sdio_exit(void)
+static int brcmf_sdio_pd_remove(struct platform_device *pdev)
{
brcmf_dbg(SDIO, "Enter\n");
+ if (brcmfmac_sdio_pdata->power_off)
+ brcmfmac_sdio_pdata->power_off();
+
sdio_unregister_driver(&brcmf_sdmmc_driver);
- platform_driver_unregister(&brcmf_sdio_pd);
+ return 0;
}
-void brcmf_sdio_init(void)
-{
- int ret;
-
- brcmf_dbg(SDIO, "Enter\n");
-
- ret = platform_driver_register(&brcmf_sdio_pd);
+static struct platform_driver brcmf_sdio_pd = {
+ .remove = brcmf_sdio_pd_remove,
+ .driver = {
+ .name = BRCMFMAC_SDIO_PDATA_NAME
+ }
+};
- if (ret)
- brcmf_err("platform_driver_register failed: %d\n", ret);
-}
-#else
void brcmf_sdio_exit(void)
{
brcmf_dbg(SDIO, "Enter\n");
- sdio_unregister_driver(&brcmf_sdmmc_driver);
+ if (brcmfmac_sdio_pdata)
+ platform_driver_unregister(&brcmf_sdio_pd);
+ else
+ sdio_unregister_driver(&brcmf_sdmmc_driver);
}
void brcmf_sdio_init(void)
@@ -677,9 +626,12 @@ void brcmf_sdio_init(void)
brcmf_dbg(SDIO, "Enter\n");
- ret = sdio_register_driver(&brcmf_sdmmc_driver);
+ ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe);
+ if (ret == -ENODEV) {
+ brcmf_dbg(SDIO, "No platform data available, registering without.\n");
+ ret = sdio_register_driver(&brcmf_sdmmc_driver);
+ }
if (ret)
- brcmf_err("sdio_register_driver failed: %d\n", ret);
+ brcmf_err("driver registration failed: %d\n", ret);
}
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
new file mode 100644
index 000000000000..0cb591b050b3
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * 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 <linux/slab.h>
+#include <linux/netdevice.h>
+#include <net/cfg80211.h>
+
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include <defs.h>
+#include <dhd.h>
+#include <dhd_dbg.h>
+#include "fwil.h"
+#include "fwil_types.h"
+#include "btcoex.h"
+#include "p2p.h"
+#include "wl_cfg80211.h"
+
+/* T1 start SCO/eSCO priority suppression */
+#define BRCMF_BTCOEX_OPPR_WIN_TIME 2000
+
+/* BT registers values during DHCP */
+#define BRCMF_BT_DHCP_REG50 0x8022
+#define BRCMF_BT_DHCP_REG51 0
+#define BRCMF_BT_DHCP_REG64 0
+#define BRCMF_BT_DHCP_REG65 0
+#define BRCMF_BT_DHCP_REG71 0
+#define BRCMF_BT_DHCP_REG66 0x2710
+#define BRCMF_BT_DHCP_REG41 0x33
+#define BRCMF_BT_DHCP_REG68 0x190
+
+/* number of samples for SCO detection */
+#define BRCMF_BT_SCO_SAMPLES 12
+
+/**
+* enum brcmf_btcoex_state - BT coex DHCP state machine states
+* @BRCMF_BT_DHCP_IDLE: DCHP is idle
+* @BRCMF_BT_DHCP_START: DHCP started, wait before
+* boosting wifi priority
+* @BRCMF_BT_DHCP_OPPR_WIN: graceful DHCP opportunity ended,
+* boost wifi priority
+* @BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT: wifi priority boost end,
+* restore defaults
+*/
+enum brcmf_btcoex_state {
+ BRCMF_BT_DHCP_IDLE,
+ BRCMF_BT_DHCP_START,
+ BRCMF_BT_DHCP_OPPR_WIN,
+ BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT
+};
+
+/**
+ * struct brcmf_btcoex_info - BT coex related information
+ * @vif: interface for which request was done.
+ * @timer: timer for DHCP state machine
+ * @timeout: configured timeout.
+ * @timer_on: DHCP timer active
+ * @dhcp_done: DHCP finished before T1/T2 timer expiration
+ * @bt_state: DHCP state machine state
+ * @work: DHCP state machine work
+ * @cfg: driver private data for cfg80211 interface
+ * @reg66: saved value of btc_params 66
+ * @reg41: saved value of btc_params 41
+ * @reg68: saved value of btc_params 68
+ * @saved_regs_part1: flag indicating regs 66,41,68
+ * have been saved
+ * @reg51: saved value of btc_params 51
+ * @reg64: saved value of btc_params 64
+ * @reg65: saved value of btc_params 65
+ * @reg71: saved value of btc_params 71
+ * @saved_regs_part1: flag indicating regs 50,51,64,65,71
+ * have been saved
+ */
+struct brcmf_btcoex_info {
+ struct brcmf_cfg80211_vif *vif;
+ struct timer_list timer;
+ u16 timeout;
+ bool timer_on;
+ bool dhcp_done;
+ enum brcmf_btcoex_state bt_state;
+ struct work_struct work;
+ struct brcmf_cfg80211_info *cfg;
+ u32 reg66;
+ u32 reg41;
+ u32 reg68;
+ bool saved_regs_part1;
+ u32 reg50;
+ u32 reg51;
+ u32 reg64;
+ u32 reg65;
+ u32 reg71;
+ bool saved_regs_part2;
+};
+
+/**
+ * brcmf_btcoex_params_write() - write btc_params firmware variable
+ * @ifp: interface
+ * @addr: btc_params register number
+ * @data: data to write
+ */
+static s32 brcmf_btcoex_params_write(struct brcmf_if *ifp, u32 addr, u32 data)
+{
+ struct {
+ __le32 addr;
+ __le32 data;
+ } reg_write;
+
+ reg_write.addr = cpu_to_le32(addr);
+ reg_write.data = cpu_to_le32(data);
+ return brcmf_fil_iovar_data_set(ifp, "btc_params",
+ &reg_write, sizeof(reg_write));
+}
+
+/**
+ * brcmf_btcoex_params_read() - read btc_params firmware variable
+ * @ifp: interface
+ * @addr: btc_params register number
+ * @data: read data
+ */
+static s32 brcmf_btcoex_params_read(struct brcmf_if *ifp, u32 addr, u32 *data)
+{
+ *data = addr;
+
+ return brcmf_fil_iovar_int_get(ifp, "btc_params", data);
+}
+
+/**
+ * brcmf_btcoex_boost_wifi() - control BT SCO/eSCO parameters
+ * @btci: BT coex info
+ * @trump_sco:
+ * true - set SCO/eSCO parameters for compatibility
+ * during DHCP window
+ * false - restore saved parameter values
+ *
+ * Enhanced BT COEX settings for eSCO compatibility during DHCP window
+ */
+static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
+ bool trump_sco)
+{
+ struct brcmf_if *ifp = btci->cfg->pub->iflist[0];
+
+ if (trump_sco && !btci->saved_regs_part2) {
+ /* this should reduce eSCO agressive
+ * retransmit w/o breaking it
+ */
+
+ /* save current */
+ brcmf_dbg(TRACE, "new SCO/eSCO coex algo {save & override}\n");
+ brcmf_btcoex_params_read(ifp, 50, &btci->reg50);
+ brcmf_btcoex_params_read(ifp, 51, &btci->reg51);
+ brcmf_btcoex_params_read(ifp, 64, &btci->reg64);
+ brcmf_btcoex_params_read(ifp, 65, &btci->reg65);
+ brcmf_btcoex_params_read(ifp, 71, &btci->reg71);
+
+ btci->saved_regs_part2 = true;
+ brcmf_dbg(TRACE,
+ "saved bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ btci->reg50, btci->reg51, btci->reg64,
+ btci->reg65, btci->reg71);
+
+ /* pacify the eSco */
+ brcmf_btcoex_params_write(ifp, 50, BRCMF_BT_DHCP_REG50);
+ brcmf_btcoex_params_write(ifp, 51, BRCMF_BT_DHCP_REG51);
+ brcmf_btcoex_params_write(ifp, 64, BRCMF_BT_DHCP_REG64);
+ brcmf_btcoex_params_write(ifp, 65, BRCMF_BT_DHCP_REG65);
+ brcmf_btcoex_params_write(ifp, 71, BRCMF_BT_DHCP_REG71);
+
+ } else if (btci->saved_regs_part2) {
+ /* restore previously saved bt params */
+ brcmf_dbg(TRACE, "Do new SCO/eSCO coex algo {restore}\n");
+ brcmf_btcoex_params_write(ifp, 50, btci->reg50);
+ brcmf_btcoex_params_write(ifp, 51, btci->reg51);
+ brcmf_btcoex_params_write(ifp, 64, btci->reg64);
+ brcmf_btcoex_params_write(ifp, 65, btci->reg65);
+ brcmf_btcoex_params_write(ifp, 71, btci->reg71);
+
+ brcmf_dbg(TRACE,
+ "restored bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ btci->reg50, btci->reg51, btci->reg64,
+ btci->reg65, btci->reg71);
+
+ btci->saved_regs_part2 = false;
+ } else {
+ brcmf_err("attempted to restore not saved BTCOEX params\n");
+ }
+}
+
+/**
+ * brcmf_btcoex_is_sco_active() - check if SCO/eSCO is active
+ * @ifp: interface
+ *
+ * return: true if SCO/eSCO session is active
+ */
+static bool brcmf_btcoex_is_sco_active(struct brcmf_if *ifp)
+{
+ int ioc_res = 0;
+ bool res = false;
+ int sco_id_cnt = 0;
+ u32 param27;
+ int i;
+
+ for (i = 0; i < BRCMF_BT_SCO_SAMPLES; i++) {
+ ioc_res = brcmf_btcoex_params_read(ifp, 27, &param27);
+
+ if (ioc_res < 0) {
+ brcmf_err("ioc read btc params error\n");
+ break;
+ }
+
+ brcmf_dbg(TRACE, "sample[%d], btc_params 27:%x\n", i, param27);
+
+ if ((param27 & 0x6) == 2) { /* count both sco & esco */
+ sco_id_cnt++;
+ }
+
+ if (sco_id_cnt > 2) {
+ brcmf_dbg(TRACE,
+ "sco/esco detected, pkt id_cnt:%d samples:%d\n",
+ sco_id_cnt, i);
+ res = true;
+ break;
+ }
+ }
+ brcmf_dbg(TRACE, "exit: result=%d\n", res);
+ return res;
+}
+
+/**
+ * btcmf_btcoex_save_part1() - save first step parameters.
+ */
+static void btcmf_btcoex_save_part1(struct brcmf_btcoex_info *btci)
+{
+ struct brcmf_if *ifp = btci->vif->ifp;
+
+ if (!btci->saved_regs_part1) {
+ /* Retrieve and save original reg value */
+ brcmf_btcoex_params_read(ifp, 66, &btci->reg66);
+ brcmf_btcoex_params_read(ifp, 41, &btci->reg41);
+ brcmf_btcoex_params_read(ifp, 68, &btci->reg68);
+ btci->saved_regs_part1 = true;
+ brcmf_dbg(TRACE,
+ "saved btc_params regs (66,41,68) 0x%x 0x%x 0x%x\n",
+ btci->reg66, btci->reg41,
+ btci->reg68);
+ }
+}
+
+/**
+ * brcmf_btcoex_restore_part1() - restore first step parameters.
+ */
+static void brcmf_btcoex_restore_part1(struct brcmf_btcoex_info *btci)
+{
+ struct brcmf_if *ifp;
+
+ if (btci->saved_regs_part1) {
+ btci->saved_regs_part1 = false;
+ ifp = btci->vif->ifp;
+ brcmf_btcoex_params_write(ifp, 66, btci->reg66);
+ brcmf_btcoex_params_write(ifp, 41, btci->reg41);
+ brcmf_btcoex_params_write(ifp, 68, btci->reg68);
+ brcmf_dbg(TRACE,
+ "restored btc_params regs {66,41,68} 0x%x 0x%x 0x%x\n",
+ btci->reg66, btci->reg41,
+ btci->reg68);
+ }
+}
+
+/**
+ * brcmf_btcoex_timerfunc() - BT coex timer callback
+ */
+static void brcmf_btcoex_timerfunc(ulong data)
+{
+ struct brcmf_btcoex_info *bt_local = (struct brcmf_btcoex_info *)data;
+ brcmf_dbg(TRACE, "enter\n");
+
+ bt_local->timer_on = false;
+ schedule_work(&bt_local->work);
+}
+
+/**
+ * brcmf_btcoex_handler() - BT coex state machine work handler
+ * @work: work
+ */
+static void brcmf_btcoex_handler(struct work_struct *work)
+{
+ struct brcmf_btcoex_info *btci;
+ btci = container_of(work, struct brcmf_btcoex_info, work);
+ if (btci->timer_on) {
+ btci->timer_on = false;
+ del_timer_sync(&btci->timer);
+ }
+
+ switch (btci->bt_state) {
+ case BRCMF_BT_DHCP_START:
+ /* DHCP started provide OPPORTUNITY window
+ to get DHCP address
+ */
+ brcmf_dbg(TRACE, "DHCP started\n");
+ btci->bt_state = BRCMF_BT_DHCP_OPPR_WIN;
+ if (btci->timeout < BRCMF_BTCOEX_OPPR_WIN_TIME) {
+ mod_timer(&btci->timer, btci->timer.expires);
+ } else {
+ btci->timeout -= BRCMF_BTCOEX_OPPR_WIN_TIME;
+ mod_timer(&btci->timer,
+ jiffies +
+ msecs_to_jiffies(BRCMF_BTCOEX_OPPR_WIN_TIME));
+ }
+ btci->timer_on = true;
+ break;
+
+ case BRCMF_BT_DHCP_OPPR_WIN:
+ if (btci->dhcp_done) {
+ brcmf_dbg(TRACE, "DHCP done before T1 expiration\n");
+ goto idle;
+ }
+
+ /* DHCP is not over yet, start lowering BT priority */
+ brcmf_dbg(TRACE, "DHCP T1:%d expired\n",
+ BRCMF_BTCOEX_OPPR_WIN_TIME);
+ brcmf_btcoex_boost_wifi(btci, true);
+
+ btci->bt_state = BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT;
+ mod_timer(&btci->timer,
+ jiffies + msecs_to_jiffies(btci->timeout));
+ btci->timer_on = true;
+ break;
+
+ case BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT:
+ if (btci->dhcp_done)
+ brcmf_dbg(TRACE, "DHCP done before T2 expiration\n");
+ else
+ brcmf_dbg(TRACE, "DHCP T2:%d expired\n",
+ BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT);
+
+ goto idle;
+
+ default:
+ brcmf_err("invalid state=%d !!!\n", btci->bt_state);
+ goto idle;
+ }
+
+ return;
+
+idle:
+ btci->bt_state = BRCMF_BT_DHCP_IDLE;
+ btci->timer_on = false;
+ brcmf_btcoex_boost_wifi(btci, false);
+ cfg80211_crit_proto_stopped(&btci->vif->wdev, GFP_KERNEL);
+ brcmf_btcoex_restore_part1(btci);
+ btci->vif = NULL;
+}
+
+/**
+ * brcmf_btcoex_attach() - initialize BT coex data
+ * @cfg: driver private cfg80211 data
+ *
+ * return: 0 on success
+ */
+int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg)
+{
+ struct brcmf_btcoex_info *btci = NULL;
+ brcmf_dbg(TRACE, "enter\n");
+
+ btci = kmalloc(sizeof(struct brcmf_btcoex_info), GFP_KERNEL);
+ if (!btci)
+ return -ENOMEM;
+
+ btci->bt_state = BRCMF_BT_DHCP_IDLE;
+
+ /* Set up timer for BT */
+ btci->timer_on = false;
+ btci->timeout = BRCMF_BTCOEX_OPPR_WIN_TIME;
+ init_timer(&btci->timer);
+ btci->timer.data = (ulong)btci;
+ btci->timer.function = brcmf_btcoex_timerfunc;
+ btci->cfg = cfg;
+ btci->saved_regs_part1 = false;
+ btci->saved_regs_part2 = false;
+
+ INIT_WORK(&btci->work, brcmf_btcoex_handler);
+
+ cfg->btcoex = btci;
+ return 0;
+}
+
+/**
+ * brcmf_btcoex_detach - clean BT coex data
+ * @cfg: driver private cfg80211 data
+ */
+void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg)
+{
+ brcmf_dbg(TRACE, "enter\n");
+
+ if (!cfg->btcoex)
+ return;
+
+ if (cfg->btcoex->timer_on) {
+ cfg->btcoex->timer_on = false;
+ del_timer_sync(&cfg->btcoex->timer);
+ }
+
+ cancel_work_sync(&cfg->btcoex->work);
+
+ brcmf_btcoex_boost_wifi(cfg->btcoex, false);
+ brcmf_btcoex_restore_part1(cfg->btcoex);
+
+ kfree(cfg->btcoex);
+ cfg->btcoex = NULL;
+}
+
+static void brcmf_btcoex_dhcp_start(struct brcmf_btcoex_info *btci)
+{
+ struct brcmf_if *ifp = btci->vif->ifp;
+
+ btcmf_btcoex_save_part1(btci);
+ /* set new regs values */
+ brcmf_btcoex_params_write(ifp, 66, BRCMF_BT_DHCP_REG66);
+ brcmf_btcoex_params_write(ifp, 41, BRCMF_BT_DHCP_REG41);
+ brcmf_btcoex_params_write(ifp, 68, BRCMF_BT_DHCP_REG68);
+ btci->dhcp_done = false;
+ btci->bt_state = BRCMF_BT_DHCP_START;
+ schedule_work(&btci->work);
+ brcmf_dbg(TRACE, "enable BT DHCP Timer\n");
+}
+
+static void brcmf_btcoex_dhcp_end(struct brcmf_btcoex_info *btci)
+{
+ /* Stop any bt timer because DHCP session is done */
+ btci->dhcp_done = true;
+ if (btci->timer_on) {
+ brcmf_dbg(TRACE, "disable BT DHCP Timer\n");
+ btci->timer_on = false;
+ del_timer_sync(&btci->timer);
+
+ /* schedule worker if transition to IDLE is needed */
+ if (btci->bt_state != BRCMF_BT_DHCP_IDLE) {
+ brcmf_dbg(TRACE, "bt_state:%d\n",
+ btci->bt_state);
+ schedule_work(&btci->work);
+ }
+ } else {
+ /* Restore original values */
+ brcmf_btcoex_restore_part1(btci);
+ }
+}
+
+/**
+ * brcmf_btcoex_set_mode - set BT coex mode
+ * @cfg: driver private cfg80211 data
+ * @mode: Wifi-Bluetooth coexistence mode
+ *
+ * return: 0 on success
+ */
+int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
+ enum brcmf_btcoex_mode mode, u16 duration)
+{
+ struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy);
+ struct brcmf_btcoex_info *btci = cfg->btcoex;
+ struct brcmf_if *ifp = cfg->pub->iflist[0];
+
+ switch (mode) {
+ case BRCMF_BTCOEX_DISABLED:
+ brcmf_dbg(TRACE, "DHCP session starts\n");
+ if (btci->bt_state != BRCMF_BT_DHCP_IDLE)
+ return -EBUSY;
+ /* Start BT timer only for SCO connection */
+ if (brcmf_btcoex_is_sco_active(ifp)) {
+ btci->timeout = duration;
+ btci->vif = vif;
+ brcmf_btcoex_dhcp_start(btci);
+ }
+ break;
+
+ case BRCMF_BTCOEX_ENABLED:
+ brcmf_dbg(TRACE, "DHCP session ends\n");
+ if (btci->bt_state != BRCMF_BT_DHCP_IDLE &&
+ vif == btci->vif) {
+ brcmf_btcoex_dhcp_end(btci);
+ }
+ break;
+ default:
+ brcmf_dbg(TRACE, "Unknown mode, ignored\n");
+ }
+ return 0;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.h b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.h
new file mode 100644
index 000000000000..19647c68aa9e
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * 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.
+ */
+#ifndef WL_BTCOEX_H_
+#define WL_BTCOEX_H_
+
+enum brcmf_btcoex_mode {
+ BRCMF_BTCOEX_DISABLED,
+ BRCMF_BTCOEX_ENABLED
+};
+
+int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg);
+void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg);
+int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
+ enum brcmf_btcoex_mode mode, u16 duration);
+
+#endif /* WL_BTCOEX_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 5249c67b466c..28db9cf39672 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -28,6 +28,7 @@
/*******************************************************************************
* IO codes that are interpreted by dongle firmware
******************************************************************************/
+#define BRCMF_C_GET_VERSION 1
#define BRCMF_C_UP 2
#define BRCMF_C_DOWN 3
#define BRCMF_C_SET_PROMISC 10
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 763a84eba216..59c25463e428 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -754,14 +754,14 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
/* this is P2P_DEVICE interface */
brcmf_dbg(INFO, "allocate non-netdev interface\n");
ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
+ if (!ifp)
+ return ERR_PTR(-ENOMEM);
} else {
brcmf_dbg(INFO, "allocate netdev interface\n");
/* Allocate netdev, including space for private structure */
ndev = alloc_netdev(sizeof(*ifp), name, ether_setup);
- if (!ndev) {
- brcmf_err("OOM - alloc_netdev\n");
+ if (!ndev)
return ERR_PTR(-ENOMEM);
- }
ifp = netdev_priv(ndev);
ifp->ndev = ndev;
@@ -899,7 +899,10 @@ int brcmf_bus_start(struct device *dev)
goto fail;
drvr->fw_signals = true;
- (void)brcmf_fws_init(drvr);
+ ret = brcmf_fws_init(drvr);
+ if (ret < 0)
+ goto fail;
+
brcmf_fws_add_interface(ifp);
drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 4ff2d3c52ee6..d2487518bd2a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -31,6 +31,7 @@
#include <linux/bcma/bcma.h>
#include <linux/debugfs.h>
#include <linux/vmalloc.h>
+#include <linux/platform_data/brcmfmac-sdio.h>
#include <asm/unaligned.h>
#include <defs.h>
#include <brcmu_wifi.h>
@@ -324,6 +325,9 @@ MODULE_FIRMWARE(BRCMF_SDIO_NV_NAME);
*/
#define BRCMF_IDLE_INTERVAL 1
+#define KSO_WAIT_US 50
+#define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
+
/*
* Conversion of 802.1D priority to precedence level
*/
@@ -333,95 +337,6 @@ static uint prio2prec(u32 prio)
(prio^2) : prio;
}
-/* core registers */
-struct sdpcmd_regs {
- u32 corecontrol; /* 0x00, rev8 */
- u32 corestatus; /* rev8 */
- u32 PAD[1];
- u32 biststatus; /* rev8 */
-
- /* PCMCIA access */
- u16 pcmciamesportaladdr; /* 0x010, rev8 */
- u16 PAD[1];
- u16 pcmciamesportalmask; /* rev8 */
- u16 PAD[1];
- u16 pcmciawrframebc; /* rev8 */
- u16 PAD[1];
- u16 pcmciaunderflowtimer; /* rev8 */
- u16 PAD[1];
-
- /* interrupt */
- u32 intstatus; /* 0x020, rev8 */
- u32 hostintmask; /* rev8 */
- u32 intmask; /* rev8 */
- u32 sbintstatus; /* rev8 */
- u32 sbintmask; /* rev8 */
- u32 funcintmask; /* rev4 */
- u32 PAD[2];
- u32 tosbmailbox; /* 0x040, rev8 */
- u32 tohostmailbox; /* rev8 */
- u32 tosbmailboxdata; /* rev8 */
- u32 tohostmailboxdata; /* rev8 */
-
- /* synchronized access to registers in SDIO clock domain */
- u32 sdioaccess; /* 0x050, rev8 */
- u32 PAD[3];
-
- /* PCMCIA frame control */
- u8 pcmciaframectrl; /* 0x060, rev8 */
- u8 PAD[3];
- u8 pcmciawatermark; /* rev8 */
- u8 PAD[155];
-
- /* interrupt batching control */
- u32 intrcvlazy; /* 0x100, rev8 */
- u32 PAD[3];
-
- /* counters */
- u32 cmd52rd; /* 0x110, rev8 */
- u32 cmd52wr; /* rev8 */
- u32 cmd53rd; /* rev8 */
- u32 cmd53wr; /* rev8 */
- u32 abort; /* rev8 */
- u32 datacrcerror; /* rev8 */
- u32 rdoutofsync; /* rev8 */
- u32 wroutofsync; /* rev8 */
- u32 writebusy; /* rev8 */
- u32 readwait; /* rev8 */
- u32 readterm; /* rev8 */
- u32 writeterm; /* rev8 */
- u32 PAD[40];
- u32 clockctlstatus; /* rev8 */
- u32 PAD[7];
-
- u32 PAD[128]; /* DMA engines */
-
- /* SDIO/PCMCIA CIS region */
- char cis[512]; /* 0x400-0x5ff, rev6 */
-
- /* PCMCIA function control registers */
- char pcmciafcr[256]; /* 0x600-6ff, rev6 */
- u16 PAD[55];
-
- /* PCMCIA backplane access */
- u16 backplanecsr; /* 0x76E, rev6 */
- u16 backplaneaddr0; /* rev6 */
- u16 backplaneaddr1; /* rev6 */
- u16 backplaneaddr2; /* rev6 */
- u16 backplaneaddr3; /* rev6 */
- u16 backplanedata0; /* rev6 */
- u16 backplanedata1; /* rev6 */
- u16 backplanedata2; /* rev6 */
- u16 backplanedata3; /* rev6 */
- u16 PAD[31];
-
- /* sprom "size" & "blank" info */
- u16 spromstatus; /* 0x7BE, rev2 */
- u32 PAD[464];
-
- u16 PAD[0x80];
-};
-
#ifdef DEBUG
/* Device console log buffer state */
struct brcmf_console {
@@ -588,12 +503,14 @@ struct brcmf_sdio {
bool txoff; /* Transmit flow-controlled */
struct brcmf_sdio_count sdcnt;
+ bool sr_enabled; /* SaveRestore enabled */
+ bool sleeping; /* SDIO bus sleeping */
};
/* clkstate */
#define CLK_NONE 0
#define CLK_SDONLY 1
-#define CLK_PENDING 2 /* Not used yet */
+#define CLK_PENDING 2
#define CLK_AVAIL 3
#ifdef DEBUG
@@ -601,7 +518,7 @@ static int qcount[NUMPRIO];
static int tx_packets[NUMPRIO];
#endif /* DEBUG */
-#define SDIO_DRIVE_STRENGTH 6 /* in milliamps */
+#define DEFAULT_SDIO_DRIVE_STRENGTH 6 /* in milliamps */
#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL)
@@ -665,6 +582,62 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
return ret;
}
+static int
+brcmf_sdbrcm_kso_control(struct brcmf_sdio *bus, bool on)
+{
+ u8 wr_val = 0, rd_val, cmp_val, bmask;
+ int err = 0;
+ int try_cnt = 0;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
+ /* 1st KSO write goes to AOS wake up core if device is asleep */
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ wr_val, &err);
+ if (err) {
+ brcmf_err("SDIO_AOS KSO write error: %d\n", err);
+ return err;
+ }
+
+ if (on) {
+ /* device WAKEUP through KSO:
+ * write bit 0 & read back until
+ * both bits 0 (kso bit) & 1 (dev on status) are set
+ */
+ cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |
+ SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
+ bmask = cmp_val;
+ usleep_range(2000, 3000);
+ } else {
+ /* Put device to sleep, turn off KSO */
+ cmp_val = 0;
+ /* only check for bit0, bit1(dev on status) may not
+ * get cleared right away
+ */
+ bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
+ }
+
+ do {
+ /* reliable KSO bit set/clr:
+ * the sdiod sleep write access is synced to PMU 32khz clk
+ * just one write attempt may fail,
+ * read it back until it matches written value
+ */
+ rd_val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ &err);
+ if (((rd_val & bmask) == cmp_val) && !err)
+ break;
+ brcmf_dbg(SDIO, "KSO wr/rd retry:%d (max: %d) ERR:%x\n",
+ try_cnt, MAX_KSO_ATTEMPTS, err);
+ udelay(KSO_WAIT_US);
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ wr_val, &err);
+ } while (try_cnt++ < MAX_KSO_ATTEMPTS);
+
+ return err;
+}
+
#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
@@ -680,6 +653,11 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
clkctl = 0;
+ if (bus->sr_enabled) {
+ bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
+ return 0;
+ }
+
if (on) {
/* Request HT Avail */
clkreq =
@@ -856,6 +834,63 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
return 0;
}
+static int
+brcmf_sdbrcm_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
+{
+ int err = 0;
+ brcmf_dbg(TRACE, "Enter\n");
+ brcmf_dbg(SDIO, "request %s currently %s\n",
+ (sleep ? "SLEEP" : "WAKE"),
+ (bus->sleeping ? "SLEEP" : "WAKE"));
+
+ /* If SR is enabled control bus state with KSO */
+ if (bus->sr_enabled) {
+ /* Done if we're already in the requested state */
+ if (sleep == bus->sleeping)
+ goto end;
+
+ /* Going to sleep */
+ if (sleep) {
+ /* Don't sleep if something is pending */
+ if (atomic_read(&bus->intstatus) ||
+ atomic_read(&bus->ipend) > 0 ||
+ (!atomic_read(&bus->fcstate) &&
+ brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
+ data_ok(bus)))
+ return -EBUSY;
+ err = brcmf_sdbrcm_kso_control(bus, false);
+ /* disable watchdog */
+ if (!err)
+ brcmf_sdbrcm_wd_timer(bus, 0);
+ } else {
+ bus->idlecount = 0;
+ err = brcmf_sdbrcm_kso_control(bus, true);
+ }
+ if (!err) {
+ /* Change state */
+ bus->sleeping = sleep;
+ brcmf_dbg(SDIO, "new state %s\n",
+ (sleep ? "SLEEP" : "WAKE"));
+ } else {
+ brcmf_err("error while changing bus sleep state %d\n",
+ err);
+ return err;
+ }
+ }
+
+end:
+ /* control clocks */
+ if (sleep) {
+ if (!bus->sr_enabled)
+ brcmf_sdbrcm_clkctl(bus, CLK_NONE, pendok);
+ } else {
+ brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, pendok);
+ }
+
+ return err;
+
+}
+
static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
{
u32 intstatus = 0;
@@ -1960,7 +1995,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
sdio_claim_host(bus->sdiodev->func[1]);
/* Enable clock for device interrupts */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
/* Disable and clear interrupts at the chip level also */
w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask));
@@ -2012,23 +2047,19 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
bus->tx_seq = bus->rx_seq = 0;
}
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
{
unsigned long flags;
- spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
- if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
- enable_irq(bus->sdiodev->irq);
- bus->sdiodev->irq_en = true;
+ if (bus->sdiodev->oob_irq_requested) {
+ spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags);
+ if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) {
+ enable_irq(bus->sdiodev->pdata->oob_irq_nr);
+ bus->sdiodev->irq_en = true;
+ }
+ spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
}
- spin_unlock_irqrestore(&bus->sdiodev->irq_en_lock, flags);
-}
-#else
-static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus)
-{
}
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
{
@@ -2096,7 +2127,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
sdio_claim_host(bus->sdiodev->func[1]);
/* If waiting for HTAVAIL, check status */
- if (bus->clkstate == CLK_PENDING) {
+ if (!bus->sr_enabled && bus->clkstate == CLK_PENDING) {
u8 clkctl, devctl = 0;
#ifdef DEBUG
@@ -2142,7 +2173,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
}
/* Make sure backplane clock is on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true);
+ brcmf_sdbrcm_bus_sleep(bus, false, true);
/* Pending interrupt indicates new device status */
if (atomic_read(&bus->ipend) > 0) {
@@ -2288,8 +2319,9 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
if ((bus->clkstate != CLK_PENDING)
&& bus->idletime == BRCMF_IDLE_IMMEDIATE) {
bus->activity = false;
+ brcmf_dbg(SDIO, "idle state\n");
sdio_claim_host(bus->sdiodev->func[1]);
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ brcmf_sdbrcm_bus_sleep(bus, true, false);
sdio_release_host(bus->sdiodev->func[1]);
}
}
@@ -2362,69 +2394,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
return ret;
}
-static int
-brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
- uint size)
-{
- int bcmerror = 0;
- u32 sdaddr;
- uint dsize;
-
- /* Determine initial transfer parameters */
- sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
- if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
- dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
- else
- dsize = size;
-
- sdio_claim_host(bus->sdiodev->func[1]);
-
- /* Set the backplane window to include the start address */
- bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address);
- if (bcmerror) {
- brcmf_err("window change failed\n");
- goto xfer_done;
- }
-
- /* Do the transfer(s) */
- while (size) {
- brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
- write ? "write" : "read", dsize,
- sdaddr, address & SBSDIO_SBWINDOW_MASK);
- bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write,
- sdaddr, data, dsize);
- if (bcmerror) {
- brcmf_err("membytes transfer failed\n");
- break;
- }
-
- /* Adjust for next transfer (if any) */
- size -= dsize;
- if (size) {
- data += dsize;
- address += dsize;
- bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev,
- address);
- if (bcmerror) {
- brcmf_err("window change failed\n");
- break;
- }
- sdaddr = 0;
- dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
- }
- }
-
-xfer_done:
- /* Return the window to backplane enumeration space for core access */
- if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, bus->sdiodev->sbwad))
- brcmf_err("FAILED to set window back to 0x%x\n",
- bus->sdiodev->sbwad);
-
- sdio_release_host(bus->sdiodev->func[1]);
-
- return bcmerror;
-}
-
#ifdef DEBUG
#define CONSOLE_LINE_MAX 192
@@ -2441,8 +2410,8 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
/* Read console log struct */
addr = bus->console_addr + offsetof(struct rte_console, log_le);
- rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log_le,
- sizeof(c->log_le));
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&c->log_le,
+ sizeof(c->log_le));
if (rv < 0)
return rv;
@@ -2467,7 +2436,7 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus)
/* Read the console buffer */
addr = le32_to_cpu(c->log_le.buf);
- rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize);
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, c->buf, c->bufsize);
if (rv < 0)
return rv;
@@ -2592,7 +2561,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
/* Make sure backplane clock is on */
sdio_claim_host(bus->sdiodev->func[1]);
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
sdio_release_host(bus->sdiodev->func[1]);
/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
@@ -2650,6 +2619,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
bus->activity = false;
sdio_claim_host(bus->sdiodev->func[1]);
+ brcmf_dbg(INFO, "idle\n");
brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
sdio_release_host(bus->sdiodev->func[1]);
} else {
@@ -2679,16 +2649,15 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
struct sdpcm_shared_le sh_le;
__le32 addr_le;
- shaddr = bus->ramsize - 4;
+ shaddr = bus->ci->rambase + bus->ramsize - 4;
/*
* Read last word in socram to determine
* address of sdpcm_shared structure
*/
sdio_claim_host(bus->sdiodev->func[1]);
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
- rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
- (u8 *)&addr_le, 4);
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4);
sdio_release_host(bus->sdiodev->func[1]);
if (rv < 0)
return rv;
@@ -2708,8 +2677,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
}
/* Read hndrte_shared structure */
- rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
- sizeof(struct sdpcm_shared_le));
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
+ sizeof(struct sdpcm_shared_le));
if (rv < 0)
return rv;
@@ -2745,22 +2714,22 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
/* obtain console information from device memory */
addr = sh->console_addr + offsetof(struct rte_console, log_le);
- rv = brcmf_sdbrcm_membytes(bus, false, addr,
- (u8 *)&sh_val, sizeof(u32));
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
+ (u8 *)&sh_val, sizeof(u32));
if (rv < 0)
return rv;
console_ptr = le32_to_cpu(sh_val);
addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size);
- rv = brcmf_sdbrcm_membytes(bus, false, addr,
- (u8 *)&sh_val, sizeof(u32));
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
+ (u8 *)&sh_val, sizeof(u32));
if (rv < 0)
return rv;
console_size = le32_to_cpu(sh_val);
addr = sh->console_addr + offsetof(struct rte_console, log_le.idx);
- rv = brcmf_sdbrcm_membytes(bus, false, addr,
- (u8 *)&sh_val, sizeof(u32));
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, addr,
+ (u8 *)&sh_val, sizeof(u32));
if (rv < 0)
return rv;
console_index = le32_to_cpu(sh_val);
@@ -2774,8 +2743,8 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
/* obtain the console data from device */
conbuf[console_size] = '\0';
- rv = brcmf_sdbrcm_membytes(bus, false, console_ptr, (u8 *)conbuf,
- console_size);
+ rv = brcmf_sdio_ramrw(bus->sdiodev, false, console_ptr, (u8 *)conbuf,
+ console_size);
if (rv < 0)
goto done;
@@ -2812,8 +2781,8 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
return 0;
}
- error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
- sizeof(struct brcmf_trap_info));
+ error = brcmf_sdio_ramrw(bus->sdiodev, false, sh->trap_addr, (u8 *)&tr,
+ sizeof(struct brcmf_trap_info));
if (error < 0)
return error;
@@ -2856,14 +2825,14 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
sdio_claim_host(bus->sdiodev->func[1]);
if (sh->assert_file_addr != 0) {
- error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
- (u8 *)file, 80);
+ error = brcmf_sdio_ramrw(bus->sdiodev, false,
+ sh->assert_file_addr, (u8 *)file, 80);
if (error < 0)
return error;
}
if (sh->assert_exp_addr != 0) {
- error = brcmf_sdbrcm_membytes(bus, false, sh->assert_exp_addr,
- (u8 *)expr, 80);
+ error = brcmf_sdio_ramrw(bus->sdiodev, false,
+ sh->assert_exp_addr, (u8 *)expr, 80);
if (error < 0)
return error;
}
@@ -3021,84 +2990,8 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
return rxlen ? (int)rxlen : -ETIMEDOUT;
}
-static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus)
-{
- int bcmerror = 0;
- u32 varaddr;
- u32 varsizew;
- __le32 varsizew_le;
-#ifdef DEBUG
- char *nvram_ularray;
-#endif /* DEBUG */
-
- /* Even if there are no vars are to be written, we still
- need to set the ramsize. */
- varaddr = (bus->ramsize - 4) - bus->varsz;
-
- if (bus->vars) {
- /* Write the vars list */
- bcmerror = brcmf_sdbrcm_membytes(bus, true, varaddr,
- bus->vars, bus->varsz);
-#ifdef DEBUG
- /* Verify NVRAM bytes */
- brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n",
- bus->varsz);
- nvram_ularray = kmalloc(bus->varsz, GFP_ATOMIC);
- if (!nvram_ularray)
- return -ENOMEM;
-
- /* Upload image to verify downloaded contents. */
- memset(nvram_ularray, 0xaa, bus->varsz);
-
- /* Read the vars list to temp buffer for comparison */
- bcmerror = brcmf_sdbrcm_membytes(bus, false, varaddr,
- nvram_ularray, bus->varsz);
- if (bcmerror) {
- brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
- bcmerror, bus->varsz, varaddr);
- }
- /* Compare the org NVRAM with the one read from RAM */
- if (memcmp(bus->vars, nvram_ularray, bus->varsz))
- brcmf_err("Downloaded NVRAM image is corrupted\n");
- else
- brcmf_err("Download/Upload/Compare of NVRAM ok\n");
-
- kfree(nvram_ularray);
-#endif /* DEBUG */
- }
-
- /* adjust to the user specified RAM */
- brcmf_dbg(INFO, "Physical memory size: %d\n", bus->ramsize);
- brcmf_dbg(INFO, "Vars are at %d, orig varsize is %d\n",
- varaddr, bus->varsz);
-
- /*
- * Determine the length token:
- * Varsize, converted to words, in lower 16-bits, checksum
- * in upper 16-bits.
- */
- if (bcmerror) {
- varsizew = 0;
- varsizew_le = cpu_to_le32(0);
- } else {
- varsizew = bus->varsz / 4;
- varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
- varsizew_le = cpu_to_le32(varsizew);
- }
-
- brcmf_dbg(INFO, "New varsize is %d, length token=0x%08x\n",
- bus->varsz, varsizew);
-
- /* Write the length token to the last word */
- bcmerror = brcmf_sdbrcm_membytes(bus, true, (bus->ramsize - 4),
- (u8 *)&varsizew_le, 4);
-
- return bcmerror;
-}
-
-static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
+static bool brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
{
- int bcmerror = 0;
struct chip_info *ci = bus->ci;
/* To enter download state, disable ARM and reset SOCRAM.
@@ -3107,41 +3000,19 @@ static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter)
if (enter) {
bus->alp_only = true;
- ci->coredisable(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
-
- ci->resetcore(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM);
-
- /* Clear the top bit of memory */
- if (bus->ramsize) {
- u32 zeros = 0;
- brcmf_sdbrcm_membytes(bus, true, bus->ramsize - 4,
- (u8 *)&zeros, 4);
- }
+ brcmf_sdio_chip_enter_download(bus->sdiodev, ci);
} else {
- if (!ci->iscoreup(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
- brcmf_err("SOCRAM core is down after reset?\n");
- bcmerror = -EBADE;
- goto fail;
- }
-
- bcmerror = brcmf_sdbrcm_write_vars(bus);
- if (bcmerror) {
- brcmf_err("no vars written to RAM\n");
- bcmerror = 0;
- }
-
- w_sdreg32(bus, 0xFFFFFFFF,
- offsetof(struct sdpcmd_regs, intstatus));
-
- ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
+ if (!brcmf_sdio_chip_exit_download(bus->sdiodev, ci, bus->vars,
+ bus->varsz))
+ return false;
/* Allow HT Clock now that the ARM is running. */
bus->alp_only = false;
bus->sdiodev->bus_if->state = BRCMF_BUS_LOAD;
}
-fail:
- return bcmerror;
+
+ return true;
}
static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus)
@@ -3156,10 +3027,11 @@ static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus)
static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
{
- int offset = 0;
+ int offset;
uint len;
u8 *memblock = NULL, *memptr;
int ret;
+ u8 idx;
brcmf_dbg(INFO, "Enter\n");
@@ -3180,10 +3052,15 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
memptr += (BRCMF_SDALIGN -
((u32)(unsigned long)memblock % BRCMF_SDALIGN));
+ offset = bus->ci->rambase;
+
/* Download image */
- while ((len =
- brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus))) {
- ret = brcmf_sdbrcm_membytes(bus, true, offset, memptr, len);
+ len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus);
+ idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_ARM_CR4);
+ if (BRCMF_MAX_CORENUM != idx)
+ memcpy(&bus->ci->rst_vec, memptr, sizeof(bus->ci->rst_vec));
+ while (len) {
+ ret = brcmf_sdio_ramrw(bus->sdiodev, true, offset, memptr, len);
if (ret) {
brcmf_err("error %d on writing %d membytes at 0x%08x\n",
ret, MEMBLOCK, offset);
@@ -3191,6 +3068,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
}
offset += MEMBLOCK;
+ len = brcmf_sdbrcm_get_image((char *)memptr, MEMBLOCK, bus);
}
err:
@@ -3298,7 +3176,7 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
int bcmerror = -1;
/* Keep arm in reset */
- if (brcmf_sdbrcm_download_state(bus, true)) {
+ if (!brcmf_sdbrcm_download_state(bus, true)) {
brcmf_err("error placing ARM core in reset\n");
goto err;
}
@@ -3314,7 +3192,7 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
}
/* Take arm out of reset */
- if (brcmf_sdbrcm_download_state(bus, false)) {
+ if (!brcmf_sdbrcm_download_state(bus, false)) {
brcmf_err("error getting out of ARM core reset\n");
goto err;
}
@@ -3325,6 +3203,103 @@ err:
return bcmerror;
}
+static bool brcmf_sdbrcm_sr_capable(struct brcmf_sdio *bus)
+{
+ u32 addr, reg;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* old chips with PMU version less than 17 don't support save restore */
+ if (bus->ci->pmurev < 17)
+ return false;
+
+ /* read PMU chipcontrol register 3*/
+ addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_addr);
+ brcmf_sdio_regwl(bus->sdiodev, addr, 3, NULL);
+ addr = CORE_CC_REG(bus->ci->c_inf[0].base, chipcontrol_data);
+ reg = brcmf_sdio_regrl(bus->sdiodev, addr, NULL);
+
+ return (bool)reg;
+}
+
+static void brcmf_sdbrcm_sr_init(struct brcmf_sdio *bus)
+{
+ int err = 0;
+ u8 val;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL,
+ &err);
+ if (err) {
+ brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n");
+ return;
+ }
+
+ val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL,
+ val, &err);
+ if (err) {
+ brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n");
+ return;
+ }
+
+ /* Add CMD14 Support */
+ brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
+ (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
+ SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
+ &err);
+ if (err) {
+ brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n");
+ return;
+ }
+
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ SBSDIO_FORCE_HT, &err);
+ if (err) {
+ brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n");
+ return;
+ }
+
+ /* set flag */
+ bus->sr_enabled = true;
+ brcmf_dbg(INFO, "SR enabled\n");
+}
+
+/* enable KSO bit */
+static int brcmf_sdbrcm_kso_init(struct brcmf_sdio *bus)
+{
+ u8 val;
+ int err = 0;
+
+ brcmf_dbg(TRACE, "Enter\n");
+
+ /* KSO bit added in SDIO core rev 12 */
+ if (bus->ci->c_inf[1].rev < 12)
+ return 0;
+
+ val = brcmf_sdio_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ &err);
+ if (err) {
+ brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n");
+ return err;
+ }
+
+ if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
+ val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN <<
+ SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+ val, &err);
+ if (err) {
+ brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n");
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+
static bool
brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
{
@@ -3423,8 +3398,13 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
ret = -ENODEV;
}
- /* Restore previous clock setting */
- brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
+ if (brcmf_sdbrcm_sr_capable(bus)) {
+ brcmf_sdbrcm_sr_init(bus);
+ } else {
+ /* Restore previous clock setting */
+ brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ saveclk, &err);
+ }
if (ret == 0) {
ret = brcmf_sdio_intr_register(bus->sdiodev);
@@ -3485,7 +3465,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
brcmf_dbg(TIMER, "Enter\n");
/* Poll period: check device if appropriate. */
- if (bus->poll && (++bus->polltick >= bus->pollrate)) {
+ if (!bus->sr_enabled &&
+ bus->poll && (++bus->polltick >= bus->pollrate)) {
u32 intstatus = 0;
/* Reset poll tick */
@@ -3536,7 +3517,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->console.count -= bus->console_interval;
sdio_claim_host(bus->sdiodev->func[1]);
/* Make sure backplane clock is on */
- brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
+ brcmf_sdbrcm_bus_sleep(bus, false, false);
if (brcmf_sdbrcm_readconsole(bus) < 0)
/* stop on error */
bus->console_interval = 0;
@@ -3553,8 +3534,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
bus->activity = false;
brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
} else {
+ brcmf_dbg(SDIO, "idle\n");
sdio_claim_host(bus->sdiodev->func[1]);
- brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+ brcmf_sdbrcm_bus_sleep(bus, true, false);
sdio_release_host(bus->sdiodev->func[1]);
}
}
@@ -3565,6 +3547,8 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
static bool brcmf_sdbrcm_chipmatch(u16 chipid)
{
+ if (chipid == BCM43143_CHIP_ID)
+ return true;
if (chipid == BCM43241_CHIP_ID)
return true;
if (chipid == BCM4329_CHIP_ID)
@@ -3573,6 +3557,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid)
return true;
if (chipid == BCM4334_CHIP_ID)
return true;
+ if (chipid == BCM4335_CHIP_ID)
+ return true;
return false;
}
@@ -3650,7 +3636,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
int err = 0;
int reg_addr;
u32 reg_val;
- u8 idx;
+ u32 drivestrength;
bus->alp_only = true;
@@ -3686,8 +3672,16 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
goto fail;
}
- brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci,
- SDIO_DRIVE_STRENGTH);
+ if (brcmf_sdbrcm_kso_init(bus)) {
+ brcmf_err("error enabling KSO\n");
+ goto fail;
+ }
+
+ if ((bus->sdiodev->pdata) && (bus->sdiodev->pdata->drive_strength))
+ drivestrength = bus->sdiodev->pdata->drive_strength;
+ else
+ drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
+ brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength);
/* Get info on the SOCRAM cores... */
bus->ramsize = bus->ci->ramsize;
@@ -3696,12 +3690,37 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
goto fail;
}
- /* Set core control so an SDIO reset does a backplane reset */
- idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
- reg_addr = bus->ci->c_inf[idx].base +
- offsetof(struct sdpcmd_regs, corecontrol);
- reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL);
- brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL);
+ /* Set card control so an SDIO card reset does a WLAN backplane reset */
+ reg_val = brcmf_sdio_regrb(bus->sdiodev,
+ SDIO_CCCR_BRCM_CARDCTRL, &err);
+ if (err)
+ goto fail;
+
+ reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
+
+ brcmf_sdio_regwb(bus->sdiodev,
+ SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
+ if (err)
+ goto fail;
+
+ /* set PMUControl so a backplane reset does PMU state reload */
+ reg_addr = CORE_CC_REG(bus->ci->c_inf[0].base,
+ pmucontrol);
+ reg_val = brcmf_sdio_regrl(bus->sdiodev,
+ reg_addr,
+ &err);
+ if (err)
+ goto fail;
+
+ reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);
+
+ brcmf_sdio_regwl(bus->sdiodev,
+ reg_addr,
+ reg_val,
+ &err);
+ if (err)
+ goto fail;
+
sdio_release_host(bus->sdiodev->func[1]);
@@ -3755,6 +3774,10 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus)
bus->use_rxchain = false;
bus->sd_rxchain = false;
+ /* SR state */
+ bus->sleeping = false;
+ bus->sr_enabled = false;
+
return true;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index b3c608ee37cf..5352dc1fdf3c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -21,6 +21,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/err.h>
+#include <linux/jiffies.h>
#include <uapi/linux/nl80211.h>
#include <net/cfg80211.h>
@@ -31,8 +32,11 @@
#include "dhd_dbg.h"
#include "dhd_bus.h"
#include "fwil.h"
+#include "fwil_types.h"
#include "fweh.h"
#include "fwsignal.h"
+#include "p2p.h"
+#include "wl_cfg80211.h"
/**
* DOC: Firmware Signalling
@@ -144,6 +148,9 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
#define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST 0x01
#define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED 0x02
+#define BRCMF_FWS_RET_OK_NOSCHEDULE 0
+#define BRCMF_FWS_RET_OK_SCHEDULE 1
+
/**
* enum brcmf_fws_skb_state - indicates processing state of skb.
*
@@ -265,6 +272,9 @@ struct brcmf_skbuff_cb {
brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \
BRCMF_FWS_TXSTAT_ ## field ## _SHIFT)
+/* How long to defer borrowing in jiffies */
+#define BRCMF_FWS_BORROW_DEFER_PERIOD (HZ / 10)
+
/**
* enum brcmf_fws_fifo - fifo indices used by dongle firmware.
*
@@ -419,9 +429,11 @@ struct brcmf_fws_info {
struct work_struct fws_dequeue_work;
u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT];
int fifo_credit[BRCMF_FWS_FIFO_COUNT];
+ int credits_borrowed[BRCMF_FWS_FIFO_AC_VO + 1];
int deq_node_pos[BRCMF_FWS_FIFO_COUNT];
u32 fifo_credit_map;
u32 fifo_delay_map;
+ unsigned long borrow_defer_timestamp;
};
/*
@@ -678,28 +690,28 @@ brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea)
}
static struct brcmf_fws_mac_descriptor*
-brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, int ifidx, u8 *da)
+brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp,
+ u8 *da)
{
struct brcmf_fws_mac_descriptor *entry = &fws->desc.other;
- struct brcmf_if *ifp;
bool multicast;
+ enum nl80211_iftype iftype;
- brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx);
+ brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
multicast = is_multicast_ether_addr(da);
- ifp = fws->drvr->iflist[ifidx ? ifidx + 1 : 0];
- if (WARN_ON(!ifp))
- goto done;
+ iftype = brcmf_cfg80211_get_iftype(ifp);
/* Multicast destination and P2P clients get the interface entry.
* STA gets the interface entry if there is no exact match. For
* example, TDLS destinations have their own entry.
*/
entry = NULL;
- if (multicast && ifp->fws_desc)
+ if ((multicast || iftype == NL80211_IFTYPE_STATION ||
+ iftype == NL80211_IFTYPE_P2P_CLIENT) && ifp->fws_desc)
entry = ifp->fws_desc;
- if (entry != NULL && multicast)
+ if (entry != NULL && iftype != NL80211_IFTYPE_STATION)
goto done;
entry = brcmf_fws_mac_descriptor_lookup(fws, da);
@@ -711,26 +723,29 @@ done:
return entry;
}
-static bool brcmf_fws_mac_desc_ready(struct brcmf_fws_mac_descriptor *entry,
- int fifo)
+static bool brcmf_fws_mac_desc_closed(struct brcmf_fws_info *fws,
+ struct brcmf_fws_mac_descriptor *entry,
+ int fifo)
{
- bool ready;
+ struct brcmf_fws_mac_descriptor *if_entry;
+ bool closed;
- /*
- * destination entry is ready when firmware says it is OPEN
- * and there are no packets enqueued for it.
+ /* for unique destination entries the related interface
+ * may be closed.
*/
- ready = entry->state == BRCMF_FWS_STATE_OPEN &&
- !entry->suppressed &&
- brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0;
-
- /*
- * Or when the destination entry is CLOSED, but firmware has
- * specifically requested packets for this entry.
+ if (entry->mac_handle) {
+ if_entry = &fws->desc.iface[entry->interface_id];
+ if (if_entry->state == BRCMF_FWS_STATE_CLOSE)
+ return true;
+ }
+ /* an entry is closed when the state is closed and
+ * the firmware did not request anything.
*/
- ready = ready || (entry->state == BRCMF_FWS_STATE_CLOSE &&
- (entry->requested_credit + entry->requested_packet));
- return ready;
+ closed = entry->state == BRCMF_FWS_STATE_CLOSE &&
+ !entry->requested_credit && !entry->requested_packet;
+
+ /* Or firmware does not allow traffic for given fifo */
+ return closed || !(entry->ac_bitmap & BIT(fifo));
}
static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_info *fws,
@@ -825,11 +840,12 @@ brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
{
struct brcmf_if *ifp = fws->drvr->iflist[if_id];
- brcmf_dbg(TRACE,
- "enter: bssidx=%d, ifidx=%d\n", ifp->bssidx, ifp->ifidx);
if (WARN_ON(!ifp))
return;
+ brcmf_dbg(TRACE,
+ "enter: bssidx=%d, ifidx=%d\n", ifp->bssidx, ifp->ifidx);
+
if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER)
brcmf_txflowblock_if(ifp,
@@ -861,9 +877,10 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
entry = &fws->desc.nodes[mac_handle & 0x1F];
if (type == BRCMF_FWS_TYPE_MACDESC_DEL) {
brcmf_dbg(TRACE, "deleting mac %pM idx %d\n", addr, ifidx);
- if (entry->occupied)
+ if (entry->occupied) {
+ brcmf_fws_mac_desc_cleanup(fws, entry, -1);
brcmf_fws_clear_mac_descriptor(entry);
- else
+ } else
fws->stats.mac_update_failed++;
return 0;
}
@@ -914,12 +931,13 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
entry->requested_credit = 0;
if (type == BRCMF_FWS_TYPE_MAC_OPEN) {
entry->state = BRCMF_FWS_STATE_OPEN;
+ return BRCMF_FWS_RET_OK_SCHEDULE;
} else {
entry->state = BRCMF_FWS_STATE_CLOSE;
for (i = BRCMF_FWS_FIFO_AC_BE; i < NL80211_NUM_ACS; i++)
brcmf_fws_tim_update(fws, entry, i);
}
- return 0;
+ return BRCMF_FWS_RET_OK_NOSCHEDULE;
}
static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
@@ -946,10 +964,10 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
switch (type) {
case BRCMF_FWS_TYPE_INTERFACE_OPEN:
entry->state = BRCMF_FWS_STATE_OPEN;
- return 0;
+ return BRCMF_FWS_RET_OK_SCHEDULE;
case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
entry->state = BRCMF_FWS_STATE_CLOSE;
- return 0;
+ return BRCMF_FWS_RET_OK_NOSCHEDULE;
default:
ret = -EINVAL;
break;
@@ -979,15 +997,40 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
entry->requested_packet = data[0];
entry->ac_bitmap = data[2];
- return 0;
+ return BRCMF_FWS_RET_OK_SCHEDULE;
}
static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
u8 fifo, u8 credits)
{
+ int lender_ac;
+ int *borrowed;
+ int *fifo_credit;
+
if (!credits)
return;
+ if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
+ (fws->credits_borrowed[0])) {
+ for (lender_ac = BRCMF_FWS_FIFO_AC_VO; lender_ac >= 0;
+ lender_ac--) {
+ borrowed = &fws->credits_borrowed[lender_ac];
+ if (*borrowed) {
+ fws->fifo_credit_map |= (1 << lender_ac);
+ fifo_credit = &fws->fifo_credit[lender_ac];
+ if (*borrowed >= credits) {
+ *borrowed -= credits;
+ *fifo_credit += credits;
+ return;
+ } else {
+ credits -= *borrowed;
+ *fifo_credit += *borrowed;
+ *borrowed = 0;
+ }
+ }
+ }
+ }
+
fws->fifo_credit_map |= 1 << fifo;
fws->fifo_credit[fifo] += credits;
}
@@ -1074,7 +1117,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
int num_nodes;
int node_pos;
int prec_out;
- int pmsk = 3;
+ int pmsk;
int i;
table = (struct brcmf_fws_mac_descriptor *)&fws->desc;
@@ -1083,11 +1126,14 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
for (i = 0; i < num_nodes; i++) {
entry = &table[(node_pos + i) % num_nodes];
- if (!entry->occupied)
+ if (!entry->occupied ||
+ brcmf_fws_mac_desc_closed(fws, entry, fifo))
continue;
if (entry->suppressed)
pmsk = 2;
+ else
+ pmsk = 3;
p = brcmu_pktq_mdeq(&entry->psq, pmsk << (fifo * 2), &prec_out);
if (p == NULL) {
if (entry->suppressed) {
@@ -1250,7 +1296,7 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
brcmf_dbg(INFO, "ignored\n");
- return 0;
+ return BRCMF_FWS_RET_OK_NOSCHEDULE;
}
brcmf_dbg(TRACE, "enter: data %pM\n", data);
@@ -1259,8 +1305,7 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
brcmf_dbg(INFO, "map: credit %x delay %x\n", fws->fifo_credit_map,
fws->fifo_delay_map);
- brcmf_fws_schedule_deq(fws);
- return 0;
+ return BRCMF_FWS_RET_OK_SCHEDULE;
}
static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
@@ -1344,6 +1389,8 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
u8 type;
u8 len;
u8 *data;
+ s32 status;
+ s32 err;
brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n",
ifidx, skb->len, signal_len);
@@ -1363,6 +1410,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
data_len = signal_len;
signal_data = skb->data;
+ status = BRCMF_FWS_RET_OK_NOSCHEDULE;
while (data_len > 0) {
/* extract tlv info */
type = signal_data[0];
@@ -1388,6 +1436,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
if (len != brcmf_fws_get_tlv_len(fws, type))
break;
+ err = BRCMF_FWS_RET_OK_NOSCHEDULE;
switch (type) {
case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
case BRCMF_FWS_TYPE_COMP_TXSTATUS:
@@ -1398,21 +1447,22 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
break;
case BRCMF_FWS_TYPE_MAC_OPEN:
case BRCMF_FWS_TYPE_MAC_CLOSE:
- brcmf_fws_macdesc_state_indicate(fws, type, data);
+ err = brcmf_fws_macdesc_state_indicate(fws, type, data);
break;
case BRCMF_FWS_TYPE_INTERFACE_OPEN:
case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
- brcmf_fws_interface_state_indicate(fws, type, data);
+ err = brcmf_fws_interface_state_indicate(fws, type,
+ data);
break;
case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT:
case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET:
- brcmf_fws_request_indicate(fws, type, data);
+ err = brcmf_fws_request_indicate(fws, type, data);
break;
case BRCMF_FWS_TYPE_TXSTATUS:
brcmf_fws_txstatus_indicate(fws, data);
break;
case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
- brcmf_fws_fifocreditback_indicate(fws, data);
+ err = brcmf_fws_fifocreditback_indicate(fws, data);
break;
case BRCMF_FWS_TYPE_RSSI:
brcmf_fws_rssi_indicate(fws, *data);
@@ -1426,7 +1476,8 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
fws->stats.tlv_invalid_type++;
break;
}
-
+ if (err == BRCMF_FWS_RET_OK_SCHEDULE)
+ status = BRCMF_FWS_RET_OK_SCHEDULE;
signal_data += len + 2;
data_len -= len + 2;
}
@@ -1434,6 +1485,9 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
if (data_len != 0)
fws->stats.tlv_parse_failed++;
+ if (status == BRCMF_FWS_RET_OK_SCHEDULE)
+ brcmf_fws_schedule_deq(fws);
+
/* signalling processing result does
* not affect the actual ethernet packet.
*/
@@ -1553,7 +1607,7 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
return rc;
}
-static int
+static void
brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb)
{
/*
@@ -1595,7 +1649,6 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb)
/* free the hanger slot */
brcmf_fws_hanger_poppkt(&fws->hanger, hslot,
&pktout, true);
- brcmf_txfinalize(fws->drvr, skb, false);
rc = -EINVAL;
goto fail;
}
@@ -1629,11 +1682,31 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb)
fail:
- if (rc)
+ if (rc) {
+ brcmf_txfinalize(fws->drvr, skb, false);
fws->stats.rollback_failed++;
- else
+ } else
fws->stats.rollback_success++;
- return rc;
+}
+
+static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws)
+{
+ int lender_ac;
+
+ if (time_after(fws->borrow_defer_timestamp, jiffies))
+ return -ENAVAIL;
+
+ for (lender_ac = 0; lender_ac <= BRCMF_FWS_FIFO_AC_VO; lender_ac++) {
+ if (fws->fifo_credit[lender_ac]) {
+ fws->credits_borrowed[lender_ac]++;
+ fws->fifo_credit[lender_ac]--;
+ if (fws->fifo_credit[lender_ac] == 0)
+ fws->fifo_credit_map &= ~(1 << lender_ac);
+ brcmf_dbg(TRACE, "borrow credit from: %d\n", lender_ac);
+ return 0;
+ }
+ }
+ return -ENAVAIL;
}
static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo,
@@ -1669,8 +1742,17 @@ static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo,
return 0;
}
+ if (fifo != BRCMF_FWS_FIFO_AC_BE)
+ fws->borrow_defer_timestamp = jiffies +
+ BRCMF_FWS_BORROW_DEFER_PERIOD;
+
if (!(*credit)) {
- brcmf_dbg(TRACE, "exit: credits depleted\n");
+ /* Try to borrow a credit from other queue */
+ if (fifo == BRCMF_FWS_FIFO_AC_BE &&
+ brcmf_fws_borrow_credit(fws) == 0)
+ return 0;
+
+ brcmf_dbg(TRACE, "exit: ac=%d, credits depleted\n", fifo);
return -ENAVAIL;
}
(*credit)--;
@@ -1712,17 +1794,17 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
return rc;
rollback:
- rc = brcmf_fws_rollback_toq(fws, skb);
+ brcmf_fws_rollback_toq(fws, skb);
return rc;
}
int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
{
struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_fws_info *fws = drvr->fws;
struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
struct ethhdr *eh = (struct ethhdr *)(skb->data);
ulong flags;
- u8 ifidx = ifp->ifidx;
int fifo = BRCMF_FWS_FIFO_BCMC;
bool multicast = is_multicast_ether_addr(eh->h_dest);
@@ -1734,9 +1816,9 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
if (ntohs(eh->h_proto) == ETH_P_PAE)
atomic_inc(&ifp->pend_8021x_cnt);
- if (!brcmf_fws_fc_active(drvr->fws)) {
+ if (!brcmf_fws_fc_active(fws)) {
/* If the protocol uses a data header, apply it */
- brcmf_proto_hdrpush(drvr, ifidx, 0, skb);
+ brcmf_proto_hdrpush(drvr, ifp->ifidx, 0, skb);
/* Use bus module to send data frame */
return brcmf_bus_txdata(drvr->bus_if, skb);
@@ -1744,9 +1826,9 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
/* set control buffer information */
skcb->if_flags = 0;
- skcb->mac = brcmf_fws_find_mac_desc(drvr->fws, ifidx, eh->h_dest);
+ skcb->mac = brcmf_fws_find_mac_desc(fws, ifp, eh->h_dest);
skcb->state = BRCMF_FWS_SKBSTATE_NEW;
- brcmf_skb_if_flags_set_field(skb, INDEX, ifidx);
+ brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx);
if (!multicast)
fifo = brcmf_fws_prio2fifo[skb->priority];
brcmf_skb_if_flags_set_field(skb, FIFO, fifo);
@@ -1755,14 +1837,18 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
multicast, fifo);
brcmf_fws_lock(drvr, flags);
- if (!brcmf_fws_mac_desc_ready(skcb->mac, fifo) ||
+ if (skcb->mac->suppressed ||
+ brcmf_fws_mac_desc_closed(fws, skcb->mac, fifo) ||
+ brcmu_pktq_mlen(&skcb->mac->psq, 3 << (fifo * 2)) ||
(!multicast &&
- brcmf_fws_consume_credit(drvr->fws, fifo, skb) < 0)) {
+ brcmf_fws_consume_credit(fws, fifo, skb) < 0)) {
/* enqueue the packet in delayQ */
drvr->fws->fifo_delay_map |= 1 << fifo;
- brcmf_fws_enq(drvr->fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
+ brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
} else {
- brcmf_fws_commit_skb(drvr->fws, fifo, skb);
+ if (brcmf_fws_commit_skb(fws, fifo, skb))
+ if (!multicast)
+ brcmf_skb_pick_up_credit(fws, fifo, skb);
}
brcmf_fws_unlock(drvr, flags);
return 0;
@@ -1799,14 +1885,17 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
void brcmf_fws_del_interface(struct brcmf_if *ifp)
{
struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
+ ulong flags;
brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
if (!entry)
return;
+ brcmf_fws_lock(ifp->drvr, flags);
ifp->fws_desc = NULL;
brcmf_fws_clear_mac_descriptor(entry);
brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx);
+ brcmf_fws_unlock(ifp->drvr, flags);
}
static void brcmf_fws_dequeue_worker(struct work_struct *worker)
@@ -1826,14 +1915,29 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
fws->fifo_credit[fifo]);
for (credit = 0; credit < fws->fifo_credit[fifo]; /* nop */) {
skb = brcmf_fws_deq(fws, fifo);
- if (!skb)
+ if (!skb || brcmf_fws_commit_skb(fws, fifo, skb))
break;
- if (!brcmf_fws_commit_skb(fws, fifo, skb) &&
- brcmf_skbcb(skb)->if_flags &
+ if (brcmf_skbcb(skb)->if_flags &
BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)
credit++;
}
- fws->fifo_credit[fifo] -= credit;
+ if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
+ (credit == fws->fifo_credit[fifo])) {
+ fws->fifo_credit[fifo] -= credit;
+ while (brcmf_fws_borrow_credit(fws) == 0) {
+ skb = brcmf_fws_deq(fws, fifo);
+ if (!skb) {
+ brcmf_fws_return_credits(fws, fifo, 1);
+ break;
+ }
+ if (brcmf_fws_commit_skb(fws, fifo, skb)) {
+ brcmf_fws_return_credits(fws, fifo, 1);
+ break;
+ }
+ }
+ } else {
+ fws->fifo_credit[fifo] -= credit;
+ }
}
brcmf_fws_unlock(fws->drvr, flags);
}
@@ -1872,16 +1976,20 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS |
BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE;
- rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv);
+ rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
+ brcmf_fws_notify_credit_map);
if (rc < 0) {
- brcmf_err("failed to set bdcv2 tlv signaling\n");
+ brcmf_err("register credit map handler failed\n");
goto fail;
}
- if (brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
- brcmf_fws_notify_credit_map)) {
- brcmf_err("register credit map handler failed\n");
- goto fail;
+ /* setting the iovar may fail if feature is unsupported
+ * so leave the rc as is so driver initialization can
+ * continue.
+ */
+ if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) {
+ brcmf_err("failed to set bdcv2 tlv signaling\n");
+ goto fail_event;
}
brcmf_fws_hanger_init(&drvr->fws->hanger);
@@ -1897,9 +2005,9 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
drvr->fw_signals ? "enabled" : "disabled", tlv);
return 0;
+fail_event:
+ brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP);
fail:
- /* disable flow control entirely */
- drvr->fw_signals = false;
brcmf_fws_deinit(drvr);
return rc;
}
@@ -1912,6 +2020,14 @@ void brcmf_fws_deinit(struct brcmf_pub *drvr)
if (!fws)
return;
+ /* disable firmware signalling entirely
+ * to avoid using the workqueue.
+ */
+ drvr->fw_signals = false;
+
+ if (drvr->fws->fws_wq)
+ destroy_workqueue(drvr->fws->fws_wq);
+
/* cleanup */
brcmf_fws_lock(drvr, flags);
brcmf_fws_cleanup(fws, -1);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
index 94ff045df2b3..2b90da0d85f3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
@@ -424,29 +424,6 @@ static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len)
/**
- * brcmf_p2p_chnr_to_chspec() - convert channel number to chanspec.
- *
- * @channel: channel number
- */
-static u16 brcmf_p2p_chnr_to_chspec(u16 channel)
-{
- u16 chanspec;
-
- chanspec = channel & WL_CHANSPEC_CHAN_MASK;
-
- if (channel <= CH_MAX_2G_CHANNEL)
- chanspec |= WL_CHANSPEC_BAND_2G;
- else
- chanspec |= WL_CHANSPEC_BAND_5G;
-
- chanspec |= WL_CHANSPEC_BW_20;
- chanspec |= WL_CHANSPEC_CTL_SB_NONE;
-
- return chanspec;
-}
-
-
-/**
* brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation.
*
* @ifp: ifp to use for iovars (primary).
@@ -837,7 +814,8 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
IEEE80211_CHAN_PASSIVE_SCAN))
continue;
- chanspecs[i] = channel_to_chanspec(chan);
+ chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf,
+ chan);
brcmf_dbg(INFO, "%d: chan=%d, channel spec=%x\n",
num_nodfs, chan->hw_value, chanspecs[i]);
num_nodfs++;
@@ -945,8 +923,8 @@ static s32
brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration)
{
struct brcmf_cfg80211_vif *vif;
+ struct brcmu_chan ch;
s32 err = 0;
- u16 chanspec;
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
if (!vif) {
@@ -961,9 +939,11 @@ brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration)
goto exit;
}
- chanspec = brcmf_p2p_chnr_to_chspec(channel);
+ ch.chnum = channel;
+ ch.bw = BRCMU_CHAN_BW_20;
+ p2p->cfg->d11inf.encchspec(&ch);
err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN,
- chanspec, (u16)duration);
+ ch.chspec, (u16)duration);
if (!err) {
set_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status);
p2p->remain_on_channel_cookie++;
@@ -1075,6 +1055,7 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel)
u32 channel_cnt;
u16 *default_chan_list;
u32 i;
+ struct brcmu_chan ch;
brcmf_dbg(TRACE, "Enter\n");
@@ -1089,15 +1070,23 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel)
err = -ENOMEM;
goto exit;
}
+ ch.bw = BRCMU_CHAN_BW_20;
if (channel) {
+ ch.chnum = channel;
+ p2p->cfg->d11inf.encchspec(&ch);
/* insert same channel to the chan_list */
for (i = 0; i < channel_cnt; i++)
- default_chan_list[i] =
- brcmf_p2p_chnr_to_chspec(channel);
+ default_chan_list[i] = ch.chspec;
} else {
- default_chan_list[0] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_1);
- default_chan_list[1] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_2);
- default_chan_list[2] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_3);
+ ch.chnum = SOCIAL_CHAN_1;
+ p2p->cfg->d11inf.encchspec(&ch);
+ default_chan_list[0] = ch.chspec;
+ ch.chnum = SOCIAL_CHAN_2;
+ p2p->cfg->d11inf.encchspec(&ch);
+ default_chan_list[1] = ch.chspec;
+ ch.chnum = SOCIAL_CHAN_3;
+ p2p->cfg->d11inf.encchspec(&ch);
+ default_chan_list[2] = ch.chspec;
}
err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list,
WL_P2P_DISC_ST_SEARCH, WL_ESCAN_ACTION_START,
@@ -1227,6 +1216,7 @@ bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
{
struct brcmf_p2p_info *p2p = &cfg->p2p;
struct afx_hdl *afx_hdl = &p2p->afx_hdl;
+ struct brcmu_chan ch;
u8 *ie;
s32 err;
u8 p2p_dev_addr[ETH_ALEN];
@@ -1252,8 +1242,12 @@ bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
p2p_dev_addr, sizeof(p2p_dev_addr));
if ((err >= 0) &&
(!memcmp(p2p_dev_addr, afx_hdl->tx_dst_addr, ETH_ALEN))) {
- afx_hdl->peer_chan = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+ if (!bi->ctl_ch) {
+ ch.chspec = le16_to_cpu(bi->chanspec);
+ cfg->d11inf.decchspec(&ch);
+ bi->ctl_ch = ch.chnum;
+ }
+ afx_hdl->peer_chan = bi->ctl_ch;
brcmf_dbg(TRACE, "ACTION FRAME SCAN : Peer %pM found, channel : %d\n",
afx_hdl->tx_dst_addr, afx_hdl->peer_chan);
complete(&afx_hdl->act_frm_scan);
@@ -1360,12 +1354,14 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
u8 *frame = (u8 *)(rxframe + 1);
struct brcmf_p2p_pub_act_frame *act_frm;
struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm;
- u16 chanspec = be16_to_cpu(rxframe->chanspec);
+ struct brcmu_chan ch;
struct ieee80211_mgmt *mgmt_frame;
s32 freq;
u16 mgmt_type;
u8 action;
+ ch.chspec = be16_to_cpu(rxframe->chanspec);
+ cfg->d11inf.decchspec(&ch);
/* Check if wpa_supplicant has registered for this frame */
brcmf_dbg(INFO, "ifp->vif->mgmt_rx_reg %04x\n", ifp->vif->mgmt_rx_reg);
mgmt_type = (IEEE80211_STYPE_ACTION & IEEE80211_FCTL_STYPE) >> 4;
@@ -1384,7 +1380,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
&p2p->status) &&
(memcmp(afx_hdl->tx_dst_addr, e->addr,
ETH_ALEN) == 0)) {
- afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec);
+ afx_hdl->peer_chan = ch.chnum;
brcmf_dbg(INFO, "GON request: Peer found, channel=%d\n",
afx_hdl->peer_chan);
complete(&afx_hdl->act_frm_scan);
@@ -1427,8 +1423,8 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
memcpy(&mgmt_frame->u, frame, mgmt_frame_len);
mgmt_frame_len += offsetof(struct ieee80211_mgmt, u);
- freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec),
- CHSPEC_IS2G(chanspec) ?
+ freq = ieee80211_channel_to_frequency(ch.chnum,
+ ch.band == BRCMU_CHAN_BAND_2G ?
IEEE80211_BAND_2GHZ :
IEEE80211_BAND_5GHZ);
@@ -1854,6 +1850,7 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
struct brcmf_cfg80211_vif *vif = ifp->vif;
struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
u16 chanspec = be16_to_cpu(rxframe->chanspec);
+ struct brcmu_chan ch;
u8 *mgmt_frame;
u32 mgmt_frame_len;
s32 freq;
@@ -1862,9 +1859,12 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code,
e->reason);
+ ch.chspec = be16_to_cpu(rxframe->chanspec);
+ cfg->d11inf.decchspec(&ch);
+
if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) &&
(memcmp(afx_hdl->tx_dst_addr, e->addr, ETH_ALEN) == 0)) {
- afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec);
+ afx_hdl->peer_chan = ch.chnum;
brcmf_dbg(INFO, "PROBE REQUEST: Peer found, channel=%d\n",
afx_hdl->peer_chan);
complete(&afx_hdl->act_frm_scan);
@@ -1889,8 +1889,8 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
mgmt_frame = (u8 *)(rxframe + 1);
mgmt_frame_len = e->datalen - sizeof(*rxframe);
- freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec),
- CHSPEC_IS2G(chanspec) ?
+ freq = ieee80211_channel_to_frequency(ch.chnum,
+ ch.band == BRCMU_CHAN_BAND_2G ?
IEEE80211_BAND_2GHZ :
IEEE80211_BAND_5GHZ);
@@ -2014,21 +2014,19 @@ static void brcmf_p2p_get_current_chanspec(struct brcmf_p2p_info *p2p,
{
struct brcmf_if *ifp;
struct brcmf_fil_chan_info_le ci;
+ struct brcmu_chan ch;
s32 err;
ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
- *chanspec = 11 & WL_CHANSPEC_CHAN_MASK;
+ ch.chnum = 11;
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci));
- if (!err) {
- *chanspec = le32_to_cpu(ci.hw_channel) & WL_CHANSPEC_CHAN_MASK;
- if (*chanspec < CH_MAX_2G_CHANNEL)
- *chanspec |= WL_CHANSPEC_BAND_2G;
- else
- *chanspec |= WL_CHANSPEC_BAND_5G;
- }
- *chanspec |= WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE;
+ if (!err)
+ ch.chnum = le32_to_cpu(ci.hw_channel);
+ ch.bw = BRCMU_CHAN_BW_20;
+ p2p->cfg->d11inf.encchspec(&ch);
+ *chanspec = ch.chspec;
}
/**
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
index 14be2d5530ce..ca72177388b9 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
@@ -40,6 +40,15 @@
#define BCM4329_CORE_ARM_BASE 0x18002000
#define BCM4329_RAMSIZE 0x48000
+/* bcm43143 */
+/* SDIO device core */
+#define BCM43143_CORE_BUS_BASE 0x18002000
+/* internal memory core */
+#define BCM43143_CORE_SOCRAM_BASE 0x18004000
+/* ARM Cortex M3 core, ID 0x82a */
+#define BCM43143_CORE_ARM_BASE 0x18003000
+#define BCM43143_RAMSIZE 0x70000
+
#define SBCOREREV(sbidh) \
((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
((sbidh) & SSB_IDHIGH_RCLO))
@@ -52,6 +61,9 @@
#define CIB_REV_MASK 0xff000000
#define CIB_REV_SHIFT 24
+/* ARM CR4 core specific control flag bits */
+#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
+
#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
/* SDIO Pad drive strength to select value mappings */
struct sdiod_drive_str {
@@ -70,6 +82,14 @@ static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
{0, 0x1}
};
+/* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
+static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
+ {16, 0x7},
+ {12, 0x5},
+ {8, 0x3},
+ {4, 0x1}
+};
+
u8
brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
{
@@ -149,7 +169,7 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
static void
brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct chip_info *ci, u16 coreid, u32 core_bits)
{
u32 regdata, base;
u8 idx;
@@ -235,7 +255,7 @@ brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
static void
brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct chip_info *ci, u16 coreid, u32 core_bits)
{
u8 idx;
u32 regdata;
@@ -249,19 +269,36 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
if ((regdata & BCMA_RESET_CTL_RESET) != 0)
return;
- brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 0, NULL);
- regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+ /* ensure no pending backplane operation
+ * 300uc should be sufficient for backplane ops to be finish
+ * extra 10ms is taken into account for firmware load stage
+ * after 10300us carry on disabling the core anyway
+ */
+ SPINWAIT(brcmf_sdio_regrl(sdiodev,
+ ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
+ NULL), 10300);
+ regdata = brcmf_sdio_regrl(sdiodev,
+ ci->c_inf[idx].wrapbase+BCMA_RESET_ST,
NULL);
- udelay(10);
+ if (regdata)
+ brcmf_err("disabling core 0x%x with reset status %x\n",
+ coreid, regdata);
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
BCMA_RESET_CTL_RESET, NULL);
udelay(1);
+
+ brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+ core_bits, NULL);
+ regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
+ NULL);
+ usleep_range(10, 20);
+
}
static void
brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct chip_info *ci, u16 coreid, u32 core_bits)
{
u32 regdata;
u8 idx;
@@ -272,7 +309,7 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
* Must do the disable sequence first to work for
* arbitrary current core state.
*/
- brcmf_sdio_sb_coredisable(sdiodev, ci, coreid);
+ brcmf_sdio_sb_coredisable(sdiodev, ci, coreid, 0);
/*
* Now do the initialization sequence.
@@ -325,7 +362,7 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
static void
brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid)
+ struct chip_info *ci, u16 coreid, u32 core_bits)
{
u8 idx;
u32 regdata;
@@ -333,31 +370,69 @@ brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
/* must disable first to work for arbitrary current core state */
- brcmf_sdio_ai_coredisable(sdiodev, ci, coreid);
+ brcmf_sdio_ai_coredisable(sdiodev, ci, coreid, core_bits);
/* now do initialization sequence */
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
- BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
+ core_bits | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL);
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
NULL);
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
0, NULL);
+ regdata = brcmf_sdio_regrl(sdiodev,
+ ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
+ NULL);
udelay(1);
brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
- BCMA_IOCTL_CLK, NULL);
+ core_bits | BCMA_IOCTL_CLK, NULL);
regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
NULL);
udelay(1);
}
+#ifdef DEBUG
+/* safety check for chipinfo */
+static int brcmf_sdio_chip_cichk(struct chip_info *ci)
+{
+ u8 core_idx;
+
+ /* check RAM core presence for ARM CM3 core */
+ core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
+ if (BRCMF_MAX_CORENUM != core_idx) {
+ core_idx = brcmf_sdio_chip_getinfidx(ci,
+ BCMA_CORE_INTERNAL_MEM);
+ if (BRCMF_MAX_CORENUM == core_idx) {
+ brcmf_err("RAM core not provided with ARM CM3 core\n");
+ return -ENODEV;
+ }
+ }
+
+ /* check RAM base for ARM CR4 core */
+ core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CR4);
+ if (BRCMF_MAX_CORENUM != core_idx) {
+ if (ci->rambase == 0) {
+ brcmf_err("RAM base not provided with ARM CR4 core\n");
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+#else /* DEBUG */
+static inline int brcmf_sdio_chip_cichk(struct chip_info *ci)
+{
+ return 0;
+}
+#endif
+
static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u32 regs)
{
u32 regdata;
+ int ret;
- /*
- * Get CC core rev
+ /* Get CC core rev
* Chipid is assume to be at offset 0 from regs arg
* For different chiptypes or old sdio hosts w/o chipcommon,
* other ways of recognition should be added here.
@@ -375,6 +450,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
/* Address of cores for new chips should be added here */
switch (ci->chip) {
+ case BCM43143_CHIP_ID:
+ ci->c_inf[0].wrapbase = ci->c_inf[0].base + 0x00100000;
+ ci->c_inf[0].cib = 0x2b000000;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = BCM43143_CORE_BUS_BASE;
+ ci->c_inf[1].wrapbase = ci->c_inf[1].base + 0x00100000;
+ ci->c_inf[1].cib = 0x18000000;
+ ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
+ ci->c_inf[2].base = BCM43143_CORE_SOCRAM_BASE;
+ ci->c_inf[2].wrapbase = ci->c_inf[2].base + 0x00100000;
+ ci->c_inf[2].cib = 0x14000000;
+ ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
+ ci->c_inf[3].base = BCM43143_CORE_ARM_BASE;
+ ci->c_inf[3].wrapbase = ci->c_inf[3].base + 0x00100000;
+ ci->c_inf[3].cib = 0x07000000;
+ ci->ramsize = BCM43143_RAMSIZE;
+ break;
case BCM43241_CHIP_ID:
ci->c_inf[0].wrapbase = 0x18100000;
ci->c_inf[0].cib = 0x2a084411;
@@ -435,11 +527,29 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
ci->c_inf[3].cib = 0x07004211;
ci->ramsize = 0x80000;
break;
+ case BCM4335_CHIP_ID:
+ ci->c_inf[0].wrapbase = 0x18100000;
+ ci->c_inf[0].cib = 0x2b084411;
+ ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+ ci->c_inf[1].base = 0x18005000;
+ ci->c_inf[1].wrapbase = 0x18105000;
+ ci->c_inf[1].cib = 0x0f004211;
+ ci->c_inf[2].id = BCMA_CORE_ARM_CR4;
+ ci->c_inf[2].base = 0x18002000;
+ ci->c_inf[2].wrapbase = 0x18102000;
+ ci->c_inf[2].cib = 0x01084411;
+ ci->ramsize = 0xc0000;
+ ci->rambase = 0x180000;
+ break;
default:
brcmf_err("chipid 0x%x is not supported\n", ci->chip);
return -ENODEV;
}
+ ret = brcmf_sdio_chip_cichk(ci);
+ if (ret)
+ return ret;
+
switch (ci->socitype) {
case SOCI_SB:
ci->iscoreup = brcmf_sdio_sb_iscoreup;
@@ -539,7 +649,7 @@ brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
* Make sure any on-chip ARM is off (in case strapping is wrong),
* or downloaded code was already running.
*/
- ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3);
+ ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
}
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
@@ -600,21 +710,37 @@ void
brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u32 drivestrength)
{
- struct sdiod_drive_str *str_tab = NULL;
- u32 str_mask = 0;
- u32 str_shift = 0;
+ const struct sdiod_drive_str *str_tab = NULL;
+ u32 str_mask;
+ u32 str_shift;
char chn[8];
u32 base = ci->c_inf[0].base;
+ u32 i;
+ u32 drivestrength_sel = 0;
+ u32 cc_data_temp;
+ u32 addr;
if (!(ci->c_inf[0].caps & CC_CAP_PMU))
return;
switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
- str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab1_1v8;
+ str_tab = sdiod_drvstr_tab1_1v8;
str_mask = 0x00003800;
str_shift = 11;
break;
+ case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
+ /* note: 43143 does not support tristate */
+ i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
+ if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
+ str_tab = sdiod_drvstr_tab2_3v3;
+ str_mask = 0x00000007;
+ str_shift = 0;
+ } else
+ brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
+ brcmf_sdio_chip_name(ci->chip, chn, 8),
+ drivestrength);
+ break;
default:
brcmf_err("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
brcmf_sdio_chip_name(ci->chip, chn, 8),
@@ -623,30 +749,207 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
}
if (str_tab != NULL) {
- u32 drivestrength_sel = 0;
- u32 cc_data_temp;
- int i;
-
for (i = 0; str_tab[i].strength != 0; i++) {
if (drivestrength >= str_tab[i].strength) {
drivestrength_sel = str_tab[i].sel;
break;
}
}
-
- brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr),
- 1, NULL);
- cc_data_temp =
- brcmf_sdio_regrl(sdiodev,
- CORE_CC_REG(base, chipcontrol_addr),
- NULL);
+ addr = CORE_CC_REG(base, chipcontrol_addr);
+ brcmf_sdio_regwl(sdiodev, addr, 1, NULL);
+ cc_data_temp = brcmf_sdio_regrl(sdiodev, addr, NULL);
cc_data_temp &= ~str_mask;
drivestrength_sel <<= str_shift;
cc_data_temp |= drivestrength_sel;
- brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr),
- cc_data_temp, NULL);
+ brcmf_sdio_regwl(sdiodev, addr, cc_data_temp, NULL);
- brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
- drivestrength, cc_data_temp);
+ brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
+ str_tab[i].strength, drivestrength, cc_data_temp);
}
}
+
+#ifdef DEBUG
+static bool
+brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
+ char *nvram_dat, uint nvram_sz)
+{
+ char *nvram_ularray;
+ int err;
+ bool ret = true;
+
+ /* read back and verify */
+ brcmf_dbg(INFO, "Compare NVRAM dl & ul; size=%d\n", nvram_sz);
+ nvram_ularray = kmalloc(nvram_sz, GFP_KERNEL);
+ /* do not proceed while no memory but */
+ if (!nvram_ularray)
+ return true;
+
+ /* Upload image to verify downloaded contents. */
+ memset(nvram_ularray, 0xaa, nvram_sz);
+
+ /* Read the vars list to temp buffer for comparison */
+ err = brcmf_sdio_ramrw(sdiodev, false, nvram_addr, nvram_ularray,
+ nvram_sz);
+ if (err) {
+ brcmf_err("error %d on reading %d nvram bytes at 0x%08x\n",
+ err, nvram_sz, nvram_addr);
+ } else if (memcmp(nvram_dat, nvram_ularray, nvram_sz)) {
+ brcmf_err("Downloaded NVRAM image is corrupted\n");
+ ret = false;
+ }
+ kfree(nvram_ularray);
+
+ return ret;
+}
+#else /* DEBUG */
+static inline bool
+brcmf_sdio_chip_verifynvram(struct brcmf_sdio_dev *sdiodev, u32 nvram_addr,
+ char *nvram_dat, uint nvram_sz)
+{
+ return true;
+}
+#endif /* DEBUG */
+
+static bool brcmf_sdio_chip_writenvram(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci,
+ char *nvram_dat, uint nvram_sz)
+{
+ int err;
+ u32 nvram_addr;
+ u32 token;
+ __le32 token_le;
+
+ nvram_addr = (ci->ramsize - 4) - nvram_sz + ci->rambase;
+
+ /* Write the vars list */
+ err = brcmf_sdio_ramrw(sdiodev, true, nvram_addr, nvram_dat, nvram_sz);
+ if (err) {
+ brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n",
+ err, nvram_sz, nvram_addr);
+ return false;
+ }
+
+ if (!brcmf_sdio_chip_verifynvram(sdiodev, nvram_addr,
+ nvram_dat, nvram_sz))
+ return false;
+
+ /* generate token:
+ * nvram size, converted to words, in lower 16-bits, checksum
+ * in upper 16-bits.
+ */
+ token = nvram_sz / 4;
+ token = (~token << 16) | (token & 0x0000FFFF);
+ token_le = cpu_to_le32(token);
+
+ brcmf_dbg(INFO, "RAM size: %d\n", ci->ramsize);
+ brcmf_dbg(INFO, "nvram is placed at %d, size %d, token=0x%08x\n",
+ nvram_addr, nvram_sz, token);
+
+ /* Write the length token to the last word */
+ if (brcmf_sdio_ramrw(sdiodev, true, (ci->ramsize - 4 + ci->rambase),
+ (u8 *)&token_le, 4))
+ return false;
+
+ return true;
+}
+
+static void
+brcmf_sdio_chip_cm3_enterdl(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci)
+{
+ u32 zeros = 0;
+
+ ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
+ ci->resetcore(sdiodev, ci, BCMA_CORE_INTERNAL_MEM, 0);
+
+ /* clear length token */
+ brcmf_sdio_ramrw(sdiodev, true, ci->ramsize - 4, (u8 *)&zeros, 4);
+}
+
+static bool
+brcmf_sdio_chip_cm3_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
+ char *nvram_dat, uint nvram_sz)
+{
+ u8 core_idx;
+ u32 reg_addr;
+
+ if (!ci->iscoreup(sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
+ brcmf_err("SOCRAM core is down after reset?\n");
+ return false;
+ }
+
+ if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
+ return false;
+
+ /* clear all interrupts */
+ core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
+ reg_addr = ci->c_inf[core_idx].base;
+ reg_addr += offsetof(struct sdpcmd_regs, intstatus);
+ brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
+
+ ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CM3, 0);
+
+ return true;
+}
+
+static inline void
+brcmf_sdio_chip_cr4_enterdl(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci)
+{
+ ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4,
+ ARMCR4_BCMA_IOCTL_CPUHALT);
+}
+
+static bool
+brcmf_sdio_chip_cr4_exitdl(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
+ char *nvram_dat, uint nvram_sz)
+{
+ u8 core_idx;
+ u32 reg_addr;
+
+ if (!brcmf_sdio_chip_writenvram(sdiodev, ci, nvram_dat, nvram_sz))
+ return false;
+
+ /* clear all interrupts */
+ core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_SDIO_DEV);
+ reg_addr = ci->c_inf[core_idx].base;
+ reg_addr += offsetof(struct sdpcmd_regs, intstatus);
+ brcmf_sdio_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
+
+ /* Write reset vector to address 0 */
+ brcmf_sdio_ramrw(sdiodev, true, 0, (void *)&ci->rst_vec,
+ sizeof(ci->rst_vec));
+
+ /* restore ARM */
+ ci->resetcore(sdiodev, ci, BCMA_CORE_ARM_CR4, 0);
+
+ return true;
+}
+
+void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci)
+{
+ u8 arm_core_idx;
+
+ arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
+ if (BRCMF_MAX_CORENUM != arm_core_idx) {
+ brcmf_sdio_chip_cm3_enterdl(sdiodev, ci);
+ return;
+ }
+
+ brcmf_sdio_chip_cr4_enterdl(sdiodev, ci);
+}
+
+bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci, char *nvram_dat,
+ uint nvram_sz)
+{
+ u8 arm_core_idx;
+
+ arm_core_idx = brcmf_sdio_chip_getinfidx(ci, BCMA_CORE_ARM_CM3);
+ if (BRCMF_MAX_CORENUM != arm_core_idx)
+ return brcmf_sdio_chip_cm3_exitdl(sdiodev, ci, nvram_dat,
+ nvram_sz);
+
+ return brcmf_sdio_chip_cr4_exitdl(sdiodev, ci, nvram_dat, nvram_sz);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
index ce974d76bd92..83c041f1bf4a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
@@ -73,15 +73,17 @@ struct chip_info {
u32 pmurev;
u32 pmucaps;
u32 ramsize;
+ u32 rambase;
+ u32 rst_vec; /* reset vertor for ARM CR4 core */
bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
u16 coreid);
u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
u16 coreid);
void (*coredisable)(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid);
+ struct chip_info *ci, u16 coreid, u32 core_bits);
void (*resetcore)(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, u16 coreid);
+ struct chip_info *ci, u16 coreid, u32 core_bits);
};
struct sbconfig {
@@ -124,6 +126,95 @@ struct sbconfig {
u32 sbidhigh; /* identification */
};
+/* sdio core registers */
+struct sdpcmd_regs {
+ u32 corecontrol; /* 0x00, rev8 */
+ u32 corestatus; /* rev8 */
+ u32 PAD[1];
+ u32 biststatus; /* rev8 */
+
+ /* PCMCIA access */
+ u16 pcmciamesportaladdr; /* 0x010, rev8 */
+ u16 PAD[1];
+ u16 pcmciamesportalmask; /* rev8 */
+ u16 PAD[1];
+ u16 pcmciawrframebc; /* rev8 */
+ u16 PAD[1];
+ u16 pcmciaunderflowtimer; /* rev8 */
+ u16 PAD[1];
+
+ /* interrupt */
+ u32 intstatus; /* 0x020, rev8 */
+ u32 hostintmask; /* rev8 */
+ u32 intmask; /* rev8 */
+ u32 sbintstatus; /* rev8 */
+ u32 sbintmask; /* rev8 */
+ u32 funcintmask; /* rev4 */
+ u32 PAD[2];
+ u32 tosbmailbox; /* 0x040, rev8 */
+ u32 tohostmailbox; /* rev8 */
+ u32 tosbmailboxdata; /* rev8 */
+ u32 tohostmailboxdata; /* rev8 */
+
+ /* synchronized access to registers in SDIO clock domain */
+ u32 sdioaccess; /* 0x050, rev8 */
+ u32 PAD[3];
+
+ /* PCMCIA frame control */
+ u8 pcmciaframectrl; /* 0x060, rev8 */
+ u8 PAD[3];
+ u8 pcmciawatermark; /* rev8 */
+ u8 PAD[155];
+
+ /* interrupt batching control */
+ u32 intrcvlazy; /* 0x100, rev8 */
+ u32 PAD[3];
+
+ /* counters */
+ u32 cmd52rd; /* 0x110, rev8 */
+ u32 cmd52wr; /* rev8 */
+ u32 cmd53rd; /* rev8 */
+ u32 cmd53wr; /* rev8 */
+ u32 abort; /* rev8 */
+ u32 datacrcerror; /* rev8 */
+ u32 rdoutofsync; /* rev8 */
+ u32 wroutofsync; /* rev8 */
+ u32 writebusy; /* rev8 */
+ u32 readwait; /* rev8 */
+ u32 readterm; /* rev8 */
+ u32 writeterm; /* rev8 */
+ u32 PAD[40];
+ u32 clockctlstatus; /* rev8 */
+ u32 PAD[7];
+
+ u32 PAD[128]; /* DMA engines */
+
+ /* SDIO/PCMCIA CIS region */
+ char cis[512]; /* 0x400-0x5ff, rev6 */
+
+ /* PCMCIA function control registers */
+ char pcmciafcr[256]; /* 0x600-6ff, rev6 */
+ u16 PAD[55];
+
+ /* PCMCIA backplane access */
+ u16 backplanecsr; /* 0x76E, rev6 */
+ u16 backplaneaddr0; /* rev6 */
+ u16 backplaneaddr1; /* rev6 */
+ u16 backplaneaddr2; /* rev6 */
+ u16 backplaneaddr3; /* rev6 */
+ u16 backplanedata0; /* rev6 */
+ u16 backplanedata1; /* rev6 */
+ u16 backplanedata2; /* rev6 */
+ u16 backplanedata3; /* rev6 */
+ u16 PAD[31];
+
+ /* sprom "size" & "blank" info */
+ u16 spromstatus; /* 0x7BE, rev2 */
+ u32 PAD[464];
+
+ u16 PAD[0x80];
+};
+
extern int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
struct chip_info **ci_ptr, u32 regs);
extern void brcmf_sdio_chip_detach(struct chip_info **ci_ptr);
@@ -131,6 +222,10 @@ extern void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci,
u32 drivestrength);
extern u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid);
-
+extern void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci);
+extern bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci, char *nvram_dat,
+ uint nvram_sz);
#endif /* _BRCMFMAC_SDIO_CHIP_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 0d30afd8c672..7c1b6332747e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -48,7 +48,13 @@
#define SBSDIO_NUM_FUNCTION 3
/* function 0 vendor specific CCCR registers */
-#define SDIO_CCCR_BRCM_SEPINT 0xf2
+#define SDIO_CCCR_BRCM_CARDCAP 0xf0
+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
+#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08
+#define SDIO_CCCR_BRCM_CARDCTRL 0xf1
+#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02
+#define SDIO_CCCR_BRCM_SEPINT 0xf2
#define SDIO_SEPINT_MASK 0x01
#define SDIO_SEPINT_OE 0x02
@@ -97,9 +103,23 @@
#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B
/* Read Frame Byte Count High */
#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C
+/* MesBusyCtl (rev 11) */
+#define SBSDIO_FUNC1_MESBUSYCTRL 0x1001D
+/* Sdio Core Rev 12 */
+#define SBSDIO_FUNC1_WAKEUPCTRL 0x1001E
+#define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK 0x1
+#define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT 0
+#define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK 0x2
+#define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT 1
+#define SBSDIO_FUNC1_SLEEPCSR 0x1001F
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK 0x1
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT 0
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_EN 1
+#define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK 0x2
+#define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT 1
#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */
-#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */
+#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001F /* f1 misc register end */
/* function 1 OCP space */
@@ -154,13 +174,11 @@ struct brcmf_sdio_dev {
wait_queue_head_t request_buffer_wait;
struct device *dev;
struct brcmf_bus *bus_if;
-#ifdef CONFIG_BRCMFMAC_SDIO_OOB
- unsigned int irq; /* oob interrupt number */
- unsigned long irq_flags; /* board specific oob flags */
+ struct brcmfmac_sdio_platform_data *pdata;
+ bool oob_irq_requested;
bool irq_en; /* irq enable flags */
spinlock_t irq_en_lock;
bool irq_wake; /* irq wake enable flags */
-#endif /* CONFIG_BRCMFMAC_SDIO_OOB */
};
/* Register/deregister interrupt handler. */
@@ -224,6 +242,8 @@ brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
*/
extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw,
u32 addr, u8 *buf, uint nbytes);
+extern int brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write,
+ u32 address, u8 *data, uint size);
/* Issue an abort to the specified function */
extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index e4f1f3c9575a..6d758f285352 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -29,6 +29,7 @@
#include "tracepoint.h"
#include "fwil_types.h"
#include "p2p.h"
+#include "btcoex.h"
#include "wl_cfg80211.h"
#include "fwil.h"
@@ -334,22 +335,16 @@ static u8 brcmf_mw_to_qdbm(u16 mw)
return qdbm;
}
-u16 channel_to_chanspec(struct ieee80211_channel *ch)
+u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
+ struct ieee80211_channel *ch)
{
- u16 chanspec;
-
- chanspec = ieee80211_frequency_to_channel(ch->center_freq);
- chanspec &= WL_CHANSPEC_CHAN_MASK;
-
- if (ch->band == IEEE80211_BAND_2GHZ)
- chanspec |= WL_CHANSPEC_BAND_2G;
- else
- chanspec |= WL_CHANSPEC_BAND_5G;
+ struct brcmu_chan ch_inf;
- chanspec |= WL_CHANSPEC_BW_20;
- chanspec |= WL_CHANSPEC_CTL_SB_NONE;
+ ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq);
+ ch_inf.bw = BRCMU_CHAN_BW_20;
+ d11inf->encchspec(&ch_inf);
- return chanspec;
+ return ch_inf.chspec;
}
/* Traverse a string of 1-byte tag/1-byte length/variable-length value
@@ -680,7 +675,8 @@ done:
return err;
}
-static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
+static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
+ struct brcmf_scan_params_le *params_le,
struct cfg80211_scan_request *request)
{
u32 n_ssids;
@@ -712,7 +708,8 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
n_channels);
if (n_channels > 0) {
for (i = 0; i < n_channels; i++) {
- chanspec = channel_to_chanspec(request->channels[i]);
+ chanspec = channel_to_chanspec(&cfg->d11inf,
+ request->channels[i]);
brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
request->channels[i]->hw_value, chanspec);
params_le->channel_list[i] = cpu_to_le16(chanspec);
@@ -784,7 +781,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
goto exit;
}
BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
- brcmf_escan_prep(&params->params_le, request);
+ brcmf_escan_prep(cfg, &params->params_le, request);
params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
params->action = cpu_to_le16(action);
params->sync_id = cpu_to_le16(0x1234);
@@ -860,6 +857,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
cfg->scan_status);
return -EAGAIN;
}
+ if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
+ brcmf_err("Scanning suppressed: status (%lu)\n",
+ cfg->scan_status);
+ return -EAGAIN;
+ }
if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
brcmf_err("Connecting: status (%lu)\n", ifp->vif->sme_state);
return -EAGAIN;
@@ -1050,6 +1052,7 @@ static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
s32 err = 0;
brcmf_dbg(TRACE, "Enter\n");
@@ -1063,6 +1066,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
}
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
+ clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
+ brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
brcmf_dbg(TRACE, "Exit\n");
}
@@ -1182,7 +1187,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
params->chandef.chan->center_freq);
if (params->channel_fixed) {
/* adding chanspec */
- chanspec = channel_to_chanspec(params->chandef.chan);
+ chanspec = channel_to_chanspec(&cfg->d11inf,
+ params->chandef.chan);
join_params.params_le.chanspec_list[0] =
cpu_to_le16(chanspec);
join_params.params_le.chanspec_num = cpu_to_le32(1);
@@ -1572,7 +1578,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
if (chan) {
cfg->channel =
ieee80211_frequency_to_channel(chan->center_freq);
- chanspec = channel_to_chanspec(chan);
+ chanspec = channel_to_chanspec(&cfg->d11inf, chan);
brcmf_dbg(CONN, "channel=%d, center_req=%d, chanspec=0x%04x\n",
cfg->channel, chan->center_freq, chanspec);
} else {
@@ -2231,6 +2237,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
struct ieee80211_channel *notify_channel;
struct cfg80211_bss *bss;
struct ieee80211_supported_band *band;
+ struct brcmu_chan ch;
s32 err = 0;
u16 channel;
u32 freq;
@@ -2245,8 +2252,12 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
return 0;
}
- channel = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+ if (!bi->ctl_ch) {
+ ch.chspec = le16_to_cpu(bi->chanspec);
+ cfg->d11inf.decchspec(&ch);
+ bi->ctl_ch = ch.chnum;
+ }
+ channel = bi->ctl_ch;
if (channel <= CH_MAX_2G_CHANNEL)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
@@ -2321,9 +2332,9 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
struct brcmf_bss_info_le *bi = NULL;
struct ieee80211_supported_band *band;
struct cfg80211_bss *bss;
+ struct brcmu_chan ch;
u8 *buf = NULL;
s32 err = 0;
- u16 channel;
u32 freq;
u16 notify_capability;
u16 notify_interval;
@@ -2350,15 +2361,15 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
bi = (struct brcmf_bss_info_le *)(buf + 4);
- channel = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+ ch.chspec = le16_to_cpu(bi->chanspec);
+ cfg->d11inf.decchspec(&ch);
- if (channel <= CH_MAX_2G_CHANNEL)
+ if (ch.band == BRCMU_CHAN_BAND_2G)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
else
band = wiphy->bands[IEEE80211_BAND_5GHZ];
- freq = ieee80211_channel_to_frequency(channel, band->band);
+ freq = ieee80211_channel_to_frequency(ch.chnum, band->band);
notify_channel = ieee80211_get_channel(wiphy, freq);
notify_capability = le16_to_cpu(bi->capability);
@@ -2367,7 +2378,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
notify_ielen = le32_to_cpu(bi->ie_length);
notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
- brcmf_dbg(CONN, "channel: %d(%d)\n", channel, freq);
+ brcmf_dbg(CONN, "channel: %d(%d)\n", ch.chnum, freq);
brcmf_dbg(CONN, "capability: %X\n", notify_capability);
brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval);
brcmf_dbg(CONN, "signal: %d\n", notify_signal);
@@ -2490,12 +2501,19 @@ static void brcmf_escan_timeout(unsigned long data)
}
static s32
-brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
+brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg,
+ struct brcmf_bss_info_le *bss,
struct brcmf_bss_info_le *bss_info_le)
{
+ struct brcmu_chan ch_bss, ch_bss_info_le;
+
+ ch_bss.chspec = le16_to_cpu(bss->chanspec);
+ cfg->d11inf.decchspec(&ch_bss);
+ ch_bss_info_le.chspec = le16_to_cpu(bss_info_le->chanspec);
+ cfg->d11inf.decchspec(&ch_bss_info_le);
+
if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) &&
- (CHSPEC_BAND(le16_to_cpu(bss_info_le->chanspec)) ==
- CHSPEC_BAND(le16_to_cpu(bss->chanspec))) &&
+ ch_bss.band == ch_bss_info_le.band &&
bss_info_le->SSID_len == bss->SSID_len &&
!memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
@@ -2593,7 +2611,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
bss = bss ? (struct brcmf_bss_info_le *)
((unsigned char *)bss +
le32_to_cpu(bss->length)) : list->bss_info_le;
- if (brcmf_compare_update_same_bss(bss, bss_info_le))
+ if (brcmf_compare_update_same_bss(cfg, bss,
+ bss_info_le))
goto exit;
}
memcpy(&(cfg->escan_info.escan_buf[list->buflen]),
@@ -3007,6 +3026,11 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
return -EAGAIN;
}
+ if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
+ brcmf_err("Scanning suppressed: status (%lu)\n",
+ cfg->scan_status);
+ return -EAGAIN;
+ }
if (!request->n_ssids || !request->n_match_sets) {
brcmf_err("Invalid sched scan req!! n_ssids:%d\n",
@@ -3993,6 +4017,39 @@ exit:
return err;
}
+static int brcmf_cfg80211_crit_proto_start(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ enum nl80211_crit_proto_id proto,
+ u16 duration)
+{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_cfg80211_vif *vif;
+
+ vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+
+ /* only DHCP support for now */
+ if (proto != NL80211_CRIT_PROTO_DHCP)
+ return -EINVAL;
+
+ /* suppress and abort scanning */
+ set_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
+ brcmf_abort_scanning(cfg);
+
+ return brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_DISABLED, duration);
+}
+
+static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy,
+ struct wireless_dev *wdev)
+{
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct brcmf_cfg80211_vif *vif;
+
+ vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+
+ brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
+ clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
+}
+
static struct cfg80211_ops wl_cfg80211_ops = {
.add_virtual_intf = brcmf_cfg80211_add_iface,
.del_virtual_intf = brcmf_cfg80211_del_iface,
@@ -4029,6 +4086,8 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
.start_p2p_device = brcmf_p2p_start_device,
.stop_p2p_device = brcmf_p2p_stop_device,
+ .crit_proto_start = brcmf_cfg80211_crit_proto_start,
+ .crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
#ifdef CONFIG_NL80211_TESTMODE
.testmode_cmd = brcmf_cfg80211_testmode
#endif
@@ -4337,9 +4396,9 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
struct ieee80211_channel *notify_channel = NULL;
struct ieee80211_supported_band *band;
struct brcmf_bss_info_le *bi;
+ struct brcmu_chan ch;
u32 freq;
s32 err = 0;
- u32 target_channel;
u8 *buf;
brcmf_dbg(TRACE, "Enter\n");
@@ -4363,15 +4422,15 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
goto done;
bi = (struct brcmf_bss_info_le *)(buf + 4);
- target_channel = bi->ctl_ch ? bi->ctl_ch :
- CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+ ch.chspec = le16_to_cpu(bi->chanspec);
+ cfg->d11inf.decchspec(&ch);
- if (target_channel <= CH_MAX_2G_CHANNEL)
+ if (ch.band == BRCMU_CHAN_BAND_2G)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
else
band = wiphy->bands[IEEE80211_BAND_5GHZ];
- freq = ieee80211_channel_to_frequency(target_channel, band->band);
+ freq = ieee80211_channel_to_frequency(ch.chnum, band->band);
notify_channel = ieee80211_get_channel(wiphy, freq);
done:
@@ -4725,6 +4784,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
struct brcmf_cfg80211_vif *vif;
struct brcmf_if *ifp;
s32 err = 0;
+ s32 io_type;
if (!ndev) {
brcmf_err("ndev is invalid\n");
@@ -4765,6 +4825,21 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
brcmf_err("P2P initilisation failed (%d)\n", err);
goto cfg80211_p2p_attach_out;
}
+ err = brcmf_btcoex_attach(cfg);
+ if (err) {
+ brcmf_err("BT-coex initialisation failed (%d)\n", err);
+ brcmf_p2p_detach(&cfg->p2p);
+ goto cfg80211_p2p_attach_out;
+ }
+
+ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION,
+ &io_type);
+ if (err) {
+ brcmf_err("Failed to get D11 version (%d)\n", err);
+ goto cfg80211_p2p_attach_out;
+ }
+ cfg->d11inf.io_type = (u8)io_type;
+ brcmu_d11_attach(&cfg->d11inf);
return cfg;
@@ -4783,6 +4858,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
struct brcmf_cfg80211_vif *tmp;
wl_deinit_priv(cfg);
+ brcmf_btcoex_detach(cfg);
list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
brcmf_free_vif(vif);
}
@@ -4885,11 +4961,11 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
struct ieee80211_channel *band_chan_arr;
struct brcmf_chanspec_list *list;
+ struct brcmu_chan ch;
s32 err;
u8 *pbuf;
u32 i, j;
u32 total;
- u16 chanspec;
enum ieee80211_band band;
u32 channel;
u32 *n_cnt;
@@ -4918,42 +4994,30 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
total = le32_to_cpu(list->count);
for (i = 0; i < total; i++) {
- chanspec = (u16)le32_to_cpu(list->element[i]);
- channel = CHSPEC_CHANNEL(chanspec);
+ ch.chspec = (u16)le32_to_cpu(list->element[i]);
+ cfg->d11inf.decchspec(&ch);
- if (CHSPEC_IS40(chanspec)) {
- if (CHSPEC_SB_UPPER(chanspec))
- channel += CH_10MHZ_APART;
- else
- channel -= CH_10MHZ_APART;
- } else if (CHSPEC_IS80(chanspec)) {
- brcmf_dbg(INFO, "HT80 center channel : %d\n",
- channel);
- continue;
- }
- if (CHSPEC_IS2G(chanspec) && (channel >= CH_MIN_2G_CHANNEL) &&
- (channel <= CH_MAX_2G_CHANNEL)) {
+ if (ch.band == BRCMU_CHAN_BAND_2G) {
band_chan_arr = __wl_2ghz_channels;
array_size = ARRAY_SIZE(__wl_2ghz_channels);
n_cnt = &__wl_band_2ghz.n_channels;
band = IEEE80211_BAND_2GHZ;
ht40_allowed = (bw_cap == WLC_N_BW_40ALL);
- } else if (CHSPEC_IS5G(chanspec) &&
- channel >= CH_MIN_5G_CHANNEL) {
+ } else if (ch.band == BRCMU_CHAN_BAND_5G) {
band_chan_arr = __wl_5ghz_a_channels;
array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
n_cnt = &__wl_band_5ghz_a.n_channels;
band = IEEE80211_BAND_5GHZ;
ht40_allowed = !(bw_cap == WLC_N_BW_20ALL);
} else {
- brcmf_err("Invalid channel Sepc. 0x%x.\n", chanspec);
+ brcmf_err("Invalid channel Sepc. 0x%x.\n", ch.chspec);
continue;
}
- if (!ht40_allowed && CHSPEC_IS40(chanspec))
+ if (!ht40_allowed && ch.bw == BRCMU_CHAN_BW_40)
continue;
update = false;
for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
- if (band_chan_arr[j].hw_value == channel) {
+ if (band_chan_arr[j].hw_value == ch.chnum) {
update = true;
break;
}
@@ -4964,16 +5028,16 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
index = *n_cnt;
if (index < array_size) {
band_chan_arr[index].center_freq =
- ieee80211_channel_to_frequency(channel, band);
- band_chan_arr[index].hw_value = channel;
+ ieee80211_channel_to_frequency(ch.chnum, band);
+ band_chan_arr[index].hw_value = ch.chnum;
- if (CHSPEC_IS40(chanspec) && ht40_allowed) {
+ if (ch.bw == BRCMU_CHAN_BW_40 && ht40_allowed) {
/* assuming the order is HT20, HT40 Upper,
* HT40 lower from chanspecs
*/
ht40_flag = band_chan_arr[index].flags &
IEEE80211_CHAN_NO_HT40;
- if (CHSPEC_SB_UPPER(chanspec)) {
+ if (ch.sb == BRCMU_CHAN_SB_U) {
if (ht40_flag == IEEE80211_CHAN_NO_HT40)
band_chan_arr[index].flags &=
~IEEE80211_CHAN_NO_HT40;
@@ -4993,11 +5057,9 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
} else {
band_chan_arr[index].flags =
IEEE80211_CHAN_NO_HT40;
- if (band == IEEE80211_BAND_2GHZ)
- channel |= WL_CHANSPEC_BAND_2G;
- else
- channel |= WL_CHANSPEC_BAND_5G;
- channel |= WL_CHANSPEC_BW_20;
+ ch.bw = BRCMU_CHAN_BW_20;
+ cfg->d11inf.encchspec(&ch);
+ channel = ch.chspec;
err = brcmf_fil_bsscfg_int_get(ifp,
"per_chan_info",
&channel);
@@ -5226,6 +5288,13 @@ s32 brcmf_cfg80211_down(struct net_device *ndev)
return err;
}
+enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp)
+{
+ struct wireless_dev *wdev = &ifp->vif->wdev;
+
+ return wdev->iftype;
+}
+
u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state)
{
struct brcmf_cfg80211_vif *vif;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
index 2907437ef438..a71cff84cdcf 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
@@ -17,6 +17,9 @@
#ifndef _wl_cfg80211_h_
#define _wl_cfg80211_h_
+/* for brcmu_d11inf */
+#include <brcmu_d11.h>
+
#define WL_NUM_SCAN_MAX 10
#define WL_NUM_PMKIDS_MAX MAXPMKID
#define WL_TLV_INFO_MAX 1024
@@ -74,14 +77,16 @@
/**
- * enum brcmf_scan_status - dongle scan status
+ * enum brcmf_scan_status - scan engine status
*
* @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle.
* @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle.
+ * @BRCMF_SCAN_STATUS_SUPPRESS: scanning is suppressed in driver.
*/
enum brcmf_scan_status {
BRCMF_SCAN_STATUS_BUSY,
BRCMF_SCAN_STATUS_ABORT,
+ BRCMF_SCAN_STATUS_SUPPRESS,
};
/**
@@ -346,6 +351,7 @@ struct brcmf_cfg80211_vif_event {
* @wiphy: wiphy object for cfg80211 interface.
* @conf: dongle configuration.
* @p2p: peer-to-peer specific information.
+ * @btcoex: Bluetooth coexistence information.
* @scan_request: cfg80211 scan request object.
* @usr_sync: mainly for dongle up/down synchronization.
* @bss_list: bss_list holding scanned ap information.
@@ -379,6 +385,7 @@ struct brcmf_cfg80211_info {
struct wiphy *wiphy;
struct brcmf_cfg80211_conf *conf;
struct brcmf_p2p_info p2p;
+ struct brcmf_btcoex_info *btcoex;
struct cfg80211_scan_request *scan_request;
struct mutex usr_sync;
struct brcmf_scan_results *bss_list;
@@ -408,6 +415,7 @@ struct brcmf_cfg80211_info {
u8 vif_cnt;
struct brcmf_cfg80211_vif_event vif_event;
struct completion vif_disabled;
+ struct brcmu_d11inf d11inf;
};
/**
@@ -474,6 +482,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
s32 brcmf_cfg80211_up(struct net_device *ndev);
s32 brcmf_cfg80211_down(struct net_device *ndev);
+enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
enum nl80211_iftype type,
@@ -484,7 +493,8 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
const u8 *vndr_ie_buf, u32 vndr_ie_len);
s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key);
-u16 channel_to_chanspec(struct ieee80211_channel *ch);
+u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
+ struct ieee80211_channel *ch);
u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
struct brcmf_cfg80211_vif *vif);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
index cba19d839b77..32464acccd90 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
@@ -21,7 +21,7 @@ ccflags-y := \
-Idrivers/net/wireless/brcm80211/brcmsmac/phy \
-Idrivers/net/wireless/brcm80211/include
-BRCMSMAC_OFILES := \
+brcmsmac-y := \
mac80211_if.o \
ucode_loader.o \
ampdu.o \
@@ -43,11 +43,6 @@ BRCMSMAC_OFILES := \
brcms_trace_events.o \
debug.o
-ifdef CONFIG_BCMA_DRIVER_GPIO
-BRCMSMAC_OFILES += led.o
-endif
+brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o
-MODULEPFX := brcmsmac
-
-obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o
-$(MODULEPFX)-objs = $(BRCMSMAC_OFILES)
+obj-$(CONFIG_BRCMSMAC) += brcmsmac.o
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
index 10ee314c4229..cc87926f5055 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
@@ -379,7 +379,7 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
u8 local_constraint_qdbm)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
- struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
struct txpwr_limits txpwr;
brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
@@ -404,7 +404,7 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
struct txpwr_limits *txpwr)
{
struct brcms_c_info *wlc = wlc_cm->wlc;
- struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
uint i;
uint chan;
int maxpwr;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index c837be242cba..2346821667e6 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -556,10 +556,10 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
new_int);
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- if (conf->channel_type == NL80211_CHAN_HT20 ||
- conf->channel_type == NL80211_CHAN_NO_HT)
+ if (conf->chandef.width == NL80211_CHAN_WIDTH_20 ||
+ conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
err = brcms_c_set_channel(wl->wlc,
- conf->channel->hw_value);
+ conf->chandef.chan->hw_value);
else
err = -ENOTSUPP;
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 59d438409dfb..28e7aeedd184 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -5135,7 +5135,7 @@ int brcms_c_up(struct brcms_c_info *wlc)
wlc->pub->up = true;
if (wlc->bandinit_pending) {
- ch = wlc->pub->ieee_hw->conf.channel;
+ ch = wlc->pub->ieee_hw->conf.chandef.chan;
brcms_c_suspend_mac_and_wait(wlc);
brcms_c_set_chanspec(wlc, ch20mhz_chspec(ch->hw_value));
wlc->bandinit_pending = false;
@@ -7919,7 +7919,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
{
struct bcma_device *core = wlc->hw->d11core;
- struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
+ struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
u16 chanspec;
brcms_dbg_info(core, "wl%d\n", wlc->pub->unit);
diff --git a/drivers/net/wireless/brcm80211/brcmutil/Makefile b/drivers/net/wireless/brcm80211/brcmutil/Makefile
index 6281c416289e..8a928184016a 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmutil/Makefile
@@ -19,10 +19,5 @@ ccflags-y := \
-Idrivers/net/wireless/brcm80211/brcmutil \
-Idrivers/net/wireless/brcm80211/include
-BRCMUTIL_OFILES := \
- utils.o
-
-MODULEPFX := brcmutil
-
-obj-$(CONFIG_BRCMUTIL) += $(MODULEPFX).o
-$(MODULEPFX)-objs = $(BRCMUTIL_OFILES)
+obj-$(CONFIG_BRCMUTIL) += brcmutil.o
+brcmutil-objs = utils.o d11.o
diff --git a/drivers/net/wireless/brcm80211/brcmutil/d11.c b/drivers/net/wireless/brcm80211/brcmutil/d11.c
new file mode 100644
index 000000000000..30e54e2c6c9b
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmutil/d11.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * 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.
+ */
+/*********************channel spec common functions*********************/
+
+#include <linux/module.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <brcmu_d11.h>
+
+static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
+{
+ ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
+
+ switch (ch->bw) {
+ case BRCMU_CHAN_BW_20:
+ ch->chspec |= BRCMU_CHSPEC_D11N_BW_20 | BRCMU_CHSPEC_D11N_SB_N;
+ break;
+ case BRCMU_CHAN_BW_40:
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ if (ch->chnum <= CH_MAX_2G_CHANNEL)
+ ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G;
+ else
+ ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G;
+}
+
+static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
+{
+ ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
+
+ switch (ch->bw) {
+ case BRCMU_CHAN_BW_20:
+ ch->chspec |= BRCMU_CHSPEC_D11AC_BW_20;
+ break;
+ case BRCMU_CHAN_BW_40:
+ case BRCMU_CHAN_BW_80:
+ case BRCMU_CHAN_BW_80P80:
+ case BRCMU_CHAN_BW_160:
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ if (ch->chnum <= CH_MAX_2G_CHANNEL)
+ ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G;
+ else
+ ch->chspec |= BRCMU_CHSPEC_D11AC_BND_5G;
+}
+
+static void brcmu_d11n_decchspec(struct brcmu_chan *ch)
+{
+ u16 val;
+
+ ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
+
+ switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) {
+ case BRCMU_CHSPEC_D11N_BW_20:
+ ch->bw = BRCMU_CHAN_BW_20;
+ break;
+ case BRCMU_CHSPEC_D11N_BW_40:
+ ch->bw = BRCMU_CHAN_BW_40;
+ val = ch->chspec & BRCMU_CHSPEC_D11N_SB_MASK;
+ if (val == BRCMU_CHSPEC_D11N_SB_L) {
+ ch->sb = BRCMU_CHAN_SB_L;
+ ch->chnum -= CH_10MHZ_APART;
+ } else {
+ ch->sb = BRCMU_CHAN_SB_U;
+ ch->chnum += CH_10MHZ_APART;
+ }
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ switch (ch->chspec & BRCMU_CHSPEC_D11N_BND_MASK) {
+ case BRCMU_CHSPEC_D11N_BND_5G:
+ ch->band = BRCMU_CHAN_BAND_5G;
+ break;
+ case BRCMU_CHSPEC_D11N_BND_2G:
+ ch->band = BRCMU_CHAN_BAND_2G;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+}
+
+static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
+{
+ u16 val;
+
+ ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
+
+ switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) {
+ case BRCMU_CHSPEC_D11AC_BW_20:
+ ch->bw = BRCMU_CHAN_BW_20;
+ break;
+ case BRCMU_CHSPEC_D11AC_BW_40:
+ ch->bw = BRCMU_CHAN_BW_40;
+ val = ch->chspec & BRCMU_CHSPEC_D11AC_SB_MASK;
+ if (val == BRCMU_CHSPEC_D11AC_SB_L) {
+ ch->sb = BRCMU_CHAN_SB_L;
+ ch->chnum -= CH_10MHZ_APART;
+ } else if (val == BRCMU_CHSPEC_D11AC_SB_U) {
+ ch->sb = BRCMU_CHAN_SB_U;
+ ch->chnum += CH_10MHZ_APART;
+ } else {
+ WARN_ON_ONCE(1);
+ }
+ break;
+ case BRCMU_CHSPEC_D11AC_BW_80:
+ ch->bw = BRCMU_CHAN_BW_80;
+ break;
+ case BRCMU_CHSPEC_D11AC_BW_8080:
+ case BRCMU_CHSPEC_D11AC_BW_160:
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ switch (ch->chspec & BRCMU_CHSPEC_D11AC_BND_MASK) {
+ case BRCMU_CHSPEC_D11AC_BND_5G:
+ ch->band = BRCMU_CHAN_BAND_5G;
+ break;
+ case BRCMU_CHSPEC_D11AC_BND_2G:
+ ch->band = BRCMU_CHAN_BAND_2G;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
+}
+
+void brcmu_d11_attach(struct brcmu_d11inf *d11inf)
+{
+ if (d11inf->io_type == BRCMU_D11N_IOTYPE) {
+ d11inf->encchspec = brcmu_d11n_encchspec;
+ d11inf->decchspec = brcmu_d11n_decchspec;
+ } else {
+ d11inf->encchspec = brcmu_d11ac_encchspec;
+ d11inf->decchspec = brcmu_d11ac_decchspec;
+ }
+}
+EXPORT_SYMBOL(brcmu_d11_attach);
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
index bf5e50fc21ba..0f7e1c7b6f58 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -45,17 +45,9 @@ void brcmu_pkt_buf_free_skb(struct sk_buff *skb)
{
if (!skb)
return;
+
WARN_ON(skb->next);
- if (skb->destructor)
- /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
- * destructor exists
- */
- dev_kfree_skb_any(skb);
- else
- /* can free immediately (even in_irq()) if destructor
- * does not exist
- */
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
}
EXPORT_SYMBOL(brcmu_pkt_buf_free_skb);
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
index e8682855b73a..c1fe245bb07e 100644
--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
@@ -29,6 +29,7 @@
/* Chipcommon Core Chip IDs */
#define BCM4313_CHIP_ID 0x4313
+#define BCM43143_CHIP_ID 43143
#define BCM43224_CHIP_ID 43224
#define BCM43225_CHIP_ID 43225
#define BCM43235_CHIP_ID 43235
@@ -39,5 +40,6 @@
#define BCM4330_CHIP_ID 0x4330
#define BCM4331_CHIP_ID 0x4331
#define BCM4334_CHIP_ID 0x4334
+#define BCM4335_CHIP_ID 0x4335
#endif /* _BRCM_HW_IDS_H_ */
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_d11.h b/drivers/net/wireless/brcm80211/include/brcmu_d11.h
new file mode 100644
index 000000000000..92623f02b1c0
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/include/brcmu_d11.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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.
+ */
+
+#ifndef _BRCMU_D11_H_
+#define _BRCMU_D11_H_
+
+/* d11 io type */
+#define BRCMU_D11N_IOTYPE 1
+#define BRCMU_D11AC_IOTYPE 2
+
+/* A chanspec (channel specification) holds the channel number, band,
+ * bandwidth and control sideband
+ */
+
+/* chanspec binary format */
+
+#define BRCMU_CHSPEC_INVALID 255
+/* bit 0~7 channel number
+ * for 80+80 channels: bit 0~3 low channel id, bit 4~7 high channel id
+ */
+#define BRCMU_CHSPEC_CH_MASK 0x00ff
+#define BRCMU_CHSPEC_CH_SHIFT 0
+#define BRCMU_CHSPEC_CHL_MASK 0x000f
+#define BRCMU_CHSPEC_CHL_SHIFT 0
+#define BRCMU_CHSPEC_CHH_MASK 0x00f0
+#define BRCMU_CHSPEC_CHH_SHIFT 4
+
+/* bit 8~16 for dot 11n IO types
+ * bit 8~9 sideband
+ * bit 10~11 bandwidth
+ * bit 12~13 spectral band
+ * bit 14~15 not used
+ */
+#define BRCMU_CHSPEC_D11N_SB_MASK 0x0300
+#define BRCMU_CHSPEC_D11N_SB_SHIFT 8
+#define BRCMU_CHSPEC_D11N_SB_L 0x0100 /* control lower */
+#define BRCMU_CHSPEC_D11N_SB_U 0x0200 /* control upper */
+#define BRCMU_CHSPEC_D11N_SB_N 0x0300 /* none */
+#define BRCMU_CHSPEC_D11N_BW_MASK 0x0c00
+#define BRCMU_CHSPEC_D11N_BW_SHIFT 10
+#define BRCMU_CHSPEC_D11N_BW_10 0x0400
+#define BRCMU_CHSPEC_D11N_BW_20 0x0800
+#define BRCMU_CHSPEC_D11N_BW_40 0x0c00
+#define BRCMU_CHSPEC_D11N_BND_MASK 0x3000
+#define BRCMU_CHSPEC_D11N_BND_SHIFT 12
+#define BRCMU_CHSPEC_D11N_BND_5G 0x1000
+#define BRCMU_CHSPEC_D11N_BND_2G 0x2000
+
+/* bit 8~16 for dot 11ac IO types
+ * bit 8~10 sideband
+ * bit 11~13 bandwidth
+ * bit 14~15 spectral band
+ */
+#define BRCMU_CHSPEC_D11AC_SB_MASK 0x0700
+#define BRCMU_CHSPEC_D11AC_SB_SHIFT 8
+#define BRCMU_CHSPEC_D11AC_SB_LLL 0x0000
+#define BRCMU_CHSPEC_D11AC_SB_LLU 0x0100
+#define BRCMU_CHSPEC_D11AC_SB_LUL 0x0200
+#define BRCMU_CHSPEC_D11AC_SB_LUU 0x0300
+#define BRCMU_CHSPEC_D11AC_SB_ULL 0x0400
+#define BRCMU_CHSPEC_D11AC_SB_ULU 0x0500
+#define BRCMU_CHSPEC_D11AC_SB_UUL 0x0600
+#define BRCMU_CHSPEC_D11AC_SB_UUU 0x0700
+#define BRCMU_CHSPEC_D11AC_SB_LL BRCMU_CHSPEC_D11AC_SB_LLL
+#define BRCMU_CHSPEC_D11AC_SB_LU BRCMU_CHSPEC_D11AC_SB_LLU
+#define BRCMU_CHSPEC_D11AC_SB_UL BRCMU_CHSPEC_D11AC_SB_LUL
+#define BRCMU_CHSPEC_D11AC_SB_UU BRCMU_CHSPEC_D11AC_SB_LUU
+#define BRCMU_CHSPEC_D11AC_SB_L BRCMU_CHSPEC_D11AC_SB_LLL
+#define BRCMU_CHSPEC_D11AC_SB_U BRCMU_CHSPEC_D11AC_SB_LLU
+#define BRCMU_CHSPEC_D11AC_BW_MASK 0x3800
+#define BRCMU_CHSPEC_D11AC_BW_SHIFT 11
+#define BRCMU_CHSPEC_D11AC_BW_5 0x0000
+#define BRCMU_CHSPEC_D11AC_BW_10 0x0800
+#define BRCMU_CHSPEC_D11AC_BW_20 0x1000
+#define BRCMU_CHSPEC_D11AC_BW_40 0x1800
+#define BRCMU_CHSPEC_D11AC_BW_80 0x2000
+#define BRCMU_CHSPEC_D11AC_BW_160 0x2800
+#define BRCMU_CHSPEC_D11AC_BW_8080 0x3000
+#define BRCMU_CHSPEC_D11AC_BND_MASK 0xc000
+#define BRCMU_CHSPEC_D11AC_BND_SHIFT 14
+#define BRCMU_CHSPEC_D11AC_BND_2G 0x0000
+#define BRCMU_CHSPEC_D11AC_BND_3G 0x4000
+#define BRCMU_CHSPEC_D11AC_BND_4G 0x8000
+#define BRCMU_CHSPEC_D11AC_BND_5G 0xc000
+
+#define BRCMU_CHAN_BAND_2G 0
+#define BRCMU_CHAN_BAND_5G 1
+
+enum brcmu_chan_bw {
+ BRCMU_CHAN_BW_20,
+ BRCMU_CHAN_BW_40,
+ BRCMU_CHAN_BW_80,
+ BRCMU_CHAN_BW_80P80,
+ BRCMU_CHAN_BW_160,
+};
+
+enum brcmu_chan_sb {
+ BRCMU_CHAN_SB_NONE = 0,
+ BRCMU_CHAN_SB_L,
+ BRCMU_CHAN_SB_U,
+ BRCMU_CHAN_SB_LL,
+ BRCMU_CHAN_SB_LU,
+ BRCMU_CHAN_SB_UL,
+ BRCMU_CHAN_SB_UU,
+ BRCMU_CHAN_SB_LLL,
+ BRCMU_CHAN_SB_LLU,
+ BRCMU_CHAN_SB_LUL,
+ BRCMU_CHAN_SB_LUU,
+ BRCMU_CHAN_SB_ULL,
+ BRCMU_CHAN_SB_ULU,
+ BRCMU_CHAN_SB_UUL,
+ BRCMU_CHAN_SB_UUU,
+};
+
+struct brcmu_chan {
+ u16 chspec;
+ u8 chnum;
+ u8 band;
+ enum brcmu_chan_bw bw;
+ enum brcmu_chan_sb sb;
+};
+
+struct brcmu_d11inf {
+ u8 io_type;
+
+ void (*encchspec)(struct brcmu_chan *ch);
+ void (*decchspec)(struct brcmu_chan *ch);
+};
+
+extern void brcmu_d11_attach(struct brcmu_d11inf *d11inf);
+
+#endif /* _BRCMU_CHANNELS_H_ */
diff --git a/drivers/net/wireless/brcm80211/include/chipcommon.h b/drivers/net/wireless/brcm80211/include/chipcommon.h
index f96834a7c055..d242333b7559 100644
--- a/drivers/net/wireless/brcm80211/include/chipcommon.h
+++ b/drivers/net/wireless/brcm80211/include/chipcommon.h
@@ -205,7 +205,7 @@ struct chipcregs {
u32 res_req_timer_sel;
u32 res_req_timer;
u32 res_req_mask;
- u32 PAD;
+ u32 pmucapabilities_ext; /* 0x64c, pmurev >=15 */
u32 chipcontrol_addr; /* 0x650 */
u32 chipcontrol_data; /* 0x654 */
u32 regcontrol_addr;
@@ -214,7 +214,11 @@ struct chipcregs {
u32 pllcontrol_data;
u32 pmustrapopt; /* 0x668, corerev >= 28 */
u32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */
- u32 PAD[100];
+ u32 retention_ctl; /* 0x670, pmurev >= 15 */
+ u32 PAD[3];
+ u32 retention_grpidx; /* 0x680 */
+ u32 retention_grpctl; /* 0x684 */
+ u32 PAD[94];
u16 sromotp[768];
};
@@ -276,6 +280,12 @@ struct chipcregs {
#define PCAP5_VC_SHIFT 22
#define PCAP5_CC_MASK 0xf8000000
#define PCAP5_CC_SHIFT 27
+/* pmucapabilites_ext PMU rev >= 15 */
+#define PCAPEXT_SR_SUPPORTED_MASK (1 << 1)
+/* retention_ctl PMU rev >= 15 */
+#define PMU_RCTL_MACPHY_DISABLE_MASK (1 << 26)
+#define PMU_RCTL_LOGIC_DISABLE_MASK (1 << 27)
+
/*
* Maximum delay for the PMU state transition in us.
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index cb066f62879d..15920aaa5dd6 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -4167,17 +4167,11 @@ static ssize_t show_debug_level(struct device_driver *d, char *buf)
static ssize_t store_debug_level(struct device_driver *d,
const char *buf, size_t count)
{
- char *p = (char *)buf;
u32 val;
+ int ret;
- if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
- p++;
- if (p[0] == 'x' || p[0] == 'X')
- p++;
- val = simple_strtoul(p, &p, 16);
- } else
- val = simple_strtoul(p, &p, 10);
- if (p == buf)
+ ret = kstrtou32(buf, 0, &val);
+ if (ret)
IPW_DEBUG_INFO(": %s is not in hex or decimal form.\n", buf);
else
ipw2100_debug_level = val;
@@ -4238,27 +4232,15 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
{
struct ipw2100_priv *priv = dev_get_drvdata(d);
struct net_device *dev = priv->net_dev;
- char buffer[] = "00000000";
- unsigned long len =
- (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1;
unsigned long val;
- char *p = buffer;
+ int ret;
(void)dev; /* kill unused-var warning for debug-only code */
IPW_DEBUG_INFO("enter\n");
- strncpy(buffer, buf, len);
- buffer[len] = 0;
-
- if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
- p++;
- if (p[0] == 'x' || p[0] == 'X')
- p++;
- val = simple_strtoul(p, &p, 16);
- } else
- val = simple_strtoul(p, &p, 10);
- if (p == buffer) {
+ ret = kstrtoul(buf, 0, &val);
+ if (ret) {
IPW_DEBUG_INFO("%s: user supplied invalid value.\n", dev->name);
} else {
priv->ieee->scan_age = val;
@@ -4266,7 +4248,7 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
}
IPW_DEBUG_INFO("exit\n");
- return len;
+ return strnlen(buf, count);
}
static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age);
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c
index d4fd29ad90dc..c9f197d9ca1e 100644
--- a/drivers/net/wireless/iwlegacy/3945-rs.c
+++ b/drivers/net/wireless/iwlegacy/3945-rs.c
@@ -347,7 +347,7 @@ il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id)
psta = (struct il3945_sta_priv *)sta->drv_priv;
rs_sta = &psta->rs_sta;
- sband = hw->wiphy->bands[conf->channel->band];
+ sband = hw->wiphy->bands[conf->chandef.chan->band];
rs_sta->il = il;
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 6affa7e8f017..b8f82e688c72 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -6057,7 +6057,7 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
struct il_priv *il = hw->priv;
const struct il_channel_info *ch_info;
struct ieee80211_conf *conf = &hw->conf;
- struct ieee80211_channel *channel = ch_switch->channel;
+ struct ieee80211_channel *channel = ch_switch->chandef.chan;
struct il_ht_config *ht_conf = &il->current_ht_config;
u16 ch;
@@ -6094,23 +6094,21 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw,
il->current_ht_config.smps = conf->smps_mode;
/* Configure HT40 channels */
- il->ht.enabled = conf_is_ht(conf);
- if (il->ht.enabled) {
- if (conf_is_ht40_minus(conf)) {
- il->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- il->ht.is_40mhz = true;
- } else if (conf_is_ht40_plus(conf)) {
- il->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- il->ht.is_40mhz = true;
- } else {
- il->ht.extension_chan_offset =
- IEEE80211_HT_PARAM_CHA_SEC_NONE;
- il->ht.is_40mhz = false;
- }
- } else
+ switch (cfg80211_get_chandef_type(&ch_switch->chandef)) {
+ case NL80211_CHAN_NO_HT:
+ case NL80211_CHAN_HT20:
il->ht.is_40mhz = false;
+ il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ break;
+ case NL80211_CHAN_HT40MINUS:
+ il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ il->ht.is_40mhz = true;
+ break;
+ case NL80211_CHAN_HT40PLUS:
+ il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ il->ht.is_40mhz = true;
+ break;
+ }
if ((le16_to_cpu(il->staging.channel) != ch))
il->staging.flags = 0;
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
index 6c7493c2d698..1fc0b227e120 100644
--- a/drivers/net/wireless/iwlegacy/4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/4965-rs.c
@@ -2300,7 +2300,7 @@ il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id)
sta_priv = (struct il_station_priv *)sta->drv_priv;
lq_sta = &sta_priv->lq_sta;
- sband = hw->wiphy->bands[conf->channel->band];
+ sband = hw->wiphy->bands[conf->chandef.chan->band];
lq_sta->lq.sta_id = sta_id;
diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c
index 91eb2d07fdb8..777a578294bd 100644
--- a/drivers/net/wireless/iwlegacy/4965.c
+++ b/drivers/net/wireless/iwlegacy/4965.c
@@ -1493,7 +1493,7 @@ il4965_hw_channel_switch(struct il_priv *il,
cmd.band = band;
cmd.expect_beacon = 0;
- ch = ch_switch->channel->hw_value;
+ ch = ch_switch->chandef.chan->hw_value;
cmd.channel = cpu_to_le16(ch);
cmd.rxon_flags = il->staging.flags;
cmd.rxon_filter_flags = il->staging.filter_flags;
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index 3613b3a81ad2..592d0aa634a8 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -4971,7 +4971,7 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed)
struct il_priv *il = hw->priv;
const struct il_channel_info *ch_info;
struct ieee80211_conf *conf = &hw->conf;
- struct ieee80211_channel *channel = conf->channel;
+ struct ieee80211_channel *channel = conf->chandef.chan;
struct il_ht_config *ht_conf = &il->current_ht_config;
unsigned long flags = 0;
int ret = 0;
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index 019d433900ef..e575b9b0cda8 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -73,6 +73,8 @@
/* AUX (TX during scan dwell) queue */
#define IWL_AUX_QUEUE 10
+#define IWL_INVALID_STATION 255
+
/* device operations */
extern struct iwl_lib_ops iwl1000_lib;
extern struct iwl_lib_ops iwl2000_lib;
@@ -176,7 +178,7 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr);
/* lib */
int iwlagn_send_tx_power(struct iwl_priv *priv);
void iwlagn_temperature(struct iwl_priv *priv);
-int iwlagn_txfifo_flush(struct iwl_priv *priv);
+int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk);
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv);
int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
int iwl_send_statistics_request(struct iwl_priv *priv,
@@ -210,6 +212,8 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u8 buf_size);
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid);
+int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, u16 tid);
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c
index 15cca2ef9294..c48907c8ab43 100644
--- a/drivers/net/wireless/iwlwifi/dvm/devices.c
+++ b/drivers/net/wireless/iwlwifi/dvm/devices.c
@@ -379,7 +379,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
};
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
- ch = ch_switch->channel->hw_value;
+ ch = ch_switch->chandef.chan->hw_value;
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
ctx->active.channel, ch);
cmd.channel = cpu_to_le16(ch);
@@ -414,7 +414,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
}
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
cmd.switch_time);
- cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
+ cmd.expect_beacon =
+ ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR;
return iwl_dvm_send_cmd(priv, &hcmd);
}
@@ -540,7 +541,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
hcmd.data[0] = cmd;
cmd->band = priv->band == IEEE80211_BAND_2GHZ;
- ch = ch_switch->channel->hw_value;
+ ch = ch_switch->chandef.chan->hw_value;
IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
ctx->active.channel, ch);
cmd->channel = cpu_to_le16(ch);
@@ -575,7 +576,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
}
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
cmd->switch_time);
- cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
+ cmd->expect_beacon =
+ ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR;
err = iwl_dvm_send_cmd(priv, &hcmd);
kfree(cmd);
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index 87c006c9c573..54f553380aa8 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -136,7 +136,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
* 1. acquire mutex before calling
* 2. make sure rf is on and not in exit state
*/
-int iwlagn_txfifo_flush(struct iwl_priv *priv)
+int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk)
{
struct iwl_txfifo_flush_cmd flush_cmd;
struct iwl_host_cmd cmd = {
@@ -162,6 +162,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv)
if (priv->nvm_data->sku_cap_11n_enable)
flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK;
+ if (scd_q_msk)
+ flush_cmd.queue_control = cpu_to_le32(scd_q_msk);
+
IWL_DEBUG_INFO(priv, "queue control: 0x%x\n",
flush_cmd.queue_control);
flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL);
@@ -173,7 +176,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)
{
mutex_lock(&priv->mutex);
ieee80211_stop_queues(priv->hw);
- if (iwlagn_txfifo_flush(priv)) {
+ if (iwlagn_txfifo_flush(priv, 0)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
@@ -1084,7 +1087,14 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd;
struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {};
- struct iwlagn_d3_config_cmd d3_cfg_cmd = {};
+ struct iwlagn_d3_config_cmd d3_cfg_cmd = {
+ /*
+ * Program the minimum sleep time to 10 seconds, as many
+ * platforms have issues processing a wakeup signal while
+ * still being in the process of suspending.
+ */
+ .min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
+ };
struct wowlan_key_data key_data = {
.ctx = ctx,
.bssid = ctx->active.bssid_addr,
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index a7294fa4d7e5..cab23af0be9e 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -777,9 +777,12 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "start Tx\n");
ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
break;
- case IEEE80211_AMPDU_TX_STOP_CONT:
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+ IWL_DEBUG_HT(priv, "Flush Tx\n");
+ ret = iwlagn_tx_agg_flush(priv, vif, sta, tid);
+ break;
+ case IEEE80211_AMPDU_TX_STOP_CONT:
IWL_DEBUG_HT(priv, "stop Tx\n");
ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
if ((ret == 0) && (priv->agg_tids_count > 0)) {
@@ -967,7 +970,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct ieee80211_conf *conf = &hw->conf;
- struct ieee80211_channel *channel = ch_switch->channel;
+ struct ieee80211_channel *channel = ch_switch->chandef.chan;
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
/*
* MULTI-FIXME
@@ -1005,11 +1008,21 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
priv->current_ht_config.smps = conf->smps_mode;
/* Configure HT40 channels */
- ctx->ht.enabled = conf_is_ht(conf);
- if (ctx->ht.enabled)
- iwlagn_config_ht40(conf, ctx);
- else
+ switch (cfg80211_get_chandef_type(&ch_switch->chandef)) {
+ case NL80211_CHAN_NO_HT:
+ case NL80211_CHAN_HT20:
ctx->ht.is_40mhz = false;
+ ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ break;
+ case NL80211_CHAN_HT40MINUS:
+ ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ ctx->ht.is_40mhz = true;
+ break;
+ case NL80211_CHAN_HT40PLUS:
+ ctx->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ ctx->ht.is_40mhz = true;
+ break;
+ }
if ((le16_to_cpu(ctx->staging.channel) != ch))
ctx->staging.flags = 0;
@@ -1122,7 +1135,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
*/
if (drop) {
IWL_DEBUG_MAC80211(priv, "send flush command\n");
- if (iwlagn_txfifo_flush(priv)) {
+ if (iwlagn_txfifo_flush(priv, 0)) {
IWL_ERR(priv, "flush request fail\n");
goto done;
}
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c
index abe304267261..907bd6e50aad 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rs.c
@@ -2831,7 +2831,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
sta_priv = (struct iwl_station_priv *) sta->drv_priv;
lq_sta = &sta_priv->lq_sta;
- sband = hw->wiphy->bands[conf->channel->band];
+ sband = hw->wiphy->bands[conf->chandef.chan->band];
lq_sta->lq.sta_id = sta_id;
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c
index a82b6b39d4ff..707446fa00bd 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c
@@ -78,8 +78,9 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
#endif
- ctx->staging.channel = cpu_to_le16(priv->hw->conf.channel->hw_value);
- priv->band = priv->hw->conf.channel->band;
+ ctx->staging.channel =
+ cpu_to_le16(priv->hw->conf.chandef.chan->hw_value);
+ priv->band = priv->hw->conf.chandef.chan->band;
iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
@@ -951,7 +952,7 @@ static void iwl_calc_basic_rates(struct iwl_priv *priv,
unsigned long basic = ctx->vif->bss_conf.basic_rates;
int i;
- sband = priv->hw->wiphy->bands[priv->hw->conf.channel->band];
+ sband = priv->hw->wiphy->bands[priv->hw->conf.chandef.chan->band];
for_each_set_bit(i, &basic, BITS_PER_LONG) {
int hw = sband->bitrates[i].hw_value;
@@ -1159,7 +1160,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
}
void iwlagn_config_ht40(struct ieee80211_conf *conf,
- struct iwl_rxon_context *ctx)
+ struct iwl_rxon_context *ctx)
{
if (conf_is_ht40_minus(conf)) {
ctx->ht.extension_chan_offset =
@@ -1181,7 +1182,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx;
struct ieee80211_conf *conf = &hw->conf;
- struct ieee80211_channel *channel = conf->channel;
+ struct ieee80211_channel *channel = conf->chandef.chan;
int ret = 0;
IWL_DEBUG_MAC80211(priv, "enter: changed %#x\n", changed);
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index 70b7f68c4958..a900aaf47790 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -674,6 +674,51 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
return ret;
}
+int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, u16 tid)
+{
+ struct iwl_tid_data *tid_data;
+ enum iwl_agg_state agg_state;
+ int sta_id, txq_id;
+ sta_id = iwl_sta_id(sta);
+
+ /*
+ * First set the agg state to OFF to avoid calling
+ * ieee80211_stop_tx_ba_cb in iwlagn_check_ratid_empty.
+ */
+ spin_lock_bh(&priv->sta_lock);
+
+ tid_data = &priv->tid_data[sta_id][tid];
+ txq_id = tid_data->agg.txq_id;
+ agg_state = tid_data->agg.state;
+ IWL_DEBUG_TX_QUEUES(priv, "Flush AGG: sta %d tid %d q %d state %d\n",
+ sta_id, tid, txq_id, tid_data->agg.state);
+
+ tid_data->agg.state = IWL_AGG_OFF;
+
+ spin_unlock_bh(&priv->sta_lock);
+
+ if (iwlagn_txfifo_flush(priv, BIT(txq_id)))
+ IWL_ERR(priv, "Couldn't flush the AGG queue\n");
+
+ if (test_bit(txq_id, priv->agg_q_alloc)) {
+ /*
+ * If the transport didn't know that we wanted to start
+ * agreggation, don't tell it that we want to stop them.
+ * This can happen when we don't get the addBA response on
+ * time, or we hadn't time to drain the AC queues.
+ */
+ if (agg_state == IWL_AGG_ON)
+ iwl_trans_txq_disable(priv->trans, txq_id);
+ else
+ IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n",
+ agg_state);
+ iwlagn_dealloc_agg_txq(priv, txq_id);
+ }
+
+ return 0;
+}
+
int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid, u8 buf_size)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 498300577ac0..39aad9893e0b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -912,8 +912,6 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
}
}
- IWL_INFO(drv, "loaded firmware version %s", drv->fw.fw_version);
-
/*
* In mvm uCode there is no difference between data and instructions
* sections.
@@ -970,6 +968,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
else
op = &iwlwifi_opmode_table[DVM_OP_MODE];
+ IWL_INFO(drv, "loaded firmware version %s op_mode %s\n",
+ drv->fw.fw_version, op->name);
+
/* add this device to the list of devices using this op_mode */
list_add_tail(&drv->list, &op->drv);
@@ -997,8 +998,13 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
* else from proceeding if the module fails to load
* or hangs loading.
*/
- if (load_module)
- request_module("%s", op->name);
+ if (load_module) {
+ err = request_module("%s", op->name);
+ if (err)
+ IWL_ERR(drv,
+ "failed to load module %s (error %d), is dynamic loading enabled?\n",
+ op->name, err);
+ }
return;
try_again:
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 7f9c254292a8..7a13790b5bfe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -305,7 +305,6 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
* currently supports
*/
#define IWL_MAX_HW_QUEUES 32
-#define IWL_INVALID_STATION 255
#define IWL_MAX_TID_COUNT 8
#define IWL_FRAME_LIMIT 64
@@ -682,7 +681,7 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
int fifo)
{
- iwl_trans_txq_enable(trans, queue, fifo, IWL_INVALID_STATION,
+ iwl_trans_txq_enable(trans, queue, fifo, -1,
IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
index 1700232aa166..810bfa5f6de0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
@@ -61,6 +61,8 @@
*
*****************************************************************************/
+#include <net/mac80211.h>
+
#include "fw-api-bt-coex.h"
#include "iwl-modparams.h"
#include "mvm.h"
@@ -96,6 +98,20 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
#undef EVENT_PRIO_ANT
+/* BT Antenna Coupling Threshold (dB) */
+#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
+#define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3)
+
+#define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62)
+#define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65)
+#define BT_REDUCED_TX_POWER_BIT BIT(7)
+
+static inline bool is_loose_coex(void)
+{
+ return iwlwifi_mod_params.ant_coupling >
+ IWL_BT_ANTENNA_COUPLING_THRESHOLD;
+}
+
int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
{
return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC,
@@ -186,11 +202,6 @@ static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = {
cpu_to_le32(0x00000000),
};
-/* BT Antenna Coupling Threshold (dB) */
-#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
-#define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3)
-
-
int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
{
struct iwl_bt_coex_cmd cmd = {
@@ -203,8 +214,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
cmd.flags = iwlwifi_mod_params.bt_coex_active ?
BT_COEX_NW : BT_COEX_DISABLE;
- cmd.flags |= iwlwifi_mod_params.bt_ch_announce ? BT_CH_PRIMARY_EN : 0;
- cmd.flags |= BT_SYNC_2_BT_DISABLE;
+ cmd.flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE;
cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
BT_VALID_BT_PRIO_BOOST |
@@ -215,7 +225,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
BT_VALID_REDUCED_TX_POWER |
BT_VALID_LUT);
- if (iwlwifi_mod_params.ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD)
+ if (is_loose_coex())
memcpy(&cmd.decision_lut, iwl_loose_lookup,
sizeof(iwl_tight_lookup));
else
@@ -228,6 +238,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
cmd.kill_cts_msk =
cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
+ memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
+
/* go to CALIB state in internal BT-Coex state machine */
ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
@@ -243,19 +255,101 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
sizeof(cmd), &cmd);
}
-struct iwl_bt_notif_iterator_data {
- struct iwl_mvm *mvm;
+static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
+ bool reduced_tx_power)
+{
+ enum iwl_bt_kill_msk bt_kill_msk;
+ struct iwl_bt_coex_cmd cmd = {};
+ struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (reduced_tx_power) {
+ /* Reduced Tx power has precedence on the type of the profile */
+ bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
+ } else {
+ /* Low latency BT profile is active: give higher prio to BT */
+ if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
+ BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
+ BT_MBOX_MSG(notif, 3, SNIFF_STATE))
+ bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
+ else
+ bt_kill_msk = BT_KILL_MSK_DEFAULT;
+ }
+
+ IWL_DEBUG_COEX(mvm,
+ "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
+ bt_kill_msk,
+ BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
+ BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
+ BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
+
+ /* Don't send HCMD if there is no update */
+ if (bt_kill_msk == mvm->bt_kill_msk)
+ return 0;
+
+ mvm->bt_kill_msk = bt_kill_msk;
+ cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
+ cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
+ cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
+
+ IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk);
+ return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC,
+ sizeof(cmd), &cmd);
+}
+
+static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
+ bool enable)
+{
+ struct iwl_bt_coex_cmd cmd = {
+ .valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER),
+ .bt_reduced_tx_power = sta_id,
+ };
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvmsta;
+
+ /* This can happen if the station has been removed right now */
+ if (sta_id == IWL_MVM_STATION_COUNT)
+ return 0;
+
+ sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
+ lockdep_is_held(&mvm->mutex));
+ mvmsta = (void *)sta->drv_priv;
+
+ /* nothing to do */
+ if (mvmsta->bt_reduced_txpower == enable)
+ return 0;
+
+ if (enable)
+ cmd.bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
+
+ IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
+ enable ? "en" : "dis", sta_id);
+
+ mvmsta->bt_reduced_txpower = enable;
+
+ /* Send ASYNC since this can be sent from an atomic context */
+ return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_ASYNC,
+ sizeof(cmd), &cmd);
+}
+
+struct iwl_bt_iterator_data {
struct iwl_bt_coex_profile_notif *notif;
+ struct iwl_mvm *mvm;
+ u32 num_bss_ifaces;
+ bool reduced_tx_power;
};
static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_bt_notif_iterator_data *data = _data;
+ struct iwl_bt_iterator_data *data = _data;
+ struct iwl_mvm *mvm = data->mvm;
struct ieee80211_chanctx_conf *chanctx_conf;
enum ieee80211_smps_mode smps_mode;
enum ieee80211_band band;
+ int ave_rssi;
if (vif->type != NL80211_IFTYPE_STATION)
return;
@@ -268,11 +362,13 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
band = -1;
rcu_read_unlock();
- if (band != IEEE80211_BAND_2GHZ)
- return;
-
smps_mode = IEEE80211_SMPS_AUTOMATIC;
+ if (band != IEEE80211_BAND_2GHZ) {
+ ieee80211_request_smps(vif, smps_mode);
+ return;
+ }
+
if (data->notif->bt_status)
smps_mode = IEEE80211_SMPS_DYNAMIC;
@@ -285,20 +381,88 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
data->notif->bt_traffic_load, smps_mode);
ieee80211_request_smps(vif, smps_mode);
+
+ /* don't reduce the Tx power if in loose scheme */
+ if (is_loose_coex())
+ return;
+
+ data->num_bss_ifaces++;
+
+ /* reduced Txpower only if there are open BT connections, so ...*/
+ if (!BT_MBOX_MSG(data->notif, 3, OPEN_CON_2)) {
+ /* ... cancel reduced Tx power ... */
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
+ IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+ data->reduced_tx_power = false;
+
+ /* ... and there is no need to get reports on RSSI any more. */
+ ieee80211_disable_rssi_reports(vif);
+ return;
+ }
+
+ ave_rssi = ieee80211_ave_rssi(vif);
+
+ /* if the RSSI isn't valid, fake it is very low */
+ if (!ave_rssi)
+ ave_rssi = -100;
+ if (ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) {
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
+ IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+
+ /*
+ * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
+ * BSS / P2P clients have rssi above threshold.
+ * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
+ * the iteration, if one interface's rssi isn't good enough,
+ * bt_kill_msk will be set to default values.
+ */
+ } else if (ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) {
+ if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
+ IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+
+ /*
+ * One interface hasn't rssi above threshold, bt_kill_msk must
+ * be set to default values.
+ */
+ data->reduced_tx_power = false;
+ }
+
+ /* Begin to monitor the RSSI: it may influence the reduced Tx power */
+ ieee80211_enable_rssi_reports(vif, BT_DISABLE_REDUCED_TXPOWER_THRESHOLD,
+ BT_ENABLE_REDUCED_TXPOWER_THRESHOLD);
+}
+
+static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
+{
+ struct iwl_bt_iterator_data data = {
+ .mvm = mvm,
+ .notif = &mvm->last_bt_notif,
+ .reduced_tx_power = true,
+ };
+
+ ieee80211_iterate_active_interfaces_atomic(
+ mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_bt_notif_iterator, &data);
+
+ /*
+ * If there are no BSS / P2P client interfaces, reduced Tx Power is
+ * irrelevant since it is based on the RSSI coming from the beacon.
+ * Use BT_KILL_MSK_DEFAULT in that case.
+ */
+ data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
+
+ if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
+ IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
}
+/* upon association, the fw will send in BT Coex notification */
int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *dev_cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
- struct iwl_bt_notif_iterator_data data = {
- .mvm = mvm,
- .notif = notif,
- };
- struct iwl_bt_coex_cmd cmd = {};
- enum iwl_bt_kill_msk bt_kill_msk;
+
IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
IWL_DEBUG_COEX(mvm, "\tBT %salive\n", notif->bt_status ? "" : "not ");
@@ -311,38 +475,115 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
/* remember this notification for future use: rssi fluctuations */
memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif));
- ieee80211_iterate_active_interfaces_atomic(
- mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_bt_notif_iterator, &data);
+ iwl_mvm_bt_coex_notif_handle(mvm);
+
+ /*
+ * This is an async handler for a notification, returning anything other
+ * than 0 doesn't make sense even if HCMD failed.
+ */
+ return 0;
+}
+
+static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
+ struct iwl_bt_iterator_data *data = _data;
+ struct iwl_mvm *mvm = data->mvm;
+
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvmsta;
+
+ if (vif->type != NL80211_IFTYPE_STATION ||
+ mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
+ return;
+
+ sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
+ lockdep_is_held(&mvm->mutex));
+ mvmsta = (void *)sta->drv_priv;
+
+ /*
+ * This interface doesn't support reduced Tx power (because of low
+ * RSSI probably), then set bt_kill_msk to default values.
+ */
+ if (!mvmsta->bt_reduced_txpower)
+ data->reduced_tx_power = false;
+ /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
+}
+
+void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ enum ieee80211_rssi_event rssi_event)
+{
+ struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
+ struct iwl_bt_iterator_data data = {
+ .mvm = mvm,
+ .reduced_tx_power = true,
+ };
+ int ret;
+
+ mutex_lock(&mvm->mutex);
+
+ /* Rssi update while not associated ?! */
+ if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT))
+ goto out_unlock;
- /* Low latency BT profile is active: give higher prio to BT */
- if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
- BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
- BT_MBOX_MSG(notif, 3, SNIFF_STATE))
- bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
+ /* No open connection - reports should be disabled */
+ if (!BT_MBOX_MSG(&mvm->last_bt_notif, 3, OPEN_CON_2))
+ goto out_unlock;
+
+ IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid,
+ rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW");
+
+ /*
+ * Check if rssi is good enough for reduced Tx power, but not in loose
+ * scheme.
+ */
+ if (rssi_event == RSSI_EVENT_LOW || is_loose_coex())
+ ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+ false);
else
- bt_kill_msk = BT_KILL_MSK_DEFAULT;
+ ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true);
- /* Don't send HCMD if there is no update */
- if (bt_kill_msk == mvm->bt_kill_msk)
- return 0;
+ if (ret)
+ IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
- IWL_DEBUG_COEX(mvm,
- "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
- bt_kill_msk,
- BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
- BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
- BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
+ ieee80211_iterate_active_interfaces_atomic(
+ mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_bt_rssi_iterator, &data);
- mvm->bt_kill_msk = bt_kill_msk;
- cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
- cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
+ /*
+ * If there are no BSS / P2P client interfaces, reduced Tx Power is
+ * irrelevant since it is based on the RSSI coming from the beacon.
+ * Use BT_KILL_MSK_DEFAULT in that case.
+ */
+ data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
- cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
+ if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
+ IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
- if (iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, sizeof(cmd), &cmd))
- IWL_ERR(mvm, "Failed to sent BT Coex CMD\n");
+ out_unlock:
+ mutex_unlock(&mvm->mutex);
+}
- /* This handler is ASYNC */
- return 0;
+void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ enum ieee80211_band band;
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(vif->chanctx_conf);
+ if (chanctx_conf && chanctx_conf->def.chan)
+ band = chanctx_conf->def.chan->band;
+ else
+ band = -1;
+ rcu_read_unlock();
+
+ /* if we are in 2GHz we will get a notification from the fw */
+ if (band == IEEE80211_BAND_2GHZ)
+ return;
+
+ /* else, we can remove all the constraints */
+ memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
+
+ iwl_mvm_bt_coex_notif_handle(mvm);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index bf087abe39f3..16bbdcc8627a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -769,7 +769,14 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
- struct iwl_d3_manager_config d3_cfg_cmd = {};
+ struct iwl_d3_manager_config d3_cfg_cmd = {
+ /*
+ * Program the minimum sleep time to 10 seconds, as many
+ * platforms have issues processing a wakeup signal while
+ * still being in the process of suspending.
+ */
+ .min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
+ };
struct wowlan_key_data key_data = {
.use_rsc_tsc = false,
.tkip = &tkip_cmd,
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index b080b4ba5458..2053dccefcd6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -300,6 +300,67 @@ static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file,
return count;
}
+static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_vif *vif = file->private_data;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm *mvm = mvmvif->dbgfs_data;
+ u8 ap_sta_id;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ char buf[512];
+ int bufsz = sizeof(buf);
+ int pos = 0;
+ int i;
+
+ mutex_lock(&mvm->mutex);
+
+ ap_sta_id = mvmvif->ap_sta_id;
+
+ pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
+ mvmvif->id, mvmvif->color);
+ pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
+ vif->bss_conf.bssid);
+ pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
+ for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++) {
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
+ i, mvmvif->queue_params[i].txop,
+ mvmvif->queue_params[i].cw_min,
+ mvmvif->queue_params[i].cw_max,
+ mvmvif->queue_params[i].aifs,
+ mvmvif->queue_params[i].uapsd);
+ }
+
+ if (vif->type == NL80211_IFTYPE_STATION &&
+ ap_sta_id != IWL_MVM_STATION_COUNT) {
+ struct ieee80211_sta *sta;
+ struct iwl_mvm_sta *mvm_sta;
+
+ sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
+ lockdep_is_held(&mvm->mutex));
+ mvm_sta = (void *)sta->drv_priv;
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "ap_sta_id %d - reduced Tx power %d\n",
+ ap_sta_id, mvm_sta->bt_reduced_txpower);
+ }
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(vif->chanctx_conf);
+ if (chanctx_conf) {
+ pos += scnprintf(buf+pos, bufsz-pos,
+ "idle rx chains %d, active rx chains: %d\n",
+ chanctx_conf->rx_chains_static,
+ chanctx_conf->rx_chains_dynamic);
+ }
+ rcu_read_unlock();
+
+ mutex_unlock(&mvm->mutex);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
#define BT_MBOX_MSG(_notif, _num, _field) \
((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
>> BT_MBOX##_num##_##_field##_POS)
@@ -464,6 +525,9 @@ MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow);
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart);
+/* Interface specific debugfs entries */
+MVM_DEBUGFS_READ_FILE_OPS(mac_params);
+
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
{
char buf[100];
@@ -494,3 +558,58 @@ err:
IWL_ERR(mvm, "Can't create the mvm debugfs directory\n");
return -ENOMEM;
}
+
+void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+ struct dentry *dbgfs_dir = vif->debugfs_dir;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ char buf[100];
+
+ if (!dbgfs_dir)
+ return;
+
+ mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
+ mvmvif->dbgfs_data = mvm;
+
+ if (!mvmvif->dbgfs_dir) {
+ IWL_ERR(mvm, "Failed to create debugfs directory under %s\n",
+ dbgfs_dir->d_name.name);
+ return;
+ }
+
+ MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir,
+ S_IRUSR);
+
+ /*
+ * Create symlink for convenience pointing to interface specific
+ * debugfs entries for the driver. For example, under
+ * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
+ * find
+ * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
+ */
+ snprintf(buf, 100, "../../../%s/%s/%s/%s",
+ dbgfs_dir->d_parent->d_parent->d_name.name,
+ dbgfs_dir->d_parent->d_name.name,
+ dbgfs_dir->d_name.name,
+ mvmvif->dbgfs_dir->d_name.name);
+
+ mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
+ mvm->debugfs_dir, buf);
+ if (!mvmvif->dbgfs_slink)
+ IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n",
+ dbgfs_dir->d_name.name);
+ return;
+err:
+ IWL_ERR(mvm, "Can't create debugfs entity\n");
+}
+
+void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ debugfs_remove(mvmvif->dbgfs_slink);
+ mvmvif->dbgfs_slink = NULL;
+
+ debugfs_remove_recursive(mvmvif->dbgfs_dir);
+ mvmvif->dbgfs_dir = NULL;
+}
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index 127051891e9b..81fe45f46be7 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -68,73 +68,53 @@
/**
* enum iwl_scan_flags - masks for power table command flags
+ * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
+ * receiver and transmitter. '0' - does not allow.
* @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
* '1' Driver enables PM (use rest of parameters)
- * @POWER_FLAGS_SLEEP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
+ * @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
* '1' PM could sleep over DTIM till listen Interval.
- * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
- * @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all
- * access categories are both delivery and trigger enabled.
- * @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and
- * PBW Snoozing enabled
* @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
+ * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
*/
enum iwl_power_flags {
- POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(0),
- POWER_FLAGS_SLEEP_OVER_DTIM_MSK = BIT(1),
- POWER_FLAGS_LPRX_ENA_MSK = BIT(2),
- POWER_FLAGS_SNOOZE_ENA_MSK = BIT(3),
- POWER_FLAGS_BT_SCO_ENA = BIT(4),
- POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(5)
+ POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
+ POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(1),
+ POWER_FLAGS_SKIP_OVER_DTIM_MSK = BIT(2),
+ POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9),
+ POWER_FLAGS_LPRX_ENA_MSK = BIT(11),
};
+#define IWL_POWER_VEC_SIZE 5
+
/**
* struct iwl_powertable_cmd - Power Table Command
* POWER_TABLE_CMD = 0x77 (command, has simple generic response)
*
- * @id_and_color: MAC contex identifier
- * @action: Action on context - no action, add new,
- * modify existent, remove
* @flags: Power table command flags from POWER_FLAGS_*
* @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
- * Minimum allowed:- 3 * DTIM
+ * Minimum allowed:- 3 * DTIM. Keep alive period must be
+ * set regardless of power scheme or current power state.
+ * FW use this value also when PM is disabled.
* @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to
* PSM transition - legacy PM
* @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
* PSM transition - legacy PM
- * @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to
- * PSM transition - uAPSD
- * @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to
- * PSM transition - uAPSD
+ * @sleep_interval: not in use
+ * @keep_alive_beacons: not in use
* @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
* Default: 80dbm
- * @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set
- * @snooze_interval: TBD
- * @snooze_window: TBD
- * @snooze_step: TBD
- * @qndp_tid: TBD
- * @uapsd_ac_flags: TBD
- * @uapsd_max_sp: TBD
*/
struct iwl_powertable_cmd {
- /* COMMON_INDEX_HDR_API_S_VER_1 */
- __le32 id_and_color;
- __le32 action;
+ /* PM_POWER_TABLE_CMD_API_S_VER_5 */
__le16 flags;
- u8 reserved;
- __le16 keep_alive_seconds;
+ u8 keep_alive_seconds;
+ u8 debug_flags;
__le32 rx_data_timeout;
__le32 tx_data_timeout;
- __le32 rx_data_timeout_uapsd;
- __le32 tx_data_timeout_uapsd;
- u8 lprx_rssi_threshold;
- u8 num_skip_dtim;
- __le16 snooze_interval;
- __le16 snooze_window;
- u8 snooze_step;
- u8 qndp_tid;
- u8 uapsd_ac_flags;
- u8 uapsd_max_sp;
+ __le32 sleep_interval[IWL_POWER_VEC_SIZE];
+ __le32 keep_alive_beacons;
+ __le32 lprx_rssi_threshold;
} __packed;
#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 1073f2682221..191dcae8ba47 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -480,15 +480,34 @@ enum {
TE_DEP_TSF = 2,
TE_EVENT_SOCIOPATHIC = 4,
}; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */
-
-/* When to send Time Event notifications and to whom (internal = FW) */
+/*
+ * Supported Time event notifications configuration.
+ * A notification (both event and fragment) includes a status indicating weather
+ * the FW was able to schedule the event or not. For fragment start/end
+ * notification the status is always success. There is no start/end fragment
+ * notification for monolithic events.
+ *
+ * @TE_NOTIF_NONE: no notifications
+ * @TE_NOTIF_HOST_EVENT_START: request/receive notification on event start
+ * @TE_NOTIF_HOST_EVENT_END:request/receive notification on event end
+ * @TE_NOTIF_INTERNAL_EVENT_START: internal FW use
+ * @TE_NOTIF_INTERNAL_EVENT_END: internal FW use.
+ * @TE_NOTIF_HOST_FRAG_START: request/receive notification on frag start
+ * @TE_NOTIF_HOST_FRAG_END:request/receive notification on frag end
+ * @TE_NOTIF_INTERNAL_FRAG_START: internal FW use.
+ * @TE_NOTIF_INTERNAL_FRAG_END: internal FW use.
+ */
enum {
TE_NOTIF_NONE = 0,
- TE_NOTIF_HOST_START = 0x1,
- TE_NOTIF_HOST_END = 0x2,
- TE_NOTIF_INTERNAL_START = 0x4,
- TE_NOTIF_INTERNAL_END = 0x8
-}; /* MAC_EVENT_ACTION_API_E_VER_1 */
+ TE_NOTIF_HOST_EVENT_START = 0x1,
+ TE_NOTIF_HOST_EVENT_END = 0x2,
+ TE_NOTIF_INTERNAL_EVENT_START = 0x4,
+ TE_NOTIF_INTERNAL_EVENT_END = 0x8,
+ TE_NOTIF_HOST_FRAG_START = 0x10,
+ TE_NOTIF_HOST_FRAG_END = 0x20,
+ TE_NOTIF_INTERNAL_FRAG_START = 0x40,
+ TE_NOTIF_INTERNAL_FRAG_END = 0x80
+}; /* MAC_EVENT_ACTION_API_E_VER_2 */
/*
* @TE_FRAG_NONE: fragmentation of the time event is NOT allowed.
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 86e312a4f629..e6eca4d66f6c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -669,6 +669,7 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,
u32 action)
{
struct iwl_mac_ctx_cmd cmd = {};
+ struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
WARN_ON(vif->type != NL80211_IFTYPE_STATION || !vif->p2p);
@@ -678,7 +679,8 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,
/* Fill the data specific for station mode */
iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta);
- cmd.p2p_sta.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow);
+ cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &
+ IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
@@ -919,6 +921,7 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
u32 action)
{
struct iwl_mac_ctx_cmd cmd = {};
+ struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
WARN_ON(vif->type != NL80211_IFTYPE_AP || !vif->p2p);
@@ -929,8 +932,11 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap,
action == FW_CTXT_ACTION_ADD);
- cmd.go.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow);
- cmd.go.opp_ps_enabled = cpu_to_le32(!!vif->bss_conf.p2p_oppps);
+ cmd.go.ctwin = cpu_to_le32(noa->oppps_ctwindow &
+ IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
+ cmd.go.opp_ps_enabled =
+ cpu_to_le32(!!(noa->oppps_ctwindow &
+ IEEE80211_P2P_OPPPS_ENABLE_BIT));
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 3d193f8c33b6..fe031608fd91 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -502,11 +502,15 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
/*
* TODO: remove this temporary code.
* Currently MVM FW supports power management only on single MAC.
- * Iterate and disable PM on all active interfaces.
+ * If new interface added, disable PM on existing interface.
+ * P2P device is a special case, since it is handled by FW similary to
+ * scan. If P2P deviced is added, PM remains enabled on existing
+ * interface.
* Note: the method below does not count the new interface being added
* at this moment.
*/
- mvm->vif_count++;
+ if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
+ mvm->vif_count++;
if (mvm->vif_count > 1) {
IWL_DEBUG_MAC80211(mvm,
"Disable power on existing interfaces\n");
@@ -562,6 +566,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
mvm->p2p_device_vif = vif;
}
+ iwl_mvm_vif_dbgfs_register(mvm, vif);
goto out_unlock;
out_unbind:
@@ -575,10 +580,11 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
/*
* TODO: remove this temporary code.
* Currently MVM FW supports power management only on single MAC.
- * Check if only one additional interface remains after rereasing
+ * Check if only one additional interface remains after releasing
* current one. Update power mode on the remaining interface.
*/
- mvm->vif_count--;
+ if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
+ mvm->vif_count--;
IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n",
mvm->vif_count);
if (mvm->vif_count == 1) {
@@ -640,6 +646,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
+ iwl_mvm_vif_dbgfs_clean(mvm, vif);
+
/*
* For AP/GO interface, the tear down of the resources allocated to the
* interface is be handled as part of the stop_ap flow.
@@ -663,7 +671,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
* Check if only one additional interface remains after removing
* current one. Update power mode on the remaining interface.
*/
- if (mvm->vif_count)
+ if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE)
mvm->vif_count--;
IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n",
mvm->vif_count);
@@ -713,6 +721,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_ERR(mvm, "failed to update quotas\n");
return;
}
+ iwl_mvm_bt_coex_vif_assoc(mvm, vif);
} else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
/* remove AP station now that the MAC is unassoc */
ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id);
@@ -931,7 +940,7 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
*/
break;
case STA_NOTIFY_AWAKE:
- if (WARN_ON(mvmsta->sta_id == IWL_INVALID_STATION))
+ if (WARN_ON(mvmsta->sta_id == IWL_MVM_STATION_COUNT))
break;
iwl_mvm_sta_modify_ps_wake(mvm, sta);
break;
@@ -1326,6 +1335,15 @@ static int iwl_mvm_set_tim(struct ieee80211_hw *hw,
return iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm_sta->vif);
}
+static void iwl_mvm_mac_rssi_callback(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum ieee80211_rssi_event rssi_event)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+ iwl_mvm_bt_rssi_event(mvm, vif, rssi_event);
+}
+
struct ieee80211_ops iwl_mvm_hw_ops = {
.tx = iwl_mvm_mac_tx,
.ampdu_action = iwl_mvm_mac_ampdu_action,
@@ -1349,6 +1367,7 @@ struct ieee80211_ops iwl_mvm_hw_ops = {
.update_tkip_key = iwl_mvm_mac_update_tkip_key,
.remain_on_channel = iwl_mvm_roc,
.cancel_remain_on_channel = iwl_mvm_cancel_roc,
+ .rssi_callback = iwl_mvm_mac_rssi_callback,
.add_chanctx = iwl_mvm_add_chanctx,
.remove_chanctx = iwl_mvm_remove_chanctx,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 53d58968e30a..8269bc562951 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -212,6 +212,7 @@ struct iwl_mvm_vif {
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct dentry *dbgfs_dir;
+ struct dentry *dbgfs_slink;
void *dbgfs_data;
#endif
};
@@ -321,6 +322,13 @@ struct iwl_mvm {
* can hold 16 keys at most. Reflect this fact.
*/
unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
+
+ /*
+ * This counter of created interfaces is referenced only in conjunction
+ * with FW limitation related to power management. Currently PM is
+ * supported only on a single interface.
+ * IMPORTANT: this variable counts all interfaces except P2P device.
+ */
u8 vif_count;
struct led_classdev led;
@@ -471,16 +479,22 @@ void iwl_mvm_cancel_scan(struct iwl_mvm *mvm);
/* MVM debugfs */
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir);
-int iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct dentry *dbgfs_dir);
-void iwl_power_get_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct iwl_powertable_cmd *cmd);
+void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
#else
static inline int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm,
struct dentry *dbgfs_dir)
{
return 0;
}
+static inline void
+iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+}
+static inline void
+iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+}
#endif /* CONFIG_IWLWIFI_DEBUGFS */
/* rate scaling */
@@ -490,6 +504,8 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
/* power managment */
int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct iwl_powertable_cmd *cmd);
int iwl_mvm_leds_init(struct iwl_mvm *mvm);
void iwl_mvm_leds_exit(struct iwl_mvm *mvm);
@@ -513,5 +529,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm);
int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
+void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ enum ieee80211_rssi_event rssi_event);
+void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index efb9a6f3faac..9395ab2a1af2 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -75,23 +75,49 @@
#define POWER_KEEP_ALIVE_PERIOD_SEC 25
-static void iwl_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct iwl_powertable_cmd *cmd)
+static void iwl_mvm_power_log(struct iwl_mvm *mvm,
+ struct iwl_powertable_cmd *cmd)
+{
+ IWL_DEBUG_POWER(mvm,
+ "Sending power table command for power level %d, flags = 0x%X\n",
+ iwlmvm_mod_params.power_scheme,
+ le16_to_cpu(cmd->flags));
+ IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds);
+
+ if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
+ IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
+ le32_to_cpu(cmd->rx_data_timeout));
+ IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
+ le32_to_cpu(cmd->tx_data_timeout));
+ IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
+ cmd->lprx_rssi_threshold);
+ }
+}
+
+void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct iwl_powertable_cmd *cmd)
{
struct ieee80211_hw *hw = mvm->hw;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_channel *chan;
int dtimper, dtimper_msec;
int keep_alive;
bool radar_detect = false;
- cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
- mvmvif->color));
- cmd->action = cpu_to_le32(FW_CTXT_ACTION_MODIFY);
+ /*
+ * Regardless of power management state the driver must set
+ * keep alive period. FW will use it for sending keep alive NDPs
+ * immediately after association.
+ */
+ cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC;
+
+ if ((iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) ||
+ !iwlwifi_mod_params.power_save)
+ return;
+
+ cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
- if ((!vif->bss_conf.ps) ||
- (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM))
+ if (!vif->bss_conf.ps)
return;
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
@@ -110,26 +136,23 @@ static void iwl_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
/* Check skip over DTIM conditions */
if (!radar_detect && (dtimper <= 10) &&
- (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP)) {
- cmd->flags |= cpu_to_le16(POWER_FLAGS_SLEEP_OVER_DTIM_MSK);
- cmd->num_skip_dtim = 2;
- }
+ (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP))
+ cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
/* Check that keep alive period is at least 3 * DTIM */
dtimper_msec = dtimper * vif->bss_conf.beacon_int;
keep_alive = max_t(int, 3 * dtimper_msec,
- MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC);
+ MSEC_PER_SEC * cmd->keep_alive_seconds);
keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
-
- cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
+ cmd->keep_alive_seconds = keep_alive;
if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP) {
/* TODO: Also for D3 (device sleep / WoWLAN) */
- cmd->rx_data_timeout = cpu_to_le32(10);
- cmd->tx_data_timeout = cpu_to_le32(10);
+ cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
+ cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
} else {
- cmd->rx_data_timeout = cpu_to_le32(50);
- cmd->tx_data_timeout = cpu_to_le32(50);
+ cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
+ cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
}
}
@@ -137,36 +160,11 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_powertable_cmd cmd = {};
- if (!iwlwifi_mod_params.power_save) {
- IWL_DEBUG_POWER(mvm, "Power management is not allowed\n");
- return 0;
- }
-
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return 0;
- iwl_power_build_cmd(mvm, vif, &cmd);
-
- IWL_DEBUG_POWER(mvm,
- "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
- cmd.id_and_color, iwlmvm_mod_params.power_scheme,
- le16_to_cpu(cmd.flags));
-
- if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
- IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
- le16_to_cpu(cmd.keep_alive_seconds));
- IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
- le32_to_cpu(cmd.rx_data_timeout));
- IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
- le32_to_cpu(cmd.tx_data_timeout));
- IWL_DEBUG_POWER(mvm, "Rx timeout (uAPSD) = %u usec\n",
- le32_to_cpu(cmd.rx_data_timeout_uapsd));
- IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
- le32_to_cpu(cmd.tx_data_timeout_uapsd));
- IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
- cmd.lprx_rssi_threshold);
- IWL_DEBUG_POWER(mvm, "DTIMs to skip = %u\n", cmd.num_skip_dtim);
- }
+ iwl_mvm_power_build_cmd(mvm, vif, &cmd);
+ iwl_mvm_power_log(mvm, &cmd);
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
sizeof(cmd), &cmd);
@@ -175,33 +173,16 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_powertable_cmd cmd = {};
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- if (!iwlwifi_mod_params.power_save) {
- IWL_DEBUG_POWER(mvm, "Power management is not allowed\n");
- return 0;
- }
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return 0;
- cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
- mvmvif->color));
- cmd.action = cpu_to_le32(FW_CTXT_ACTION_MODIFY);
+ if ((iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) &&
+ iwlwifi_mod_params.power_save)
+ cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
- IWL_DEBUG_POWER(mvm,
- "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
- cmd.id_and_color, iwlmvm_mod_params.power_scheme,
- le16_to_cpu(cmd.flags));
+ iwl_mvm_power_log(mvm, &cmd);
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
sizeof(cmd), &cmd);
}
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-void iwl_power_get_params(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct iwl_powertable_cmd *cmd)
-{
- iwl_power_build_cmd(mvm, vif, cmd);
-}
-#endif /* CONFIG_IWLWIFI_DEBUGFS */
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index a01a6612677e..55334d542e26 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -793,7 +793,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
if (num_of_ant(tbl->ant_type) > 1)
tbl->ant_type =
- first_antenna(mvm->nvm_data->valid_tx_ant);
+ first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
tbl->is_ht40 = 0;
tbl->is_SGI = 0;
@@ -1235,7 +1235,7 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm,
return -1;
/* Need both Tx chains/antennas to support MIMO */
- if (num_of_ant(mvm->nvm_data->valid_tx_ant) < 2)
+ if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 2)
return -1;
IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n");
@@ -1287,7 +1287,7 @@ static int rs_switch_to_mimo3(struct iwl_mvm *mvm,
return -1;
/* Need both Tx chains/antennas to support MIMO */
- if (num_of_ant(mvm->nvm_data->valid_tx_ant) < 3)
+ if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 3)
return -1;
IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO3\n");
@@ -1381,7 +1381,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
u8 tx_chains_num = num_of_ant(valid_tx_ant);
int ret;
u8 update_search_tbl_counter = 0;
@@ -1514,7 +1514,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
u8 tx_chains_num = num_of_ant(valid_tx_ant);
u8 update_search_tbl_counter = 0;
int ret;
@@ -1649,7 +1649,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
u8 tx_chains_num = num_of_ant(valid_tx_ant);
u8 update_search_tbl_counter = 0;
int ret;
@@ -1786,7 +1786,7 @@ static int rs_move_mimo3_to_other(struct iwl_mvm *mvm,
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action;
- u8 valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
u8 tx_chains_num = num_of_ant(valid_tx_ant);
int ret;
u8 update_search_tbl_counter = 0;
@@ -2449,7 +2449,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
i = lq_sta->last_txrate_idx;
- valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
if (!lq_sta->search_better_tbl)
active_tbl = lq_sta->active_tbl;
@@ -2639,15 +2639,15 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
/* These values will be overridden later */
lq_sta->lq.single_stream_ant_msk =
- first_antenna(mvm->nvm_data->valid_tx_ant);
+ first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
lq_sta->lq.dual_stream_ant_msk =
- mvm->nvm_data->valid_tx_ant &
- ~first_antenna(mvm->nvm_data->valid_tx_ant);
+ iwl_fw_valid_tx_ant(mvm->fw) &
+ ~first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
if (!lq_sta->lq.dual_stream_ant_msk) {
lq_sta->lq.dual_stream_ant_msk = ANT_AB;
- } else if (num_of_ant(mvm->nvm_data->valid_tx_ant) == 2) {
+ } else if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) == 2) {
lq_sta->lq.dual_stream_ant_msk =
- mvm->nvm_data->valid_tx_ant;
+ iwl_fw_valid_tx_ant(mvm->fw);
}
/* as default allow aggregation for all tids */
@@ -2708,7 +2708,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
index++;
repeat_rate--;
if (mvm)
- valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
/* Fill rest of rate table */
while (index < LINK_QUAL_MAX_RETRY_NUM) {
@@ -2813,7 +2813,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
u8 ant_sel_tx;
mvm = lq_sta->drv;
- valid_tx_ant = mvm->nvm_data->valid_tx_ant;
+ valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
if (lq_sta->dbg_fixed_rate) {
ant_sel_tx =
((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK)
@@ -2884,9 +2884,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
desc += sprintf(buff+desc, "fixed rate 0x%X\n",
lq_sta->dbg_fixed_rate);
desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
- (mvm->nvm_data->valid_tx_ant & ANT_A) ? "ANT_A," : "",
- (mvm->nvm_data->valid_tx_ant & ANT_B) ? "ANT_B," : "",
- (mvm->nvm_data->valid_tx_ant & ANT_C) ? "ANT_C" : "");
+ (iwl_fw_valid_tx_ant(mvm->fw) & ANT_A) ? "ANT_A," : "",
+ (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "",
+ (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : "");
desc += sprintf(buff+desc, "lq type %s\n",
(is_legacy(tbl->lq_type)) ? "legacy" : "HT");
if (is_Ht(tbl->lq_type)) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 4d872d69577f..0fd96e4da461 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -945,7 +945,7 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT)
return mvmvif->ap_sta_id;
- return IWL_INVALID_STATION;
+ return IWL_MVM_STATION_COUNT;
}
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
@@ -1093,7 +1093,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
/* Get the station id from the mvm local station table */
sta_id = iwl_mvm_get_key_sta_id(vif, sta);
- if (sta_id == IWL_INVALID_STATION) {
+ if (sta_id == IWL_MVM_STATION_COUNT) {
IWL_ERR(mvm, "Failed to find station id\n");
return -EINVAL;
}
@@ -1188,7 +1188,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
return -ENOENT;
}
- if (sta_id == IWL_INVALID_STATION) {
+ if (sta_id == IWL_MVM_STATION_COUNT) {
IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n");
return 0;
}
@@ -1254,7 +1254,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvm_sta;
u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta);
- if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION))
+ if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
return;
rcu_read_lock();
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h
index b0352df981e4..12abd2d71835 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.h
@@ -271,6 +271,7 @@ struct iwl_mvm_tid_data {
* @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for
* tid.
* @max_agg_bufsize: the maximal size of the AGG buffer for this station
+ * @bt_reduced_txpower: is reduced tx power enabled for this station
* @lock: lock to protect the whole struct. Since %tid_data is access from Tx
* and from Tx response flow, it needs a spinlock.
* @pending_frames: number of frames for this STA on the shared Tx queues.
@@ -287,6 +288,7 @@ struct iwl_mvm_sta {
u32 mac_id_n_color;
u16 tid_disable_agg;
u8 max_agg_bufsize;
+ bool bt_reduced_txpower;
spinlock_t lock;
atomic_t pending_frames;
struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT];
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index 4dc934bed055..ad9bbca99213 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -166,7 +166,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
WARN_ONCE(!le32_to_cpu(notif->status),
"Failed to schedule time event\n");
- if (le32_to_cpu(notif->action) == TE_NOTIF_HOST_END) {
+ if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_END) {
IWL_DEBUG_TE(mvm,
"TE ended - current time %lu, estimated end %lu\n",
jiffies, te_data->end_jiffies);
@@ -189,7 +189,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
}
iwl_mvm_te_clear_data(mvm, te_data);
- } else if (le32_to_cpu(notif->action) == TE_NOTIF_HOST_START) {
+ } else if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_START) {
te_data->running = true;
te_data->end_jiffies = jiffies +
TU_TO_JIFFIES(te_data->duration);
@@ -368,7 +368,8 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
time_cmd.interval_reciprocal = cpu_to_le32(iwl_mvm_reciprocal(1));
time_cmd.duration = cpu_to_le32(duration);
time_cmd.repeat = cpu_to_le32(1);
- time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END);
+ time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START |
+ TE_NOTIF_HOST_EVENT_END);
iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
}
@@ -485,7 +486,8 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2));
time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration));
time_cmd.repeat = cpu_to_le32(1);
- time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_START | TE_NOTIF_HOST_END);
+ time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START |
+ TE_NOTIF_HOST_EVENT_END);
return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 0acc0bff43c7..479074303bd7 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -205,7 +205,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx);
mvm->mgmt_last_antenna_idx =
- iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant,
+ iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
mvm->mgmt_last_antenna_idx);
rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
@@ -365,7 +365,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
if (WARN_ON_ONCE(!mvmsta))
return -1;
- if (WARN_ON_ONCE(mvmsta->sta_id == IWL_INVALID_STATION))
+ if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT))
return -1;
dev_cmd = iwl_mvm_set_tx_params(mvm, skb, sta, mvmsta->sta_id);
@@ -641,10 +641,12 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
}
IWL_DEBUG_TX_REPLY(mvm,
- "TXQ %d status %s (0x%08x)\n\t\t\t\tinitial_rate 0x%x "
- "retries %d, idx=%d ssn=%d next_reclaimed=0x%x seq_ctl=0x%x\n",
- txq_id, iwl_mvm_get_tx_fail_reason(status),
- status, le32_to_cpu(tx_resp->initial_rate),
+ "TXQ %d status %s (0x%08x)\n",
+ txq_id, iwl_mvm_get_tx_fail_reason(status), status);
+
+ IWL_DEBUG_TX_REPLY(mvm,
+ "\t\t\t\tinitial_rate 0x%x retries %d, idx=%d ssn=%d next_reclaimed=0x%x seq_ctl=0x%x\n",
+ le32_to_cpu(tx_resp->initial_rate),
tx_resp->failure_frame, SEQ_TO_INDEX(sequence),
ssn, next_reclaimed, seq_ctl);
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index e308ad93aa9e..0cc8d8c0d393 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -462,7 +462,7 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
.data = { lq, },
};
- if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
+ if (WARN_ON(lq->sta_id == IWL_MVM_STATION_COUNT))
return -EINVAL;
if (WARN_ON(init && (cmd.flags & CMD_ASYNC)))
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index 46ca91f77c9c..0016bb24b3d7 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -241,6 +241,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
{IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
{IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088F, 0x5260, iwl6035_2agn_cfg)},
/* 105 Series */
{IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 68466ca80770..c5e30294c5ac 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1061,7 +1061,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id));
/* If this queue is mapped to a certain station: it is an AGG queue */
- if (sta_id != IWL_INVALID_STATION) {
+ if (sta_id >= 0) {
u16 ra_tid = BUILD_RAxTID(sta_id, tid);
/* Map receiver-address / traffic-ID to this queue */
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index 7001856241e6..088de9d25c39 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -412,9 +412,9 @@ static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
lbtf_deb_enter(LBTF_DEB_MACOPS);
- if (conf->channel->center_freq != priv->cur_freq) {
- priv->cur_freq = conf->channel->center_freq;
- lbtf_set_channel(priv, conf->channel->hw_value);
+ if (conf->chandef.chan->center_freq != priv->cur_freq) {
+ priv->cur_freq = conf->chandef.chan->center_freq;
+ lbtf_set_channel(priv, conf->chandef.chan->hw_value);
}
lbtf_deb_leave(LBTF_DEB_MACOPS);
return 0;
@@ -537,7 +537,7 @@ static int lbtf_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = priv->noise;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 0064d38276bf..b878a32e7a98 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -25,6 +25,7 @@
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
#include <linux/etherdevice.h>
+#include <linux/platform_device.h>
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/ktime.h>
@@ -52,6 +53,10 @@ static bool paged_rx = false;
module_param(paged_rx, bool, 0644);
MODULE_PARM_DESC(paged_rx, "Use paged SKBs for RX instead of linear ones");
+static bool rctbl = false;
+module_param(rctbl, bool, 0444);
+MODULE_PARM_DESC(rctbl, "Handle rate control table");
+
/**
* enum hwsim_regtest - the type of regulatory tests we offer
*
@@ -717,9 +722,17 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
rx_status.flag |= RX_FLAG_MACTIME_START;
rx_status.freq = chan->center_freq;
rx_status.band = chan->band;
- rx_status.rate_idx = info->control.rates[0].idx;
- if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
- rx_status.flag |= RX_FLAG_HT;
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
+ rx_status.rate_idx =
+ ieee80211_rate_get_vht_mcs(&info->control.rates[0]);
+ rx_status.vht_nss =
+ ieee80211_rate_get_vht_nss(&info->control.rates[0]);
+ rx_status.flag |= RX_FLAG_VHT;
+ } else {
+ rx_status.rate_idx = info->control.rates[0].idx;
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
+ rx_status.flag |= RX_FLAG_HT;
+ }
if (info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
rx_status.flag |= RX_FLAG_40MHZ;
if (info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
@@ -886,8 +899,12 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
if (control->sta)
hwsim_check_sta_magic(control->sta);
- txi->rate_driver_data[0] = channel;
+ if (rctbl)
+ ieee80211_get_tx_rates(txi->control.vif, control->sta, skb,
+ txi->control.rates,
+ ARRAY_SIZE(txi->control.rates));
+ txi->rate_driver_data[0] = channel;
mac80211_hwsim_monitor_rx(hw, skb, channel);
/* wmediumd mode check */
@@ -989,6 +1006,13 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
{
u32 _pid = ACCESS_ONCE(wmediumd_portid);
+ if (rctbl) {
+ struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
+ ieee80211_get_tx_rates(txi->control.vif, NULL, skb,
+ txi->control.rates,
+ ARRAY_SIZE(txi->control.rates));
+ }
+
mac80211_hwsim_monitor_rx(hw, skb, chan);
if (_pid)
@@ -1019,6 +1043,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
if (skb == NULL)
return;
info = IEEE80211_SKB_CB(skb);
+ if (rctbl)
+ ieee80211_get_tx_rates(vif, NULL, skb,
+ info->control.rates,
+ ARRAY_SIZE(info->control.rates));
+
txrate = ieee80211_get_tx_rate(hw, info);
mgmt = (struct ieee80211_mgmt *) skb->data;
@@ -1062,11 +1091,13 @@ out:
return HRTIMER_NORESTART;
}
-static const char *hwsim_chantypes[] = {
- [NL80211_CHAN_NO_HT] = "noht",
- [NL80211_CHAN_HT20] = "ht20",
- [NL80211_CHAN_HT40MINUS] = "ht40-",
- [NL80211_CHAN_HT40PLUS] = "ht40+",
+static const char * const hwsim_chanwidths[] = {
+ [NL80211_CHAN_WIDTH_20_NOHT] = "noht",
+ [NL80211_CHAN_WIDTH_20] = "ht20",
+ [NL80211_CHAN_WIDTH_40] = "ht40",
+ [NL80211_CHAN_WIDTH_80] = "vht80",
+ [NL80211_CHAN_WIDTH_80P80] = "vht80p80",
+ [NL80211_CHAN_WIDTH_160] = "vht160",
};
static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
@@ -1080,18 +1111,28 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
[IEEE80211_SMPS_DYNAMIC] = "dynamic",
};
- wiphy_debug(hw->wiphy,
- "%s (freq=%d/%s idle=%d ps=%d smps=%s)\n",
- __func__,
- conf->channel ? conf->channel->center_freq : 0,
- hwsim_chantypes[conf->channel_type],
- !!(conf->flags & IEEE80211_CONF_IDLE),
- !!(conf->flags & IEEE80211_CONF_PS),
- smps_modes[conf->smps_mode]);
+ if (conf->chandef.chan)
+ wiphy_debug(hw->wiphy,
+ "%s (freq=%d(%d - %d)/%s idle=%d ps=%d smps=%s)\n",
+ __func__,
+ conf->chandef.chan->center_freq,
+ conf->chandef.center_freq1,
+ conf->chandef.center_freq2,
+ hwsim_chanwidths[conf->chandef.width],
+ !!(conf->flags & IEEE80211_CONF_IDLE),
+ !!(conf->flags & IEEE80211_CONF_PS),
+ smps_modes[conf->smps_mode]);
+ else
+ wiphy_debug(hw->wiphy,
+ "%s (freq=0 idle=%d ps=%d smps=%s)\n",
+ __func__,
+ !!(conf->flags & IEEE80211_CONF_IDLE),
+ !!(conf->flags & IEEE80211_CONF_PS),
+ smps_modes[conf->smps_mode]);
data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
- data->channel = conf->channel;
+ data->channel = conf->chandef.chan;
WARN_ON(data->channel && channels > 1);
@@ -1277,7 +1318,7 @@ static int mac80211_hwsim_get_survey(
return -ENOENT;
/* Current channel */
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
/*
* Magically conjured noise level --- this is only ok for simulated hardware.
@@ -1675,6 +1716,7 @@ static void mac80211_hwsim_free(void)
debugfs_remove(data->debugfs_ps);
debugfs_remove(data->debugfs);
ieee80211_unregister_hw(data->hw);
+ device_release_driver(data->dev);
device_unregister(data->dev);
ieee80211_free_hw(data->hw);
}
@@ -1683,7 +1725,9 @@ static void mac80211_hwsim_free(void)
static struct device_driver mac80211_hwsim_driver = {
- .name = "mac80211_hwsim"
+ .name = "mac80211_hwsim",
+ .bus = &platform_bus_type,
+ .owner = THIS_MODULE,
};
static const struct net_device_ops hwsim_netdev_ops = {
@@ -2175,9 +2219,15 @@ static int __init init_mac80211_hwsim(void)
spin_lock_init(&hwsim_radio_lock);
INIT_LIST_HEAD(&hwsim_radios);
+ err = driver_register(&mac80211_hwsim_driver);
+ if (err)
+ return err;
+
hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
- if (IS_ERR(hwsim_class))
- return PTR_ERR(hwsim_class);
+ if (IS_ERR(hwsim_class)) {
+ err = PTR_ERR(hwsim_class);
+ goto failed_unregister_driver;
+ }
memset(addr, 0, ETH_ALEN);
addr[0] = 0x02;
@@ -2199,12 +2249,20 @@ static int __init init_mac80211_hwsim(void)
"hwsim%d", i);
if (IS_ERR(data->dev)) {
printk(KERN_DEBUG
- "mac80211_hwsim: device_create "
- "failed (%ld)\n", PTR_ERR(data->dev));
+ "mac80211_hwsim: device_create failed (%ld)\n",
+ PTR_ERR(data->dev));
err = -ENOMEM;
goto failed_drvdata;
}
data->dev->driver = &mac80211_hwsim_driver;
+ err = device_bind_driver(data->dev);
+ if (err != 0) {
+ printk(KERN_DEBUG
+ "mac80211_hwsim: device_bind_driver failed (%d)\n",
+ err);
+ goto failed_hw;
+ }
+
skb_queue_head_init(&data->pending);
SET_IEEE80211_DEV(hw, data->dev);
@@ -2247,6 +2305,8 @@ static int __init init_mac80211_hwsim(void)
IEEE80211_HW_AMPDU_AGGREGATION |
IEEE80211_HW_WANT_MONITOR_VIF |
IEEE80211_HW_QUEUE_CONTROL;
+ if (rctbl)
+ hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE;
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
@@ -2298,9 +2358,6 @@ static int __init init_mac80211_hwsim(void)
hw->wiphy->bands[band] = sband;
- if (channels == 1)
- continue;
-
sband->vht_cap.vht_supported = true;
sband->vht_cap.cap =
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
@@ -2506,6 +2563,8 @@ failed_drvdata:
ieee80211_free_hw(hw);
failed:
mac80211_hwsim_free();
+failed_unregister_driver:
+ driver_unregister(&mac80211_hwsim_driver);
return err;
}
module_init(init_mac80211_hwsim);
@@ -2518,5 +2577,6 @@ static void __exit exit_mac80211_hwsim(void)
mac80211_hwsim_free();
unregister_netdev(hwsim_mon);
+ driver_unregister(&mac80211_hwsim_driver);
}
module_exit(exit_mac80211_hwsim);
diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c
index 966a78f8e21a..5e0eec4d71c7 100644
--- a/drivers/net/wireless/mwifiex/11ac.c
+++ b/drivers/net/wireless/mwifiex/11ac.c
@@ -200,7 +200,7 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
/* VHT Operation IE */
if (bss_desc->bcn_vht_oper) {
- if (priv->bss_mode == HostCmd_BSS_MODE_IBSS) {
+ if (priv->bss_mode == NL80211_IFTYPE_STATION) {
vht_op = (struct mwifiex_ie_types_vht_oper *)*buffer;
memset(vht_op, 0, sizeof(*vht_op));
vht_op->header.type =
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index af8fe6352eed..a78e0651409c 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -296,19 +296,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
break;
}
if (ret != -EBUSY) {
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
- if (mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) {
- priv->wmm.packets_out[ptrindex]++;
- priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list;
- }
- /* Now bss_prio_cur pointer points to next node */
- adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur =
- list_first_entry(
- &adapter->bss_prio_tbl[priv->bss_priority]
- .bss_prio_cur->list,
- struct mwifiex_bss_prio_node, list);
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
- ra_list_flags);
+ mwifiex_rotate_priolists(priv, pra_list, ptrindex);
}
return 0;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 5e796f847088..ada809f576fe 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -447,7 +447,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
del_timer(&tbl->timer_context.timer);
mod_timer(&tbl->timer_context.timer,
- jiffies + (MIN_FLUSH_TIMER_MS * win_size * HZ) / 1000);
+ jiffies + msecs_to_jiffies(MIN_FLUSH_TIMER_MS * win_size));
/*
* If seq_num is less then starting win then ignore and drop the
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 47012947a447..a0cb0770d319 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1666,17 +1666,13 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_connect_params *sme)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
- int ret = 0;
-
- if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
- wiphy_err(wiphy, "received infra assoc request "
- "when station is in ibss mode\n");
- goto done;
- }
+ int ret;
- if (priv->bss_mode == NL80211_IFTYPE_AP) {
- wiphy_err(wiphy, "skip association request for AP interface\n");
- goto done;
+ if (priv->bss_mode != NL80211_IFTYPE_STATION) {
+ wiphy_err(wiphy,
+ "%s: reject infra assoc request in non-STA mode\n",
+ dev->name);
+ return -EINVAL;
}
wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
@@ -1684,7 +1680,6 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
priv->bss_mode, sme->channel, sme, 0);
-done:
if (!ret) {
cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
NULL, 0, WLAN_STATUS_SUCCESS,
@@ -2136,10 +2131,9 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
/* At start-up, wpa_supplicant tries to change the interface
* to NL80211_IFTYPE_STATION if it is not managed mode.
- * So, we initialize it to STA mode.
*/
- wdev->iftype = NL80211_IFTYPE_STATION;
- priv->bss_mode = NL80211_IFTYPE_STATION;
+ wdev->iftype = NL80211_IFTYPE_P2P_CLIENT;
+ priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT;
/* Setting bss_type to P2P tells firmware that this interface
* is receiving P2P peers found during find phase and doing
@@ -2153,6 +2147,9 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->bss_started = 0;
priv->bss_num = 0;
+ if (mwifiex_cfg80211_init_p2p_client(priv))
+ return ERR_PTR(-EFAULT);
+
break;
default:
wiphy_err(wiphy, "type not supported\n");
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index da469c336aa1..74db0d24a579 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -250,7 +250,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
/* Setup the timer after transmit command */
mod_timer(&adapter->cmd_timer,
- jiffies + (MWIFIEX_TIMER_10S * HZ) / 1000);
+ jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
return 0;
}
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 42d7f0adf9bd..9f44fda19db9 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -44,8 +44,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
bss_prio->priv = priv;
INIT_LIST_HEAD(&bss_prio->list);
- if (!tbl[priv->bss_priority].bss_prio_cur)
- tbl[priv->bss_priority].bss_prio_cur = bss_prio;
spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head);
@@ -525,7 +523,6 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
for (i = 0; i < adapter->priv_num; ++i) {
INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head);
- adapter->bss_prio_tbl[i].bss_prio_cur = NULL;
spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock);
}
@@ -625,42 +622,36 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv)
{
int i;
struct mwifiex_adapter *adapter = priv->adapter;
- struct mwifiex_bss_prio_node *bssprio_node, *tmp_node, **cur;
+ struct mwifiex_bss_prio_node *bssprio_node, *tmp_node;
struct list_head *head;
spinlock_t *lock; /* bss priority lock */
unsigned long flags;
for (i = 0; i < adapter->priv_num; ++i) {
head = &adapter->bss_prio_tbl[i].bss_prio_head;
- cur = &adapter->bss_prio_tbl[i].bss_prio_cur;
lock = &adapter->bss_prio_tbl[i].bss_prio_lock;
dev_dbg(adapter->dev, "info: delete BSS priority table,"
" bss_type = %d, bss_num = %d, i = %d,"
- " head = %p, cur = %p\n",
- priv->bss_type, priv->bss_num, i, head, *cur);
- if (*cur) {
+ " head = %p\n",
+ priv->bss_type, priv->bss_num, i, head);
+
+ {
spin_lock_irqsave(lock, flags);
if (list_empty(head)) {
spin_unlock_irqrestore(lock, flags);
continue;
}
- bssprio_node = list_first_entry(head,
- struct mwifiex_bss_prio_node, list);
- spin_unlock_irqrestore(lock, flags);
-
list_for_each_entry_safe(bssprio_node, tmp_node, head,
list) {
if (bssprio_node->priv == priv) {
dev_dbg(adapter->dev, "info: Delete "
"node %p, next = %p\n",
bssprio_node, tmp_node);
- spin_lock_irqsave(lock, flags);
list_del(&bssprio_node->list);
- spin_unlock_irqrestore(lock, flags);
kfree(bssprio_node);
}
}
- *cur = (struct mwifiex_bss_prio_node *)head;
+ spin_unlock_irqrestore(lock, flags);
}
}
}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index b7484efc9443..4ef67fca06d3 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -213,7 +213,6 @@ struct mwifiex_ra_list_tbl {
struct mwifiex_tid_tbl {
struct list_head ra_list;
- struct mwifiex_ra_list_tbl *ra_list_curr;
};
#define WMM_HIGHEST_PRIORITY 7
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 856959b64bc7..80f282c0bd4d 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -572,7 +572,7 @@ static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
if (card->rx_buf_list[i]) {
skb = card->rx_buf_list[i];
pci_unmap_single(card->dev, desc2->paddr,
- skb->len, PCI_DMA_TODEVICE);
+ skb->len, PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(skb);
}
memset(desc2, 0, sizeof(*desc2));
@@ -581,7 +581,7 @@ static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
if (card->rx_buf_list[i]) {
skb = card->rx_buf_list[i];
pci_unmap_single(card->dev, desc->paddr,
- skb->len, PCI_DMA_TODEVICE);
+ skb->len, PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(skb);
}
memset(desc, 0, sizeof(*desc));
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index e7f6deaf715e..9cf5d8f07df8 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1500,43 +1500,22 @@ static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
if (ret)
goto done;
- /* Update current bss descriptor parameters */
spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
- priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL;
- priv->curr_bss_params.bss_descriptor.wpa_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL;
- priv->curr_bss_params.bss_descriptor.rsn_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL;
- priv->curr_bss_params.bss_descriptor.wapi_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL;
- priv->curr_bss_params.bss_descriptor.ht_cap_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_ht_oper = NULL;
- priv->curr_bss_params.bss_descriptor.ht_info_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 = NULL;
- priv->curr_bss_params.bss_descriptor.bss_co_2040_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL;
- priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
- priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
- priv->curr_bss_params.bss_descriptor.beacon_buf_size = 0;
- priv->curr_bss_params.bss_descriptor.bcn_vht_cap = NULL;
- priv->curr_bss_params.bss_descriptor.vht_cap_offset = 0;
- priv->curr_bss_params.bss_descriptor.bcn_vht_oper = NULL;
- priv->curr_bss_params.bss_descriptor.vht_info_offset = 0;
- priv->curr_bss_params.bss_descriptor.oper_mode = NULL;
- priv->curr_bss_params.bss_descriptor.oper_mode_offset = 0;
-
- /* Disable 11ac by default. Enable it only where there
- * exist VHT_CAP IE in AP beacon
- */
- priv->curr_bss_params.bss_descriptor.disable_11ac = true;
-
/* Make a copy of current BSSID descriptor */
memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
sizeof(priv->curr_bss_params.bss_descriptor));
+
+ /* The contents of beacon_ie will be copied to its own buffer
+ * in mwifiex_save_curr_bcn()
+ */
mwifiex_save_curr_bcn(priv);
spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
done:
+ /* beacon_ie buffer was allocated in function
+ * mwifiex_fill_new_bss_desc(). Free it now.
+ */
+ kfree(bss_desc->beacon_buf);
kfree(bss_desc);
return 0;
}
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index e6c9b2ae22ed..311d0b26b81c 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -140,12 +140,13 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
/*
* This function fills bss descriptor structure using provided
* information.
+ * beacon_ie buffer is allocated in this function. It is caller's
+ * responsibility to free the memory.
*/
int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
struct cfg80211_bss *bss,
struct mwifiex_bssdescriptor *bss_desc)
{
- int ret;
u8 *beacon_ie;
size_t beacon_ie_len;
struct mwifiex_bss_priv *bss_priv = (void *)bss->priv;
@@ -165,6 +166,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN);
bss_desc->rssi = bss->signal;
+ /* The caller of this function will free beacon_ie */
bss_desc->beacon_buf = beacon_ie;
bss_desc->beacon_buf_size = beacon_ie_len;
bss_desc->beacon_period = bss->beacon_interval;
@@ -182,10 +184,12 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
else
bss_desc->bss_mode = NL80211_IFTYPE_STATION;
- ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc);
+ /* Disable 11ac by default. Enable it only where there
+ * exist VHT_CAP IE in AP beacon
+ */
+ bss_desc->disable_11ac = true;
- kfree(beacon_ie);
- return ret;
+ return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc);
}
static int mwifiex_process_country_ie(struct mwifiex_private *priv,
@@ -349,6 +353,11 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
}
done:
+ /* beacon_ie buffer was allocated in function
+ * mwifiex_fill_new_bss_desc(). Free it now.
+ */
+ if (bss_desc)
+ kfree(bss_desc->beacon_buf);
kfree(bss_desc);
return ret;
}
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 2cc81ba590e3..4be3d33ceae8 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -191,9 +191,6 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
}
list_add_tail(&ra_list->list,
&priv->wmm.tid_tbl_ptr[i].ra_list);
-
- if (!priv->wmm.tid_tbl_ptr[i].ra_list_curr)
- priv->wmm.tid_tbl_ptr[i].ra_list_curr = ra_list;
}
}
@@ -424,7 +421,6 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
priv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i];
priv->aggr_prio_tbl[i].ampdu_ap = tos_to_tid_inv[i];
priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i];
- priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL;
}
priv->aggr_prio_tbl[6].amsdu
@@ -530,8 +526,6 @@ static void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv)
}
INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list);
-
- priv->wmm.tid_tbl_ptr[i].ra_list_curr = NULL;
}
}
@@ -883,38 +877,26 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
struct mwifiex_private **priv, int *tid)
{
struct mwifiex_private *priv_tmp;
- struct mwifiex_ra_list_tbl *ptr, *head;
- struct mwifiex_bss_prio_node *bssprio_node, *bssprio_head;
+ struct mwifiex_ra_list_tbl *ptr;
struct mwifiex_tid_tbl *tid_ptr;
atomic_t *hqp;
unsigned long flags_bss, flags_ra;
int i, j;
+ /* check the BSS with highest priority first */
for (j = adapter->priv_num - 1; j >= 0; --j) {
spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock,
flags_bss);
- if (list_empty(&adapter->bss_prio_tbl[j].bss_prio_head))
- goto skip_prio_tbl;
-
- if (adapter->bss_prio_tbl[j].bss_prio_cur ==
- (struct mwifiex_bss_prio_node *)
- &adapter->bss_prio_tbl[j].bss_prio_head) {
- adapter->bss_prio_tbl[j].bss_prio_cur =
- list_first_entry(&adapter->bss_prio_tbl[j]
- .bss_prio_head,
- struct mwifiex_bss_prio_node,
- list);
- }
-
- bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur;
- bssprio_head = bssprio_node;
+ /* iterate over BSS with the equal priority */
+ list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur,
+ &adapter->bss_prio_tbl[j].bss_prio_head,
+ list) {
- do {
- priv_tmp = bssprio_node->priv;
+ priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv;
if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0)
- goto skip_bss;
+ continue;
/* iterate over the WMM queues of the BSS */
hqp = &priv_tmp->wmm.highest_queued_prio;
@@ -926,73 +908,21 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
tid_ptr = &(priv_tmp)->wmm.
tid_tbl_ptr[tos_to_tid[i]];
- /* For non-STA ra_list_curr may be NULL */
- if (!tid_ptr->ra_list_curr)
- goto skip_wmm_queue;
-
- if (list_empty(&tid_ptr->ra_list))
- goto skip_wmm_queue;
-
- /*
- * Always choose the next ra we transmitted
- * last time, this way we pick the ra's in
- * round robin fashion.
- */
- ptr = list_first_entry(
- &tid_ptr->ra_list_curr->list,
- struct mwifiex_ra_list_tbl,
- list);
-
- head = ptr;
- if (ptr == (struct mwifiex_ra_list_tbl *)
- &tid_ptr->ra_list) {
- /* Get next ra */
- ptr = list_first_entry(&ptr->list,
- struct mwifiex_ra_list_tbl, list);
- head = ptr;
- }
+ /* iterate over receiver addresses */
+ list_for_each_entry(ptr, &tid_ptr->ra_list,
+ list) {
- do {
if (!skb_queue_empty(&ptr->skb_head))
/* holds both locks */
goto found;
+ }
- /* Get next ra */
- ptr = list_first_entry(&ptr->list,
- struct mwifiex_ra_list_tbl,
- list);
- if (ptr ==
- (struct mwifiex_ra_list_tbl *)
- &tid_ptr->ra_list)
- ptr = list_first_entry(
- &ptr->list,
- struct mwifiex_ra_list_tbl,
- list);
- } while (ptr != head);
-
-skip_wmm_queue:
spin_unlock_irqrestore(&priv_tmp->wmm.
ra_list_spinlock,
flags_ra);
}
+ }
-skip_bss:
- /* Get next bss priority node */
- bssprio_node = list_first_entry(&bssprio_node->list,
- struct mwifiex_bss_prio_node,
- list);
-
- if (bssprio_node ==
- (struct mwifiex_bss_prio_node *)
- &adapter->bss_prio_tbl[j].bss_prio_head)
- /* Get next bss priority node */
- bssprio_node = list_first_entry(
- &bssprio_node->list,
- struct mwifiex_bss_prio_node,
- list);
- } while (bssprio_node != bssprio_head);
-
-skip_prio_tbl:
spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock,
flags_bss);
}
@@ -1013,6 +943,42 @@ found:
return ptr;
}
+/* This functions rotates ra and bss lists so packets are picked round robin.
+ *
+ * After a packet is successfully transmitted, rotate the ra list, so the ra
+ * next to the one transmitted, will come first in the list. This way we pick
+ * the ra' in a round robin fashion. Same applies to bss nodes of equal
+ * priority.
+ *
+ * Function also increments wmm.packets_out counter.
+ */
+void mwifiex_rotate_priolists(struct mwifiex_private *priv,
+ struct mwifiex_ra_list_tbl *ra,
+ int tid)
+{
+ struct mwifiex_adapter *adapter = priv->adapter;
+ struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl;
+ struct mwifiex_tid_tbl *tid_ptr = &priv->wmm.tid_tbl_ptr[tid];
+ unsigned long flags;
+
+ spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags);
+ /*
+ * dirty trick: we remove 'head' temporarily and reinsert it after
+ * curr bss node. imagine list to stay fixed while head is moved
+ */
+ list_move(&tbl[priv->bss_priority].bss_prio_head,
+ &tbl[priv->bss_priority].bss_prio_cur->list);
+ spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags);
+
+ spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+ if (mwifiex_is_ralist_valid(priv, ra, tid)) {
+ priv->wmm.packets_out[tid]++;
+ /* same as above */
+ list_move(&tid_ptr->ra_list, &ra->list);
+ }
+ spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+}
+
/*
* This function checks if 11n aggregation is possible.
*/
@@ -1099,20 +1065,8 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
ra_list_flags);
} else {
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
- if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
- priv->wmm.packets_out[ptr_index]++;
- priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr;
- }
- adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur =
- list_first_entry(
- &adapter->bss_prio_tbl[priv->bss_priority]
- .bss_prio_cur->list,
- struct mwifiex_bss_prio_node,
- list);
+ mwifiex_rotate_priolists(priv, ptr, ptr_index);
atomic_dec(&priv->wmm.tx_pkts_queued);
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
- ra_list_flags);
}
}
@@ -1216,20 +1170,8 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
break;
}
if (ret != -EBUSY) {
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags);
- if (mwifiex_is_ralist_valid(priv, ptr, ptr_index)) {
- priv->wmm.packets_out[ptr_index]++;
- priv->wmm.tid_tbl_ptr[ptr_index].ra_list_curr = ptr;
- }
- adapter->bss_prio_tbl[priv->bss_priority].bss_prio_cur =
- list_first_entry(
- &adapter->bss_prio_tbl[priv->bss_priority]
- .bss_prio_cur->list,
- struct mwifiex_bss_prio_node,
- list);
+ mwifiex_rotate_priolists(priv, ptr, ptr_index);
atomic_dec(&priv->wmm.tx_pkts_queued);
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
- ra_list_flags);
}
}
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h
index b92f39d8963b..644d6e0c51cc 100644
--- a/drivers/net/wireless/mwifiex/wmm.h
+++ b/drivers/net/wireless/mwifiex/wmm.h
@@ -85,6 +85,9 @@ mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead)
void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
struct sk_buff *skb);
void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra);
+void mwifiex_rotate_priolists(struct mwifiex_private *priv,
+ struct mwifiex_ra_list_tbl *ra,
+ int tid);
int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter);
void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter);
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 956c1084ebf1..6820fce4016b 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -193,10 +193,10 @@ struct mwl8k_priv {
struct rxd_ops *rxd_ops;
struct ieee80211_supported_band band_24;
struct ieee80211_channel channels_24[14];
- struct ieee80211_rate rates_24[14];
+ struct ieee80211_rate rates_24[13];
struct ieee80211_supported_band band_50;
struct ieee80211_channel channels_50[4];
- struct ieee80211_rate rates_50[9];
+ struct ieee80211_rate rates_50[8];
u32 ap_macids_supported;
u32 sta_macids_supported;
@@ -366,7 +366,6 @@ static const struct ieee80211_rate mwl8k_rates_24[] = {
{ .bitrate = 360, .hw_value = 72, },
{ .bitrate = 480, .hw_value = 96, },
{ .bitrate = 540, .hw_value = 108, },
- { .bitrate = 720, .hw_value = 144, },
};
static const struct ieee80211_channel mwl8k_channels_50[] = {
@@ -385,7 +384,6 @@ static const struct ieee80211_rate mwl8k_rates_50[] = {
{ .bitrate = 360, .hw_value = 72, },
{ .bitrate = 480, .hw_value = 96, },
{ .bitrate = 540, .hw_value = 108, },
- { .bitrate = 720, .hw_value = 144, },
};
/* Set or get info from Firmware */
@@ -2852,7 +2850,9 @@ static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
struct ieee80211_conf *conf,
unsigned short pwr)
{
- struct ieee80211_channel *channel = conf->channel;
+ struct ieee80211_channel *channel = conf->chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&conf->chandef);
struct mwl8k_cmd_tx_power *cmd;
int rc;
int i;
@@ -2872,14 +2872,14 @@ static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
cmd->channel = cpu_to_le16(channel->hw_value);
- if (conf->channel_type == NL80211_CHAN_NO_HT ||
- conf->channel_type == NL80211_CHAN_HT20) {
+ if (channel_type == NL80211_CHAN_NO_HT ||
+ channel_type == NL80211_CHAN_HT20) {
cmd->bw = cpu_to_le16(0x2);
} else {
cmd->bw = cpu_to_le16(0x4);
- if (conf->channel_type == NL80211_CHAN_HT40MINUS)
+ if (channel_type == NL80211_CHAN_HT40MINUS)
cmd->sub_ch = cpu_to_le16(0x3);
- else if (conf->channel_type == NL80211_CHAN_HT40PLUS)
+ else if (channel_type == NL80211_CHAN_HT40PLUS)
cmd->sub_ch = cpu_to_le16(0x1);
}
@@ -3023,7 +3023,9 @@ struct mwl8k_cmd_set_rf_channel {
static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw,
struct ieee80211_conf *conf)
{
- struct ieee80211_channel *channel = conf->channel;
+ struct ieee80211_channel *channel = conf->chandef.chan;
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&conf->chandef);
struct mwl8k_cmd_set_rf_channel *cmd;
int rc;
@@ -3041,12 +3043,12 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw,
else if (channel->band == IEEE80211_BAND_5GHZ)
cmd->channel_flags |= cpu_to_le32(0x00000004);
- if (conf->channel_type == NL80211_CHAN_NO_HT ||
- conf->channel_type == NL80211_CHAN_HT20)
+ if (channel_type == NL80211_CHAN_NO_HT ||
+ channel_type == NL80211_CHAN_HT20)
cmd->channel_flags |= cpu_to_le32(0x00000080);
- else if (conf->channel_type == NL80211_CHAN_HT40MINUS)
+ else if (channel_type == NL80211_CHAN_HT40MINUS)
cmd->channel_flags |= cpu_to_le32(0x000001900);
- else if (conf->channel_type == NL80211_CHAN_HT40PLUS)
+ else if (channel_type == NL80211_CHAN_HT40PLUS)
cmd->channel_flags |= cpu_to_le32(0x000000900);
rc = mwl8k_post_cmd(hw, &cmd->header);
@@ -3079,11 +3081,11 @@ static void legacy_rate_mask_to_array(u8 *rates, u32 mask)
int j;
/*
- * Clear nonstandard rates 4 and 13.
+ * Clear nonstandard rate 4.
*/
mask &= 0x1fef;
- for (i = 0, j = 0; i < 14; i++) {
+ for (i = 0, j = 0; i < 13; i++) {
if (mask & (1 << i))
rates[j++] = mwl8k_rates_24[i].hw_value;
}
@@ -3965,7 +3967,7 @@ static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw,
memcpy(cmd->mac_addr, sta->addr, ETH_ALEN);
cmd->stn_id = cpu_to_le16(sta->aid);
cmd->action = cpu_to_le16(MWL8K_STA_ACTION_ADD);
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
rates = sta->supp_rates[IEEE80211_BAND_2GHZ];
else
rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5;
@@ -4400,7 +4402,7 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
p->ht_caps = cpu_to_le16(sta->ht_cap.cap);
p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) |
((sta->ht_cap.ampdu_density & 7) << 2);
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
rates = sta->supp_rates[IEEE80211_BAND_2GHZ];
else
rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5;
@@ -4881,7 +4883,7 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
goto out;
}
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) {
ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ];
} else {
ap_legacy_rates =
@@ -4913,7 +4915,7 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (idx)
idx--;
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
rate = mwl8k_rates_24[idx].hw_value;
else
rate = mwl8k_rates_50[idx].hw_value;
@@ -4986,7 +4988,7 @@ mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (idx)
idx--;
- if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
rate = mwl8k_rates_24[idx].hw_value;
else
rate = mwl8k_rates_50[idx].hw_value;
@@ -5259,7 +5261,7 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = priv->noise;
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index 9ba85106eec0..b3879fbf5368 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -402,7 +402,7 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
struct p54_rssi_db_entry *rssi_data;
unsigned int i;
void *entry;
- __le16 freq = cpu_to_le16(priv->hw->conf.channel->center_freq);
+ __le16 freq = cpu_to_le16(priv->hw->conf.chandef.chan->center_freq);
skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) +
2 + sizeof(*iq_autocal) + sizeof(*body) +
@@ -532,7 +532,7 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
err:
wiphy_err(priv->hw->wiphy, "frequency change to channel %d failed.\n",
ieee80211_frequency_to_channel(
- priv->hw->conf.channel->center_freq));
+ priv->hw->conf.chandef.chan->center_freq));
dev_kfree_skb_any(skb);
return -EINVAL;
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index ee654a691f38..067e6f2fd050 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -340,7 +340,7 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed)
* TODO: Use the LM_SCAN_TRAP to determine the current
* operating channel.
*/
- priv->curchan = priv->hw->conf.channel;
+ priv->curchan = priv->hw->conf.chandef.chan;
p54_reset_stats(priv);
WARN_ON(p54_fetch_statistics(priv));
}
@@ -480,7 +480,7 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev,
p54_set_edcf(priv);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
- if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
+ if (dev->conf.chandef.chan->band == IEEE80211_BAND_5GHZ)
priv->basic_rate_mask = (info->basic_rates << 4);
else
priv->basic_rate_mask = info->basic_rates;
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 12f0a34477f2..f95de0d16216 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -354,13 +354,13 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
rx_status->signal = p54_rssi_to_dbm(priv, hdr->rssi);
if (hdr->rate & 0x10)
rx_status->flag |= RX_FLAG_SHORTPRE;
- if (priv->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
+ if (priv->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ)
rx_status->rate_idx = (rate < 4) ? 0 : rate - 4;
else
rx_status->rate_idx = rate;
rx_status->freq = freq;
- rx_status->band = priv->hw->conf.channel->band;
+ rx_status->band = priv->hw->conf.chandef.chan->band;
rx_status->antenna = hdr->antenna;
tsf32 = le32_to_cpu(hdr->tsf32);
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index dcfb54e0c516..f7143733d7e9 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -41,7 +41,7 @@
/*
* Register access.
* All access to the CSR registers will go through the methods
- * rt2x00pci_register_read and rt2x00pci_register_write.
+ * rt2x00mmio_register_read and rt2x00mmio_register_write.
* BBP and RF register require indirect register access,
* and use the CSR registers BBPCSR and RFCSR to achieve this.
* These indirect registers work with busy bits,
@@ -52,9 +52,9 @@
* and we will print an error.
*/
#define WAIT_FOR_BBP(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
#define WAIT_FOR_RF(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
@@ -74,7 +74,7 @@ static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
}
mutex_unlock(&rt2x00dev->csr_mutex);
@@ -101,7 +101,7 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
WAIT_FOR_BBP(rt2x00dev, &reg);
}
@@ -129,7 +129,7 @@ static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
- rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RFCSR, reg);
rt2x00_rf_write(rt2x00dev, word, value);
}
@@ -141,7 +141,7 @@ static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR21, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
@@ -163,15 +163,15 @@ static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
rt2x00_set_field32(&reg, CSR21_EEPROM_CHIP_SELECT,
!!eeprom->reg_chip_select);
- rt2x00pci_register_write(rt2x00dev, CSR21, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR21, reg);
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
static const struct rt2x00debug rt2400pci_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
- .read = rt2x00pci_register_read,
- .write = rt2x00pci_register_write,
+ .read = rt2x00mmio_register_read,
+ .write = rt2x00mmio_register_write,
.flags = RT2X00DEBUGFS_OFFSET,
.word_base = CSR_REG_BASE,
.word_size = sizeof(u32),
@@ -205,7 +205,7 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
return rt2x00_get_field32(reg, GPIOCSR_VAL0);
}
@@ -218,14 +218,14 @@ static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
unsigned int enabled = brightness != LED_OFF;
u32 reg;
- rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
+ rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
else if (led->type == LED_TYPE_ACTIVITY)
rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
- rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
}
static int rt2400pci_blink_set(struct led_classdev *led_cdev,
@@ -236,10 +236,10 @@ static int rt2400pci_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
- rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
+ rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
- rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
return 0;
}
@@ -269,7 +269,7 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
* Note that the version error will always be dropped
* since there is no filter for it at this time.
*/
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
@@ -282,7 +282,7 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
!(filter_flags & FIF_PROMISC_IN_BSS) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
}
static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
@@ -298,25 +298,26 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
* Enable beacon config
*/
bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
- rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
- rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
/*
* Enable synchronisation.
*/
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
}
if (flags & CONFIG_UPDATE_MAC)
- rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
- conf->mac, sizeof(conf->mac));
+ rt2x00mmio_register_multiwrite(rt2x00dev, CSR3,
+ conf->mac, sizeof(conf->mac));
if (flags & CONFIG_UPDATE_BSSID)
- rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
- conf->bssid, sizeof(conf->bssid));
+ rt2x00mmio_register_multiwrite(rt2x00dev, CSR5,
+ conf->bssid,
+ sizeof(conf->bssid));
}
static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
@@ -332,68 +333,68 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
preamble_mask = erp->short_preamble << 3;
- rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 10));
- rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 20));
- rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 55));
- rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 110));
- rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg);
}
if (changed & BSS_CHANGED_BASIC_RATES)
- rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
if (changed & BSS_CHANGED_ERP_SLOT) {
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
- rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
- rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
- rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
- rt2x00pci_register_write(rt2x00dev, CSR19, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
}
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
erp->beacon_int * 16);
rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
erp->beacon_int * 16);
- rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR12, reg);
}
}
@@ -497,7 +498,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
/*
* Clear false CRC during channel switch.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
}
static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
@@ -510,12 +511,12 @@ static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
libconf->conf->long_frame_max_tx_count);
rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
libconf->conf->short_frame_max_tx_count);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
}
static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
@@ -527,7 +528,7 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (state == STATE_SLEEP) {
- rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
(rt2x00dev->beacon_int - 20) * 16);
rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
@@ -535,14 +536,14 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
/* We must first disable autowake before it can be enabled */
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
} else {
- rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
}
rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
@@ -568,10 +569,10 @@ static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_CWMIN, cw_min);
rt2x00_set_field32(&reg, CSR11_CWMAX, cw_max);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
}
/*
@@ -586,7 +587,7 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
/*
@@ -641,16 +642,16 @@ static void rt2400pci_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
break;
default:
break;
@@ -664,19 +665,19 @@ static void rt2400pci_kick_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_AC_VI:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_ATIM:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
default:
break;
@@ -692,21 +693,21 @@ static void rt2400pci_stop_queue(struct data_queue *queue)
case QID_AC_VO:
case QID_AC_VI:
case QID_ATIM:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
/*
* Wait for possibly running tbtt tasklets.
@@ -723,7 +724,7 @@ static void rt2400pci_stop_queue(struct data_queue *queue)
*/
static bool rt2400pci_get_entry_state(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word;
if (entry->queue->qid == QID_RX) {
@@ -740,7 +741,7 @@ static bool rt2400pci_get_entry_state(struct queue_entry *entry)
static void rt2400pci_clear_entry(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
@@ -766,53 +767,53 @@ static void rt2400pci_clear_entry(struct queue_entry *entry)
static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
{
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
u32 reg;
/*
* Initialize registers.
*/
- rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
- rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
entry_priv = rt2x00dev->atim->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
entry_priv = rt2x00dev->bcn->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
- rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
- rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
return 0;
}
@@ -821,23 +822,23 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002);
- rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002);
- rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00023f20);
- rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00023f20);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
- rt2x00pci_register_read(rt2x00dev, TIMECSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);
rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);
rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);
- rt2x00pci_register_write(rt2x00dev, TIMECSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
- rt2x00pci_register_read(rt2x00dev, CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
(rt2x00dev->rx->data_size / 128));
- rt2x00pci_register_write(rt2x00dev, CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
@@ -846,63 +847,63 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
- rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000);
+ rt2x00mmio_register_write(rt2x00dev, CNT3, 0x3f080000);
- rt2x00pci_register_read(rt2x00dev, ARCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR0, &reg);
rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA0, 133);
rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID0, 134);
rt2x00_set_field32(&reg, ARCSR0_AR_BBP_DATA1, 136);
rt2x00_set_field32(&reg, ARCSR0_AR_BBP_ID1, 135);
- rt2x00pci_register_write(rt2x00dev, ARCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR0, reg);
- rt2x00pci_register_read(rt2x00dev, RXCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID0, 3); /* Tx power.*/
rt2x00_set_field32(&reg, RXCSR3_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID1, 32); /* Signal */
rt2x00_set_field32(&reg, RXCSR3_BBP_ID1_VALID, 1);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID2, 36); /* Rssi */
rt2x00_set_field32(&reg, RXCSR3_BBP_ID2_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, RXCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg);
- rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
return -EBUSY;
- rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00217223);
- rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00217223);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
- rt2x00pci_register_read(rt2x00dev, MACCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
- rt2x00pci_register_write(rt2x00dev, MACCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
- rt2x00pci_register_read(rt2x00dev, RALINKCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA0, 17);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID0, 154);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA1, 0);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID1, 154);
- rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg);
- rt2x00pci_register_read(rt2x00dev, CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
- rt2x00pci_register_write(rt2x00dev, CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
- rt2x00pci_register_write(rt2x00dev, CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
/*
* We must clear the FCS and FIFO error count.
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
- rt2x00pci_register_read(rt2x00dev, CNT4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
return 0;
}
@@ -919,7 +920,7 @@ static int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -976,8 +977,8 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
- rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
}
/*
@@ -986,13 +987,13 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
@@ -1025,7 +1026,7 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Disable power
*/
- rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0);
}
static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -1039,12 +1040,12 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
put_to_sleep = (state != STATE_AWAKE);
- rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
- rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
/*
* Device is not guaranteed to be in the requested state yet.
@@ -1052,12 +1053,12 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg2);
+ rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
if (bbp_state == state && rf_state == state)
return 0;
- rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
msleep(10);
}
@@ -1092,8 +1093,8 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -1105,7 +1106,7 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -1182,12 +1183,12 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
if (rt2x00queue_map_txskb(entry)) {
- ERROR(rt2x00dev, "Fail to map beacon, aborting\n");
+ rt2x00_err(rt2x00dev, "Fail to map beacon, aborting\n");
goto out;
}
/*
@@ -1208,7 +1209,7 @@ out:
* Enable beaconing again.
*/
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
}
/*
@@ -1218,7 +1219,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word0;
u32 word2;
u32 word3;
@@ -1276,7 +1277,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
const enum data_queue_qid queue_idx)
{
struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
struct queue_entry *entry;
struct txdone_entry_desc txdesc;
u32 word;
@@ -1322,9 +1323,9 @@ static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, irq_field, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -1347,11 +1348,11 @@ static void rt2400pci_txstatus_tasklet(unsigned long data)
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -1368,7 +1369,7 @@ static void rt2400pci_tbtt_tasklet(unsigned long data)
static void rt2400pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- if (rt2x00pci_rxdone(rt2x00dev))
+ if (rt2x00mmio_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
@@ -1383,8 +1384,8 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
* Get the interrupt sources & saved to local variable.
* Write register value back to clear pending interrupts.
*/
- rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
- rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
if (!reg)
return IRQ_NONE;
@@ -1421,9 +1422,9 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
reg |= mask;
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock(&rt2x00dev->irqmask_lock);
@@ -1442,7 +1443,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
u16 word;
u8 *mac;
- rt2x00pci_register_read(rt2x00dev, CSR21, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
eeprom.data = rt2x00dev;
eeprom.register_read = rt2400pci_eepromregister_read;
@@ -1463,12 +1464,12 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
- ERROR(rt2x00dev, "Invalid EEPROM data detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid EEPROM data detected\n");
return -EINVAL;
}
@@ -1490,12 +1491,12 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00pci_register_read(rt2x00dev, CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
rt2x00_set_chip(rt2x00dev, RT2460, value,
rt2x00_get_field32(reg, CSR0_REVISION));
if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) {
- ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
return -ENODEV;
}
@@ -1635,9 +1636,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
- rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
/*
* Initialize hw specifications.
@@ -1697,9 +1698,9 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw,
u64 tsf;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR17, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
- rt2x00pci_register_read(rt2x00dev, CSR16, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
return tsf;
@@ -1710,7 +1711,7 @@ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
struct rt2x00_dev *rt2x00dev = hw->priv;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR15, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
}
@@ -1743,8 +1744,8 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.tbtt_tasklet = rt2400pci_tbtt_tasklet,
.rxdone_tasklet = rt2400pci_rxdone_tasklet,
.probe_hw = rt2400pci_probe_hw,
- .initialize = rt2x00pci_initialize,
- .uninitialize = rt2x00pci_uninitialize,
+ .initialize = rt2x00mmio_initialize,
+ .uninitialize = rt2x00mmio_uninitialize,
.get_entry_state = rt2400pci_get_entry_state,
.clear_entry = rt2400pci_clear_entry,
.set_device_state = rt2400pci_set_device_state,
@@ -1755,7 +1756,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,
+ .flush_queue = rt2x00mmio_flush_queue,
.write_tx_desc = rt2400pci_write_tx_desc,
.write_beacon = rt2400pci_write_beacon,
.fill_rxdone = rt2400pci_fill_rxdone,
@@ -1770,28 +1771,28 @@ static const struct data_queue_desc rt2400pci_queue_rx = {
.entry_num = 24,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2400pci_queue_tx = {
.entry_num = 24,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2400pci_queue_bcn = {
.entry_num = 1,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2400pci_queue_atim = {
.entry_num = 8,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct rt2x00_ops rt2400pci_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index e1d2dc9ed28a..77e45b223d15 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -41,7 +41,7 @@
/*
* Register access.
* All access to the CSR registers will go through the methods
- * rt2x00pci_register_read and rt2x00pci_register_write.
+ * rt2x00mmio_register_read and rt2x00mmio_register_write.
* BBP and RF register require indirect register access,
* and use the CSR registers BBPCSR and RFCSR to achieve this.
* These indirect registers work with busy bits,
@@ -52,9 +52,9 @@
* and we will print an error.
*/
#define WAIT_FOR_BBP(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
#define WAIT_FOR_RF(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
@@ -74,7 +74,7 @@ static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
}
mutex_unlock(&rt2x00dev->csr_mutex);
@@ -101,7 +101,7 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);
WAIT_FOR_BBP(rt2x00dev, &reg);
}
@@ -129,7 +129,7 @@ static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
- rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RFCSR, reg);
rt2x00_rf_write(rt2x00dev, word, value);
}
@@ -141,7 +141,7 @@ static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR21, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
@@ -163,15 +163,15 @@ static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
rt2x00_set_field32(&reg, CSR21_EEPROM_CHIP_SELECT,
!!eeprom->reg_chip_select);
- rt2x00pci_register_write(rt2x00dev, CSR21, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR21, reg);
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
static const struct rt2x00debug rt2500pci_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
- .read = rt2x00pci_register_read,
- .write = rt2x00pci_register_write,
+ .read = rt2x00mmio_register_read,
+ .write = rt2x00mmio_register_write,
.flags = RT2X00DEBUGFS_OFFSET,
.word_base = CSR_REG_BASE,
.word_size = sizeof(u32),
@@ -205,7 +205,7 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
return rt2x00_get_field32(reg, GPIOCSR_VAL0);
}
@@ -218,14 +218,14 @@ static void rt2500pci_brightness_set(struct led_classdev *led_cdev,
unsigned int enabled = brightness != LED_OFF;
u32 reg;
- rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
+ rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
else if (led->type == LED_TYPE_ACTIVITY)
rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
- rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
}
static int rt2500pci_blink_set(struct led_classdev *led_cdev,
@@ -236,10 +236,10 @@ static int rt2500pci_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
- rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
+ rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, &reg);
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
- rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
+ rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);
return 0;
}
@@ -270,7 +270,7 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
* and broadcast frames will always be accepted since
* there is no filter for it at this time.
*/
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
@@ -286,7 +286,7 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
!(filter_flags & FIF_ALLMULTI));
rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, 0);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
}
static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
@@ -303,25 +303,25 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
* Enable beacon config
*/
bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
- rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCNCSR1, &reg);
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN, queue->cw_min);
- rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);
/*
* Enable synchronisation.
*/
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
}
if (flags & CONFIG_UPDATE_MAC)
- rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
+ rt2x00mmio_register_multiwrite(rt2x00dev, CSR3,
conf->mac, sizeof(conf->mac));
if (flags & CONFIG_UPDATE_BSSID)
- rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
+ rt2x00mmio_register_multiwrite(rt2x00dev, CSR5,
conf->bssid, sizeof(conf->bssid));
}
@@ -338,68 +338,68 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
preamble_mask = erp->short_preamble << 3;
- rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR1, &reg);
rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162);
rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2);
rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR2, &reg);
rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 10));
- rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR3, &reg);
rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 20));
- rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR4, &reg);
rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 55));
- rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg);
- rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARCSR5, &reg);
rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
rt2x00_set_field32(&reg, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 110));
- rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg);
}
if (changed & BSS_CHANGED_BASIC_RATES)
- rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+ rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
if (changed & BSS_CHANGED_ERP_SLOT) {
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
- rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR18, &reg);
rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
- rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR18, reg);
- rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR19, &reg);
rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
- rt2x00pci_register_write(rt2x00dev, CSR19, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR19, reg);
}
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR12, &reg);
rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
erp->beacon_int * 16);
rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
erp->beacon_int * 16);
- rt2x00pci_register_write(rt2x00dev, CSR12, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR12, reg);
}
}
@@ -418,7 +418,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
ant->tx == ANTENNA_SW_DIVERSITY);
- rt2x00pci_register_read(rt2x00dev, BBPCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BBPCSR1, &reg);
rt2500pci_bbp_read(rt2x00dev, 14, &r14);
rt2500pci_bbp_read(rt2x00dev, 2, &r2);
@@ -470,7 +470,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 0);
}
- rt2x00pci_register_write(rt2x00dev, BBPCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR1, reg);
rt2500pci_bbp_write(rt2x00dev, 14, r14);
rt2500pci_bbp_write(rt2x00dev, 2, r2);
}
@@ -541,7 +541,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
/*
* Clear false CRC during channel switch.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);
}
static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev,
@@ -559,12 +559,12 @@ static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
libconf->conf->long_frame_max_tx_count);
rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
libconf->conf->short_frame_max_tx_count);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
}
static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
@@ -576,7 +576,7 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (state == STATE_SLEEP) {
- rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
(rt2x00dev->beacon_int - 20) * 16);
rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
@@ -584,14 +584,14 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
/* We must first disable autowake before it can be enabled */
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
} else {
- rt2x00pci_register_read(rt2x00dev, CSR20, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR20, &reg);
rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
- rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR20, reg);
}
rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
@@ -625,13 +625,13 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
- rt2x00pci_register_read(rt2x00dev, CNT3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT3, &reg);
qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
}
@@ -731,16 +731,16 @@ static void rt2500pci_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
break;
default:
break;
@@ -754,19 +754,19 @@ static void rt2500pci_kick_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_AC_VI:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_ATIM:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
default:
break;
@@ -782,21 +782,21 @@ static void rt2500pci_stop_queue(struct data_queue *queue)
case QID_AC_VO:
case QID_AC_VI:
case QID_ATIM:
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
/*
* Wait for possibly running tbtt tasklets.
@@ -813,7 +813,7 @@ static void rt2500pci_stop_queue(struct data_queue *queue)
*/
static bool rt2500pci_get_entry_state(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word;
if (entry->queue->qid == QID_RX) {
@@ -830,7 +830,7 @@ static bool rt2500pci_get_entry_state(struct queue_entry *entry)
static void rt2500pci_clear_entry(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
@@ -852,53 +852,53 @@ static void rt2500pci_clear_entry(struct queue_entry *entry)
static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
{
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
u32 reg;
/*
* Initialize registers.
*/
- rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR2, &reg);
rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
- rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR3, &reg);
rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR5, &reg);
rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg);
entry_priv = rt2x00dev->atim->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR4, &reg);
rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg);
entry_priv = rt2x00dev->bcn->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR6, &reg);
rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg);
- rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR1, &reg);
rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
- rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR2, &reg);
rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);
return 0;
}
@@ -907,30 +907,30 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002);
- rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002);
- rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00020002);
- rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00020002);
+ rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002);
- rt2x00pci_register_read(rt2x00dev, TIMECSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TIMECSR, &reg);
rt2x00_set_field32(&reg, TIMECSR_US_COUNT, 33);
rt2x00_set_field32(&reg, TIMECSR_US_64_COUNT, 63);
rt2x00_set_field32(&reg, TIMECSR_BEACON_EXPECT, 0);
- rt2x00pci_register_write(rt2x00dev, TIMECSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg);
- rt2x00pci_register_read(rt2x00dev, CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR9, &reg);
rt2x00_set_field32(&reg, CSR9_MAX_FRAME_UNIT,
rt2x00dev->rx->data_size / 128);
- rt2x00pci_register_write(rt2x00dev, CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR9, reg);
/*
* Always use CWmin and CWmax set in descriptor.
*/
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR11, &reg);
rt2x00_set_field32(&reg, CSR11_CW_SELECT, 0);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR11, reg);
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
@@ -939,11 +939,11 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
- rt2x00pci_register_write(rt2x00dev, CNT3, 0);
+ rt2x00mmio_register_write(rt2x00dev, CNT3, 0);
- rt2x00pci_register_read(rt2x00dev, TXCSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXCSR8, &reg);
rt2x00_set_field32(&reg, TXCSR8_BBP_ID0, 10);
rt2x00_set_field32(&reg, TXCSR8_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, TXCSR8_BBP_ID1, 11);
@@ -952,30 +952,30 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXCSR8_BBP_ID2_VALID, 1);
rt2x00_set_field32(&reg, TXCSR8_BBP_ID3, 12);
rt2x00_set_field32(&reg, TXCSR8_BBP_ID3_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXCSR8, reg);
- rt2x00pci_register_read(rt2x00dev, ARTCSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARTCSR0, &reg);
rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_1MBS, 112);
rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_2MBS, 56);
rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_5_5MBS, 20);
rt2x00_set_field32(&reg, ARTCSR0_ACK_CTS_11MBS, 10);
- rt2x00pci_register_write(rt2x00dev, ARTCSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARTCSR0, reg);
- rt2x00pci_register_read(rt2x00dev, ARTCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARTCSR1, &reg);
rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_6MBS, 45);
rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_9MBS, 37);
rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_12MBS, 33);
rt2x00_set_field32(&reg, ARTCSR1_ACK_CTS_18MBS, 29);
- rt2x00pci_register_write(rt2x00dev, ARTCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARTCSR1, reg);
- rt2x00pci_register_read(rt2x00dev, ARTCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, ARTCSR2, &reg);
rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_24MBS, 29);
rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_36MBS, 25);
rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_48MBS, 25);
rt2x00_set_field32(&reg, ARTCSR2_ACK_CTS_54MBS, 25);
- rt2x00pci_register_write(rt2x00dev, ARTCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, ARTCSR2, reg);
- rt2x00pci_register_read(rt2x00dev, RXCSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RXCSR3, &reg);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID0, 47); /* CCK Signal */
rt2x00_set_field32(&reg, RXCSR3_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID1, 51); /* Rssi */
@@ -984,9 +984,9 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, RXCSR3_BBP_ID2_VALID, 1);
rt2x00_set_field32(&reg, RXCSR3_BBP_ID3, 51); /* RSSI */
rt2x00_set_field32(&reg, RXCSR3_BBP_ID3_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, RXCSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg);
- rt2x00pci_register_read(rt2x00dev, PCICSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, PCICSR, &reg);
rt2x00_set_field32(&reg, PCICSR_BIG_ENDIAN, 0);
rt2x00_set_field32(&reg, PCICSR_RX_TRESHOLD, 0);
rt2x00_set_field32(&reg, PCICSR_TX_TRESHOLD, 3);
@@ -994,54 +994,54 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, PCICSR_ENABLE_CLK, 1);
rt2x00_set_field32(&reg, PCICSR_READ_MULTIPLE, 1);
rt2x00_set_field32(&reg, PCICSR_WRITE_INVALID, 1);
- rt2x00pci_register_write(rt2x00dev, PCICSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, PCICSR, reg);
- rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
- rt2x00pci_register_write(rt2x00dev, GPIOCSR, 0x0000ff00);
- rt2x00pci_register_write(rt2x00dev, TESTCSR, 0x000000f0);
+ rt2x00mmio_register_write(rt2x00dev, GPIOCSR, 0x0000ff00);
+ rt2x00mmio_register_write(rt2x00dev, TESTCSR, 0x000000f0);
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
return -EBUSY;
- rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00213223);
- rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00213223);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518);
- rt2x00pci_register_read(rt2x00dev, MACCSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MACCSR2, &reg);
rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
- rt2x00pci_register_write(rt2x00dev, MACCSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg);
- rt2x00pci_register_read(rt2x00dev, RALINKCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RALINKCSR, &reg);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA0, 17);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID0, 26);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_VALID0, 1);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_DATA1, 0);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_ID1, 26);
rt2x00_set_field32(&reg, RALINKCSR_AR_BBP_VALID1, 1);
- rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg);
- rt2x00pci_register_write(rt2x00dev, BBPCSR1, 0x82188200);
+ rt2x00mmio_register_write(rt2x00dev, BBPCSR1, 0x82188200);
- rt2x00pci_register_write(rt2x00dev, TXACKCSR0, 0x00000020);
+ rt2x00mmio_register_write(rt2x00dev, TXACKCSR0, 0x00000020);
- rt2x00pci_register_read(rt2x00dev, CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, CSR1_BBP_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 0);
- rt2x00pci_register_write(rt2x00dev, CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR1, &reg);
rt2x00_set_field32(&reg, CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, CSR1_HOST_READY, 1);
- rt2x00pci_register_write(rt2x00dev, CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR1, reg);
/*
* We must clear the FCS and FIFO error count.
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
- rt2x00pci_register_read(rt2x00dev, CNT4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CNT4, &reg);
return 0;
}
@@ -1058,7 +1058,7 @@ static int rt2500pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -1131,8 +1131,8 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
- rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
}
/*
@@ -1141,13 +1141,13 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, mask);
rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
@@ -1179,7 +1179,7 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Disable power
*/
- rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0);
}
static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -1193,12 +1193,12 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
put_to_sleep = (state != STATE_AWAKE);
- rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg);
rt2x00_set_field32(&reg, PWRCSR1_SET_STATE, 1);
rt2x00_set_field32(&reg, PWRCSR1_BBP_DESIRE_STATE, state);
rt2x00_set_field32(&reg, PWRCSR1_RF_DESIRE_STATE, state);
rt2x00_set_field32(&reg, PWRCSR1_PUT_TO_SLEEP, put_to_sleep);
- rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
/*
* Device is not guaranteed to be in the requested state yet.
@@ -1206,12 +1206,12 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, PWRCSR1, &reg2);
+ rt2x00mmio_register_read(rt2x00dev, PWRCSR1, &reg2);
bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);
rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);
if (bbp_state == state && rf_state == state)
return 0;
- rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);
msleep(10);
}
@@ -1246,8 +1246,8 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -1259,7 +1259,7 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -1335,12 +1335,12 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
if (rt2x00queue_map_txskb(entry)) {
- ERROR(rt2x00dev, "Fail to map beacon, aborting\n");
+ rt2x00_err(rt2x00dev, "Fail to map beacon, aborting\n");
goto out;
}
@@ -1358,7 +1358,7 @@ out:
* Enable beaconing again.
*/
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR14, reg);
}
/*
@@ -1367,7 +1367,7 @@ out:
static void rt2500pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word0;
u32 word2;
@@ -1405,7 +1405,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
const enum data_queue_qid queue_idx)
{
struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
struct queue_entry *entry;
struct txdone_entry_desc txdesc;
u32 word;
@@ -1451,9 +1451,9 @@ static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, irq_field, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -1476,11 +1476,11 @@ static void rt2500pci_txstatus_tasklet(unsigned long data)
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -1497,7 +1497,7 @@ static void rt2500pci_tbtt_tasklet(unsigned long data)
static void rt2500pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- if (rt2x00pci_rxdone(rt2x00dev))
+ if (rt2x00mmio_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
@@ -1512,8 +1512,8 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
* Get the interrupt sources & saved to local variable.
* Write register value back to clear pending interrupts.
*/
- rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
- rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR7, &reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR7, reg);
if (!reg)
return IRQ_NONE;
@@ -1550,9 +1550,9 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR8, &reg);
reg |= mask;
- rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, CSR8, reg);
spin_unlock(&rt2x00dev->irqmask_lock);
@@ -1569,7 +1569,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
u16 word;
u8 *mac;
- rt2x00pci_register_read(rt2x00dev, CSR21, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR21, &reg);
eeprom.data = rt2x00dev;
eeprom.register_read = rt2500pci_eepromregister_read;
@@ -1590,7 +1590,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1606,7 +1606,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
- EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
@@ -1615,7 +1615,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
- EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
@@ -1623,7 +1623,8 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
DEFAULT_RSSI_OFFSET);
rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
- EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n",
+ word);
}
return 0;
@@ -1644,7 +1645,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00pci_register_read(rt2x00dev, CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR0, &reg);
rt2x00_set_chip(rt2x00dev, RT2560, value,
rt2x00_get_field32(reg, CSR0_REVISION));
@@ -1654,7 +1655,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
!rt2x00_rf(rt2x00dev, RF2525) &&
!rt2x00_rf(rt2x00dev, RF2525E) &&
!rt2x00_rf(rt2x00dev, RF5222)) {
- ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
return -ENODEV;
}
@@ -1950,9 +1951,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, GPIOCSR, &reg);
rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
- rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg);
/*
* Initialize hw specifications.
@@ -1986,9 +1987,9 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw,
u64 tsf;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR17, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR17, &reg);
tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32;
- rt2x00pci_register_read(rt2x00dev, CSR16, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR16, &reg);
tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);
return tsf;
@@ -1999,7 +2000,7 @@ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
struct rt2x00_dev *rt2x00dev = hw->priv;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR15, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CSR15, &reg);
return rt2x00_get_field32(reg, CSR15_BEACON_SENT);
}
@@ -2032,8 +2033,8 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.tbtt_tasklet = rt2500pci_tbtt_tasklet,
.rxdone_tasklet = rt2500pci_rxdone_tasklet,
.probe_hw = rt2500pci_probe_hw,
- .initialize = rt2x00pci_initialize,
- .uninitialize = rt2x00pci_uninitialize,
+ .initialize = rt2x00mmio_initialize,
+ .uninitialize = rt2x00mmio_uninitialize,
.get_entry_state = rt2500pci_get_entry_state,
.clear_entry = rt2500pci_clear_entry,
.set_device_state = rt2500pci_set_device_state,
@@ -2044,7 +2045,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,
+ .flush_queue = rt2x00mmio_flush_queue,
.write_tx_desc = rt2500pci_write_tx_desc,
.write_beacon = rt2500pci_write_beacon,
.fill_rxdone = rt2500pci_fill_rxdone,
@@ -2059,28 +2060,28 @@ static const struct data_queue_desc rt2500pci_queue_rx = {
.entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2500pci_queue_tx = {
.entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2500pci_queue_bcn = {
.entry_num = 1,
.data_size = MGMT_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2500pci_queue_atim = {
.entry_num = 8,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct rt2x00_ops rt2500pci_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 6b2e1e431dd2..a7f7b365eff4 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -134,8 +134,8 @@ static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "Indirect register access failed: "
- "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+ rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
+ offset, *reg);
*reg = ~0;
return 0;
@@ -916,7 +916,7 @@ static int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -1069,8 +1069,8 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -1353,7 +1353,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1369,7 +1369,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
- EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
@@ -1378,7 +1378,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
- EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
@@ -1386,14 +1386,15 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
DEFAULT_RSSI_OFFSET);
rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
- EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n",
+ word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_THRESHOLD, 45);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE, word);
- EEPROM(rt2x00dev, "BBPtune: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune: 0x%04x\n", word);
}
/*
@@ -1408,7 +1409,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
- EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
} else {
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
@@ -1419,7 +1420,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_LOW, 0x48);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word);
- EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
@@ -1427,7 +1428,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_LOW, 0x40);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_HIGH, 0x80);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R24, word);
- EEPROM(rt2x00dev, "BBPtune r24: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r24: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &word);
@@ -1435,7 +1436,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_LOW, 0x40);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_HIGH, 0x50);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R25, word);
- EEPROM(rt2x00dev, "BBPtune r25: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r25: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &word);
@@ -1443,7 +1444,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_LOW, 0x60);
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_HIGH, 0x6d);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R61, word);
- EEPROM(rt2x00dev, "BBPtune r61: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r61: 0x%04x\n", word);
}
return 0;
@@ -1468,7 +1469,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) {
- ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");
return -ENODEV;
}
@@ -1478,7 +1479,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
!rt2x00_rf(rt2x00dev, RF2525) &&
!rt2x00_rf(rt2x00dev, RF2525E) &&
!rt2x00_rf(rt2x00dev, RF5222)) {
- ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
return -ENODEV;
}
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 7deac4d2459f..b52d70c75e1a 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -80,7 +80,7 @@ static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev)
rt2x00_rf(rt2x00dev, RF3022))
return true;
- WARNING(rt2x00dev, "Unknown RF chipset on rt305x\n");
+ rt2x00_warn(rt2x00dev, "Unknown RF chipset on rt305x\n");
return false;
}
@@ -328,7 +328,7 @@ int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev)
msleep(1);
}
- ERROR(rt2x00dev, "Unstable hardware.\n");
+ rt2x00_err(rt2x00dev, "Unstable hardware\n");
return -EBUSY;
}
EXPORT_SYMBOL_GPL(rt2800_wait_csr_ready);
@@ -351,7 +351,7 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
msleep(10);
}
- ERROR(rt2x00dev, "WPDMA TX/RX busy [0x%08x].\n", reg);
+ rt2x00_err(rt2x00dev, "WPDMA TX/RX busy [0x%08x]\n", reg);
return -EACCES;
}
EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready);
@@ -512,7 +512,7 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
}
if (i == REGISTER_BUSY_COUNT) {
- ERROR(rt2x00dev, "PBF system register not ready.\n");
+ rt2x00_err(rt2x00dev, "PBF system register not ready\n");
return -EBUSY;
}
@@ -542,6 +542,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
{
__le32 *txwi = rt2800_drv_get_txwi(entry);
u32 word;
+ int i;
/*
* Initialize TX Info descriptor
@@ -584,14 +585,16 @@ void rt2800_write_tx_data(struct queue_entry *entry,
rt2x00_desc_write(txwi, 1, word);
/*
- * Always write 0 to IV/EIV fields, hardware will insert the IV
- * from the IVEIV register when TXD_W3_WIV is set to 0.
+ * Always write 0 to IV/EIV fields (word 2 and 3), hardware will insert
+ * the IV from the IVEIV register when TXD_W3_WIV is set to 0.
* When TXD_W3_WIV is set to 1 it will use the IV data
* from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which
* crypto entry in the registers should be used to encrypt the frame.
+ *
+ * Nulify all remaining words as well, we don't know how to program them.
*/
- _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */);
- _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */);
+ for (i = 2; i < entry->queue->winfo_size / sizeof(__le32); i++)
+ _rt2x00_desc_write(txwi, i, 0);
}
EXPORT_SYMBOL_GPL(rt2800_write_tx_data);
@@ -676,6 +679,10 @@ void rt2800_process_rxwi(struct queue_entry *entry,
* Convert descriptor AGC value to RSSI value.
*/
rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word);
+ /*
+ * Remove RXWI descriptor from start of the buffer.
+ */
+ skb_pull(entry->skb, entry->queue->winfo_size);
}
EXPORT_SYMBOL_GPL(rt2800_process_rxwi);
@@ -766,6 +773,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
unsigned int beacon_base;
unsigned int padding_len;
u32 orig_reg, reg;
+ const int txwi_desc_size = entry->queue->winfo_size;
/*
* Disable beaconing while we are reloading the beacon data,
@@ -779,14 +787,14 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
/*
* Add space for the TXWI in front of the skb.
*/
- memset(skb_push(entry->skb, TXWI_DESC_SIZE), 0, TXWI_DESC_SIZE);
+ memset(skb_push(entry->skb, txwi_desc_size), 0, txwi_desc_size);
/*
* Register descriptor details in skb frame descriptor.
*/
skbdesc->flags |= SKBDESC_DESC_IN_SKB;
skbdesc->desc = entry->skb->data;
- skbdesc->desc_len = TXWI_DESC_SIZE;
+ skbdesc->desc_len = txwi_desc_size;
/*
* Add the TXWI for the beacon to the skb.
@@ -803,7 +811,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
*/
padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
if (padding_len && skb_pad(entry->skb, padding_len)) {
- ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+ rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
/* skb freed by skb_pad() on failure */
entry->skb = NULL;
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
@@ -832,13 +840,14 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
unsigned int beacon_base)
{
int i;
+ const int txwi_desc_size = rt2x00dev->ops->bcn->winfo_size;
/*
* For the Beacon base registers we only need to clear
* the whole TXWI which (when set to 0) will invalidate
* the entire beacon.
*/
- for (i = 0; i < TXWI_DESC_SIZE; i += sizeof(__le32))
+ for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
rt2800_register_write(rt2x00dev, beacon_base + i, 0);
}
@@ -3147,7 +3156,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
{
- rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.channel,
+ rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.chandef.chan,
rt2x00dev->tx_power);
}
EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
@@ -3282,11 +3291,11 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,
if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
rt2800_config_channel(rt2x00dev, libconf->conf,
&libconf->rf, &libconf->channel);
- rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
+ rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,
libconf->conf->power_level);
}
if (flags & IEEE80211_CONF_CHANGE_POWER)
- rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
+ rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan,
libconf->conf->power_level);
if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
rt2800_config_retry_limit(rt2x00dev, libconf);
@@ -3860,7 +3869,7 @@ static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP/RF register access failed, aborting\n");
return -EACCES;
}
@@ -3884,7 +3893,7 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -3924,7 +3933,7 @@ static void rt2800_init_bbp_5592_glrt(struct rt2x00_dev *rt2x00dev)
}
};
-static void rt2800_init_bbb_early(struct rt2x00_dev *rt2x00dev)
+static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev)
{
rt2800_bbp_write(rt2x00dev, 65, 0x2C);
rt2800_bbp_write(rt2x00dev, 66, 0x38);
@@ -3950,7 +3959,7 @@ static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev)
u16 eeprom;
u8 value;
- rt2800_init_bbb_early(rt2x00dev);
+ rt2800_init_bbp_early(rt2x00dev);
rt2800_bbp_read(rt2x00dev, 105, &value);
rt2x00_set_field8(&value, BBP105_MLD,
@@ -4332,8 +4341,17 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
return 0;
}
-static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,
- bool bw40, u8 rfcsr24, u8 filter_target)
+static void rt2800_led_open_drain_enable(struct rt2x00_dev *rt2x00dev)
+{
+ u32 reg;
+
+ rt2800_register_read(rt2x00dev, OPT_14_CSR, &reg);
+ rt2x00_set_field32(&reg, OPT_14_CSR_BIT0, 1);
+ rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
+}
+
+static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40,
+ u8 filter_target)
{
unsigned int i;
u8 bbp;
@@ -4341,6 +4359,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,
u8 passband;
u8 stopband;
u8 overtuned = 0;
+ u8 rfcsr24 = (bw40) ? 0x27 : 0x07;
rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
@@ -4396,8 +4415,169 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,
return rfcsr24;
}
+static void rt2800_rf_init_calibration(struct rt2x00_dev *rt2x00dev,
+ const unsigned int rf_reg)
+{
+ u8 rfcsr;
+
+ rt2800_rfcsr_read(rt2x00dev, rf_reg, &rfcsr);
+ rt2x00_set_field8(&rfcsr, FIELD8(0x80), 1);
+ rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);
+ msleep(1);
+ rt2x00_set_field8(&rfcsr, FIELD8(0x80), 0);
+ rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr);
+}
+
+static void rt2800_rx_filter_calibration(struct rt2x00_dev *rt2x00dev)
+{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+ u8 filter_tgt_bw20;
+ u8 filter_tgt_bw40;
+ u8 rfcsr, bbp;
+
+ /*
+ * TODO: sync filter_tgt values with vendor driver
+ */
+ if (rt2x00_rt(rt2x00dev, RT3070)) {
+ filter_tgt_bw20 = 0x16;
+ filter_tgt_bw40 = 0x19;
+ } else {
+ filter_tgt_bw20 = 0x13;
+ filter_tgt_bw40 = 0x15;
+ }
+
+ drv_data->calibration_bw20 =
+ rt2800_init_rx_filter(rt2x00dev, false, filter_tgt_bw20);
+ drv_data->calibration_bw40 =
+ rt2800_init_rx_filter(rt2x00dev, true, filter_tgt_bw40);
+
+ /*
+ * Save BBP 25 & 26 values for later use in channel switching (for 3052)
+ */
+ rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);
+ rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
+
+ /*
+ * Set back to initial state
+ */
+ rt2800_bbp_write(rt2x00dev, 24, 0);
+
+ rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
+ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
+
+ /*
+ * Set BBP back to BW20
+ */
+ rt2800_bbp_read(rt2x00dev, 4, &bbp);
+ rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
+ rt2800_bbp_write(rt2x00dev, 4, bbp);
+}
+
+static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev)
+{
+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+ u8 min_gain, rfcsr, bbp;
+ u16 eeprom;
+
+ rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+
+ rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
+ if (rt2x00_rt(rt2x00dev, RT3070) ||
+ 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(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
+ rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
+ }
+
+ min_gain = rt2x00_rt(rt2x00dev, RT3070) ? 1 : 2;
+ if (drv_data->txmixer_gain_24g >= min_gain) {
+ rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
+ drv_data->txmixer_gain_24g);
+ }
+
+ rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+ if (rt2x00_rt(rt2x00dev, RT3090)) {
+ /* Turn off unused DAC1 and ADC1 to reduce power consumption */
+ rt2800_bbp_read(rt2x00dev, 138, &bbp);
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
+ rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
+ rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1);
+ rt2800_bbp_write(rt2x00dev, 138, bbp);
+ }
+
+ if (rt2x00_rt(rt2x00dev, RT3070)) {
+ rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F))
+ rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0);
+ rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);
+ } else if (rt2x00_rt(rt2x00dev, RT3071) ||
+ rt2x00_rt(rt2x00dev, RT3090) ||
+ rt2x00_rt(rt2x00dev, RT3390)) {
+ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0);
+ rt2800_rfcsr_write(rt2x00dev, 15, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0);
+ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);
+ rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
+ }
+}
+
+static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev)
+{
+ u8 reg;
+ u16 eeprom;
+
+ /* Turn off unused DAC1 and ADC1 to reduce power consumption */
+ rt2800_bbp_read(rt2x00dev, 138, &reg);
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
+ rt2x00_set_field8(&reg, BBP138_RX_ADC1, 0);
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
+ rt2x00_set_field8(&reg, BBP138_TX_DAC1, 1);
+ rt2800_bbp_write(rt2x00dev, 138, reg);
+
+ rt2800_rfcsr_read(rt2x00dev, 38, &reg);
+ rt2x00_set_field8(&reg, RFCSR38_RX_LO1_EN, 0);
+ rt2800_rfcsr_write(rt2x00dev, 38, reg);
+
+ rt2800_rfcsr_read(rt2x00dev, 39, &reg);
+ rt2x00_set_field8(&reg, RFCSR39_RX_LO2_EN, 0);
+ rt2800_rfcsr_write(rt2x00dev, 39, reg);
+
+ rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+
+ rt2800_rfcsr_read(rt2x00dev, 30, &reg);
+ rt2x00_set_field8(&reg, RFCSR30_RX_VCM, 2);
+ rt2800_rfcsr_write(rt2x00dev, 30, reg);
+}
+
static void rt2800_init_rfcsr_305x_soc(struct rt2x00_dev *rt2x00dev)
{
+ rt2800_rf_init_calibration(rt2x00dev, 30);
+
rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
rt2800_rfcsr_write(rt2x00dev, 2, 0xf7);
@@ -4434,6 +4614,13 @@ static void rt2800_init_rfcsr_305x_soc(struct rt2x00_dev *rt2x00dev)
static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
{
+ u8 rfcsr;
+ u16 eeprom;
+ u32 reg;
+
+ /* XXX vendor driver do this only for 3070 */
+ rt2800_rf_init_calibration(rt2x00dev, 30);
+
rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
@@ -4453,10 +4640,54 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
+
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+ } else if (rt2x00_rt(rt2x00dev, RT3071) ||
+ rt2x00_rt(rt2x00dev, RT3090)) {
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
+
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+ rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+ else
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
+ }
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+ rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+ rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
+ rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+ }
+
+ rt2800_rx_filter_calibration(rt2x00dev);
+
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
+ rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+ rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E))
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
+
+ rt2800_led_open_drain_enable(rt2x00dev);
+ rt2800_normal_mode_setup_3xxx(rt2x00dev);
}
static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev)
{
+ u8 rfcsr;
+
+ rt2800_rf_init_calibration(rt2x00dev, 2);
+
rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
@@ -4503,10 +4734,19 @@ static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
+
+ rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3);
+ rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
+
+ rt2800_led_open_drain_enable(rt2x00dev);
+ rt2800_normal_mode_setup_3xxx(rt2x00dev);
}
static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
{
+ rt2800_rf_init_calibration(rt2x00dev, 30);
+
rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
rt2800_rfcsr_write(rt2x00dev, 1, 0x23);
rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
@@ -4570,10 +4810,18 @@ static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
+
+ rt2800_rx_filter_calibration(rt2x00dev);
+ rt2800_led_open_drain_enable(rt2x00dev);
+ rt2800_normal_mode_setup_3xxx(rt2x00dev);
}
static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev)
{
+ u32 reg;
+
+ rt2800_rf_init_calibration(rt2x00dev, 30);
+
rt2800_rfcsr_write(rt2x00dev, 0, 0xa0);
rt2800_rfcsr_write(rt2x00dev, 1, 0xe1);
rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
@@ -4606,10 +4854,27 @@ static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
+
+ rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+ rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
+ rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
+
+ rt2800_rx_filter_calibration(rt2x00dev);
+
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E))
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
+
+ rt2800_led_open_drain_enable(rt2x00dev);
+ rt2800_normal_mode_setup_3xxx(rt2x00dev);
}
static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev)
{
+ u8 rfcsr;
+ u32 reg;
+
+ rt2800_rf_init_calibration(rt2x00dev, 30);
+
rt2800_rfcsr_write(rt2x00dev, 0, 0x70);
rt2800_rfcsr_write(rt2x00dev, 1, 0x81);
rt2800_rfcsr_write(rt2x00dev, 2, 0xf1);
@@ -4641,10 +4906,30 @@ static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 29, 0x9b);
rt2800_rfcsr_write(rt2x00dev, 30, 0x09);
rt2800_rfcsr_write(rt2x00dev, 31, 0x10);
+
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+ msleep(1);
+ rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+ rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
+ rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
+ rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+ rt2800_rx_filter_calibration(rt2x00dev);
+ rt2800_led_open_drain_enable(rt2x00dev);
+ rt2800_normal_mode_setup_3xxx(rt2x00dev);
}
static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
{
+ rt2800_rf_init_calibration(rt2x00dev, 2);
+
rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
@@ -4725,10 +5010,16 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 61, 0xdd);
rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
+
+ rt2800_normal_mode_setup_5xxx(rt2x00dev);
+
+ rt2800_led_open_drain_enable(rt2x00dev);
}
static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev)
{
+ rt2800_rf_init_calibration(rt2x00dev, 2);
+
rt2800_rfcsr_write(rt2x00dev, 1, 0x17);
rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
@@ -4788,12 +5079,15 @@ static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
+
+ rt2800_normal_mode_setup_5xxx(rt2x00dev);
+
+ rt2800_led_open_drain_enable(rt2x00dev);
}
static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev)
{
- u8 reg;
- u16 eeprom;
+ rt2800_rf_init_calibration(rt2x00dev, 30);
rt2800_rfcsr_write(rt2x00dev, 1, 0x3F);
rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
@@ -4823,83 +5117,23 @@ static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev)
rt2800_adjust_freq_offset(rt2x00dev);
- rt2800_bbp_read(rt2x00dev, 138, &reg);
-
- /* Turn off unused DAC1 and ADC1 to reduce power consumption */
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
- rt2x00_set_field8(&reg, BBP138_RX_ADC1, 0);
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
- rt2x00_set_field8(&reg, BBP138_TX_DAC1, 1);
-
- rt2800_bbp_write(rt2x00dev, 138, reg);
-
/* Enable DC filter */
if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C))
rt2800_bbp_write(rt2x00dev, 103, 0xc0);
- rt2800_rfcsr_read(rt2x00dev, 38, &reg);
- rt2x00_set_field8(&reg, RFCSR38_RX_LO1_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 38, reg);
-
- rt2800_rfcsr_read(rt2x00dev, 39, &reg);
- rt2x00_set_field8(&reg, RFCSR39_RX_LO2_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 39, reg);
+ rt2800_normal_mode_setup_5xxx(rt2x00dev);
- rt2800_bbp4_mac_if_ctrl(rt2x00dev);
+ if (rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C))
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
- rt2800_rfcsr_read(rt2x00dev, 30, &reg);
- rt2x00_set_field8(&reg, RFCSR30_RX_VCM, 2);
- rt2800_rfcsr_write(rt2x00dev, 30, reg);
+ rt2800_led_open_drain_enable(rt2x00dev);
}
-static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
{
- struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
- u8 rfcsr;
- u8 bbp;
- u32 reg;
- u16 eeprom;
-
- if (!rt2x00_rt(rt2x00dev, RT3070) &&
- !rt2x00_rt(rt2x00dev, RT3071) &&
- !rt2x00_rt(rt2x00dev, RT3090) &&
- !rt2x00_rt(rt2x00dev, RT3290) &&
- !rt2x00_rt(rt2x00dev, RT3352) &&
- !rt2x00_rt(rt2x00dev, RT3390) &&
- !rt2x00_rt(rt2x00dev, RT3572) &&
- !rt2x00_rt(rt2x00dev, RT5390) &&
- !rt2x00_rt(rt2x00dev, RT5392) &&
- !rt2x00_rt(rt2x00dev, RT5392) &&
- !rt2x00_rt(rt2x00dev, RT5592) &&
- !rt2800_is_305x_soc(rt2x00dev))
- return 0;
-
- /*
- * Init RF calibration.
- */
-
- if (rt2x00_rt(rt2x00dev, RT3290) ||
- rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392)) {
- rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
- rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
- msleep(1);
- rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
- } else {
- rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
- rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
- msleep(1);
- rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
- rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
- }
-
if (rt2800_is_305x_soc(rt2x00dev)) {
rt2800_init_rfcsr_305x_soc(rt2x00dev);
- return 0;
+ return;
}
switch (rt2x00dev->chip.rt) {
@@ -4928,202 +5162,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
break;
case RT5592:
rt2800_init_rfcsr_5592(rt2x00dev);
- return 0;
- }
-
- if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
- rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
- rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
- rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
- } else if (rt2x00_rt(rt2x00dev, RT3071) ||
- rt2x00_rt(rt2x00dev, RT3090)) {
- rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
-
- rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
- rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
-
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
- rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
- if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
- rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
- else
- rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
- }
- rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
-
- rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
- rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
- rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
- } else if (rt2x00_rt(rt2x00dev, RT3390)) {
- rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
- rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
- rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
- } else if (rt2x00_rt(rt2x00dev, RT3572)) {
- rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
- rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
-
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
- rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
- rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
- rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
- msleep(1);
- rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
- rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
- rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
- rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
- }
-
- /*
- * Set RX Filter calibration for 20MHz and 40MHz
- */
- if (rt2x00_rt(rt2x00dev, RT3070)) {
- drv_data->calibration_bw20 =
- rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16);
- drv_data->calibration_bw40 =
- rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
- } else if (rt2x00_rt(rt2x00dev, RT3071) ||
- rt2x00_rt(rt2x00dev, RT3090) ||
- rt2x00_rt(rt2x00dev, RT3352) ||
- rt2x00_rt(rt2x00dev, RT3390) ||
- rt2x00_rt(rt2x00dev, RT3572)) {
- drv_data->calibration_bw20 =
- rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13);
- drv_data->calibration_bw40 =
- rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15);
- }
-
- /*
- * Save BBP 25 & 26 values for later use in channel switching
- */
- rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25);
- rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);
-
- if (!rt2x00_rt(rt2x00dev, RT5390) &&
- !rt2x00_rt(rt2x00dev, RT5392)) {
- /*
- * Set back to initial state
- */
- rt2800_bbp_write(rt2x00dev, 24, 0);
-
- rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
- rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
-
- /*
- * Set BBP back to BW20
- */
- rt2800_bbp_read(rt2x00dev, 4, &bbp);
- rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
- rt2800_bbp_write(rt2x00dev, 4, bbp);
- }
-
- if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E) ||
- rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C))
- rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
-
- rt2800_register_read(rt2x00dev, OPT_14_CSR, &reg);
- rt2x00_set_field32(&reg, OPT_14_CSR_BIT0, 1);
- rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
-
- if (!rt2x00_rt(rt2x00dev, RT5390) &&
- !rt2x00_rt(rt2x00dev, RT5392)) {
- rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
- if (rt2x00_rt(rt2x00dev, RT3070) ||
- 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(CAPABILITY_EXTERNAL_LNA_BG,
- &rt2x00dev->cap_flags))
- rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
- }
- rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
- drv_data->txmixer_gain_24g);
- rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
- }
-
- if (rt2x00_rt(rt2x00dev, RT3090) ||
- rt2x00_rt(rt2x00dev, RT5592)) {
- rt2800_bbp_read(rt2x00dev, 138, &bbp);
-
- /* Turn off unused DAC1 and ADC1 to reduce power consumption */
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
- rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
- rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1);
-
- rt2800_bbp_write(rt2x00dev, 138, bbp);
- }
-
- if (rt2x00_rt(rt2x00dev, RT3071) ||
- rt2x00_rt(rt2x00dev, RT3090) ||
- rt2x00_rt(rt2x00dev, RT3390)) {
- rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
- rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
- rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
- rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
- rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
- rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
-
- rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 15, rfcsr);
-
- rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
-
- rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
- }
-
- if (rt2x00_rt(rt2x00dev, RT3070)) {
- rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);
- if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F))
- rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);
- else
- rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0);
- rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0);
- rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0);
- rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0);
- rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);
- }
-
- if (rt2x00_rt(rt2x00dev, RT3290)) {
- rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3);
- rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
- }
-
- if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392) ||
- rt2x00_rt(rt2x00dev, RT5592)) {
- rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 38, rfcsr);
-
- rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0);
- rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
-
- rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
- rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+ break;
}
-
- return 0;
}
int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -5149,10 +5189,11 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
}
msleep(1);
- if (unlikely(rt2800_init_bbp(rt2x00dev) ||
- rt2800_init_rfcsr(rt2x00dev)))
+ if (unlikely(rt2800_init_bbp(rt2x00dev)))
return -EIO;
+ rt2800_init_rfcsr(rt2x00dev);
+
if (rt2x00_is_usb(rt2x00dev) &&
(rt2x00_rt(rt2x00dev, RT3070) ||
rt2x00_rt(rt2x00dev, RT3071) ||
@@ -5312,7 +5353,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);
@@ -5321,7 +5362,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);
rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
- EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
} else if (rt2x00_rt(rt2x00dev, RT2860) ||
rt2x00_rt(rt2x00dev, RT2872)) {
/*
@@ -5350,14 +5391,14 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word);
- EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
if ((word & 0x00ff) == 0x00ff) {
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
- EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
}
if ((word & 0xff00) == 0xff00) {
rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
@@ -5367,7 +5408,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8);
- EEPROM(rt2x00dev, "Led Mode: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Led Mode: 0x%04x\n", word);
}
/*
@@ -5473,7 +5514,8 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RF5592:
break;
default:
- ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", rf);
+ rt2x00_err(rt2x00dev, "Invalid RF chipset 0x%04x detected\n",
+ rf);
return -ENODEV;
}
@@ -6062,9 +6104,8 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
case RT5592:
break;
default:
- ERROR(rt2x00dev,
- "Invalid RT chipset 0x%04x, rev %04x detected.\n",
- rt, rev);
+ rt2x00_err(rt2x00dev, "Invalid RT chipset 0x%04x, rev %04x detected\n",
+ rt, rev);
return -ENODEV;
}
@@ -6323,7 +6364,8 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_OPERATIONAL:
break;
default:
- WARNING((struct rt2x00_dev *)hw->priv, "Unknown AMPDU action\n");
+ rt2x00_warn((struct rt2x00_dev *)hw->priv,
+ "Unknown AMPDU action\n");
}
return ret;
@@ -6340,7 +6382,7 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle);
rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 565a80d0e564..6f4a861af336 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -72,7 +72,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
return;
for (i = 0; i < 200; i++) {
- rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+ rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
(rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
@@ -84,10 +84,10 @@ 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");
+ rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n");
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
}
#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
@@ -116,7 +116,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -138,7 +138,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
!!eeprom->reg_chip_select);
- rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg);
}
static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
@@ -146,7 +146,7 @@ static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
struct eeprom_93cx6 eeprom;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
eeprom.data = rt2x00dev;
eeprom.register_read = rt2800pci_eepromregister_read;
@@ -210,20 +210,20 @@ static void rt2800pci_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
- rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
break;
default:
break;
@@ -241,13 +241,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);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
- entry->entry_idx);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
+ entry->entry_idx);
break;
case QID_MGMT:
entry = rt2x00queue_get_entry(queue, Q_INDEX);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(5),
- entry->entry_idx);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(5),
+ entry->entry_idx);
break;
default:
break;
@@ -261,20 +261,20 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, &reg);
rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
- rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg);
/*
* Wait for current invocation to finish. The tasklet
@@ -314,19 +314,19 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
*/
reg = 0;
rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
/*
* Write firmware to device.
*/
- rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
- data, len);
+ rt2x00mmio_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+ data, len);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
- rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
return 0;
}
@@ -336,7 +336,7 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
*/
static bool rt2800pci_get_entry_state(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word;
if (entry->queue->qid == QID_RX) {
@@ -352,7 +352,7 @@ static bool rt2800pci_get_entry_state(struct queue_entry *entry)
static void rt2800pci_clear_entry(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
u32 word;
@@ -370,8 +370,8 @@ 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.
*/
- rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
- entry->entry_idx);
+ rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX,
+ entry->entry_idx);
} else {
rt2x00_desc_read(entry_priv->desc, 1, &word);
rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
@@ -381,60 +381,65 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
{
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
/*
* Initialize registers.
*/
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- 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);
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0,
+ entry_priv->desc_dma);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0,
+ rt2x00dev->tx[0].limit);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- 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);
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1,
+ entry_priv->desc_dma);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1,
+ rt2x00dev->tx[1].limit);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0);
entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
- 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);
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2,
+ entry_priv->desc_dma);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2,
+ rt2x00dev->tx[2].limit);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0);
entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
- 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);
-
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR4, 0);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT4, 0);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX4, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX4, 0);
-
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR5, 0);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT5, 0);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX5, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX5, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3,
+ entry_priv->desc_dma);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3,
+ rt2x00dev->tx[3].limit);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0);
+
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX4, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX4, 0);
+
+ rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR5, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT5, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX5, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX5, 0);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- 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);
+ rt2x00mmio_register_write(rt2x00dev, RX_BASE_PTR,
+ entry_priv->desc_dma);
+ rt2x00mmio_register_write(rt2x00dev, RX_MAX_CNT,
+ rt2x00dev->rx[0].limit);
+ rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX,
+ rt2x00dev->rx[0].limit - 1);
+ rt2x00mmio_register_write(rt2x00dev, RX_DRX_IDX, 0);
rt2800_disable_wpdma(rt2x00dev);
- rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0);
+ rt2x00mmio_register_write(rt2x00dev, DELAY_INT_CFG, 0);
return 0;
}
@@ -453,8 +458,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) {
- rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
}
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
@@ -466,7 +471,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
}
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
if (state == STATE_RADIO_IRQ_OFF) {
@@ -488,7 +493,7 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
/*
* Reset DMA indexes
*/
- rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+ rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
@@ -496,29 +501,29 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
- rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+ rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+ rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
if (rt2x00_is_pcie(rt2x00dev) &&
(rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))) {
- rt2x00pci_register_read(rt2x00dev, AUX_CTRL, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, &reg);
rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
- rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg);
+ rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg);
}
- rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+ rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
reg = 0;
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+ rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
return 0;
}
@@ -538,8 +543,8 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
return retval;
/* After resume MCU_BOOT_SIGNAL will trash these. */
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02);
rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF);
@@ -554,8 +559,8 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
{
if (rt2x00_is_soc(rt2x00dev)) {
rt2800_disable_radio(rt2x00dev);
- rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
- rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
+ rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+ rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0);
}
}
@@ -567,10 +572,10 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
0, 0x02);
rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
} else if (state == STATE_SLEEP) {
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
- 0xffffffff);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID,
- 0xffffffff);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
+ 0xffffffff);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID,
+ 0xffffffff);
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP,
0xff, 0x01);
}
@@ -611,8 +616,8 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -629,7 +634,7 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -683,7 +688,7 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
static void rt2800pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
__le32 *rxd = entry_priv->desc;
u32 word;
@@ -730,11 +735,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
* Process the RXWI structure that is at the start of the buffer.
*/
rt2800_process_rxwi(entry, rxdesc);
-
- /*
- * Remove RXWI descriptor from start of buffer.
- */
- skb_pull(entry->skb, RXWI_DESC_SIZE);
}
/*
@@ -843,8 +843,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
* Unknown queue, this shouldn't happen. Just drop
* this tx status.
*/
- WARNING(rt2x00dev, "Got TX status report with "
- "unexpected pid %u, dropping\n", qid);
+ rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n",
+ qid);
break;
}
@@ -854,8 +854,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
* The queue is NULL, this shouldn't happen. Stop
* processing here and drop the tx status
*/
- WARNING(rt2x00dev, "Got TX status for an unavailable "
- "queue %u, dropping\n", qid);
+ rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n",
+ qid);
break;
}
@@ -864,8 +864,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
* The queue is empty. Stop processing here
* and drop the tx status.
*/
- WARNING(rt2x00dev, "Got TX status for an empty "
- "queue %u, dropping\n", qid);
+ rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
+ qid);
break;
}
@@ -883,9 +883,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE,
Q_INDEX, &status,
rt2800pci_txdone_match_first)) {
- WARNING(rt2x00dev, "No frame found for TX "
- "status on queue %u, dropping\n",
- qid);
+ rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n",
+ qid);
break;
}
}
@@ -914,9 +913,9 @@ static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
* access needs locking.
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, irq_field, 1);
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -957,15 +956,15 @@ static void rt2800pci_tbtt_tasklet(unsigned long data)
* interval every 64 beacons by 64us to mitigate this effect.
*/
if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) {
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
(rt2x00dev->beacon_int * 16) - 1);
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
} else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) {
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
(rt2x00dev->beacon_int * 16));
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg);
}
drv_data->tbtt_tick++;
drv_data->tbtt_tick %= BCN_TBTT_OFFSET;
@@ -978,7 +977,7 @@ static void rt2800pci_tbtt_tasklet(unsigned long data)
static void rt2800pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- if (rt2x00pci_rxdone(rt2x00dev))
+ if (rt2x00mmio_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
@@ -1016,14 +1015,13 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
* need to lock the kfifo.
*/
for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
- rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &status);
+ rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status);
if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
break;
if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) {
- WARNING(rt2x00dev, "TX status FIFO overrun,"
- "drop tx status report.\n");
+ rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
break;
}
}
@@ -1038,8 +1036,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
u32 reg, mask;
/* Read status and ACK all interrupts */
- rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
if (!reg)
return IRQ_NONE;
@@ -1079,9 +1077,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
* the tasklet will reenable the appropriate interrupts.
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
reg &= mask;
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock(&rt2x00dev->irqmask_lock);
return IRQ_HANDLED;
@@ -1132,13 +1130,13 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
};
static const struct rt2800_ops rt2800pci_rt2800_ops = {
- .register_read = rt2x00pci_register_read,
- .register_read_lock = rt2x00pci_register_read, /* same for PCI */
- .register_write = rt2x00pci_register_write,
- .register_write_lock = rt2x00pci_register_write, /* same for PCI */
- .register_multiread = rt2x00pci_register_multiread,
- .register_multiwrite = rt2x00pci_register_multiwrite,
- .regbusy_read = rt2x00pci_regbusy_read,
+ .register_read = rt2x00mmio_register_read,
+ .register_read_lock = rt2x00mmio_register_read, /* same for PCI */
+ .register_write = rt2x00mmio_register_write,
+ .register_write_lock = rt2x00mmio_register_write, /* same for PCI */
+ .register_multiread = rt2x00mmio_register_multiread,
+ .register_multiwrite = rt2x00mmio_register_multiwrite,
+ .regbusy_read = rt2x00mmio_regbusy_read,
.read_eeprom = rt2800pci_read_eeprom,
.hwcrypt_disabled = rt2800pci_hwcrypt_disabled,
.drv_write_firmware = rt2800pci_write_firmware,
@@ -1157,8 +1155,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.get_firmware_name = rt2800pci_get_firmware_name,
.check_firmware = rt2800_check_firmware,
.load_firmware = rt2800_load_firmware,
- .initialize = rt2x00pci_initialize,
- .uninitialize = rt2x00pci_uninitialize,
+ .initialize = rt2x00mmio_initialize,
+ .uninitialize = rt2x00mmio_uninitialize,
.get_entry_state = rt2800pci_get_entry_state,
.clear_entry = rt2800pci_clear_entry,
.set_device_state = rt2800pci_set_device_state,
@@ -1171,7 +1169,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,
+ .flush_queue = rt2x00mmio_flush_queue,
.write_tx_desc = rt2800pci_write_tx_desc,
.write_tx_data = rt2800_write_tx_data,
.write_beacon = rt2800_write_beacon,
@@ -1192,21 +1190,24 @@ static const struct data_queue_desc rt2800pci_queue_rx = {
.entry_num = 128,
.data_size = AGGREGATION_SIZE,
.desc_size = RXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .winfo_size = RXWI_DESC_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2800pci_queue_tx = {
.entry_num = 64,
.data_size = AGGREGATION_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .winfo_size = TXWI_DESC_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt2800pci_queue_bcn = {
.entry_num = 8,
.data_size = 0, /* No DMA required for beacons */
- .desc_size = TXWI_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .desc_size = TXD_DESC_SIZE,
+ .winfo_size = TXWI_DESC_SIZE,
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct rt2x00_ops rt2800pci_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index f32282009146..ac854d75bd6c 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -128,9 +128,9 @@ static inline bool rt2800usb_entry_txstatus_timeout(struct queue_entry *entry)
tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
if (unlikely(tout))
- WARNING(entry->queue->rt2x00dev,
- "TX status timeout for entry %d in queue %d\n",
- entry->entry_idx, entry->queue->qid);
+ rt2x00_warn(entry->queue->rt2x00dev,
+ "TX status timeout for entry %d in queue %d\n",
+ entry->entry_idx, entry->queue->qid);
return tout;
}
@@ -154,7 +154,8 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
bool valid;
if (urb_status) {
- WARNING(rt2x00dev, "TX status read failed %d\n", urb_status);
+ rt2x00_warn(rt2x00dev, "TX status read failed %d\n",
+ urb_status);
goto stop_reading;
}
@@ -162,7 +163,7 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID);
if (valid) {
if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status))
- WARNING(rt2x00dev, "TX status FIFO overrun\n");
+ rt2x00_warn(rt2x00dev, "TX status FIFO overrun\n");
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
@@ -269,7 +270,7 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
0, USB_MODE_FIRMWARE,
REGISTER_TIMEOUT_FIRMWARE);
if (status < 0) {
- ERROR(rt2x00dev, "Failed to write Firmware to device.\n");
+ rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");
return status;
}
@@ -392,8 +393,8 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -408,8 +409,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
- WARNING(rt2x00dev, "TX HW queue 0 timed out,"
- " invoke forced kick\n");
+ rt2x00_warn(rt2x00dev, "TX HW queue 0 timed out, invoke forced kick\n");
rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);
@@ -424,8 +424,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
- WARNING(rt2x00dev, "TX HW queue 1 timed out,"
- " invoke forced kick\n");
+ rt2x00_warn(rt2x00dev, "TX HW queue 1 timed out, invoke forced kick\n");
rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
@@ -485,7 +484,7 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry,
*/
skbdesc->flags |= SKBDESC_DESC_IN_SKB;
skbdesc->desc = txi;
- skbdesc->desc_len = entry->queue->desc_size;
+ skbdesc->desc_len = TXINFO_DESC_SIZE + entry->queue->winfo_size;
}
/*
@@ -540,9 +539,9 @@ rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID);
if (wcid != tx_wcid || ack != tx_ack || (!is_agg && pid != tx_pid)) {
- DEBUG(entry->queue->rt2x00dev,
- "TX status report missed for queue %d entry %d\n",
- entry->queue->qid, entry->entry_idx);
+ rt2x00_dbg(entry->queue->rt2x00dev,
+ "TX status report missed for queue %d entry %d\n",
+ entry->queue->qid, entry->entry_idx);
return TXDONE_UNKNOWN;
}
@@ -566,8 +565,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
if (unlikely(rt2x00queue_empty(queue))) {
- WARNING(rt2x00dev, "Got TX status for an empty "
- "queue %u, dropping\n", qid);
+ rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n",
+ qid);
break;
}
@@ -575,8 +574,8 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
- WARNING(rt2x00dev, "Data pending for entry %u "
- "in queue %u\n", entry->entry_idx, qid);
+ rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n",
+ entry->entry_idx, qid);
break;
}
@@ -677,8 +676,8 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
*/
if (unlikely(rx_pkt_len == 0 ||
rx_pkt_len > entry->queue->data_size)) {
- ERROR(entry->queue->rt2x00dev,
- "Bad frame size %d, forcing to 0\n", rx_pkt_len);
+ rt2x00_err(entry->queue->rt2x00dev,
+ "Bad frame size %d, forcing to 0\n", rx_pkt_len);
return;
}
@@ -730,11 +729,6 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
* Process the RXWI structure.
*/
rt2800_process_rxwi(entry, rxdesc);
-
- /*
- * Remove RXWI descriptor from start of buffer.
- */
- skb_pull(entry->skb, entry->queue->desc_size - RXINFO_DESC_SIZE);
}
/*
@@ -858,21 +852,24 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
static const struct data_queue_desc rt2800usb_queue_rx = {
.entry_num = 128,
.data_size = AGGREGATION_SIZE,
- .desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE,
+ .desc_size = RXINFO_DESC_SIZE,
+ .winfo_size = RXWI_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
static const struct data_queue_desc rt2800usb_queue_tx = {
.entry_num = 16,
.data_size = AGGREGATION_SIZE,
- .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
+ .desc_size = TXINFO_DESC_SIZE,
+ .winfo_size = TXWI_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
static const struct data_queue_desc rt2800usb_queue_bcn = {
.entry_num = 8,
.data_size = MGMT_FRAME_SIZE,
- .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
+ .desc_size = TXINFO_DESC_SIZE,
+ .winfo_size = TXWI_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
@@ -898,21 +895,24 @@ static const struct rt2x00_ops rt2800usb_ops = {
static const struct data_queue_desc rt2800usb_queue_rx_5592 = {
.entry_num = 128,
.data_size = AGGREGATION_SIZE,
- .desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE_5592,
+ .desc_size = RXINFO_DESC_SIZE,
+ .winfo_size = RXWI_DESC_SIZE_5592,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
static const struct data_queue_desc rt2800usb_queue_tx_5592 = {
.entry_num = 16,
.data_size = AGGREGATION_SIZE,
- .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592,
+ .desc_size = TXINFO_DESC_SIZE,
+ .winfo_size = TXWI_DESC_SIZE_5592,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
static const struct data_queue_desc rt2800usb_queue_bcn_5592 = {
.entry_num = 8,
.data_size = MGMT_FRAME_SIZE,
- .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592,
+ .desc_size = TXINFO_DESC_SIZE,
+ .winfo_size = TXWI_DESC_SIZE_5592,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 0d02d16ca166..7510723a8c37 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -54,47 +54,36 @@
#define DRV_VERSION "2.3.0"
#define DRV_PROJECT "http://rt2x00.serialmonkey.com"
-/*
- * Debug definitions.
+/* Debug definitions.
* Debug output has to be enabled during compile time.
*/
-#define DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, __args...) \
- printk(__kernlvl "%s -> %s: %s - " __msg, \
- wiphy_name((__dev)->hw->wiphy), __func__, __lvl, ##__args)
-
-#define DEBUG_PRINTK_PROBE(__kernlvl, __lvl, __msg, __args...) \
- printk(__kernlvl "%s -> %s: %s - " __msg, \
- KBUILD_MODNAME, __func__, __lvl, ##__args)
-
#ifdef CONFIG_RT2X00_DEBUG
-#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \
- DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args)
-#else
-#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \
- do { } while (0)
+#define DEBUG
#endif /* CONFIG_RT2X00_DEBUG */
-/*
- * Various debug levels.
- * The debug levels PANIC and ERROR both indicate serious problems,
- * for this reason they should never be ignored.
- * The special ERROR_PROBE message is for messages that are generated
- * when the rt2x00_dev is not yet initialized.
+/* Utility printing macros
+ * rt2x00_probe_err is for messages when rt2x00_dev is uninitialized
*/
-#define PANIC(__dev, __msg, __args...) \
- DEBUG_PRINTK_MSG(__dev, KERN_CRIT, "Panic", __msg, ##__args)
-#define ERROR(__dev, __msg, __args...) \
- DEBUG_PRINTK_MSG(__dev, KERN_ERR, "Error", __msg, ##__args)
-#define ERROR_PROBE(__msg, __args...) \
- DEBUG_PRINTK_PROBE(KERN_ERR, "Error", __msg, ##__args)
-#define WARNING(__dev, __msg, __args...) \
- DEBUG_PRINTK_MSG(__dev, KERN_WARNING, "Warning", __msg, ##__args)
-#define INFO(__dev, __msg, __args...) \
- DEBUG_PRINTK_MSG(__dev, KERN_INFO, "Info", __msg, ##__args)
-#define DEBUG(__dev, __msg, __args...) \
- DEBUG_PRINTK(__dev, KERN_DEBUG, "Debug", __msg, ##__args)
-#define EEPROM(__dev, __msg, __args...) \
- DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args)
+#define rt2x00_probe_err(fmt, ...) \
+ printk(KERN_ERR KBUILD_MODNAME ": %s: Error - " fmt, \
+ __func__, ##__VA_ARGS__)
+#define rt2x00_err(dev, fmt, ...) \
+ wiphy_err((dev)->hw->wiphy, "%s: Error - " fmt, \
+ __func__, ##__VA_ARGS__)
+#define rt2x00_warn(dev, fmt, ...) \
+ wiphy_warn((dev)->hw->wiphy, "%s: Warning - " fmt, \
+ __func__, ##__VA_ARGS__)
+#define rt2x00_info(dev, fmt, ...) \
+ wiphy_info((dev)->hw->wiphy, "%s: Info - " fmt, \
+ __func__, ##__VA_ARGS__)
+
+/* Various debug levels */
+#define rt2x00_dbg(dev, fmt, ...) \
+ wiphy_dbg((dev)->hw->wiphy, "%s: Debug - " fmt, \
+ __func__, ##__VA_ARGS__)
+#define rt2x00_eeprom_dbg(dev, fmt, ...) \
+ wiphy_dbg((dev)->hw->wiphy, "%s: EEPROM recovery - " fmt, \
+ __func__, ##__VA_ARGS__)
/*
* Duration calculations
@@ -1101,9 +1090,9 @@ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev,
rt2x00dev->chip.rf = rf;
rt2x00dev->chip.rev = rev;
- INFO(rt2x00dev,
- "Chipset detected - rt: %04x, rf: %04x, rev: %04x.\n",
- rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev);
+ rt2x00_info(rt2x00dev, "Chipset detected - rt: %04x, rf: %04x, rev: %04x\n",
+ rt2x00dev->chip.rt, rt2x00dev->chip.rf,
+ rt2x00dev->chip.rev);
}
static inline void rt2x00_set_rt(struct rt2x00_dev *rt2x00dev,
@@ -1112,15 +1101,16 @@ static inline void rt2x00_set_rt(struct rt2x00_dev *rt2x00dev,
rt2x00dev->chip.rt = rt;
rt2x00dev->chip.rev = rev;
- INFO(rt2x00dev, "RT chipset %04x, rev %04x detected\n",
- rt2x00dev->chip.rt, rt2x00dev->chip.rev);
+ rt2x00_info(rt2x00dev, "RT chipset %04x, rev %04x detected\n",
+ rt2x00dev->chip.rt, rt2x00dev->chip.rev);
}
static inline void rt2x00_set_rf(struct rt2x00_dev *rt2x00dev, const u16 rf)
{
rt2x00dev->chip.rf = rf;
- INFO(rt2x00dev, "RF chipset %04x detected\n", rt2x00dev->chip.rf);
+ rt2x00_info(rt2x00dev, "RF chipset %04x detected\n",
+ rt2x00dev->chip.rf);
}
static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt)
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 49a63e973934..8cb43f8f3efc 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -184,7 +184,7 @@ static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
/*
* Initialize center channel to current channel.
*/
- center_channel = spec->channels[conf->channel->hw_value].channel;
+ center_channel = spec->channels[conf->chandef.chan->hw_value].channel;
/*
* Adjust center channel to HT40+ and HT40- operation.
@@ -199,7 +199,7 @@ static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
return i;
WARN_ON(1);
- return conf->channel->hw_value;
+ return conf->chandef.chan->hw_value;
}
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
@@ -227,7 +227,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
} else {
clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
- hw_value = conf->channel->hw_value;
+ hw_value = conf->chandef.chan->hw_value;
}
memcpy(&libconf.rf,
@@ -279,8 +279,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
else
clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
- rt2x00dev->curr_band = conf->channel->band;
- rt2x00dev->curr_freq = conf->channel->center_freq;
+ rt2x00dev->curr_band = conf->chandef.chan->band;
+ rt2x00dev->curr_freq = conf->chandef.chan->center_freq;
rt2x00dev->tx_power = conf->power_level;
rt2x00dev->short_retry = conf->short_frame_max_tx_count;
rt2x00dev->long_retry = conf->long_frame_max_tx_count;
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 3bb8cafbac59..fe7a7f63a9ed 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -174,7 +174,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
do_gettimeofday(&timestamp);
if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
- DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
+ rt2x00_dbg(rt2x00dev, "txrx dump queue length exceeded\n");
return;
}
@@ -185,7 +185,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + data_len,
GFP_ATOMIC);
if (!skbcopy) {
- DEBUG(rt2x00dev, "Failed to copy skb for dump.\n");
+ rt2x00_dbg(rt2x00dev, "Failed to copy skb for dump\n");
return;
}
@@ -657,7 +657,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL);
if (!intf) {
- ERROR(rt2x00dev, "Failed to allocate debug handler.\n");
+ rt2x00_err(rt2x00dev, "Failed to allocate debug handler\n");
return;
}
@@ -760,7 +760,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
exit:
rt2x00debug_deregister(rt2x00dev);
- ERROR(rt2x00dev, "Failed to register debug handler.\n");
+ rt2x00_err(rt2x00dev, "Failed to register debug handler\n");
}
void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 189744db65e0..90dc14336980 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -171,7 +171,7 @@ static void rt2x00lib_autowakeup(struct work_struct *work)
return;
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
- ERROR(rt2x00dev, "Device failed to wakeup.\n");
+ rt2x00_err(rt2x00dev, "Device failed to wakeup\n");
clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags);
}
@@ -673,9 +673,8 @@ static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
break;
}
- WARNING(rt2x00dev, "Frame received with unrecognized signal, "
- "mode=0x%.4x, signal=0x%.4x, type=%d.\n",
- rxdesc->rate_mode, signal, type);
+ rt2x00_warn(rt2x00dev, "Frame received with unrecognized signal, mode=0x%.4x, signal=0x%.4x, type=%d\n",
+ rxdesc->rate_mode, signal, type);
return 0;
}
@@ -720,8 +719,8 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
*/
if (unlikely(rxdesc.size == 0 ||
rxdesc.size > entry->queue->data_size)) {
- ERROR(rt2x00dev, "Wrong frame size %d max %d.\n",
- rxdesc.size, entry->queue->data_size);
+ rt2x00_err(rt2x00dev, "Wrong frame size %d max %d\n",
+ rxdesc.size, entry->queue->data_size);
dev_kfree_skb(entry->skb);
goto renew_skb;
}
@@ -1006,7 +1005,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
exit_free_channels:
kfree(channels);
- ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n");
+ rt2x00_err(rt2x00dev, "Allocation ieee80211 modes failed\n");
return -ENOMEM;
}
@@ -1337,7 +1336,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
*/
retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev);
if (retval) {
- ERROR(rt2x00dev, "Failed to allocate device.\n");
+ rt2x00_err(rt2x00dev, "Failed to allocate device\n");
goto exit;
}
@@ -1353,7 +1352,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
*/
retval = rt2x00lib_probe_hw(rt2x00dev);
if (retval) {
- ERROR(rt2x00dev, "Failed to initialize hw.\n");
+ rt2x00_err(rt2x00dev, "Failed to initialize hw\n");
goto exit;
}
@@ -1451,7 +1450,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
#ifdef CONFIG_PM
int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
{
- DEBUG(rt2x00dev, "Going to sleep.\n");
+ rt2x00_dbg(rt2x00dev, "Going to sleep\n");
/*
* Prevent mac80211 from accessing driver while suspended.
@@ -1482,8 +1481,7 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
* device is as good as disabled.
*/
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP))
- WARNING(rt2x00dev, "Device failed to enter sleep state, "
- "continue suspending.\n");
+ rt2x00_warn(rt2x00dev, "Device failed to enter sleep state, continue suspending\n");
return 0;
}
@@ -1491,7 +1489,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_suspend);
int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
{
- DEBUG(rt2x00dev, "Waking up.\n");
+ rt2x00_dbg(rt2x00dev, "Waking up\n");
/*
* Restore/enable extra components.
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
index f316aad30612..1b4254b4272d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
@@ -42,28 +42,28 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
*/
fw_name = rt2x00dev->ops->lib->get_firmware_name(rt2x00dev);
if (!fw_name) {
- ERROR(rt2x00dev,
- "Invalid firmware filename.\n"
- "Please file bug report to %s.\n", DRV_PROJECT);
+ rt2x00_err(rt2x00dev,
+ "Invalid firmware filename\n"
+ "Please file bug report to %s\n", DRV_PROJECT);
return -EINVAL;
}
- INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name);
+ rt2x00_info(rt2x00dev, "Loading firmware file '%s'\n", fw_name);
retval = request_firmware(&fw, fw_name, device);
if (retval) {
- ERROR(rt2x00dev, "Failed to request Firmware.\n");
+ rt2x00_err(rt2x00dev, "Failed to request Firmware\n");
return retval;
}
if (!fw || !fw->size || !fw->data) {
- ERROR(rt2x00dev, "Failed to read Firmware.\n");
+ rt2x00_err(rt2x00dev, "Failed to read Firmware\n");
release_firmware(fw);
return -ENOENT;
}
- INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n",
- fw->data[fw->size - 4], fw->data[fw->size - 3]);
+ rt2x00_info(rt2x00dev, "Firmware detected - version: %d.%d\n",
+ fw->data[fw->size - 4], fw->data[fw->size - 3]);
snprintf(rt2x00dev->hw->wiphy->fw_version,
sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d",
fw->data[fw->size - 4], fw->data[fw->size - 3]);
@@ -73,15 +73,14 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
case FW_OK:
break;
case FW_BAD_CRC:
- ERROR(rt2x00dev, "Firmware checksum error.\n");
+ rt2x00_err(rt2x00dev, "Firmware checksum error\n");
goto exit;
case FW_BAD_LENGTH:
- ERROR(rt2x00dev,
- "Invalid firmware file length (len=%zu)\n", fw->size);
+ rt2x00_err(rt2x00dev, "Invalid firmware file length (len=%zu)\n",
+ fw->size);
goto exit;
case FW_BAD_VERSION:
- ERROR(rt2x00dev,
- "Current firmware does not support detected chipset.\n");
+ rt2x00_err(rt2x00dev, "Current firmware does not support detected chipset\n");
goto exit;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c
index 8679d781a264..997a6c89e66e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00leds.c
+++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
@@ -113,7 +113,7 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
retval = led_classdev_register(device, &led->led_dev);
if (retval) {
- ERROR(rt2x00dev, "Failed to register led handler.\n");
+ rt2x00_err(rt2x00dev, "Failed to register led handler\n");
return retval;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 9161c02d8ff9..f883802f3505 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -46,7 +46,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
skb = dev_alloc_skb(data_length + rt2x00dev->hw->extra_tx_headroom);
if (unlikely(!skb)) {
- WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n");
+ rt2x00_warn(rt2x00dev, "Failed to create RTS/CTS frame\n");
return -ENOMEM;
}
@@ -93,7 +93,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
retval = rt2x00queue_write_tx_frame(queue, skb, true);
if (retval) {
dev_kfree_skb_any(skb);
- WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
+ rt2x00_warn(rt2x00dev, "Failed to send RTS/CTS frame\n");
}
return retval;
@@ -126,9 +126,9 @@ void rt2x00mac_tx(struct ieee80211_hw *hw,
queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
if (unlikely(!queue)) {
- ERROR(rt2x00dev,
- "Attempt to send packet over invalid queue %d.\n"
- "Please file bug report to %s.\n", qid, DRV_PROJECT);
+ rt2x00_err(rt2x00dev,
+ "Attempt to send packet over invalid queue %d\n"
+ "Please file bug report to %s\n", qid, DRV_PROJECT);
goto exit_free_skb;
}
@@ -731,9 +731,10 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
queue->aifs = params->aifs;
queue->txop = params->txop;
- DEBUG(rt2x00dev,
- "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d.\n",
- queue_idx, queue->cw_min, queue->cw_max, queue->aifs, queue->txop);
+ rt2x00_dbg(rt2x00dev,
+ "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d\n",
+ queue_idx, queue->cw_min, queue->cw_max, queue->aifs,
+ queue->txop);
return 0;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.c b/drivers/net/wireless/rt2x00/rt2x00mmio.c
index d84a680ba0c9..64b06c6abe58 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mmio.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mmio.c
@@ -34,10 +34,10 @@
/*
* Register access.
*/
-int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- const struct rt2x00_field32 field,
- u32 *reg)
+int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const struct rt2x00_field32 field,
+ u32 *reg)
{
unsigned int i;
@@ -45,7 +45,7 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
return 0;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, offset, reg);
+ rt2x00mmio_register_read(rt2x00dev, offset, reg);
if (!rt2x00_get_field32(*reg, field))
return 1;
udelay(REGISTER_BUSY_DELAY);
@@ -57,13 +57,13 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
return 0;
}
-EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
+EXPORT_SYMBOL_GPL(rt2x00mmio_regbusy_read);
-bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
+bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue = rt2x00dev->rx;
struct queue_entry *entry;
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
struct skb_frame_desc *skbdesc;
int max_rx = 16;
@@ -96,24 +96,24 @@ bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
return !max_rx;
}
-EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
+EXPORT_SYMBOL_GPL(rt2x00mmio_rxdone);
-void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
+void rt2x00mmio_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);
+EXPORT_SYMBOL_GPL(rt2x00mmio_flush_queue);
/*
* Device initialization handlers.
*/
-static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
- struct data_queue *queue)
+static int rt2x00mmio_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
+ struct data_queue *queue)
{
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
void *addr;
dma_addr_t dma;
unsigned int i;
@@ -141,10 +141,10 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
return 0;
}
-static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
- struct data_queue *queue)
+static void rt2x00mmio_free_queue_dma(struct rt2x00_dev *rt2x00dev,
+ struct data_queue *queue)
{
- struct queue_entry_priv_pci *entry_priv =
+ struct queue_entry_priv_mmio *entry_priv =
queue->entries[0].priv_data;
if (entry_priv->desc)
@@ -154,7 +154,7 @@ static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
entry_priv->desc = NULL;
}
-int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
+int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
int status;
@@ -163,7 +163,7 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
* Allocate DMA
*/
queue_for_each(rt2x00dev, queue) {
- status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
+ status = rt2x00mmio_alloc_queue_dma(rt2x00dev, queue);
if (status)
goto exit;
}
@@ -175,8 +175,8 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
rt2x00dev->ops->lib->irq_handler,
IRQF_SHARED, rt2x00dev->name, rt2x00dev);
if (status) {
- ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
- rt2x00dev->irq, status);
+ rt2x00_err(rt2x00dev, "IRQ %d allocation failed (error %d)\n",
+ rt2x00dev->irq, status);
goto exit;
}
@@ -184,13 +184,13 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
exit:
queue_for_each(rt2x00dev, queue)
- rt2x00pci_free_queue_dma(rt2x00dev, queue);
+ rt2x00mmio_free_queue_dma(rt2x00dev, queue);
return status;
}
-EXPORT_SYMBOL_GPL(rt2x00pci_initialize);
+EXPORT_SYMBOL_GPL(rt2x00mmio_initialize);
-void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
+void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
@@ -203,9 +203,9 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
* Free DMA
*/
queue_for_each(rt2x00dev, queue)
- rt2x00pci_free_queue_dma(rt2x00dev, queue);
+ rt2x00mmio_free_queue_dma(rt2x00dev, queue);
}
-EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
+EXPORT_SYMBOL_GPL(rt2x00mmio_uninitialize);
/*
* rt2x00mmio module information.
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.h b/drivers/net/wireless/rt2x00/rt2x00mmio.h
index 4ecaf60175bf..cda3dbcf7ead 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mmio.h
+++ b/drivers/net/wireless/rt2x00/rt2x00mmio.h
@@ -31,37 +31,37 @@
/*
* Register access.
*/
-static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 *value)
+static inline void rt2x00mmio_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 *value)
{
*value = readl(rt2x00dev->csr.base + offset);
}
-static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- void *value, const u32 length)
+static inline void rt2x00mmio_register_multiread(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ void *value, const u32 length)
{
memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
}
-static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 value)
+static inline void rt2x00mmio_register_write(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 value)
{
writel(value, rt2x00dev->csr.base + offset);
}
-static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- const void *value,
- const u32 length)
+static inline void rt2x00mmio_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const void *value,
+ const u32 length)
{
__iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2);
}
/**
- * rt2x00pci_regbusy_read - Read from register with busy check
+ * rt2x00mmio_regbusy_read - Read from register with busy check
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
* @field: Field to check if register is busy
@@ -73,47 +73,47 @@ static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
* is not read after a certain timeout, this function will return
* FALSE.
*/
-int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- const struct rt2x00_field32 field,
- u32 *reg);
+int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const struct rt2x00_field32 field,
+ u32 *reg);
/**
- * struct queue_entry_priv_pci: Per entry PCI specific information
+ * struct queue_entry_priv_mmio: Per entry PCI specific information
*
* @desc: Pointer to device descriptor
* @desc_dma: DMA pointer to &desc.
* @data: Pointer to device's entry memory.
* @data_dma: DMA pointer to &data.
*/
-struct queue_entry_priv_pci {
+struct queue_entry_priv_mmio {
__le32 *desc;
dma_addr_t desc_dma;
};
/**
- * rt2x00pci_rxdone - Handle RX done events
+ * rt2x00mmio_rxdone - Handle RX done events
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
*
* Returns true if there are still rx frames pending and false if all
* pending rx frames were processed.
*/
-bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
+bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev);
/**
- * rt2x00pci_flush_queue - Flush data queue
+ * rt2x00mmio_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);
+void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop);
/*
* Device initialization handlers.
*/
-int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev);
-void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
+int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev);
+void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev);
#endif /* RT2X00MMIO_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index e87865e33113..dc49e525ae5e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -68,7 +68,7 @@ static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev)
return 0;
exit:
- ERROR_PROBE("Failed to allocate registers.\n");
+ rt2x00_probe_err("Failed to allocate registers\n");
rt2x00pci_free_reg(rt2x00dev);
@@ -84,30 +84,30 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
retval = pci_enable_device(pci_dev);
if (retval) {
- ERROR_PROBE("Enable device failed.\n");
+ rt2x00_probe_err("Enable device failed\n");
return retval;
}
retval = pci_request_regions(pci_dev, pci_name(pci_dev));
if (retval) {
- ERROR_PROBE("PCI request regions failed.\n");
+ rt2x00_probe_err("PCI request regions failed\n");
goto exit_disable_device;
}
pci_set_master(pci_dev);
if (pci_set_mwi(pci_dev))
- ERROR_PROBE("MWI not available.\n");
+ rt2x00_probe_err("MWI not available\n");
if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) {
- ERROR_PROBE("PCI DMA not supported.\n");
+ rt2x00_probe_err("PCI DMA not supported\n");
retval = -EIO;
goto exit_release_regions;
}
hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
if (!hw) {
- ERROR_PROBE("Failed to allocate hardware.\n");
+ rt2x00_probe_err("Failed to allocate hardware\n");
retval = -ENOMEM;
goto exit_release_regions;
}
@@ -207,7 +207,7 @@ int rt2x00pci_resume(struct pci_dev *pci_dev)
if (pci_set_power_state(pci_dev, PCI_D0) ||
pci_enable_device(pci_dev)) {
- ERROR(rt2x00dev, "Failed to resume device.\n");
+ rt2x00_err(rt2x00dev, "Failed to resume device\n");
return -EIO;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 952a0490eb17..2c12311467a9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -35,7 +35,8 @@
struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct data_queue *queue = entry->queue;
+ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
struct sk_buff *skb;
struct skb_frame_desc *skbdesc;
unsigned int frame_size;
@@ -46,7 +47,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp)
* The frame size includes descriptor size, because the
* hardware directly receive the frame into the skbuffer.
*/
- frame_size = entry->queue->data_size + entry->queue->desc_size;
+ frame_size = queue->data_size + queue->desc_size + queue->winfo_size;
/*
* The payload should be aligned to a 4-byte boundary,
@@ -531,10 +532,10 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,
*/
if (unlikely(rt2x00dev->ops->lib->get_entry_state &&
rt2x00dev->ops->lib->get_entry_state(entry))) {
- ERROR(rt2x00dev,
- "Corrupt queue %d, accessing entry which is not ours.\n"
- "Please file bug report to %s.\n",
- entry->queue->qid, DRV_PROJECT);
+ rt2x00_err(rt2x00dev,
+ "Corrupt queue %d, accessing entry which is not ours\n"
+ "Please file bug report to %s\n",
+ entry->queue->qid, DRV_PROJECT);
return -EINVAL;
}
@@ -698,8 +699,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
spin_lock(&queue->tx_lock);
if (unlikely(rt2x00queue_full(queue))) {
- ERROR(queue->rt2x00dev,
- "Dropping frame due to full tx queue %d.\n", queue->qid);
+ rt2x00_err(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n",
+ queue->qid);
ret = -ENOBUFS;
goto out;
}
@@ -708,10 +709,10 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
&entry->flags))) {
- ERROR(queue->rt2x00dev,
- "Arrived at non-free entry in the non-full queue %d.\n"
- "Please file bug report to %s.\n",
- queue->qid, DRV_PROJECT);
+ rt2x00_err(queue->rt2x00dev,
+ "Arrived at non-free entry in the non-full queue %d\n"
+ "Please file bug report to %s\n",
+ queue->qid, DRV_PROJECT);
ret = -EINVAL;
goto out;
}
@@ -842,9 +843,9 @@ bool rt2x00queue_for_each_entry(struct data_queue *queue,
unsigned int i;
if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) {
- ERROR(queue->rt2x00dev,
- "Entry requested from invalid index range (%d - %d)\n",
- start, end);
+ rt2x00_err(queue->rt2x00dev,
+ "Entry requested from invalid index range (%d - %d)\n",
+ start, end);
return true;
}
@@ -891,8 +892,8 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
unsigned long irqflags;
if (unlikely(index >= Q_INDEX_MAX)) {
- ERROR(queue->rt2x00dev,
- "Entry requested from invalid index type (%d)\n", index);
+ rt2x00_err(queue->rt2x00dev, "Entry requested from invalid index type (%d)\n",
+ index);
return NULL;
}
@@ -912,8 +913,8 @@ void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
unsigned long irqflags;
if (unlikely(index >= Q_INDEX_MAX)) {
- ERROR(queue->rt2x00dev,
- "Index change on invalid index type (%d)\n", index);
+ rt2x00_err(queue->rt2x00dev,
+ "Index change on invalid index type (%d)\n", index);
return;
}
@@ -1073,7 +1074,8 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
* The queue flush has failed...
*/
if (unlikely(!rt2x00queue_empty(queue)))
- WARNING(queue->rt2x00dev, "Queue %d failed to flush\n", queue->qid);
+ rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n",
+ queue->qid);
/*
* Restore the queue to the previous status
@@ -1172,6 +1174,7 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue,
queue->threshold = DIV_ROUND_UP(qdesc->entry_num, 10);
queue->data_size = qdesc->data_size;
queue->desc_size = qdesc->desc_size;
+ queue->winfo_size = qdesc->winfo_size;
/*
* Allocate all queue entries.
@@ -1262,7 +1265,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
return 0;
exit:
- ERROR(rt2x00dev, "Queue entries allocation failed.\n");
+ rt2x00_err(rt2x00dev, "Queue entries allocation failed\n");
rt2x00queue_uninitialize(rt2x00dev);
@@ -1314,7 +1317,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
queue = kcalloc(rt2x00dev->data_queues, sizeof(*queue), GFP_KERNEL);
if (!queue) {
- ERROR(rt2x00dev, "Queue allocation failed.\n");
+ rt2x00_err(rt2x00dev, "Queue allocation failed\n");
return -ENOMEM;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 3d0137193da0..4a7b34e9261b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -479,7 +479,8 @@ struct data_queue {
unsigned short cw_max;
unsigned short data_size;
- unsigned short desc_size;
+ unsigned char desc_size;
+ unsigned char winfo_size;
unsigned short usb_endpoint;
unsigned short usb_maxpacket;
@@ -499,7 +500,8 @@ struct data_queue {
struct data_queue_desc {
unsigned short entry_num;
unsigned short data_size;
- unsigned short desc_size;
+ unsigned char desc_size;
+ unsigned char winfo_size;
unsigned short priv_size;
};
diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c
index 2aa5c38022f3..9271a5fce0a8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00soc.c
+++ b/drivers/net/wireless/rt2x00/rt2x00soc.c
@@ -68,7 +68,7 @@ static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev)
return 0;
exit:
- ERROR_PROBE("Failed to allocate registers.\n");
+ rt2x00_probe_err("Failed to allocate registers\n");
rt2x00soc_free_reg(rt2x00dev);
return -ENOMEM;
@@ -82,7 +82,7 @@ int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)
hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
if (!hw) {
- ERROR_PROBE("Failed to allocate hardware.\n");
+ rt2x00_probe_err("Failed to allocate hardware\n");
return -ENOMEM;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 5e50d4ff9d21..88289873c0cf 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -70,9 +70,9 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
}
}
- ERROR(rt2x00dev,
- "Vendor Request 0x%02x failed for offset 0x%04x with error %d.\n",
- request, offset, status);
+ rt2x00_err(rt2x00dev,
+ "Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",
+ request, offset, status);
return status;
}
@@ -91,7 +91,7 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
* Check for Cache availability.
*/
if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) {
- ERROR(rt2x00dev, "CSR cache not available.\n");
+ rt2x00_err(rt2x00dev, "CSR cache not available\n");
return -ENOMEM;
}
@@ -157,8 +157,8 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "Indirect register access failed: "
- "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+ rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n",
+ offset, *reg);
*reg = ~0;
return 0;
@@ -307,7 +307,7 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data)
status = skb_padto(entry->skb, length);
if (unlikely(status)) {
/* TODO: report something more appropriate than IO_FAILED. */
- WARNING(rt2x00dev, "TX SKB padding error, out of memory\n");
+ rt2x00_warn(rt2x00dev, "TX SKB padding error, out of memory\n");
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
rt2x00lib_dmadone(entry);
@@ -520,8 +520,8 @@ EXPORT_SYMBOL_GPL(rt2x00usb_flush_queue);
static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
{
- WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
- " invoke forced forced reset\n", queue->qid);
+ rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n",
+ queue->qid);
rt2x00queue_flush_queue(queue, true);
}
@@ -622,7 +622,7 @@ static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
* At least 1 endpoint for RX and 1 endpoint for TX must be available.
*/
if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) {
- ERROR(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
+ rt2x00_err(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
return -EPIPE;
}
@@ -775,7 +775,7 @@ static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev)
return 0;
exit:
- ERROR_PROBE("Failed to allocate registers.\n");
+ rt2x00_probe_err("Failed to allocate registers\n");
rt2x00usb_free_reg(rt2x00dev);
@@ -795,7 +795,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
if (!hw) {
- ERROR_PROBE("Failed to allocate hardware.\n");
+ rt2x00_probe_err("Failed to allocate hardware\n");
retval = -ENOMEM;
goto exit_put_device;
}
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 9e3c8ff53e3f..0dc8180e251b 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -58,12 +58,12 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
* and we will print an error.
*/
#define WAIT_FOR_BBP(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
#define WAIT_FOR_RF(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
+ rt2x00mmio_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
#define WAIT_FOR_MCU(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \
- H2M_MAILBOX_CSR_OWNER, (__reg))
+ rt2x00mmio_regbusy_read((__dev), H2M_MAILBOX_CSR, \
+ H2M_MAILBOX_CSR_OWNER, (__reg))
static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
@@ -83,7 +83,7 @@ static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg);
}
mutex_unlock(&rt2x00dev->csr_mutex);
@@ -110,7 +110,7 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg);
WAIT_FOR_BBP(rt2x00dev, &reg);
}
@@ -138,7 +138,7 @@ static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR4, reg);
rt2x00_rf_write(rt2x00dev, word, value);
}
@@ -162,12 +162,12 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, HOST_CMD_CSR, &reg);
rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
- rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, reg);
}
mutex_unlock(&rt2x00dev->csr_mutex);
@@ -179,7 +179,7 @@ static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -201,15 +201,15 @@ static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
!!eeprom->reg_chip_select);
- rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg);
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
static const struct rt2x00debug rt61pci_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
- .read = rt2x00pci_register_read,
- .write = rt2x00pci_register_write,
+ .read = rt2x00mmio_register_read,
+ .write = rt2x00mmio_register_write,
.flags = RT2X00DEBUGFS_OFFSET,
.word_base = CSR_REG_BASE,
.word_size = sizeof(u32),
@@ -243,7 +243,7 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
return rt2x00_get_field32(reg, MAC_CSR13_VAL5);
}
@@ -294,10 +294,10 @@ static int rt61pci_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
- rt2x00pci_register_read(led->rt2x00dev, MAC_CSR14, &reg);
+ rt2x00mmio_register_read(led->rt2x00dev, MAC_CSR14, &reg);
rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
- rt2x00pci_register_write(led->rt2x00dev, MAC_CSR14, reg);
+ rt2x00mmio_register_write(led->rt2x00dev, MAC_CSR14, reg);
return 0;
}
@@ -339,7 +339,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
*/
mask = (0xf << crypto->bssidx);
- rt2x00pci_register_read(rt2x00dev, SEC_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
reg &= mask;
if (reg && reg == mask)
@@ -358,8 +358,8 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
sizeof(key_entry.rx_mic));
reg = SHARED_KEY_ENTRY(key->hw_key_idx);
- rt2x00pci_register_multiwrite(rt2x00dev, reg,
- &key_entry, sizeof(key_entry));
+ rt2x00mmio_register_multiwrite(rt2x00dev, reg,
+ &key_entry, sizeof(key_entry));
/*
* The cipher types are stored over 2 registers.
@@ -372,16 +372,16 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
field.bit_offset = (3 * key->hw_key_idx);
field.bit_mask = 0x7 << field.bit_offset;
- rt2x00pci_register_read(rt2x00dev, SEC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR1, &reg);
rt2x00_set_field32(&reg, field, crypto->cipher);
- rt2x00pci_register_write(rt2x00dev, SEC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, reg);
} else {
field.bit_offset = (3 * (key->hw_key_idx - 8));
field.bit_mask = 0x7 << field.bit_offset;
- rt2x00pci_register_read(rt2x00dev, SEC_CSR5, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR5, &reg);
rt2x00_set_field32(&reg, field, crypto->cipher);
- rt2x00pci_register_write(rt2x00dev, SEC_CSR5, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, reg);
}
/*
@@ -404,12 +404,12 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
*/
mask = 1 << key->hw_key_idx;
- rt2x00pci_register_read(rt2x00dev, SEC_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, &reg);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
reg &= ~mask;
- rt2x00pci_register_write(rt2x00dev, SEC_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, reg);
return 0;
}
@@ -433,10 +433,10 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
* When both registers are full, we drop the key.
* Otherwise, we use the first invalid entry.
*/
- rt2x00pci_register_read(rt2x00dev, SEC_CSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
if (reg && reg == ~0) {
key->hw_key_idx = 32;
- rt2x00pci_register_read(rt2x00dev, SEC_CSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
if (reg && reg == ~0)
return -ENOSPC;
}
@@ -458,21 +458,21 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
addr_entry.cipher = crypto->cipher;
reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
- rt2x00pci_register_multiwrite(rt2x00dev, reg,
- &key_entry, sizeof(key_entry));
+ rt2x00mmio_register_multiwrite(rt2x00dev, reg,
+ &key_entry, sizeof(key_entry));
reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
- rt2x00pci_register_multiwrite(rt2x00dev, reg,
- &addr_entry, sizeof(addr_entry));
+ rt2x00mmio_register_multiwrite(rt2x00dev, reg,
+ &addr_entry, sizeof(addr_entry));
/*
* Enable pairwise lookup table for given BSS idx.
* Without this, received frames will not be decrypted
* by the hardware.
*/
- rt2x00pci_register_read(rt2x00dev, SEC_CSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR4, &reg);
reg |= (1 << crypto->bssidx);
- rt2x00pci_register_write(rt2x00dev, SEC_CSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR4, reg);
/*
* The driver does not support the IV/EIV generation
@@ -495,21 +495,21 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
if (key->hw_key_idx < 32) {
mask = 1 << key->hw_key_idx;
- rt2x00pci_register_read(rt2x00dev, SEC_CSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, &reg);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
reg &= ~mask;
- rt2x00pci_register_write(rt2x00dev, SEC_CSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR2, reg);
} else {
mask = 1 << (key->hw_key_idx - 32);
- rt2x00pci_register_read(rt2x00dev, SEC_CSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, &reg);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
reg &= ~mask;
- rt2x00pci_register_write(rt2x00dev, SEC_CSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR3, reg);
}
return 0;
@@ -526,7 +526,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
* and broadcast frames will always be accepted since
* there is no filter for it at this time.
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
@@ -544,7 +544,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
!(filter_flags & FIF_CONTROL));
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
}
static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
@@ -558,9 +558,9 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
/*
* Enable synchronisation.
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
}
if (flags & CONFIG_UPDATE_MAC) {
@@ -568,8 +568,8 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
conf->mac[1] = cpu_to_le32(reg);
- rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2,
- conf->mac, sizeof(conf->mac));
+ rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR2,
+ conf->mac, sizeof(conf->mac));
}
if (flags & CONFIG_UPDATE_BSSID) {
@@ -577,8 +577,9 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
conf->bssid[1] = cpu_to_le32(reg);
- rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4,
- conf->bssid, sizeof(conf->bssid));
+ rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR4,
+ conf->bssid,
+ sizeof(conf->bssid));
}
}
@@ -588,40 +589,40 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
!!erp->short_preamble);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg);
}
if (changed & BSS_CHANGED_BASIC_RATES)
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR5,
- erp->basic_rates);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR5,
+ erp->basic_rates);
if (changed & BSS_CHANGED_BEACON_INT) {
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
erp->beacon_int * 16);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
}
if (changed & BSS_CHANGED_ERP_SLOT) {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR8, &reg);
rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR8, reg);
}
}
@@ -714,7 +715,7 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
rt2x00_set_field32(&reg, MAC_CSR13_DIR4, 0);
rt2x00_set_field32(&reg, MAC_CSR13_VAL4, p1);
@@ -722,7 +723,7 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MAC_CSR13_DIR3, 0);
rt2x00_set_field32(&reg, MAC_CSR13_VAL3, !p2);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg);
}
static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
@@ -821,14 +822,14 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
- rt2x00pci_register_read(rt2x00dev, PHY_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, PHY_CSR0, &reg);
rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR0, reg);
if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325))
rt61pci_config_antenna_5x(rt2x00dev, ant);
@@ -848,7 +849,7 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
u16 eeprom;
short lna_gain = 0;
- if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
+ if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) {
if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
lna_gain += 14;
@@ -928,7 +929,7 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, &reg);
rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1);
rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_RATE_STEP, 0);
rt2x00_set_field32(&reg, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0);
@@ -936,7 +937,7 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
libconf->conf->long_frame_max_tx_count);
rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
libconf->conf->short_frame_max_tx_count);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg);
}
static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
@@ -948,7 +949,7 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (state == STATE_SLEEP) {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN,
rt2x00dev->beacon_int - 10);
rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP,
@@ -957,27 +958,29 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
/* We must first disable autowake before it can be enabled */
rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
- rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000005);
- rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c);
- rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060);
+ rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR,
+ 0x00000005);
+ rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c);
+ rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060);
rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0);
} else {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR11, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, &reg);
rt2x00_set_field32(&reg, MAC_CSR11_DELAY_AFTER_TBCN, 0);
rt2x00_set_field32(&reg, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);
rt2x00_set_field32(&reg, MAC_CSR11_AUTOWAKE, 0);
rt2x00_set_field32(&reg, MAC_CSR11_WAKEUP_LATENCY, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);
- rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
- rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018);
- rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020);
+ rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR,
+ 0x00000007);
+ rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018);
+ rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020);
rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
}
@@ -1013,13 +1016,13 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt2x00pci_register_read(rt2x00dev, STA_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
- rt2x00pci_register_read(rt2x00dev, STA_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
}
@@ -1138,16 +1141,16 @@ static void rt61pci_start_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
break;
default:
break;
@@ -1161,24 +1164,24 @@ static void rt61pci_kick_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_VI:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BE:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BK:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
default:
break;
@@ -1192,36 +1195,36 @@ static void rt61pci_stop_queue(struct data_queue *queue)
switch (queue->qid) {
case QID_AC_VO:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_VI:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BE:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BK:
- rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_RX:
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
/*
* Wait for possibly running tbtt tasklets.
@@ -1299,14 +1302,14 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
* Wait for stable hardware.
*/
for (i = 0; i < 100; i++) {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
if (reg)
break;
msleep(1);
}
if (!reg) {
- ERROR(rt2x00dev, "Unstable hardware.\n");
+ rt2x00_err(rt2x00dev, "Unstable hardware\n");
return -EBUSY;
}
@@ -1315,10 +1318,10 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
*/
reg = 0;
rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 1);
- rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
- rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
- rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, 0);
+ rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
+ rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, 0);
/*
* Write firmware to device.
@@ -1326,26 +1329,26 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
reg = 0;
rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 1);
rt2x00_set_field32(&reg, MCU_CNTL_CSR_SELECT_BANK, 1);
- rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
- rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
- data, len);
+ rt2x00mmio_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+ data, len);
rt2x00_set_field32(&reg, MCU_CNTL_CSR_SELECT_BANK, 0);
- rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
rt2x00_set_field32(&reg, MCU_CNTL_CSR_RESET, 0);
- rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);
for (i = 0; i < 100; i++) {
- rt2x00pci_register_read(rt2x00dev, MCU_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MCU_CNTL_CSR, &reg);
if (rt2x00_get_field32(reg, MCU_CNTL_CSR_READY))
break;
msleep(1);
}
if (i == 100) {
- ERROR(rt2x00dev, "MCU Control register not ready.\n");
+ rt2x00_err(rt2x00dev, "MCU Control register not ready\n");
return -EBUSY;
}
@@ -1360,16 +1363,16 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
reg = 0;
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
return 0;
}
@@ -1379,7 +1382,7 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,
*/
static bool rt61pci_get_entry_state(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word;
if (entry->queue->qid == QID_RX) {
@@ -1396,7 +1399,7 @@ static bool rt61pci_get_entry_state(struct queue_entry *entry)
static void rt61pci_clear_entry(struct queue_entry *entry)
{
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
@@ -1419,13 +1422,13 @@ static void rt61pci_clear_entry(struct queue_entry *entry)
static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
{
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
u32 reg;
/*
* Initialize registers.
*/
- rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR0, &reg);
rt2x00_set_field32(&reg, TX_RING_CSR0_AC0_RING_SIZE,
rt2x00dev->tx[0].limit);
rt2x00_set_field32(&reg, TX_RING_CSR0_AC1_RING_SIZE,
@@ -1434,67 +1437,67 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
rt2x00dev->tx[2].limit);
rt2x00_set_field32(&reg, TX_RING_CSR0_AC3_RING_SIZE,
rt2x00dev->tx[3].limit);
- rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR0, reg);
- rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR1, &reg);
rt2x00_set_field32(&reg, TX_RING_CSR1_TXD_SIZE,
rt2x00dev->tx[0].desc_size / 4);
- rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR1, reg);
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, AC0_BASE_CSR, reg);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, AC1_BASE_CSR, reg);
entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, AC2_BASE_CSR, reg);
entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, AC3_BASE_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RX_RING_CSR, &reg);
rt2x00_set_field32(&reg, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);
rt2x00_set_field32(&reg, RX_RING_CSR_RXD_SIZE,
rt2x00dev->rx->desc_size / 4);
rt2x00_set_field32(&reg, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4);
- rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RX_RING_CSR, reg);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RX_BASE_CSR, &reg);
rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RX_BASE_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC0, 2);
rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC1, 2);
rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC2, 2);
rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC3, 2);
- rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC0, 1);
rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
- rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, RX_CNTL_CSR_LOAD_RXD, 1);
- rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
return 0;
}
@@ -1503,13 +1506,13 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR1, &reg);
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1, 30); /* Rssi */
@@ -1518,12 +1521,12 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3, 30); /* Rssi */
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR1, reg);
/*
* CCK TXD BBP registers
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR2, &reg);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0, 13);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1, 12);
@@ -1532,76 +1535,76 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3, 10);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR2, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR2, reg);
/*
* OFDM TXD BBP registers
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR3, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR3, &reg);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0, 7);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1, 6);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2, 5);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR3, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR3, reg);
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR7, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR7, &reg);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_6MBS, 59);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_9MBS, 53);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_12MBS, 49);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_18MBS, 46);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR7, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR7, reg);
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR8, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR8, &reg);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_24MBS, 44);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_36MBS, 42);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_48MBS, 42);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR8, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR8, reg);
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, &reg);
rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x0000071c);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR10, 0x0000071c);
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
return -EBUSY;
- rt2x00pci_register_write(rt2x00dev, MAC_CSR13, 0x0000e000);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, 0x0000e000);
/*
* Invalidate all Shared Keys (SEC_CSR0),
* and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
*/
- rt2x00pci_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
- rt2x00pci_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
- rt2x00pci_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
+ rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR1, 0x000023b0);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR5, 0x060a100c);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR7, 0x00000a08);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR1, 0x000023b0);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR5, 0x060a100c);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
+ rt2x00mmio_register_write(rt2x00dev, PHY_CSR7, 0x00000a08);
- rt2x00pci_register_write(rt2x00dev, PCI_CFG_CSR, 0x28ca4404);
+ rt2x00mmio_register_write(rt2x00dev, PCI_CFG_CSR, 0x28ca4404);
- rt2x00pci_register_write(rt2x00dev, TEST_MODE_CSR, 0x00000200);
+ rt2x00mmio_register_write(rt2x00dev, TEST_MODE_CSR, 0x00000200);
- rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
+ rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);
/*
* Clear all beacons
@@ -1609,36 +1612,36 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
* the first byte since that byte contains the VALID and OWNER
* bits which (when set to 0) will invalidate the entire beacon.
*/
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+ rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+ rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+ rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+ rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
/*
* We must clear the error counters.
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt2x00pci_register_read(rt2x00dev, STA_CSR0, &reg);
- rt2x00pci_register_read(rt2x00dev, STA_CSR1, &reg);
- rt2x00pci_register_read(rt2x00dev, STA_CSR2, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR2, &reg);
/*
* Reset MAC and BBP registers.
*/
- rt2x00pci_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);
return 0;
}
@@ -1655,7 +1658,7 @@ static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -1722,11 +1725,11 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
+ rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
}
/*
@@ -1735,15 +1738,15 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_0, mask);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_1, mask);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_2, mask);
@@ -1753,7 +1756,7 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_6, mask);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_7, mask);
rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_TWAKEUP, mask);
- rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
@@ -1783,9 +1786,9 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Enable RX.
*/
- rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, RX_CNTL_CSR_ENABLE_RX_DMA, 1);
- rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);
return 0;
}
@@ -1795,7 +1798,7 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Disable power
*/
- rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
}
static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
@@ -1806,10 +1809,10 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
put_to_sleep = (state != STATE_AWAKE);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR12, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg);
rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);
/*
* Device is not guaranteed to be in the requested state yet.
@@ -1817,11 +1820,11 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR12, &reg2);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, &reg2);
state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);
if (state == !put_to_sleep)
return 0;
- rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);
msleep(10);
}
@@ -1856,8 +1859,8 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -1869,7 +1872,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
__le32 *txd = entry_priv->desc;
u32 word;
@@ -1967,7 +1970,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
struct txentry_desc *txdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
unsigned int beacon_base;
unsigned int padding_len;
u32 orig_reg, reg;
@@ -1976,10 +1979,10 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
orig_reg = reg;
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
/*
* Write the TX descriptor for the beacon.
@@ -1996,19 +1999,19 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
*/
padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
if (padding_len && skb_pad(entry->skb, padding_len)) {
- ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+ rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
/* skb freed by skb_pad() on failure */
entry->skb = NULL;
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
return;
}
beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
- rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
- entry_priv->desc, TXINFO_SIZE);
- rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE,
- entry->skb->data,
- entry->skb->len + padding_len);
+ rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base,
+ entry_priv->desc, TXINFO_SIZE);
+ rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE,
+ entry->skb->data,
+ entry->skb->len + padding_len);
/*
* Enable beaconing again.
@@ -2016,10 +2019,10 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
* For Wi-Fi faily generated beacons between participating
* stations. Set TBTT phase adaptive adjustment step to 8us.
*/
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
/*
* Clean up beacon skb.
@@ -2037,21 +2040,21 @@ static void rt61pci_clear_beacon(struct queue_entry *entry)
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
/*
* Clear beacon.
*/
- rt2x00pci_register_write(rt2x00dev,
- HW_BEACON_OFFSET(entry->entry_idx), 0);
+ rt2x00mmio_register_write(rt2x00dev,
+ HW_BEACON_OFFSET(entry->entry_idx), 0);
/*
* Enable beaconing again.
*/
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);
}
/*
@@ -2089,7 +2092,7 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct queue_entry_priv_mmio *entry_priv = entry->priv_data;
u32 word0;
u32 word1;
@@ -2155,7 +2158,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
struct data_queue *queue;
struct queue_entry *entry;
struct queue_entry *entry_done;
- struct queue_entry_priv_pci *entry_priv;
+ struct queue_entry_priv_mmio *entry_priv;
struct txdone_entry_desc txdesc;
u32 word;
u32 reg;
@@ -2173,7 +2176,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
* tx ring size for now.
*/
for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
- rt2x00pci_register_read(rt2x00dev, STA_CSR4, &reg);
+ rt2x00mmio_register_read(rt2x00dev, STA_CSR4, &reg);
if (!rt2x00_get_field32(reg, STA_CSR4_VALID))
break;
@@ -2207,9 +2210,8 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
/* Catch up.
* Just report any entries we missed as failed.
*/
- WARNING(rt2x00dev,
- "TX status report missed for entry %d\n",
- entry_done->entry_idx);
+ rt2x00_warn(rt2x00dev, "TX status report missed for entry %d\n",
+ entry_done->entry_idx);
rt2x00lib_txdone_noinfo(entry_done, TXDONE_UNKNOWN);
entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
@@ -2260,9 +2262,9 @@ static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, irq_field, 0);
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -2278,9 +2280,9 @@ static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev,
*/
spin_lock_irq(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, irq_field, 0);
- rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
@@ -2304,7 +2306,7 @@ static void rt61pci_tbtt_tasklet(unsigned long data)
static void rt61pci_rxdone_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
- if (rt2x00pci_rxdone(rt2x00dev))
+ if (rt2x00mmio_rxdone(rt2x00dev))
tasklet_schedule(&rt2x00dev->rxdone_tasklet);
else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE);
@@ -2314,8 +2316,8 @@ static void rt61pci_autowake_tasklet(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
rt61pci_wakeup(rt2x00dev);
- rt2x00pci_register_write(rt2x00dev,
- M2H_CMD_DONE_CSR, 0xffffffff);
+ rt2x00mmio_register_write(rt2x00dev,
+ M2H_CMD_DONE_CSR, 0xffffffff);
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP);
}
@@ -2330,11 +2332,11 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
* Get the interrupt sources & saved to local variable.
* Write register value back to clear pending interrupts.
*/
- rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
- rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
+ rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
+ rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
- rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
if (!reg && !reg_mcu)
return IRQ_NONE;
@@ -2371,13 +2373,13 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
*/
spin_lock(&rt2x00dev->irqmask_lock);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, &reg);
reg |= mask;
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
reg |= mask_mcu;
- rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
spin_unlock(&rt2x00dev->irqmask_lock);
@@ -2395,7 +2397,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
u8 *mac;
s8 value;
- rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
eeprom.data = rt2x00dev;
eeprom.register_read = rt61pci_eepromregister_read;
@@ -2416,7 +2418,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -2431,7 +2433,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5225);
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
- EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
@@ -2444,7 +2446,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
- EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
@@ -2452,7 +2454,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,
LED_MODE_DEFAULT);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word);
- EEPROM(rt2x00dev, "Led: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
@@ -2460,7 +2462,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
- EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
@@ -2468,7 +2470,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
- EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
} else {
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
if (value < -10 || value > 10)
@@ -2484,7 +2486,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
- EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
} else {
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
if (value < -10 || value > 10)
@@ -2513,7 +2515,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, &reg);
rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
@@ -2521,7 +2523,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
!rt2x00_rf(rt2x00dev, RF5325) &&
!rt2x00_rf(rt2x00dev, RF2527) &&
!rt2x00_rf(rt2x00dev, RF2529)) {
- ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
return -ENODEV;
}
@@ -2838,7 +2840,7 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* Disable power saving.
*/
- rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
+ rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);
/*
* Allocate eeprom data.
@@ -2855,9 +2857,9 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
* Enable rfkill polling by setting GPIO direction of the
* rfkill switch GPIO pin correctly.
*/
- rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
+ rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, &reg);
rt2x00_set_field32(&reg, MAC_CSR13_DIR5, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
+ rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg);
/*
* Initialize hw specifications.
@@ -2927,25 +2929,25 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw,
field.bit_offset = (queue_idx & 1) * 16;
field.bit_mask = 0xffff << field.bit_offset;
- rt2x00pci_register_read(rt2x00dev, offset, &reg);
+ rt2x00mmio_register_read(rt2x00dev, offset, &reg);
rt2x00_set_field32(&reg, field, queue->txop);
- rt2x00pci_register_write(rt2x00dev, offset, reg);
+ rt2x00mmio_register_write(rt2x00dev, offset, reg);
/* Update WMM registers */
field.bit_offset = queue_idx * 4;
field.bit_mask = 0xf << field.bit_offset;
- rt2x00pci_register_read(rt2x00dev, AIFSN_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, AIFSN_CSR, &reg);
rt2x00_set_field32(&reg, field, queue->aifs);
- rt2x00pci_register_write(rt2x00dev, AIFSN_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, AIFSN_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, CWMIN_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CWMIN_CSR, &reg);
rt2x00_set_field32(&reg, field, queue->cw_min);
- rt2x00pci_register_write(rt2x00dev, CWMIN_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, CWMIN_CSR, reg);
- rt2x00pci_register_read(rt2x00dev, CWMAX_CSR, &reg);
+ rt2x00mmio_register_read(rt2x00dev, CWMAX_CSR, &reg);
rt2x00_set_field32(&reg, field, queue->cw_max);
- rt2x00pci_register_write(rt2x00dev, CWMAX_CSR, reg);
+ rt2x00mmio_register_write(rt2x00dev, CWMAX_CSR, reg);
return 0;
}
@@ -2956,9 +2958,9 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
u64 tsf;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR13, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR13, &reg);
tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR12, &reg);
+ rt2x00mmio_register_read(rt2x00dev, TXRX_CSR12, &reg);
tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
return tsf;
@@ -2997,8 +2999,8 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.get_firmware_name = rt61pci_get_firmware_name,
.check_firmware = rt61pci_check_firmware,
.load_firmware = rt61pci_load_firmware,
- .initialize = rt2x00pci_initialize,
- .uninitialize = rt2x00pci_uninitialize,
+ .initialize = rt2x00mmio_initialize,
+ .uninitialize = rt2x00mmio_uninitialize,
.get_entry_state = rt61pci_get_entry_state,
.clear_entry = rt61pci_clear_entry,
.set_device_state = rt61pci_set_device_state,
@@ -3009,7 +3011,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,
+ .flush_queue = rt2x00mmio_flush_queue,
.write_tx_desc = rt61pci_write_tx_desc,
.write_beacon = rt61pci_write_beacon,
.clear_beacon = rt61pci_clear_beacon,
@@ -3027,21 +3029,21 @@ static const struct data_queue_desc rt61pci_queue_rx = {
.entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = RXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt61pci_queue_tx = {
.entry_num = 32,
.data_size = DATA_FRAME_SIZE,
.desc_size = TXD_DESC_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct data_queue_desc rt61pci_queue_bcn = {
.entry_num = 4,
.data_size = 0, /* No DMA required for beacons */
.desc_size = TXINFO_SIZE,
- .priv_size = sizeof(struct queue_entry_priv_pci),
+ .priv_size = sizeof(struct queue_entry_priv_mmio),
};
static const struct rt2x00_ops rt61pci_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 24eec66e9fd2..377e09bb0b81 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -739,7 +739,7 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
u16 eeprom;
short lna_gain = 0;
- if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
+ if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) {
if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
lna_gain += 14;
@@ -1122,7 +1122,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,
}
if (!reg) {
- ERROR(rt2x00dev, "Unstable hardware.\n");
+ rt2x00_err(rt2x00dev, "Unstable hardware\n");
return -EBUSY;
}
@@ -1139,7 +1139,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,
0, USB_MODE_FIRMWARE,
REGISTER_TIMEOUT_FIRMWARE);
if (status < 0) {
- ERROR(rt2x00dev, "Failed to write Firmware to device.\n");
+ rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");
return status;
}
@@ -1305,7 +1305,7 @@ static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");
return -EACCES;
}
@@ -1443,8 +1443,8 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
}
if (unlikely(retval))
- ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n",
- state, retval);
+ rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n",
+ state, retval);
return retval;
}
@@ -1567,7 +1567,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
*/
padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
if (padding_len && skb_pad(entry->skb, padding_len)) {
- ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+ rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n");
/* skb freed by skb_pad() on failure */
entry->skb = NULL;
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
@@ -1771,7 +1771,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
eth_random_addr(mac);
- EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+ rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1786,14 +1786,14 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5226);
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
- EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
- EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word);
@@ -1809,7 +1809,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,
LED_MODE_DEFAULT);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word);
- EEPROM(rt2x00dev, "Led: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
@@ -1817,7 +1817,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
- EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
@@ -1825,7 +1825,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
- EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
} else {
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
if (value < -10 || value > 10)
@@ -1841,7 +1841,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
- EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
+ rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
} else {
value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
if (value < -10 || value > 10)
@@ -1875,7 +1875,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) {
- ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");
return -ENODEV;
}
@@ -1883,7 +1883,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
!rt2x00_rf(rt2x00dev, RF2528) &&
!rt2x00_rf(rt2x00dev, RF5225) &&
!rt2x00_rf(rt2x00dev, RF2527)) {
- ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+ rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");
return -ENODEV;
}
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 1b3c2843221d..91a04e2b8ece 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -147,8 +147,8 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
signal = priv->rf->calc_rssi(agc, sq);
}
rx_status.signal = signal;
- rx_status.freq = dev->conf.channel->center_freq;
- rx_status.band = dev->conf.channel->band;
+ rx_status.freq = dev->conf.chandef.chan->center_freq;
+ rx_status.band = dev->conf.chandef.chan->band;
rx_status.mactime = le64_to_cpu(entry->tsft);
rx_status.flag |= RX_FLAG_MACTIME_START;
if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
diff --git a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c b/drivers/net/wireless/rtl818x/rtl8180/grf5101.c
index 5ee7589dd546..077ff92cc139 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/grf5101.c
@@ -82,7 +82,8 @@ static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
- int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ int channel =
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
u32 chan = channel - 1;
diff --git a/drivers/net/wireless/rtl818x/rtl8180/max2820.c b/drivers/net/wireless/rtl818x/rtl8180/max2820.c
index 667b3363d437..4715000c94dd 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/max2820.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/max2820.c
@@ -95,7 +95,7 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev,
{
struct rtl8180_priv *priv = dev->priv;
int channel = conf ?
- ieee80211_frequency_to_channel(conf->channel->center_freq) : 1;
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq) : 1;
unsigned int chan_idx = channel - 1;
u32 txpw = priv->channels[chan_idx].hw_value & 0xFF;
u32 chan = max2820_chan[chan_idx];
diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c
index 7c4574ba9d75..cc2a5412c1f0 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c
@@ -719,7 +719,8 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
- int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ int chan =
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
if (priv->rf->init == rtl8225_rf_init)
rtl8225_rf_set_tx_power(dev, chan);
diff --git a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c b/drivers/net/wireless/rtl818x/rtl8180/sa2400.c
index 44771a6286af..b3ec40f6bd23 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/sa2400.c
@@ -105,7 +105,8 @@ static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8180_priv *priv = dev->priv;
- int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ int channel =
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
u32 chan = sa2400_chan[channel - 1];
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 4574bd213705..f49220e234b0 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -379,8 +379,8 @@ static void rtl8187_rx_cb(struct urb *urb)
rate = (flags >> 20) & 0xF;
skb_trim(skb, flags & 0x0FFF);
rx_status.rate_idx = rate;
- rx_status.freq = dev->conf.channel->center_freq;
- rx_status.band = dev->conf.channel->band;
+ rx_status.freq = dev->conf.chandef.chan->center_freq;
+ rx_status.band = dev->conf.chandef.chan->band;
rx_status.flag |= RX_FLAG_MACTIME_START;
if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c
index 908903f721f5..f0bf35fedbaf 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c
@@ -905,7 +905,8 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
struct ieee80211_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
- int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ int chan =
+ ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
if (priv->rf->init == rtl8225_rf_init)
rtl8225_rf_set_tx_power(dev, chan);
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index cac1fa912e8c..af59dd5718e1 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -722,7 +722,7 @@ int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
int rate_idx;
if (false == isht) {
- if (IEEE80211_BAND_2GHZ == hw->conf.channel->band) {
+ if (IEEE80211_BAND_2GHZ == hw->conf.chandef.chan->band) {
switch (desc_rate) {
case DESC92_RATE1M:
rate_idx = 0;
@@ -987,8 +987,8 @@ static bool addbareq_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (tid_data->agg.rx_agg_state == RTL_RX_AGG_START) {
skb_delba = rtl_make_del_ba(hw, hdr->addr2, hdr->addr3, tid);
if (skb_delba) {
- rx_status.freq = hw->conf.channel->center_freq;
- rx_status.band = hw->conf.channel->band;
+ rx_status.freq = hw->conf.chandef.chan->center_freq;
+ rx_status.band = hw->conf.chandef.chan->band;
rx_status.flag |= RX_FLAG_DECRYPTED;
rx_status.flag |= RX_FLAG_MACTIME_END;
rx_status.rate_idx = 0;
@@ -1593,7 +1593,7 @@ int rtl_send_smps_action(struct ieee80211_hw *hw,
sta_entry->mimo_ps = smps;
info->control.rates[0].idx = 0;
- info->band = hw->conf.channel->band;
+ info->band = hw->conf.chandef.chan->band;
rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc);
}
return 1;
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index 2201b5cee08f..ee84844be008 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -370,7 +370,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
- struct ieee80211_channel *channel = hw->conf.channel;
+ struct ieee80211_channel *channel = hw->conf.chandef.chan;
u8 wide_chan = (u8) channel->hw_value;
if (mac->act_scanning)
@@ -392,7 +392,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
*info for cisco1253 bw20, so we modify
*it here based on UPPER & LOWER
*/
- switch (hw->conf.channel_type) {
+ switch (cfg80211_get_chandef_type(&hw->conf.chandef)) {
case NL80211_CHAN_HT20:
case NL80211_CHAN_NO_HT:
/* SC */
@@ -450,7 +450,7 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
rtlpriv->cfg->ops->switch_channel(hw);
rtlpriv->cfg->ops->set_channel_access(hw);
rtlpriv->cfg->ops->set_bw_mode(hw,
- hw->conf.channel_type);
+ cfg80211_get_chandef_type(&hw->conf.chandef));
}
mutex_unlock(&rtlpriv->locks.conf_mutex);
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
index bcff49730a4e..b68cae3024fc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
@@ -1635,7 +1635,7 @@ static void _rtl8188e_read_power_value_fromprom(struct ieee80211_hw *hw,
if (pwr2g->index_cck_base[path][i] == 0xFF)
pwr2g->index_cck_base[path][i] = 0x2D;
}
- for (i = 0; i < MAX_CHNL_GROUP_24G-1; i++) {
+ for (i = 0; i < MAX_CHNL_GROUP_24G; i++) {
pwr2g->index_bw40_base[path][i] = hwinfo[eadr++];
if (pwr2g->index_bw40_base[path][i] == 0xFF)
pwr2g->index_bw40_base[path][i] = 0x2D;
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
index d075237add51..a8871d66d56a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
@@ -421,8 +421,8 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw,
RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD,
"Get Wakeup Packet!! WakeMatch =%d\n",
status->wake_match);
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (status->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index 926e2a34c766..d2d57a27a7c1 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -669,7 +669,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 = 0;
- u8 ofdm_index[2], ofdm_index_old[2], cck_index_old = 0;
+ u8 ofdm_index[2], ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
s8 cck_index = 0;
int i;
bool is2t = IS_92C_SERIAL(rtlhal->version);
@@ -717,7 +717,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
if (ele_d == (ofdmswing_table[i] &
MASKOFDM_D)) {
-
+ ofdm_index_old[1] = (u8) i;
RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
DBG_LOUD,
"Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index 65bf5fb97002..6ad23b413eb3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -363,8 +363,8 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
stats->is_cck = RX_HAL_IS_CCK_RATE(pdesc);
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size
+ stats->rx_bufshift);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index 710f7904ecdf..763cf1defab5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -324,8 +324,8 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
&& (GET_RX_DESC_FAGGR(pdesc) == 1));
stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (GET_RX_DESC_CRC32(pdesc))
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (!GET_RX_DESC_SWDEC(pdesc))
@@ -395,8 +395,8 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
stats.rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(rxdesc);
/* TODO: is center_freq changed when doing scan? */
/* TODO: Shall we add protection or just skip those two step? */
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (GET_RX_DESC_CRC32(rxdesc))
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (!GET_RX_DESC_SWDEC(rxdesc))
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
index 941080e03c06..b8ec718a0fab 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c
@@ -499,8 +499,8 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
&& (GET_RX_DESC_FAGGR(pdesc) == 1));
stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (GET_RX_DESC_CRC32(pdesc))
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (!GET_RX_DESC_SWDEC(pdesc))
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 960bc28cc51e..c7095118de6e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -281,8 +281,8 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
if (stats->hwerror)
return false;
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (stats->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
index 6c64365308d3..c72758d8f4ed 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
@@ -304,8 +304,8 @@ bool rtl8723ae_rx_query_desc(struct ieee80211_hw *hw,
status->is_cck = RTL8723E_RX_HAL_IS_CCK_RATE(status->rate);
- rx_status->freq = hw->conf.channel->center_freq;
- rx_status->band = hw->conf.channel->band;
+ rx_status->freq = hw->conf.chandef.chan->center_freq;
+ rx_status->band = hw->conf.chandef.chan->band;
if (status->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index bbbf68cf50a7..3291ffa95273 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -572,7 +572,8 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
int channel, ret = 0;
- channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ channel = ieee80211_frequency_to_channel(
+ conf->chandef.chan->center_freq);
wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
channel,
@@ -1223,7 +1224,7 @@ static int wl1251_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = wl->noise;
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c
index 7dc9f965037d..7485dbae8c4b 100644
--- a/drivers/net/wireless/ti/wl12xx/cmd.c
+++ b/drivers/net/wireless/ti/wl12xx/cmd.c
@@ -301,7 +301,7 @@ int wl12xx_cmd_channel_switch(struct wl1271 *wl,
}
cmd->role_id = wlvif->role_id;
- cmd->channel = ch_switch->channel->hw_value;
+ cmd->channel = ch_switch->chandef.chan->hw_value;
cmd->switch_time = ch_switch->count;
cmd->stop_tx = ch_switch->block_tx;
diff --git a/drivers/net/wireless/ti/wl18xx/cmd.c b/drivers/net/wireless/ti/wl18xx/cmd.c
index 1d1f6cc7a50a..7649c75cd68d 100644
--- a/drivers/net/wireless/ti/wl18xx/cmd.c
+++ b/drivers/net/wireless/ti/wl18xx/cmd.c
@@ -42,11 +42,11 @@ int wl18xx_cmd_channel_switch(struct wl1271 *wl,
}
cmd->role_id = wlvif->role_id;
- cmd->channel = ch_switch->channel->hw_value;
+ cmd->channel = ch_switch->chandef.chan->hw_value;
cmd->switch_time = ch_switch->count;
cmd->stop_tx = ch_switch->block_tx;
- switch (ch_switch->channel->band) {
+ switch (ch_switch->chandef.chan->band) {
case IEEE80211_BAND_2GHZ:
cmd->band = WLCORE_BAND_2_4GHZ;
break;
@@ -55,7 +55,7 @@ int wl18xx_cmd_channel_switch(struct wl1271 *wl,
break;
default:
wl1271_error("invalid channel switch band: %d",
- ch_switch->channel->band);
+ ch_switch->chandef.chan->band);
ret = -EINVAL;
goto out_free;
}
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index d10954c0c181..953111a502ee 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -4502,7 +4502,7 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = 0;
return 0;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 114364b5d466..c6208a7988e4 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -1156,10 +1156,10 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
spin_lock_irq(&mac->lock);
- mac->channel = conf->channel->hw_value;
+ mac->channel = conf->chandef.chan->hw_value;
spin_unlock_irq(&mac->lock);
- return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
+ return zd_chip_set_channel(&mac->chip, conf->chandef.chan->hw_value);
}
static void zd_beacon_done(struct zd_mac *mac)
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index e57034971ccc..4775d4e61b88 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -26,6 +26,16 @@ config NFC_WILINK
Say Y here to compile support for Texas Instrument's NFC WiLink driver
into the kernel or say M to compile it as module.
+config NFC_MEI_PHY
+ tristate "MEI bus NFC device support"
+ depends on INTEL_MEI_BUS_NFC && NFC_HCI
+ help
+ This adds support to use an mei bus nfc device. Select this if you
+ will use an HCI NFC driver for an NFC chip connected behind an
+ Intel's Management Engine chip.
+
+ If unsure, say N.
+
source "drivers/nfc/pn544/Kconfig"
source "drivers/nfc/microread/Kconfig"
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index a189ada0926a..aa6bd657ef40 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -6,5 +6,6 @@ obj-$(CONFIG_NFC_PN544) += pn544/
obj-$(CONFIG_NFC_MICROREAD) += microread/
obj-$(CONFIG_NFC_PN533) += pn533.o
obj-$(CONFIG_NFC_WILINK) += nfcwilink.o
+obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o
ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c
new file mode 100644
index 000000000000..b8f8abc422f0
--- /dev/null
+++ b/drivers/nfc/mei_phy.c
@@ -0,0 +1,164 @@
+/*
+ * MEI Library for mei bus nfc device access
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/nfc.h>
+
+#include "mei_phy.h"
+
+struct mei_nfc_hdr {
+ u8 cmd;
+ u8 status;
+ u16 req_id;
+ u32 reserved;
+ u16 data_size;
+} __attribute__((packed));
+
+#define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)
+
+#define MEI_DUMP_SKB_IN(info, skb) \
+do { \
+ pr_debug("%s:\n", info); \
+ print_hex_dump_debug("mei in : ", DUMP_PREFIX_OFFSET, \
+ 16, 1, (skb)->data, (skb)->len, false); \
+} while (0)
+
+#define MEI_DUMP_SKB_OUT(info, skb) \
+do { \
+ pr_debug("%s:\n", info); \
+ print_hex_dump_debug("mei out: ", DUMP_PREFIX_OFFSET, \
+ 16, 1, (skb)->data, (skb)->len, false); \
+} while (0)
+
+int nfc_mei_phy_enable(void *phy_id)
+{
+ int r;
+ struct nfc_mei_phy *phy = phy_id;
+
+ pr_info("%s\n", __func__);
+
+ if (phy->powered == 1)
+ return 0;
+
+ r = mei_cl_enable_device(phy->device);
+ if (r < 0) {
+ pr_err("MEI_PHY: Could not enable device\n");
+ return r;
+ }
+
+ phy->powered = 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nfc_mei_phy_enable);
+
+void nfc_mei_phy_disable(void *phy_id)
+{
+ struct nfc_mei_phy *phy = phy_id;
+
+ pr_info("%s\n", __func__);
+
+ mei_cl_disable_device(phy->device);
+
+ phy->powered = 0;
+}
+EXPORT_SYMBOL_GPL(nfc_mei_phy_disable);
+
+/*
+ * Writing a frame must not return the number of written bytes.
+ * It must return either zero for success, or <0 for error.
+ * In addition, it must not alter the skb
+ */
+static int nfc_mei_phy_write(void *phy_id, struct sk_buff *skb)
+{
+ struct nfc_mei_phy *phy = phy_id;
+ int r;
+
+ MEI_DUMP_SKB_OUT("mei frame sent", skb);
+
+ r = mei_cl_send(phy->device, skb->data, skb->len);
+ if (r > 0)
+ r = 0;
+
+ return r;
+}
+
+void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, void *context)
+{
+ struct nfc_mei_phy *phy = context;
+
+ if (phy->hard_fault != 0)
+ return;
+
+ if (events & BIT(MEI_CL_EVENT_RX)) {
+ struct sk_buff *skb;
+ int reply_size;
+
+ skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
+ if (!skb)
+ return;
+
+ reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ);
+ if (reply_size < MEI_NFC_HEADER_SIZE) {
+ kfree(skb);
+ return;
+ }
+
+ skb_put(skb, reply_size);
+ skb_pull(skb, MEI_NFC_HEADER_SIZE);
+
+ MEI_DUMP_SKB_IN("mei frame read", skb);
+
+ nfc_hci_recv_frame(phy->hdev, skb);
+ }
+}
+EXPORT_SYMBOL_GPL(nfc_mei_event_cb);
+
+struct nfc_phy_ops mei_phy_ops = {
+ .write = nfc_mei_phy_write,
+ .enable = nfc_mei_phy_enable,
+ .disable = nfc_mei_phy_disable,
+};
+EXPORT_SYMBOL_GPL(mei_phy_ops);
+
+struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device)
+{
+ struct nfc_mei_phy *phy;
+
+ phy = kzalloc(sizeof(struct nfc_mei_phy), GFP_KERNEL);
+ if (!phy)
+ return NULL;
+
+ phy->device = device;
+ mei_cl_set_drvdata(device, phy);
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(nfc_mei_phy_alloc);
+
+void nfc_mei_phy_free(struct nfc_mei_phy *phy)
+{
+ kfree(phy);
+}
+EXPORT_SYMBOL_GPL(nfc_mei_phy_free);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("mei bus NFC device interface");
diff --git a/drivers/nfc/mei_phy.h b/drivers/nfc/mei_phy.h
new file mode 100644
index 000000000000..d669900f8278
--- /dev/null
+++ b/drivers/nfc/mei_phy.h
@@ -0,0 +1,30 @@
+#ifndef __LOCAL_MEI_PHY_H_
+#define __LOCAL_MEI_PHY_H_
+
+#include <linux/mei_cl_bus.h>
+#include <net/nfc/hci.h>
+
+#define MEI_NFC_HEADER_SIZE 10
+#define MEI_NFC_MAX_HCI_PAYLOAD 300
+
+struct nfc_mei_phy {
+ struct mei_cl_device *device;
+ struct nfc_hci_dev *hdev;
+
+ int powered;
+
+ int hard_fault; /*
+ * < 0 if hardware error occured
+ * and prevents normal operation.
+ */
+};
+
+extern struct nfc_phy_ops mei_phy_ops;
+
+int nfc_mei_phy_enable(void *phy_id);
+void nfc_mei_phy_disable(void *phy_id);
+void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, void *context);
+struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device);
+void nfc_mei_phy_free(struct nfc_mei_phy *phy);
+
+#endif /* __LOCAL_MEI_PHY_H_ */
diff --git a/drivers/nfc/microread/Kconfig b/drivers/nfc/microread/Kconfig
index 572305be6e37..951d5542f6bc 100644
--- a/drivers/nfc/microread/Kconfig
+++ b/drivers/nfc/microread/Kconfig
@@ -25,7 +25,7 @@ config NFC_MICROREAD_I2C
config NFC_MICROREAD_MEI
tristate "NFC Microread MEI support"
- depends on NFC_MICROREAD && INTEL_MEI_BUS_NFC
+ depends on NFC_MICROREAD && NFC_MEI_PHY
---help---
This module adds support for the mei interface of adapters using
Inside microread chipsets. Select this if your microread chipset
diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c
index ca33ae193935..1ad044dce7b6 100644
--- a/drivers/nfc/microread/mei.c
+++ b/drivers/nfc/microread/mei.c
@@ -19,151 +19,31 @@
*/
#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/mei_cl_bus.h>
-
+#include <linux/mod_devicetable.h>
#include <linux/nfc.h>
#include <net/nfc/hci.h>
#include <net/nfc/llc.h>
+#include "../mei_phy.h"
#include "microread.h"
#define MICROREAD_DRIVER_NAME "microread"
-struct mei_nfc_hdr {
- u8 cmd;
- u8 status;
- u16 req_id;
- u32 reserved;
- u16 data_size;
-} __attribute__((packed));
-
-#define MEI_NFC_HEADER_SIZE 10
-#define MEI_NFC_MAX_HCI_PAYLOAD 300
-#define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)
-
-struct microread_mei_phy {
- struct mei_cl_device *device;
- struct nfc_hci_dev *hdev;
-
- int powered;
-
- int hard_fault; /*
- * < 0 if hardware error occured (e.g. i2c err)
- * and prevents normal operation.
- */
-};
-
-#define MEI_DUMP_SKB_IN(info, skb) \
-do { \
- pr_debug("%s:\n", info); \
- print_hex_dump(KERN_DEBUG, "mei in : ", DUMP_PREFIX_OFFSET, \
- 16, 1, (skb)->data, (skb)->len, 0); \
-} while (0)
-
-#define MEI_DUMP_SKB_OUT(info, skb) \
-do { \
- pr_debug("%s:\n", info); \
- print_hex_dump(KERN_DEBUG, "mei out: ", DUMP_PREFIX_OFFSET, \
- 16, 1, (skb)->data, (skb)->len, 0); \
-} while (0)
-
-static int microread_mei_enable(void *phy_id)
-{
- struct microread_mei_phy *phy = phy_id;
-
- pr_info(DRIVER_DESC ": %s\n", __func__);
-
- phy->powered = 1;
-
- return 0;
-}
-
-static void microread_mei_disable(void *phy_id)
-{
- struct microread_mei_phy *phy = phy_id;
-
- pr_info(DRIVER_DESC ": %s\n", __func__);
-
- phy->powered = 0;
-}
-
-/*
- * Writing a frame must not return the number of written bytes.
- * It must return either zero for success, or <0 for error.
- * In addition, it must not alter the skb
- */
-static int microread_mei_write(void *phy_id, struct sk_buff *skb)
-{
- struct microread_mei_phy *phy = phy_id;
- int r;
-
- MEI_DUMP_SKB_OUT("mei frame sent", skb);
-
- r = mei_cl_send(phy->device, skb->data, skb->len);
- if (r > 0)
- r = 0;
-
- return r;
-}
-
-static void microread_event_cb(struct mei_cl_device *device, u32 events,
- void *context)
-{
- struct microread_mei_phy *phy = context;
-
- if (phy->hard_fault != 0)
- return;
-
- if (events & BIT(MEI_CL_EVENT_RX)) {
- struct sk_buff *skb;
- int reply_size;
-
- skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
- if (!skb)
- return;
-
- reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ);
- if (reply_size < MEI_NFC_HEADER_SIZE) {
- kfree(skb);
- return;
- }
-
- skb_put(skb, reply_size);
- skb_pull(skb, MEI_NFC_HEADER_SIZE);
-
- MEI_DUMP_SKB_IN("mei frame read", skb);
-
- nfc_hci_recv_frame(phy->hdev, skb);
- }
-}
-
-static struct nfc_phy_ops mei_phy_ops = {
- .write = microread_mei_write,
- .enable = microread_mei_enable,
- .disable = microread_mei_disable,
-};
-
static int microread_mei_probe(struct mei_cl_device *device,
const struct mei_cl_device_id *id)
{
- struct microread_mei_phy *phy;
+ struct nfc_mei_phy *phy;
int r;
pr_info("Probing NFC microread\n");
- phy = kzalloc(sizeof(struct microread_mei_phy), GFP_KERNEL);
+ phy = nfc_mei_phy_alloc(device);
if (!phy) {
pr_err("Cannot allocate memory for microread mei phy.\n");
return -ENOMEM;
}
- phy->device = device;
- mei_cl_set_drvdata(device, phy);
-
- r = mei_cl_register_event_cb(device, microread_event_cb, phy);
+ r = mei_cl_register_event_cb(device, nfc_mei_event_cb, phy);
if (r) {
pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n");
goto err_out;
@@ -178,23 +58,22 @@ static int microread_mei_probe(struct mei_cl_device *device,
return 0;
err_out:
- kfree(phy);
+ nfc_mei_phy_free(phy);
return r;
}
static int microread_mei_remove(struct mei_cl_device *device)
{
- struct microread_mei_phy *phy = mei_cl_get_drvdata(device);
+ struct nfc_mei_phy *phy = mei_cl_get_drvdata(device);
pr_info("Removing microread\n");
microread_remove(phy->hdev);
- if (phy->powered)
- microread_mei_disable(phy);
+ nfc_mei_phy_disable(phy);
- kfree(phy);
+ nfc_mei_phy_free(phy);
return 0;
}
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index f0f6763d67ae..8f6f2baa930d 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -1,9 +1,6 @@
/*
* Copyright (C) 2011 Instituto Nokia de Tecnologia
- *
- * Authors:
- * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
- * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
+ * Copyright (C) 2012-2013 Tieto Poland
*
* 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
@@ -30,7 +27,7 @@
#include <linux/netdevice.h>
#include <net/nfc/nfc.h>
-#define VERSION "0.1"
+#define VERSION "0.2"
#define PN533_VENDOR_ID 0x4CC
#define PN533_PRODUCT_ID 0x2533
@@ -41,8 +38,12 @@
#define SONY_VENDOR_ID 0x054c
#define PASORI_PRODUCT_ID 0x02e1
-#define PN533_DEVICE_STD 0x1
-#define PN533_DEVICE_PASORI 0x2
+#define ACS_VENDOR_ID 0x072f
+#define ACR122U_PRODUCT_ID 0x2200
+
+#define PN533_DEVICE_STD 0x1
+#define PN533_DEVICE_PASORI 0x2
+#define PN533_DEVICE_ACR122U 0x3
#define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\
NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\
@@ -71,6 +72,11 @@ static const struct usb_device_id pn533_table[] = {
.idProduct = PASORI_PRODUCT_ID,
.driver_info = PN533_DEVICE_PASORI,
},
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = ACS_VENDOR_ID,
+ .idProduct = ACR122U_PRODUCT_ID,
+ .driver_info = PN533_DEVICE_ACR122U,
+ },
{ }
};
MODULE_DEVICE_TABLE(usb, pn533_table);
@@ -78,32 +84,47 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
/* How much time we spend listening for initiators */
#define PN533_LISTEN_TIME 2
-/* frame definitions */
-#define PN533_FRAME_HEADER_LEN (sizeof(struct pn533_frame) \
+/* Standard pn533 frame definitions */
+#define PN533_STD_FRAME_HEADER_LEN (sizeof(struct pn533_std_frame) \
+ 2) /* data[0] TFI, data[1] CC */
-#define PN533_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/
+#define PN533_STD_FRAME_TAIL_LEN 2 /* data[len] DCS, data[len + 1] postamble*/
/*
* Max extended frame payload len, excluding TFI and CC
* which are already in PN533_FRAME_HEADER_LEN.
*/
-#define PN533_FRAME_MAX_PAYLOAD_LEN 263
+#define PN533_STD_FRAME_MAX_PAYLOAD_LEN 263
-#define PN533_FRAME_ACK_SIZE 6 /* Preamble (1), SoPC (2), ACK Code (2),
+#define PN533_STD_FRAME_ACK_SIZE 6 /* Preamble (1), SoPC (2), ACK Code (2),
Postamble (1) */
-#define PN533_FRAME_CHECKSUM(f) (f->data[f->datalen])
-#define PN533_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
+#define PN533_STD_FRAME_CHECKSUM(f) (f->data[f->datalen])
+#define PN533_STD_FRAME_POSTAMBLE(f) (f->data[f->datalen + 1])
/* start of frame */
-#define PN533_SOF 0x00FF
+#define PN533_STD_FRAME_SOF 0x00FF
+
+/* standard frame identifier: in/out/error */
+#define PN533_STD_FRAME_IDENTIFIER(f) (f->data[0]) /* TFI */
+#define PN533_STD_FRAME_DIR_OUT 0xD4
+#define PN533_STD_FRAME_DIR_IN 0xD5
+
+/* ACS ACR122 pn533 frame definitions */
+#define PN533_ACR122_TX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_tx_frame) \
+ + 2)
+#define PN533_ACR122_TX_FRAME_TAIL_LEN 0
+#define PN533_ACR122_RX_FRAME_HEADER_LEN (sizeof(struct pn533_acr122_rx_frame) \
+ + 2)
+#define PN533_ACR122_RX_FRAME_TAIL_LEN 2
+#define PN533_ACR122_FRAME_MAX_PAYLOAD_LEN PN533_STD_FRAME_MAX_PAYLOAD_LEN
+
+/* CCID messages types */
+#define PN533_ACR122_PC_TO_RDR_ICCPOWERON 0x62
+#define PN533_ACR122_PC_TO_RDR_ESCAPE 0x6B
-/* frame identifier: in/out/error */
-#define PN533_FRAME_IDENTIFIER(f) (f->data[0])
-#define PN533_DIR_OUT 0xD4
-#define PN533_DIR_IN 0xD5
+#define PN533_ACR122_RDR_TO_PC_ESCAPE 0x83
/* PN533 Commands */
-#define PN533_FRAME_CMD(f) (f->data[1])
+#define PN533_STD_FRAME_CMD(f) (f->data[1])
#define PN533_CMD_GET_FIRMWARE_VERSION 0x02
#define PN533_CMD_RF_CONFIGURATION 0x32
@@ -128,8 +149,6 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
struct pn533;
-typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, int status);
-
typedef int (*pn533_send_async_complete_t) (struct pn533 *dev, void *arg,
struct sk_buff *resp);
@@ -144,9 +163,13 @@ struct pn533_fw_version {
};
/* PN533_CMD_RF_CONFIGURATION */
-#define PN533_CFGITEM_TIMING 0x02
+#define PN533_CFGITEM_RF_FIELD 0x01
+#define PN533_CFGITEM_TIMING 0x02
#define PN533_CFGITEM_MAX_RETRIES 0x05
-#define PN533_CFGITEM_PASORI 0x82
+#define PN533_CFGITEM_PASORI 0x82
+
+#define PN533_CFGITEM_RF_FIELD_ON 0x1
+#define PN533_CFGITEM_RF_FIELD_OFF 0x0
#define PN533_CONFIG_TIMING_102 0xb
#define PN533_CONFIG_TIMING_204 0xc
@@ -313,10 +336,17 @@ struct pn533_cmd_jump_dep_response {
#define PN533_INIT_TARGET_RESP_ACTIVE 0x1
#define PN533_INIT_TARGET_RESP_DEP 0x4
+enum pn533_protocol_type {
+ PN533_PROTO_REQ_ACK_RESP = 0,
+ PN533_PROTO_REQ_RESP
+};
+
struct pn533 {
struct usb_device *udev;
struct usb_interface *interface;
struct nfc_dev *nfc_dev;
+ u32 device_type;
+ enum pn533_protocol_type protocol_type;
struct urb *out_urb;
struct urb *in_urb;
@@ -329,21 +359,21 @@ struct pn533 {
struct work_struct poll_work;
struct work_struct mi_work;
struct work_struct tg_work;
- struct timer_list listen_timer;
- int wq_in_error;
- int cancel_listen;
- pn533_cmd_complete_t cmd_complete;
- void *cmd_complete_arg;
+ struct list_head cmd_queue;
+ struct pn533_cmd *cmd;
+ u8 cmd_pending;
+ struct mutex cmd_lock; /* protects cmd queue */
+
void *cmd_complete_mi_arg;
- struct mutex cmd_lock;
- u8 cmd;
struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1];
u8 poll_mod_count;
u8 poll_mod_curr;
u32 poll_protocols;
u32 listen_protocols;
+ struct timer_list listen_timer;
+ int cancel_listen;
u8 *gb;
size_t gb_len;
@@ -352,24 +382,21 @@ struct pn533 {
u8 tgt_active_prot;
u8 tgt_mode;
- u32 device_type;
-
- struct list_head cmd_queue;
- u8 cmd_pending;
-
struct pn533_frame_ops *ops;
};
struct pn533_cmd {
struct list_head queue;
- u8 cmd_code;
+ u8 code;
+ int status;
struct sk_buff *req;
struct sk_buff *resp;
int resp_len;
- void *arg;
+ pn533_send_async_complete_t complete_cb;
+ void *complete_cb_context;
};
-struct pn533_frame {
+struct pn533_std_frame {
u8 preamble;
__be16 start_frame;
u8 datalen;
@@ -393,14 +420,124 @@ struct pn533_frame_ops {
u8 (*get_cmd_code)(void *frame);
};
+struct pn533_acr122_ccid_hdr {
+ u8 type;
+ u32 datalen;
+ u8 slot;
+ u8 seq;
+ u8 params[3]; /* 3 msg specific bytes or status, error and 1 specific
+ byte for reposnse msg */
+ u8 data[]; /* payload */
+} __packed;
+
+struct pn533_acr122_apdu_hdr {
+ u8 class;
+ u8 ins;
+ u8 p1;
+ u8 p2;
+} __packed;
+
+struct pn533_acr122_tx_frame {
+ struct pn533_acr122_ccid_hdr ccid;
+ struct pn533_acr122_apdu_hdr apdu;
+ u8 datalen;
+ u8 data[]; /* pn533 frame: TFI ... */
+} __packed;
+
+struct pn533_acr122_rx_frame {
+ struct pn533_acr122_ccid_hdr ccid;
+ u8 data[]; /* pn533 frame : TFI ... */
+} __packed;
+
+static void pn533_acr122_tx_frame_init(void *_frame, u8 cmd_code)
+{
+ struct pn533_acr122_tx_frame *frame = _frame;
+
+ frame->ccid.type = PN533_ACR122_PC_TO_RDR_ESCAPE;
+ frame->ccid.datalen = sizeof(frame->apdu) + 1; /* sizeof(apdu_hdr) +
+ sizeof(datalen) */
+ frame->ccid.slot = 0;
+ frame->ccid.seq = 0;
+ frame->ccid.params[0] = 0;
+ frame->ccid.params[1] = 0;
+ frame->ccid.params[2] = 0;
+
+ frame->data[0] = PN533_STD_FRAME_DIR_OUT;
+ frame->data[1] = cmd_code;
+ frame->datalen = 2; /* data[0] + data[1] */
+
+ frame->apdu.class = 0xFF;
+ frame->apdu.ins = 0;
+ frame->apdu.p1 = 0;
+ frame->apdu.p2 = 0;
+}
+
+static void pn533_acr122_tx_frame_finish(void *_frame)
+{
+ struct pn533_acr122_tx_frame *frame = _frame;
+
+ frame->ccid.datalen += frame->datalen;
+}
+
+static void pn533_acr122_tx_update_payload_len(void *_frame, int len)
+{
+ struct pn533_acr122_tx_frame *frame = _frame;
+
+ frame->datalen += len;
+}
+
+static bool pn533_acr122_is_rx_frame_valid(void *_frame)
+{
+ struct pn533_acr122_rx_frame *frame = _frame;
+
+ if (frame->ccid.type != 0x83)
+ return false;
+
+ if (frame->data[frame->ccid.datalen - 2] == 0x63)
+ return false;
+
+ return true;
+}
+
+static int pn533_acr122_rx_frame_size(void *frame)
+{
+ struct pn533_acr122_rx_frame *f = frame;
+
+ /* f->ccid.datalen already includes tail length */
+ return sizeof(struct pn533_acr122_rx_frame) + f->ccid.datalen;
+}
+
+static u8 pn533_acr122_get_cmd_code(void *frame)
+{
+ struct pn533_acr122_rx_frame *f = frame;
+
+ return PN533_STD_FRAME_CMD(f);
+}
+
+static struct pn533_frame_ops pn533_acr122_frame_ops = {
+ .tx_frame_init = pn533_acr122_tx_frame_init,
+ .tx_frame_finish = pn533_acr122_tx_frame_finish,
+ .tx_update_payload_len = pn533_acr122_tx_update_payload_len,
+ .tx_header_len = PN533_ACR122_TX_FRAME_HEADER_LEN,
+ .tx_tail_len = PN533_ACR122_TX_FRAME_TAIL_LEN,
+
+ .rx_is_frame_valid = pn533_acr122_is_rx_frame_valid,
+ .rx_header_len = PN533_ACR122_RX_FRAME_HEADER_LEN,
+ .rx_tail_len = PN533_ACR122_RX_FRAME_TAIL_LEN,
+ .rx_frame_size = pn533_acr122_rx_frame_size,
+
+ .max_payload_len = PN533_ACR122_FRAME_MAX_PAYLOAD_LEN,
+ .get_cmd_code = pn533_acr122_get_cmd_code,
+};
+
/* The rule: value + checksum = 0 */
-static inline u8 pn533_checksum(u8 value)
+static inline u8 pn533_std_checksum(u8 value)
{
return ~value + 1;
}
/* The rule: sum(data elements) + checksum = 0 */
-static u8 pn533_data_checksum(u8 *data, int datalen)
+static u8 pn533_std_data_checksum(u8 *data, int datalen)
{
u8 sum = 0;
int i;
@@ -408,61 +545,61 @@ static u8 pn533_data_checksum(u8 *data, int datalen)
for (i = 0; i < datalen; i++)
sum += data[i];
- return pn533_checksum(sum);
+ return pn533_std_checksum(sum);
}
-static void pn533_tx_frame_init(void *_frame, u8 cmd_code)
+static void pn533_std_tx_frame_init(void *_frame, u8 cmd_code)
{
- struct pn533_frame *frame = _frame;
+ struct pn533_std_frame *frame = _frame;
frame->preamble = 0;
- frame->start_frame = cpu_to_be16(PN533_SOF);
- PN533_FRAME_IDENTIFIER(frame) = PN533_DIR_OUT;
- PN533_FRAME_CMD(frame) = cmd_code;
+ frame->start_frame = cpu_to_be16(PN533_STD_FRAME_SOF);
+ PN533_STD_FRAME_IDENTIFIER(frame) = PN533_STD_FRAME_DIR_OUT;
+ PN533_STD_FRAME_CMD(frame) = cmd_code;
frame->datalen = 2;
}
-static void pn533_tx_frame_finish(void *_frame)
+static void pn533_std_tx_frame_finish(void *_frame)
{
- struct pn533_frame *frame = _frame;
+ struct pn533_std_frame *frame = _frame;
- frame->datalen_checksum = pn533_checksum(frame->datalen);
+ frame->datalen_checksum = pn533_std_checksum(frame->datalen);
- PN533_FRAME_CHECKSUM(frame) =
- pn533_data_checksum(frame->data, frame->datalen);
+ PN533_STD_FRAME_CHECKSUM(frame) =
+ pn533_std_data_checksum(frame->data, frame->datalen);
- PN533_FRAME_POSTAMBLE(frame) = 0;
+ PN533_STD_FRAME_POSTAMBLE(frame) = 0;
}
-static void pn533_tx_update_payload_len(void *_frame, int len)
+static void pn533_std_tx_update_payload_len(void *_frame, int len)
{
- struct pn533_frame *frame = _frame;
+ struct pn533_std_frame *frame = _frame;
frame->datalen += len;
}
-static bool pn533_rx_frame_is_valid(void *_frame)
+static bool pn533_std_rx_frame_is_valid(void *_frame)
{
u8 checksum;
- struct pn533_frame *frame = _frame;
+ struct pn533_std_frame *frame = _frame;
- if (frame->start_frame != cpu_to_be16(PN533_SOF))
+ if (frame->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
return false;
- checksum = pn533_checksum(frame->datalen);
+ checksum = pn533_std_checksum(frame->datalen);
if (checksum != frame->datalen_checksum)
return false;
- checksum = pn533_data_checksum(frame->data, frame->datalen);
- if (checksum != PN533_FRAME_CHECKSUM(frame))
+ checksum = pn533_std_data_checksum(frame->data, frame->datalen);
+ if (checksum != PN533_STD_FRAME_CHECKSUM(frame))
return false;
return true;
}
-static bool pn533_rx_frame_is_ack(struct pn533_frame *frame)
+static bool pn533_std_rx_frame_is_ack(struct pn533_std_frame *frame)
{
- if (frame->start_frame != cpu_to_be16(PN533_SOF))
+ if (frame->start_frame != cpu_to_be16(PN533_STD_FRAME_SOF))
return false;
if (frame->datalen != 0 || frame->datalen_checksum != 0xFF)
@@ -471,57 +608,51 @@ static bool pn533_rx_frame_is_ack(struct pn533_frame *frame)
return true;
}
-static inline int pn533_rx_frame_size(void *frame)
+static inline int pn533_std_rx_frame_size(void *frame)
{
- struct pn533_frame *f = frame;
+ struct pn533_std_frame *f = frame;
- return sizeof(struct pn533_frame) + f->datalen + PN533_FRAME_TAIL_LEN;
+ return sizeof(struct pn533_std_frame) + f->datalen +
+ PN533_STD_FRAME_TAIL_LEN;
}
-static u8 pn533_get_cmd_code(void *frame)
+static u8 pn533_std_get_cmd_code(void *frame)
{
- struct pn533_frame *f = frame;
+ struct pn533_std_frame *f = frame;
- return PN533_FRAME_CMD(f);
+ return PN533_STD_FRAME_CMD(f);
}
static struct pn533_frame_ops pn533_std_frame_ops = {
- .tx_frame_init = pn533_tx_frame_init,
- .tx_frame_finish = pn533_tx_frame_finish,
- .tx_update_payload_len = pn533_tx_update_payload_len,
- .tx_header_len = PN533_FRAME_HEADER_LEN,
- .tx_tail_len = PN533_FRAME_TAIL_LEN,
-
- .rx_is_frame_valid = pn533_rx_frame_is_valid,
- .rx_frame_size = pn533_rx_frame_size,
- .rx_header_len = PN533_FRAME_HEADER_LEN,
- .rx_tail_len = PN533_FRAME_TAIL_LEN,
-
- .max_payload_len = PN533_FRAME_MAX_PAYLOAD_LEN,
- .get_cmd_code = pn533_get_cmd_code,
+ .tx_frame_init = pn533_std_tx_frame_init,
+ .tx_frame_finish = pn533_std_tx_frame_finish,
+ .tx_update_payload_len = pn533_std_tx_update_payload_len,
+ .tx_header_len = PN533_STD_FRAME_HEADER_LEN,
+ .tx_tail_len = PN533_STD_FRAME_TAIL_LEN,
+
+ .rx_is_frame_valid = pn533_std_rx_frame_is_valid,
+ .rx_frame_size = pn533_std_rx_frame_size,
+ .rx_header_len = PN533_STD_FRAME_HEADER_LEN,
+ .rx_tail_len = PN533_STD_FRAME_TAIL_LEN,
+
+ .max_payload_len = PN533_STD_FRAME_MAX_PAYLOAD_LEN,
+ .get_cmd_code = pn533_std_get_cmd_code,
};
static bool pn533_rx_frame_is_cmd_response(struct pn533 *dev, void *frame)
{
- return (dev->ops->get_cmd_code(frame) == PN533_CMD_RESPONSE(dev->cmd));
-}
-
-
-static void pn533_wq_cmd_complete(struct work_struct *work)
-{
- struct pn533 *dev = container_of(work, struct pn533, cmd_complete_work);
- int rc;
-
- rc = dev->cmd_complete(dev, dev->cmd_complete_arg, dev->wq_in_error);
- if (rc != -EINPROGRESS)
- queue_work(dev->wq, &dev->cmd_work);
+ return (dev->ops->get_cmd_code(frame) ==
+ PN533_CMD_RESPONSE(dev->cmd->code));
}
static void pn533_recv_response(struct urb *urb)
{
struct pn533 *dev = urb->context;
+ struct pn533_cmd *cmd = dev->cmd;
u8 *in_frame;
+ cmd->status = urb->status;
+
switch (urb->status) {
case 0:
break; /* success */
@@ -530,37 +661,33 @@ static void pn533_recv_response(struct urb *urb)
nfc_dev_dbg(&dev->interface->dev,
"The urb has been canceled (status %d)",
urb->status);
- dev->wq_in_error = urb->status;
goto sched_wq;
case -ESHUTDOWN:
default:
nfc_dev_err(&dev->interface->dev,
"Urb failure (status %d)", urb->status);
- dev->wq_in_error = urb->status;
goto sched_wq;
}
in_frame = dev->in_urb->transfer_buffer;
nfc_dev_dbg(&dev->interface->dev, "Received a frame.");
- print_hex_dump(KERN_DEBUG, "PN533 RX: ", DUMP_PREFIX_NONE, 16, 1,
- in_frame, dev->ops->rx_frame_size(in_frame), false);
+ print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, in_frame,
+ dev->ops->rx_frame_size(in_frame), false);
if (!dev->ops->rx_is_frame_valid(in_frame)) {
nfc_dev_err(&dev->interface->dev, "Received an invalid frame");
- dev->wq_in_error = -EIO;
+ cmd->status = -EIO;
goto sched_wq;
}
if (!pn533_rx_frame_is_cmd_response(dev, in_frame)) {
nfc_dev_err(&dev->interface->dev,
"It it not the response to the last command");
- dev->wq_in_error = -EIO;
+ cmd->status = -EIO;
goto sched_wq;
}
- dev->wq_in_error = 0;
-
sched_wq:
queue_work(dev->wq, &dev->cmd_complete_work);
}
@@ -575,9 +702,12 @@ static int pn533_submit_urb_for_response(struct pn533 *dev, gfp_t flags)
static void pn533_recv_ack(struct urb *urb)
{
struct pn533 *dev = urb->context;
- struct pn533_frame *in_frame;
+ struct pn533_cmd *cmd = dev->cmd;
+ struct pn533_std_frame *in_frame;
int rc;
+ cmd->status = urb->status;
+
switch (urb->status) {
case 0:
break; /* success */
@@ -586,21 +716,19 @@ static void pn533_recv_ack(struct urb *urb)
nfc_dev_dbg(&dev->interface->dev,
"The urb has been stopped (status %d)",
urb->status);
- dev->wq_in_error = urb->status;
goto sched_wq;
case -ESHUTDOWN:
default:
nfc_dev_err(&dev->interface->dev,
"Urb failure (status %d)", urb->status);
- dev->wq_in_error = urb->status;
goto sched_wq;
}
in_frame = dev->in_urb->transfer_buffer;
- if (!pn533_rx_frame_is_ack(in_frame)) {
+ if (!pn533_std_rx_frame_is_ack(in_frame)) {
nfc_dev_err(&dev->interface->dev, "Received an invalid ack");
- dev->wq_in_error = -EIO;
+ cmd->status = -EIO;
goto sched_wq;
}
@@ -608,7 +736,7 @@ static void pn533_recv_ack(struct urb *urb)
if (rc) {
nfc_dev_err(&dev->interface->dev,
"usb_submit_urb failed with result %d", rc);
- dev->wq_in_error = rc;
+ cmd->status = rc;
goto sched_wq;
}
@@ -627,7 +755,7 @@ static int pn533_submit_urb_for_ack(struct pn533 *dev, gfp_t flags)
static int pn533_send_ack(struct pn533 *dev, gfp_t flags)
{
- u8 ack[PN533_FRAME_ACK_SIZE] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
+ u8 ack[PN533_STD_FRAME_ACK_SIZE] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00};
/* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */
int rc;
@@ -643,32 +771,34 @@ static int pn533_send_ack(struct pn533 *dev, gfp_t flags)
static int __pn533_send_frame_async(struct pn533 *dev,
struct sk_buff *out,
struct sk_buff *in,
- int in_len,
- pn533_cmd_complete_t cmd_complete,
- void *arg)
+ int in_len)
{
int rc;
- dev->cmd = dev->ops->get_cmd_code(out->data);
- dev->cmd_complete = cmd_complete;
- dev->cmd_complete_arg = arg;
-
dev->out_urb->transfer_buffer = out->data;
dev->out_urb->transfer_buffer_length = out->len;
dev->in_urb->transfer_buffer = in->data;
dev->in_urb->transfer_buffer_length = in_len;
- print_hex_dump(KERN_DEBUG, "PN533 TX: ", DUMP_PREFIX_NONE, 16, 1,
- out->data, out->len, false);
+ print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1,
+ out->data, out->len, false);
rc = usb_submit_urb(dev->out_urb, GFP_KERNEL);
if (rc)
return rc;
- rc = pn533_submit_urb_for_ack(dev, GFP_KERNEL);
- if (rc)
- goto error;
+ if (dev->protocol_type == PN533_PROTO_REQ_RESP) {
+ /* request for response for sent packet directly */
+ rc = pn533_submit_urb_for_response(dev, GFP_ATOMIC);
+ if (rc)
+ goto error;
+ } else if (dev->protocol_type == PN533_PROTO_REQ_ACK_RESP) {
+ /* request for ACK if that's the case */
+ rc = pn533_submit_urb_for_ack(dev, GFP_KERNEL);
+ if (rc)
+ goto error;
+ }
return 0;
@@ -693,39 +823,34 @@ static void pn533_build_cmd_frame(struct pn533 *dev, u8 cmd_code,
ops->tx_frame_finish(skb->data);
}
-struct pn533_send_async_complete_arg {
- pn533_send_async_complete_t complete_cb;
- void *complete_cb_context;
- struct sk_buff *resp;
- struct sk_buff *req;
-};
-
-static int pn533_send_async_complete(struct pn533 *dev, void *_arg, int status)
+static int pn533_send_async_complete(struct pn533 *dev)
{
- struct pn533_send_async_complete_arg *arg = _arg;
+ struct pn533_cmd *cmd = dev->cmd;
+ int status = cmd->status;
- struct sk_buff *req = arg->req;
- struct sk_buff *resp = arg->resp;
+ struct sk_buff *req = cmd->req;
+ struct sk_buff *resp = cmd->resp;
int rc;
dev_kfree_skb(req);
if (status < 0) {
- arg->complete_cb(dev, arg->complete_cb_context,
- ERR_PTR(status));
+ rc = cmd->complete_cb(dev, cmd->complete_cb_context,
+ ERR_PTR(status));
dev_kfree_skb(resp);
- kfree(arg);
- return status;
+ goto done;
}
skb_put(resp, dev->ops->rx_frame_size(resp->data));
skb_pull(resp, dev->ops->rx_header_len);
skb_trim(resp, resp->len - dev->ops->rx_tail_len);
- rc = arg->complete_cb(dev, arg->complete_cb_context, resp);
+ rc = cmd->complete_cb(dev, cmd->complete_cb_context, resp);
- kfree(arg);
+done:
+ kfree(cmd);
+ dev->cmd = NULL;
return rc;
}
@@ -736,56 +861,45 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code,
void *complete_cb_context)
{
struct pn533_cmd *cmd;
- struct pn533_send_async_complete_arg *arg;
int rc = 0;
nfc_dev_dbg(&dev->interface->dev, "Sending command 0x%x", cmd_code);
- arg = kzalloc(sizeof(*arg), GFP_KERNEL);
- if (!arg)
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
return -ENOMEM;
- arg->complete_cb = complete_cb;
- arg->complete_cb_context = complete_cb_context;
- arg->resp = resp;
- arg->req = req;
+ cmd->code = cmd_code;
+ cmd->req = req;
+ cmd->resp = resp;
+ cmd->resp_len = resp_len;
+ cmd->complete_cb = complete_cb;
+ cmd->complete_cb_context = complete_cb_context;
pn533_build_cmd_frame(dev, cmd_code, req);
mutex_lock(&dev->cmd_lock);
if (!dev->cmd_pending) {
- rc = __pn533_send_frame_async(dev, req, resp, resp_len,
- pn533_send_async_complete, arg);
+ rc = __pn533_send_frame_async(dev, req, resp, resp_len);
if (rc)
goto error;
dev->cmd_pending = 1;
+ dev->cmd = cmd;
goto unlock;
}
nfc_dev_dbg(&dev->interface->dev, "%s Queueing command 0x%x", __func__,
cmd_code);
- cmd = kzalloc(sizeof(struct pn533_cmd), GFP_KERNEL);
- if (!cmd) {
- rc = -ENOMEM;
- goto error;
- }
-
INIT_LIST_HEAD(&cmd->queue);
- cmd->cmd_code = cmd_code;
- cmd->req = req;
- cmd->resp = resp;
- cmd->resp_len = resp_len;
- cmd->arg = arg;
-
list_add_tail(&cmd->queue, &dev->cmd_queue);
goto unlock;
error:
- kfree(arg);
+ kfree(cmd);
unlock:
mutex_unlock(&dev->cmd_lock);
return rc;
@@ -850,8 +964,8 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code,
pn533_send_async_complete_t complete_cb,
void *complete_cb_context)
{
- struct pn533_send_async_complete_arg *arg;
struct sk_buff *resp;
+ struct pn533_cmd *cmd;
int rc;
int resp_len = dev->ops->rx_header_len +
dev->ops->max_payload_len +
@@ -861,33 +975,47 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code,
if (!resp)
return -ENOMEM;
- arg = kzalloc(sizeof(*arg), GFP_KERNEL);
- if (!arg) {
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
dev_kfree_skb(resp);
return -ENOMEM;
}
- arg->complete_cb = complete_cb;
- arg->complete_cb_context = complete_cb_context;
- arg->resp = resp;
- arg->req = req;
+ cmd->code = cmd_code;
+ cmd->req = req;
+ cmd->resp = resp;
+ cmd->resp_len = resp_len;
+ cmd->complete_cb = complete_cb;
+ cmd->complete_cb_context = complete_cb_context;
pn533_build_cmd_frame(dev, cmd_code, req);
- rc = __pn533_send_frame_async(dev, req, resp, resp_len,
- pn533_send_async_complete, arg);
+ rc = __pn533_send_frame_async(dev, req, resp, resp_len);
if (rc < 0) {
dev_kfree_skb(resp);
- kfree(arg);
+ kfree(cmd);
+ } else {
+ dev->cmd = cmd;
}
return rc;
}
+static void pn533_wq_cmd_complete(struct work_struct *work)
+{
+ struct pn533 *dev = container_of(work, struct pn533, cmd_complete_work);
+ int rc;
+
+ rc = pn533_send_async_complete(dev);
+ if (rc != -EINPROGRESS)
+ queue_work(dev->wq, &dev->cmd_work);
+}
+
static void pn533_wq_cmd(struct work_struct *work)
{
struct pn533 *dev = container_of(work, struct pn533, cmd_work);
struct pn533_cmd *cmd;
+ int rc;
mutex_lock(&dev->cmd_lock);
@@ -903,10 +1031,15 @@ static void pn533_wq_cmd(struct work_struct *work)
mutex_unlock(&dev->cmd_lock);
- __pn533_send_frame_async(dev, cmd->req, cmd->resp, cmd->resp_len,
- pn533_send_async_complete, cmd->arg);
+ rc = __pn533_send_frame_async(dev, cmd->req, cmd->resp, cmd->resp_len);
+ if (rc < 0) {
+ dev_kfree_skb(cmd->req);
+ dev_kfree_skb(cmd->resp);
+ kfree(cmd);
+ return;
+ }
- kfree(cmd);
+ dev->cmd = cmd;
}
struct pn533_sync_cmd_response {
@@ -982,6 +1115,23 @@ static void pn533_send_complete(struct urb *urb)
}
}
+static void pn533_abort_cmd(struct pn533 *dev, gfp_t flags)
+{
+ /* ACR122U does not support any command which aborts last
+ * issued command i.e. as ACK for standard PN533. Additionally,
+ * it behaves stange, sending broken or incorrect responses,
+ * when we cancel urb before the chip will send response.
+ */
+ if (dev->device_type == PN533_DEVICE_ACR122U)
+ return;
+
+ /* An ack will cancel the last issued command */
+ pn533_send_ack(dev, flags);
+
+ /* cancel the urb request */
+ usb_kill_urb(dev->in_urb);
+}
+
static struct sk_buff *pn533_alloc_skb(struct pn533 *dev, unsigned int size)
{
struct sk_buff *skb;
@@ -1500,9 +1650,6 @@ static void pn533_listen_mode_timer(unsigned long data)
nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout");
- /* An ack will cancel the last issued command (poll) */
- pn533_send_ack(dev, GFP_ATOMIC);
-
dev->cancel_listen = 1;
pn533_poll_next_mod(dev);
@@ -1549,6 +1696,11 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg,
if (!rc)
goto done;
+ if (!dev->poll_mod_count) {
+ nfc_dev_dbg(&dev->interface->dev, "Polling has been stoped.");
+ goto done;
+ }
+
pn533_poll_next_mod(dev);
queue_work(dev->wq, &dev->poll_work);
@@ -1627,7 +1779,7 @@ static void pn533_wq_poll(struct work_struct *work)
if (dev->cancel_listen == 1) {
dev->cancel_listen = 0;
- usb_kill_urb(dev->in_urb);
+ pn533_abort_cmd(dev, GFP_ATOMIC);
}
rc = pn533_send_poll_frame(dev);
@@ -1689,12 +1841,7 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev)
return;
}
- /* An ack will cancel the last issued command (poll) */
- pn533_send_ack(dev, GFP_KERNEL);
-
- /* prevent pn533_start_poll_complete to issue a new poll meanwhile */
- usb_kill_urb(dev->in_urb);
-
+ pn533_abort_cmd(dev, GFP_KERNEL);
pn533_poll_reset_mod_list(dev);
}
@@ -1723,6 +1870,8 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev)
rsp = (struct pn533_cmd_activate_response *)resp->data;
rc = rsp->status & PN533_CMD_RET_MASK;
if (rc != PN533_CMD_RET_SUCCESS) {
+ nfc_dev_err(&dev->interface->dev,
+ "Target activation failed (error 0x%x)", rc);
dev_kfree_skb(resp);
return -EIO;
}
@@ -1850,7 +1999,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
rc = rsp->status & PN533_CMD_RET_MASK;
if (rc != PN533_CMD_RET_SUCCESS) {
nfc_dev_err(&dev->interface->dev,
- "Bringing DEP link up failed %d", rc);
+ "Bringing DEP link up failed (error 0x%x)", rc);
goto error;
}
@@ -1985,10 +2134,8 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
pn533_poll_reset_mod_list(dev);
- if (dev->tgt_mode || dev->tgt_active_prot) {
- pn533_send_ack(dev, GFP_KERNEL);
- usb_kill_urb(dev->in_urb);
- }
+ if (dev->tgt_mode || dev->tgt_active_prot)
+ pn533_abort_cmd(dev, GFP_KERNEL);
dev->tgt_active_prot = 0;
dev->tgt_mode = 0;
@@ -2064,8 +2211,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
if (ret != PN533_CMD_RET_SUCCESS) {
nfc_dev_err(&dev->interface->dev,
- "PN533 reported error %d when exchanging data",
- ret);
+ "Exchanging data failed (error 0x%x)", ret);
rc = -EIO;
goto error;
}
@@ -2253,7 +2399,7 @@ static void pn533_wq_mi_recv(struct work_struct *work)
"Error %d when trying to perform data_exchange", rc);
dev_kfree_skb(skb);
- kfree(dev->cmd_complete_arg);
+ kfree(dev->cmd_complete_mi_arg);
error:
pn533_send_ack(dev, GFP_KERNEL);
@@ -2310,7 +2456,7 @@ static int pn533_get_firmware_version(struct pn533 *dev,
return 0;
}
-static int pn533_fw_reset(struct pn533 *dev)
+static int pn533_pasori_fw_reset(struct pn533 *dev)
{
struct sk_buff *skb;
struct sk_buff *resp;
@@ -2332,9 +2478,102 @@ static int pn533_fw_reset(struct pn533 *dev)
return 0;
}
+struct pn533_acr122_poweron_rdr_arg {
+ int rc;
+ struct completion done;
+};
+
+static void pn533_acr122_poweron_rdr_resp(struct urb *urb)
+{
+ struct pn533_acr122_poweron_rdr_arg *arg = urb->context;
+
+ nfc_dev_dbg(&urb->dev->dev, "%s", __func__);
+
+ print_hex_dump(KERN_ERR, "ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1,
+ urb->transfer_buffer, urb->transfer_buffer_length,
+ false);
+
+ arg->rc = urb->status;
+ complete(&arg->done);
+}
+
+static int pn533_acr122_poweron_rdr(struct pn533 *dev)
+{
+ /* Power on th reader (CCID cmd) */
+ u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON,
+ 0, 0, 0, 0, 0, 0, 3, 0, 0};
+ u8 buf[255];
+ int rc;
+ void *cntx;
+ struct pn533_acr122_poweron_rdr_arg arg;
+
+ nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+ init_completion(&arg.done);
+ cntx = dev->in_urb->context; /* backup context */
+
+ dev->in_urb->transfer_buffer = buf;
+ dev->in_urb->transfer_buffer_length = 255;
+ dev->in_urb->complete = pn533_acr122_poweron_rdr_resp;
+ dev->in_urb->context = &arg;
+
+ dev->out_urb->transfer_buffer = cmd;
+ dev->out_urb->transfer_buffer_length = sizeof(cmd);
+
+ print_hex_dump(KERN_ERR, "ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1,
+ cmd, sizeof(cmd), false);
+
+ rc = usb_submit_urb(dev->out_urb, GFP_KERNEL);
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev,
+ "Reader power on cmd error %d", rc);
+ return rc;
+ }
+
+ rc = usb_submit_urb(dev->in_urb, GFP_KERNEL);
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev,
+ "Can't submit for reader power on cmd response %d",
+ rc);
+ return rc;
+ }
+
+ wait_for_completion(&arg.done);
+ dev->in_urb->context = cntx; /* restore context */
+
+ return arg.rc;
+}
+
+static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf)
+{
+ struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+ u8 rf_field = !!rf;
+ int rc;
+
+ rc = pn533_set_configuration(dev, PN533_CFGITEM_RF_FIELD,
+ (u8 *)&rf_field, 1);
+ if (rc) {
+ nfc_dev_err(&dev->interface->dev,
+ "Error on setting RF field");
+ return rc;
+ }
+
+ return rc;
+}
+
+int pn533_dev_up(struct nfc_dev *nfc_dev)
+{
+ return pn533_rf_field(nfc_dev, 1);
+}
+
+int pn533_dev_down(struct nfc_dev *nfc_dev)
+{
+ return pn533_rf_field(nfc_dev, 0);
+}
+
static struct nfc_ops pn533_nfc_ops = {
- .dev_up = NULL,
- .dev_down = NULL,
+ .dev_up = pn533_dev_up,
+ .dev_down = pn533_dev_down,
.dep_link_up = pn533_dep_link_up,
.dep_link_down = pn533_dep_link_down,
.start_poll = pn533_start_poll,
@@ -2366,6 +2605,7 @@ static int pn533_setup(struct pn533 *dev)
break;
case PN533_DEVICE_PASORI:
+ case PN533_DEVICE_ACR122U:
max_retries.mx_rty_atr = 0x2;
max_retries.mx_rty_psl = 0x1;
max_retries.mx_rty_passive_act =
@@ -2405,7 +2645,7 @@ static int pn533_setup(struct pn533 *dev)
break;
case PN533_DEVICE_PASORI:
- pn533_fw_reset(dev);
+ pn533_pasori_fw_reset(dev);
rc = pn533_set_configuration(dev, PN533_CFGITEM_PASORI,
pasori_cfg, 3);
@@ -2415,7 +2655,7 @@ static int pn533_setup(struct pn533 *dev)
return rc;
}
- pn533_fw_reset(dev);
+ pn533_pasori_fw_reset(dev);
break;
}
@@ -2496,6 +2736,7 @@ static int pn533_probe(struct usb_interface *interface,
dev->ops = &pn533_std_frame_ops;
+ dev->protocol_type = PN533_PROTO_REQ_ACK_RESP;
dev->device_type = id->driver_info;
switch (dev->device_type) {
case PN533_DEVICE_STD:
@@ -2506,6 +2747,20 @@ static int pn533_probe(struct usb_interface *interface,
protocols = PN533_NO_TYPE_B_PROTOCOLS;
break;
+ case PN533_DEVICE_ACR122U:
+ protocols = PN533_NO_TYPE_B_PROTOCOLS;
+ dev->ops = &pn533_acr122_frame_ops;
+ dev->protocol_type = PN533_PROTO_REQ_RESP,
+
+ rc = pn533_acr122_poweron_rdr(dev);
+ if (rc < 0) {
+ nfc_dev_err(&dev->interface->dev,
+ "Couldn't poweron the reader (error %d)",
+ rc);
+ goto destroy_wq;
+ }
+ break;
+
default:
nfc_dev_err(&dev->interface->dev, "Unknown device type %d\n",
dev->device_type);
@@ -2555,6 +2810,7 @@ destroy_wq:
error:
usb_free_urb(dev->in_urb);
usb_free_urb(dev->out_urb);
+ usb_put_dev(dev->udev);
kfree(dev);
return rc;
}
@@ -2600,8 +2856,9 @@ static struct usb_driver pn533_driver = {
module_usb_driver(pn533_driver);
-MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>,"
- " Aloisio Almeida Jr <aloisio.almeida@openbossa.org>");
+MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
+MODULE_AUTHOR("Aloisio Almeida Jr <aloisio.almeida@openbossa.org>");
+MODULE_AUTHOR("Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>");
MODULE_DESCRIPTION("PN533 usb driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/nfc/pn544/Kconfig b/drivers/nfc/pn544/Kconfig
index c277790ac71c..ccf06f5f6ebb 100644
--- a/drivers/nfc/pn544/Kconfig
+++ b/drivers/nfc/pn544/Kconfig
@@ -20,4 +20,15 @@ config NFC_PN544_I2C
Select this if your platform is using the i2c bus.
If you choose to build a module, it'll be called pn544_i2c.
- Say N if unsure. \ No newline at end of file
+ Say N if unsure.
+
+config NFC_PN544_MEI
+ tristate "NFC PN544 MEI support"
+ depends on NFC_PN544 && NFC_MEI_PHY
+ ---help---
+ This module adds support for the mei interface of adapters using
+ NXP pn544 chipsets. Select this if your pn544 chipset
+ is handled by Intel's Management Engine Interface on your platform.
+
+ If you choose to build a module, it'll be called pn544_mei.
+ Say N if unsure.
diff --git a/drivers/nfc/pn544/Makefile b/drivers/nfc/pn544/Makefile
index ac076793687d..29fb5a174036 100644
--- a/drivers/nfc/pn544/Makefile
+++ b/drivers/nfc/pn544/Makefile
@@ -3,6 +3,8 @@
#
pn544_i2c-objs = i2c.o
+pn544_mei-objs = mei.o
obj-$(CONFIG_NFC_PN544) += pn544.o
obj-$(CONFIG_NFC_PN544_I2C) += pn544_i2c.o
+obj-$(CONFIG_NFC_PN544_MEI) += pn544_mei.o
diff --git a/drivers/nfc/pn544/mei.c b/drivers/nfc/pn544/mei.c
new file mode 100644
index 000000000000..1eb48848a35a
--- /dev/null
+++ b/drivers/nfc/pn544/mei.c
@@ -0,0 +1,121 @@
+/*
+ * HCI based Driver for NXP pn544 NFC Chip
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/nfc.h>
+#include <net/nfc/hci.h>
+#include <net/nfc/llc.h>
+
+#include "../mei_phy.h"
+#include "pn544.h"
+
+#define PN544_DRIVER_NAME "pn544"
+
+static int pn544_mei_probe(struct mei_cl_device *device,
+ const struct mei_cl_device_id *id)
+{
+ struct nfc_mei_phy *phy;
+ int r;
+
+ pr_info("Probing NFC pn544\n");
+
+ phy = nfc_mei_phy_alloc(device);
+ if (!phy) {
+ pr_err("Cannot allocate memory for pn544 mei phy.\n");
+ return -ENOMEM;
+ }
+
+ r = mei_cl_register_event_cb(device, nfc_mei_event_cb, phy);
+ if (r) {
+ pr_err(PN544_DRIVER_NAME ": event cb registration failed\n");
+ goto err_out;
+ }
+
+ r = pn544_hci_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
+ MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
+ &phy->hdev);
+ if (r < 0)
+ goto err_out;
+
+ return 0;
+
+err_out:
+ nfc_mei_phy_free(phy);
+
+ return r;
+}
+
+static int pn544_mei_remove(struct mei_cl_device *device)
+{
+ struct nfc_mei_phy *phy = mei_cl_get_drvdata(device);
+
+ pr_info("Removing pn544\n");
+
+ pn544_hci_remove(phy->hdev);
+
+ nfc_mei_phy_disable(phy);
+
+ nfc_mei_phy_free(phy);
+
+ return 0;
+}
+
+static struct mei_cl_device_id pn544_mei_tbl[] = {
+ { PN544_DRIVER_NAME },
+
+ /* required last entry */
+ { }
+};
+MODULE_DEVICE_TABLE(mei, pn544_mei_tbl);
+
+static struct mei_cl_driver pn544_driver = {
+ .id_table = pn544_mei_tbl,
+ .name = PN544_DRIVER_NAME,
+
+ .probe = pn544_mei_probe,
+ .remove = pn544_mei_remove,
+};
+
+static int pn544_mei_init(void)
+{
+ int r;
+
+ pr_debug(DRIVER_DESC ": %s\n", __func__);
+
+ r = mei_cl_driver_register(&pn544_driver);
+ if (r) {
+ pr_err(PN544_DRIVER_NAME ": driver registration failed\n");
+ return r;
+ }
+
+ return 0;
+}
+
+static void pn544_mei_exit(void)
+{
+ mei_cl_driver_unregister(&pn544_driver);
+}
+
+module_init(pn544_mei_init);
+module_exit(pn544_mei_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 0ab6712fd76b..f14a98a79c9d 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -134,6 +134,7 @@ struct bcma_host_ops {
#define BCMA_CORE_I2S 0x834
#define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */
#define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */
+#define BCMA_CORE_ARM_CR4 0x83e
#define BCMA_CORE_DEFAULT 0xFFF
#define BCMA_MAX_NR_CORES 16
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index 453fcc914683..b8b09eac60a4 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -316,6 +316,9 @@
#define BCMA_CC_PMU_CTL 0x0600 /* PMU control */
#define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */
#define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16
+#define BCMA_CC_PMU_CTL_RES 0x00006000 /* reset control mask */
+#define BCMA_CC_PMU_CTL_RES_SHIFT 13
+#define BCMA_CC_PMU_CTL_RES_RELOAD 0x2 /* reload POR values */
#define BCMA_CC_PMU_CTL_PLL_UPD 0x00000400
#define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */
#define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h
index 7e8104bb7a7e..917dcd7965e7 100644
--- a/include/linux/bcma/bcma_regs.h
+++ b/include/linux/bcma/bcma_regs.h
@@ -37,6 +37,7 @@
#define BCMA_IOST_BIST_DONE 0x8000
#define BCMA_RESET_CTL 0x0800
#define BCMA_RESET_CTL_RESET 0x0001
+#define BCMA_RESET_ST 0x0804
/* BCMA PCI config space registers. */
#define BCMA_PCI_PMCSR 0x44
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 4cf0c9e4dd99..06b0ed0154a4 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -673,6 +673,36 @@ struct ieee80211_channel_sw_ie {
} __packed;
/**
+ * struct ieee80211_ext_chansw_ie
+ *
+ * This structure represents the "Extended Channel Switch Announcement element"
+ */
+struct ieee80211_ext_chansw_ie {
+ u8 mode;
+ u8 new_operating_class;
+ u8 new_ch_num;
+ u8 count;
+} __packed;
+
+/**
+ * struct ieee80211_sec_chan_offs_ie - secondary channel offset IE
+ * @sec_chan_offs: secondary channel offset, uses IEEE80211_HT_PARAM_CHA_SEC_*
+ * values here
+ * This structure represents the "Secondary Channel Offset element"
+ */
+struct ieee80211_sec_chan_offs_ie {
+ u8 sec_chan_offs;
+} __packed;
+
+/**
+ * struct ieee80211_wide_bw_chansw_ie - wide bandwidth channel switch IE
+ */
+struct ieee80211_wide_bw_chansw_ie {
+ u8 new_channel_width;
+ u8 new_center_freq_seg0, new_center_freq_seg1;
+} __packed;
+
+/**
* struct ieee80211_tim
*
* This structure refers to "Traffic Indication Map information element"
@@ -840,12 +870,15 @@ struct ieee80211_mgmt {
} __packed wme_action;
struct{
u8 action_code;
- u8 element_id;
- u8 length;
- struct ieee80211_channel_sw_ie sw_elem;
+ u8 variable[0];
} __packed chan_switch;
struct{
u8 action_code;
+ struct ieee80211_ext_chansw_ie data;
+ u8 variable[0];
+ } __packed ext_chan_switch;
+ struct{
+ u8 action_code;
u8 dialog_token;
u8 element_id;
u8 length;
@@ -1027,6 +1060,26 @@ enum ieee80211_p2p_attr_id {
IEEE80211_P2P_ATTR_MAX
};
+/* Notice of Absence attribute - described in P2P spec 4.1.14 */
+/* Typical max value used here */
+#define IEEE80211_P2P_NOA_DESC_MAX 4
+
+struct ieee80211_p2p_noa_desc {
+ u8 count;
+ __le32 duration;
+ __le32 interval;
+ __le32 start_time;
+} __packed;
+
+struct ieee80211_p2p_noa_attr {
+ u8 index;
+ u8 oppps_ctwindow;
+ struct ieee80211_p2p_noa_desc desc[IEEE80211_P2P_NOA_DESC_MAX];
+} __packed;
+
+#define IEEE80211_P2P_OPPPS_ENABLE_BIT BIT(7)
+#define IEEE80211_P2P_OPPPS_CTWINDOW_MASK 0x7F
+
/**
* struct ieee80211_bar - HT Block Ack Request
*
@@ -1618,6 +1671,7 @@ enum ieee80211_eid {
WLAN_EID_HT_CAPABILITY = 45,
WLAN_EID_HT_OPERATION = 61,
+ WLAN_EID_SECONDARY_CHANNEL_OFFSET = 62,
WLAN_EID_RSN = 48,
WLAN_EID_MMIE = 76,
@@ -1652,6 +1706,8 @@ enum ieee80211_eid {
WLAN_EID_VHT_CAPABILITY = 191,
WLAN_EID_VHT_OPERATION = 192,
WLAN_EID_OPMODE_NOTIF = 199,
+ WLAN_EID_WIDE_BW_CHANNEL_SWITCH = 194,
+ WLAN_EID_CHANNEL_SWITCH_WRAPPER = 196,
/* 802.11ad */
WLAN_EID_NON_TX_BSSID_CAP = 83,
@@ -1775,6 +1831,7 @@ enum ieee80211_key_len {
/* Public action codes */
enum ieee80211_pub_actioncode {
+ WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4,
WLAN_PUB_ACTION_TDLS_DISCOVER_RES = 14,
};
@@ -1935,6 +1992,16 @@ enum ieee80211_timeout_interval_type {
WLAN_TIMEOUT_ASSOC_COMEBACK = 3 /* 802.11w */,
};
+/**
+ * struct ieee80211_timeout_interval_ie - Timeout Interval element
+ * @type: type, see &enum ieee80211_timeout_interval_type
+ * @value: timeout interval value
+ */
+struct ieee80211_timeout_interval_ie {
+ u8 type;
+ __le32 value;
+} __packed;
+
/* BACK action code */
enum ieee80211_back_actioncode {
WLAN_ACTION_ADDBA_REQ = 0,
diff --git a/include/linux/platform_data/brcmfmac-sdio.h b/include/linux/platform_data/brcmfmac-sdio.h
new file mode 100644
index 000000000000..1ade657d5fc1
--- /dev/null
+++ b/include/linux/platform_data/brcmfmac-sdio.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_BRCMFMAC_PLATFORM_H
+#define _LINUX_BRCMFMAC_PLATFORM_H
+
+/*
+ * Platform specific driver functions and data. Through the platform specific
+ * device data functions can be provided to help the brcmfmac driver to
+ * operate with the device in combination with the used platform.
+ *
+ * Use the platform data in the following (similar) way:
+ *
+ *
+#include <brcmfmac_platform.h>
+
+
+static void brcmfmac_power_on(void)
+{
+}
+
+static void brcmfmac_power_off(void)
+{
+}
+
+static void brcmfmac_reset(void)
+{
+}
+
+static struct brcmfmac_sdio_platform_data brcmfmac_sdio_pdata = {
+ .power_on = brcmfmac_power_on,
+ .power_off = brcmfmac_power_off,
+ .reset = brcmfmac_reset
+};
+
+static struct platform_device brcmfmac_device = {
+ .name = BRCMFMAC_SDIO_PDATA_NAME,
+ .id = PLATFORM_DEVID_NONE,
+ .dev.platform_data = &brcmfmac_sdio_pdata
+};
+
+void __init brcmfmac_init_pdata(void)
+{
+ brcmfmac_sdio_pdata.oob_irq_supported = true;
+ brcmfmac_sdio_pdata.oob_irq_nr = gpio_to_irq(GPIO_BRCMF_SDIO_OOB);
+ brcmfmac_sdio_pdata.oob_irq_flags = IORESOURCE_IRQ |
+ IORESOURCE_IRQ_HIGHLEVEL;
+ platform_device_register(&brcmfmac_device);
+}
+ *
+ *
+ * Note: the brcmfmac can be loaded as module or be statically built-in into
+ * the kernel. If built-in then do note that it uses module_init (and
+ * module_exit) routines which equal device_initcall. So if you intend to
+ * create a module with the platform specific data for the brcmfmac and have
+ * it built-in to the kernel then use a higher initcall then device_initcall
+ * (see init.h). If this is not done then brcmfmac will load without problems
+ * but will not pickup the platform data.
+ *
+ * When the driver does not "detect" platform driver data then it will continue
+ * without reporting anything and just assume there is no data needed. Which is
+ * probably true for most platforms.
+ *
+ * Explanation of the platform_data fields:
+ *
+ * drive_strength: is the preferred drive_strength to be used for the SDIO
+ * pins. If 0 then a default value will be used. This is the target drive
+ * strength, the exact drive strength which will be used depends on the
+ * capabilities of the device.
+ *
+ * oob_irq_supported: does the board have support for OOB interrupts. SDIO
+ * in-band interrupts are relatively slow and for having less overhead on
+ * interrupt processing an out of band interrupt can be used. If the HW
+ * supports this then enable this by setting this field to true and configure
+ * the oob related fields.
+ *
+ * oob_irq_nr, oob_irq_flags: the OOB interrupt information. The values are
+ * used for registering the irq using request_irq function.
+ *
+ * power_on: This function is called by the brcmfmac when the module gets
+ * loaded. This can be particularly useful for low power devices. The platform
+ * spcific routine may for example decide to power up the complete device.
+ * If there is no use-case for this function then provide NULL.
+ *
+ * power_off: This function is called by the brcmfmac when the module gets
+ * unloaded. At this point the device can be powered down or otherwise be reset.
+ * So if an actual power_off is not supported but reset is then reset the device
+ * when this function gets called. This can be particularly useful for low power
+ * devices. If there is no use-case for this function (either power-down or
+ * reset) then provide NULL.
+ *
+ * reset: This function can get called if the device communication broke down.
+ * This functionality is particularly useful in case of SDIO type devices. It is
+ * possible to reset a dongle via sdio data interface, but it requires that
+ * this is fully functional. This function is chip/module specific and this
+ * function should return only after the complete reset has completed.
+ */
+
+#define BRCMFMAC_SDIO_PDATA_NAME "brcmfmac_sdio"
+
+struct brcmfmac_sdio_platform_data {
+ unsigned int drive_strength;
+ bool oob_irq_supported;
+ unsigned int oob_irq_nr;
+ unsigned long oob_irq_flags;
+ void (*power_on)(void);
+ void (*power_off)(void);
+ void (*reset)(void);
+};
+
+#endif /* _LINUX_BRCMFMAC_PLATFORM_H */
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index ed6e9552252e..6912ef9a1881 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -193,11 +193,11 @@ static inline bool bdaddr_type_is_le(__u8 type)
#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff} })
/* Copy, swap, convert BD Address */
-static inline int bacmp(bdaddr_t *ba1, bdaddr_t *ba2)
+static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
{
return memcmp(ba1, ba2, sizeof(bdaddr_t));
}
-static inline void bacpy(bdaddr_t *dst, bdaddr_t *src)
+static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src)
{
memcpy(dst, src, sizeof(bdaddr_t));
}
@@ -266,6 +266,7 @@ typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status);
struct hci_req_ctrl {
bool start;
+ u8 event;
hci_req_complete_t complete;
};
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index b3308927a0a1..e0512aaef4b8 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -984,6 +984,9 @@ struct hci_cp_le_set_adv_data {
#define HCI_OP_LE_SET_ADV_ENABLE 0x200a
+#define LE_SCAN_PASSIVE 0x00
+#define LE_SCAN_ACTIVE 0x01
+
#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
struct hci_cp_le_set_scan_param {
__u8 type;
@@ -993,8 +996,10 @@ struct hci_cp_le_set_scan_param {
__u8 filter_policy;
} __packed;
-#define LE_SCANNING_DISABLED 0x00
-#define LE_SCANNING_ENABLED 0x01
+#define LE_SCAN_DISABLE 0x00
+#define LE_SCAN_ENABLE 0x01
+#define LE_SCAN_FILTER_DUP_DISABLE 0x00
+#define LE_SCAN_FILTER_DUP_ENABLE 0x01
#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
struct hci_cp_le_set_scan_enable {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 358a6983d3bb..80d718a9b31f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -134,6 +134,8 @@ struct amp_assoc {
__u8 data[HCI_MAX_AMP_ASSOC_SIZE];
};
+#define HCI_MAX_PAGES 3
+
#define NUM_REASSEMBLY 4
struct hci_dev {
struct list_head list;
@@ -151,8 +153,8 @@ struct hci_dev {
__u8 dev_class[3];
__u8 major_class;
__u8 minor_class;
- __u8 features[8];
- __u8 host_features[8];
+ __u8 max_page;
+ __u8 features[HCI_MAX_PAGES][8];
__u8 le_features[8];
__u8 le_white_list_size;
__u8 le_states[8];
@@ -244,6 +246,7 @@ struct hci_dev {
struct sk_buff_head raw_q;
struct sk_buff_head cmd_q;
+ struct sk_buff *recv_evt;
struct sk_buff *sent_cmd;
struct sk_buff *reassembly[NUM_REASSEMBLY];
@@ -268,8 +271,6 @@ struct hci_dev {
struct hci_dev_stats stat;
- struct sk_buff_head driver_init;
-
atomic_t promisc;
struct dentry *debugfs;
@@ -292,6 +293,7 @@ struct hci_dev {
int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev);
+ int (*setup)(struct hci_dev *hdev);
int (*send)(struct sk_buff *skb);
void (*notify)(struct hci_dev *hdev, unsigned int evt);
int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
@@ -313,7 +315,7 @@ struct hci_conn {
bool out;
__u8 attempt;
__u8 dev_class[3];
- __u8 features[8];
+ __u8 features[HCI_MAX_PAGES][8];
__u16 interval;
__u16 pkt_type;
__u16 link_policy;
@@ -345,7 +347,6 @@ struct hci_conn {
struct timer_list auto_accept_timer;
struct device dev;
- atomic_t devref;
struct hci_dev *hdev;
void *l2cap_data;
@@ -584,7 +585,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
-void hci_conn_accept(struct hci_conn *conn, int mask);
struct hci_chan *hci_chan_create(struct hci_conn *conn);
void hci_chan_del(struct hci_chan *chan);
@@ -601,8 +601,36 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
-void hci_conn_hold_device(struct hci_conn *conn);
-void hci_conn_put_device(struct hci_conn *conn);
+/*
+ * hci_conn_get() and hci_conn_put() are used to control the life-time of an
+ * "hci_conn" object. They do not guarantee that the hci_conn object is running,
+ * working or anything else. They just guarantee that the object is available
+ * and can be dereferenced. So you can use its locks, local variables and any
+ * other constant data.
+ * Before accessing runtime data, you _must_ lock the object and then check that
+ * it is still running. As soon as you release the locks, the connection might
+ * get dropped, though.
+ *
+ * On the other hand, hci_conn_hold() and hci_conn_drop() are used to control
+ * how long the underlying connection is held. So every channel that runs on the
+ * hci_conn object calls this to prevent the connection from disappearing. As
+ * long as you hold a device, you must also guarantee that you have a valid
+ * reference to the device via hci_conn_get() (or the initial reference from
+ * hci_conn_add()).
+ * The hold()/drop() ref-count is known to drop below 0 sometimes, which doesn't
+ * break because nobody cares for that. But this means, we cannot use
+ * _get()/_drop() in it, but require the caller to have a valid ref (FIXME).
+ */
+
+static inline void hci_conn_get(struct hci_conn *conn)
+{
+ get_device(&conn->dev);
+}
+
+static inline void hci_conn_put(struct hci_conn *conn)
+{
+ put_device(&conn->dev);
+}
static inline void hci_conn_hold(struct hci_conn *conn)
{
@@ -612,7 +640,7 @@ static inline void hci_conn_hold(struct hci_conn *conn)
cancel_delayed_work(&conn->disc_work);
}
-static inline void hci_conn_put(struct hci_conn *conn)
+static inline void hci_conn_drop(struct hci_conn *conn)
{
BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
@@ -760,29 +788,29 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
/* ----- LMP capabilities ----- */
-#define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT)
-#define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH)
-#define lmp_hold_capable(dev) ((dev)->features[0] & LMP_HOLD)
-#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
-#define lmp_park_capable(dev) ((dev)->features[1] & LMP_PARK)
-#define lmp_inq_rssi_capable(dev) ((dev)->features[3] & LMP_RSSI_INQ)
-#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
-#define lmp_bredr_capable(dev) (!((dev)->features[4] & LMP_NO_BREDR))
-#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
-#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
-#define lmp_pause_enc_capable(dev) ((dev)->features[5] & LMP_PAUSE_ENC)
-#define lmp_ext_inq_capable(dev) ((dev)->features[6] & LMP_EXT_INQ)
-#define lmp_le_br_capable(dev) !!((dev)->features[6] & LMP_SIMUL_LE_BR)
-#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
-#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
-#define lmp_lsto_capable(dev) ((dev)->features[7] & LMP_LSTO)
-#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[7] & LMP_INQ_TX_PWR)
-#define lmp_ext_feat_capable(dev) ((dev)->features[7] & LMP_EXTFEATURES)
+#define lmp_encrypt_capable(dev) ((dev)->features[0][0] & LMP_ENCRYPT)
+#define lmp_rswitch_capable(dev) ((dev)->features[0][0] & LMP_RSWITCH)
+#define lmp_hold_capable(dev) ((dev)->features[0][0] & LMP_HOLD)
+#define lmp_sniff_capable(dev) ((dev)->features[0][0] & LMP_SNIFF)
+#define lmp_park_capable(dev) ((dev)->features[0][1] & LMP_PARK)
+#define lmp_inq_rssi_capable(dev) ((dev)->features[0][3] & LMP_RSSI_INQ)
+#define lmp_esco_capable(dev) ((dev)->features[0][3] & LMP_ESCO)
+#define lmp_bredr_capable(dev) (!((dev)->features[0][4] & LMP_NO_BREDR))
+#define lmp_le_capable(dev) ((dev)->features[0][4] & LMP_LE)
+#define lmp_sniffsubr_capable(dev) ((dev)->features[0][5] & LMP_SNIFF_SUBR)
+#define lmp_pause_enc_capable(dev) ((dev)->features[0][5] & LMP_PAUSE_ENC)
+#define lmp_ext_inq_capable(dev) ((dev)->features[0][6] & LMP_EXT_INQ)
+#define lmp_le_br_capable(dev) (!!((dev)->features[0][6] & LMP_SIMUL_LE_BR))
+#define lmp_ssp_capable(dev) ((dev)->features[0][6] & LMP_SIMPLE_PAIR)
+#define lmp_no_flush_capable(dev) ((dev)->features[0][6] & LMP_NO_FLUSH)
+#define lmp_lsto_capable(dev) ((dev)->features[0][7] & LMP_LSTO)
+#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[0][7] & LMP_INQ_TX_PWR)
+#define lmp_ext_feat_capable(dev) ((dev)->features[0][7] & LMP_EXTFEATURES)
/* ----- Extended LMP capabilities ----- */
-#define lmp_host_ssp_capable(dev) ((dev)->host_features[0] & LMP_HOST_SSP)
-#define lmp_host_le_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE)
-#define lmp_host_le_br_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE_BREDR)
+#define lmp_host_ssp_capable(dev) ((dev)->features[1][0] & LMP_HOST_SSP)
+#define lmp_host_le_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE))
+#define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR))
/* returns true if at least one AMP active */
static inline bool hci_amp_capable(void)
@@ -1054,8 +1082,14 @@ struct hci_request {
void hci_req_init(struct hci_request *req, struct hci_dev *hdev);
int hci_req_run(struct hci_request *req, hci_req_complete_t complete);
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param);
+void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
+ u8 event);
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
-void hci_req_cmd_status(struct hci_dev *hdev, u16 opcode, u8 status);
+
+struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void *param, u32 timeout);
+struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void *param, u8 event, u32 timeout);
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index cdd33021f831..fb94cf13c777 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -583,6 +583,14 @@ struct l2cap_conn {
struct list_head chan_l;
struct mutex chan_lock;
+ struct kref ref;
+ struct list_head users;
+};
+
+struct l2cap_user {
+ struct list_head list;
+ int (*probe) (struct l2cap_conn *conn, struct l2cap_user *user);
+ void (*remove) (struct l2cap_conn *conn, struct l2cap_user *user);
};
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
@@ -786,6 +794,7 @@ extern bool disable_ertm;
int l2cap_init_sockets(void);
void l2cap_cleanup_sockets(void);
+bool l2cap_is_socket(struct socket *sock);
void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
int __l2cap_wait_ack(struct sock *sk);
@@ -812,4 +821,10 @@ void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
u8 status);
void __l2cap_physical_cfm(struct l2cap_chan *chan, int result);
+void l2cap_conn_get(struct l2cap_conn *conn);
+void l2cap_conn_put(struct l2cap_conn *conn);
+
+int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user);
+void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user);
+
#endif /* __L2CAP_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bdba9b619064..26b5b692c22b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1998,6 +1998,16 @@ struct cfg80211_update_ft_ies_params {
* advertise the support for MAC based ACL have to implement this callback.
*
* @start_radar_detection: Start radar detection in the driver.
+ *
+ * @update_ft_ies: Provide updated Fast BSS Transition information to the
+ * driver. If the SME is in the driver/firmware, this information can be
+ * used in building Authentication and Reassociation Request frames.
+ *
+ * @crit_proto_start: Indicates a critical protocol needs more link reliability
+ * for a given duration (milliseconds). The protocol is provided so the
+ * driver can take the most appropriate actions.
+ * @crit_proto_stop: Indicates critical protocol no longer needs increased link
+ * reliability. This operation can not fail.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2227,6 +2237,12 @@ struct cfg80211_ops {
struct cfg80211_chan_def *chandef);
int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_update_ft_ies_params *ftie);
+ int (*crit_proto_start)(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ enum nl80211_crit_proto_id protocol,
+ u16 duration);
+ void (*crit_proto_stop)(struct wiphy *wiphy,
+ struct wireless_dev *wdev);
};
/*
@@ -4020,6 +4036,17 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
void cfg80211_ch_switch_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef);
+/**
+ * ieee80211_operating_class_to_band - convert operating class to band
+ *
+ * @operating_class: the operating class to convert
+ * @band: band pointer to fill
+ *
+ * Returns %true if the conversion was successful, %false otherwise.
+ */
+bool ieee80211_operating_class_to_band(u8 operating_class,
+ enum ieee80211_band *band);
+
/*
* cfg80211_tdls_oper_request - request userspace to perform TDLS operation
* @dev: the device on which the operation is requested
@@ -4122,6 +4149,17 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
struct cfg80211_wowlan_wakeup *wakeup,
gfp_t gfp);
+/**
+ * cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver.
+ *
+ * @wdev: the wireless device for which critical protocol is stopped.
+ *
+ * This function can be called by the driver to indicate it has reverted
+ * operation back to normal. One reason could be that the duration given
+ * by .crit_proto_start() has expired.
+ */
+void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp);
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index dd73b8c6746b..04c2d4670dc6 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -128,6 +128,7 @@ enum ieee80211_ac_numbers {
* 2^n-1 in the range 1..32767]
* @cw_max: maximum contention window [like @cw_min]
* @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
+ * @acm: is mandatory admission control required for the access category
* @uapsd: is U-APSD mode enabled for the queue
*/
struct ieee80211_tx_queue_params {
@@ -135,6 +136,7 @@ struct ieee80211_tx_queue_params {
u16 cw_min;
u16 cw_max;
u8 aifs;
+ bool acm;
bool uapsd;
};
@@ -209,7 +211,7 @@ struct ieee80211_chanctx_conf {
* @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
* that it is only ever disabled for station mode.
* @BSS_CHANGED_IDLE: Idle changed for this BSS/interface.
- * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
+ * @BSS_CHANGED_SSID: SSID changed for this BSS (AP and IBSS mode)
* @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
* @BSS_CHANGED_PS: PS changed for this BSS (STA mode)
* @BSS_CHANGED_TXPOWER: TX power setting changed for this interface
@@ -326,12 +328,11 @@ enum ieee80211_rssi_event {
* your driver/device needs to do.
* @ps: power-save mode (STA only). This flag is NOT affected by
* offchannel/dynamic_ps operations.
- * @ssid: The SSID of the current vif. Only valid in AP-mode.
+ * @ssid: The SSID of the current vif. Valid in AP and IBSS mode.
* @ssid_len: Length of SSID given in @ssid.
* @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
* @txpower: TX power in dBm
- * @p2p_ctwindow: P2P CTWindow, only for P2P client interfaces
- * @p2p_oppps: P2P opportunistic PS is enabled
+ * @p2p_noa_attr: P2P NoA attribute for P2P powersave
*/
struct ieee80211_bss_conf {
const u8 *bssid;
@@ -365,8 +366,7 @@ struct ieee80211_bss_conf {
size_t ssid_len;
bool hidden_ssid;
int txpower;
- u8 p2p_ctwindow;
- bool p2p_oppps;
+ struct ieee80211_p2p_noa_attr p2p_noa_attr;
};
/**
@@ -563,6 +563,9 @@ enum mac80211_rate_control_flags {
/* maximum number of rate stages */
#define IEEE80211_TX_MAX_RATES 4
+/* maximum number of rate table entries */
+#define IEEE80211_TX_RATE_TABLE_SIZE 4
+
/**
* struct ieee80211_tx_rate - rate selection/status
*
@@ -603,8 +606,8 @@ static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate,
u8 mcs, u8 nss)
{
WARN_ON(mcs & ~0xF);
- WARN_ON(nss & ~0x7);
- rate->idx = (nss << 4) | mcs;
+ WARN_ON((nss - 1) & ~0x7);
+ rate->idx = ((nss - 1) << 4) | mcs;
}
static inline u8
@@ -616,7 +619,7 @@ ieee80211_rate_get_vht_mcs(const struct ieee80211_tx_rate *rate)
static inline u8
ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate)
{
- return rate->idx >> 4;
+ return (rate->idx >> 4) + 1;
}
/**
@@ -657,7 +660,11 @@ struct ieee80211_tx_info {
struct ieee80211_tx_rate rates[
IEEE80211_TX_MAX_RATES];
s8 rts_cts_rate_idx;
- /* 3 bytes free */
+ u8 use_rts:1;
+ u8 use_cts_prot:1;
+ u8 short_preamble:1;
+ u8 skip_table:1;
+ /* 2 bytes free */
};
/* only needed before rate control */
unsigned long jiffies;
@@ -678,6 +685,8 @@ struct ieee80211_tx_info {
struct {
struct ieee80211_tx_rate driver_rates[
IEEE80211_TX_MAX_RATES];
+ u8 pad[4];
+
void *rate_driver_data[
IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE / sizeof(void *)];
};
@@ -976,8 +985,7 @@ enum ieee80211_smps_mode {
* @power_level: requested transmit power (in dBm), backward compatibility
* value only that is set to the minimum of all interfaces
*
- * @channel: the channel to tune to
- * @channel_type: the channel (HT) type
+ * @chandef: the channel definition to tune to
* @radar_enabled: whether radar detection is enabled
*
* @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame
@@ -1003,8 +1011,7 @@ struct ieee80211_conf {
u8 long_frame_max_tx_count, short_frame_max_tx_count;
- struct ieee80211_channel *channel;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
bool radar_enabled;
enum ieee80211_smps_mode smps_mode;
};
@@ -1021,13 +1028,13 @@ struct ieee80211_conf {
* the driver passed into mac80211.
* @block_tx: Indicates whether transmission must be blocked before the
* scheduled channel switch, as indicated by the AP.
- * @channel: the new channel to switch to
+ * @chandef: the new channel to switch to
* @count: the number of TBTT's until the channel switch event
*/
struct ieee80211_channel_switch {
u64 timestamp;
bool block_tx;
- struct ieee80211_channel *channel;
+ struct cfg80211_chan_def chandef;
u8 count;
};
@@ -1225,6 +1232,24 @@ enum ieee80211_sta_rx_bandwidth {
};
/**
+ * struct ieee80211_sta_rates - station rate selection table
+ *
+ * @rcu_head: RCU head used for freeing the table on update
+ * @rates: transmit rates/flags to be used by default.
+ * Overriding entries per-packet is possible by using cb tx control.
+ */
+struct ieee80211_sta_rates {
+ struct rcu_head rcu_head;
+ struct {
+ s8 idx;
+ u8 count;
+ u8 count_cts;
+ u8 count_rts;
+ u16 flags;
+ } rate[IEEE80211_TX_RATE_TABLE_SIZE];
+};
+
+/**
* struct ieee80211_sta - station table entry
*
* A station table entry represents a station we are possibly
@@ -1251,6 +1276,7 @@ enum ieee80211_sta_rx_bandwidth {
* notifications and capabilities. The value is only valid after
* the station moves to associated state.
* @smps_mode: current SMPS mode (off, static or dynamic)
+ * @tx_rates: rate control selection table
*/
struct ieee80211_sta {
u32 supp_rates[IEEE80211_NUM_BANDS];
@@ -1264,6 +1290,7 @@ struct ieee80211_sta {
u8 rx_nss;
enum ieee80211_sta_rx_bandwidth bandwidth;
enum ieee80211_smps_mode smps_mode;
+ struct ieee80211_sta_rates __rcu *rates;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
@@ -1419,6 +1446,9 @@ struct ieee80211_tx_control {
* for different virtual interfaces. See the doc section on HW queue
* control for more details.
*
+ * @IEEE80211_HW_SUPPORTS_RC_TABLE: The driver supports using a rate
+ * selection table provided by the rate control algorithm.
+ *
* @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any
* P2P Interface. This will be honoured even if more than one interface
* is supported.
@@ -1451,6 +1481,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21,
IEEE80211_HW_AP_LINK_PS = 1<<22,
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23,
+ IEEE80211_HW_SUPPORTS_RC_TABLE = 1<<24,
IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25,
IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26,
};
@@ -1536,6 +1567,17 @@ enum ieee80211_hw_flags {
* @netdev_features: netdev features to be set in each netdev created
* from this HW. Note only HW checksum features are currently
* compatible with mac80211. Other feature bits will be rejected.
+ *
+ * @uapsd_queues: This bitmap is included in (re)association frame to indicate
+ * for each access category if it is uAPSD trigger-enabled and delivery-
+ * enabled. Use IEEE80211_WMM_IE_STA_QOSINFO_AC_* to set this bitmap.
+ * Each bit corresponds to different AC. Value '1' in specific bit means
+ * that corresponding AC is both trigger- and delivery-enabled. '0' means
+ * neither enabled.
+ *
+ * @uapsd_max_sp_len: maximum number of total buffered frames the WMM AP may
+ * deliver to a WMM STA during any Service Period triggered by the WMM STA.
+ * Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values.
*/
struct ieee80211_hw {
struct ieee80211_conf conf;
@@ -1561,6 +1603,8 @@ struct ieee80211_hw {
u8 radiotap_mcs_details;
u16 radiotap_vht_details;
netdev_features_t netdev_features;
+ u8 uapsd_queues;
+ u8 uapsd_max_sp_len;
};
/**
@@ -3124,6 +3168,25 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *sta,
u8 tid, bool buffered);
/**
+ * ieee80211_get_tx_rates - get the selected transmit rates for a packet
+ *
+ * Call this function in a driver with per-packet rate selection support
+ * to combine the rate info in the packet tx info with the most recent
+ * rate selection table for the station entry.
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @sta: the receiver station to which this packet is sent.
+ * @skb: the frame to be transmitted.
+ * @dest: buffer for extracted rate/retry information
+ * @max_rates: maximum number of rates to fetch
+ */
+void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb,
+ struct ieee80211_tx_rate *dest,
+ int max_rates);
+
+/**
* ieee80211_tx_status - transmit status callback
*
* Call this function for all transmitted frames after they have been
@@ -4098,7 +4161,7 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
* (deprecated; this will be removed once drivers get updated to use
* rate_idx_mask)
* @rate_idx_mask: user-requested (legacy) rate mask
- * @rate_idx_mcs_mask: user-requested MCS rate mask
+ * @rate_idx_mcs_mask: user-requested MCS rate mask (NULL if not in use)
* @bss: whether this frame is sent out in AP or IBSS mode
*/
struct ieee80211_tx_rate_control {
@@ -4110,7 +4173,7 @@ struct ieee80211_tx_rate_control {
bool rts, short_preamble;
u8 max_rate_idx;
u32 rate_idx_mask;
- u8 rate_idx_mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
+ u8 *rate_idx_mcs_mask;
bool bss;
};
@@ -4199,37 +4262,55 @@ bool rate_usable_index_exists(struct ieee80211_supported_band *sband,
return false;
}
+/**
+ * rate_control_set_rates - pass the sta rate selection to mac80211/driver
+ *
+ * When not doing a rate control probe to test rates, rate control should pass
+ * its rate selection to mac80211. If the driver supports receiving a station
+ * rate table, it will use it to ensure that frames are always sent based on
+ * the most recent rate control module decision.
+ *
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ * @pubsta: &struct ieee80211_sta pointer to the target destination.
+ * @rates: new tx rate set to be used for this station.
+ */
+int rate_control_set_rates(struct ieee80211_hw *hw,
+ struct ieee80211_sta *pubsta,
+ struct ieee80211_sta_rates *rates);
+
int ieee80211_rate_control_register(struct rate_control_ops *ops);
void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
static inline bool
conf_is_ht20(struct ieee80211_conf *conf)
{
- return conf->channel_type == NL80211_CHAN_HT20;
+ return conf->chandef.width == NL80211_CHAN_WIDTH_20;
}
static inline bool
conf_is_ht40_minus(struct ieee80211_conf *conf)
{
- return conf->channel_type == NL80211_CHAN_HT40MINUS;
+ return conf->chandef.width == NL80211_CHAN_WIDTH_40 &&
+ conf->chandef.center_freq1 < conf->chandef.chan->center_freq;
}
static inline bool
conf_is_ht40_plus(struct ieee80211_conf *conf)
{
- return conf->channel_type == NL80211_CHAN_HT40PLUS;
+ return conf->chandef.width == NL80211_CHAN_WIDTH_40 &&
+ conf->chandef.center_freq1 > conf->chandef.chan->center_freq;
}
static inline bool
conf_is_ht40(struct ieee80211_conf *conf)
{
- return conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf);
+ return conf->chandef.width == NL80211_CHAN_WIDTH_40;
}
static inline bool
conf_is_ht(struct ieee80211_conf *conf)
{
- return conf->channel_type != NL80211_CHAN_NO_HT;
+ return conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT;
}
static inline enum nl80211_iftype
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 87a6417fc934..5eb80bb3cbb2 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -122,6 +122,8 @@ struct nfc_dev {
bool shutting_down;
+ struct rfkill *rfkill;
+
struct nfc_ops *ops;
};
#define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev)
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h
index 7440bc81a04b..7c6f627a717d 100644
--- a/include/uapi/linux/nfc.h
+++ b/include/uapi/linux/nfc.h
@@ -233,7 +233,10 @@ struct sockaddr_nfc_llcp {
#define NFC_LLCP_DIRECTION_TX 0x01
/* socket option names */
-#define NFC_LLCP_RW 0
-#define NFC_LLCP_MIUX 1
+#define NFC_LLCP_RW 0
+#define NFC_LLCP_MIUX 1
+#define NFC_LLCP_REMOTE_MIU 2
+#define NFC_LLCP_REMOTE_LTO 3
+#define NFC_LLCP_REMOTE_RW 4
#endif /*__LINUX_NFC_H */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 79da8710448e..d1e48b5e348f 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -639,6 +639,13 @@
* with the relevant Information Elements. This event is used to report
* received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
*
+ * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running
+ * a critical protocol that needs more reliability in the connection to
+ * complete.
+ *
+ * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
+ * return back to normal.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -798,6 +805,9 @@ enum nl80211_commands {
NL80211_CMD_UPDATE_FT_IES,
NL80211_CMD_FT_EVENT,
+ NL80211_CMD_CRIT_PROTOCOL_START,
+ NL80211_CMD_CRIT_PROTOCOL_STOP,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1414,6 +1424,11 @@ enum nl80211_commands {
* @NL80211_ATTR_IE_RIC: Resource Information Container Information
* Element
*
+ * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased
+ * reliability, see &enum nl80211_crit_proto_id (u16).
+ * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
+ * the connection should have increased reliability (u16).
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1709,6 +1724,9 @@ enum nl80211_attrs {
NL80211_ATTR_MDID,
NL80211_ATTR_IE_RIC,
+ NL80211_ATTR_CRIT_PROT_ID,
+ NL80211_ATTR_MAX_CRIT_PROT_DURATION,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -3682,4 +3700,25 @@ enum nl80211_protocol_features {
NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0,
};
+/**
+ * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers
+ *
+ * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified.
+ * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol.
+ * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol.
+ * @NL80211_CRIT_PROTO_APIPA: APIPA protocol.
+ * @NUM_NL80211_CRIT_PROTO: must be kept last.
+ */
+enum nl80211_crit_proto_id {
+ NL80211_CRIT_PROTO_UNSPEC,
+ NL80211_CRIT_PROTO_DHCP,
+ NL80211_CRIT_PROTO_EAPOL,
+ NL80211_CRIT_PROTO_APIPA,
+ /* add other protocols before this one */
+ NUM_NL80211_CRIT_PROTO
+};
+
+/* maximum duration for critical protocol measures */
+#define NL80211_CRIT_PROTO_MAX_DURATION 5000 /* msec */
+
#endif /* __LINUX_NL80211_H */
diff --git a/include/uapi/linux/rfkill.h b/include/uapi/linux/rfkill.h
index 2753c6cc9740..058757f7a733 100644
--- a/include/uapi/linux/rfkill.h
+++ b/include/uapi/linux/rfkill.h
@@ -37,6 +37,7 @@
* @RFKILL_TYPE_WWAN: switch is on a wireless WAN device.
* @RFKILL_TYPE_GPS: switch is on a GPS device.
* @RFKILL_TYPE_FM: switch is on a FM radio device.
+ * @RFKILL_TYPE_NFC: switch is on an NFC device.
* @NUM_RFKILL_TYPES: number of defined rfkill types
*/
enum rfkill_type {
@@ -48,6 +49,7 @@ enum rfkill_type {
RFKILL_TYPE_WWAN,
RFKILL_TYPE_GPS,
RFKILL_TYPE_FM,
+ RFKILL_TYPE_NFC,
NUM_RFKILL_TYPES,
};
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b9f90169940b..6c7f36379722 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -117,6 +117,16 @@ static void hci_acl_create_connection_cancel(struct hci_conn *conn)
hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
}
+static void hci_reject_sco(struct hci_conn *conn)
+{
+ struct hci_cp_reject_sync_conn_req cp;
+
+ cp.reason = HCI_ERROR_REMOTE_USER_TERM;
+ bacpy(&cp.bdaddr, &conn->dst);
+
+ hci_send_cmd(conn->hdev, HCI_OP_REJECT_SYNC_CONN_REQ, sizeof(cp), &cp);
+}
+
void hci_disconnect(struct hci_conn *conn, __u8 reason)
{
struct hci_cp_disconnect cp;
@@ -276,6 +286,8 @@ static void hci_conn_timeout(struct work_struct *work)
hci_acl_create_connection_cancel(conn);
else if (conn->type == LE_LINK)
hci_le_create_connection_cancel(conn);
+ } else if (conn->type == SCO_LINK || conn->type == ESCO_LINK) {
+ hci_reject_sco(conn);
}
break;
case BT_CONFIG:
@@ -398,8 +410,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
- atomic_set(&conn->devref, 0);
-
hci_conn_init_sysfs(conn);
return conn;
@@ -433,7 +443,7 @@ int hci_conn_del(struct hci_conn *conn)
struct hci_conn *acl = conn->link;
if (acl) {
acl->link = NULL;
- hci_conn_put(acl);
+ hci_conn_drop(acl);
}
}
@@ -448,12 +458,11 @@ int hci_conn_del(struct hci_conn *conn)
skb_queue_purge(&conn->data_q);
- hci_conn_put_device(conn);
+ hci_conn_del_sysfs(conn);
hci_dev_put(hdev);
- if (conn->handle == 0)
- kfree(conn);
+ hci_conn_put(conn);
return 0;
}
@@ -565,7 +574,7 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
if (!sco) {
sco = hci_conn_add(hdev, type, dst);
if (!sco) {
- hci_conn_put(acl);
+ hci_conn_drop(acl);
return ERR_PTR(-ENOMEM);
}
}
@@ -835,19 +844,6 @@ void hci_conn_check_pending(struct hci_dev *hdev)
hci_dev_unlock(hdev);
}
-void hci_conn_hold_device(struct hci_conn *conn)
-{
- atomic_inc(&conn->devref);
-}
-EXPORT_SYMBOL(hci_conn_hold_device);
-
-void hci_conn_put_device(struct hci_conn *conn)
-{
- if (atomic_dec_and_test(&conn->devref))
- hci_conn_del_sysfs(conn);
-}
-EXPORT_SYMBOL(hci_conn_put_device);
-
int hci_get_conn_list(void __user *arg)
{
struct hci_conn *c;
@@ -980,7 +976,7 @@ void hci_chan_del(struct hci_chan *chan)
synchronize_rcu();
- hci_conn_put(conn);
+ hci_conn_drop(conn);
skb_queue_purge(&chan->data_q);
kfree(chan);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index cfcad5423f1c..ce82265f5619 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -79,6 +79,121 @@ static void hci_req_cancel(struct hci_dev *hdev, int err)
}
}
+struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 event)
+{
+ struct hci_ev_cmd_complete *ev;
+ struct hci_event_hdr *hdr;
+ struct sk_buff *skb;
+
+ hci_dev_lock(hdev);
+
+ skb = hdev->recv_evt;
+ hdev->recv_evt = NULL;
+
+ hci_dev_unlock(hdev);
+
+ if (!skb)
+ return ERR_PTR(-ENODATA);
+
+ if (skb->len < sizeof(*hdr)) {
+ BT_ERR("Too short HCI event");
+ goto failed;
+ }
+
+ hdr = (void *) skb->data;
+ skb_pull(skb, HCI_EVENT_HDR_SIZE);
+
+ if (event) {
+ if (hdr->evt != event)
+ goto failed;
+ return skb;
+ }
+
+ if (hdr->evt != HCI_EV_CMD_COMPLETE) {
+ BT_DBG("Last event is not cmd complete (0x%2.2x)", hdr->evt);
+ goto failed;
+ }
+
+ if (skb->len < sizeof(*ev)) {
+ BT_ERR("Too short cmd_complete event");
+ goto failed;
+ }
+
+ ev = (void *) skb->data;
+ skb_pull(skb, sizeof(*ev));
+
+ if (opcode == __le16_to_cpu(ev->opcode))
+ return skb;
+
+ BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode,
+ __le16_to_cpu(ev->opcode));
+
+failed:
+ kfree_skb(skb);
+ return ERR_PTR(-ENODATA);
+}
+
+struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void *param, u8 event, u32 timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct hci_request req;
+ int err = 0;
+
+ BT_DBG("%s", hdev->name);
+
+ hci_req_init(&req, hdev);
+
+ hci_req_add_ev(&req, opcode, plen, param, event);
+
+ hdev->req_status = HCI_REQ_PEND;
+
+ err = hci_req_run(&req, hci_req_sync_complete);
+ if (err < 0)
+ return ERR_PTR(err);
+
+ add_wait_queue(&hdev->req_wait_q, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ schedule_timeout(timeout);
+
+ remove_wait_queue(&hdev->req_wait_q, &wait);
+
+ if (signal_pending(current))
+ return ERR_PTR(-EINTR);
+
+ switch (hdev->req_status) {
+ case HCI_REQ_DONE:
+ err = -bt_to_errno(hdev->req_result);
+ break;
+
+ case HCI_REQ_CANCELED:
+ err = -hdev->req_result;
+ break;
+
+ default:
+ err = -ETIMEDOUT;
+ break;
+ }
+
+ hdev->req_status = hdev->req_result = 0;
+
+ BT_DBG("%s end: err %d", hdev->name, err);
+
+ if (err < 0)
+ return ERR_PTR(err);
+
+ return hci_get_cmd_complete(hdev, opcode, event);
+}
+EXPORT_SYMBOL(__hci_cmd_sync_ev);
+
+struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void *param, u32 timeout)
+{
+ return __hci_cmd_sync_ev(hdev, opcode, plen, param, 0, timeout);
+}
+EXPORT_SYMBOL(__hci_cmd_sync);
+
/* Execute request and wait for completion. */
static int __hci_req_sync(struct hci_dev *hdev,
void (*func)(struct hci_request *req,
@@ -201,29 +316,9 @@ static void amp_init(struct hci_request *req)
static void hci_init1_req(struct hci_request *req, unsigned long opt)
{
struct hci_dev *hdev = req->hdev;
- struct hci_request init_req;
- struct sk_buff *skb;
BT_DBG("%s %ld", hdev->name, opt);
- /* Driver initialization */
-
- hci_req_init(&init_req, hdev);
-
- /* Special commands */
- while ((skb = skb_dequeue(&hdev->driver_init))) {
- bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
- skb->dev = (void *) hdev;
-
- if (skb_queue_empty(&init_req.cmd_q))
- bt_cb(skb)->req.start = true;
-
- skb_queue_tail(&init_req.cmd_q, skb);
- }
- skb_queue_purge(&hdev->driver_init);
-
- hci_req_run(&init_req, NULL);
-
/* Reset */
if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks))
hci_reset_req(req, 0);
@@ -494,6 +589,7 @@ static void hci_set_le_support(struct hci_request *req)
static void hci_init3_req(struct hci_request *req, unsigned long opt)
{
struct hci_dev *hdev = req->hdev;
+ u8 p;
if (hdev->commands[5] & 0x10)
hci_setup_link_policy(req);
@@ -502,6 +598,15 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
hci_set_le_support(req);
hci_update_ad(req);
}
+
+ /* Read features beyond page 1 if available */
+ for (p = 2; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) {
+ struct hci_cp_read_local_ext_features cp;
+
+ cp.page = p;
+ hci_req_add(req, HCI_OP_READ_LOCAL_EXT_FEATURES,
+ sizeof(cp), &cp);
+ }
}
static int __hci_init(struct hci_dev *hdev)
@@ -818,6 +923,12 @@ static void hci_inq_req(struct hci_request *req, unsigned long opt)
hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
}
+static int wait_inquiry(void *word)
+{
+ schedule();
+ return signal_pending(current);
+}
+
int hci_inquiry(void __user *arg)
{
__u8 __user *ptr = arg;
@@ -849,6 +960,13 @@ int hci_inquiry(void __user *arg)
timeo);
if (err < 0)
goto done;
+
+ /* Wait until Inquiry procedure finishes (HCI_INQUIRY flag is
+ * cleared). If it is interrupted by a signal, return -EINTR.
+ */
+ if (wait_on_bit(&hdev->flags, HCI_INQUIRY, wait_inquiry,
+ TASK_INTERRUPTIBLE))
+ return -EINTR;
}
/* for unlimited number of responses we will use buffer with
@@ -999,26 +1117,33 @@ int hci_dev_open(__u16 dev)
goto done;
}
- if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
- set_bit(HCI_RAW, &hdev->flags);
-
- /* Treat all non BR/EDR controllers as raw devices if
- enable_hs is not set */
- if (hdev->dev_type != HCI_BREDR && !enable_hs)
- set_bit(HCI_RAW, &hdev->flags);
-
if (hdev->open(hdev)) {
ret = -EIO;
goto done;
}
- if (!test_bit(HCI_RAW, &hdev->flags)) {
- atomic_set(&hdev->cmd_cnt, 1);
- set_bit(HCI_INIT, &hdev->flags);
- ret = __hci_init(hdev);
- clear_bit(HCI_INIT, &hdev->flags);
+ atomic_set(&hdev->cmd_cnt, 1);
+ set_bit(HCI_INIT, &hdev->flags);
+
+ if (hdev->setup && test_bit(HCI_SETUP, &hdev->dev_flags))
+ ret = hdev->setup(hdev);
+
+ if (!ret) {
+ /* Treat all non BR/EDR controllers as raw devices if
+ * enable_hs is not set.
+ */
+ if (hdev->dev_type != HCI_BREDR && !enable_hs)
+ set_bit(HCI_RAW, &hdev->flags);
+
+ if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+ set_bit(HCI_RAW, &hdev->flags);
+
+ if (!test_bit(HCI_RAW, &hdev->flags))
+ ret = __hci_init(hdev);
}
+ clear_bit(HCI_INIT, &hdev->flags);
+
if (!ret) {
hci_dev_hold(hdev);
set_bit(HCI_UP, &hdev->flags);
@@ -1123,6 +1248,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
hdev->sent_cmd = NULL;
}
+ kfree_skb(hdev->recv_evt);
+ hdev->recv_evt = NULL;
+
/* After this point our queues are empty
* and no tasks are scheduled. */
hdev->close(hdev);
@@ -1861,8 +1989,8 @@ static void le_scan_enable_req(struct hci_request *req, unsigned long opt)
struct hci_cp_le_set_scan_enable cp;
memset(&cp, 0, sizeof(cp));
- cp.enable = 1;
- cp.filter_dup = 1;
+ cp.enable = LE_SCAN_ENABLE;
+ cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
}
@@ -1896,7 +2024,7 @@ static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval,
return err;
queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
- msecs_to_jiffies(timeout));
+ timeout);
return 0;
}
@@ -2006,7 +2134,6 @@ struct hci_dev *hci_alloc_dev(void)
INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off);
INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work);
- skb_queue_head_init(&hdev->driver_init);
skb_queue_head_init(&hdev->rx_q);
skb_queue_head_init(&hdev->cmd_q);
skb_queue_head_init(&hdev->raw_q);
@@ -2025,8 +2152,6 @@ EXPORT_SYMBOL(hci_alloc_dev);
/* Free HCI device */
void hci_free_dev(struct hci_dev *hdev)
{
- skb_queue_purge(&hdev->driver_init);
-
/* will free via device release */
put_device(&hdev->dev);
}
@@ -2527,7 +2652,8 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
}
/* Queue a command to an asynchronous HCI request */
-void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
+void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
+ u8 event)
{
struct hci_dev *hdev = req->hdev;
struct sk_buff *skb;
@@ -2551,9 +2677,16 @@ void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
if (skb_queue_empty(&req->cmd_q))
bt_cb(skb)->req.start = true;
+ bt_cb(skb)->req.event = event;
+
skb_queue_tail(&req->cmd_q, skb);
}
+void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
+{
+ hci_req_add_ev(req, opcode, plen, param, 0);
+}
+
/* Get data from the previously sent command */
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
{
@@ -3309,32 +3442,6 @@ call_complete:
req_complete(hdev, status);
}
-void hci_req_cmd_status(struct hci_dev *hdev, u16 opcode, u8 status)
-{
- hci_req_complete_t req_complete = NULL;
-
- BT_DBG("opcode 0x%04x status 0x%02x", opcode, status);
-
- if (status) {
- hci_req_cmd_complete(hdev, opcode, status);
- return;
- }
-
- /* No need to handle success status if there are more commands */
- if (!hci_req_is_complete(hdev))
- return;
-
- if (hdev->sent_cmd)
- req_complete = bt_cb(hdev->sent_cmd)->req.complete;
-
- /* If the request doesn't have a complete callback or there
- * are other commands/requests in the hdev queue we consider
- * this request as completed.
- */
- if (!req_complete || !skb_queue_empty(&hdev->cmd_q))
- hci_req_cmd_complete(hdev, opcode, status);
-}
-
static void hci_rx_work(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 138580745c2c..b93cd2eb5d58 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -48,13 +48,13 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
}
clear_bit(HCI_INQUIRY, &hdev->flags);
+ smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
+ wake_up_bit(&hdev->flags, HCI_INQUIRY);
hci_dev_lock(hdev);
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
hci_dev_unlock(hdev);
- hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
-
hci_conn_check_pending(hdev);
}
@@ -433,9 +433,9 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
if (!status) {
if (sent->mode)
- hdev->host_features[0] |= LMP_HOST_SSP;
+ hdev->features[1][0] |= LMP_HOST_SSP;
else
- hdev->host_features[0] &= ~LMP_HOST_SSP;
+ hdev->features[1][0] &= ~LMP_HOST_SSP;
}
if (test_bit(HCI_MGMT, &hdev->dev_flags))
@@ -493,18 +493,18 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
/* Adjust default settings according to features
* supported by device. */
- if (hdev->features[0] & LMP_3SLOT)
+ if (hdev->features[0][0] & LMP_3SLOT)
hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
- if (hdev->features[0] & LMP_5SLOT)
+ if (hdev->features[0][0] & LMP_5SLOT)
hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
- if (hdev->features[1] & LMP_HV2) {
+ if (hdev->features[0][1] & LMP_HV2) {
hdev->pkt_type |= (HCI_HV2);
hdev->esco_type |= (ESCO_HV2);
}
- if (hdev->features[1] & LMP_HV3) {
+ if (hdev->features[0][1] & LMP_HV3) {
hdev->pkt_type |= (HCI_HV3);
hdev->esco_type |= (ESCO_HV3);
}
@@ -512,26 +512,26 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
if (lmp_esco_capable(hdev))
hdev->esco_type |= (ESCO_EV3);
- if (hdev->features[4] & LMP_EV4)
+ if (hdev->features[0][4] & LMP_EV4)
hdev->esco_type |= (ESCO_EV4);
- if (hdev->features[4] & LMP_EV5)
+ if (hdev->features[0][4] & LMP_EV5)
hdev->esco_type |= (ESCO_EV5);
- if (hdev->features[5] & LMP_EDR_ESCO_2M)
+ if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
hdev->esco_type |= (ESCO_2EV3);
- if (hdev->features[5] & LMP_EDR_ESCO_3M)
+ if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
hdev->esco_type |= (ESCO_3EV3);
- if (hdev->features[5] & LMP_EDR_3S_ESCO)
+ if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
- hdev->features[0], hdev->features[1],
- hdev->features[2], hdev->features[3],
- hdev->features[4], hdev->features[5],
- hdev->features[6], hdev->features[7]);
+ hdev->features[0][0], hdev->features[0][1],
+ hdev->features[0][2], hdev->features[0][3],
+ hdev->features[0][4], hdev->features[0][5],
+ hdev->features[0][6], hdev->features[0][7]);
}
static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
@@ -544,14 +544,10 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
if (rp->status)
return;
- switch (rp->page) {
- case 0:
- memcpy(hdev->features, rp->features, 8);
- break;
- case 1:
- memcpy(hdev->host_features, rp->features, 8);
- break;
- }
+ hdev->max_page = rp->max_page;
+
+ if (rp->page < HCI_MAX_PAGES)
+ memcpy(hdev->features[rp->page], rp->features, 8);
}
static void hci_cc_read_flow_control_mode(struct hci_dev *hdev,
@@ -968,7 +964,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
return;
switch (cp->enable) {
- case LE_SCANNING_ENABLED:
+ case LE_SCAN_ENABLE:
if (status) {
hci_dev_lock(hdev);
mgmt_start_discovery_failed(hdev, status);
@@ -983,7 +979,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
hci_dev_unlock(hdev);
break;
- case LE_SCANNING_DISABLED:
+ case LE_SCAN_DISABLE:
if (status) {
hci_dev_lock(hdev);
mgmt_stop_discovery_failed(hdev, status);
@@ -1046,14 +1042,14 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
if (!status) {
if (sent->le)
- hdev->host_features[0] |= LMP_HOST_LE;
+ hdev->features[1][0] |= LMP_HOST_LE;
else
- hdev->host_features[0] &= ~LMP_HOST_LE;
+ hdev->features[1][0] &= ~LMP_HOST_LE;
if (sent->simul)
- hdev->host_features[0] |= LMP_HOST_LE_BREDR;
+ hdev->features[1][0] |= LMP_HOST_LE_BREDR;
else
- hdev->host_features[0] &= ~LMP_HOST_LE_BREDR;
+ hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
}
if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
@@ -1190,7 +1186,7 @@ static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
}
@@ -1217,7 +1213,7 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
}
@@ -1379,7 +1375,7 @@ static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
}
@@ -1406,7 +1402,7 @@ static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
if (conn) {
if (conn->state == BT_CONFIG) {
hci_proto_connect_cfm(conn, status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
}
@@ -1600,13 +1596,14 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s status 0x%2.2x", hdev->name, status);
- hci_req_cmd_complete(hdev, HCI_OP_INQUIRY, status);
-
hci_conn_check_pending(hdev);
if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
return;
+ smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */
+ wake_up_bit(&hdev->flags, HCI_INQUIRY);
+
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
return;
@@ -1705,7 +1702,6 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
} else
conn->state = BT_CONNECTED;
- hci_conn_hold_device(conn);
hci_conn_add_sysfs(conn);
if (test_bit(HCI_AUTH, &hdev->flags))
@@ -1752,42 +1748,6 @@ unlock:
hci_conn_check_pending(hdev);
}
-void hci_conn_accept(struct hci_conn *conn, int mask)
-{
- struct hci_dev *hdev = conn->hdev;
-
- BT_DBG("conn %p", conn);
-
- conn->state = BT_CONFIG;
-
- if (!lmp_esco_capable(hdev)) {
- struct hci_cp_accept_conn_req cp;
-
- bacpy(&cp.bdaddr, &conn->dst);
-
- if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
- cp.role = 0x00; /* Become master */
- else
- cp.role = 0x01; /* Remain slave */
-
- hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
- } else /* lmp_esco_capable(hdev)) */ {
- struct hci_cp_accept_sync_conn_req cp;
-
- bacpy(&cp.bdaddr, &conn->dst);
- cp.pkt_type = cpu_to_le16(conn->pkt_type);
-
- cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
- cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
- cp.max_latency = __constant_cpu_to_le16(0xffff);
- cp.content_format = cpu_to_le16(hdev->voice_setting);
- cp.retrans_effort = 0xff;
-
- hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
- sizeof(cp), &cp);
- }
-}
-
static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_conn_request *ev = (void *) skb->data;
@@ -1859,7 +1819,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
} else {
conn->state = BT_CONNECT2;
hci_proto_connect_cfm(conn, 0);
- hci_conn_put(conn);
}
} else {
/* Connection rejected */
@@ -1966,14 +1925,14 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
} else {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
} else {
hci_auth_cfm(conn, ev->status);
hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
@@ -2057,7 +2016,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (ev->status && conn->state == BT_CONNECTED) {
hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
goto unlock;
}
@@ -2066,7 +2025,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
} else
hci_encrypt_cfm(conn, ev->status, ev->encrypt);
}
@@ -2113,7 +2072,7 @@ static void hci_remote_features_evt(struct hci_dev *hdev,
goto unlock;
if (!ev->status)
- memcpy(conn->features, ev->features, 8);
+ memcpy(conn->features[0], ev->features, 8);
if (conn->state != BT_CONFIG)
goto unlock;
@@ -2141,7 +2100,7 @@ static void hci_remote_features_evt(struct hci_dev *hdev,
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
unlock:
@@ -2462,7 +2421,9 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (opcode != HCI_OP_NOP)
del_timer(&hdev->cmd_timer);
- hci_req_cmd_status(hdev, opcode, ev->status);
+ if (ev->status ||
+ (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
+ hci_req_cmd_complete(hdev, opcode, ev->status);
if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
atomic_set(&hdev->cmd_cnt, 1);
@@ -2679,7 +2640,7 @@ static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (conn->state == BT_CONNECTED) {
hci_conn_hold(conn);
conn->disc_timeout = HCI_PAIRING_TIMEOUT;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags))
@@ -2782,7 +2743,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
conn->key_type = ev->key_type;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags))
@@ -2923,6 +2884,9 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
if (!conn)
goto unlock;
+ if (ev->page < HCI_MAX_PAGES)
+ memcpy(conn->features[ev->page], ev->features, 8);
+
if (!ev->status && ev->page == 0x01) {
struct inquiry_entry *ie;
@@ -2930,8 +2894,19 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
if (ie)
ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
- if (ev->features[0] & LMP_HOST_SSP)
+ if (ev->features[0] & LMP_HOST_SSP) {
set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
+ } else {
+ /* It is mandatory by the Bluetooth specification that
+ * Extended Inquiry Results are only used when Secure
+ * Simple Pairing is enabled, but some devices violate
+ * this.
+ *
+ * To make these devices work, the internal SSP
+ * enabled flag needs to be cleared if the remote host
+ * features do not indicate SSP support */
+ clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
+ }
}
if (conn->state != BT_CONFIG)
@@ -2951,7 +2926,7 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
unlock:
@@ -2985,7 +2960,6 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
conn->handle = __le16_to_cpu(ev->handle);
conn->state = BT_CONNECTED;
- hci_conn_hold_device(conn);
hci_conn_add_sysfs(conn);
break;
@@ -3084,7 +3058,7 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
if (ev->status && conn->state == BT_CONNECTED) {
hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
goto unlock;
}
@@ -3093,13 +3067,13 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
} else {
hci_auth_cfm(conn, ev->status);
hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
}
unlock:
@@ -3360,7 +3334,7 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
ev->status);
- hci_conn_put(conn);
+ hci_conn_drop(conn);
unlock:
hci_dev_unlock(hdev);
@@ -3371,11 +3345,16 @@ static void hci_remote_host_features_evt(struct hci_dev *hdev,
{
struct hci_ev_remote_host_features *ev = (void *) skb->data;
struct inquiry_entry *ie;
+ struct hci_conn *conn;
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+ if (conn)
+ memcpy(conn->features[1], ev->features, 8);
+
ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
if (ie)
ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
@@ -3448,9 +3427,8 @@ static void hci_phy_link_complete_evt(struct hci_dev *hdev,
hci_conn_hold(hcon);
hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
- hci_conn_put(hcon);
+ hci_conn_drop(hcon);
- hci_conn_hold_device(hcon);
hci_conn_add_sysfs(hcon);
amp_physical_cfm(bredr_hcon, hcon);
@@ -3584,7 +3562,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn->handle = __le16_to_cpu(ev->handle);
conn->state = BT_CONNECTED;
- hci_conn_hold_device(conn);
hci_conn_add_sysfs(conn);
hci_proto_connect_cfm(conn, ev->status);
@@ -3698,8 +3675,27 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
struct hci_event_hdr *hdr = (void *) skb->data;
__u8 event = hdr->evt;
+ hci_dev_lock(hdev);
+
+ /* Received events are (currently) only needed when a request is
+ * ongoing so avoid unnecessary memory allocation.
+ */
+ if (hdev->req_status == HCI_REQ_PEND) {
+ kfree_skb(hdev->recv_evt);
+ hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
+ }
+
+ hci_dev_unlock(hdev);
+
skb_pull(skb, HCI_EVENT_HDR_SIZE);
+ if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
+ struct hci_command_hdr *hdr = (void *) hdev->sent_cmd->data;
+ u16 opcode = __le16_to_cpu(hdr->opcode);
+
+ hci_req_cmd_complete(hdev, opcode, 0);
+ }
+
switch (event) {
case HCI_EV_INQUIRY_COMPLETE:
hci_inquiry_complete_evt(hdev, skb);
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index ff38561385de..7ad6ecf36f20 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -48,10 +48,10 @@ static ssize_t show_link_features(struct device *dev,
struct hci_conn *conn = to_hci_conn(dev);
return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
- conn->features[0], conn->features[1],
- conn->features[2], conn->features[3],
- conn->features[4], conn->features[5],
- conn->features[6], conn->features[7]);
+ conn->features[0][0], conn->features[0][1],
+ conn->features[0][2], conn->features[0][3],
+ conn->features[0][4], conn->features[0][5],
+ conn->features[0][6], conn->features[0][7]);
}
#define LINK_ATTR(_name, _mode, _show, _store) \
@@ -146,7 +146,6 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
}
device_del(&conn->dev);
- put_device(&conn->dev);
hci_dev_put(hdev);
}
@@ -234,10 +233,10 @@ static ssize_t show_features(struct device *dev,
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
- hdev->features[0], hdev->features[1],
- hdev->features[2], hdev->features[3],
- hdev->features[4], hdev->features[5],
- hdev->features[6], hdev->features[7]);
+ hdev->features[0][0], hdev->features[0][1],
+ hdev->features[0][2], hdev->features[0][3],
+ hdev->features[0][4], hdev->features[0][5],
+ hdev->features[0][6], hdev->features[0][7]);
}
static ssize_t show_manufacturer(struct device *dev,
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 2342327f3335..940f5acb6694 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -1,6 +1,7 @@
/*
HIDP implementation for Linux Bluetooth stack (BlueZ).
Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
+ Copyright (C) 2013 David Herrmann <dh.herrmann@gmail.com>
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
@@ -20,6 +21,7 @@
SOFTWARE IS DISCLAIMED.
*/
+#include <linux/kref.h>
#include <linux/module.h>
#include <linux/file.h>
#include <linux/kthread.h>
@@ -59,39 +61,20 @@ static unsigned char hidp_keycode[256] = {
static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
-static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
-{
- struct hidp_session *session;
-
- BT_DBG("");
+static int hidp_session_probe(struct l2cap_conn *conn,
+ struct l2cap_user *user);
+static void hidp_session_remove(struct l2cap_conn *conn,
+ struct l2cap_user *user);
+static int hidp_session_thread(void *arg);
+static void hidp_session_terminate(struct hidp_session *s);
- list_for_each_entry(session, &hidp_session_list, list) {
- if (!bacmp(bdaddr, &session->bdaddr))
- return session;
- }
-
- return NULL;
-}
-
-static void __hidp_link_session(struct hidp_session *session)
-{
- list_add(&session->list, &hidp_session_list);
-}
-
-static void __hidp_unlink_session(struct hidp_session *session)
-{
- hci_conn_put_device(session->conn);
-
- list_del(&session->list);
-}
-
-static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
+static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
{
memset(ci, 0, sizeof(*ci));
bacpy(&ci->bdaddr, &session->bdaddr);
ci->flags = session->flags;
- ci->state = session->state;
+ ci->state = BT_CONNECTED;
ci->vendor = 0x0000;
ci->product = 0x0000;
@@ -115,58 +98,80 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin
}
}
-static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
- unsigned int type, unsigned int code, int value)
+/* assemble skb, queue message on @transmit and wake up the session thread */
+static int hidp_send_message(struct hidp_session *session, struct socket *sock,
+ struct sk_buff_head *transmit, unsigned char hdr,
+ const unsigned char *data, int size)
{
- unsigned char newleds;
struct sk_buff *skb;
+ struct sock *sk = sock->sk;
- BT_DBG("session %p type %d code %d value %d", session, type, code, value);
-
- if (type != EV_LED)
- return -1;
-
- newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
- (!!test_bit(LED_COMPOSE, dev->led) << 3) |
- (!!test_bit(LED_SCROLLL, dev->led) << 2) |
- (!!test_bit(LED_CAPSL, dev->led) << 1) |
- (!!test_bit(LED_NUML, dev->led));
-
- if (session->leds == newleds)
- return 0;
+ BT_DBG("session %p data %p size %d", session, data, size);
- session->leds = newleds;
+ if (atomic_read(&session->terminate))
+ return -EIO;
- skb = alloc_skb(3, GFP_ATOMIC);
+ skb = alloc_skb(size + 1, GFP_ATOMIC);
if (!skb) {
BT_ERR("Can't allocate memory for new frame");
return -ENOMEM;
}
- *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
- *skb_put(skb, 1) = 0x01;
- *skb_put(skb, 1) = newleds;
-
- skb_queue_tail(&session->intr_transmit, skb);
+ *skb_put(skb, 1) = hdr;
+ if (data && size > 0)
+ memcpy(skb_put(skb, size), data, size);
- hidp_schedule(session);
+ skb_queue_tail(transmit, skb);
+ wake_up_interruptible(sk_sleep(sk));
return 0;
}
-static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static int hidp_send_ctrl_message(struct hidp_session *session,
+ unsigned char hdr, const unsigned char *data,
+ int size)
{
- struct hid_device *hid = input_get_drvdata(dev);
- struct hidp_session *session = hid->driver_data;
+ return hidp_send_message(session, session->ctrl_sock,
+ &session->ctrl_transmit, hdr, data, size);
+}
- return hidp_queue_event(session, dev, type, code, value);
+static int hidp_send_intr_message(struct hidp_session *session,
+ unsigned char hdr, const unsigned char *data,
+ int size)
+{
+ return hidp_send_message(session, session->intr_sock,
+ &session->intr_transmit, hdr, data, size);
}
-static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static int hidp_input_event(struct input_dev *dev, unsigned int type,
+ unsigned int code, int value)
{
struct hidp_session *session = input_get_drvdata(dev);
+ unsigned char newleds;
+ unsigned char hdr, data[2];
+
+ BT_DBG("session %p type %d code %d value %d",
+ session, type, code, value);
+
+ if (type != EV_LED)
+ return -1;
+
+ newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
+ (!!test_bit(LED_COMPOSE, dev->led) << 3) |
+ (!!test_bit(LED_SCROLLL, dev->led) << 2) |
+ (!!test_bit(LED_CAPSL, dev->led) << 1) |
+ (!!test_bit(LED_NUML, dev->led));
- return hidp_queue_event(session, dev, type, code, value);
+ if (session->leds == newleds)
+ return 0;
+
+ session->leds = newleds;
+
+ hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
+ data[0] = 0x01;
+ data[1] = newleds;
+
+ return hidp_send_intr_message(session, hdr, data, 2);
}
static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
@@ -224,71 +229,9 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
input_sync(dev);
}
-static int __hidp_send_ctrl_message(struct hidp_session *session,
- unsigned char hdr, unsigned char *data,
- int size)
-{
- struct sk_buff *skb;
-
- BT_DBG("session %p data %p size %d", session, data, size);
-
- if (atomic_read(&session->terminate))
- return -EIO;
-
- skb = alloc_skb(size + 1, GFP_ATOMIC);
- if (!skb) {
- BT_ERR("Can't allocate memory for new frame");
- return -ENOMEM;
- }
-
- *skb_put(skb, 1) = hdr;
- if (data && size > 0)
- memcpy(skb_put(skb, size), data, size);
-
- skb_queue_tail(&session->ctrl_transmit, skb);
-
- return 0;
-}
-
-static int hidp_send_ctrl_message(struct hidp_session *session,
- unsigned char hdr, unsigned char *data, int size)
-{
- int err;
-
- err = __hidp_send_ctrl_message(session, hdr, data, size);
-
- hidp_schedule(session);
-
- return err;
-}
-
-static int hidp_queue_report(struct hidp_session *session,
- unsigned char *data, int size)
-{
- struct sk_buff *skb;
-
- BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
-
- skb = alloc_skb(size + 1, GFP_ATOMIC);
- if (!skb) {
- BT_ERR("Can't allocate memory for new frame");
- return -ENOMEM;
- }
-
- *skb_put(skb, 1) = 0xa2;
- if (size > 0)
- memcpy(skb_put(skb, size), data, size);
-
- skb_queue_tail(&session->intr_transmit, skb);
-
- hidp_schedule(session);
-
- return 0;
-}
-
static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
{
- unsigned char buf[32];
+ unsigned char buf[32], hdr;
int rsize;
rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
@@ -296,8 +239,9 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
return -EIO;
hid_output_report(report, buf);
+ hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
- return hidp_queue_report(session, buf, rsize);
+ return hidp_send_intr_message(session, hdr, buf, rsize);
}
static int hidp_get_raw_report(struct hid_device *hid,
@@ -336,17 +280,19 @@ static int hidp_get_raw_report(struct hid_device *hid,
session->waiting_report_number = numbered_reports ? report_number : -1;
set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
data[0] = report_number;
- ret = hidp_send_ctrl_message(hid->driver_data, report_type, data, 1);
+ ret = hidp_send_ctrl_message(session, report_type, data, 1);
if (ret)
goto err;
/* Wait for the return of the report. The returned report
gets put in session->report_return. */
- while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
+ while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
+ !atomic_read(&session->terminate)) {
int res;
res = wait_event_interruptible_timeout(session->report_queue,
- !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
+ !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)
+ || atomic_read(&session->terminate),
5*HZ);
if (res == 0) {
/* timeout */
@@ -389,14 +335,11 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s
struct hidp_session *session = hid->driver_data;
int ret;
- switch (report_type) {
- case HID_FEATURE_REPORT:
- report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
- break;
- case HID_OUTPUT_REPORT:
- report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
- break;
- default:
+ if (report_type == HID_OUTPUT_REPORT) {
+ report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
+ return hidp_send_intr_message(session, report_type,
+ data, count);
+ } else if (report_type != HID_FEATURE_REPORT) {
return -EINVAL;
}
@@ -405,17 +348,19 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s
/* Set up our wait, and send the report request to the device. */
set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
- ret = hidp_send_ctrl_message(hid->driver_data, report_type, data,
- count);
+ report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
+ ret = hidp_send_ctrl_message(session, report_type, data, count);
if (ret)
goto err;
/* Wait for the ACK from the device. */
- while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
+ while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags) &&
+ !atomic_read(&session->terminate)) {
int res;
res = wait_event_interruptible_timeout(session->report_queue,
- !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
+ !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)
+ || atomic_read(&session->terminate),
10*HZ);
if (res == 0) {
/* timeout */
@@ -446,8 +391,7 @@ static void hidp_idle_timeout(unsigned long arg)
{
struct hidp_session *session = (struct hidp_session *) arg;
- atomic_inc(&session->terminate);
- wake_up_process(session->task);
+ hidp_session_terminate(session);
}
static void hidp_set_timer(struct hidp_session *session)
@@ -490,12 +434,12 @@ static void hidp_process_handshake(struct hidp_session *session,
case HIDP_HSHK_ERR_FATAL:
/* Device requests a reboot, as this is the only way this error
* can be recovered. */
- __hidp_send_ctrl_message(session,
+ hidp_send_ctrl_message(session,
HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
break;
default:
- __hidp_send_ctrl_message(session,
+ hidp_send_ctrl_message(session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
break;
}
@@ -515,8 +459,7 @@ static void hidp_process_hid_control(struct hidp_session *session,
skb_queue_purge(&session->ctrl_transmit);
skb_queue_purge(&session->intr_transmit);
- atomic_inc(&session->terminate);
- wake_up_process(current);
+ hidp_session_terminate(session);
}
}
@@ -544,7 +487,7 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
break;
default:
- __hidp_send_ctrl_message(session,
+ hidp_send_ctrl_message(session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
}
@@ -591,7 +534,7 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
break;
default:
- __hidp_send_ctrl_message(session,
+ hidp_send_ctrl_message(session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
break;
}
@@ -642,32 +585,24 @@ static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
return kernel_sendmsg(sock, &msg, &iv, 1, len);
}
-static void hidp_process_intr_transmit(struct hidp_session *session)
+/* dequeue message from @transmit and send via @sock */
+static void hidp_process_transmit(struct hidp_session *session,
+ struct sk_buff_head *transmit,
+ struct socket *sock)
{
struct sk_buff *skb;
+ int ret;
BT_DBG("session %p", session);
- while ((skb = skb_dequeue(&session->intr_transmit))) {
- if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
- skb_queue_head(&session->intr_transmit, skb);
+ while ((skb = skb_dequeue(transmit))) {
+ ret = hidp_send_frame(sock, skb->data, skb->len);
+ if (ret == -EAGAIN) {
+ skb_queue_head(transmit, skb);
break;
- }
-
- hidp_set_timer(session);
- kfree_skb(skb);
- }
-}
-
-static void hidp_process_ctrl_transmit(struct hidp_session *session)
-{
- struct sk_buff *skb;
-
- BT_DBG("session %p", session);
-
- while ((skb = skb_dequeue(&session->ctrl_transmit))) {
- if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
- skb_queue_head(&session->ctrl_transmit, skb);
+ } else if (ret < 0) {
+ hidp_session_terminate(session);
+ kfree_skb(skb);
break;
}
@@ -676,122 +611,6 @@ static void hidp_process_ctrl_transmit(struct hidp_session *session)
}
}
-static int hidp_session(void *arg)
-{
- struct hidp_session *session = arg;
- struct sock *ctrl_sk = session->ctrl_sock->sk;
- struct sock *intr_sk = session->intr_sock->sk;
- struct sk_buff *skb;
- wait_queue_t ctrl_wait, intr_wait;
-
- BT_DBG("session %p", session);
-
- __module_get(THIS_MODULE);
- set_user_nice(current, -15);
-
- init_waitqueue_entry(&ctrl_wait, current);
- init_waitqueue_entry(&intr_wait, current);
- add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
- add_wait_queue(sk_sleep(intr_sk), &intr_wait);
- session->waiting_for_startup = 0;
- wake_up_interruptible(&session->startup_queue);
- set_current_state(TASK_INTERRUPTIBLE);
- while (!atomic_read(&session->terminate)) {
- if (ctrl_sk->sk_state != BT_CONNECTED ||
- intr_sk->sk_state != BT_CONNECTED)
- break;
-
- while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
- skb_orphan(skb);
- if (!skb_linearize(skb))
- hidp_recv_intr_frame(session, skb);
- else
- kfree_skb(skb);
- }
-
- hidp_process_intr_transmit(session);
-
- while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
- skb_orphan(skb);
- if (!skb_linearize(skb))
- hidp_recv_ctrl_frame(session, skb);
- else
- kfree_skb(skb);
- }
-
- hidp_process_ctrl_transmit(session);
-
- schedule();
- set_current_state(TASK_INTERRUPTIBLE);
- }
- set_current_state(TASK_RUNNING);
- atomic_inc(&session->terminate);
- remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
- remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
-
- clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
- clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
- wake_up_interruptible(&session->report_queue);
-
- down_write(&hidp_session_sem);
-
- hidp_del_timer(session);
-
- if (session->input) {
- input_unregister_device(session->input);
- session->input = NULL;
- }
-
- if (session->hid) {
- hid_destroy_device(session->hid);
- session->hid = NULL;
- }
-
- /* Wakeup user-space polling for socket errors */
- session->intr_sock->sk->sk_err = EUNATCH;
- session->ctrl_sock->sk->sk_err = EUNATCH;
-
- hidp_schedule(session);
-
- fput(session->intr_sock->file);
-
- wait_event_timeout(*(sk_sleep(ctrl_sk)),
- (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
-
- fput(session->ctrl_sock->file);
-
- __hidp_unlink_session(session);
-
- up_write(&hidp_session_sem);
-
- kfree(session->rd_data);
- kfree(session);
- module_put_and_exit(0);
- return 0;
-}
-
-static struct hci_conn *hidp_get_connection(struct hidp_session *session)
-{
- bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
- bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
- struct hci_conn *conn;
- struct hci_dev *hdev;
-
- hdev = hci_get_route(dst, src);
- if (!hdev)
- return NULL;
-
- hci_dev_lock(hdev);
- conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
- if (conn)
- hci_conn_hold_device(conn);
- hci_dev_unlock(hdev);
-
- hci_dev_put(hdev);
-
- return conn;
-}
-
static int hidp_setup_input(struct hidp_session *session,
struct hidp_connadd_req *req)
{
@@ -839,7 +658,7 @@ static int hidp_setup_input(struct hidp_session *session,
input->relbit[0] |= BIT_MASK(REL_WHEEL);
}
- input->dev.parent = &session->conn->dev;
+ input->dev.parent = &session->conn->hcon->dev;
input->event = hidp_input_event;
@@ -898,7 +717,6 @@ static struct hid_ll_driver hidp_hid_driver = {
.stop = hidp_stop,
.open = hidp_open,
.close = hidp_close,
- .hidinput_input_event = hidp_hidinput_event,
};
/* This function sets up the hid device. It does not add it
@@ -943,7 +761,7 @@ static int hidp_setup_hid(struct hidp_session *session,
snprintf(hid->uniq, sizeof(hid->uniq), "%pMR",
&bt_sk(session->ctrl_sock->sk)->dst);
- hid->dev.parent = &session->conn->dev;
+ hid->dev.parent = &session->conn->hcon->dev;
hid->ll_driver = &hidp_hid_driver;
hid->hid_get_raw_report = hidp_get_raw_report;
@@ -965,80 +783,217 @@ fault:
return err;
}
-int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
+/* initialize session devices */
+static int hidp_session_dev_init(struct hidp_session *session,
+ struct hidp_connadd_req *req)
{
- struct hidp_session *session, *s;
- int vendor, product;
- int err;
+ int ret;
- BT_DBG("");
+ if (req->rd_size > 0) {
+ ret = hidp_setup_hid(session, req);
+ if (ret && ret != -ENODEV)
+ return ret;
+ }
- if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
- bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
- return -ENOTUNIQ;
+ if (!session->hid) {
+ ret = hidp_setup_input(session, req);
+ if (ret < 0)
+ return ret;
+ }
- BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
+ return 0;
+}
- down_write(&hidp_session_sem);
+/* destroy session devices */
+static void hidp_session_dev_destroy(struct hidp_session *session)
+{
+ if (session->hid)
+ put_device(&session->hid->dev);
+ else if (session->input)
+ input_put_device(session->input);
- s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
- if (s && s->state == BT_CONNECTED) {
- up_write(&hidp_session_sem);
- return -EEXIST;
- }
+ kfree(session->rd_data);
+ session->rd_data = NULL;
+}
- session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
- if (!session) {
- up_write(&hidp_session_sem);
- return -ENOMEM;
- }
+/* add HID/input devices to their underlying bus systems */
+static int hidp_session_dev_add(struct hidp_session *session)
+{
+ int ret;
- bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
+ /* Both HID and input systems drop a ref-count when unregistering the
+ * device but they don't take a ref-count when registering them. Work
+ * around this by explicitly taking a refcount during registration
+ * which is dropped automatically by unregistering the devices. */
- session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu,
- l2cap_pi(ctrl_sock->sk)->chan->imtu);
- session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu,
- l2cap_pi(intr_sock->sk)->chan->imtu);
+ if (session->hid) {
+ ret = hid_add_device(session->hid);
+ if (ret)
+ return ret;
+ get_device(&session->hid->dev);
+ } else if (session->input) {
+ ret = input_register_device(session->input);
+ if (ret)
+ return ret;
+ input_get_device(session->input);
+ }
- BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
+ return 0;
+}
- session->ctrl_sock = ctrl_sock;
- session->intr_sock = intr_sock;
- session->state = BT_CONNECTED;
+/* remove HID/input devices from their bus systems */
+static void hidp_session_dev_del(struct hidp_session *session)
+{
+ if (session->hid)
+ hid_destroy_device(session->hid);
+ else if (session->input)
+ input_unregister_device(session->input);
+}
- session->conn = hidp_get_connection(session);
- if (!session->conn) {
- err = -ENOTCONN;
- goto failed;
- }
+/*
+ * Create new session object
+ * Allocate session object, initialize static fields, copy input data into the
+ * object and take a reference to all sub-objects.
+ * This returns 0 on success and puts a pointer to the new session object in
+ * \out. Otherwise, an error code is returned.
+ * The new session object has an initial ref-count of 1.
+ */
+static int hidp_session_new(struct hidp_session **out, const bdaddr_t *bdaddr,
+ struct socket *ctrl_sock,
+ struct socket *intr_sock,
+ struct hidp_connadd_req *req,
+ struct l2cap_conn *conn)
+{
+ struct hidp_session *session;
+ int ret;
+ struct bt_sock *ctrl, *intr;
+
+ ctrl = bt_sk(ctrl_sock->sk);
+ intr = bt_sk(intr_sock->sk);
- setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
+ session = kzalloc(sizeof(*session), GFP_KERNEL);
+ if (!session)
+ return -ENOMEM;
+ /* object and runtime management */
+ kref_init(&session->ref);
+ atomic_set(&session->state, HIDP_SESSION_IDLING);
+ init_waitqueue_head(&session->state_queue);
+ session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
+
+ /* connection management */
+ bacpy(&session->bdaddr, bdaddr);
+ session->conn = conn;
+ session->user.probe = hidp_session_probe;
+ session->user.remove = hidp_session_remove;
+ session->ctrl_sock = ctrl_sock;
+ session->intr_sock = intr_sock;
skb_queue_head_init(&session->ctrl_transmit);
skb_queue_head_init(&session->intr_transmit);
+ session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl)->chan->omtu,
+ l2cap_pi(ctrl)->chan->imtu);
+ session->intr_mtu = min_t(uint, l2cap_pi(intr)->chan->omtu,
+ l2cap_pi(intr)->chan->imtu);
+ session->idle_to = req->idle_to;
+
+ /* device management */
+ setup_timer(&session->timer, hidp_idle_timeout,
+ (unsigned long)session);
+ /* session data */
mutex_init(&session->report_mutex);
init_waitqueue_head(&session->report_queue);
- init_waitqueue_head(&session->startup_queue);
- session->waiting_for_startup = 1;
- session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
- session->idle_to = req->idle_to;
- __hidp_link_session(session);
+ ret = hidp_session_dev_init(session, req);
+ if (ret)
+ goto err_free;
- if (req->rd_size > 0) {
- err = hidp_setup_hid(session, req);
- if (err && err != -ENODEV)
- goto purge;
- }
+ l2cap_conn_get(session->conn);
+ get_file(session->intr_sock->file);
+ get_file(session->ctrl_sock->file);
+ *out = session;
+ return 0;
- if (!session->hid) {
- err = hidp_setup_input(session, req);
- if (err < 0)
- goto purge;
+err_free:
+ kfree(session);
+ return ret;
+}
+
+/* increase ref-count of the given session by one */
+static void hidp_session_get(struct hidp_session *session)
+{
+ kref_get(&session->ref);
+}
+
+/* release callback */
+static void session_free(struct kref *ref)
+{
+ struct hidp_session *session = container_of(ref, struct hidp_session,
+ ref);
+
+ hidp_session_dev_destroy(session);
+ skb_queue_purge(&session->ctrl_transmit);
+ skb_queue_purge(&session->intr_transmit);
+ fput(session->intr_sock->file);
+ fput(session->ctrl_sock->file);
+ l2cap_conn_put(session->conn);
+ kfree(session);
+}
+
+/* decrease ref-count of the given session by one */
+static void hidp_session_put(struct hidp_session *session)
+{
+ kref_put(&session->ref, session_free);
+}
+
+/*
+ * Search the list of active sessions for a session with target address
+ * \bdaddr. You must hold at least a read-lock on \hidp_session_sem. As long as
+ * you do not release this lock, the session objects cannot vanish and you can
+ * safely take a reference to the session yourself.
+ */
+static struct hidp_session *__hidp_session_find(const bdaddr_t *bdaddr)
+{
+ struct hidp_session *session;
+
+ list_for_each_entry(session, &hidp_session_list, list) {
+ if (!bacmp(bdaddr, &session->bdaddr))
+ return session;
}
- hidp_set_timer(session);
+ return NULL;
+}
+
+/*
+ * Same as __hidp_session_find() but no locks must be held. This also takes a
+ * reference of the returned session (if non-NULL) so you must drop this
+ * reference if you no longer use the object.
+ */
+static struct hidp_session *hidp_session_find(const bdaddr_t *bdaddr)
+{
+ struct hidp_session *session;
+
+ down_read(&hidp_session_sem);
+
+ session = __hidp_session_find(bdaddr);
+ if (session)
+ hidp_session_get(session);
+
+ up_read(&hidp_session_sem);
+
+ return session;
+}
+
+/*
+ * Start session synchronously
+ * This starts a session thread and waits until initialization
+ * is done or returns an error if it couldn't be started.
+ * If this returns 0 the session thread is up and running. You must call
+ * hipd_session_stop_sync() before deleting any runtime resources.
+ */
+static int hidp_session_start_sync(struct hidp_session *session)
+{
+ unsigned int vendor, product;
if (session->hid) {
vendor = session->hid->vendor;
@@ -1051,98 +1006,320 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
product = 0x0000;
}
- session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x",
- vendor, product);
- if (IS_ERR(session->task)) {
- err = PTR_ERR(session->task);
- goto unlink;
- }
+ session->task = kthread_run(hidp_session_thread, session,
+ "khidpd_%04x%04x", vendor, product);
+ if (IS_ERR(session->task))
+ return PTR_ERR(session->task);
- while (session->waiting_for_startup) {
- wait_event_interruptible(session->startup_queue,
- !session->waiting_for_startup);
- }
+ while (atomic_read(&session->state) <= HIDP_SESSION_IDLING)
+ wait_event(session->state_queue,
+ atomic_read(&session->state) > HIDP_SESSION_IDLING);
- if (session->hid)
- err = hid_add_device(session->hid);
- else
- err = input_register_device(session->input);
+ return 0;
+}
- if (err < 0) {
- atomic_inc(&session->terminate);
- wake_up_process(session->task);
- up_write(&hidp_session_sem);
- return err;
- }
+/*
+ * Terminate session thread
+ * Wake up session thread and notify it to stop. This is asynchronous and
+ * returns immediately. Call this whenever a runtime error occurs and you want
+ * the session to stop.
+ * Note: wake_up_process() performs any necessary memory-barriers for us.
+ */
+static void hidp_session_terminate(struct hidp_session *session)
+{
+ atomic_inc(&session->terminate);
+ wake_up_process(session->task);
+}
- if (session->input) {
- hidp_send_ctrl_message(session,
- HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
- session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
+/*
+ * Probe HIDP session
+ * This is called from the l2cap_conn core when our l2cap_user object is bound
+ * to the hci-connection. We get the session via the \user object and can now
+ * start the session thread, register the HID/input devices and link it into
+ * the global session list.
+ * The global session-list owns its own reference to the session object so you
+ * can drop your own reference after registering the l2cap_user object.
+ */
+static int hidp_session_probe(struct l2cap_conn *conn,
+ struct l2cap_user *user)
+{
+ struct hidp_session *session = container_of(user,
+ struct hidp_session,
+ user);
+ struct hidp_session *s;
+ int ret;
+
+ down_write(&hidp_session_sem);
- session->leds = 0xff;
- hidp_input_event(session->input, EV_LED, 0, 0);
+ /* check that no other session for this device exists */
+ s = __hidp_session_find(&session->bdaddr);
+ if (s) {
+ ret = -EEXIST;
+ goto out_unlock;
}
+ ret = hidp_session_start_sync(session);
+ if (ret)
+ goto out_unlock;
+
+ ret = hidp_session_dev_add(session);
+ if (ret)
+ goto out_stop;
+
+ hidp_session_get(session);
+ list_add(&session->list, &hidp_session_list);
+ ret = 0;
+ goto out_unlock;
+
+out_stop:
+ hidp_session_terminate(session);
+out_unlock:
up_write(&hidp_session_sem);
- return 0;
+ return ret;
+}
+
+/*
+ * Remove HIDP session
+ * Called from the l2cap_conn core when either we explicitly unregistered
+ * the l2cap_user object or if the underlying connection is shut down.
+ * We signal the hidp-session thread to shut down, unregister the HID/input
+ * devices and unlink the session from the global list.
+ * This drops the reference to the session that is owned by the global
+ * session-list.
+ * Note: We _must_ not synchronosly wait for the session-thread to shut down.
+ * This is, because the session-thread might be waiting for an HCI lock that is
+ * held while we are called. Therefore, we only unregister the devices and
+ * notify the session-thread to terminate. The thread itself owns a reference
+ * to the session object so it can safely shut down.
+ */
+static void hidp_session_remove(struct l2cap_conn *conn,
+ struct l2cap_user *user)
+{
+ struct hidp_session *session = container_of(user,
+ struct hidp_session,
+ user);
+
+ down_write(&hidp_session_sem);
+
+ hidp_session_terminate(session);
+ hidp_session_dev_del(session);
+ list_del(&session->list);
+
+ up_write(&hidp_session_sem);
+
+ hidp_session_put(session);
+}
+
+/*
+ * Session Worker
+ * This performs the actual main-loop of the HIDP worker. We first check
+ * whether the underlying connection is still alive, then parse all pending
+ * messages and finally send all outstanding messages.
+ */
+static void hidp_session_run(struct hidp_session *session)
+{
+ struct sock *ctrl_sk = session->ctrl_sock->sk;
+ struct sock *intr_sk = session->intr_sock->sk;
+ struct sk_buff *skb;
+
+ for (;;) {
+ /*
+ * This thread can be woken up two ways:
+ * - You call hidp_session_terminate() which sets the
+ * session->terminate flag and wakes this thread up.
+ * - Via modifying the socket state of ctrl/intr_sock. This
+ * thread is woken up by ->sk_state_changed().
+ *
+ * Note: set_current_state() performs any necessary
+ * memory-barriers for us.
+ */
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (atomic_read(&session->terminate))
+ break;
+
+ if (ctrl_sk->sk_state != BT_CONNECTED ||
+ intr_sk->sk_state != BT_CONNECTED)
+ break;
+
+ /* parse incoming intr-skbs */
+ while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
+ skb_orphan(skb);
+ if (!skb_linearize(skb))
+ hidp_recv_intr_frame(session, skb);
+ else
+ kfree_skb(skb);
+ }
+
+ /* send pending intr-skbs */
+ hidp_process_transmit(session, &session->intr_transmit,
+ session->intr_sock);
-unlink:
+ /* parse incoming ctrl-skbs */
+ while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
+ skb_orphan(skb);
+ if (!skb_linearize(skb))
+ hidp_recv_ctrl_frame(session, skb);
+ else
+ kfree_skb(skb);
+ }
+
+ /* send pending ctrl-skbs */
+ hidp_process_transmit(session, &session->ctrl_transmit,
+ session->ctrl_sock);
+
+ schedule();
+ }
+
+ atomic_inc(&session->terminate);
+ set_current_state(TASK_RUNNING);
+}
+
+/*
+ * HIDP session thread
+ * This thread runs the I/O for a single HIDP session. Startup is synchronous
+ * which allows us to take references to ourself here instead of doing that in
+ * the caller.
+ * When we are ready to run we notify the caller and call hidp_session_run().
+ */
+static int hidp_session_thread(void *arg)
+{
+ struct hidp_session *session = arg;
+ wait_queue_t ctrl_wait, intr_wait;
+
+ BT_DBG("session %p", session);
+
+ /* initialize runtime environment */
+ hidp_session_get(session);
+ __module_get(THIS_MODULE);
+ set_user_nice(current, -15);
+ hidp_set_timer(session);
+
+ init_waitqueue_entry(&ctrl_wait, current);
+ init_waitqueue_entry(&intr_wait, current);
+ add_wait_queue(sk_sleep(session->ctrl_sock->sk), &ctrl_wait);
+ add_wait_queue(sk_sleep(session->intr_sock->sk), &intr_wait);
+ /* This memory barrier is paired with wq_has_sleeper(). See
+ * sock_poll_wait() for more information why this is needed. */
+ smp_mb();
+
+ /* notify synchronous startup that we're ready */
+ atomic_inc(&session->state);
+ wake_up(&session->state_queue);
+
+ /* run session */
+ hidp_session_run(session);
+
+ /* cleanup runtime environment */
+ remove_wait_queue(sk_sleep(session->intr_sock->sk), &intr_wait);
+ remove_wait_queue(sk_sleep(session->intr_sock->sk), &ctrl_wait);
+ wake_up_interruptible(&session->report_queue);
hidp_del_timer(session);
- if (session->input) {
- input_unregister_device(session->input);
- session->input = NULL;
+ /*
+ * If we stopped ourself due to any internal signal, we should try to
+ * unregister our own session here to avoid having it linger until the
+ * parent l2cap_conn dies or user-space cleans it up.
+ * This does not deadlock as we don't do any synchronous shutdown.
+ * Instead, this call has the same semantics as if user-space tried to
+ * delete the session.
+ */
+ l2cap_unregister_user(session->conn, &session->user);
+ hidp_session_put(session);
+
+ module_put_and_exit(0);
+ return 0;
+}
+
+static int hidp_verify_sockets(struct socket *ctrl_sock,
+ struct socket *intr_sock)
+{
+ struct bt_sock *ctrl, *intr;
+ struct hidp_session *session;
+
+ if (!l2cap_is_socket(ctrl_sock) || !l2cap_is_socket(intr_sock))
+ return -EINVAL;
+
+ ctrl = bt_sk(ctrl_sock->sk);
+ intr = bt_sk(intr_sock->sk);
+
+ if (bacmp(&ctrl->src, &intr->src) || bacmp(&ctrl->dst, &intr->dst))
+ return -ENOTUNIQ;
+ if (ctrl->sk.sk_state != BT_CONNECTED ||
+ intr->sk.sk_state != BT_CONNECTED)
+ return -EBADFD;
+
+ /* early session check, we check again during session registration */
+ session = hidp_session_find(&ctrl->dst);
+ if (session) {
+ hidp_session_put(session);
+ return -EEXIST;
}
- if (session->hid) {
- hid_destroy_device(session->hid);
- session->hid = NULL;
+ return 0;
+}
+
+int hidp_connection_add(struct hidp_connadd_req *req,
+ struct socket *ctrl_sock,
+ struct socket *intr_sock)
+{
+ struct hidp_session *session;
+ struct l2cap_conn *conn;
+ struct l2cap_chan *chan = l2cap_pi(ctrl_sock->sk)->chan;
+ int ret;
+
+ ret = hidp_verify_sockets(ctrl_sock, intr_sock);
+ if (ret)
+ return ret;
+
+ conn = NULL;
+ l2cap_chan_lock(chan);
+ if (chan->conn) {
+ l2cap_conn_get(chan->conn);
+ conn = chan->conn;
}
+ l2cap_chan_unlock(chan);
- kfree(session->rd_data);
- session->rd_data = NULL;
+ if (!conn)
+ return -EBADFD;
-purge:
- __hidp_unlink_session(session);
+ ret = hidp_session_new(&session, &bt_sk(ctrl_sock->sk)->dst, ctrl_sock,
+ intr_sock, req, conn);
+ if (ret)
+ goto out_conn;
- skb_queue_purge(&session->ctrl_transmit);
- skb_queue_purge(&session->intr_transmit);
+ ret = l2cap_register_user(conn, &session->user);
+ if (ret)
+ goto out_session;
-failed:
- up_write(&hidp_session_sem);
+ ret = 0;
- kfree(session);
- return err;
+out_session:
+ hidp_session_put(session);
+out_conn:
+ l2cap_conn_put(conn);
+ return ret;
}
-int hidp_del_connection(struct hidp_conndel_req *req)
+int hidp_connection_del(struct hidp_conndel_req *req)
{
struct hidp_session *session;
- int err = 0;
- BT_DBG("");
+ session = hidp_session_find(&req->bdaddr);
+ if (!session)
+ return -ENOENT;
- down_read(&hidp_session_sem);
+ if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG))
+ hidp_send_ctrl_message(session,
+ HIDP_TRANS_HID_CONTROL |
+ HIDP_CTRL_VIRTUAL_CABLE_UNPLUG,
+ NULL, 0);
+ else
+ l2cap_unregister_user(session->conn, &session->user);
- session = __hidp_get_session(&req->bdaddr);
- if (session) {
- if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
- hidp_send_ctrl_message(session,
- HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
- } else {
- /* Flush the transmit queues */
- skb_queue_purge(&session->ctrl_transmit);
- skb_queue_purge(&session->intr_transmit);
-
- atomic_inc(&session->terminate);
- wake_up_process(session->task);
- }
- } else
- err = -ENOENT;
+ hidp_session_put(session);
- up_read(&hidp_session_sem);
- return err;
+ return 0;
}
int hidp_get_connlist(struct hidp_connlist_req *req)
@@ -1157,7 +1334,7 @@ int hidp_get_connlist(struct hidp_connlist_req *req)
list_for_each_entry(session, &hidp_session_list, list) {
struct hidp_conninfo ci;
- __hidp_copy_session(session, &ci);
+ hidp_copy_session(session, &ci);
if (copy_to_user(req->ci, &ci, sizeof(ci))) {
err = -EFAULT;
@@ -1178,18 +1355,14 @@ int hidp_get_connlist(struct hidp_connlist_req *req)
int hidp_get_conninfo(struct hidp_conninfo *ci)
{
struct hidp_session *session;
- int err = 0;
-
- down_read(&hidp_session_sem);
- session = __hidp_get_session(&ci->bdaddr);
- if (session)
- __hidp_copy_session(session, ci);
- else
- err = -ENOENT;
+ session = hidp_session_find(&ci->bdaddr);
+ if (session) {
+ hidp_copy_session(session, ci);
+ hidp_session_put(session);
+ }
- up_read(&hidp_session_sem);
- return err;
+ return session ? 0 : -ENOENT;
}
static int __init hidp_init(void)
@@ -1208,6 +1381,7 @@ module_init(hidp_init);
module_exit(hidp_exit);
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
+MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index af1bcc823f26..6162ce8606ac 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -24,7 +24,9 @@
#define __HIDP_H
#include <linux/types.h>
+#include <linux/kref.h>
#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/l2cap.h>
/* HIDP header masks */
#define HIDP_HEADER_TRANS_MASK 0xf0
@@ -119,43 +121,52 @@ struct hidp_connlist_req {
struct hidp_conninfo __user *ci;
};
-int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
-int hidp_del_connection(struct hidp_conndel_req *req);
+int hidp_connection_add(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
+int hidp_connection_del(struct hidp_conndel_req *req);
int hidp_get_connlist(struct hidp_connlist_req *req);
int hidp_get_conninfo(struct hidp_conninfo *ci);
+enum hidp_session_state {
+ HIDP_SESSION_IDLING,
+ HIDP_SESSION_RUNNING,
+};
+
/* HIDP session defines */
struct hidp_session {
struct list_head list;
+ struct kref ref;
- struct hci_conn *conn;
+ /* runtime management */
+ atomic_t state;
+ wait_queue_head_t state_queue;
+ atomic_t terminate;
+ struct task_struct *task;
+ unsigned long flags;
+ /* connection management */
+ bdaddr_t bdaddr;
+ struct l2cap_conn *conn;
+ struct l2cap_user user;
struct socket *ctrl_sock;
struct socket *intr_sock;
-
- bdaddr_t bdaddr;
-
- unsigned long state;
- unsigned long flags;
- unsigned long idle_to;
-
+ struct sk_buff_head ctrl_transmit;
+ struct sk_buff_head intr_transmit;
uint ctrl_mtu;
uint intr_mtu;
+ unsigned long idle_to;
- atomic_t terminate;
- struct task_struct *task;
-
- unsigned char keys[8];
- unsigned char leds;
-
+ /* device management */
struct input_dev *input;
-
struct hid_device *hid;
-
struct timer_list timer;
- struct sk_buff_head ctrl_transmit;
- struct sk_buff_head intr_transmit;
+ /* Report descriptor */
+ __u8 *rd_data;
+ uint rd_size;
+
+ /* session data */
+ unsigned char keys[8];
+ unsigned char leds;
/* Used in hidp_get_raw_report() */
int waiting_report_type; /* HIDP_DATA_RTYPE_* */
@@ -166,24 +177,8 @@ struct hidp_session {
/* Used in hidp_output_raw_report() */
int output_report_success; /* boolean */
-
- /* Report descriptor */
- __u8 *rd_data;
- uint rd_size;
-
- wait_queue_head_t startup_queue;
- int waiting_for_startup;
};
-static inline void hidp_schedule(struct hidp_session *session)
-{
- struct sock *ctrl_sk = session->ctrl_sock->sk;
- struct sock *intr_sk = session->intr_sock->sk;
-
- wake_up_interruptible(sk_sleep(ctrl_sk));
- wake_up_interruptible(sk_sleep(intr_sk));
-}
-
/* HIDP init defines */
extern int __init hidp_init_sockets(void);
extern void __exit hidp_cleanup_sockets(void);
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 5d0f1ca0a314..2f4cbb0865ca 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -77,21 +77,12 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return err;
}
- if (csock->sk->sk_state != BT_CONNECTED ||
- isock->sk->sk_state != BT_CONNECTED) {
- sockfd_put(csock);
- sockfd_put(isock);
- return -EBADFD;
- }
+ err = hidp_connection_add(&ca, csock, isock);
+ if (!err && copy_to_user(argp, &ca, sizeof(ca)))
+ err = -EFAULT;
- err = hidp_add_connection(&ca, csock, isock);
- if (!err) {
- if (copy_to_user(argp, &ca, sizeof(ca)))
- err = -EFAULT;
- } else {
- sockfd_put(csock);
- sockfd_put(isock);
- }
+ sockfd_put(csock);
+ sockfd_put(isock);
return err;
@@ -102,7 +93,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
if (copy_from_user(&cd, argp, sizeof(cd)))
return -EFAULT;
- return hidp_del_connection(&cd);
+ return hidp_connection_del(&cd);
case HIDPGETCONNLIST:
if (copy_from_user(&cl, argp, sizeof(cl)))
@@ -296,7 +287,6 @@ int __init hidp_init_sockets(void)
return 0;
error:
- BT_ERR("Can't register HIDP socket");
proto_unregister(&hidp_proto);
return err;
}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7c7e9321f1ea..eae1d9f90b68 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -571,7 +571,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
chan->conn = NULL;
if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP)
- hci_conn_put(conn->hcon);
+ hci_conn_drop(conn->hcon);
if (mgr && mgr->bredr_chan == chan)
mgr->bredr_chan = NULL;
@@ -1446,6 +1446,89 @@ static void l2cap_info_timeout(struct work_struct *work)
l2cap_conn_start(conn);
}
+/*
+ * l2cap_user
+ * External modules can register l2cap_user objects on l2cap_conn. The ->probe
+ * callback is called during registration. The ->remove callback is called
+ * during unregistration.
+ * An l2cap_user object can either be explicitly unregistered or when the
+ * underlying l2cap_conn object is deleted. This guarantees that l2cap->hcon,
+ * l2cap->hchan, .. are valid as long as the remove callback hasn't been called.
+ * External modules must own a reference to the l2cap_conn object if they intend
+ * to call l2cap_unregister_user(). The l2cap_conn object might get destroyed at
+ * any time if they don't.
+ */
+
+int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
+{
+ struct hci_dev *hdev = conn->hcon->hdev;
+ int ret;
+
+ /* We need to check whether l2cap_conn is registered. If it is not, we
+ * must not register the l2cap_user. l2cap_conn_del() is unregisters
+ * l2cap_conn objects, but doesn't provide its own locking. Instead, it
+ * relies on the parent hci_conn object to be locked. This itself relies
+ * on the hci_dev object to be locked. So we must lock the hci device
+ * here, too. */
+
+ hci_dev_lock(hdev);
+
+ if (user->list.next || user->list.prev) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ /* conn->hchan is NULL after l2cap_conn_del() was called */
+ if (!conn->hchan) {
+ ret = -ENODEV;
+ goto out_unlock;
+ }
+
+ ret = user->probe(conn, user);
+ if (ret)
+ goto out_unlock;
+
+ list_add(&user->list, &conn->users);
+ ret = 0;
+
+out_unlock:
+ hci_dev_unlock(hdev);
+ return ret;
+}
+EXPORT_SYMBOL(l2cap_register_user);
+
+void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
+{
+ struct hci_dev *hdev = conn->hcon->hdev;
+
+ hci_dev_lock(hdev);
+
+ if (!user->list.next || !user->list.prev)
+ goto out_unlock;
+
+ list_del(&user->list);
+ user->list.next = NULL;
+ user->list.prev = NULL;
+ user->remove(conn, user);
+
+out_unlock:
+ hci_dev_unlock(hdev);
+}
+EXPORT_SYMBOL(l2cap_unregister_user);
+
+static void l2cap_unregister_all_users(struct l2cap_conn *conn)
+{
+ struct l2cap_user *user;
+
+ while (!list_empty(&conn->users)) {
+ user = list_first_entry(&conn->users, struct l2cap_user, list);
+ list_del(&user->list);
+ user->list.next = NULL;
+ user->list.prev = NULL;
+ user->remove(conn, user);
+ }
+}
+
static void l2cap_conn_del(struct hci_conn *hcon, int err)
{
struct l2cap_conn *conn = hcon->l2cap_data;
@@ -1458,6 +1541,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
kfree_skb(conn->rx_skb);
+ l2cap_unregister_all_users(conn);
+
mutex_lock(&conn->chan_lock);
/* Kill channels */
@@ -1486,7 +1571,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
}
hcon->l2cap_data = NULL;
- kfree(conn);
+ conn->hchan = NULL;
+ l2cap_conn_put(conn);
}
static void security_timeout(struct work_struct *work)
@@ -1502,12 +1588,12 @@ static void security_timeout(struct work_struct *work)
}
}
-static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
+static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
{
struct l2cap_conn *conn = hcon->l2cap_data;
struct hci_chan *hchan;
- if (conn || status)
+ if (conn)
return conn;
hchan = hci_chan_create(hcon);
@@ -1520,8 +1606,10 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
return NULL;
}
+ kref_init(&conn->ref);
hcon->l2cap_data = conn;
conn->hcon = hcon;
+ hci_conn_get(conn->hcon);
conn->hchan = hchan;
BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
@@ -1547,6 +1635,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
mutex_init(&conn->chan_lock);
INIT_LIST_HEAD(&conn->chan_l);
+ INIT_LIST_HEAD(&conn->users);
if (hcon->type == LE_LINK)
INIT_DELAYED_WORK(&conn->security_timer, security_timeout);
@@ -1558,6 +1647,26 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
return conn;
}
+static void l2cap_conn_free(struct kref *ref)
+{
+ struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref);
+
+ hci_conn_put(conn->hcon);
+ kfree(conn);
+}
+
+void l2cap_conn_get(struct l2cap_conn *conn)
+{
+ kref_get(&conn->ref);
+}
+EXPORT_SYMBOL(l2cap_conn_get);
+
+void l2cap_conn_put(struct l2cap_conn *conn)
+{
+ kref_put(&conn->ref, l2cap_conn_free);
+}
+EXPORT_SYMBOL(l2cap_conn_put);
+
/* ---- Socket interface ---- */
/* Find socket with psm and source / destination bdaddr.
@@ -1695,9 +1804,9 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
goto done;
}
- conn = l2cap_conn_add(hcon, 0);
+ conn = l2cap_conn_add(hcon);
if (!conn) {
- hci_conn_put(hcon);
+ hci_conn_drop(hcon);
err = -ENOMEM;
goto done;
}
@@ -1707,7 +1816,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
if (!list_empty(&conn->chan_l)) {
err = -EBUSY;
- hci_conn_put(hcon);
+ hci_conn_drop(hcon);
}
if (err)
@@ -6313,7 +6422,7 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
if (!status) {
- conn = l2cap_conn_add(hcon, status);
+ conn = l2cap_conn_add(hcon);
if (conn)
l2cap_conn_ready(conn);
} else {
@@ -6482,7 +6591,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
goto drop;
if (!conn)
- conn = l2cap_conn_add(hcon, 0);
+ conn = l2cap_conn_add(hcon);
if (!conn)
goto drop;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 7f9704993b74..141e7b058b7e 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -43,6 +43,12 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent);
static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
int proto, gfp_t prio);
+bool l2cap_is_socket(struct socket *sock)
+{
+ return sock && sock->ops == &l2cap_sock_ops;
+}
+EXPORT_SYMBOL(l2cap_is_socket);
+
static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
{
struct sock *sk = sock->sk;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 03e7e732215f..4c830c62ef74 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -106,11 +106,10 @@ static const u16 mgmt_events[] = {
* These LE scan and inquiry parameters were chosen according to LE General
* Discovery Procedure specification.
*/
-#define LE_SCAN_TYPE 0x01
#define LE_SCAN_WIN 0x12
#define LE_SCAN_INT 0x12
-#define LE_SCAN_TIMEOUT_LE_ONLY 10240 /* TGAP(gen_disc_scan_min) */
-#define LE_SCAN_TIMEOUT_BREDR_LE 5120 /* TGAP(100)/2 */
+#define LE_SCAN_TIMEOUT_LE_ONLY msecs_to_jiffies(10240)
+#define LE_SCAN_TIMEOUT_BREDR_LE msecs_to_jiffies(5120)
#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */
#define INQUIRY_LEN_BREDR_LE 0x04 /* TGAP(100)/2 */
@@ -2131,7 +2130,7 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status)
conn->security_cfm_cb = NULL;
conn->disconn_cfm_cb = NULL;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
mgmt_pending_remove(cmd);
}
@@ -2222,7 +2221,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
}
if (conn->connect_cfm_cb) {
- hci_conn_put(conn);
+ hci_conn_drop(conn);
err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_BUSY, &rp, sizeof(rp));
goto unlock;
@@ -2231,7 +2230,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
- hci_conn_put(conn);
+ hci_conn_drop(conn);
goto unlock;
}
@@ -2703,7 +2702,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed;
}
- err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT,
+ err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT,
LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY);
break;
@@ -2715,8 +2714,8 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed;
}
- err = hci_le_scan(hdev, LE_SCAN_TYPE, LE_SCAN_INT, LE_SCAN_WIN,
- LE_SCAN_TIMEOUT_BREDR_LE);
+ err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT,
+ LE_SCAN_WIN, LE_SCAN_TIMEOUT_BREDR_LE);
break;
default:
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 2c8055350510..373d81e6e8f0 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -83,7 +83,7 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
if (conn)
return conn;
- conn = kzalloc(sizeof(struct sco_conn), GFP_ATOMIC);
+ conn = kzalloc(sizeof(struct sco_conn), GFP_KERNEL);
if (!conn)
return NULL;
@@ -185,7 +185,7 @@ static int sco_connect(struct sock *sk)
conn = sco_conn_add(hcon);
if (!conn) {
- hci_conn_put(hcon);
+ hci_conn_drop(hcon);
err = -ENOMEM;
goto done;
}
@@ -353,7 +353,7 @@ static void __sco_sock_close(struct sock *sk)
if (sco_pi(sk)->conn->hcon) {
sk->sk_state = BT_DISCONN;
sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
- hci_conn_put(sco_pi(sk)->conn->hcon);
+ hci_conn_drop(sco_pi(sk)->conn->hcon);
sco_pi(sk)->conn->hcon = NULL;
} else
sco_chan_del(sk, ECONNRESET);
@@ -481,8 +481,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
{
struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
struct sock *sk = sock->sk;
- int err = 0;
-
+ int err;
BT_DBG("sk %p", sk);
@@ -653,6 +652,42 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
return err;
}
+static void sco_conn_defer_accept(struct hci_conn *conn, int mask)
+{
+ struct hci_dev *hdev = conn->hdev;
+
+ BT_DBG("conn %p", conn);
+
+ conn->state = BT_CONFIG;
+
+ if (!lmp_esco_capable(hdev)) {
+ struct hci_cp_accept_conn_req cp;
+
+ bacpy(&cp.bdaddr, &conn->dst);
+
+ if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
+ cp.role = 0x00; /* Become master */
+ else
+ cp.role = 0x01; /* Remain slave */
+
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
+ } else {
+ struct hci_cp_accept_sync_conn_req cp;
+
+ bacpy(&cp.bdaddr, &conn->dst);
+ cp.pkt_type = cpu_to_le16(conn->pkt_type);
+
+ cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
+ cp.max_latency = __constant_cpu_to_le16(0xffff);
+ cp.content_format = cpu_to_le16(hdev->voice_setting);
+ cp.retrans_effort = 0xff;
+
+ hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
+ sizeof(cp), &cp);
+ }
+}
+
static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags)
{
@@ -663,7 +698,7 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
if (sk->sk_state == BT_CONNECT2 &&
test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
- hci_conn_accept(pi->conn->hcon, 0);
+ sco_conn_defer_accept(pi->conn->hcon, 0);
sk->sk_state = BT_CONFIG;
msg->msg_namelen = 0;
@@ -883,7 +918,7 @@ static void sco_chan_del(struct sock *sk, int err)
sco_conn_unlock(conn);
if (conn->hcon)
- hci_conn_put(conn->hcon);
+ hci_conn_drop(conn->hcon);
}
sk->sk_state = BT_CLOSED;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 5abefb12891d..b2296d3857a0 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -522,7 +522,7 @@ void smp_chan_destroy(struct l2cap_conn *conn)
kfree(smp);
conn->smp_chan = NULL;
conn->hcon->smp_conn = NULL;
- hci_conn_put(conn->hcon);
+ hci_conn_drop(conn->hcon);
}
int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index c50c19402588..1a89c80e6407 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -805,8 +805,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
IEEE80211_CHANCTX_EXCLUSIVE);
}
} else if (local->open_count == local->monitors) {
- local->_oper_channel = chandef->chan;
- local->_oper_channel_type = cfg80211_get_chandef_type(chandef);
+ local->_oper_chandef = *chandef;
ieee80211_hw_config(local, 0);
}
@@ -965,8 +964,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
sdata->vif.bss_conf.hidden_ssid =
(params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE);
- sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow;
- sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps;
+ memset(&sdata->vif.bss_conf.p2p_noa_attr, 0,
+ sizeof(sdata->vif.bss_conf.p2p_noa_attr));
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow =
+ params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
+ if (params->p2p_opp_ps)
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+ IEEE80211_P2P_OPPPS_ENABLE_BIT;
err = ieee80211_assign_beacon(sdata, &params->beacon);
if (err < 0)
@@ -1039,6 +1043,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
sta_info_flush_defer(vlan);
sta_info_flush_defer(sdata);
+ synchronize_net();
rcu_barrier();
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
sta_info_flush_cleanup(vlan);
@@ -1048,6 +1053,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
ieee80211_free_keys(sdata);
sdata->vif.bss_conf.enable_beacon = false;
+ sdata->vif.bss_conf.ssid_len = 0;
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
@@ -1536,7 +1542,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_sub_if_data *sdata;
struct mesh_path *mpath;
struct sta_info *sta;
- int err;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1547,17 +1552,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
return -ENOENT;
}
- err = mesh_path_add(sdata, dst);
- if (err) {
+ mpath = mesh_path_add(sdata, dst);
+ if (IS_ERR(mpath)) {
rcu_read_unlock();
- return err;
+ return PTR_ERR(mpath);
}
- mpath = mesh_path_lookup(sdata, dst);
- if (!mpath) {
- rcu_read_unlock();
- return -ENXIO;
- }
mesh_path_fix_nexthop(mpath, sta);
rcu_read_unlock();
@@ -1961,12 +1961,20 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
}
if (params->p2p_ctwindow >= 0) {
- sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow;
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &=
+ ~IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+ params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
changed |= BSS_CHANGED_P2P_PS;
}
- if (params->p2p_opp_ps >= 0) {
- sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps;
+ if (params->p2p_opp_ps > 0) {
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+ IEEE80211_P2P_OPPPS_ENABLE_BIT;
+ changed |= BSS_CHANGED_P2P_PS;
+ } else if (params->p2p_opp_ps == 0) {
+ sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &=
+ ~IEEE80211_P2P_OPPPS_ENABLE_BIT;
changed |= BSS_CHANGED_P2P_PS;
}
@@ -2410,9 +2418,22 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
}
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+ struct ieee80211_supported_band *sband = wiphy->bands[i];
+ int j;
+
sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs,
sizeof(mask->control[i].mcs));
+
+ sdata->rc_has_mcs_mask[i] = false;
+ if (!sband)
+ continue;
+
+ for (j = 0; j < IEEE80211_HT_MCS_MASK_LEN; j++)
+ if (~sdata->rc_rateidx_mcs_mask[i][j]) {
+ sdata->rc_has_mcs_mask[i] = true;
+ break;
+ }
}
return 0;
@@ -3362,9 +3383,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
if (local->use_chanctx)
*chandef = local->monitor_chandef;
else
- cfg80211_chandef_create(chandef,
- local->_oper_channel,
- local->_oper_channel_type);
+ *chandef = local->_oper_chandef;
ret = 0;
}
rcu_read_unlock();
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 931be419ab5a..03e8d2e3270e 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -22,7 +22,7 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
if (!local->use_chanctx) {
- local->_oper_channel_type = cfg80211_get_chandef_type(chandef);
+ local->_oper_chandef = *chandef;
ieee80211_hw_config(local, 0);
}
}
@@ -57,6 +57,22 @@ ieee80211_find_chanctx(struct ieee80211_local *local,
return NULL;
}
+static bool ieee80211_is_radar_required(struct ieee80211_local *local)
+{
+ struct ieee80211_sub_if_data *sdata;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ if (sdata->radar_required) {
+ rcu_read_unlock();
+ return true;
+ }
+ }
+ rcu_read_unlock();
+
+ return false;
+}
+
static struct ieee80211_chanctx *
ieee80211_new_chanctx(struct ieee80211_local *local,
const struct cfg80211_chan_def *chandef,
@@ -76,6 +92,9 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
ctx->conf.rx_chains_static = 1;
ctx->conf.rx_chains_dynamic = 1;
ctx->mode = mode;
+ ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
+ if (!local->use_chanctx)
+ local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
/* acquire mutex to prevent idle from changing */
mutex_lock(&local->mtx);
@@ -85,9 +104,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
ieee80211_hw_config(local, changed);
if (!local->use_chanctx) {
- local->_oper_channel_type =
- cfg80211_get_chandef_type(chandef);
- local->_oper_channel = chandef->chan;
+ local->_oper_chandef = *chandef;
ieee80211_hw_config(local, 0);
} else {
err = drv_add_chanctx(local, ctx);
@@ -112,12 +129,24 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
static void ieee80211_free_chanctx(struct ieee80211_local *local,
struct ieee80211_chanctx *ctx)
{
+ bool check_single_channel = false;
lockdep_assert_held(&local->chanctx_mtx);
WARN_ON_ONCE(ctx->refcount != 0);
if (!local->use_chanctx) {
- local->_oper_channel_type = NL80211_CHAN_NO_HT;
+ struct cfg80211_chan_def *chandef = &local->_oper_chandef;
+ chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
+ chandef->center_freq1 = chandef->chan->center_freq;
+ chandef->center_freq2 = 0;
+
+ /* NOTE: Disabling radar is only valid here for
+ * single channel context. To be sure, check it ...
+ */
+ if (local->hw.conf.radar_enabled)
+ check_single_channel = true;
+ local->hw.conf.radar_enabled = false;
+
ieee80211_hw_config(local, 0);
} else {
drv_remove_chanctx(local, ctx);
@@ -126,6 +155,9 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
list_del_rcu(&ctx->list);
kfree_rcu(ctx, rcu_head);
+ /* throw a warning if this wasn't the only channel context. */
+ WARN_ON(check_single_channel && !list_empty(&local->chanctx_list));
+
mutex_lock(&local->mtx);
ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx);
@@ -237,19 +269,11 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
struct ieee80211_chanctx *chanctx)
{
- struct ieee80211_sub_if_data *sdata;
- bool radar_enabled = false;
+ bool radar_enabled;
lockdep_assert_held(&local->chanctx_mtx);
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (sdata->radar_required) {
- radar_enabled = true;
- break;
- }
- }
- rcu_read_unlock();
+ radar_enabled = ieee80211_is_radar_required(local);
if (radar_enabled == chanctx->conf.radar_enabled)
return;
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ddb426867904..14abcf44f974 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -124,6 +124,15 @@ static ssize_t ieee80211_if_fmt_##name( \
return scnprintf(buf, buflen, "%d\n", sdata->field / 16); \
}
+#define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, field) \
+static ssize_t ieee80211_if_fmt_##name( \
+ const struct ieee80211_sub_if_data *sdata, \
+ char *buf, int buflen) \
+{ \
+ return scnprintf(buf, buflen, "%d\n", \
+ jiffies_to_msecs(sdata->field)); \
+}
+
#define __IEEE80211_IF_FILE(name, _write) \
static ssize_t ieee80211_if_read_##name(struct file *file, \
char __user *userbuf, \
@@ -197,6 +206,7 @@ IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
IEEE80211_IF_FILE(last_beacon, u.mgd.last_beacon_signal, DEC);
IEEE80211_IF_FILE(ave_beacon, u.mgd.ave_beacon_signal, DEC_DIV_16);
+IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS);
static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
enum ieee80211_smps_mode smps_mode)
@@ -542,6 +552,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(aid);
DEBUGFS_ADD(last_beacon);
DEBUGFS_ADD(ave_beacon);
+ DEBUGFS_ADD(beacon_timeout);
DEBUGFS_ADD_MODE(smps, 0600);
DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
DEBUGFS_ADD_MODE(uapsd_queues, 0600);
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 4f841fe559df..44e201d60a13 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -54,6 +54,7 @@ STA_FILE(aid, sta.aid, D);
STA_FILE(dev, sdata->name, S);
STA_FILE(last_signal, last_signal, D);
STA_FILE(last_ack_signal, last_ack_signal, D);
+STA_FILE(beacon_loss_count, beacon_loss_count, D);
static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
@@ -434,6 +435,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
DEBUGFS_ADD(agg_status);
DEBUGFS_ADD(dev);
DEBUGFS_ADD(last_signal);
+ DEBUGFS_ADD(beacon_loss_count);
DEBUGFS_ADD(ht_capa);
DEBUGFS_ADD(vht_capa);
DEBUGFS_ADD(last_ack_signal);
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 539d4a11b47b..170f9a7fa319 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -44,7 +44,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
int rates, i;
- struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
u8 *pos;
struct ieee80211_supported_band *sband;
@@ -52,20 +51,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
u32 bss_change;
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
struct cfg80211_chan_def chandef;
+ struct beacon_data *presp;
+ int frame_len;
lockdep_assert_held(&ifibss->mtx);
/* Reset own TSF to allow time synchronization work. */
drv_reset_tsf(local, sdata);
- skb = ifibss->skb;
- RCU_INIT_POINTER(ifibss->presp, NULL);
- synchronize_rcu();
- skb->data = skb->head;
- skb->len = 0;
- skb_reset_tail_pointer(skb);
- skb_reserve(skb, sdata->local->hw.extra_tx_headroom);
-
if (!ether_addr_equal(ifibss->bssid, bssid))
sta_info_flush(sdata);
@@ -73,10 +66,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
if (sdata->vif.bss_conf.ibss_joined) {
sdata->vif.bss_conf.ibss_joined = false;
sdata->vif.bss_conf.ibss_creator = false;
+ sdata->vif.bss_conf.enable_beacon = false;
netif_carrier_off(sdata->dev);
- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS);
+ ieee80211_bss_info_change_notify(sdata,
+ BSS_CHANGED_IBSS |
+ BSS_CHANGED_BEACON_ENABLED);
}
+ presp = rcu_dereference_protected(ifibss->presp,
+ lockdep_is_held(&ifibss->mtx));
+ rcu_assign_pointer(ifibss->presp, NULL);
+ if (presp)
+ kfree_rcu(presp, rcu_head);
+
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
cfg80211_chandef_create(&chandef, chan, ifibss->channel_type);
@@ -98,19 +100,24 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
sband = local->hw.wiphy->bands[chan->band];
- /* build supported rates array */
- pos = supp_rates;
- for (i = 0; i < sband->n_bitrates; i++) {
- int rate = sband->bitrates[i].bitrate;
- u8 basic = 0;
- if (basic_rates & BIT(i))
- basic = 0x80;
- *pos++ = basic | (u8) (rate / 5);
- }
-
/* Build IBSS probe response */
- mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon));
- memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
+ frame_len = sizeof(struct ieee80211_hdr_3addr) +
+ 12 /* struct ieee80211_mgmt.u.beacon */ +
+ 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
+ 2 + 8 /* max Supported Rates */ +
+ 3 /* max DS params */ +
+ 4 /* IBSS params */ +
+ 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
+ 2 + sizeof(struct ieee80211_ht_cap) +
+ 2 + sizeof(struct ieee80211_ht_operation) +
+ ifibss->ie_len;
+ presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL);
+ if (!presp)
+ return;
+
+ presp->head = (void *)(presp + 1);
+
+ mgmt = (void *) presp->head;
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
eth_broadcast_addr(mgmt->da);
@@ -120,27 +127,30 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
mgmt->u.beacon.timestamp = cpu_to_le64(tsf);
mgmt->u.beacon.capab_info = cpu_to_le16(capability);
- pos = skb_put(skb, 2 + ifibss->ssid_len);
+ pos = (u8 *)mgmt + offsetof(struct ieee80211_mgmt, u.beacon.variable);
+
*pos++ = WLAN_EID_SSID;
*pos++ = ifibss->ssid_len;
memcpy(pos, ifibss->ssid, ifibss->ssid_len);
+ pos += ifibss->ssid_len;
- rates = sband->n_bitrates;
- if (rates > 8)
- rates = 8;
- pos = skb_put(skb, 2 + rates);
+ rates = min_t(int, 8, sband->n_bitrates);
*pos++ = WLAN_EID_SUPP_RATES;
*pos++ = rates;
- memcpy(pos, supp_rates, rates);
+ for (i = 0; i < rates; i++) {
+ int rate = sband->bitrates[i].bitrate;
+ u8 basic = 0;
+ if (basic_rates & BIT(i))
+ basic = 0x80;
+ *pos++ = basic | (u8) (rate / 5);
+ }
if (sband->band == IEEE80211_BAND_2GHZ) {
- pos = skb_put(skb, 2 + 1);
*pos++ = WLAN_EID_DS_PARAMS;
*pos++ = 1;
*pos++ = ieee80211_frequency_to_channel(chan->center_freq);
}
- pos = skb_put(skb, 2 + 2);
*pos++ = WLAN_EID_IBSS_PARAMS;
*pos++ = 2;
/* FIX: set ATIM window based on scan results */
@@ -148,23 +158,25 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
*pos++ = 0;
if (sband->n_bitrates > 8) {
- rates = sband->n_bitrates - 8;
- pos = skb_put(skb, 2 + rates);
*pos++ = WLAN_EID_EXT_SUPP_RATES;
- *pos++ = rates;
- memcpy(pos, &supp_rates[8], rates);
+ *pos++ = sband->n_bitrates - 8;
+ for (i = 8; i < sband->n_bitrates; i++) {
+ int rate = sband->bitrates[i].bitrate;
+ u8 basic = 0;
+ if (basic_rates & BIT(i))
+ basic = 0x80;
+ *pos++ = basic | (u8) (rate / 5);
+ }
}
- if (ifibss->ie_len)
- memcpy(skb_put(skb, ifibss->ie_len),
- ifibss->ie, ifibss->ie_len);
+ if (ifibss->ie_len) {
+ memcpy(pos, ifibss->ie, ifibss->ie_len);
+ pos += ifibss->ie_len;
+ }
/* add HT capability and information IEs */
if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
sband->ht_cap.ht_supported) {
- pos = skb_put(skb, 4 +
- sizeof(struct ieee80211_ht_cap) +
- sizeof(struct ieee80211_ht_operation));
pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
sband->ht_cap.cap);
/*
@@ -177,7 +189,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
}
if (local->hw.queues >= IEEE80211_NUM_ACS) {
- pos = skb_put(skb, 9);
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 7; /* len */
*pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
@@ -189,11 +200,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
*pos++ = 0; /* U-APSD no in use */
}
- rcu_assign_pointer(ifibss->presp, skb);
+ presp->head_len = pos - presp->head;
+ if (WARN_ON(presp->head_len > frame_len))
+ return;
+
+ rcu_assign_pointer(ifibss->presp, presp);
sdata->vif.bss_conf.enable_beacon = true;
sdata->vif.bss_conf.beacon_int = beacon_int;
sdata->vif.bss_conf.basic_rates = basic_rates;
+ sdata->vif.bss_conf.ssid_len = ifibss->ssid_len;
+ memcpy(sdata->vif.bss_conf.ssid, ifibss->ssid, ifibss->ssid_len);
bss_change = BSS_CHANGED_BEACON_INT;
bss_change |= ieee80211_reset_erp_info(sdata);
bss_change |= BSS_CHANGED_BSSID;
@@ -202,6 +219,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
bss_change |= BSS_CHANGED_BASIC_RATES;
bss_change |= BSS_CHANGED_HT;
bss_change |= BSS_CHANGED_IBSS;
+ bss_change |= BSS_CHANGED_SSID;
/*
* In 5 GHz/802.11a, we can always use short slot time.
@@ -227,7 +245,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan,
- mgmt, skb->len, 0, GFP_KERNEL);
+ mgmt, presp->head_len, 0, GFP_KERNEL);
cfg80211_put_bss(local->hw.wiphy, bss);
netif_carrier_on(sdata->dev);
cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
@@ -448,7 +466,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
bool rates_updated = false;
- if (elems->ds_params && elems->ds_params_len == 1)
+ if (elems->ds_params)
freq = ieee80211_channel_to_frequency(elems->ds_params[0],
band);
else
@@ -822,8 +840,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
int tx_last_beacon, len = req->len;
struct sk_buff *skb;
- struct ieee80211_mgmt *resp;
- struct sk_buff *presp;
+ struct beacon_data *presp;
u8 *pos, *end;
lockdep_assert_held(&ifibss->mtx);
@@ -864,13 +881,15 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
}
/* Reply with ProbeResp */
- skb = skb_copy(presp, GFP_KERNEL);
+ skb = dev_alloc_skb(local->tx_headroom + presp->head_len);
if (!skb)
return;
- resp = (struct ieee80211_mgmt *) skb->data;
- memcpy(resp->da, mgmt->sa, ETH_ALEN);
- ibss_dbg(sdata, "Sending ProbeResp to %pM\n", resp->da);
+ skb_reserve(skb, local->tx_headroom);
+ memcpy(skb_put(skb, presp->head_len), presp->head, presp->head_len);
+
+ memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN);
+ ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa);
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
ieee80211_tx_skb(sdata, skb);
}
@@ -895,7 +914,7 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata,
return;
ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
- &elems);
+ false, &elems);
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
}
@@ -1020,23 +1039,8 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
struct cfg80211_ibss_params *params)
{
- struct sk_buff *skb;
u32 changed = 0;
- skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
- sizeof(struct ieee80211_hdr_3addr) +
- 12 /* struct ieee80211_mgmt.u.beacon */ +
- 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
- 2 + 8 /* max Supported Rates */ +
- 3 /* max DS params */ +
- 4 /* IBSS params */ +
- 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
- 2 + sizeof(struct ieee80211_ht_cap) +
- 2 + sizeof(struct ieee80211_ht_operation) +
- params->ie_len);
- if (!skb)
- return -ENOMEM;
-
mutex_lock(&sdata->u.ibss.mtx);
if (params->bssid) {
@@ -1065,7 +1069,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
sdata->u.ibss.ie_len = params->ie_len;
}
- sdata->u.ibss.skb = skb;
sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
sdata->u.ibss.ibss_join_req = jiffies;
@@ -1101,13 +1104,13 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
{
- struct sk_buff *skb;
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
struct cfg80211_bss *cbss;
u16 capability;
int active_ibss;
struct sta_info *sta;
+ struct beacon_data *presp;
mutex_lock(&sdata->u.ibss.mtx);
@@ -1153,17 +1156,18 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
/* remove beacon */
kfree(sdata->u.ibss.ie);
- skb = rcu_dereference_protected(sdata->u.ibss.presp,
- lockdep_is_held(&sdata->u.ibss.mtx));
+ presp = rcu_dereference_protected(ifibss->presp,
+ lockdep_is_held(&sdata->u.ibss.mtx));
RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
sdata->vif.bss_conf.ibss_joined = false;
sdata->vif.bss_conf.ibss_creator = false;
sdata->vif.bss_conf.enable_beacon = false;
+ sdata->vif.bss_conf.ssid_len = 0;
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
BSS_CHANGED_IBSS);
synchronize_rcu();
- kfree_skb(skb);
+ kfree(presp);
skb_queue_purge(&sdata->skb_queue);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0b09716d22ad..158e6eb188d3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -156,6 +156,7 @@ struct ieee80211_tx_data {
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
struct ieee80211_key *key;
+ struct ieee80211_tx_rate rate;
unsigned int flags;
};
@@ -443,7 +444,7 @@ struct ieee80211_if_managed {
u8 use_4addr;
- u8 p2p_noa_index;
+ s16 p2p_noa_index;
/* Signal strength from the last Beacon frame in the current BSS. */
int last_beacon_signal;
@@ -509,8 +510,7 @@ struct ieee80211_if_ibss {
unsigned long ibss_join_req;
/* probe response/beacon for IBSS */
- struct sk_buff __rcu *presp;
- struct sk_buff *skb;
+ struct beacon_data __rcu *presp;
spinlock_t incomplete_lock;
struct list_head incomplete_stations;
@@ -741,6 +741,8 @@ struct ieee80211_sub_if_data {
/* bitmap of allowed (non-MCS) rate indexes for rate control */
u32 rc_rateidx_mask[IEEE80211_NUM_BANDS];
+
+ bool rc_has_mcs_mask[IEEE80211_NUM_BANDS];
u8 rc_rateidx_mcs_mask[IEEE80211_NUM_BANDS][IEEE80211_HT_MCS_MASK_LEN];
union {
@@ -1021,10 +1023,9 @@ struct ieee80211_local {
enum mac80211_scan_state next_scan_state;
struct delayed_work scan_work;
struct ieee80211_sub_if_data __rcu *scan_sdata;
- struct ieee80211_channel *csa_channel;
+ struct cfg80211_chan_def csa_chandef;
/* For backward compatibility only -- do not use */
- struct ieee80211_channel *_oper_channel;
- enum nl80211_channel_type _oper_channel_type;
+ struct cfg80211_chan_def _oper_chandef;
/* Temporary remain-on-channel for off-channel operations */
struct ieee80211_channel *tmp_channel;
@@ -1160,11 +1161,8 @@ struct ieee802_11_elems {
/* pointers to IEs */
const u8 *ssid;
const u8 *supp_rates;
- const u8 *fh_params;
const u8 *ds_params;
- const u8 *cf_params;
const struct ieee80211_tim_ie *tim;
- const u8 *ibss_params;
const u8 *challenge;
const u8 *rsn;
const u8 *erp_info;
@@ -1184,23 +1182,20 @@ struct ieee802_11_elems {
const u8 *perr;
const struct ieee80211_rann_ie *rann;
const struct ieee80211_channel_sw_ie *ch_switch_ie;
+ const struct ieee80211_ext_chansw_ie *ext_chansw_ie;
+ const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
const u8 *country_elem;
const u8 *pwr_constr_elem;
- const u8 *quiet_elem; /* first quite element */
- const u8 *timeout_int;
+ const struct ieee80211_timeout_interval_ie *timeout_int;
const u8 *opmode_notif;
+ const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
/* length of them, respectively */
u8 ssid_len;
u8 supp_rates_len;
- u8 fh_params_len;
- u8 ds_params_len;
- u8 cf_params_len;
u8 tim_len;
- u8 ibss_params_len;
u8 challenge_len;
u8 rsn_len;
- u8 erp_info_len;
u8 ext_supp_rates_len;
u8 wmm_info_len;
u8 wmm_param_len;
@@ -1210,9 +1205,6 @@ struct ieee802_11_elems {
u8 prep_len;
u8 perr_len;
u8 country_elem_len;
- u8 quiet_elem_len;
- u8 num_of_quiet_elem; /* can be more the one */
- u8 timeout_int_len;
/* whether a parse error occurred while retrieving these elements */
bool parse_error;
@@ -1267,10 +1259,6 @@ void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata);
int ieee80211_max_network_latency(struct notifier_block *nb,
unsigned long data, void *dummy);
int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata);
-void
-ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
- const struct ieee80211_channel_sw_ie *sw_elem,
- struct ieee80211_bss *bss, u64 timestamp);
void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
@@ -1330,7 +1318,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local);
void ieee80211_offchannel_return(struct ieee80211_local *local);
void ieee80211_roc_setup(struct ieee80211_local *local);
void ieee80211_start_next_roc(struct ieee80211_local *local);
-void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
+void ieee80211_roc_purge(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata);
void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free);
void ieee80211_sw_roc_work(struct work_struct *work);
void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
@@ -1351,6 +1340,8 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
const int offset);
int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up);
void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata);
+int ieee80211_add_virtual_monitor(struct ieee80211_local *local);
+void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
@@ -1505,11 +1496,15 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
ieee80211_tx_skb_tid(sdata, skb, 7);
}
-void ieee802_11_parse_elems(u8 *start, size_t len,
- struct ieee802_11_elems *elems);
-u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
+u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems,
u64 filter, u32 crc);
+static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action,
+ struct ieee802_11_elems *elems)
+{
+ ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
+}
+
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
enum ieee80211_band band);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index e8a260f53c16..60f1ce5e5e52 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1,5 +1,5 @@
/*
- * Interface handling (except master interface)
+ * Interface handling
*
* Copyright 2002-2005, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
@@ -357,7 +357,7 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
}
-static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
+int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
int ret;
@@ -410,7 +410,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
return 0;
}
-static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
+void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
@@ -595,7 +595,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
case NL80211_IFTYPE_P2P_DEVICE:
break;
default:
- netif_carrier_on(dev);
+ /* not reached */
+ WARN_ON(1);
}
/*
@@ -652,8 +653,28 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
ieee80211_recalc_ps(local, -1);
- if (dev)
- netif_tx_start_all_queues(dev);
+ if (dev) {
+ unsigned long flags;
+ int n_acs = IEEE80211_NUM_ACS;
+ int ac;
+
+ if (local->hw.queues < IEEE80211_NUM_ACS)
+ n_acs = 1;
+
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+ if (sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE ||
+ (local->queue_stop_reasons[sdata->vif.cab_queue] == 0 &&
+ skb_queue_empty(&local->pending[sdata->vif.cab_queue]))) {
+ for (ac = 0; ac < n_acs; ac++) {
+ int ac_queue = sdata->vif.hw_queue[ac];
+
+ if (local->queue_stop_reasons[ac_queue] == 0 &&
+ skb_queue_empty(&local->pending[ac_queue]))
+ netif_start_subqueue(dev, ac);
+ }
+ }
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+ }
return 0;
err_del_interface:
@@ -707,7 +728,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
if (sdata->dev)
netif_tx_stop_all_queues(sdata->dev);
- ieee80211_roc_purge(sdata);
+ ieee80211_roc_purge(local, sdata);
if (sdata->vif.type == NL80211_IFTYPE_STATION)
ieee80211_mgd_stop(sdata);
@@ -732,12 +753,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
(sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1));
- /*
- * Don't count this interface for promisc/allmulti while it
- * is down. dev_mc_unsync() will invoke set_multicast_list
- * on the master interface which will sync these down to the
- * hardware as filter flags.
- */
+ /* don't count this interface for promisc/allmulti while it is down */
if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
atomic_dec(&local->iff_allmultis);
@@ -758,8 +774,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
sdata->dev->addr_len);
spin_unlock_bh(&local->filter_lock);
netif_addr_unlock_bh(sdata->dev);
-
- ieee80211_configure_filter(local);
}
del_timer_sync(&local->dynamic_ps_timer);
@@ -770,6 +784,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
if (sdata->wdev.cac_started) {
+ WARN_ON(local->suspended);
mutex_lock(&local->iflist_mtx);
ieee80211_vif_release_channel(sdata);
mutex_unlock(&local->iflist_mtx);
@@ -820,14 +835,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
if (local->monitors == 0) {
local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
- ieee80211_del_virtual_monitor(local);
}
ieee80211_adjust_monitor_flags(sdata, -1);
- ieee80211_configure_filter(local);
- mutex_lock(&local->mtx);
- ieee80211_recalc_idle(local);
- mutex_unlock(&local->mtx);
break;
case NL80211_IFTYPE_P2P_DEVICE:
/* relies on synchronize_rcu() below */
@@ -840,11 +850,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
*
* sta_info_flush_cleanup() requires rcu_barrier()
* first to wait for the station call_rcu() calls
- * to complete, here we need at least sychronize_rcu()
- * it to wait for the RX path in case it is using the
+ * to complete, and we also need synchronize_rcu()
+ * to wait for the RX path in case it is using the
* interface and enqueuing frames at this very time on
* another CPU.
*/
+ synchronize_rcu();
rcu_barrier();
sta_info_flush_cleanup(sdata);
@@ -857,27 +868,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
/* fall through */
case NL80211_IFTYPE_AP:
skb_queue_purge(&sdata->skb_queue);
-
- if (going_down)
- drv_remove_interface(local, sdata);
}
sdata->bss = NULL;
- ieee80211_recalc_ps(local, -1);
-
- if (local->open_count == 0) {
- ieee80211_clear_tx_pending(local);
- ieee80211_stop_device(local);
-
- /* no reconfiguring after stop! */
- hw_reconf_flags = 0;
- }
-
- /* do after stop to avoid reconfiguring when we stop anyway */
- if (hw_reconf_flags)
- ieee80211_hw_config(local, hw_reconf_flags);
-
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
skb_queue_walk_safe(&local->pending[i], skb, tmp) {
@@ -890,7 +884,54 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
}
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
- if (local->monitors == local->open_count && local->monitors > 0)
+ if (local->open_count == 0)
+ ieee80211_clear_tx_pending(local);
+
+ /*
+ * If the interface goes down while suspended, presumably because
+ * the device was unplugged and that happens before our resume,
+ * then the driver is already unconfigured and the remainder of
+ * this function isn't needed.
+ * XXX: what about WoWLAN? If the device has software state, e.g.
+ * memory allocated, it might expect teardown commands from
+ * mac80211 here?
+ */
+ if (local->suspended) {
+ WARN_ON(local->wowlan);
+ WARN_ON(rtnl_dereference(local->monitor_sdata));
+ return;
+ }
+
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_AP_VLAN:
+ break;
+ case NL80211_IFTYPE_MONITOR:
+ if (local->monitors == 0)
+ ieee80211_del_virtual_monitor(local);
+
+ mutex_lock(&local->mtx);
+ ieee80211_recalc_idle(local);
+ mutex_unlock(&local->mtx);
+ break;
+ default:
+ if (going_down)
+ drv_remove_interface(local, sdata);
+ }
+
+ ieee80211_recalc_ps(local, -1);
+
+ if (local->open_count == 0) {
+ ieee80211_stop_device(local);
+
+ /* no reconfiguring after stop! */
+ return;
+ }
+
+ /* do after stop to avoid reconfiguring when we stop anyway */
+ ieee80211_configure_filter(local);
+ ieee80211_hw_config(local, hw_reconf_flags);
+
+ if (local->monitors == local->open_count)
ieee80211_add_virtual_monitor(local);
}
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index c6f81ecc36a1..8a7bfc47d577 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -95,42 +95,47 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
- struct ieee80211_channel *chan;
+ struct cfg80211_chan_def chandef = {};
u32 changed = 0;
int power;
- enum nl80211_channel_type channel_type;
u32 offchannel_flag;
offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
+
if (local->scan_channel) {
- chan = local->scan_channel;
+ chandef.chan = local->scan_channel;
/* If scanning on oper channel, use whatever channel-type
* is currently in use.
*/
- if (chan == local->_oper_channel)
- channel_type = local->_oper_channel_type;
- else
- channel_type = NL80211_CHAN_NO_HT;
+ if (chandef.chan == local->_oper_chandef.chan) {
+ chandef = local->_oper_chandef;
+ } else {
+ chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+ chandef.center_freq1 = chandef.chan->center_freq;
+ }
} else if (local->tmp_channel) {
- chan = local->tmp_channel;
- channel_type = NL80211_CHAN_NO_HT;
- } else {
- chan = local->_oper_channel;
- channel_type = local->_oper_channel_type;
- }
-
- if (chan != local->_oper_channel ||
- channel_type != local->_oper_channel_type)
+ chandef.chan = local->tmp_channel;
+ chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+ chandef.center_freq1 = chandef.chan->center_freq;
+ } else
+ chandef = local->_oper_chandef;
+
+ WARN(!cfg80211_chandef_valid(&chandef),
+ "control:%d MHz width:%d center: %d/%d MHz",
+ chandef.chan->center_freq, chandef.width,
+ chandef.center_freq1, chandef.center_freq2);
+
+ if (!cfg80211_chandef_identical(&chandef, &local->_oper_chandef))
local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
else
local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
- if (offchannel_flag || chan != local->hw.conf.channel ||
- channel_type != local->hw.conf.channel_type) {
- local->hw.conf.channel = chan;
- local->hw.conf.channel_type = channel_type;
+ if (offchannel_flag ||
+ !cfg80211_chandef_identical(&local->hw.conf.chandef,
+ &local->_oper_chandef)) {
+ local->hw.conf.chandef = chandef;
changed |= IEEE80211_CONF_CHANGE_CHANNEL;
}
@@ -146,7 +151,7 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
changed |= IEEE80211_CONF_CHANGE_SMPS;
}
- power = chan->max_power;
+ power = chandef.chan->max_power;
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
@@ -587,6 +592,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
IEEE80211_RADIOTAP_MCS_HAVE_BW;
local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
+ local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+ local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask;
@@ -661,6 +668,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
int channels, max_bitrates;
bool supp_ht, supp_vht;
netdev_features_t feature_whitelist;
+ struct cfg80211_chan_def dflt_chandef = {};
static const u32 cipher_suites[] = {
/* keep WEP first, it may be removed below */
WLAN_CIPHER_SUITE_WEP40,
@@ -738,15 +746,19 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
sband = local->hw.wiphy->bands[band];
if (!sband)
continue;
- if (!local->use_chanctx && !local->_oper_channel) {
+
+ if (!dflt_chandef.chan) {
+ cfg80211_chandef_create(&dflt_chandef,
+ &sband->channels[0],
+ NL80211_CHAN_NO_HT);
/* init channel we're on */
- local->hw.conf.channel =
- local->_oper_channel = &sband->channels[0];
- local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
+ if (!local->use_chanctx && !local->_oper_chandef.chan) {
+ local->hw.conf.chandef = dflt_chandef;
+ local->_oper_chandef = dflt_chandef;
+ }
+ local->monitor_chandef = dflt_chandef;
}
- cfg80211_chandef_create(&local->monitor_chandef,
- &sband->channels[0],
- NL80211_CHAN_NO_HT);
+
channels += sband->n_channels;
if (max_bitrates < sband->n_bitrates)
@@ -829,22 +841,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (supp_ht)
local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
- if (supp_vht) {
+ if (supp_vht)
local->scan_ies_len +=
2 + sizeof(struct ieee80211_vht_cap);
- /*
- * (for now at least), drivers wanting to use VHT must
- * support channel contexts, as they contain all the
- * necessary VHT information and the global hw config
- * doesn't (yet)
- */
- if (WARN_ON(!local->use_chanctx)) {
- result = -EINVAL;
- goto fail_wiphy_register;
- }
- }
-
if (!local->ops->hw_scan) {
/* For hw_scan, driver needs to set these up. */
local->hw.wiphy->max_scan_ssids = 4;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 123a300cef57..6952760881c8 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -838,7 +838,7 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
if (baselen > len)
return;
- ieee802_11_parse_elems(pos, len - baselen, &elems);
+ ieee802_11_parse_elems(pos, len - baselen, false, &elems);
/* 802.11-2012 10.1.4.3.2 */
if ((!ether_addr_equal(mgmt->da, sdata->vif.addr) &&
@@ -899,7 +899,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
return;
ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
- &elems);
+ false, &elems);
/* ignore non-mesh or secure / unsecure mismatch */
if ((!elems.mesh_id || !elems.mesh_config) ||
@@ -907,7 +907,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
(!elems.rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE))
return;
- if (elems.ds_params && elems.ds_params_len == 1)
+ if (elems.ds_params)
freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);
else
freq = rx_status->freq;
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 6ffabbe99c46..da158774eebb 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -275,7 +275,8 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len);
-int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst);
+struct mesh_path *
+mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst);
int mesh_path_add_gate(struct mesh_path *mpath);
int mesh_path_send_to_gates(struct mesh_path *mpath);
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index bdb8d3b14587..486819cd02cd 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -144,7 +144,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
*pos++ = WLAN_EID_PREQ;
break;
case MPATH_PREP:
- mhwmp_dbg(sdata, "sending PREP to %pM\n", target);
+ mhwmp_dbg(sdata, "sending PREP to %pM\n", orig_addr);
ie_len = 31;
pos = skb_put(skb, 2 + ie_len);
*pos++ = WLAN_EID_PREP;
@@ -445,9 +445,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
}
}
} else {
- mesh_path_add(sdata, orig_addr);
- mpath = mesh_path_lookup(sdata, orig_addr);
- if (!mpath) {
+ mpath = mesh_path_add(sdata, orig_addr);
+ if (IS_ERR(mpath)) {
rcu_read_unlock();
return 0;
}
@@ -486,9 +485,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
(last_hop_metric > mpath->metric)))
fresh_info = false;
} else {
- mesh_path_add(sdata, ta);
- mpath = mesh_path_lookup(sdata, ta);
- if (!mpath) {
+ mpath = mesh_path_add(sdata, ta);
+ if (IS_ERR(mpath)) {
rcu_read_unlock();
return 0;
}
@@ -661,7 +659,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
u32 target_sn, orig_sn, lifetime;
mhwmp_dbg(sdata, "received PREP from %pM\n",
- PREP_IE_ORIG_ADDR(prep_elem));
+ PREP_IE_TARGET_ADDR(prep_elem));
orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
if (ether_addr_equal(orig_addr, sdata->vif.addr))
@@ -804,9 +802,8 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
mpath = mesh_path_lookup(sdata, orig_addr);
if (!mpath) {
- mesh_path_add(sdata, orig_addr);
- mpath = mesh_path_lookup(sdata, orig_addr);
- if (!mpath) {
+ mpath = mesh_path_add(sdata, orig_addr);
+ if (IS_ERR(mpath)) {
rcu_read_unlock();
sdata->u.mesh.mshstats.dropped_frames_no_route++;
return;
@@ -883,7 +880,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
- len - baselen, &elems);
+ len - baselen, false, &elems);
if (elems.preq) {
if (elems.preq_len != 37)
@@ -1098,11 +1095,10 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
/* no nexthop found, start resolving */
mpath = mesh_path_lookup(sdata, target_addr);
if (!mpath) {
- mesh_path_add(sdata, target_addr);
- mpath = mesh_path_lookup(sdata, target_addr);
- if (!mpath) {
+ mpath = mesh_path_add(sdata, target_addr);
+ if (IS_ERR(mpath)) {
mesh_path_discard_frame(sdata, skb);
- err = -ENOSPC;
+ err = PTR_ERR(mpath);
goto endlookup;
}
}
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index dc7c8df40c2c..89aacfd2756d 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -493,7 +493,8 @@ int mesh_gate_num(struct ieee80211_sub_if_data *sdata)
*
* State: the initial state of the new path is set to 0
*/
-int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
+struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
+ const u8 *dst)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local;
@@ -502,18 +503,33 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
struct mpath_node *node, *new_node;
struct hlist_head *bucket;
int grow = 0;
- int err = 0;
+ int err;
u32 hash_idx;
if (ether_addr_equal(dst, sdata->vif.addr))
/* never add ourselves as neighbours */
- return -ENOTSUPP;
+ return ERR_PTR(-ENOTSUPP);
if (is_multicast_ether_addr(dst))
- return -ENOTSUPP;
+ return ERR_PTR(-ENOTSUPP);
if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0)
- return -ENOSPC;
+ return ERR_PTR(-ENOSPC);
+
+ read_lock_bh(&pathtbl_resize_lock);
+ tbl = resize_dereference_mesh_paths();
+
+ hash_idx = mesh_table_hash(dst, sdata, tbl);
+ bucket = &tbl->hash_buckets[hash_idx];
+
+ spin_lock(&tbl->hashwlock[hash_idx]);
+
+ hlist_for_each_entry(node, bucket, list) {
+ mpath = node->mpath;
+ if (mpath->sdata == sdata &&
+ ether_addr_equal(dst, mpath->dst))
+ goto found;
+ }
err = -ENOMEM;
new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
@@ -524,7 +540,6 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
if (!new_node)
goto err_node_alloc;
- read_lock_bh(&pathtbl_resize_lock);
memcpy(new_mpath->dst, dst, ETH_ALEN);
eth_broadcast_addr(new_mpath->rann_snd_addr);
new_mpath->is_root = false;
@@ -538,21 +553,6 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
spin_lock_init(&new_mpath->state_lock);
init_timer(&new_mpath->timer);
- tbl = resize_dereference_mesh_paths();
-
- hash_idx = mesh_table_hash(dst, sdata, tbl);
- bucket = &tbl->hash_buckets[hash_idx];
-
- spin_lock(&tbl->hashwlock[hash_idx]);
-
- err = -EEXIST;
- hlist_for_each_entry(node, bucket, list) {
- mpath = node->mpath;
- if (mpath->sdata == sdata &&
- ether_addr_equal(dst, mpath->dst))
- goto err_exists;
- }
-
hlist_add_head_rcu(&new_node->list, bucket);
if (atomic_inc_return(&tbl->entries) >=
tbl->mean_chain_len * (tbl->hash_mask + 1))
@@ -560,23 +560,23 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
mesh_paths_generation++;
- spin_unlock(&tbl->hashwlock[hash_idx]);
- read_unlock_bh(&pathtbl_resize_lock);
if (grow) {
set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
ieee80211_queue_work(&local->hw, &sdata->work);
}
- return 0;
-
-err_exists:
+ mpath = new_mpath;
+found:
spin_unlock(&tbl->hashwlock[hash_idx]);
read_unlock_bh(&pathtbl_resize_lock);
- kfree(new_node);
+ return mpath;
+
err_node_alloc:
kfree(new_mpath);
err_path_alloc:
atomic_dec(&sdata->u.mesh.mpaths);
- return err;
+ spin_unlock(&tbl->hashwlock[hash_idx]);
+ read_unlock_bh(&pathtbl_resize_lock);
+ return ERR_PTR(err);
}
static void mesh_table_free_rcu(struct rcu_head *rcu)
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 937e06fe8f2a..09bebed99416 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -544,8 +544,8 @@ static void mesh_plink_timer(unsigned long data)
return;
}
mpl_dbg(sta->sdata,
- "Mesh plink timer for %pM fired on state %d\n",
- sta->sta.addr, sta->plink_state);
+ "Mesh plink timer for %pM fired on state %s\n",
+ sta->sta.addr, mplstates[sta->plink_state]);
reason = 0;
llid = sta->llid;
plid = sta->plid;
@@ -687,7 +687,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
baseaddr += 4;
baselen += 4;
}
- ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
+ ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems);
if (!elems.peering) {
mpl_dbg(sdata,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index dec42ab1fa91..29620bfc7a69 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -56,7 +56,10 @@ MODULE_PARM_DESC(max_probe_tries,
* probe on beacon miss before declaring the connection lost
* default to what we want.
*/
-#define IEEE80211_BEACON_LOSS_COUNT 7
+static int beacon_loss_count = 7;
+module_param(beacon_loss_count, int, 0644);
+MODULE_PARM_DESC(beacon_loss_count,
+ "Number of beacon intervals before we decide beacon was lost.");
/*
* Time the connection can be idle before we probe
@@ -286,6 +289,8 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
} else {
/* 40 MHz (and 80 MHz) must be supported for VHT */
ret = IEEE80211_STA_DISABLE_VHT;
+ /* also mark 40 MHz disabled */
+ ret |= IEEE80211_STA_DISABLE_40MHZ;
goto out;
}
@@ -300,12 +305,6 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
channel->band);
vht_chandef.center_freq2 = 0;
- if (vht_oper->center_freq_seg2_idx)
- vht_chandef.center_freq2 =
- ieee80211_channel_to_frequency(
- vht_oper->center_freq_seg2_idx,
- channel->band);
-
switch (vht_oper->chan_width) {
case IEEE80211_VHT_CHANWIDTH_USE_HT:
vht_chandef.width = chandef->width;
@@ -318,6 +317,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
break;
case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
+ vht_chandef.center_freq2 =
+ ieee80211_channel_to_frequency(
+ vht_oper->center_freq_seg2_idx,
+ channel->band);
break;
default:
if (verbose)
@@ -601,7 +604,6 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
u8 *pos;
u32 cap;
struct ieee80211_sta_vht_cap vht_cap;
- int i;
BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap));
@@ -629,37 +631,6 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)))
cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
- if (!(ap_vht_cap->vht_cap_info &
- cpu_to_le32(IEEE80211_VHT_CAP_TXSTBC)))
- cap &= ~(IEEE80211_VHT_CAP_RXSTBC_1 |
- IEEE80211_VHT_CAP_RXSTBC_3 |
- IEEE80211_VHT_CAP_RXSTBC_4);
-
- for (i = 0; i < 8; i++) {
- int shift = i * 2;
- u16 mask = IEEE80211_VHT_MCS_NOT_SUPPORTED << shift;
- u16 ap_mcs, our_mcs;
-
- ap_mcs = (le16_to_cpu(ap_vht_cap->supp_mcs.tx_mcs_map) &
- mask) >> shift;
- our_mcs = (le16_to_cpu(vht_cap.vht_mcs.rx_mcs_map) &
- mask) >> shift;
-
- if (our_mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED)
- continue;
-
- switch (ap_mcs) {
- default:
- if (our_mcs <= ap_mcs)
- break;
- /* fall through */
- case IEEE80211_VHT_MCS_NOT_SUPPORTED:
- vht_cap.vht_mcs.rx_mcs_map &= cpu_to_le16(~mask);
- vht_cap.vht_mcs.rx_mcs_map |=
- cpu_to_le16(ap_mcs << shift);
- }
- }
-
/* reserve and fill IE */
pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
@@ -985,6 +956,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
{
struct ieee80211_sub_if_data *sdata =
container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
+ struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
if (!ieee80211_sdata_running(sdata))
@@ -994,21 +966,21 @@ static void ieee80211_chswitch_work(struct work_struct *work)
if (!ifmgd->associated)
goto out;
- sdata->local->_oper_channel = sdata->local->csa_channel;
- if (!sdata->local->ops->channel_switch) {
+ local->_oper_chandef = local->csa_chandef;
+
+ if (!local->ops->channel_switch) {
/* call "hw_config" only if doing sw channel switch */
- ieee80211_hw_config(sdata->local,
- IEEE80211_CONF_CHANGE_CHANNEL);
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
} else {
/* update the device channel directly */
- sdata->local->hw.conf.channel = sdata->local->_oper_channel;
+ local->hw.conf.chandef = local->_oper_chandef;
}
/* XXX: shouldn't really modify cfg80211-owned data! */
- ifmgd->associated->channel = sdata->local->_oper_channel;
+ ifmgd->associated->channel = local->_oper_chandef.chan;
/* XXX: wait for a beacon first? */
- ieee80211_wake_queues_by_reason(&sdata->local->hw,
+ ieee80211_wake_queues_by_reason(&local->hw,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
out:
@@ -1041,56 +1013,193 @@ static void ieee80211_chswitch_timer(unsigned long data)
ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
}
-void
+static void
ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
- const struct ieee80211_channel_sw_ie *sw_elem,
- struct ieee80211_bss *bss, u64 timestamp)
+ u64 timestamp, struct ieee802_11_elems *elems)
{
- struct cfg80211_bss *cbss =
- container_of((void *)bss, struct cfg80211_bss, priv);
- struct ieee80211_channel *new_ch;
+ struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num,
- cbss->channel->band);
+ struct cfg80211_bss *cbss = ifmgd->associated;
+ struct ieee80211_bss *bss;
struct ieee80211_chanctx *chanctx;
+ enum ieee80211_band new_band;
+ int new_freq;
+ u8 new_chan_no;
+ u8 count;
+ u8 mode;
+ struct ieee80211_channel *new_chan;
+ struct cfg80211_chan_def new_chandef = {};
+ struct cfg80211_chan_def new_vht_chandef = {};
+ const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
+ const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
+ int secondary_channel_offset = -1;
ASSERT_MGD_MTX(ifmgd);
- if (!ifmgd->associated)
+ if (!cbss)
return;
- if (sdata->local->scanning)
+ if (local->scanning)
return;
- /* Disregard subsequent beacons if we are already running a timer
- processing a CSA */
-
+ /* disregard subsequent announcements if we are already processing */
if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
return;
- new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
- if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) {
+ sec_chan_offs = elems->sec_chan_offs;
+ wide_bw_chansw_ie = elems->wide_bw_chansw_ie;
+
+ if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
+ IEEE80211_STA_DISABLE_40MHZ)) {
+ sec_chan_offs = NULL;
+ wide_bw_chansw_ie = NULL;
+ }
+
+ if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
+ wide_bw_chansw_ie = NULL;
+
+ if (elems->ext_chansw_ie) {
+ if (!ieee80211_operating_class_to_band(
+ elems->ext_chansw_ie->new_operating_class,
+ &new_band)) {
+ sdata_info(sdata,
+ "cannot understand ECSA IE operating class %d, disconnecting\n",
+ elems->ext_chansw_ie->new_operating_class);
+ ieee80211_queue_work(&local->hw,
+ &ifmgd->csa_connection_drop_work);
+ }
+ new_chan_no = elems->ext_chansw_ie->new_ch_num;
+ count = elems->ext_chansw_ie->count;
+ mode = elems->ext_chansw_ie->mode;
+ } else if (elems->ch_switch_ie) {
+ new_band = cbss->channel->band;
+ new_chan_no = elems->ch_switch_ie->new_ch_num;
+ count = elems->ch_switch_ie->count;
+ mode = elems->ch_switch_ie->mode;
+ } else {
+ /* nothing here we understand */
+ return;
+ }
+
+ bss = (void *)cbss->priv;
+
+ new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);
+ new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
+ if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) {
sdata_info(sdata,
"AP %pM switches to unsupported channel (%d MHz), disconnecting\n",
ifmgd->associated->bssid, new_freq);
- ieee80211_queue_work(&sdata->local->hw,
+ ieee80211_queue_work(&local->hw,
+ &ifmgd->csa_connection_drop_work);
+ return;
+ }
+
+ if (sec_chan_offs) {
+ secondary_channel_offset = sec_chan_offs->sec_chan_offs;
+ } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
+ /* if HT is enabled and the IE not present, it's still HT */
+ secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ }
+
+ switch (secondary_channel_offset) {
+ default:
+ /* secondary_channel_offset was present but is invalid */
+ case IEEE80211_HT_PARAM_CHA_SEC_NONE:
+ cfg80211_chandef_create(&new_chandef, new_chan,
+ NL80211_CHAN_HT20);
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+ cfg80211_chandef_create(&new_chandef, new_chan,
+ NL80211_CHAN_HT40PLUS);
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+ cfg80211_chandef_create(&new_chandef, new_chan,
+ NL80211_CHAN_HT40MINUS);
+ break;
+ case -1:
+ cfg80211_chandef_create(&new_chandef, new_chan,
+ NL80211_CHAN_NO_HT);
+ break;
+ }
+
+ if (wide_bw_chansw_ie) {
+ new_vht_chandef.chan = new_chan;
+ new_vht_chandef.center_freq1 =
+ ieee80211_channel_to_frequency(
+ wide_bw_chansw_ie->new_center_freq_seg0,
+ new_band);
+
+ switch (wide_bw_chansw_ie->new_channel_width) {
+ default:
+ /* hmmm, ignore VHT and use HT if present */
+ case IEEE80211_VHT_CHANWIDTH_USE_HT:
+ new_vht_chandef.chan = NULL;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_80MHZ:
+ new_vht_chandef.width = NL80211_CHAN_WIDTH_80;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_160MHZ:
+ new_vht_chandef.width = NL80211_CHAN_WIDTH_160;
+ break;
+ case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
+ /* field is otherwise reserved */
+ new_vht_chandef.center_freq2 =
+ ieee80211_channel_to_frequency(
+ wide_bw_chansw_ie->new_center_freq_seg1,
+ new_band);
+ new_vht_chandef.width = NL80211_CHAN_WIDTH_80P80;
+ break;
+ }
+ if (ifmgd->flags & IEEE80211_STA_DISABLE_80P80MHZ &&
+ new_vht_chandef.width == NL80211_CHAN_WIDTH_80P80)
+ chandef_downgrade(&new_vht_chandef);
+ if (ifmgd->flags & IEEE80211_STA_DISABLE_160MHZ &&
+ new_vht_chandef.width == NL80211_CHAN_WIDTH_160)
+ chandef_downgrade(&new_vht_chandef);
+ if (ifmgd->flags & IEEE80211_STA_DISABLE_40MHZ &&
+ new_vht_chandef.width > NL80211_CHAN_WIDTH_20)
+ chandef_downgrade(&new_vht_chandef);
+ }
+
+ /* if VHT data is there validate & use it */
+ if (new_vht_chandef.chan) {
+ if (!cfg80211_chandef_compatible(&new_vht_chandef,
+ &new_chandef)) {
+ sdata_info(sdata,
+ "AP %pM CSA has inconsistent channel data, disconnecting\n",
+ ifmgd->associated->bssid);
+ ieee80211_queue_work(&local->hw,
+ &ifmgd->csa_connection_drop_work);
+ return;
+ }
+ new_chandef = new_vht_chandef;
+ }
+
+ if (!cfg80211_chandef_usable(local->hw.wiphy, &new_chandef,
+ IEEE80211_CHAN_DISABLED)) {
+ sdata_info(sdata,
+ "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
+ ifmgd->associated->bssid, new_freq,
+ new_chandef.width, new_chandef.center_freq1,
+ new_chandef.center_freq2);
+ ieee80211_queue_work(&local->hw,
&ifmgd->csa_connection_drop_work);
return;
}
ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
- if (sdata->local->use_chanctx) {
+ if (local->use_chanctx) {
sdata_info(sdata,
"not handling channel switch with channel contexts\n");
- ieee80211_queue_work(&sdata->local->hw,
+ ieee80211_queue_work(&local->hw,
&ifmgd->csa_connection_drop_work);
return;
}
- mutex_lock(&sdata->local->chanctx_mtx);
+ mutex_lock(&local->chanctx_mtx);
if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) {
- mutex_unlock(&sdata->local->chanctx_mtx);
+ mutex_unlock(&local->chanctx_mtx);
return;
}
chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf),
@@ -1098,40 +1207,39 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
if (chanctx->refcount > 1) {
sdata_info(sdata,
"channel switch with multiple interfaces on the same channel, disconnecting\n");
- ieee80211_queue_work(&sdata->local->hw,
+ ieee80211_queue_work(&local->hw,
&ifmgd->csa_connection_drop_work);
- mutex_unlock(&sdata->local->chanctx_mtx);
+ mutex_unlock(&local->chanctx_mtx);
return;
}
- mutex_unlock(&sdata->local->chanctx_mtx);
+ mutex_unlock(&local->chanctx_mtx);
- sdata->local->csa_channel = new_ch;
+ local->csa_chandef = new_chandef;
- if (sw_elem->mode)
- ieee80211_stop_queues_by_reason(&sdata->local->hw,
+ if (mode)
+ ieee80211_stop_queues_by_reason(&local->hw,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
- if (sdata->local->ops->channel_switch) {
+ if (local->ops->channel_switch) {
/* use driver's channel switch callback */
struct ieee80211_channel_switch ch_switch = {
.timestamp = timestamp,
- .block_tx = sw_elem->mode,
- .channel = new_ch,
- .count = sw_elem->count,
+ .block_tx = mode,
+ .chandef = new_chandef,
+ .count = count,
};
- drv_channel_switch(sdata->local, &ch_switch);
+ drv_channel_switch(local, &ch_switch);
return;
}
/* channel switch handled in software */
- if (sw_elem->count <= 1)
- ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
+ if (count <= 1)
+ ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
else
mod_timer(&ifmgd->chswitch_timer,
- TU_TO_EXP_TIME(sw_elem->count *
- cbss->beacon_interval));
+ TU_TO_EXP_TIME(count * cbss->beacon_interval));
}
static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
@@ -1430,13 +1538,11 @@ 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);
-
- if (drv_tx_frames_pending(local))
+ if (drv_tx_frames_pending(local)) {
mod_timer(&local->dynamic_ps_timer, jiffies +
msecs_to_jiffies(
local->hw.conf.dynamic_ps_timeout));
- else {
+ } else {
ieee80211_send_nullfunc(local, sdata, 1);
/* Flush to get the tx status of nullfunc frame */
ieee80211_flush_queues(local, sdata);
@@ -1450,9 +1556,6 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
local->hw.conf.flags |= IEEE80211_CONF_PS;
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
}
-
- if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
- netif_tx_wake_all_queues(sdata->dev);
}
void ieee80211_dynamic_ps_timer(unsigned long data)
@@ -1558,6 +1661,7 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
params.cw_min = ecw2cw(pos[1] & 0x0f);
params.txop = get_unaligned_le16(pos + 2);
+ params.acm = acm;
params.uapsd = uapsd;
mlme_dbg(sdata,
@@ -1645,7 +1749,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value);
sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec(
- IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int));
+ beacon_loss_count * bss_conf->beacon_int));
sdata->u.mgd.associated = cbss;
memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
@@ -1658,18 +1762,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
rcu_read_lock();
ies = rcu_dereference(cbss->ies);
if (ies) {
- u8 noa[2];
int ret;
ret = cfg80211_get_p2p_attr(
ies->data, ies->len,
IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
- noa, sizeof(noa));
+ (u8 *) &bss_conf->p2p_noa_attr,
+ sizeof(bss_conf->p2p_noa_attr));
if (ret >= 2) {
- bss_conf->p2p_oppps = noa[1] & 0x80;
- bss_conf->p2p_ctwindow = noa[1] & 0x7f;
+ sdata->u.mgd.p2p_noa_index =
+ bss_conf->p2p_noa_attr.index;
bss_info_changed |= BSS_CHANGED_P2P_PS;
- sdata->u.mgd.p2p_noa_index = noa[0];
}
}
rcu_read_unlock();
@@ -1713,7 +1816,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_smps(sdata);
ieee80211_recalc_ps_vif(sdata);
- netif_tx_start_all_queues(sdata->dev);
netif_carrier_on(sdata->dev);
}
@@ -1736,22 +1838,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_stop_poll(sdata);
ifmgd->associated = NULL;
-
- /*
- * we need to commit the associated = NULL change because the
- * scan code uses that to determine whether this iface should
- * go to/wake up from powersave or not -- and could otherwise
- * wake the queues erroneously.
- */
- smp_mb();
-
- /*
- * Thus, we can only afterwards stop the queues -- to account
- * for the case where another CPU is finishing a scan at this
- * time -- we don't want the scan code to enable queues.
- */
-
- netif_tx_stop_all_queues(sdata->dev);
netif_carrier_off(sdata->dev);
/*
@@ -1794,8 +1880,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_ASSOC;
sdata->vif.bss_conf.assoc = false;
- sdata->vif.bss_conf.p2p_ctwindow = 0;
- sdata->vif.bss_conf.p2p_oppps = false;
+ ifmgd->p2p_noa_index = -1;
+ memset(&sdata->vif.bss_conf.p2p_noa_attr, 0,
+ sizeof(sdata->vif.bss_conf.p2p_noa_attr));
/* on the next assoc, re-program HT/VHT parameters */
memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
@@ -1975,12 +2062,15 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
goto out;
}
- if (beacon)
+ if (beacon) {
mlme_dbg_ratelimited(sdata,
- "detected beacon loss from AP - probing\n");
+ "detected beacon loss from AP (missed %d beacons) - probing\n",
+ beacon_loss_count);
- ieee80211_cqm_rssi_notify(&sdata->vif,
- NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL);
+ ieee80211_cqm_rssi_notify(&sdata->vif,
+ NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
+ GFP_KERNEL);
+ }
/*
* The driver/our work has already reported this event or the
@@ -2126,7 +2216,6 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
trace_api_beacon_loss(sdata);
- WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR);
sdata->u.mgd.connection_loss = false;
ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
}
@@ -2176,7 +2265,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
u32 tx_flags = 0;
pos = mgmt->u.auth.variable;
- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
if (!elems.challenge)
return;
auth_data->expected_transaction = 4;
@@ -2441,7 +2530,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
}
pos = mgmt->u.assoc_resp.variable;
- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
if (!elems.supp_rates) {
sdata_info(sdata, "no SuppRates element in AssocResp\n");
@@ -2610,13 +2699,13 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
pos = mgmt->u.assoc_resp.variable;
- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), false, &elems);
if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
- elems.timeout_int && elems.timeout_int_len == 5 &&
- elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
+ elems.timeout_int &&
+ elems.timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
u32 tu, ms;
- tu = get_unaligned_le32(elems.timeout_int + 1);
+ tu = le32_to_cpu(elems.timeout_int->value);
ms = tu * 1024 / 1000;
sdata_info(sdata,
"%pM rejected association temporarily; comeback duration %u TU (%u ms)\n",
@@ -2665,6 +2754,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel;
bool need_ps = false;
+ lockdep_assert_held(&sdata->u.mgd.mtx);
+
if ((sdata->u.mgd.associated &&
ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||
(sdata->u.mgd.assoc_data &&
@@ -2679,7 +2770,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
}
}
- if (elems->ds_params && elems->ds_params_len == 1)
+ if (elems->ds_params)
freq = ieee80211_channel_to_frequency(elems->ds_params[0],
rx_status->band);
else
@@ -2695,7 +2786,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
if (bss)
ieee80211_rx_bss_put(local, bss);
- if (!sdata->u.mgd.associated)
+ if (!sdata->u.mgd.associated ||
+ !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid))
return;
if (need_ps) {
@@ -2704,10 +2796,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
mutex_unlock(&local->iflist_mtx);
}
- if (elems->ch_switch_ie &&
- memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, ETH_ALEN) == 0)
- ieee80211_sta_process_chanswitch(sdata, elems->ch_switch_ie,
- bss, rx_status->mactime);
+ ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems);
+
}
@@ -2732,7 +2822,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
return;
ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
- &elems);
+ false, &elems);
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
@@ -2815,7 +2905,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
ieee802_11_parse_elems(mgmt->u.beacon.variable,
- len - baselen, &elems);
+ len - baselen, false, &elems);
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
ifmgd->assoc_data->have_beacon = true;
@@ -2925,7 +3015,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
- len - baselen, &elems,
+ len - baselen, false, &elems,
care_about_ies, ncrc);
if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
@@ -2957,22 +3047,30 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
if (sdata->vif.p2p) {
- u8 noa[2];
+ struct ieee80211_p2p_noa_attr noa = {};
int ret;
ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable,
len - baselen,
IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
- noa, sizeof(noa));
- if (ret >= 2 && sdata->u.mgd.p2p_noa_index != noa[0]) {
- bss_conf->p2p_oppps = noa[1] & 0x80;
- bss_conf->p2p_ctwindow = noa[1] & 0x7f;
+ (u8 *) &noa, sizeof(noa));
+ if (ret >= 2) {
+ if (sdata->u.mgd.p2p_noa_index != noa.index) {
+ /* valid noa_attr and index changed */
+ sdata->u.mgd.p2p_noa_index = noa.index;
+ memcpy(&bss_conf->p2p_noa_attr, &noa, sizeof(noa));
+ changed |= BSS_CHANGED_P2P_PS;
+ /*
+ * make sure we update all information, the CRC
+ * mechanism doesn't look at P2P attributes.
+ */
+ ifmgd->beacon_crc_valid = false;
+ }
+ } else if (sdata->u.mgd.p2p_noa_index != -1) {
+ /* noa_attr not found and we had valid noa_attr before */
+ sdata->u.mgd.p2p_noa_index = -1;
+ memset(&bss_conf->p2p_noa_attr, 0, sizeof(bss_conf->p2p_noa_attr));
changed |= BSS_CHANGED_P2P_PS;
- sdata->u.mgd.p2p_noa_index = noa[0];
- /*
- * make sure we update all information, the CRC
- * mechanism doesn't look at P2P attributes.
- */
ifmgd->beacon_crc_valid = false;
}
}
@@ -3014,7 +3112,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
changed |= BSS_CHANGED_DTIM_PERIOD;
}
- if (elems.erp_info && elems.erp_info_len >= 1) {
+ if (elems.erp_info) {
erp_valid = true;
erp_value = elems.erp_info[0];
} else {
@@ -3064,6 +3162,8 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
enum rx_mgmt_action rma = RX_MGMT_NONE;
u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
u16 fc;
+ struct ieee802_11_elems elems;
+ int ies_len;
rx_status = (struct ieee80211_rx_status *) skb->cb;
mgmt = (struct ieee80211_mgmt *) skb->data;
@@ -3093,14 +3193,48 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss);
break;
case IEEE80211_STYPE_ACTION:
- switch (mgmt->u.action.category) {
- case WLAN_CATEGORY_SPECTRUM_MGMT:
+ if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
+ ies_len = skb->len -
+ offsetof(struct ieee80211_mgmt,
+ u.action.u.chan_switch.variable);
+
+ if (ies_len < 0)
+ break;
+
+ ieee802_11_parse_elems(
+ mgmt->u.action.u.chan_switch.variable,
+ ies_len, true, &elems);
+
+ if (elems.parse_error)
+ break;
+
ieee80211_sta_process_chanswitch(sdata,
- &mgmt->u.action.u.chan_switch.sw_elem,
- (void *)ifmgd->associated->priv,
- rx_status->mactime);
- break;
+ rx_status->mactime,
+ &elems);
+ } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
+ ies_len = skb->len -
+ offsetof(struct ieee80211_mgmt,
+ u.action.u.ext_chan_switch.variable);
+
+ if (ies_len < 0)
+ break;
+
+ ieee802_11_parse_elems(
+ mgmt->u.action.u.ext_chan_switch.variable,
+ ies_len, true, &elems);
+
+ if (elems.parse_error)
+ break;
+
+ /* for the handling code pretend this was also an IE */
+ elems.ext_chansw_ie =
+ &mgmt->u.action.u.ext_chan_switch.data;
+
+ ieee80211_sta_process_chanswitch(sdata,
+ rx_status->mactime,
+ &elems);
}
+ break;
}
mutex_unlock(&ifmgd->mtx);
@@ -3513,8 +3647,9 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
ifmgd->flags = 0;
ifmgd->powersave = sdata->wdev.ps;
- ifmgd->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
- ifmgd->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
+ ifmgd->uapsd_queues = sdata->local->hw.uapsd_queues;
+ ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;
+ ifmgd->p2p_noa_index = -1;
mutex_init(&ifmgd->mtx);
@@ -4079,7 +4214,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock();
if (bss->wmm_used && bss->uapsd_supported &&
- (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
+ (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) &&
+ sdata->wmm_acm != 0xff) {
assoc_data->uapsd = true;
ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
} else {
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index cce795871ab1..acd1f71adc03 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -445,15 +445,15 @@ void ieee80211_roc_setup(struct ieee80211_local *local)
INIT_LIST_HEAD(&local->roc_list);
}
-void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
+void ieee80211_roc_purge(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata)
{
- struct ieee80211_local *local = sdata->local;
struct ieee80211_roc_work *roc, *tmp;
LIST_HEAD(tmp_list);
mutex_lock(&local->mtx);
list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
- if (roc->sdata != sdata)
+ if (sdata && roc->sdata != sdata)
continue;
if (roc->started && local->ops->remain_on_channel) {
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 3d16f4e61743..7fc5d0d8149a 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -19,6 +19,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
ieee80211_dfs_cac_cancel(local);
+ ieee80211_roc_purge(local, NULL);
+
+ ieee80211_del_virtual_monitor(local);
+
if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list) {
@@ -33,8 +37,9 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
- /* flush out all packets */
+ /* flush out all packets and station cleanup call_rcu()s */
synchronize_net();
+ rcu_barrier();
ieee80211_flush_queues(local, NULL);
@@ -101,10 +106,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
drv_remove_interface(local, sdata);
}
- sdata = rtnl_dereference(local->monitor_sdata);
- if (sdata)
- drv_remove_interface(local, sdata);
-
/*
* We disconnected on all interfaces before suspend, all channel
* contexts should be released.
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index dd88381c53b7..0d51877efdb7 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -252,6 +252,25 @@ rate_lowest_non_cck_index(struct ieee80211_supported_band *sband,
return 0;
}
+static void __rate_control_send_low(struct ieee80211_hw *hw,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta,
+ struct ieee80211_tx_info *info)
+{
+ if ((sband->band != IEEE80211_BAND_2GHZ) ||
+ !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE))
+ info->control.rates[0].idx = rate_lowest_index(sband, sta);
+ else
+ info->control.rates[0].idx =
+ rate_lowest_non_cck_index(sband, sta);
+
+ info->control.rates[0].count =
+ (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
+ 1 : hw->max_rate_tries;
+
+ info->control.skip_table = 1;
+}
+
bool rate_control_send_low(struct ieee80211_sta *sta,
void *priv_sta,
@@ -262,16 +281,8 @@ bool rate_control_send_low(struct ieee80211_sta *sta,
int mcast_rate;
if (!sta || !priv_sta || rc_no_data_or_no_ack_use_min(txrc)) {
- if ((sband->band != IEEE80211_BAND_2GHZ) ||
- !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE))
- info->control.rates[0].idx =
- rate_lowest_index(txrc->sband, sta);
- else
- info->control.rates[0].idx =
- rate_lowest_non_cck_index(txrc->sband, sta);
- info->control.rates[0].count =
- (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
- 1 : txrc->hw->max_rate_tries;
+ __rate_control_send_low(txrc->hw, sband, sta, info);
+
if (!sta && txrc->bss) {
mcast_rate = txrc->bss_conf->mcast_rate[sband->band];
if (mcast_rate > 0) {
@@ -355,7 +366,8 @@ static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate,
static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
- struct ieee80211_tx_rate_control *txrc,
+ struct ieee80211_supported_band *sband,
+ enum nl80211_chan_width chan_width,
u32 mask,
u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN])
{
@@ -375,27 +387,17 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
alt_rate.count = rate->count;
if (rate_idx_match_legacy_mask(&alt_rate,
- txrc->sband->n_bitrates,
- mask)) {
+ sband->n_bitrates, mask)) {
*rate = alt_rate;
return;
}
} else {
- struct sk_buff *skb = txrc->skb;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- __le16 fc;
-
/* handle legacy rates */
- if (rate_idx_match_legacy_mask(rate, txrc->sband->n_bitrates,
- mask))
+ if (rate_idx_match_legacy_mask(rate, sband->n_bitrates, mask))
return;
/* if HT BSS, and we handle a data frame, also try HT rates */
- if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
- return;
-
- fc = hdr->frame_control;
- if (!ieee80211_is_data(fc))
+ if (chan_width == NL80211_CHAN_WIDTH_20_NOHT)
return;
alt_rate.idx = 0;
@@ -408,7 +410,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
alt_rate.flags |= IEEE80211_TX_RC_MCS;
- if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_40)
+ if (chan_width == NL80211_CHAN_WIDTH_40)
alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) {
@@ -426,6 +428,228 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
*/
}
+static void rate_fixup_ratelist(struct ieee80211_vif *vif,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_tx_rate *rates,
+ int max_rates)
+{
+ struct ieee80211_rate *rate;
+ bool inval = false;
+ int i;
+
+ /*
+ * Set up the RTS/CTS rate as the fastest basic rate
+ * that is not faster than the data rate unless there
+ * is no basic rate slower than the data rate, in which
+ * case we pick the slowest basic rate
+ *
+ * XXX: Should this check all retry rates?
+ */
+ if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) {
+ u32 basic_rates = vif->bss_conf.basic_rates;
+ s8 baserate = basic_rates ? ffs(basic_rates - 1) : 0;
+
+ rate = &sband->bitrates[rates[0].idx];
+
+ for (i = 0; i < sband->n_bitrates; i++) {
+ /* must be a basic rate */
+ if (!(basic_rates & BIT(i)))
+ continue;
+ /* must not be faster than the data rate */
+ if (sband->bitrates[i].bitrate > rate->bitrate)
+ continue;
+ /* maximum */
+ if (sband->bitrates[baserate].bitrate <
+ sband->bitrates[i].bitrate)
+ baserate = i;
+ }
+
+ info->control.rts_cts_rate_idx = baserate;
+ }
+
+ for (i = 0; i < max_rates; i++) {
+ /*
+ * make sure there's no valid rate following
+ * an invalid one, just in case drivers don't
+ * take the API seriously to stop at -1.
+ */
+ if (inval) {
+ rates[i].idx = -1;
+ continue;
+ }
+ if (rates[i].idx < 0) {
+ inval = true;
+ continue;
+ }
+
+ /*
+ * For now assume MCS is already set up correctly, this
+ * needs to be fixed.
+ */
+ if (rates[i].flags & IEEE80211_TX_RC_MCS) {
+ WARN_ON(rates[i].idx > 76);
+
+ if (!(rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) &&
+ info->control.use_cts_prot)
+ rates[i].flags |=
+ IEEE80211_TX_RC_USE_CTS_PROTECT;
+ continue;
+ }
+
+ if (rates[i].flags & IEEE80211_TX_RC_VHT_MCS) {
+ WARN_ON(ieee80211_rate_get_vht_mcs(&rates[i]) > 9);
+ continue;
+ }
+
+ /* set up RTS protection if desired */
+ if (info->control.use_rts) {
+ rates[i].flags |= IEEE80211_TX_RC_USE_RTS_CTS;
+ info->control.use_cts_prot = false;
+ }
+
+ /* RC is busted */
+ if (WARN_ON_ONCE(rates[i].idx >= sband->n_bitrates)) {
+ rates[i].idx = -1;
+ continue;
+ }
+
+ rate = &sband->bitrates[rates[i].idx];
+
+ /* set up short preamble */
+ if (info->control.short_preamble &&
+ rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
+ rates[i].flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
+
+ /* set up G protection */
+ if (!(rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) &&
+ info->control.use_cts_prot &&
+ rate->flags & IEEE80211_RATE_ERP_G)
+ rates[i].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT;
+ }
+}
+
+
+static void rate_control_fill_sta_table(struct ieee80211_sta *sta,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_tx_rate *rates,
+ int max_rates)
+{
+ struct ieee80211_sta_rates *ratetbl = NULL;
+ int i;
+
+ if (sta && !info->control.skip_table)
+ ratetbl = rcu_dereference(sta->rates);
+
+ /* Fill remaining rate slots with data from the sta rate table. */
+ max_rates = min_t(int, max_rates, IEEE80211_TX_RATE_TABLE_SIZE);
+ for (i = 0; i < max_rates; i++) {
+ if (i < ARRAY_SIZE(info->control.rates) &&
+ info->control.rates[i].idx >= 0 &&
+ info->control.rates[i].count) {
+ if (rates != info->control.rates)
+ rates[i] = info->control.rates[i];
+ } else if (ratetbl) {
+ rates[i].idx = ratetbl->rate[i].idx;
+ rates[i].flags = ratetbl->rate[i].flags;
+ if (info->control.use_rts)
+ rates[i].count = ratetbl->rate[i].count_rts;
+ else if (info->control.use_cts_prot)
+ rates[i].count = ratetbl->rate[i].count_cts;
+ else
+ rates[i].count = ratetbl->rate[i].count;
+ } else {
+ rates[i].idx = -1;
+ rates[i].count = 0;
+ }
+
+ if (rates[i].idx < 0 || !rates[i].count)
+ break;
+ }
+}
+
+static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_tx_rate *rates,
+ int max_rates)
+{
+ enum nl80211_chan_width chan_width;
+ u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
+ bool has_mcs_mask;
+ u32 mask;
+ int i;
+
+ /*
+ * Try to enforce the rateidx mask the user wanted. skip this if the
+ * default mask (allow all rates) is used to save some processing for
+ * the common case.
+ */
+ mask = sdata->rc_rateidx_mask[info->band];
+ has_mcs_mask = sdata->rc_has_mcs_mask[info->band];
+ if (mask == (1 << sband->n_bitrates) - 1 && !has_mcs_mask)
+ return;
+
+ if (has_mcs_mask)
+ memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band],
+ sizeof(mcs_mask));
+ else
+ memset(mcs_mask, 0xff, sizeof(mcs_mask));
+
+ if (sta) {
+ /* Filter out rates that the STA does not support */
+ mask &= sta->supp_rates[info->band];
+ for (i = 0; i < sizeof(mcs_mask); i++)
+ mcs_mask[i] &= sta->ht_cap.mcs.rx_mask[i];
+ }
+
+ /*
+ * Make sure the rate index selected for each TX rate is
+ * included in the configured mask and change the rate indexes
+ * if needed.
+ */
+ chan_width = sdata->vif.bss_conf.chandef.width;
+ for (i = 0; i < max_rates; i++) {
+ /* Skip invalid rates */
+ if (rates[i].idx < 0)
+ break;
+
+ rate_idx_match_mask(&rates[i], sband, mask, chan_width,
+ mcs_mask);
+ }
+}
+
+void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb,
+ struct ieee80211_tx_rate *dest,
+ int max_rates)
+{
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_supported_band *sband;
+
+ rate_control_fill_sta_table(sta, info, dest, max_rates);
+
+ if (!vif)
+ return;
+
+ sdata = vif_to_sdata(vif);
+ sband = sdata->local->hw.wiphy->bands[info->band];
+
+ if (ieee80211_is_data(hdr->frame_control))
+ rate_control_apply_mask(sdata, sta, sband, info, dest, max_rates);
+
+ if (dest[0].idx < 0)
+ __rate_control_send_low(&sdata->local->hw, sband, sta, info);
+
+ if (sta)
+ rate_fixup_ratelist(vif, sband, info, dest, max_rates);
+}
+EXPORT_SYMBOL(ieee80211_get_tx_rates);
+
void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta,
struct ieee80211_tx_rate_control *txrc)
@@ -435,8 +659,6 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *ista = NULL;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
int i;
- u32 mask;
- u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
if (sta && test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) {
ista = &sta->sta;
@@ -454,37 +676,27 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
ref->ops->get_rate(ref->priv, ista, priv_sta, txrc);
- /*
- * Try to enforce the rateidx mask the user wanted. skip this if the
- * default mask (allow all rates) is used to save some processing for
- * the common case.
- */
- mask = sdata->rc_rateidx_mask[info->band];
- memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band],
- sizeof(mcs_mask));
- if (mask != (1 << txrc->sband->n_bitrates) - 1) {
- if (sta) {
- /* Filter out rates that the STA does not support */
- mask &= sta->sta.supp_rates[info->band];
- for (i = 0; i < sizeof(mcs_mask); i++)
- mcs_mask[i] &= sta->sta.ht_cap.mcs.rx_mask[i];
- }
- /*
- * Make sure the rate index selected for each TX rate is
- * included in the configured mask and change the rate indexes
- * if needed.
- */
- for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
- /* Skip invalid rates */
- if (info->control.rates[i].idx < 0)
- break;
- rate_idx_match_mask(&info->control.rates[i], txrc,
- mask, mcs_mask);
- }
- }
+ if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_RC_TABLE)
+ return;
+
+ ieee80211_get_tx_rates(&sdata->vif, ista, txrc->skb,
+ info->control.rates,
+ ARRAY_SIZE(info->control.rates));
+}
- BUG_ON(info->control.rates[0].idx < 0);
+int rate_control_set_rates(struct ieee80211_hw *hw,
+ struct ieee80211_sta *pubsta,
+ struct ieee80211_sta_rates *rates)
+{
+ struct ieee80211_sta_rates *old = rcu_dereference(pubsta->rates);
+
+ rcu_assign_pointer(pubsta->rates, rates);
+ if (old)
+ kfree_rcu(old, rcu_head);
+
+ return 0;
}
+EXPORT_SYMBOL(rate_control_set_rates);
int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
const char *name)
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 1c36c9b4fa4a..ac7ef5414bde 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -84,6 +84,50 @@ minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
}
static void
+minstrel_set_rate(struct minstrel_sta_info *mi, struct ieee80211_sta_rates *ratetbl,
+ int offset, int idx)
+{
+ struct minstrel_rate *r = &mi->r[idx];
+
+ ratetbl->rate[offset].idx = r->rix;
+ ratetbl->rate[offset].count = r->adjusted_retry_count;
+ ratetbl->rate[offset].count_cts = r->retry_count_cts;
+ ratetbl->rate[offset].count_rts = r->retry_count_rtscts;
+}
+
+static void
+minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
+{
+ struct ieee80211_sta_rates *ratetbl;
+ int i = 0;
+
+ ratetbl = kzalloc(sizeof(*ratetbl), GFP_ATOMIC);
+ if (!ratetbl)
+ return;
+
+ /* Start with max_tp_rate */
+ minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[0]);
+
+ if (mp->hw->max_rates >= 3) {
+ /* At least 3 tx rates supported, use max_tp_rate2 next */
+ minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[1]);
+ }
+
+ if (mp->hw->max_rates >= 2) {
+ /* At least 2 tx rates supported, use max_prob_rate next */
+ minstrel_set_rate(mi, ratetbl, i++, mi->max_prob_rate);
+ }
+
+ /* Use lowest rate last */
+ ratetbl->rate[i].idx = mi->lowest_rix;
+ ratetbl->rate[i].count = mp->max_retry;
+ ratetbl->rate[i].count_cts = mp->max_retry;
+ ratetbl->rate[i].count_rts = mp->max_retry;
+
+ rate_control_set_rates(mp->hw, mi->sta, ratetbl);
+}
+
+static void
minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
{
u8 tmp_tp_rate[MAX_THR_RATES];
@@ -161,6 +205,8 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi)
/* Reset update timer */
mi->stats_update = jiffies;
+
+ minstrel_update_rates(mp, mi);
}
static void
@@ -209,9 +255,9 @@ minstrel_get_retry_count(struct minstrel_rate *mr,
{
unsigned int retry = mr->adjusted_retry_count;
- if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+ if (info->control.use_rts)
retry = max(2U, min(mr->retry_count_rtscts, retry));
- else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+ else if (info->control.use_cts_prot)
retry = max(2U, min(mr->retry_count_cts, retry));
return retry;
}
@@ -240,13 +286,12 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct minstrel_sta_info *mi = priv_sta;
struct minstrel_priv *mp = priv;
- struct ieee80211_tx_rate *ar = info->control.rates;
- unsigned int ndx, sample_ndx = 0;
+ struct ieee80211_tx_rate *rate = &info->control.rates[0];
+ struct minstrel_rate *msr, *mr;
+ unsigned int ndx;
bool mrr_capable;
- bool indirect_rate_sampling = false;
- bool rate_sampling = false;
- int i, delta;
- int mrr_ndx[3];
+ bool prev_sample = mi->prev_sample;
+ int delta;
int sampling_ratio;
/* management/no-ack frames do not use rate control */
@@ -262,107 +307,75 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
else
sampling_ratio = mp->lookaround_rate;
- /* init rateindex [ndx] with max throughput rate */
- ndx = mi->max_tp_rate[0];
-
/* increase sum packet counter */
mi->packet_count++;
delta = (mi->packet_count * sampling_ratio / 100) -
(mi->sample_count + mi->sample_deferred / 2);
- /* delta > 0: sampling required */
- if ((delta > 0) && (mrr_capable || !mi->prev_sample)) {
- struct minstrel_rate *msr;
- if (mi->packet_count >= 10000) {
- mi->sample_deferred = 0;
- mi->sample_count = 0;
- mi->packet_count = 0;
- } else if (delta > mi->n_rates * 2) {
- /* With multi-rate retry, not every planned sample
- * attempt actually gets used, due to the way the retry
- * chain is set up - [max_tp,sample,prob,lowest] for
- * sample_rate < max_tp.
- *
- * If there's too much sampling backlog and the link
- * starts getting worse, minstrel would start bursting
- * out lots of sampling frames, which would result
- * in a large throughput loss. */
- mi->sample_count += (delta - mi->n_rates * 2);
- }
+ /* delta < 0: no sampling required */
+ mi->prev_sample = false;
+ if (delta < 0 || (!mrr_capable && prev_sample))
+ return;
- /* get next random rate sample */
- sample_ndx = minstrel_get_next_sample(mi);
- msr = &mi->r[sample_ndx];
- rate_sampling = true;
-
- /* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
- * rate sampling method should be used.
- * Respect such rates that are not sampled for 20 interations.
- */
- if (mrr_capable &&
- msr->perfect_tx_time > mi->r[ndx].perfect_tx_time &&
- msr->sample_skipped < 20)
- indirect_rate_sampling = true;
-
- if (!indirect_rate_sampling) {
- if (msr->sample_limit != 0) {
- ndx = sample_ndx;
- mi->sample_count++;
- if (msr->sample_limit > 0)
- msr->sample_limit--;
- } else
- rate_sampling = false;
- } else {
- /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
- * packets that have the sampling rate deferred to the
- * second MRR stage. Increase the sample counter only
- * if the deferred sample rate was actually used.
- * Use the sample_deferred counter to make sure that
- * the sampling is not done in large bursts */
- info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
- mi->sample_deferred++;
- }
+ if (mi->packet_count >= 10000) {
+ mi->sample_deferred = 0;
+ mi->sample_count = 0;
+ mi->packet_count = 0;
+ } else if (delta > mi->n_rates * 2) {
+ /* With multi-rate retry, not every planned sample
+ * attempt actually gets used, due to the way the retry
+ * chain is set up - [max_tp,sample,prob,lowest] for
+ * sample_rate < max_tp.
+ *
+ * If there's too much sampling backlog and the link
+ * starts getting worse, minstrel would start bursting
+ * out lots of sampling frames, which would result
+ * in a large throughput loss. */
+ mi->sample_count += (delta - mi->n_rates * 2);
+ }
+
+ /* get next random rate sample */
+ ndx = minstrel_get_next_sample(mi);
+ msr = &mi->r[ndx];
+ mr = &mi->r[mi->max_tp_rate[0]];
+
+ /* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage)
+ * rate sampling method should be used.
+ * Respect such rates that are not sampled for 20 interations.
+ */
+ if (mrr_capable &&
+ msr->perfect_tx_time > mr->perfect_tx_time &&
+ msr->sample_skipped < 20) {
+ /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark
+ * packets that have the sampling rate deferred to the
+ * second MRR stage. Increase the sample counter only
+ * if the deferred sample rate was actually used.
+ * Use the sample_deferred counter to make sure that
+ * the sampling is not done in large bursts */
+ info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+ rate++;
+ mi->sample_deferred++;
+ } else {
+ if (!msr->sample_limit != 0)
+ return;
+
+ mi->sample_count++;
+ if (msr->sample_limit > 0)
+ msr->sample_limit--;
}
- mi->prev_sample = rate_sampling;
/* If we're not using MRR and the sampling rate already
* has a probability of >95%, we shouldn't be attempting
* to use it, as this only wastes precious airtime */
- if (!mrr_capable && rate_sampling &&
+ if (!mrr_capable &&
(mi->r[ndx].probability > MINSTREL_FRAC(95, 100)))
- ndx = mi->max_tp_rate[0];
-
- /* mrr setup for 1st stage */
- ar[0].idx = mi->r[ndx].rix;
- ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info);
-
- /* non mrr setup for 2nd stage */
- if (!mrr_capable) {
- if (!rate_sampling)
- ar[0].count = mp->max_retry;
- ar[1].idx = mi->lowest_rix;
- ar[1].count = mp->max_retry;
return;
- }
- /* mrr setup for 2nd stage */
- if (rate_sampling) {
- if (indirect_rate_sampling)
- mrr_ndx[0] = sample_ndx;
- else
- mrr_ndx[0] = mi->max_tp_rate[0];
- } else {
- mrr_ndx[0] = mi->max_tp_rate[1];
- }
+ mi->prev_sample = true;
- /* mrr setup for 3rd & 4th stage */
- mrr_ndx[1] = mi->max_prob_rate;
- mrr_ndx[2] = 0;
- for (i = 1; i < 4; i++) {
- ar[i].idx = mi->r[mrr_ndx[i - 1]].rix;
- ar[i].count = mi->r[mrr_ndx[i - 1]].adjusted_retry_count;
- }
+ rate->idx = mi->r[ndx].rix;
+ rate->count = minstrel_get_retry_count(&mi->r[ndx], info);
}
@@ -412,12 +425,16 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
unsigned int i, n = 0;
unsigned int t_slot = 9; /* FIXME: get real slot time */
+ mi->sta = sta;
mi->lowest_rix = rate_lowest_index(sband, sta);
ctl_rate = &sband->bitrates[mi->lowest_rix];
mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10,
ctl_rate->bitrate,
!!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1);
+ memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate));
+ mi->max_prob_rate = 0;
+
for (i = 0; i < sband->n_bitrates; i++) {
struct minstrel_rate *mr = &mi->r[n];
unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0;
@@ -460,6 +477,8 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
} while ((tx_time < mp->segment_size) &&
(++mr->retry_count < mp->max_retry));
mr->adjusted_retry_count = mr->retry_count;
+ if (!(sband->bitrates[i].flags & IEEE80211_RATE_ERP_G))
+ mr->retry_count_cts = mr->retry_count;
}
for (i = n; i < sband->n_bitrates; i++) {
@@ -471,6 +490,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband,
mi->stats_update = jiffies;
init_sample_table(mi);
+ minstrel_update_rates(mp, mi);
}
static void *
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h
index 85ebf42cb46d..f4301f4b2e41 100644
--- a/net/mac80211/rc80211_minstrel.h
+++ b/net/mac80211/rc80211_minstrel.h
@@ -9,7 +9,8 @@
#ifndef __RC_MINSTREL_H
#define __RC_MINSTREL_H
-#define EWMA_LEVEL 75 /* ewma weighting factor [%] */
+#define EWMA_LEVEL 96 /* ewma weighting factor [/EWMA_DIV] */
+#define EWMA_DIV 128
#define SAMPLE_COLUMNS 10 /* number of columns in sample table */
@@ -27,7 +28,7 @@
static inline int
minstrel_ewma(int old, int new, int weight)
{
- return (new * (100 - weight) + old * weight) / 100;
+ return (new * (EWMA_DIV - weight) + old * weight) / EWMA_DIV;
}
@@ -62,6 +63,8 @@ struct minstrel_rate {
};
struct minstrel_sta_info {
+ struct ieee80211_sta *sta;
+
unsigned long stats_update;
unsigned int sp_ack_dur;
unsigned int rate_avg;
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index d1048348d399..fd0b9ca1570e 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -68,7 +68,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
file->private_data = ms;
p = ms->buf;
- p += sprintf(p, "rate throughput ewma prob this prob "
+ p += sprintf(p, "rate throughput ewma prob this prob "
"this succ/attempt success attempts\n");
for (i = 0; i < mi->n_rates; i++) {
struct minstrel_rate *mr = &mi->r[i];
@@ -86,7 +86,7 @@ minstrel_stats_open(struct inode *inode, struct file *file)
eprob = MINSTREL_TRUNC(mr->probability * 1000);
p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u "
- "%3u(%3u) %8llu %8llu\n",
+ " %3u(%3u) %8llu %8llu\n",
tp / 10, tp % 10,
eprob / 10, eprob % 10,
prob / 10, prob % 10,
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index d2b264d1311d..5b2d3012b983 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -126,6 +126,9 @@ const struct mcs_group minstrel_mcs_groups[] = {
static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
+static void
+minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
+
/*
* Look up an MCS group index based on mac80211 rate information
*/
@@ -244,6 +247,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
struct minstrel_rate_stats *mr;
int cur_prob, cur_prob_tp, cur_tp, cur_tp2;
int group, i, index;
+ bool mi_rates_valid = false;
if (mi->ampdu_packets > 0) {
mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
@@ -254,11 +258,10 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
mi->sample_slow = 0;
mi->sample_count = 0;
- mi->max_tp_rate = 0;
- mi->max_tp_rate2 = 0;
- mi->max_prob_rate = 0;
for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
+ bool mg_rates_valid = false;
+
cur_prob = 0;
cur_prob_tp = 0;
cur_tp = 0;
@@ -268,15 +271,24 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
if (!mg->supported)
continue;
- mg->max_tp_rate = 0;
- mg->max_tp_rate2 = 0;
- mg->max_prob_rate = 0;
mi->sample_count++;
for (i = 0; i < MCS_GROUP_RATES; i++) {
if (!(mg->supported & BIT(i)))
continue;
+ /* initialize rates selections starting indexes */
+ if (!mg_rates_valid) {
+ mg->max_tp_rate = mg->max_tp_rate2 =
+ mg->max_prob_rate = i;
+ if (!mi_rates_valid) {
+ mi->max_tp_rate = mi->max_tp_rate2 =
+ mi->max_prob_rate = i;
+ mi_rates_valid = true;
+ }
+ mg_rates_valid = true;
+ }
+
mr = &mg->rates[i];
mr->retry_updated = false;
index = MCS_GROUP_RATES * group + i;
@@ -456,7 +468,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_tx_rate *ar = info->status.rates;
struct minstrel_rate_stats *rate, *rate2;
struct minstrel_priv *mp = priv;
- bool last;
+ bool last, update = false;
int i;
if (!msp->is_ht)
@@ -505,21 +517,29 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
rate = minstrel_get_ratestats(mi, mi->max_tp_rate);
if (rate->attempts > 30 &&
MINSTREL_FRAC(rate->success, rate->attempts) <
- MINSTREL_FRAC(20, 100))
+ MINSTREL_FRAC(20, 100)) {
minstrel_downgrade_rate(mi, &mi->max_tp_rate, true);
+ update = true;
+ }
rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2);
if (rate2->attempts > 30 &&
MINSTREL_FRAC(rate2->success, rate2->attempts) <
- MINSTREL_FRAC(20, 100))
+ MINSTREL_FRAC(20, 100)) {
minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false);
+ update = true;
+ }
if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
+ update = true;
minstrel_ht_update_stats(mp, mi);
if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
minstrel_aggr_check(sta, skb);
}
+
+ if (update)
+ minstrel_ht_update_rates(mp, mi);
}
static void
@@ -583,36 +603,71 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
static void
minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
- struct ieee80211_tx_rate *rate, int index,
- bool sample, bool rtscts)
+ struct ieee80211_sta_rates *ratetbl, int offset, int index)
{
const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
struct minstrel_rate_stats *mr;
+ u8 idx;
+ u16 flags;
mr = minstrel_get_ratestats(mi, index);
if (!mr->retry_updated)
minstrel_calc_retransmit(mp, mi, index);
- if (sample)
- rate->count = 1;
- else if (mr->probability < MINSTREL_FRAC(20, 100))
- rate->count = 2;
- else if (rtscts)
- rate->count = mr->retry_count_rtscts;
- else
- rate->count = mr->retry_count;
-
- rate->flags = 0;
- if (rtscts)
- rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
+ if (mr->probability < MINSTREL_FRAC(20, 100) || !mr->retry_count) {
+ ratetbl->rate[offset].count = 2;
+ ratetbl->rate[offset].count_rts = 2;
+ ratetbl->rate[offset].count_cts = 2;
+ } else {
+ ratetbl->rate[offset].count = mr->retry_count;
+ ratetbl->rate[offset].count_cts = mr->retry_count;
+ ratetbl->rate[offset].count_rts = mr->retry_count_rtscts;
+ }
if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
- rate->idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
+ idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
+ flags = 0;
+ } else {
+ idx = index % MCS_GROUP_RATES +
+ (group->streams - 1) * MCS_GROUP_RATES;
+ flags = IEEE80211_TX_RC_MCS | group->flags;
+ }
+
+ if (offset > 0) {
+ ratetbl->rate[offset].count = ratetbl->rate[offset].count_rts;
+ flags |= IEEE80211_TX_RC_USE_RTS_CTS;
+ }
+
+ ratetbl->rate[offset].idx = idx;
+ ratetbl->rate[offset].flags = flags;
+}
+
+static void
+minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
+{
+ struct ieee80211_sta_rates *rates;
+ int i = 0;
+
+ rates = kzalloc(sizeof(*rates), GFP_ATOMIC);
+ if (!rates)
return;
+
+ /* Start with max_tp_rate */
+ minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate);
+
+ if (mp->hw->max_rates >= 3) {
+ /* At least 3 tx rates supported, use max_tp_rate2 next */
+ minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_tp_rate2);
+ }
+
+ if (mp->hw->max_rates >= 2) {
+ /*
+ * At least 2 tx rates supported, use max_prob_rate next */
+ minstrel_ht_set_rate(mp, mi, rates, i++, mi->max_prob_rate);
}
- rate->flags |= IEEE80211_TX_RC_MCS | group->flags;
- rate->idx = index % MCS_GROUP_RATES + (group->streams - 1) * MCS_GROUP_RATES;
+ rates->rate[i].idx = -1;
+ rate_control_set_rates(mp->hw, mi->sta, rates);
}
static inline int
@@ -702,13 +757,13 @@ static void
minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_rate_control *txrc)
{
+ const struct mcs_group *sample_group;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
- struct ieee80211_tx_rate *ar = info->status.rates;
+ struct ieee80211_tx_rate *rate = &info->status.rates[0];
struct minstrel_ht_sta_priv *msp = priv_sta;
struct minstrel_ht_sta *mi = &msp->ht;
struct minstrel_priv *mp = priv;
int sample_idx;
- bool sample = false;
if (rate_control_send_low(sta, priv_sta, txrc))
return;
@@ -736,51 +791,6 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
}
#endif
- if (sample_idx >= 0) {
- sample = true;
- minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
- true, false);
- info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
- } else {
- minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
- false, false);
- }
-
- if (mp->hw->max_rates >= 3) {
- /*
- * At least 3 tx rates supported, use
- * sample_rate -> max_tp_rate -> max_prob_rate for sampling and
- * max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
- */
- if (sample_idx >= 0)
- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
- false, false);
- else
- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
- false, true);
-
- minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
- false, !sample);
-
- ar[3].count = 0;
- ar[3].idx = -1;
- } else if (mp->hw->max_rates == 2) {
- /*
- * Only 2 tx rates supported, use
- * sample_rate -> max_prob_rate for sampling and
- * max_tp_rate -> max_prob_rate by default.
- */
- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
- false, !sample);
-
- ar[2].count = 0;
- ar[2].idx = -1;
- } else {
- /* Not using MRR, only use the first rate */
- ar[1].count = 0;
- ar[1].idx = -1;
- }
-
mi->total_packets++;
/* wraparound */
@@ -788,6 +798,16 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
mi->total_packets = 0;
mi->sample_packets = 0;
}
+
+ if (sample_idx < 0)
+ return;
+
+ sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
+ info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+ rate->idx = sample_idx % MCS_GROUP_RATES +
+ (sample_group->streams - 1) * MCS_GROUP_RATES;
+ rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
+ rate->count = 1;
}
static void
@@ -837,6 +857,8 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
msp->is_ht = true;
memset(mi, 0, sizeof(*mi));
+
+ mi->sta = sta;
mi->stats_update = jiffies;
ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1);
@@ -898,6 +920,10 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
if (!n_supported)
goto use_legacy;
+ /* create an initial rate table with the lowest supported rates */
+ minstrel_ht_update_stats(mp, mi);
+ minstrel_ht_update_rates(mp, mi);
+
return;
use_legacy:
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index 9b16e9de9923..d655586773ac 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -65,6 +65,8 @@ struct minstrel_mcs_group_data {
};
struct minstrel_ht_sta {
+ struct ieee80211_sta *sta;
+
/* ampdu length (average, per sampling interval) */
unsigned int ampdu_len;
unsigned int ampdu_packets;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 2528b5a4d6d4..c8447af76ead 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2085,6 +2085,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
}
fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
+ fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
info = IEEE80211_SKB_CB(fwd_skb);
memset(info, 0, sizeof(*info));
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
@@ -2423,6 +2424,22 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
}
break;
+ case WLAN_CATEGORY_PUBLIC:
+ if (len < IEEE80211_MIN_ACTION_SIZE + 1)
+ goto invalid;
+ if (sdata->vif.type != NL80211_IFTYPE_STATION)
+ break;
+ if (!rx->sta)
+ break;
+ if (!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid))
+ break;
+ if (mgmt->u.action.u.ext_chan_switch.action_code !=
+ WLAN_PUB_ACTION_EXT_CHANSW_ANN)
+ break;
+ if (len < offsetof(struct ieee80211_mgmt,
+ u.action.u.ext_chan_switch.variable))
+ goto invalid;
+ goto queue;
case WLAN_CATEGORY_VHT:
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
@@ -2506,10 +2523,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
ieee80211_process_measurement_req(sdata, mgmt, len);
goto handled;
case WLAN_ACTION_SPCT_CHL_SWITCH:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.chan_switch)))
- break;
-
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
@@ -3042,7 +3055,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
!ieee80211_is_probe_resp(hdr->frame_control) &&
!ieee80211_is_beacon(hdr->frame_control))
return 0;
- if (!ether_addr_equal(sdata->vif.addr, hdr->addr1))
+ if (!ether_addr_equal(sdata->vif.addr, hdr->addr1) &&
+ !multicast)
status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
break;
default:
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index cb34cbbaa20c..99b103921a4b 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -98,9 +98,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
}
/* save the ERP value so that it is available at association time */
- if (elems->erp_info && elems->erp_info_len >= 1 &&
- (!elems->parse_error ||
- !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
+ if (elems->erp_info && (!elems->parse_error ||
+ !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
bss->erp_value = elems->erp_info[0];
bss->has_erp_value = true;
if (!elems->parse_error)
@@ -182,7 +181,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
if (baselen > skb->len)
return;
- ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
+ ieee802_11_parse_elems(elements, skb->len - baselen, false, &elems);
channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
@@ -384,7 +383,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
{
int i;
struct ieee80211_sub_if_data *sdata;
- enum ieee80211_band band = local->hw.conf.channel->band;
+ enum ieee80211_band band = local->hw.conf.chandef.chan->band;
u32 tx_flags;
tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
@@ -401,7 +400,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
local->scan_req->ssids[i].ssid_len,
local->scan_req->ie, local->scan_req->ie_len,
local->scan_req->rates[band], false,
- tx_flags, local->hw.conf.channel, true);
+ tx_flags, local->hw.conf.chandef.chan, true);
/*
* After sending probe requests, wait for probe responses
@@ -467,7 +466,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
if (local->ops->hw_scan) {
__set_bit(SCAN_HW_SCANNING, &local->scanning);
} else if ((req->n_channels == 1) &&
- (req->channels[0] == local->_oper_channel)) {
+ (req->channels[0] == local->_oper_chandef.chan)) {
/*
* If we are scanning only on the operating channel
* then we do not need to stop normal activities
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index c5899797a8d4..c215fafd7a2f 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -28,27 +28,27 @@
#define VIF_PR_FMT " vif:%s(%d%s)"
#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
-#define CHANDEF_ENTRY __field(u32, control_freq) \
- __field(u32, chan_width) \
- __field(u32, center_freq1) \
+#define CHANDEF_ENTRY __field(u32, control_freq) \
+ __field(u32, chan_width) \
+ __field(u32, center_freq1) \
__field(u32, center_freq2)
-#define CHANDEF_ASSIGN(c) \
- __entry->control_freq = (c)->chan->center_freq; \
- __entry->chan_width = (c)->width; \
- __entry->center_freq1 = (c)->center_freq1; \
+#define CHANDEF_ASSIGN(c) \
+ __entry->control_freq = (c)->chan ? (c)->chan->center_freq : 0; \
+ __entry->chan_width = (c)->width; \
+ __entry->center_freq1 = (c)->center_freq1; \
__entry->center_freq2 = (c)->center_freq2;
#define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz"
-#define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \
+#define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \
__entry->center_freq1, __entry->center_freq2
-#define CHANCTX_ENTRY CHANDEF_ENTRY \
- __field(u8, rx_chains_static) \
+#define CHANCTX_ENTRY CHANDEF_ENTRY \
+ __field(u8, rx_chains_static) \
__field(u8, rx_chains_dynamic)
-#define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \
- __entry->rx_chains_static = ctx->conf.rx_chains_static; \
+#define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def) \
+ __entry->rx_chains_static = ctx->conf.rx_chains_static; \
__entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
#define CHANCTX_PR_FMT CHANDEF_PR_FMT " chains:%d/%d"
-#define CHANCTX_PR_ARG CHANDEF_PR_ARG, \
+#define CHANCTX_PR_ARG CHANDEF_PR_ARG, \
__entry->rx_chains_static, __entry->rx_chains_dynamic
@@ -286,8 +286,7 @@ TRACE_EVENT(drv_config,
__field(u16, listen_interval)
__field(u8, long_frame_max_tx_count)
__field(u8, short_frame_max_tx_count)
- __field(int, center_freq)
- __field(int, channel_type)
+ CHANDEF_ENTRY
__field(int, smps)
),
@@ -303,15 +302,13 @@ TRACE_EVENT(drv_config,
local->hw.conf.long_frame_max_tx_count;
__entry->short_frame_max_tx_count =
local->hw.conf.short_frame_max_tx_count;
- __entry->center_freq = local->hw.conf.channel ?
- local->hw.conf.channel->center_freq : 0;
- __entry->channel_type = local->hw.conf.channel_type;
+ CHANDEF_ASSIGN(&local->hw.conf.chandef)
__entry->smps = local->hw.conf.smps_mode;
),
TP_printk(
- LOCAL_PR_FMT " ch:%#x freq:%d",
- LOCAL_PR_ARG, __entry->changed, __entry->center_freq
+ LOCAL_PR_FMT " ch:%#x" CHANDEF_PR_FMT,
+ LOCAL_PR_ARG, __entry->changed, CHANDEF_PR_ARG
)
);
@@ -359,8 +356,7 @@ TRACE_EVENT(drv_bss_info_changed,
__dynamic_array(u8, ssid, info->ssid_len);
__field(bool, hidden_ssid);
__field(int, txpower)
- __field(u8, p2p_ctwindow)
- __field(bool, p2p_oppps)
+ __field(u8, p2p_oppps_ctwindow)
),
TP_fast_assign(
@@ -400,8 +396,7 @@ TRACE_EVENT(drv_bss_info_changed,
memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len);
__entry->hidden_ssid = info->hidden_ssid;
__entry->txpower = info->txpower;
- __entry->p2p_ctwindow = info->p2p_ctwindow;
- __entry->p2p_oppps = info->p2p_oppps;
+ __entry->p2p_oppps_ctwindow = info->p2p_noa_attr.oppps_ctwindow;
),
TP_printk(
@@ -995,23 +990,23 @@ TRACE_EVENT(drv_channel_switch,
TP_STRUCT__entry(
LOCAL_ENTRY
+ CHANDEF_ENTRY
__field(u64, timestamp)
__field(bool, block_tx)
- __field(u16, freq)
__field(u8, count)
),
TP_fast_assign(
LOCAL_ASSIGN;
+ CHANDEF_ASSIGN(&ch_switch->chandef)
__entry->timestamp = ch_switch->timestamp;
__entry->block_tx = ch_switch->block_tx;
- __entry->freq = ch_switch->channel->center_freq;
__entry->count = ch_switch->count;
),
TP_printk(
- LOCAL_PR_FMT " new freq:%u count:%d",
- LOCAL_PR_ARG, __entry->freq, __entry->count
+ LOCAL_PR_FMT " new " CHANDEF_PR_FMT " count:%d",
+ LOCAL_PR_ARG, CHANDEF_PR_ARG, __entry->count
)
);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 9e67cc97b87b..9972e07a2f96 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -48,15 +48,15 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
/* assume HW handles this */
- if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
+ if (tx->rate.flags & IEEE80211_TX_RC_MCS)
return 0;
/* uh huh? */
- if (WARN_ON_ONCE(info->control.rates[0].idx < 0))
+ if (WARN_ON_ONCE(tx->rate.idx < 0))
return 0;
sband = local->hw.wiphy->bands[info->band];
- txrate = &sband->bitrates[info->control.rates[0].idx];
+ txrate = &sband->bitrates[tx->rate.idx];
erp = txrate->flags & IEEE80211_RATE_ERP_G;
@@ -617,11 +617,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
struct ieee80211_hdr *hdr = (void *)tx->skb->data;
struct ieee80211_supported_band *sband;
- struct ieee80211_rate *rate;
- int i;
u32 len;
- bool inval = false, rts = false, short_preamble = false;
struct ieee80211_tx_rate_control txrc;
+ struct ieee80211_sta_rates *ratetbl = NULL;
bool assoc = false;
memset(&txrc, 0, sizeof(txrc));
@@ -642,18 +640,23 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
txrc.max_rate_idx = -1;
else
txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
- memcpy(txrc.rate_idx_mcs_mask,
- tx->sdata->rc_rateidx_mcs_mask[info->band],
- sizeof(txrc.rate_idx_mcs_mask));
+
+ if (tx->sdata->rc_has_mcs_mask[info->band])
+ txrc.rate_idx_mcs_mask =
+ tx->sdata->rc_rateidx_mcs_mask[info->band];
+
txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
/* set up RTS protection if desired */
if (len > tx->local->hw.wiphy->rts_threshold) {
- txrc.rts = rts = true;
+ txrc.rts = true;
}
+ info->control.use_rts = txrc.rts;
+ info->control.use_cts_prot = tx->sdata->vif.bss_conf.use_cts_prot;
+
/*
* Use short preamble if the BSS can handle it, but not for
* management frames unless we know the receiver can handle
@@ -663,7 +666,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
if (tx->sdata->vif.bss_conf.use_short_preamble &&
(ieee80211_is_data(hdr->frame_control) ||
(tx->sta && test_sta_flag(tx->sta, WLAN_STA_SHORT_PREAMBLE))))
- txrc.short_preamble = short_preamble = true;
+ txrc.short_preamble = true;
+
+ info->control.short_preamble = txrc.short_preamble;
if (tx->sta)
assoc = test_sta_flag(tx->sta, WLAN_STA_ASSOC);
@@ -687,16 +692,38 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
*/
rate_control_get_rate(tx->sdata, tx->sta, &txrc);
- if (unlikely(info->control.rates[0].idx < 0))
- return TX_DROP;
+ if (tx->sta && !info->control.skip_table)
+ ratetbl = rcu_dereference(tx->sta->sta.rates);
+
+ if (unlikely(info->control.rates[0].idx < 0)) {
+ if (ratetbl) {
+ struct ieee80211_tx_rate rate = {
+ .idx = ratetbl->rate[0].idx,
+ .flags = ratetbl->rate[0].flags,
+ .count = ratetbl->rate[0].count
+ };
+
+ if (ratetbl->rate[0].idx < 0)
+ return TX_DROP;
+
+ tx->rate = rate;
+ } else {
+ return TX_DROP;
+ }
+ } else {
+ tx->rate = info->control.rates[0];
+ }
if (txrc.reported_rate.idx < 0) {
- txrc.reported_rate = info->control.rates[0];
+ txrc.reported_rate = tx->rate;
if (tx->sta && ieee80211_is_data(hdr->frame_control))
tx->sta->last_tx_rate = txrc.reported_rate;
} else if (tx->sta)
tx->sta->last_tx_rate = txrc.reported_rate;
+ if (ratetbl)
+ return TX_CONTINUE;
+
if (unlikely(!info->control.rates[0].count))
info->control.rates[0].count = 1;
@@ -704,91 +731,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
(info->flags & IEEE80211_TX_CTL_NO_ACK)))
info->control.rates[0].count = 1;
- if (is_multicast_ether_addr(hdr->addr1)) {
- /*
- * XXX: verify the rate is in the basic rateset
- */
- return TX_CONTINUE;
- }
-
- /*
- * set up the RTS/CTS rate as the fastest basic rate
- * that is not faster than the data rate
- *
- * XXX: Should this check all retry rates?
- */
- if (!(info->control.rates[0].flags & IEEE80211_TX_RC_MCS)) {
- s8 baserate = 0;
-
- rate = &sband->bitrates[info->control.rates[0].idx];
-
- for (i = 0; i < sband->n_bitrates; i++) {
- /* must be a basic rate */
- if (!(tx->sdata->vif.bss_conf.basic_rates & BIT(i)))
- continue;
- /* must not be faster than the data rate */
- if (sband->bitrates[i].bitrate > rate->bitrate)
- continue;
- /* maximum */
- if (sband->bitrates[baserate].bitrate <
- sband->bitrates[i].bitrate)
- baserate = i;
- }
-
- info->control.rts_cts_rate_idx = baserate;
- }
-
- for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
- /*
- * make sure there's no valid rate following
- * an invalid one, just in case drivers don't
- * take the API seriously to stop at -1.
- */
- if (inval) {
- info->control.rates[i].idx = -1;
- continue;
- }
- if (info->control.rates[i].idx < 0) {
- inval = true;
- continue;
- }
-
- /*
- * For now assume MCS is already set up correctly, this
- * needs to be fixed.
- */
- if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) {
- WARN_ON(info->control.rates[i].idx > 76);
- continue;
- }
-
- /* set up RTS protection if desired */
- if (rts)
- info->control.rates[i].flags |=
- IEEE80211_TX_RC_USE_RTS_CTS;
-
- /* RC is busted */
- if (WARN_ON_ONCE(info->control.rates[i].idx >=
- sband->n_bitrates)) {
- info->control.rates[i].idx = -1;
- continue;
- }
-
- rate = &sband->bitrates[info->control.rates[i].idx];
-
- /* set up short preamble */
- if (short_preamble &&
- rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
- info->control.rates[i].flags |=
- IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
-
- /* set up G protection */
- if (!rts && tx->sdata->vif.bss_conf.use_cts_prot &&
- rate->flags & IEEE80211_RATE_ERP_G)
- info->control.rates[i].flags |=
- IEEE80211_TX_RC_USE_CTS_PROTECT;
- }
-
return TX_CONTINUE;
}
@@ -1709,7 +1651,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
if (chanctx_conf)
chan = chanctx_conf->def.chan;
else if (!local->use_chanctx)
- chan = local->_oper_channel;
+ chan = local->_oper_chandef.chan;
else
goto fail_rcu;
@@ -1843,7 +1785,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
* This is the exception! WDS style interfaces are prohibited
* when channel contexts are in used so this must be valid
*/
- band = local->hw.conf.channel->band;
+ band = local->hw.conf.chandef.chan->band;
break;
#ifdef CONFIG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
@@ -2442,14 +2384,17 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_hdr *hdr;
- struct sk_buff *presp = rcu_dereference(ifibss->presp);
+ struct beacon_data *presp = rcu_dereference(ifibss->presp);
if (!presp)
goto out;
- skb = skb_copy(presp, GFP_ATOMIC);
+ skb = dev_alloc_skb(local->tx_headroom + presp->head_len);
if (!skb)
goto out;
+ skb_reserve(skb, local->tx_headroom);
+ memcpy(skb_put(skb, presp->head_len), presp->head,
+ presp->head_len);
hdr = (struct ieee80211_hdr *) skb->data;
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
@@ -2499,8 +2444,6 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
txrc.max_rate_idx = -1;
else
txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
- memcpy(txrc.rate_idx_mcs_mask, sdata->rc_rateidx_mcs_mask[band],
- sizeof(txrc.rate_idx_mcs_mask));
txrc.bss = true;
rate_control_get_rate(sdata, NULL, &txrc);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index a7368870c8ee..3f87fa468b1f 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -485,7 +485,8 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
return true;
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
- ret = !!local->queue_stop_reasons[queue];
+ ret = test_bit(IEEE80211_QUEUE_STOP_REASON_DRIVER,
+ &local->queue_stop_reasons[queue]);
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
return ret;
}
@@ -660,7 +661,7 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ieee80211_queue_delayed_work);
-u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
+u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems,
u64 filter, u32 crc)
{
@@ -668,6 +669,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
u8 *pos = start;
bool calc_crc = filter != 0;
DECLARE_BITMAP(seen_elems, 256);
+ const u8 *ie;
bitmap_zero(seen_elems, 256);
memset(elems, 0, sizeof(*elems));
@@ -715,6 +717,12 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
case WLAN_EID_COUNTRY:
case WLAN_EID_PWR_CONSTRAINT:
case WLAN_EID_TIMEOUT_INTERVAL:
+ case WLAN_EID_SECONDARY_CHANNEL_OFFSET:
+ case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
+ /*
+ * not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
+ * that if the content gets bigger it might be needed more than once
+ */
if (test_bit(id, seen_elems)) {
elems->parse_error = true;
left -= elen;
@@ -738,17 +746,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
elems->supp_rates = pos;
elems->supp_rates_len = elen;
break;
- case WLAN_EID_FH_PARAMS:
- elems->fh_params = pos;
- elems->fh_params_len = elen;
- break;
case WLAN_EID_DS_PARAMS:
- elems->ds_params = pos;
- elems->ds_params_len = elen;
- break;
- case WLAN_EID_CF_PARAMS:
- elems->cf_params = pos;
- elems->cf_params_len = elen;
+ if (elen >= 1)
+ elems->ds_params = pos;
+ else
+ elem_parse_failed = true;
break;
case WLAN_EID_TIM:
if (elen >= sizeof(struct ieee80211_tim_ie)) {
@@ -757,10 +759,6 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
} else
elem_parse_failed = true;
break;
- case WLAN_EID_IBSS_PARAMS:
- elems->ibss_params = pos;
- elems->ibss_params_len = elen;
- break;
case WLAN_EID_CHALLENGE:
elems->challenge = pos;
elems->challenge_len = elen;
@@ -790,8 +788,10 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
elems->rsn_len = elen;
break;
case WLAN_EID_ERP_INFO:
- elems->erp_info = pos;
- elems->erp_info_len = elen;
+ if (elen >= 1)
+ elems->erp_info = pos;
+ else
+ elem_parse_failed = true;
break;
case WLAN_EID_EXT_SUPP_RATES:
elems->ext_supp_rates = pos;
@@ -870,12 +870,47 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
}
elems->ch_switch_ie = (void *)pos;
break;
- case WLAN_EID_QUIET:
- if (!elems->quiet_elem) {
- elems->quiet_elem = pos;
- elems->quiet_elem_len = elen;
+ case WLAN_EID_EXT_CHANSWITCH_ANN:
+ if (elen != sizeof(struct ieee80211_ext_chansw_ie)) {
+ elem_parse_failed = true;
+ break;
+ }
+ elems->ext_chansw_ie = (void *)pos;
+ break;
+ case WLAN_EID_SECONDARY_CHANNEL_OFFSET:
+ if (elen != sizeof(struct ieee80211_sec_chan_offs_ie)) {
+ elem_parse_failed = true;
+ break;
+ }
+ elems->sec_chan_offs = (void *)pos;
+ break;
+ case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
+ if (!action ||
+ elen != sizeof(*elems->wide_bw_chansw_ie)) {
+ elem_parse_failed = true;
+ break;
+ }
+ elems->wide_bw_chansw_ie = (void *)pos;
+ break;
+ case WLAN_EID_CHANNEL_SWITCH_WRAPPER:
+ if (action) {
+ elem_parse_failed = true;
+ break;
+ }
+ /*
+ * This is a bit tricky, but as we only care about
+ * the wide bandwidth channel switch element, so
+ * just parse it out manually.
+ */
+ ie = cfg80211_find_ie(WLAN_EID_WIDE_BW_CHANNEL_SWITCH,
+ pos, elen);
+ if (ie) {
+ if (ie[1] == sizeof(*elems->wide_bw_chansw_ie))
+ elems->wide_bw_chansw_ie =
+ (void *)(ie + 2);
+ else
+ elem_parse_failed = true;
}
- elems->num_of_quiet_elem++;
break;
case WLAN_EID_COUNTRY:
elems->country_elem = pos;
@@ -889,8 +924,10 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
elems->pwr_constr_elem = pos;
break;
case WLAN_EID_TIMEOUT_INTERVAL:
- elems->timeout_int = pos;
- elems->timeout_int_len = elen;
+ if (elen >= sizeof(struct ieee80211_timeout_interval_ie))
+ elems->timeout_int = (void *)pos;
+ else
+ elem_parse_failed = true;
break;
default:
break;
@@ -911,12 +948,6 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
return crc;
}
-void ieee802_11_parse_elems(u8 *start, size_t len,
- struct ieee802_11_elems *elems)
-{
- ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
-}
-
void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
bool bss_notify)
{
@@ -1474,6 +1505,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
/* add interfaces */
sdata = rtnl_dereference(local->monitor_sdata);
if (sdata) {
+ /* in HW restart it exists already */
+ WARN_ON(local->resuming);
res = drv_add_interface(local, sdata);
if (WARN_ON(res)) {
rcu_assign_pointer(local->monitor_sdata, NULL);
@@ -1663,6 +1696,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
local->in_reconfig = false;
barrier();
+ if (local->monitors == local->open_count && local->monitors > 0)
+ ieee80211_add_virtual_monitor(local);
+
/*
* Clear the WLAN_STA_BLOCK_BA flag so new aggregation
* sessions can be established after a resume.
@@ -2056,7 +2092,7 @@ int ieee80211_ave_rssi(struct ieee80211_vif *vif)
/* non-managed type inferfaces */
return 0;
}
- return ifmgd->ave_beacon_signal;
+ return ifmgd->ave_beacon_signal / 16;
}
EXPORT_SYMBOL_GPL(ieee80211_ave_rssi);
@@ -2171,8 +2207,7 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work)
/* currently not handled */
WARN_ON(1);
else {
- cfg80211_chandef_create(&chandef, local->hw.conf.channel,
- local->hw.conf.channel_type);
+ chandef = local->hw.conf.chandef;
cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
}
}
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 6ceee8e181ca..40d2527693da 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/rfkill.h>
#include <linux/nfc.h>
#include <net/genetlink.h>
@@ -58,6 +59,11 @@ int nfc_dev_up(struct nfc_dev *dev)
device_lock(&dev->dev);
+ if (dev->rfkill && rfkill_blocked(dev->rfkill)) {
+ rc = -ERFKILL;
+ goto error;
+ }
+
if (!device_is_registered(&dev->dev)) {
rc = -ENODEV;
goto error;
@@ -117,6 +123,24 @@ error:
return rc;
}
+static int nfc_rfkill_set_block(void *data, bool blocked)
+{
+ struct nfc_dev *dev = data;
+
+ pr_debug("%s blocked %d", dev_name(&dev->dev), blocked);
+
+ if (!blocked)
+ return 0;
+
+ nfc_dev_down(dev);
+
+ return 0;
+}
+
+static const struct rfkill_ops nfc_rfkill_ops = {
+ .set_block = nfc_rfkill_set_block,
+};
+
/**
* nfc_start_poll - start polling for nfc targets
*
@@ -143,6 +167,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols)
goto error;
}
+ if (!dev->dev_up) {
+ rc = -ENODEV;
+ goto error;
+ }
+
if (dev->polling) {
rc = -EBUSY;
goto error;
@@ -835,6 +864,15 @@ int nfc_register_device(struct nfc_dev *dev)
pr_debug("The userspace won't be notified that the device %s was added\n",
dev_name(&dev->dev));
+ dev->rfkill = rfkill_alloc(dev_name(&dev->dev), &dev->dev,
+ RFKILL_TYPE_NFC, &nfc_rfkill_ops, dev);
+ if (dev->rfkill) {
+ if (rfkill_register(dev->rfkill) < 0) {
+ rfkill_destroy(dev->rfkill);
+ dev->rfkill = NULL;
+ }
+ }
+
return 0;
}
EXPORT_SYMBOL(nfc_register_device);
@@ -852,6 +890,11 @@ void nfc_unregister_device(struct nfc_dev *dev)
id = dev->idx;
+ if (dev->rfkill) {
+ rfkill_unregister(dev->rfkill);
+ rfkill_destroy(dev->rfkill);
+ }
+
if (dev->ops->check_presence) {
device_lock(&dev->dev);
dev->shutting_down = true;
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index b75a9b3f9e89..094f7e27e910 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -420,7 +420,8 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
}
/* If the socket parameters are not set, use the local ones */
- miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux;
+ miux = be16_to_cpu(sock->miux) > LLCP_MAX_MIUX ?
+ local->miux : sock->miux;
rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw;
miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
@@ -475,7 +476,8 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
return -ENODEV;
/* If the socket parameters are not set, use the local ones */
- miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux;
+ miux = be16_to_cpu(sock->miux) > LLCP_MAX_MIUX ?
+ local->miux : sock->miux;
rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw;
miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
@@ -656,6 +658,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
struct nfc_llcp_local *local;
size_t frag_len = 0, remaining_len;
u8 *msg_data, *msg_ptr;
+ u16 remote_miu;
pr_debug("Send I frame len %zd\n", len);
@@ -692,9 +695,11 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
remaining_len = len;
msg_ptr = msg_data;
- while (remaining_len > 0) {
+ do {
+ remote_miu = sock->remote_miu > LLCP_MAX_MIU ?
+ local->remote_miu : sock->remote_miu;
- frag_len = min_t(size_t, sock->remote_miu, remaining_len);
+ frag_len = min_t(size_t, remote_miu, remaining_len);
pr_debug("Fragment %zd bytes remaining %zd",
frag_len, remaining_len);
@@ -706,7 +711,8 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
skb_put(pdu, LLCP_SEQUENCE_SIZE);
- memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
+ if (likely(frag_len > 0))
+ memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
skb_queue_tail(&sock->tx_queue, pdu);
@@ -718,7 +724,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
remaining_len -= frag_len;
msg_ptr += frag_len;
- }
+ } while (remaining_len > 0);
kfree(msg_data);
@@ -732,6 +738,7 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
struct nfc_llcp_local *local;
size_t frag_len = 0, remaining_len;
u8 *msg_ptr, *msg_data;
+ u16 remote_miu;
int err;
pr_debug("Send UI frame len %zd\n", len);
@@ -752,9 +759,11 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
remaining_len = len;
msg_ptr = msg_data;
- while (remaining_len > 0) {
+ do {
+ remote_miu = sock->remote_miu > LLCP_MAX_MIU ?
+ local->remote_miu : sock->remote_miu;
- frag_len = min_t(size_t, sock->remote_miu, remaining_len);
+ frag_len = min_t(size_t, remote_miu, remaining_len);
pr_debug("Fragment %zd bytes remaining %zd",
frag_len, remaining_len);
@@ -768,14 +777,15 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI);
- memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
+ if (likely(frag_len > 0))
+ memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
/* No need to check for the peer RW for UI frames */
skb_queue_tail(&local->tx_queue, pdu);
remaining_len -= frag_len;
msg_ptr += frag_len;
- }
+ } while (remaining_len > 0);
kfree(msg_data);
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 7de0368aff0c..9e483c8e52f8 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -31,6 +31,8 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
static struct list_head llcp_devices;
+static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb);
+
void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk)
{
write_lock(&l->lock);
@@ -45,6 +47,12 @@ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk)
write_unlock(&l->lock);
}
+void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock)
+{
+ sock->remote_rw = LLCP_DEFAULT_RW;
+ sock->remote_miu = LLCP_MAX_MIU + 1;
+}
+
static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
{
struct nfc_llcp_local *local = sock->local;
@@ -68,7 +76,7 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
}
}
-static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
+static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device,
int err)
{
struct sock *sk;
@@ -108,21 +116,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
bh_unlock_sock(accept_sk);
}
-
- if (listen == true) {
- bh_unlock_sock(sk);
- continue;
- }
- }
-
- /*
- * If we have a connection less socket bound, we keep it alive
- * if the device is still present.
- */
- if (sk->sk_state == LLCP_BOUND && sk->sk_type == SOCK_DGRAM &&
- listen == true) {
- bh_unlock_sock(sk);
- continue;
}
if (err)
@@ -137,11 +130,8 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
write_unlock(&local->sockets.lock);
- /*
- * If we want to keep the listening sockets alive,
- * we don't touch the RAW ones.
- */
- if (listen == true)
+ /* If we still have a device, we keep the RAW sockets alive */
+ if (device == true)
return;
write_lock(&local->raw_sockets.lock);
@@ -173,9 +163,9 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
return local;
}
-static void local_cleanup(struct nfc_llcp_local *local, bool listen)
+static void local_cleanup(struct nfc_llcp_local *local)
{
- nfc_llcp_socket_release(local, listen, ENXIO);
+ nfc_llcp_socket_release(local, false, ENXIO);
del_timer_sync(&local->link_timer);
skb_queue_purge(&local->tx_queue);
cancel_work_sync(&local->tx_work);
@@ -194,7 +184,7 @@ static void local_release(struct kref *ref)
local = container_of(ref, struct nfc_llcp_local, ref);
list_del(&local->list);
- local_cleanup(local, false);
+ local_cleanup(local);
kfree(local);
}
@@ -1116,6 +1106,12 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
dsap = nfc_llcp_dsap(skb);
ssap = nfc_llcp_ssap(skb);
+ if ((dsap == 0) && (ssap == 0)) {
+ pr_debug("Connection termination");
+ nfc_dep_link_down(local->dev);
+ return;
+ }
+
llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
if (llcp_sock == NULL) {
nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN);
@@ -1349,19 +1345,54 @@ exit:
nfc_llcp_send_snl_sdres(local, &llc_sdres_list, sdres_tlvs_len);
}
-static void nfc_llcp_rx_work(struct work_struct *work)
+static void nfc_llcp_recv_agf(struct nfc_llcp_local *local, struct sk_buff *skb)
{
- struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
- rx_work);
- u8 dsap, ssap, ptype;
- struct sk_buff *skb;
+ u8 ptype;
+ u16 pdu_len;
+ struct sk_buff *new_skb;
- skb = local->rx_pending;
- if (skb == NULL) {
- pr_debug("No pending SKB\n");
+ if (skb->len <= LLCP_HEADER_SIZE) {
+ pr_err("Malformed AGF PDU\n");
return;
}
+ skb_pull(skb, LLCP_HEADER_SIZE);
+
+ while (skb->len > LLCP_AGF_PDU_HEADER_SIZE) {
+ pdu_len = skb->data[0] << 8 | skb->data[1];
+
+ skb_pull(skb, LLCP_AGF_PDU_HEADER_SIZE);
+
+ if (pdu_len < LLCP_HEADER_SIZE || pdu_len > skb->len) {
+ pr_err("Malformed AGF PDU\n");
+ return;
+ }
+
+ ptype = nfc_llcp_ptype(skb);
+
+ if (ptype == LLCP_PDU_SYMM || ptype == LLCP_PDU_AGF)
+ goto next;
+
+ new_skb = nfc_alloc_recv_skb(pdu_len, GFP_KERNEL);
+ if (new_skb == NULL) {
+ pr_err("Could not allocate PDU\n");
+ return;
+ }
+
+ memcpy(skb_put(new_skb, pdu_len), skb->data, pdu_len);
+
+ nfc_llcp_rx_skb(local, new_skb);
+
+ kfree_skb(new_skb);
+next:
+ skb_pull(skb, pdu_len);
+ }
+}
+
+static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb)
+{
+ u8 dsap, ssap, ptype;
+
ptype = nfc_llcp_ptype(skb);
dsap = nfc_llcp_dsap(skb);
ssap = nfc_llcp_ssap(skb);
@@ -1372,10 +1403,6 @@ static void nfc_llcp_rx_work(struct work_struct *work)
print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET,
16, 1, skb->data, skb->len, true);
- __net_timestamp(skb);
-
- nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX);
-
switch (ptype) {
case LLCP_PDU_SYMM:
pr_debug("SYMM\n");
@@ -1418,7 +1445,30 @@ static void nfc_llcp_rx_work(struct work_struct *work)
nfc_llcp_recv_hdlc(local, skb);
break;
+ case LLCP_PDU_AGF:
+ pr_debug("AGF frame\n");
+ nfc_llcp_recv_agf(local, skb);
+ break;
}
+}
+
+static void nfc_llcp_rx_work(struct work_struct *work)
+{
+ struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
+ rx_work);
+ struct sk_buff *skb;
+
+ skb = local->rx_pending;
+ if (skb == NULL) {
+ pr_debug("No pending SKB\n");
+ return;
+ }
+
+ __net_timestamp(skb);
+
+ nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX);
+
+ nfc_llcp_rx_skb(local, skb);
schedule_work(&local->tx_work);
kfree_skb(local->rx_pending);
@@ -1466,6 +1516,9 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
if (local == NULL)
return;
+ local->remote_miu = LLCP_DEFAULT_MIU;
+ local->remote_lto = LLCP_DEFAULT_LTO;
+
/* Close and purge all existing sockets */
nfc_llcp_socket_release(local, true, 0);
}
@@ -1553,7 +1606,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
return;
}
- local_cleanup(local, false);
+ local_cleanup(local);
nfc_llcp_local_put(local);
}
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 7e87a66b02ec..ff8c434f7df8 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -31,6 +31,7 @@ enum llcp_state {
#define LLCP_MAX_LTO 0xff
#define LLCP_MAX_RW 15
#define LLCP_MAX_MIUX 0x7ff
+#define LLCP_MAX_MIU (LLCP_MAX_MIUX + 128)
#define LLCP_WKS_NUM_SAP 16
#define LLCP_SDP_NUM_SAP 16
@@ -124,7 +125,7 @@ struct nfc_llcp_sock {
char *service_name;
size_t service_name_len;
u8 rw;
- u16 miux;
+ __be16 miux;
/* Remote link parameters */
@@ -162,6 +163,7 @@ struct nfc_llcp_ui_cb {
#define LLCP_HEADER_SIZE 2
#define LLCP_SEQUENCE_SIZE 1
+#define LLCP_AGF_PDU_HEADER_SIZE 2
/* LLCP versions: 1.1 is 1.0 plus SDP */
#define LLCP_VERSION_10 0x10
@@ -210,6 +212,7 @@ struct nfc_llcp_ui_cb {
void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s);
void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s);
+void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock);
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
int nfc_llcp_local_put(struct nfc_llcp_local *local);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index c1101e6de170..d6faa47c9bba 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -279,7 +279,7 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
break;
}
- llcp_sock->miux = (u16) opt;
+ llcp_sock->miux = cpu_to_be16((u16) opt);
break;
@@ -299,9 +299,12 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
+ struct nfc_llcp_local *local;
struct sock *sk = sock->sk;
struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
int len, err = 0;
+ u16 miux, remote_miu;
+ u8 rw;
pr_debug("%p optname %d\n", sk, optname);
@@ -311,19 +314,48 @@ static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
if (get_user(len, optlen))
return -EFAULT;
+ local = llcp_sock->local;
+ if (!local)
+ return -ENODEV;
+
len = min_t(u32, len, sizeof(u32));
lock_sock(sk);
switch (optname) {
case NFC_LLCP_RW:
- if (put_user(llcp_sock->rw, (u32 __user *) optval))
+ rw = llcp_sock->rw > LLCP_MAX_RW ? local->rw : llcp_sock->rw;
+ if (put_user(rw, (u32 __user *) optval))
err = -EFAULT;
break;
case NFC_LLCP_MIUX:
- if (put_user(llcp_sock->miux, (u32 __user *) optval))
+ miux = be16_to_cpu(llcp_sock->miux) > LLCP_MAX_MIUX ?
+ be16_to_cpu(local->miux) : be16_to_cpu(llcp_sock->miux);
+
+ if (put_user(miux, (u32 __user *) optval))
+ err = -EFAULT;
+
+ break;
+
+ case NFC_LLCP_REMOTE_MIU:
+ remote_miu = llcp_sock->remote_miu > LLCP_MAX_MIU ?
+ local->remote_miu : llcp_sock->remote_miu;
+
+ if (put_user(remote_miu, (u32 __user *) optval))
+ err = -EFAULT;
+
+ break;
+
+ case NFC_LLCP_REMOTE_LTO:
+ if (put_user(local->remote_lto / 10, (u32 __user *) optval))
+ err = -EFAULT;
+
+ break;
+
+ case NFC_LLCP_REMOTE_RW:
+ if (put_user(llcp_sock->remote_rw, (u32 __user *) optval))
err = -EFAULT;
break;
@@ -925,13 +957,12 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
llcp_sock->ssap = 0;
llcp_sock->dsap = LLCP_SAP_SDP;
llcp_sock->rw = LLCP_MAX_RW + 1;
- llcp_sock->miux = LLCP_MAX_MIUX + 1;
- llcp_sock->remote_rw = LLCP_DEFAULT_RW;
- llcp_sock->remote_miu = LLCP_DEFAULT_MIU;
+ llcp_sock->miux = cpu_to_be16(LLCP_MAX_MIUX + 1);
llcp_sock->send_n = llcp_sock->send_ack_n = 0;
llcp_sock->recv_n = llcp_sock->recv_ack_n = 0;
llcp_sock->remote_ready = 1;
llcp_sock->reserved_ssap = LLCP_SAP_MAX;
+ nfc_llcp_socket_remote_param_init(llcp_sock);
skb_queue_head_init(&llcp_sock->tx_queue);
skb_queue_head_init(&llcp_sock->tx_pending_queue);
INIT_LIST_HEAD(&llcp_sock->accept_queue);
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 9b9be5279f5d..1cec5e4f3a5e 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -587,7 +587,7 @@ static ssize_t rfkill_name_show(struct device *dev,
static const char *rfkill_get_type_str(enum rfkill_type type)
{
- BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_FM + 1);
+ BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_NFC + 1);
switch (type) {
case RFKILL_TYPE_WLAN:
@@ -604,6 +604,8 @@ static const char *rfkill_get_type_str(enum rfkill_type type)
return "gps";
case RFKILL_TYPE_FM:
return "fm";
+ case RFKILL_TYPE_NFC:
+ return "nfc";
default:
BUG();
}
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index 78fc0937948d..fb076cd6f808 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -131,6 +131,7 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
rfkill->pwr_clk = clk_get(&pdev->dev, pdata->power_clk_name);
if (IS_ERR(rfkill->pwr_clk)) {
pr_warn("%s: can't find pwr_clk.\n", __func__);
+ ret = PTR_ERR(rfkill->pwr_clk);
goto fail_shutdown_name;
}
}
@@ -152,9 +153,11 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
}
rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type,
- &rfkill_gpio_ops, rfkill);
- if (!rfkill->rfkill_dev)
+ &rfkill_gpio_ops, rfkill);
+ if (!rfkill->rfkill_dev) {
+ ret = -ENOMEM;
goto fail_shutdown;
+ }
ret = rfkill_register(rfkill->rfkill_dev);
if (ret < 0)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 124e5e773fbc..fd35dae547c4 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -88,6 +88,9 @@ struct cfg80211_registered_device {
struct delayed_work dfs_update_channels_wk;
+ /* netlink port which started critical protocol (0 means not started) */
+ u32 crit_proto_nlportid;
+
/* must be last because of the way we do wiphy_priv(),
* and it should at least be aligned to NETDEV_ALIGN */
struct wiphy wiphy __aligned(NETDEV_ALIGN);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 390198bf4b36..0c7b7dd855f6 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -648,6 +648,11 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
spin_unlock_bh(&wdev->mgmt_registrations_lock);
+ if (nlportid && rdev->crit_proto_nlportid == nlportid) {
+ rdev->crit_proto_nlportid = 0;
+ rdev_crit_proto_stop(rdev, wdev);
+ }
+
if (nlportid == wdev->ap_unexpected_nlportid)
wdev->ap_unexpected_nlportid = 0;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 671b69a3c136..afa283841e8c 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -447,62 +447,69 @@ nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
};
-/* ifidx get helper */
-static int nl80211_get_ifidx(struct netlink_callback *cb)
+static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct cfg80211_registered_device **rdev,
+ struct wireless_dev **wdev)
{
- int res;
-
- res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
- nl80211_fam.attrbuf, nl80211_fam.maxattr,
- nl80211_policy);
- if (res)
- return res;
-
- if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
- return -EINVAL;
+ int err;
- res = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
- if (!res)
- return -EINVAL;
- return res;
-}
+ rtnl_lock();
+ mutex_lock(&cfg80211_mutex);
-static int nl80211_prepare_netdev_dump(struct sk_buff *skb,
- struct netlink_callback *cb,
- struct cfg80211_registered_device **rdev,
- struct net_device **dev)
-{
- int ifidx = cb->args[0];
- int err;
+ if (!cb->args[0]) {
+ err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
+ nl80211_fam.attrbuf, nl80211_fam.maxattr,
+ nl80211_policy);
+ if (err)
+ goto out_unlock;
- if (!ifidx)
- ifidx = nl80211_get_ifidx(cb);
- if (ifidx < 0)
- return ifidx;
+ *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
+ nl80211_fam.attrbuf);
+ if (IS_ERR(*wdev)) {
+ err = PTR_ERR(*wdev);
+ goto out_unlock;
+ }
+ *rdev = wiphy_to_dev((*wdev)->wiphy);
+ cb->args[0] = (*rdev)->wiphy_idx;
+ cb->args[1] = (*wdev)->identifier;
+ } else {
+ struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]);
+ struct wireless_dev *tmp;
- cb->args[0] = ifidx;
+ if (!wiphy) {
+ err = -ENODEV;
+ goto out_unlock;
+ }
+ *rdev = wiphy_to_dev(wiphy);
+ *wdev = NULL;
- rtnl_lock();
+ mutex_lock(&(*rdev)->devlist_mtx);
+ list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
+ if (tmp->identifier == cb->args[1]) {
+ *wdev = tmp;
+ break;
+ }
+ }
+ mutex_unlock(&(*rdev)->devlist_mtx);
- *dev = __dev_get_by_index(sock_net(skb->sk), ifidx);
- if (!*dev) {
- err = -ENODEV;
- goto out_rtnl;
+ if (!*wdev) {
+ err = -ENODEV;
+ goto out_unlock;
+ }
}
- *rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
- if (IS_ERR(*rdev)) {
- err = PTR_ERR(*rdev);
- goto out_rtnl;
- }
+ cfg80211_lock_rdev(*rdev);
+ mutex_unlock(&cfg80211_mutex);
return 0;
- out_rtnl:
+ out_unlock:
+ mutex_unlock(&cfg80211_mutex);
rtnl_unlock();
return err;
}
-static void nl80211_finish_netdev_dump(struct cfg80211_registered_device *rdev)
+static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
{
cfg80211_unlock_rdev(rdev);
rtnl_unlock();
@@ -1417,6 +1424,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
}
CMD(start_p2p_device, START_P2P_DEVICE);
CMD(set_mcast_rate, SET_MCAST_RATE);
+ if (split) {
+ CMD(crit_proto_start, CRIT_PROTOCOL_START);
+ CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
+ }
#ifdef CONFIG_NL80211_TESTMODE
CMD(testmode_cmd, TESTMODE);
@@ -3525,15 +3536,20 @@ static int nl80211_dump_station(struct sk_buff *skb,
{
struct station_info sinfo;
struct cfg80211_registered_device *dev;
- struct net_device *netdev;
+ struct wireless_dev *wdev;
u8 mac_addr[ETH_ALEN];
- int sta_idx = cb->args[1];
+ int sta_idx = cb->args[2];
int err;
- err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
+ err = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
if (err)
return err;
+ if (!wdev->netdev) {
+ err = -EINVAL;
+ goto out_err;
+ }
+
if (!dev->ops->dump_station) {
err = -EOPNOTSUPP;
goto out_err;
@@ -3541,7 +3557,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
while (1) {
memset(&sinfo, 0, sizeof(sinfo));
- err = rdev_dump_station(dev, netdev, sta_idx,
+ err = rdev_dump_station(dev, wdev->netdev, sta_idx,
mac_addr, &sinfo);
if (err == -ENOENT)
break;
@@ -3551,7 +3567,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
if (nl80211_send_station(skb,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- dev, netdev, mac_addr,
+ dev, wdev->netdev, mac_addr,
&sinfo) < 0)
goto out;
@@ -3560,10 +3576,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
out:
- cb->args[1] = sta_idx;
+ cb->args[2] = sta_idx;
err = skb->len;
out_err:
- nl80211_finish_netdev_dump(dev);
+ nl80211_finish_wdev_dump(dev);
return err;
}
@@ -4167,13 +4183,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
{
struct mpath_info pinfo;
struct cfg80211_registered_device *dev;
- struct net_device *netdev;
+ struct wireless_dev *wdev;
u8 dst[ETH_ALEN];
u8 next_hop[ETH_ALEN];
- int path_idx = cb->args[1];
+ int path_idx = cb->args[2];
int err;
- err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
+ err = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
if (err)
return err;
@@ -4182,14 +4198,14 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
goto out_err;
}
- if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
+ if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
err = -EOPNOTSUPP;
goto out_err;
}
while (1) {
- err = rdev_dump_mpath(dev, netdev, path_idx, dst, next_hop,
- &pinfo);
+ err = rdev_dump_mpath(dev, wdev->netdev, path_idx, dst,
+ next_hop, &pinfo);
if (err == -ENOENT)
break;
if (err)
@@ -4197,7 +4213,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- netdev, dst, next_hop,
+ wdev->netdev, dst, next_hop,
&pinfo) < 0)
goto out;
@@ -4206,10 +4222,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
out:
- cb->args[1] = path_idx;
+ cb->args[2] = path_idx;
err = skb->len;
out_err:
- nl80211_finish_netdev_dump(dev);
+ nl80211_finish_wdev_dump(dev);
return err;
}
@@ -5565,9 +5581,13 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
genl_dump_check_consistent(cb, hdr, &nl80211_fam);
- if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation) ||
+ if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
+ goto nla_put_failure;
+ if (wdev->netdev &&
nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
goto nla_put_failure;
+ if (nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+ goto nla_put_failure;
bss = nla_nest_start(msg, NL80211_ATTR_BSS);
if (!bss)
@@ -5647,22 +5667,18 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
return -EMSGSIZE;
}
-static int nl80211_dump_scan(struct sk_buff *skb,
- struct netlink_callback *cb)
+static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
{
struct cfg80211_registered_device *rdev;
- struct net_device *dev;
struct cfg80211_internal_bss *scan;
struct wireless_dev *wdev;
- int start = cb->args[1], idx = 0;
+ int start = cb->args[2], idx = 0;
int err;
- err = nl80211_prepare_netdev_dump(skb, cb, &rdev, &dev);
+ err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
if (err)
return err;
- wdev = dev->ieee80211_ptr;
-
wdev_lock(wdev);
spin_lock_bh(&rdev->bss_lock);
cfg80211_bss_expire(rdev);
@@ -5683,8 +5699,8 @@ static int nl80211_dump_scan(struct sk_buff *skb,
spin_unlock_bh(&rdev->bss_lock);
wdev_unlock(wdev);
- cb->args[1] = idx;
- nl80211_finish_netdev_dump(rdev);
+ cb->args[2] = idx;
+ nl80211_finish_wdev_dump(rdev);
return skb->len;
}
@@ -5753,14 +5769,19 @@ static int nl80211_dump_survey(struct sk_buff *skb,
{
struct survey_info survey;
struct cfg80211_registered_device *dev;
- struct net_device *netdev;
- int survey_idx = cb->args[1];
+ struct wireless_dev *wdev;
+ int survey_idx = cb->args[2];
int res;
- res = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev);
+ res = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
if (res)
return res;
+ if (!wdev->netdev) {
+ res = -EINVAL;
+ goto out_err;
+ }
+
if (!dev->ops->dump_survey) {
res = -EOPNOTSUPP;
goto out_err;
@@ -5769,7 +5790,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
while (1) {
struct ieee80211_channel *chan;
- res = rdev_dump_survey(dev, netdev, survey_idx, &survey);
+ res = rdev_dump_survey(dev, wdev->netdev, survey_idx, &survey);
if (res == -ENOENT)
break;
if (res)
@@ -5791,17 +5812,16 @@ static int nl80211_dump_survey(struct sk_buff *skb,
if (nl80211_send_survey(skb,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- netdev,
- &survey) < 0)
+ wdev->netdev, &survey) < 0)
goto out;
survey_idx++;
}
out:
- cb->args[1] = survey_idx;
+ cb->args[2] = survey_idx;
res = skb->len;
out_err:
- nl80211_finish_netdev_dump(dev);
+ nl80211_finish_wdev_dump(dev);
return res;
}
@@ -8143,9 +8163,11 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->stop_p2p_device)
return -EOPNOTSUPP;
+ mutex_lock(&rdev->devlist_mtx);
mutex_lock(&rdev->sched_scan_mtx);
cfg80211_stop_p2p_device(rdev, wdev);
mutex_unlock(&rdev->sched_scan_mtx);
+ mutex_unlock(&rdev->devlist_mtx);
return 0;
}
@@ -8198,6 +8220,64 @@ static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
return rdev_update_ft_ies(rdev, dev, &ft_params);
}
+static int nl80211_crit_protocol_start(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+ enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
+ u16 duration;
+ int ret;
+
+ if (!rdev->ops->crit_proto_start)
+ return -EOPNOTSUPP;
+
+ if (WARN_ON(!rdev->ops->crit_proto_stop))
+ return -EINVAL;
+
+ if (rdev->crit_proto_nlportid)
+ return -EBUSY;
+
+ /* determine protocol if provided */
+ if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
+ proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
+
+ if (proto >= NUM_NL80211_CRIT_PROTO)
+ return -EINVAL;
+
+ /* timeout must be provided */
+ if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
+ return -EINVAL;
+
+ duration =
+ nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
+
+ if (duration > NL80211_CRIT_PROTO_MAX_DURATION)
+ return -ERANGE;
+
+ ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
+ if (!ret)
+ rdev->crit_proto_nlportid = info->snd_portid;
+
+ return ret;
+}
+
+static int nl80211_crit_protocol_stop(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+
+ if (!rdev->ops->crit_proto_stop)
+ return -EOPNOTSUPP;
+
+ if (rdev->crit_proto_nlportid) {
+ rdev->crit_proto_nlportid = 0;
+ rdev_crit_proto_stop(rdev, wdev);
+ }
+ return 0;
+}
+
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -8887,6 +8967,22 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
+ .doit = nl80211_crit_protocol_start,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
+ .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
+ .doit = nl80211_crit_protocol_stop,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ }
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -10632,6 +10728,45 @@ void cfg80211_ft_event(struct net_device *netdev,
}
EXPORT_SYMBOL(cfg80211_ft_event);
+void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
+{
+ struct cfg80211_registered_device *rdev;
+ struct sk_buff *msg;
+ void *hdr;
+ u32 nlportid;
+
+ rdev = wiphy_to_dev(wdev->wiphy);
+ if (!rdev->crit_proto_nlportid)
+ return;
+
+ nlportid = rdev->crit_proto_nlportid;
+ rdev->crit_proto_nlportid = 0;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
+ if (!hdr)
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+ goto nla_put_failure;
+
+ genlmsg_end(msg, hdr);
+
+ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
+ return;
+
+ nla_put_failure:
+ if (hdr)
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+
+}
+EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
+
/* initialisation/exit functions */
int nl80211_init(void)
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index d77e1c1d3a0e..9f15f0ac824d 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -875,7 +875,7 @@ static inline void rdev_stop_p2p_device(struct cfg80211_registered_device *rdev,
trace_rdev_stop_p2p_device(&rdev->wiphy, wdev);
rdev->ops->stop_p2p_device(&rdev->wiphy, wdev);
trace_rdev_return_void(&rdev->wiphy);
-}
+}
static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
struct net_device *dev,
@@ -901,4 +901,26 @@ static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev,
return ret;
}
+static inline int rdev_crit_proto_start(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ enum nl80211_crit_proto_id protocol,
+ u16 duration)
+{
+ int ret;
+
+ trace_rdev_crit_proto_start(&rdev->wiphy, wdev, protocol, duration);
+ ret = rdev->ops->crit_proto_start(&rdev->wiphy, wdev,
+ protocol, duration);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void rdev_crit_proto_stop(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ trace_rdev_crit_proto_stop(&rdev->wiphy, wdev);
+ rdev->ops->crit_proto_stop(&rdev->wiphy, wdev);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e6df52dc8c69..cc35fbaa4578 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -855,7 +855,7 @@ static void handle_channel(struct wiphy *wiphy,
return;
REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq);
- chan->flags = IEEE80211_CHAN_DISABLED;
+ chan->flags |= IEEE80211_CHAN_DISABLED;
return;
}
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 3c2033b8f596..ecd4fcec3c94 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1806,6 +1806,41 @@ TRACE_EVENT(rdev_update_ft_ies,
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->md)
);
+TRACE_EVENT(rdev_crit_proto_start,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_crit_proto_id protocol, u16 duration),
+ TP_ARGS(wiphy, wdev, protocol, duration),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(u16, proto)
+ __field(u16, duration)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->proto = protocol;
+ __entry->duration = duration;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", proto=%x, duration=%u",
+ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->proto, __entry->duration)
+);
+
+TRACE_EVENT(rdev_crit_proto_stop,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,
+ WIPHY_PR_ARG, WDEV_PR_ARG)
+);
+
/*************************************************************
* cfg80211 exported functions traces *
*************************************************************/
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 6cbac99ae03d..f5ad4d94ba88 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1155,6 +1155,26 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
}
EXPORT_SYMBOL(cfg80211_get_p2p_attr);
+bool ieee80211_operating_class_to_band(u8 operating_class,
+ enum ieee80211_band *band)
+{
+ switch (operating_class) {
+ case 112:
+ case 115 ... 127:
+ *band = IEEE80211_BAND_5GHZ;
+ return true;
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ *band = IEEE80211_BAND_2GHZ;
+ return true;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL(ieee80211_operating_class_to_band);
+
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
u32 beacon_int)
{
@@ -1258,12 +1278,12 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
if (wdev_iter == wdev)
continue;
- if (wdev_iter->netdev) {
- if (!netif_running(wdev_iter->netdev))
- continue;
- } else if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) {
+ if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) {
if (!wdev_iter->p2p_started)
continue;
+ } else if (wdev_iter->netdev) {
+ if (!netif_running(wdev_iter->netdev))
+ continue;
} else {
WARN_ON(1);
}
OpenPOWER on IntegriCloud