From 5e13fd354a39d637df9b25edcb2964edf4a7c534 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 13 Dec 2011 17:19:57 +0530 Subject: ath6kl: Use cfg80211_roamed_bss() to report roaming event This is to avoid the scenario where the bss entry of the AP got expired when reporting roaming event to current AP. As the bss entry for the current bss is available in driver, pass this bss to cfg80211. This fixes WARNING: at net/wireless/sme.c:586. This patch depends on the following patch in cfg80211 "cfg80211: Fix race in bss timeout". Reported-by: Kalle Valo Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 37 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 6c59a217b1a..85c24dd0156 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -605,11 +605,13 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, return 0; } -static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, - enum network_type nw_type, - const u8 *bssid, - struct ieee80211_channel *chan, - const u8 *beacon_ie, size_t beacon_ie_len) +static struct cfg80211_bss * +ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, + enum network_type nw_type, + const u8 *bssid, + struct ieee80211_channel *chan, + const u8 *beacon_ie, + size_t beacon_ie_len) { struct ath6kl *ar = vif->ar; struct cfg80211_bss *bss; @@ -638,7 +640,7 @@ static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, */ ie = kmalloc(2 + vif->ssid_len + beacon_ie_len, GFP_KERNEL); if (ie == NULL) - return -ENOMEM; + return NULL; ie[0] = WLAN_EID_SSID; ie[1] = vif->ssid_len; memcpy(ie + 2, vif->ssid, vif->ssid_len); @@ -652,15 +654,9 @@ static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, "cfg80211\n", bssid); kfree(ie); } else - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss " - "entry\n"); - - if (bss == NULL) - return -ENOMEM; + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n"); - cfg80211_put_bss(bss); - - return 0; + return bss; } void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, @@ -672,6 +668,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, { struct ieee80211_channel *chan; struct ath6kl *ar = vif->ar; + struct cfg80211_bss *bss; /* capinfo + listen interval */ u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16); @@ -712,8 +709,9 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, chan = ieee80211_get_channel(ar->wiphy, (int) channel); - if (ath6kl_add_bss_if_needed(vif, nw_type, bssid, chan, assoc_info, - beacon_ie_len) < 0) { + bss = ath6kl_add_bss_if_needed(vif, nw_type, bssid, chan, + assoc_info, beacon_ie_len); + if (!bss) { ath6kl_err("could not add cfg80211 bss entry\n"); return; } @@ -722,6 +720,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", nw_type & ADHOC_CREATOR ? "creator" : "joiner"); cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); + cfg80211_put_bss(bss); return; } @@ -732,11 +731,11 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, assoc_req_ie, assoc_req_len, assoc_resp_ie, assoc_resp_len, WLAN_STATUS_SUCCESS, GFP_KERNEL); + cfg80211_put_bss(bss); } else if (vif->sme_state == SME_CONNECTED) { /* inform roam event to cfg80211 */ - cfg80211_roamed(vif->ndev, chan, bssid, - assoc_req_ie, assoc_req_len, - assoc_resp_ie, assoc_resp_len, GFP_KERNEL); + cfg80211_roamed_bss(vif->ndev, bss, assoc_req_ie, assoc_req_len, + assoc_resp_ie, assoc_resp_len, GFP_KERNEL); } } -- cgit v1.2.3 From 6e786cb1e514dc87647beccaa96bd8a255d97a0c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 15 Dec 2011 14:16:00 +0200 Subject: ath6kl: Fix connect command to clear previously used IEs Empty IE buffer means that the new association is not supposed to include extra IEs. Make sure any previously configured (Re)Association Request frame IEs get cleared in such a case. This is based on a patch from Shuibing. Cc: Dai Shuibing Signed-off-by: Jouni Malinen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 85c24dd0156..1a06a04c510 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -461,13 +461,13 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, } } - if (sme->ie && (sme->ie_len > 0)) { - status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len); - if (status) { - up(&ar->sem); - return status; - } - } else + status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len); + if (status) { + up(&ar->sem); + return status; + } + + if (sme->ie == NULL || sme->ie_len == 0) ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG; if (test_bit(CONNECTED, &vif->flags) && -- cgit v1.2.3 From ca1d16a08fc2c26b693e65ad92fa37a4c778e60d Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 16 Dec 2011 14:24:23 +0530 Subject: ath6kl: Avoid taking struct as argument in ath6kl_wmi_set_ip_cmd In this way, caller is free to pass only the value of IP addr to configure. In addition to this, * 'ips' variable data type in struct wmi_set_ip_cmd is changed from __le32 to __be32 in order to match network byte order. * ipv4_is_multicast() is used to validate multicast ip addr. * New argument if_idx is added to supply correct vif index to ath6kl_wmi_cmd_send(). This will be used in the next patch. Signed-off-by: Raja Mani Signed-off-by: Thirumalai Pachamuthu Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/wmi.c | 12 +++++++----- drivers/net/wireless/ath/ath6kl/wmi.h | 5 +++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index f6f2aa27fc2..1e31c38abb4 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -2479,15 +2479,16 @@ int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 if_idx, u8 traffic_class, return ret; } -int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd) +int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, + __be32 ips0, __be32 ips1) { struct sk_buff *skb; struct wmi_set_ip_cmd *cmd; int ret; /* Multicast address are not valid */ - if ((*((u8 *) &ip_cmd->ips[0]) >= 0xE0) || - (*((u8 *) &ip_cmd->ips[1]) >= 0xE0)) + if (ipv4_is_multicast(ips0) || + ipv4_is_multicast(ips1)) return -EINVAL; skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd)); @@ -2495,9 +2496,10 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd) return -ENOMEM; cmd = (struct wmi_set_ip_cmd *) skb->data; - memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd)); + cmd->ips[0] = ips0; + cmd->ips[1] = ips1; - ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_IP_CMDID, + ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_IP_CMDID, NO_SYNC_WMIFLAG); return ret; } diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 42ac311eda4..96e3cc10cab 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -1903,7 +1903,7 @@ struct wow_filter { struct wmi_set_ip_cmd { /* IP in network byte order */ - __le32 ips[MAX_IP_ADDRS]; + __be32 ips[MAX_IP_ADDRS]; } __packed; enum ath6kl_wow_filters { @@ -2417,7 +2417,8 @@ int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); s32 ath6kl_wmi_get_rate(s8 rate_index); -int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd); +int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, + __be32 ips0, __be32 ips1); int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, enum ath6kl_host_mode host_mode); int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, -- cgit v1.2.3 From c08631c6e43e7ce91bca6b2d3466bb22a85fe724 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 16 Dec 2011 14:24:24 +0530 Subject: ath6kl: Send own IP addr to the firmware during WOW suspend Firmware ARP module requires own IP addr in order to respond to the outside world when the target is in WOW suspend state. At present, firmware ARP module has capability to hold 2 IP addr. So, WOW mode will be disabled if the total IP addr configured in net_dev for our device is greater than firmware limit (MAX_IP_ADDRS) which is 2 at this moment. Signed-off-by: Raja Mani Signed-off-by: Thirumalai Pachamuthu Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 33 +++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 1a06a04c510..45b0d974e4f 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -15,6 +15,7 @@ */ #include +#include #include "core.h" #include "cfg80211.h" @@ -1729,11 +1730,14 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) { + struct in_device *in_dev; + struct in_ifaddr *ifa; struct ath6kl_vif *vif; int ret, pos, left; u32 filter = 0; u16 i; - u8 mask[WOW_MASK_SIZE]; + u8 mask[WOW_MASK_SIZE], index = 0; + __be32 ips[MAX_IP_ADDRS]; vif = ath6kl_vif_first(ar); if (!vif) @@ -1780,6 +1784,33 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) return ret; } + /* Setup own IP addr for ARP agent. */ + in_dev = __in_dev_get_rtnl(vif->ndev); + if (!in_dev) + goto skip_arp; + + ifa = in_dev->ifa_list; + memset(&ips, 0, sizeof(ips)); + + /* Configure IP addr only if IP address count < MAX_IP_ADDRS */ + while (index < MAX_IP_ADDRS && ifa) { + ips[index] = ifa->ifa_local; + ifa = ifa->ifa_next; + index++; + } + + if (ifa) { + ath6kl_err("total IP addr count is exceeding fw limit\n"); + return -EINVAL; + } + + ret = ath6kl_wmi_set_ip_cmd(ar->wmi, vif->fw_vif_idx, ips[0], ips[1]); + if (ret) { + ath6kl_err("fail to setup ip for arp agent\n"); + return ret; + } + +skip_arp: if (wow->disconnect) filter |= WOW_FILTER_OPTION_NWK_DISASSOC; -- cgit v1.2.3 From c0038972b1253ad7f3ab7cc35ed57a830f5c8568 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Fri, 16 Dec 2011 20:53:31 +0200 Subject: ath6kl: handle firmware names more dynamically Currently ath6kl has just hardcoded paths to each firmware file. Change this more dynamic by separating the the directory and file name from each other. That way it's easier to dynamically create full paths to firmware and code looks better. And now it's possible to remove a function needed by devicetree code. While at it add a structure inside struct ath6kl_hw to contain all firmware names. I deliberately omitted board file support as those will be handled later. This is needed for firmware API 3. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.h | 45 +++++++++------- drivers/net/wireless/ath/ath6kl/init.c | 95 ++++++++++++++++++---------------- drivers/net/wireless/ath/ath6kl/sdio.c | 16 +++--- drivers/net/wireless/ath/ath6kl/usb.c | 5 +- 4 files changed, 87 insertions(+), 74 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index c863a28f2e0..26795771256 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -97,45 +97,46 @@ struct ath6kl_fw_ie { u8 data[0]; }; +#define ATH6KL_FW_API2_FILE "fw-2.bin" + /* AR6003 1.0 definitions */ #define AR6003_HW_1_0_VERSION 0x300002ba /* AR6003 2.0 definitions */ #define AR6003_HW_2_0_VERSION 0x30000384 #define AR6003_HW_2_0_PATCH_DOWNLOAD_ADDRESS 0x57e910 -#define AR6003_HW_2_0_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" -#define AR6003_HW_2_0_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" -#define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin" -#define AR6003_HW_2_0_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" -#define AR6003_HW_2_0_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin" +#define AR6003_HW_2_0_FW_DIR "ath6k/AR6003/hw2.0" +#define AR6003_HW_2_0_OTP_FILE "otp.bin.z77" +#define AR6003_HW_2_0_FIRMWARE_FILE "athwlan.bin.z77" +#define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" +#define AR6003_HW_2_0_PATCH_FILE "data.patch.bin" #define AR6003_HW_2_0_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" #define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \ "ath6k/AR6003/hw2.0/bdata.SD31.bin" /* AR6003 3.0 definitions */ #define AR6003_HW_2_1_1_VERSION 0x30000582 -#define AR6003_HW_2_1_1_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" -#define AR6003_HW_2_1_1_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" -#define AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE \ - "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin" -#define AR6003_HW_2_1_1_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" -#define AR6003_HW_2_1_1_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin" +#define AR6003_HW_2_1_1_FW_DIR "ath6k/AR6003/hw2.1.1" +#define AR6003_HW_2_1_1_OTP_FILE "otp.bin" +#define AR6003_HW_2_1_1_FIRMWARE_FILE "athwlan.bin" +#define AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" +#define AR6003_HW_2_1_1_PATCH_FILE "data.patch.bin" #define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \ "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" /* AR6004 1.0 definitions */ #define AR6004_HW_1_0_VERSION 0x30000623 -#define AR6004_HW_1_0_FIRMWARE_2_FILE "ath6k/AR6004/hw1.0/fw-2.bin" -#define AR6004_HW_1_0_FIRMWARE_FILE "ath6k/AR6004/hw1.0/fw.ram.bin" +#define AR6004_HW_1_0_FW_DIR "ath6k/AR6004/hw1.0" +#define AR6004_HW_1_0_FIRMWARE_FILE "fw.ram.bin" #define AR6004_HW_1_0_BOARD_DATA_FILE "ath6k/AR6004/hw1.0/bdata.bin" #define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \ "ath6k/AR6004/hw1.0/bdata.DB132.bin" /* AR6004 1.1 definitions */ #define AR6004_HW_1_1_VERSION 0x30000001 -#define AR6004_HW_1_1_FIRMWARE_2_FILE "ath6k/AR6004/hw1.1/fw-2.bin" -#define AR6004_HW_1_1_FIRMWARE_FILE "ath6k/AR6004/hw1.1/fw.ram.bin" +#define AR6004_HW_1_1_FW_DIR "ath6k/AR6004/hw1.1" +#define AR6004_HW_1_1_FIRMWARE_FILE "fw.ram.bin" #define AR6004_HW_1_1_BOARD_DATA_FILE "ath6k/AR6004/hw1.1/bdata.bin" #define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \ "ath6k/AR6004/hw1.1/bdata.DB132.bin" @@ -575,11 +576,15 @@ struct ath6kl { u32 refclk_hz; u32 uarttx_pin; - const char *fw_otp; - const char *fw; - const char *fw_tcmd; - const char *fw_patch; - const char *fw_api2; + struct ath6kl_hw_fw { + const char *dir; + const char *otp; + const char *fw; + const char *tcmd; + const char *patch; + const char *api2; + } fw; + const char *fw_board; const char *fw_default_board; } hw; diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 368ecbd172a..7b802e99851 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -47,11 +47,15 @@ static const struct ath6kl_hw hw_list[] = { /* hw2.0 needs override address hardcoded */ .app_start_override_addr = 0x944C00, - .fw_otp = AR6003_HW_2_0_OTP_FILE, - .fw = AR6003_HW_2_0_FIRMWARE_FILE, - .fw_tcmd = AR6003_HW_2_0_TCMD_FIRMWARE_FILE, - .fw_patch = AR6003_HW_2_0_PATCH_FILE, - .fw_api2 = AR6003_HW_2_0_FIRMWARE_2_FILE, + .fw = { + .dir = AR6003_HW_2_0_FW_DIR, + .otp = AR6003_HW_2_0_OTP_FILE, + .fw = AR6003_HW_2_0_FIRMWARE_FILE, + .tcmd = AR6003_HW_2_0_TCMD_FIRMWARE_FILE, + .patch = AR6003_HW_2_0_PATCH_FILE, + .api2 = ATH6KL_FW_API2_FILE, + }, + .fw_board = AR6003_HW_2_0_BOARD_DATA_FILE, .fw_default_board = AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE, }, @@ -65,11 +69,15 @@ static const struct ath6kl_hw hw_list[] = { .refclk_hz = 26000000, .uarttx_pin = 8, - .fw_otp = AR6003_HW_2_1_1_OTP_FILE, - .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, - .fw_tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, - .fw_patch = AR6003_HW_2_1_1_PATCH_FILE, - .fw_api2 = AR6003_HW_2_1_1_FIRMWARE_2_FILE, + .fw = { + .dir = AR6003_HW_2_1_1_FW_DIR, + .otp = AR6003_HW_2_1_1_OTP_FILE, + .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, + .tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, + .patch = AR6003_HW_2_1_1_PATCH_FILE, + .api2 = ATH6KL_FW_API2_FILE, + }, + .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE, .fw_default_board = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE, }, @@ -84,8 +92,12 @@ static const struct ath6kl_hw hw_list[] = { .refclk_hz = 26000000, .uarttx_pin = 11, - .fw = AR6004_HW_1_0_FIRMWARE_FILE, - .fw_api2 = AR6004_HW_1_0_FIRMWARE_2_FILE, + .fw = { + .dir = AR6004_HW_1_0_FW_DIR, + .fw = AR6004_HW_1_0_FIRMWARE_FILE, + .api2 = ATH6KL_FW_API2_FILE, + }, + .fw_board = AR6004_HW_1_0_BOARD_DATA_FILE, .fw_default_board = AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE, }, @@ -100,8 +112,12 @@ static const struct ath6kl_hw hw_list[] = { .refclk_hz = 40000000, .uarttx_pin = 11, - .fw = AR6004_HW_1_1_FIRMWARE_FILE, - .fw_api2 = AR6004_HW_1_1_FIRMWARE_2_FILE, + .fw = { + .dir = AR6004_HW_1_1_FW_DIR, + .fw = AR6004_HW_1_1_FIRMWARE_FILE, + .api2 = ATH6KL_FW_API2_FILE, + }, + .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, .fw_default_board = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE, }, @@ -626,21 +642,6 @@ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, } #ifdef CONFIG_OF -static const char *get_target_ver_dir(const struct ath6kl *ar) -{ - switch (ar->version.target_ver) { - case AR6003_HW_1_0_VERSION: - return "ath6k/AR6003/hw1.0"; - case AR6003_HW_2_0_VERSION: - return "ath6k/AR6003/hw2.0"; - case AR6003_HW_2_1_1_VERSION: - return "ath6k/AR6003/hw2.1.1"; - } - ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__, - ar->version.target_ver); - return NULL; -} - /* * Check the device tree for a board-id and use it to construct * the pathname to the firmware file. Used (for now) to find a @@ -663,7 +664,7 @@ static bool check_device_tree(struct ath6kl *ar) continue; } snprintf(board_filename, sizeof(board_filename), - "%s/bdata.%s.bin", get_target_ver_dir(ar), board_id); + "%s/bdata.%s.bin", ar->hw.fw.dir, board_id); ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board, &ar->fw_board_len); @@ -730,19 +731,20 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) static int ath6kl_fetch_otp_file(struct ath6kl *ar) { - const char *filename; + char filename[100]; int ret; if (ar->fw_otp != NULL) return 0; - if (ar->hw.fw_otp == NULL) { + if (ar->hw.fw.otp == NULL) { ath6kl_dbg(ATH6KL_DBG_BOOT, "no OTP file configured for this hw\n"); return 0; } - filename = ar->hw.fw_otp; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.otp); ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, &ar->fw_otp_len); @@ -757,29 +759,32 @@ static int ath6kl_fetch_otp_file(struct ath6kl *ar) static int ath6kl_fetch_fw_file(struct ath6kl *ar) { - const char *filename; + char filename[100]; int ret; if (ar->fw != NULL) return 0; if (testmode) { - if (ar->hw.fw_tcmd == NULL) { + if (ar->hw.fw.tcmd == NULL) { ath6kl_warn("testmode not supported\n"); return -EOPNOTSUPP; } - filename = ar->hw.fw_tcmd; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.tcmd); set_bit(TESTMODE, &ar->flag); goto get_fw; } - if (WARN_ON(ar->hw.fw == NULL)) + /* FIXME: remove WARN_ON() as we won't support FW API 1 for long */ + if (WARN_ON(ar->hw.fw.fw == NULL)) return -EINVAL; - filename = ar->hw.fw; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.fw); get_fw: ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); @@ -794,16 +799,17 @@ get_fw: static int ath6kl_fetch_patch_file(struct ath6kl *ar) { - const char *filename; + char filename[100]; int ret; if (ar->fw_patch != NULL) return 0; - if (ar->hw.fw_patch == NULL) + if (ar->hw.fw.patch == NULL) return 0; - filename = ar->hw.fw_patch; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.patch); ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, &ar->fw_patch_len); @@ -840,15 +846,16 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar) size_t magic_len, len, ie_len; const struct firmware *fw; struct ath6kl_fw_ie *hdr; - const char *filename; + char filename[100]; const u8 *data; int ret, ie_id, i, index, bit; __le32 *val; - if (ar->hw.fw_api2 == NULL) + if (ar->hw.fw.api2 == NULL) return -EOPNOTSUPP; - filename = ar->hw.fw_api2; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.api2); ret = request_firmware(&fw, filename, ar->dev); if (ret) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 15c3f56caf4..278a9f30795 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -1362,19 +1362,19 @@ MODULE_AUTHOR("Atheros Communications, Inc."); MODULE_DESCRIPTION("Driver support for Atheros AR600x SDIO devices"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_FIRMWARE(AR6003_HW_2_0_OTP_FILE); -MODULE_FIRMWARE(AR6003_HW_2_0_FIRMWARE_FILE); -MODULE_FIRMWARE(AR6003_HW_2_0_PATCH_FILE); +MODULE_FIRMWARE(AR6003_HW_2_0_FW_DIR "/" AR6003_HW_2_0_OTP_FILE); +MODULE_FIRMWARE(AR6003_HW_2_0_FW_DIR "/" AR6003_HW_2_0_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6003_HW_2_0_FW_DIR "/" AR6003_HW_2_0_PATCH_FILE); MODULE_FIRMWARE(AR6003_HW_2_0_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE); -MODULE_FIRMWARE(AR6003_HW_2_1_1_OTP_FILE); -MODULE_FIRMWARE(AR6003_HW_2_1_1_FIRMWARE_FILE); -MODULE_FIRMWARE(AR6003_HW_2_1_1_PATCH_FILE); +MODULE_FIRMWARE(AR6003_HW_2_1_1_FW_DIR "/" AR6003_HW_2_1_1_OTP_FILE); +MODULE_FIRMWARE(AR6003_HW_2_1_1_FW_DIR "/" AR6003_HW_2_1_1_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6003_HW_2_1_1_FW_DIR "/" AR6003_HW_2_1_1_PATCH_FILE); MODULE_FIRMWARE(AR6003_HW_2_1_1_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE); -MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_0_FW_DIR "/" AR6004_HW_1_0_FIRMWARE_FILE); MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); -MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_1_FW_DIR "/" AR6004_HW_1_1_FIRMWARE_FILE); MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index e3cf397fcaf..bb341796dc8 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c @@ -423,9 +423,10 @@ module_exit(ath6kl_usb_exit); MODULE_AUTHOR("Atheros Communications, Inc."); MODULE_DESCRIPTION("Driver support for Atheros AR600x USB devices"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE); + +MODULE_FIRMWARE(AR6004_HW_1_0_FW_DIR "/" AR6004_HW_1_0_FIRMWARE_FILE); MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); -MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_1_FW_DIR "/" AR6004_HW_1_1_FIRMWARE_FILE); MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); -- cgit v1.2.3 From 65a8b4cc511b68712799e91137324f2abece7d3e Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Fri, 16 Dec 2011 20:53:41 +0200 Subject: ath6kl: add support for FW API 3 As firmware starting from 3.2.0.12 has some API changes and doesn't work with older versions of ath6kl we need to bump up the API version. This way we don't break anything. Also store which version of API is used and print that during boot: ath6kl: ar6003 hw 2.1.1 sdio fw 3.2.0.13 api 3 Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.h | 3 ++- drivers/net/wireless/ath/ath6kl/init.c | 32 +++++++++++++++++--------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 26795771256..c095fafa278 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -98,6 +98,7 @@ struct ath6kl_fw_ie { }; #define ATH6KL_FW_API2_FILE "fw-2.bin" +#define ATH6KL_FW_API3_FILE "fw-3.bin" /* AR6003 1.0 definitions */ #define AR6003_HW_1_0_VERSION 0x300002ba @@ -582,7 +583,6 @@ struct ath6kl { const char *fw; const char *tcmd; const char *patch; - const char *api2; } fw; const char *fw_board; @@ -608,6 +608,7 @@ struct ath6kl { u8 *fw_patch; size_t fw_patch_len; + unsigned int fw_api; unsigned long fw_capabilities[ATH6KL_CAPABILITY_LEN]; struct workqueue_struct *ath6kl_wq; diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 7b802e99851..57e0312c4cb 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -53,7 +53,6 @@ static const struct ath6kl_hw hw_list[] = { .fw = AR6003_HW_2_0_FIRMWARE_FILE, .tcmd = AR6003_HW_2_0_TCMD_FIRMWARE_FILE, .patch = AR6003_HW_2_0_PATCH_FILE, - .api2 = ATH6KL_FW_API2_FILE, }, .fw_board = AR6003_HW_2_0_BOARD_DATA_FILE, @@ -75,7 +74,6 @@ static const struct ath6kl_hw hw_list[] = { .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, .tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, .patch = AR6003_HW_2_1_1_PATCH_FILE, - .api2 = ATH6KL_FW_API2_FILE, }, .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE, @@ -95,7 +93,6 @@ static const struct ath6kl_hw hw_list[] = { .fw = { .dir = AR6004_HW_1_0_FW_DIR, .fw = AR6004_HW_1_0_FIRMWARE_FILE, - .api2 = ATH6KL_FW_API2_FILE, }, .fw_board = AR6004_HW_1_0_BOARD_DATA_FILE, @@ -115,7 +112,6 @@ static const struct ath6kl_hw hw_list[] = { .fw = { .dir = AR6004_HW_1_1_FW_DIR, .fw = AR6004_HW_1_1_FIRMWARE_FILE, - .api2 = ATH6KL_FW_API2_FILE, }, .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, @@ -841,7 +837,7 @@ static int ath6kl_fetch_fw_api1(struct ath6kl *ar) return 0; } -static int ath6kl_fetch_fw_api2(struct ath6kl *ar) +static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) { size_t magic_len, len, ie_len; const struct firmware *fw; @@ -851,11 +847,7 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar) int ret, ie_id, i, index, bit; __le32 *val; - if (ar->hw.fw.api2 == NULL) - return -EOPNOTSUPP; - - snprintf(filename, sizeof(filename), "%s/%s", - ar->hw.fw.dir, ar->hw.fw.api2); + snprintf(filename, sizeof(filename), "%s/%s", ar->hw.fw.dir, name); ret = request_firmware(&fw, filename, ar->dev); if (ret) @@ -1025,17 +1017,26 @@ static int ath6kl_fetch_firmwares(struct ath6kl *ar) if (ret) return ret; - ret = ath6kl_fetch_fw_api2(ar); + ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API3_FILE); if (ret == 0) { - ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 2\n"); - return 0; + ar->fw_api = 3; + goto out; + } + + ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API2_FILE); + if (ret == 0) { + ar->fw_api = 2; + goto out; } ret = ath6kl_fetch_fw_api1(ar); if (ret) return ret; - ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 1\n"); + ar->fw_api = 1; + +out: + ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api %d\n", ar->fw_api); return 0; } @@ -1488,10 +1489,11 @@ int ath6kl_init_hw_start(struct ath6kl *ar) if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) { - ath6kl_info("%s %s fw %s%s\n", + ath6kl_info("%s %s fw %s api %d%s\n", ar->hw.name, ath6kl_init_get_hif_name(ar->hif_type), ar->wiphy->fw_version, + ar->fw_api, test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); } -- cgit v1.2.3 From e68f67509d92114c55938898643600c23f88b4c1 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Thu, 22 Dec 2011 12:15:27 +0530 Subject: ath6kl: Fix panic when setting a channel cfg80211 could pass a NULL net_device to the driver via the set_channel() callback, when it receives a request to set the device's channel. Not handling this case properly results in this panic: BUG: unable to handle kernel NULL pointer dereference at 0000000000000cb0 IP: [] ath6kl_cfg80211_ready+0x9/0x70 [ath6kl_sdio] Call Trace: [] ath6kl_set_channel+0x27/0x90 [ath6kl_sdio] [] cfg80211_set_freq+0xff/0x1d0 [cfg80211] [] ? nl80211_set_wiphy+0x85/0x660 [cfg80211] [] __nl80211_set_channel.isra.39+0x118/0x140 [cfg80211] [] nl80211_set_wiphy+0x303/0x660 [cfg80211] [] ? rtnl_lock+0x17/0x20 [] ? nl80211_pre_doit+0xb5/0x150 [cfg80211] [] genl_rcv_msg+0x1d5/0x250 [] ? genl_rcv+0x40/0x40 [] netlink_rcv_skb+0xa9/0xd0 [] genl_rcv+0x25/0x40 [] ? might_fault+0x40/0x90 [] netlink_unicast+0x2d9/0x320 [] netlink_sendmsg+0x2c6/0x320 [] ? sock_update_classid+0xb0/0x110 [] sock_sendmsg+0x10e/0x130 [] ? mem_cgroup_update_page_stat+0x193/0x250 [] ? might_fault+0x40/0x90 [] ? might_fault+0x40/0x90 [] ? might_fault+0x89/0x90 [] ? might_fault+0x40/0x90 [] ? verify_iovec+0x56/0xd0 [] __sys_sendmsg+0x396/0x3b0 [] ? up_read+0x23/0x40 [] ? do_page_fault+0x208/0x4e0 [] ? vfsmount_lock_local_unlock+0x21/0x60 [] ? mntput_no_expire+0x30/0xe0 [] ? mntput+0x1f/0x30 [] sys_sendmsg+0x49/0x90 [] system_call_fastpath+0x16/0x1b Signed-off-by: Sujith Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 45b0d974e4f..d6806be5895 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2044,7 +2044,18 @@ static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) { - struct ath6kl_vif *vif = netdev_priv(dev); + struct ath6kl_vif *vif; + + /* + * 'dev' could be NULL if a channel change is required for the hardware + * device itself, instead of a particular VIF. + * + * FIXME: To be handled properly when monitor mode is supported. + */ + if (!dev) + return -EBUSY; + + vif = netdev_priv(dev); if (!ath6kl_cfg80211_ready(vif)) return -EIO; -- cgit v1.2.3 From 33e5308d8a0fb857a57c38def36ccf7b14ebf1c1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 27 Dec 2011 11:02:56 +0200 Subject: ath6kl: Add del_station cfg80211_ops hostapd/wpa_supplicant AP mode uses this operation to flush the station entries. Implement this in ath6kl to avoid unnecessary warnings from NL80211_CMD_DEL_STATION failing. Signed-off-by: Jouni Malinen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index d6806be5895..f74762ed619 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2300,6 +2300,19 @@ static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev) return 0; } +static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + +static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac) +{ + struct ath6kl *ar = ath6kl_priv(dev); + struct ath6kl_vif *vif = netdev_priv(dev); + const u8 *addr = mac ? mac : bcast_addr; + + return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, WMI_AP_DEAUTH, + addr, WLAN_REASON_PREV_AUTH_NOT_VALID); +} + static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac, struct station_parameters *params) { @@ -2603,6 +2616,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { .add_beacon = ath6kl_add_beacon, .set_beacon = ath6kl_set_beacon, .del_beacon = ath6kl_del_beacon, + .del_station = ath6kl_del_station, .change_station = ath6kl_change_station, .remain_on_channel = ath6kl_remain_on_channel, .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, -- cgit v1.2.3 From ba1f6fe393c329230d2589ea508cbf90ff3cc9ce Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 27 Dec 2011 11:03:53 +0200 Subject: ath6kl: Advertise TX/RX support for frames in AP mode This is needed to fix current hostapd/wpa_supplicant AP operations for frame registration. P2P GO mode already advertised these, but AP mode was forgotten and could not be used after the hostapd/wpa_supplicant frame registration changes. Signed-off-by: Jouni Malinen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index f74762ed619..c756425abf7 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2572,6 +2572,12 @@ ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) }, + [NL80211_IFTYPE_AP] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, [NL80211_IFTYPE_P2P_CLIENT] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), -- cgit v1.2.3 From bc48ad31c5814feb4ff8faca9a8d422279593cb1 Mon Sep 17 00:00:00 2001 From: Rishi Panjwani Date: Tue, 27 Dec 2011 14:28:00 -0800 Subject: ath6kl: Support for TCP checksum offload to firmware The change enables offloading TCP checksum calculation to firmware. There are still some issues with the checksum offload so better to disable it by default until the issues are resolved. To enable TCP checksum offload for tx and rx paths, use the ethtool as follows: ethtool -K tx on ethtool -K rx on To disable TCP checksum offload, for tx and rx paths, use the ethtool as follows: ethtool -K tx off ethtool -K rx off kvalo: indentation changes Signed-off-by: Rishi Panjwani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/init.c | 2 ++ drivers/net/wireless/ath/ath6kl/main.c | 33 +++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath6kl/txrx.c | 38 ++++++++++++++++++++++++++++++---- drivers/net/wireless/ath/ath6kl/wmi.h | 3 +++ 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 57e0312c4cb..e74279372ef 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1686,6 +1686,8 @@ int ath6kl_core_init(struct ath6kl *ar) set_bit(FIRST_BOOT, &ar->flag); + ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; + ret = ath6kl_init_hw_start(ar); if (ret) { ath6kl_err("Failed to start hardware: %d\n", ret); diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index eea3c747653..f3d0184a5ce 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1020,11 +1020,44 @@ static struct net_device_stats *ath6kl_get_stats(struct net_device *dev) return &vif->net_stats; } +static int ath6kl_set_features(struct net_device *dev, u32 features) +{ + struct ath6kl_vif *vif = netdev_priv(dev); + struct ath6kl *ar = vif->ar; + int err = 0; + + if ((features & NETIF_F_RXCSUM) && + (ar->rx_meta_ver != WMI_META_VERSION_2)) { + ar->rx_meta_ver = WMI_META_VERSION_2; + err = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, + vif->fw_vif_idx, + ar->rx_meta_ver, 0, 0); + if (err) { + dev->features = features & ~NETIF_F_RXCSUM; + return err; + } + } else if (!(features & NETIF_F_RXCSUM) && + (ar->rx_meta_ver == WMI_META_VERSION_2)) { + ar->rx_meta_ver = 0; + err = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, + vif->fw_vif_idx, + ar->rx_meta_ver, 0, 0); + if (err) { + dev->features = features | NETIF_F_RXCSUM; + return err; + } + + } + + return err; +} + static struct net_device_ops ath6kl_netdev_ops = { .ndo_open = ath6kl_open, .ndo_stop = ath6kl_close, .ndo_start_xmit = ath6kl_data_tx, .ndo_get_stats = ath6kl_get_stats, + .ndo_set_features = ath6kl_set_features, }; void init_netdev(struct net_device *dev) diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 506a3031a88..78bd57306f7 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -244,6 +244,10 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) u8 ac = 99 ; /* initialize to unmapped ac */ bool chk_adhoc_ps_mapping = false, more_data = false; int ret; + struct wmi_tx_meta_v2 meta_v2; + void *meta; + u8 csum_start = 0, csum_dest = 0, csum = skb->ip_summed; + u8 meta_ver = 0; ath6kl_dbg(ATH6KL_DBG_WLAN_TX, "%s: skb=0x%p, data=0x%p, len=0x%x\n", __func__, @@ -265,6 +269,14 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) } if (test_bit(WMI_ENABLED, &ar->flag)) { + if ((dev->features & NETIF_F_IP_CSUM) && + (csum == CHECKSUM_PARTIAL)) { + csum_start = skb->csum_start - + (skb_network_header(skb) - skb->head) + + sizeof(struct ath6kl_llc_snap_hdr); + csum_dest = skb->csum_offset + csum_start; + } + if (skb_headroom(skb) < dev->needed_headroom) { struct sk_buff *tmp_skb = skb; @@ -281,10 +293,28 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) goto fail_tx; } - if (ath6kl_wmi_data_hdr_add(ar->wmi, skb, DATA_MSGTYPE, - more_data, 0, 0, NULL, - vif->fw_vif_idx)) { - ath6kl_err("wmi_data_hdr_add failed\n"); + if ((dev->features & NETIF_F_IP_CSUM) && + (csum == CHECKSUM_PARTIAL)) { + meta_v2.csum_start = csum_start; + meta_v2.csum_dest = csum_dest; + + /* instruct target to calculate checksum */ + meta_v2.csum_flags = WMI_META_V2_FLAG_CSUM_OFFLOAD; + meta_ver = WMI_META_VERSION_2; + meta = &meta_v2; + } else { + meta_ver = 0; + meta = NULL; + } + + ret = ath6kl_wmi_data_hdr_add(ar->wmi, skb, + DATA_MSGTYPE, more_data, 0, + meta_ver, + meta, vif->fw_vif_idx); + + if (ret) { + ath6kl_warn("failed to add wmi data header:%d\n" + , ret); goto fail_tx; } diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 96e3cc10cab..9f8425b97db 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -257,6 +257,9 @@ static inline u8 wmi_data_hdr_get_if_idx(struct wmi_data_hdr *dhdr) #define WMI_META_VERSION_1 0x01 #define WMI_META_VERSION_2 0x02 +/* Flag to signal to FW to calculate TCP checksum */ +#define WMI_META_V2_FLAG_CSUM_OFFLOAD 0x01 + struct wmi_tx_meta_v1 { /* packet ID to identify the tx request */ u8 pkt_id; -- cgit v1.2.3 From 351de2835d6429548feb8cca9a17497ec3474f41 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 29 Dec 2011 16:05:37 +0530 Subject: ath6kl: Remove few unnecessary spin_locks around set_bit() Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/txrx.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 78bd57306f7..fcea82479cd 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -479,9 +479,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, * WMI queue with too many commands the only exception to * this is during testing using endpointping. */ - spin_lock_bh(&ar->lock); set_bit(WMI_CTRL_EP_FULL, &ar->flag); - spin_unlock_bh(&ar->lock); ath6kl_err("wmi ctrl ep is full\n"); return action; } @@ -509,9 +507,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, action != HTC_SEND_FULL_DROP) { spin_unlock_bh(&ar->list_lock); - spin_lock_bh(&vif->if_lock); set_bit(NETQ_STOPPED, &vif->flags); - spin_unlock_bh(&vif->if_lock); netif_stop_queue(vif->ndev); return action; -- cgit v1.2.3 From a10e2f2f6db8f86eaca1cf3d00269463da4d6434 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 29 Dec 2011 16:05:38 +0530 Subject: ath6kl: Add a module parameter to enable uart debug To enable firmware debug messages through uart interface, modprobe ath6kl_sdio uart_debug=1. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/init.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index e74279372ef..a481b6a1715 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -28,10 +28,12 @@ unsigned int debug_mask; static unsigned int testmode; static bool suspend_cutpower; +static unsigned int uart_debug; module_param(debug_mask, uint, 0644); module_param(testmode, uint, 0644); module_param(suspend_cutpower, bool, 0444); +module_param(uart_debug, uint, 0644); static const struct ath6kl_hw hw_list[] = { { @@ -464,6 +466,13 @@ int ath6kl_configure_target(struct ath6kl *ar) u8 fw_iftype, fw_mode = 0, fw_submode = 0; int i, status; + param = uart_debug; + if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_serial_enable)), (u8 *)¶m, 4)) { + ath6kl_err("bmi_write_memory for uart debug failed\n"); + return -EIO; + } + /* * Note: Even though the firmware interface type is * chosen as BSS_STA for all three interfaces, can -- cgit v1.2.3 From 792ecb33080f4e315695e0fe21cf3a3c2a514dd0 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Thu, 29 Dec 2011 16:18:39 +0530 Subject: ath6kl: Remove redundant key_index check. Less-than-zero comparison of an unsigned value is never true. kvalo: remove WMI_MIN_KEY_INDEX altogether, it's useless Signed-off-by: Vivek Natarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 11 +++++------ drivers/net/wireless/ath/ath6kl/main.c | 2 +- drivers/net/wireless/ath/ath6kl/wmi.h | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index c756425abf7..2a166cc7cc3 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -524,8 +524,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, (vif->prwise_crypto == WEP_CRYPT)) { struct ath6kl_key *key = NULL; - if (sme->key_idx < WMI_MIN_KEY_INDEX || - sme->key_idx > WMI_MAX_KEY_INDEX) { + if (sme->key_idx > WMI_MAX_KEY_INDEX) { ath6kl_err("key index %d out of bounds\n", sme->key_idx); up(&ar->sem); @@ -997,7 +996,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, params->key); } - if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + if (key_index > WMI_MAX_KEY_INDEX) { ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: key index %d out of bounds\n", __func__, key_index); @@ -1115,7 +1114,7 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, if (!ath6kl_cfg80211_ready(vif)) return -EIO; - if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + if (key_index > WMI_MAX_KEY_INDEX) { ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: key index %d out of bounds\n", __func__, key_index); @@ -1148,7 +1147,7 @@ static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, if (!ath6kl_cfg80211_ready(vif)) return -EIO; - if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + if (key_index > WMI_MAX_KEY_INDEX) { ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: key index %d out of bounds\n", __func__, key_index); @@ -1184,7 +1183,7 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, if (!ath6kl_cfg80211_ready(vif)) return -EIO; - if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + if (key_index > WMI_MAX_KEY_INDEX) { ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: key index %d out of bounds\n", __func__, key_index); diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index f3d0184a5ce..f74986d6209 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -363,7 +363,7 @@ static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif) u8 index; u8 keyusage; - for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) { + for (index = 0; index <= WMI_MAX_KEY_INDEX; index++) { if (vif->wep_key_list[index].key_len) { keyusage = GROUP_USAGE; if (index == vif->def_txkey_index) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 9f8425b97db..2b435994b01 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -649,7 +649,6 @@ enum auth_mode { WPA2_AUTH_CCKM = 0x40, }; -#define WMI_MIN_KEY_INDEX 0 #define WMI_MAX_KEY_INDEX 3 #define WMI_MAX_KEY_LEN 32 -- cgit v1.2.3 From 4f34dacea117029dbad1f0f50d68207b97546d1e Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Fri, 30 Dec 2011 01:57:00 -0800 Subject: ath6kl: send TCMD response through testmode events ath6kl no longer knows what it is transmitting through cfg80211_testmode, and simply passes opaque buffers between userspace and the firmware. Leave the CONT_RX enum for backwards compatibility. kvalo: change ATH6KL_TM_CMD_RX_REPORT to return -EOPNOTSUPP Signed-off-by: Thomas Pedersen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/testmode.c | 102 +++++------------------------ drivers/net/wireless/ath/ath6kl/testmode.h | 6 +- drivers/net/wireless/ath/ath6kl/wmi.c | 6 +- 3 files changed, 23 insertions(+), 91 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/testmode.c b/drivers/net/wireless/ath/ath6kl/testmode.c index 381eb66a605..f0cd61d6188 100644 --- a/drivers/net/wireless/ath/ath6kl/testmode.c +++ b/drivers/net/wireless/ath/ath6kl/testmode.c @@ -15,6 +15,7 @@ */ #include "testmode.h" +#include "debug.h" #include @@ -30,7 +31,7 @@ enum ath6kl_tm_attr { enum ath6kl_tm_cmd { ATH6KL_TM_CMD_TCMD = 0, - ATH6KL_TM_CMD_RX_REPORT = 1, + ATH6KL_TM_CMD_RX_REPORT = 1, /* not used anymore */ }; #define ATH6KL_TM_DATA_MAX_LEN 5000 @@ -41,84 +42,33 @@ static const struct nla_policy ath6kl_tm_policy[ATH6KL_TM_ATTR_MAX + 1] = { .len = ATH6KL_TM_DATA_MAX_LEN }, }; -void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len) +void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, size_t buf_len) { - if (down_interruptible(&ar->sem)) - return; - - kfree(ar->tm.rx_report); - - ar->tm.rx_report = kmemdup(buf, buf_len, GFP_KERNEL); - ar->tm.rx_report_len = buf_len; - - up(&ar->sem); - - wake_up(&ar->event_wq); -} - -static int ath6kl_tm_rx_report(struct ath6kl *ar, void *buf, size_t buf_len, - struct sk_buff *skb) -{ - int ret = 0; - long left; - - if (down_interruptible(&ar->sem)) - return -ERESTARTSYS; - - if (!test_bit(WMI_READY, &ar->flag)) { - ret = -EIO; - goto out; - } - - if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { - ret = -EBUSY; - goto out; - } - - if (ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len) < 0) { - up(&ar->sem); - return -EIO; - } - - left = wait_event_interruptible_timeout(ar->event_wq, - ar->tm.rx_report != NULL, - WMI_TIMEOUT); + struct sk_buff *skb; - if (left == 0) { - ret = -ETIMEDOUT; - goto out; - } else if (left < 0) { - ret = left; - goto out; - } + if (!buf || buf_len == 0) + return; - if (ar->tm.rx_report == NULL || ar->tm.rx_report_len == 0) { - ret = -EINVAL; - goto out; + skb = cfg80211_testmode_alloc_event_skb(ar->wiphy, buf_len, GFP_KERNEL); + if (!skb) { + ath6kl_warn("failed to allocate testmode rx skb!\n"); + return; } - - NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, ar->tm.rx_report_len, - ar->tm.rx_report); - - kfree(ar->tm.rx_report); - ar->tm.rx_report = NULL; - -out: - up(&ar->sem); - - return ret; + NLA_PUT_U32(skb, ATH6KL_TM_ATTR_CMD, ATH6KL_TM_CMD_TCMD); + NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, buf_len, buf); + cfg80211_testmode_event(skb, GFP_KERNEL); + return; nla_put_failure: - ret = -ENOBUFS; - goto out; + kfree_skb(skb); + ath6kl_warn("nla_put failed on testmode rx skb!\n"); } int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) { struct ath6kl *ar = wiphy_priv(wiphy); struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1]; - int err, buf_len, reply_len; - struct sk_buff *skb; + int err, buf_len; void *buf; err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, @@ -143,24 +93,6 @@ int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) break; case ATH6KL_TM_CMD_RX_REPORT: - if (!tb[ATH6KL_TM_ATTR_DATA]) - return -EINVAL; - - buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); - buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); - - reply_len = nla_total_size(ATH6KL_TM_DATA_MAX_LEN); - skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len); - if (!skb) - return -ENOMEM; - - err = ath6kl_tm_rx_report(ar, buf, buf_len, skb); - if (err < 0) { - kfree_skb(skb); - return err; - } - - return cfg80211_testmode_reply(skb); default: return -EOPNOTSUPP; } diff --git a/drivers/net/wireless/ath/ath6kl/testmode.h b/drivers/net/wireless/ath/ath6kl/testmode.h index 43dffcc11fb..7fd47a62d07 100644 --- a/drivers/net/wireless/ath/ath6kl/testmode.h +++ b/drivers/net/wireless/ath/ath6kl/testmode.h @@ -18,13 +18,13 @@ #ifdef CONFIG_NL80211_TESTMODE -void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len); +void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, size_t buf_len); int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len); #else -static inline void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, - size_t buf_len) +static inline void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, + size_t buf_len) { } diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 1e31c38abb4..c6ca660d270 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -1145,9 +1145,9 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len) return 0; } -static int ath6kl_wmi_tcmd_test_report_rx(struct wmi *wmi, u8 *datap, int len) +static int ath6kl_wmi_test_rx(struct wmi *wmi, u8 *datap, int len) { - ath6kl_tm_rx_report_event(wmi->parent_dev, datap, len); + ath6kl_tm_rx_event(wmi->parent_dev, datap, len); return 0; } @@ -3402,7 +3402,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) break; case WMI_TEST_EVENTID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n"); - ret = ath6kl_wmi_tcmd_test_report_rx(wmi, datap, len); + ret = ath6kl_wmi_test_rx(wmi, datap, len); break; case WMI_GET_FIXRATES_CMDID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n"); -- cgit v1.2.3 From 64eeacb7f0317e5f3d6f0f63399ed00b4b2b7dc0 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 16 Dec 2011 09:31:14 -0800 Subject: iwlwifi: don't process the info from uCode if does not has ownership When enable the testmode from user space and working with uCode, driver does not own the uCode and should not process the notifications or pkts from uCode Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index b22b2976f89..eda95ae88ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -1172,20 +1172,22 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, wake_up_all(&priv->shrd->notif_waitq); } - if (priv->pre_rx_handler) + if (priv->pre_rx_handler && + priv->shrd->ucode_owner == IWL_OWNERSHIP_TM) priv->pre_rx_handler(priv, rxb); - - /* Based on type of command response or notification, - * handle those that need handling via function in - * rx_handlers table. See iwl_setup_rx_handlers() */ - if (priv->rx_handlers[pkt->hdr.cmd]) { - priv->rx_handlers_stats[pkt->hdr.cmd]++; - err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd); - } else { - /* No handling needed */ - IWL_DEBUG_RX(priv, - "No handler needed for %s, 0x%02x\n", - get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); + else { + /* Based on type of command response or notification, + * handle those that need handling via function in + * rx_handlers table. See iwl_setup_rx_handlers() */ + if (priv->rx_handlers[pkt->hdr.cmd]) { + priv->rx_handlers_stats[pkt->hdr.cmd]++; + err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd); + } else { + /* No handling needed */ + IWL_DEBUG_RX(priv, + "No handler needed for %s, 0x%02x\n", + get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); + } } return err; } -- cgit v1.2.3 From d75140120971964dca1eee9aa5c9ab25bf0f664f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 16 Dec 2011 07:31:35 -0800 Subject: iwlwifi: Sanity check for sta_id On my testing, I saw some strange behavior [ 421.739708] iwlwifi 0000:01:00.0: ACTIVATE a non DRIVER active station id 148 addr 00:00:00:00:00:00 [ 421.739719] iwlwifi 0000:01:00.0: iwl_sta_ucode_activate Added STA id 148 addr 00:00:00:00:00:00 to uCode not sure how it happen, but adding the sanity check to prevent memory corruption Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 7353826095f..8d4353a4256 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -35,9 +35,12 @@ #include "iwl-trans.h" /* priv->shrd->sta_lock must be held */ -static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) +static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) { - + if (sta_id >= IWLAGN_STATION_COUNT) { + IWL_ERR(priv, "invalid sta_id %u", sta_id); + return -EINVAL; + } if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u " "addr %pM\n", @@ -53,6 +56,7 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n", sta_id, priv->stations[sta_id].sta.sta.addr); } + return 0; } static int iwl_process_add_sta_resp(struct iwl_priv *priv, @@ -77,8 +81,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, switch (pkt->u.add_sta.status) { case ADD_STA_SUCCESS_MSK: IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); - iwl_sta_ucode_activate(priv, sta_id); - ret = 0; + ret = iwl_sta_ucode_activate(priv, sta_id); break; case ADD_STA_NO_ROOM_IN_TABLE: IWL_ERR(priv, "Adding station %d failed, no room in table.\n", -- cgit v1.2.3 From c381be2853bbe4bc1bd6fee88f0a33041de65d06 Mon Sep 17 00:00:00 2001 From: Kenny Hsu Date: Fri, 23 Dec 2011 14:50:48 +0800 Subject: iwlwifi: update testmode command of direct register access In order to make sure the testcommand function of direct register access can be performed even NIC is asleep, replace corresponding handler iwl_read32 and iwl_write32 by using iwl_direct_read32 and iwl_direct_write32. Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-testmode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 4a5cddd2d56..2fc20675dc7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -299,7 +299,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: - val32 = iwl_read32(bus(priv), ofs); + val32 = iwl_read_direct32(bus(priv), ofs); IWL_INFO(priv, "32bit value to read 0x%x\n", val32); skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); @@ -321,7 +321,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } else { val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); IWL_INFO(priv, "32bit value to write 0x%x\n", val32); - iwl_write32(bus(priv), ofs, val32); + iwl_write_direct32(bus(priv), ofs, val32); } break; case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: -- cgit v1.2.3 From 25324caf6e3fc8134444af74fc85182862d520cc Mon Sep 17 00:00:00 2001 From: Kenny Hsu Date: Tue, 27 Dec 2011 08:18:31 -0800 Subject: iwlwifi: enhance testmode command sram_read This patch enables SRAM read function to support entire target memory. Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-testmode.c | 7 +++---- drivers/net/wireless/iwlwifi/iwl-testmode.h | 3 +++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 2fc20675dc7..58575fdc450 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -733,7 +733,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) { struct iwl_priv *priv = hw->priv; - u32 base, ofs, size, maxsize; + u32 ofs, size, maxsize; if (priv->testmode_sram.sram_readed) return -EBUSY; @@ -765,7 +765,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) IWL_DEBUG_INFO(priv, "Error, unsupported uCode type\n"); return -ENOSYS; } - if ((ofs + size) > maxsize) { + if ((ofs + size) > (maxsize + SRAM_DATA_SEG_OFFSET)) { IWL_DEBUG_INFO(priv, "Invalid offset/size: out of range\n"); return -EINVAL; } @@ -776,8 +776,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) IWL_DEBUG_INFO(priv, "Error allocating memory\n"); return -ENOMEM; } - base = 0x800000; - _iwl_read_targ_mem_words(bus(priv), base + ofs, + _iwl_read_targ_mem_words(bus(priv), ofs, priv->testmode_sram.buff_addr, priv->testmode_sram.buff_size / 4); priv->testmode_sram.num_chunks = diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 26138f11034..9c6a67ab5c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -271,4 +271,7 @@ enum iwl_tm_attr_t { /* Maximum data size of each dump it packet */ #define DUMP_CHUNK_SIZE (PAGE_SIZE - 1024) +/* Address offset of data segment in SRAM */ +#define SRAM_DATA_SEG_OFFSET 0x800000 + #endif -- cgit v1.2.3 From 22b48087ea4df1841c2507173c98e6b4f26fe64d Mon Sep 17 00:00:00 2001 From: Kenny Hsu Date: Tue, 27 Dec 2011 08:27:52 -0800 Subject: iwlwifi: update error dump in testmode command sram_read The error message will be show up by using IWL_ERR insteads of IWl_DEBUG_INFO. Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-testmode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 58575fdc450..b56cd900805 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -759,21 +759,21 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) maxsize = trans(priv)->ucode_wowlan.data.len; break; case IWL_UCODE_NONE: - IWL_DEBUG_INFO(priv, "Error, uCode does not been loaded\n"); + IWL_ERR(priv, "Error, uCode does not been loaded\n"); return -ENOSYS; default: - IWL_DEBUG_INFO(priv, "Error, unsupported uCode type\n"); + IWL_ERR(priv, "Error, unsupported uCode type\n"); return -ENOSYS; } if ((ofs + size) > (maxsize + SRAM_DATA_SEG_OFFSET)) { - IWL_DEBUG_INFO(priv, "Invalid offset/size: out of range\n"); + IWL_ERR(priv, "Invalid offset/size: out of range\n"); return -EINVAL; } priv->testmode_sram.buff_size = (size / 4) * 4; priv->testmode_sram.buff_addr = kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL); if (priv->testmode_sram.buff_addr == NULL) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + IWL_ERR(priv, "Error allocating memory\n"); return -ENOMEM; } _iwl_read_targ_mem_words(bus(priv), ofs, -- cgit v1.2.3 From aca9b5f34352248a23c4d776afebf171e711090b Mon Sep 17 00:00:00 2001 From: Kenny Hsu Date: Sat, 24 Dec 2011 12:12:12 +0800 Subject: iwlwifi: add testmode cmd IWL_TM_CMD_APP2DEV_GET_FW_INFO Add new testmode command IWL_TM_CMD_APP2DEV_GET_FW_INFO for reporting the following information of existing loaded uCode image. + uCode type + Instruction section size + Data section size Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-testmode.c | 41 ++++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-testmode.h | 19 +++++++++++-- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index b56cd900805..7684c0e2f21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -115,6 +115,9 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { [IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, }, [IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, }, + [IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, }, + [IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, }, + [IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, }, }; /* @@ -422,7 +425,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) struct sk_buff *skb; unsigned char *rsp_data_ptr = NULL; int status = 0, rsp_data_len = 0; - u32 devid; + u32 devid, inst_size = 0, data_size = 0; switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: @@ -548,6 +551,41 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) "Error sending msg : %d\n", status); break; + case IWL_TM_CMD_APP2DEV_GET_FW_INFO: + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8); + if (!skb) { + IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + return -ENOMEM; + } + switch (priv->shrd->ucode_type) { + case IWL_UCODE_REGULAR: + inst_size = trans(priv)->ucode_rt.code.len; + data_size = trans(priv)->ucode_rt.data.len; + break; + case IWL_UCODE_INIT: + inst_size = trans(priv)->ucode_init.code.len; + data_size = trans(priv)->ucode_init.data.len; + break; + case IWL_UCODE_WOWLAN: + inst_size = trans(priv)->ucode_wowlan.code.len; + data_size = trans(priv)->ucode_wowlan.data.len; + break; + case IWL_UCODE_NONE: + IWL_DEBUG_INFO(priv, "The uCode has not been loaded\n"); + break; + default: + IWL_DEBUG_INFO(priv, "Unsupported uCode type\n"); + break; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type); + NLA_PUT_U32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size); + NLA_PUT_U32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size); + status = cfg80211_testmode_reply(skb); + if (status < 0) + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", status); + break; + default: IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); return -ENOSYS; @@ -881,6 +919,7 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: case IWL_TM_CMD_APP2DEV_GET_FW_VERSION: case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: + case IWL_TM_CMD_APP2DEV_GET_FW_INFO: IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); result = iwl_testmode_driver(hw, tb); break; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 9c6a67ab5c3..cb0cf35f91b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -120,6 +120,8 @@ * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Weak On Wireless LAN uCode image * @IWL_TM_CMD_APP2DEV_GET_FW_VERSION: retrieve uCode version * @IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: retrieve ID information in device + * @IWL_TM_CMD_APP2DEV_GET_FW_INFO: + * retrieve informration of existing loaded uCode image * */ enum iwl_tm_cmd_t { @@ -147,7 +149,8 @@ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW = 22, IWL_TM_CMD_APP2DEV_GET_FW_VERSION = 23, IWL_TM_CMD_APP2DEV_GET_DEVICE_ID = 24, - IWL_TM_CMD_MAX = 25, + IWL_TM_CMD_APP2DEV_GET_FW_INFO = 25, + IWL_TM_CMD_MAX = 26, }; /* @@ -237,6 +240,15 @@ enum iwl_tm_cmd_t { * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_DEVICE_ID, * IWL_TM_ATTR_DEVICE_ID for the device ID information * + * @IWL_TM_ATTR_FW_TYPE: + * @IWL_TM_ATTR_FW_INST_SIZE: + * @IWL_TM_ATTR_FW_DATA_SIZE: + * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_INFO, + * The mandatory fields are: + * IWL_TM_ATTR_FW_TYPE for the uCode type (INIT/RUNTIME/...) + * IWL_TM_ATTR_FW_INST_SIZE for the size of instruction section + * IWL_TM_ATTR_FW_DATA_SIZE for the size of data section + * */ enum iwl_tm_attr_t { IWL_TM_ATTR_NOT_APPLICABLE = 0, @@ -259,7 +271,10 @@ enum iwl_tm_attr_t { IWL_TM_ATTR_SRAM_DUMP = 17, IWL_TM_ATTR_FW_VERSION = 18, IWL_TM_ATTR_DEVICE_ID = 19, - IWL_TM_ATTR_MAX = 20, + IWL_TM_ATTR_FW_TYPE = 20, + IWL_TM_ATTR_FW_INST_SIZE = 21, + IWL_TM_ATTR_FW_DATA_SIZE = 22, + IWL_TM_ATTR_MAX = 23, }; /* uCode trace buffer */ -- cgit v1.2.3 From 4e3182626a914443a5e0fbe014813f03e51a75df Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 27 Dec 2011 11:21:32 -0800 Subject: iwlwifi: update Copyright Update Copyright to 2012 Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-2000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn-calib.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn-hw.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-bus.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-cfg.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-csr.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-debug.h | 2 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-devtrace.c | 2 +- drivers/net/wireless/iwlwifi/iwl-devtrace.h | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-fh.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-io.c | 2 +- drivers/net/wireless/iwlwifi/iwl-io.h | 2 +- drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 2 +- drivers/net/wireless/iwlwifi/iwl-pci.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-power.h | 2 +- drivers/net/wireless/iwlwifi/iwl-prph.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 6 +++--- drivers/net/wireless/iwlwifi/iwl-testmode.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-testmode.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-trans.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-trans.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-ucode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-wifi.h | 4 ++-- 53 files changed, 75 insertions(+), 75 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 1ef7bfc2ab2..cc04cce1156 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 094693328db..00db092d8cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index b3a365fea7b..47fd98b3652 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 54b753399e6..ab62c018fcd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 50ff849c9f6..6aa00982786 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h index 10275ce92bd..9ed6683314a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index 123ef5e129d..d0ec0abd3c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 64cf439035c..a8f7689aaac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 334b5ae8fdd..b9ba404d15c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 6675b3c816d..203b1c13c49 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index eda95ae88ef..f127f913e5a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portionhelp of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 1c665941662..8ca9570ec36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 8d4353a4256..d6aab00272b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index b0dff7a753a..56c6def015a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h index 7282a23e8f1..86bbf47501c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index c664c272655..a8c6880af34 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b5c7c5f0a75..7321e7d3140 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index f84fb3c5356..39cbe1a1577 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 940d5038b39..941b9cb2344 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-cfg.h b/drivers/net/wireless/iwlwifi/iwl-cfg.h index e1d78257e4a..957bc00cdaf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-cfg.h +++ b/drivers/net/wireless/iwlwifi/iwl-cfg.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 265de39d394..b4779c25a4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 7bcfa781e0b..7d6eef96454 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7bf76ab94dd..63f29111da1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index fbc3095c7b4..5f96ce105f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index f8fc2393dd4..6f7612781e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 04a3343f461..f837f32bb71 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index e54a4d11e58..4579d61da25 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index 2a2c8de64a0..91f45e71e0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2009 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 9b212a8f30b..4d892211ce4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2009 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index c1eda9724f4..e27d9f55267 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 9fa937ec35e..13f2d3928ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 5bede9d7f95..90208094b8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index d57ea6484bb..83fdff38115 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index aae2eeb331a..427d065435c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 14dcbfcdc0f..eca79087afb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 2550b3c7dcb..b02a853103d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index f980e574e1f..965d0475aff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index fb30ea7ca96..03702a2e913 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 2b188a6025b..c7394ef2e49 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 5f7b720cf1a..07a19fce5fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index bebdd828f32..a4d11016c3b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 084aa2c4ccf..2cd5b4f5993 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index dc55cc4a810..e406d49f418 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -102,7 +102,7 @@ struct iwl_trans_ops; #define DRV_NAME "iwlwifi" #define IWLWIFI_VERSION "in-tree:" -#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2012 Intel Corporation" #define DRV_AUTHOR "" extern struct iwl_mod_params iwlagn_mod_params; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 7684c0e2f21..a56a77b8f92 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index cb0cf35f91b..185b69ef753 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index f6debf91d7b..0ac9b4d3027 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 752493f0040..848c598bfad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index bd29568177e..30814b55705 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 67d6e324e26..5e6af4ba965 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 1b20c4fb791..506c062343b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index e6bf3f55477..42a9f303f54 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 36a1b5b2585..2edf0ef65a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-wifi.h b/drivers/net/wireless/iwlwifi/iwl-wifi.h index 18501101a53..7e6eb20823c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-wifi.h +++ b/drivers/net/wireless/iwlwifi/iwl-wifi.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without -- cgit v1.2.3 From 3f3c4ee735ff0957a53b9dccae66c8e5ead25b17 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 3 Jan 2012 14:41:59 +0530 Subject: ath6kl: Add a function in wmi to send WMI_MCAST_FILTER_CMDID This will be used to disable/enable multicast receive. Signed-off-by: Vasanthakumar Thiagarajan --- drivers/net/wireless/ath/ath6kl/wmi.c | 17 +++++++++++++++++ drivers/net/wireless/ath/ath6kl/wmi.h | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index c6ca660d270..d3eec0761ea 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -2855,6 +2855,23 @@ int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) return ret; } +int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on) +{ + struct sk_buff *skb; + struct wmi_mcast_filter_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_mcast_filter_cmd *) skb->data; + cmd->mcast_all_enable = mc_all_on; + + ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_MCAST_FILTER_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} s32 ath6kl_wmi_get_rate(s8 rate_index) { diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 2b435994b01..dc704571155 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -1239,6 +1239,10 @@ enum target_event_report_config { NO_DISCONN_EVT_IN_RECONN }; +struct wmi_mcast_filter_cmd { + u8 mcast_all_enable; +} __packed; + /* Command Replies */ /* WMI_GET_CHANNEL_LIST_CMDID reply */ @@ -2434,6 +2438,7 @@ int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); +int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); /* AP mode */ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, -- cgit v1.2.3 From f914edd38920369d8926261f9ab72da6756c3e0c Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 3 Jan 2012 14:42:00 +0530 Subject: ath6kl: Add a function in wmi.c to add/delete a multicast filter Signed-off-by: Vasanthakumar Thiagarajan --- drivers/net/wireless/ath/ath6kl/wmi.c | 28 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath6kl/wmi.h | 7 +++++++ 2 files changed, 35 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index d3eec0761ea..08fbd9a9be4 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -2873,6 +2873,34 @@ int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on) return ret; } +int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, + u8 *filter, bool add_filter) +{ + struct sk_buff *skb; + struct wmi_mcast_filter_add_del_cmd *cmd; + int ret; + + if ((filter[0] != 0x33 || filter[1] != 0x33) && + (filter[0] != 0x01 || filter[1] != 0x00 || + filter[2] != 0x5e || filter[3] > 0x7f)) { + ath6kl_warn("invalid multicast filter address\n"); + return -EINVAL; + } + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_mcast_filter_add_del_cmd *) skb->data; + memcpy(cmd->mcast_mac, filter, ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE); + ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, + add_filter ? WMI_SET_MCAST_FILTER_CMDID : + WMI_DEL_MCAST_FILTER_CMDID, + NO_SYNC_WMIFLAG); + + return ret; +} + s32 ath6kl_wmi_get_rate(s8 rate_index) { if (rate_index == RATE_AUTO) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index dc704571155..eae0e4e065c 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -1243,6 +1243,11 @@ struct wmi_mcast_filter_cmd { u8 mcast_all_enable; } __packed; +#define ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE 6 +struct wmi_mcast_filter_add_del_cmd { + u8 mcast_mac[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; +} __packed; + /* Command Replies */ /* WMI_GET_CHANNEL_LIST_CMDID reply */ @@ -2439,6 +2444,8 @@ int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); +int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, + u8 *filter, bool add_filter); /* AP mode */ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, -- cgit v1.2.3 From 80abaf9b4c920cab044e185ed4327f801c1ff99d Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 3 Jan 2012 14:42:01 +0530 Subject: ath6kl: Implement ndo_set_rx_mode() There are maximum of seven multicast filter are supported by hw. When the requested number of filters exceeds the maximum supported one, multicast filtering is completely disabled, the requested filters will be configured in firmware and the only multicast frames that host is interested in will be passed to host for further processing otherwise. Signed-off-by: Vasanthakumar Thiagarajan --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 8 +++ drivers/net/wireless/ath/ath6kl/core.h | 9 +++ drivers/net/wireless/ath/ath6kl/main.c | 110 +++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 2a166cc7cc3..14f180eac48 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2818,12 +2818,15 @@ static int ath6kl_init_if_data(struct ath6kl_vif *vif) set_bit(WMM_ENABLED, &vif->flags); spin_lock_init(&vif->if_lock); + INIT_LIST_HEAD(&vif->mc_filter); + return 0; } void ath6kl_deinit_if_data(struct ath6kl_vif *vif) { struct ath6kl *ar = vif->ar; + struct ath6kl_mc_filter *mc_filter, *tmp; aggr_module_destroy(vif->aggr_cntxt); @@ -2832,6 +2835,11 @@ void ath6kl_deinit_if_data(struct ath6kl_vif *vif) if (vif->nw_type == ADHOC_NETWORK) ar->ibss_if_active = false; + list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { + list_del(&mc_filter->list); + kfree(mc_filter); + } + unregister_netdevice(vif->ndev); ar->num_vif--; diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index c095fafa278..793c6a58f0f 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -410,6 +410,13 @@ enum ath6kl_hif_type { ATH6KL_HIF_TYPE_USB, }; +/* Max number of filters that hw supports */ +#define ATH6K_MAX_MC_FILTERS_PER_LIST 7 +struct ath6kl_mc_filter { + struct list_head list; + char hw_addr[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; +}; + /* * Driver's maximum limit, note that some firmwares support only one vif * and the runtime (current) limit must be checked from ar->vif_max. @@ -473,6 +480,8 @@ struct ath6kl_vif { u8 assoc_bss_dtim_period; struct net_device_stats net_stats; struct target_stats target_stats; + + struct list_head mc_filter; }; #define WOW_LIST_ID 0 diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index f74986d6209..cffbc62ee79 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1052,12 +1052,122 @@ static int ath6kl_set_features(struct net_device *dev, u32 features) return err; } +static void ath6kl_set_multicast_list(struct net_device *ndev) +{ + struct ath6kl_vif *vif = netdev_priv(ndev); + bool mc_all_on = false, mc_all_off = false; + int mc_count = netdev_mc_count(ndev); + struct netdev_hw_addr *ha; + bool found; + struct ath6kl_mc_filter *mc_filter, *tmp; + struct list_head mc_filter_new; + int ret; + + if (!test_bit(WMI_READY, &vif->ar->flag) || + !test_bit(WLAN_ENABLED, &vif->flags)) + return; + + mc_all_on = !!(ndev->flags & IFF_PROMISC) || + !!(ndev->flags & IFF_ALLMULTI) || + !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST); + + mc_all_off = !(ndev->flags & IFF_MULTICAST) || mc_count == 0; + + if (mc_all_on || mc_all_off) { + /* Enable/disable all multicast */ + ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n", + mc_all_on ? "enabling" : "disabling"); + ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, + mc_all_on); + if (ret) + ath6kl_warn("Failed to %s multicast receive\n", + mc_all_on ? "enable" : "disable"); + return; + } + + list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { + found = false; + netdev_for_each_mc_addr(ha, ndev) { + if (memcmp(ha->addr, mc_filter->hw_addr, + ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) { + found = true; + break; + } + } + + if (!found) { + /* + * Delete the filter which was previously set + * but not in the new request. + */ + ath6kl_dbg(ATH6KL_DBG_TRC, + "Removing %pM from multicast filter\n", + mc_filter->hw_addr); + ret = ath6kl_wmi_add_del_mcast_filter_cmd(vif->ar->wmi, + vif->fw_vif_idx, mc_filter->hw_addr, + false); + if (ret) { + ath6kl_warn("Failed to remove multicast filter:%pM\n", + mc_filter->hw_addr); + return; + } + + list_del(&mc_filter->list); + kfree(mc_filter); + } + } + + INIT_LIST_HEAD(&mc_filter_new); + + netdev_for_each_mc_addr(ha, ndev) { + found = false; + list_for_each_entry(mc_filter, &vif->mc_filter, list) { + if (memcmp(ha->addr, mc_filter->hw_addr, + ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) { + found = true; + break; + } + } + + if (!found) { + mc_filter = kzalloc(sizeof(struct ath6kl_mc_filter), + GFP_ATOMIC); + if (!mc_filter) { + WARN_ON(1); + goto out; + } + + memcpy(mc_filter->hw_addr, ha->addr, + ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE); + /* Set the multicast filter */ + ath6kl_dbg(ATH6KL_DBG_TRC, + "Adding %pM to multicast filter list\n", + mc_filter->hw_addr); + ret = ath6kl_wmi_add_del_mcast_filter_cmd(vif->ar->wmi, + vif->fw_vif_idx, mc_filter->hw_addr, + true); + if (ret) { + ath6kl_warn("Failed to add multicast filter :%pM\n", + mc_filter->hw_addr); + kfree(mc_filter); + goto out; + } + + list_add_tail(&mc_filter->list, &mc_filter_new); + } + } + +out: + list_splice_tail(&mc_filter_new, &vif->mc_filter); +} + static struct net_device_ops ath6kl_netdev_ops = { .ndo_open = ath6kl_open, .ndo_stop = ath6kl_close, .ndo_start_xmit = ath6kl_data_tx, .ndo_get_stats = ath6kl_get_stats, .ndo_set_features = ath6kl_set_features, + .ndo_set_rx_mode = ath6kl_set_multicast_list, }; void init_netdev(struct net_device *dev) -- cgit v1.2.3 From 3d6aba260bcd5a5f9d47056cac2e313ce986ad12 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 3 Jan 2012 15:19:02 +0530 Subject: ath6kl: Remove deadcode in main.c In ath6kl_reset_device(), since control can never reach switch..case when the target_type is neither TARGET_TYPE_AR6003 nor TARGET_TYPE_AR6004, remove the default option of switch statement. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index cffbc62ee79..d764768f8f7 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -347,9 +347,6 @@ void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, case TARGET_TYPE_AR6004: address = AR6004_RESET_CONTROL_ADDRESS; break; - default: - address = AR6003_RESET_CONTROL_ADDRESS; - break; } status = ath6kl_diag_write32(ar, address, data); -- cgit v1.2.3 From 982767b8c94482b4b7f694e2ab2074c95fbf3e0e Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 3 Jan 2012 15:28:53 +0530 Subject: ath6kl: Change ielen in ath6kl_add_new_sta() from u8 to size_t Otherwise if (ielen <= ATH6KL_MAX_IE) is dead code. It looks safe to change the type of ielen from u8 to size_t instead of removing this if check, this ielen can have the length of more than one ies in future. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index d764768f8f7..325d316f40e 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -53,7 +53,7 @@ struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid) } static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, - u8 ielen, u8 keymgmt, u8 ucipher, u8 auth) + size_t ielen, u8 keymgmt, u8 ucipher, u8 auth) { struct ath6kl_sta *sta; u8 free_slot; -- cgit v1.2.3 From 9d82682d45ef7407474e0ae043a587cb33a7fa26 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 4 Jan 2012 15:57:19 +0530 Subject: ath6kl: Use a mutex_lock to avoid race in diabling and handling irq Currently this race is handled but in a messy way an atomic variable is being checked in a loop which sleeps upto ms in every iteration. Remove this logic and use a mutex to make sure irq is not disabled when irq handling is in progress. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/sdio.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 278a9f30795..8b36904ec3e 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -49,11 +49,13 @@ struct ath6kl_sdio { /* scatter request list head */ struct list_head scat_req; + /* Avoids disabling irq while the interrupts being handled */ + struct mutex mtx_irq; + spinlock_t scat_lock; bool scatter_enabled; bool is_disabled; - atomic_t irq_handling; const struct sdio_device_id *id; struct work_struct wr_async_work; struct list_head wr_asyncq; @@ -460,8 +462,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); ar_sdio = sdio_get_drvdata(func); - atomic_set(&ar_sdio->irq_handling, 1); - + mutex_lock(&ar_sdio->mtx_irq); /* * Release the host during interrups so we can pick it back up when * we process commands. @@ -470,7 +471,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) status = ath6kl_hif_intr_bh_handler(ar_sdio->ar); sdio_claim_host(ar_sdio->func); - atomic_set(&ar_sdio->irq_handling, 0); + mutex_unlock(&ar_sdio->mtx_irq); WARN_ON(status && status != -ECANCELED); } @@ -578,17 +579,14 @@ static void ath6kl_sdio_irq_disable(struct ath6kl *ar) sdio_claim_host(ar_sdio->func); - /* Mask our function IRQ */ - while (atomic_read(&ar_sdio->irq_handling)) { - sdio_release_host(ar_sdio->func); - schedule_timeout(HZ / 10); - sdio_claim_host(ar_sdio->func); - } + mutex_lock(&ar_sdio->mtx_irq); ret = sdio_release_irq(ar_sdio->func); if (ret) ath6kl_err("Failed to release sdio irq: %d\n", ret); + mutex_unlock(&ar_sdio->mtx_irq); + sdio_release_host(ar_sdio->func); } @@ -1253,6 +1251,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, spin_lock_init(&ar_sdio->scat_lock); spin_lock_init(&ar_sdio->wr_async_lock); mutex_init(&ar_sdio->dma_buffer_mutex); + mutex_init(&ar_sdio->mtx_irq); INIT_LIST_HEAD(&ar_sdio->scat_req); INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); -- cgit v1.2.3 From 4269a930548966014dd4186a15c8e023ca4abc29 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 5 Jan 2012 10:39:48 -0800 Subject: ath6kl: make net_device_ops const Signed-off-by: Stephen Hemminger Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 325d316f40e..8742eaa7818 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1158,7 +1158,7 @@ out: list_splice_tail(&mc_filter_new, &vif->mc_filter); } -static struct net_device_ops ath6kl_netdev_ops = { +static const struct net_device_ops ath6kl_netdev_ops = { .ndo_open = ath6kl_open, .ndo_stop = ath6kl_close, .ndo_start_xmit = ath6kl_data_tx, -- cgit v1.2.3 From 866dc88607aa07f297eec7b504be58ca17d91a26 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 10 Jan 2012 09:53:23 +0530 Subject: ath6kl: Fix SDIO error path sdio_release_host() would be called twice if sdio_set_block_size() fails for some reason, which would result in the following warning. WARNING: at /home/sujith/dev/wireless-testing/drivers/mmc/core/core.c:828 mmc_release_host+0x42/0x50 [mmc_core]() Call Trace: [] warn_slowpath_common+0x7f/0xc0 [] warn_slowpath_null+0x1a/0x20 [] mmc_release_host+0x42/0x50 [mmc_core] [] sdio_release_host+0x1e/0x30 [mmc_core] [] ath6kl_sdio_config+0xc7/0x110 [ath6kl_sdio] [] ath6kl_sdio_probe+0x21c/0x320 [ath6kl_sdio] [] ? mmc_release_host+0x2a/0x50 [mmc_core] [] sdio_bus_probe+0xfa/0x130 [mmc_core] [] driver_probe_device+0x7e/0x1b0 [] __driver_attach+0xab/0xb0 [] ? driver_probe_device+0x1b0/0x1b0 [] ? driver_probe_device+0x1b0/0x1b0 [] bus_for_each_dev+0x64/0xa0 [] driver_attach+0x1e/0x20 [] bus_add_driver+0x1b0/0x280 [] ? 0xffffffffa0064fff [] driver_register+0x76/0x140 [] ? 0xffffffffa0064fff [] sdio_register_driver+0x21/0x30 [mmc_core] [] ath6kl_sdio_init+0x12/0x35 [ath6kl_sdio] [] do_one_initcall+0x42/0x180 [] sys_init_module+0x8f/0x200 [] system_call_fastpath+0x16/0x1b Signed-off-by: Sujith Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/sdio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 8b36904ec3e..50b19d3aefa 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -770,7 +770,6 @@ static int ath6kl_sdio_config(struct ath6kl *ar) if (ret) { ath6kl_err("Set sdio block size %d failed: %d)\n", HIF_MBOX_BLOCK_SIZE, ret); - sdio_release_host(func); goto out; } -- cgit v1.2.3 From 4a8ce2fd055f8c117fb6fa6da39af8f62cbffe4b Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 10 Jan 2012 09:53:38 +0530 Subject: ath6kl: Remove redundant pointer check 'params' is already used earlier and there is no point in checking for a NULL condition again. Signed-off-by: Sujith Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 31 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 14f180eac48..9b26bbaf124 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -983,6 +983,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, struct ath6kl *ar = ath6kl_priv(ndev); struct ath6kl_vif *vif = netdev_priv(ndev); struct ath6kl_key *key = NULL; + int seq_len; u8 key_usage; u8 key_type; @@ -1011,23 +1012,21 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, else key_usage = GROUP_USAGE; - if (params) { - int seq_len = params->seq_len; - if (params->cipher == WLAN_CIPHER_SUITE_SMS4 && - seq_len > ATH6KL_KEY_SEQ_LEN) { - /* Only first half of the WPI PN is configured */ - seq_len = ATH6KL_KEY_SEQ_LEN; - } - if (params->key_len > WLAN_MAX_KEY_LEN || - seq_len > sizeof(key->seq)) - return -EINVAL; - - key->key_len = params->key_len; - memcpy(key->key, params->key, key->key_len); - key->seq_len = seq_len; - memcpy(key->seq, params->seq, key->seq_len); - key->cipher = params->cipher; + seq_len = params->seq_len; + if (params->cipher == WLAN_CIPHER_SUITE_SMS4 && + seq_len > ATH6KL_KEY_SEQ_LEN) { + /* Only first half of the WPI PN is configured */ + seq_len = ATH6KL_KEY_SEQ_LEN; } + if (params->key_len > WLAN_MAX_KEY_LEN || + seq_len > sizeof(key->seq)) + return -EINVAL; + + key->key_len = params->key_len; + memcpy(key->key, params->key, key->key_len); + key->seq_len = seq_len; + memcpy(key->seq, params->seq, key->seq_len); + key->cipher = params->cipher; switch (key->cipher) { case WLAN_CIPHER_SUITE_WEP40: -- cgit v1.2.3 From cbec267a5143f70ece4069d18889a442bcb3365b Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 10 Jan 2012 09:53:53 +0530 Subject: ath6kl: Initialize a variable properly This prevents 'comp_pktq' from being used in an incorrect manner. Signed-off-by: Sujith Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/htc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c index b01702258fa..2d721903640 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.c +++ b/drivers/net/wireless/ath/ath6kl/htc.c @@ -2062,6 +2062,7 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, enum htc_endpoint_id id; int n_fetched = 0; + INIT_LIST_HEAD(&comp_pktq); *num_pkts = 0; /* -- cgit v1.2.3 From 8232736dabd2a0310f76944fa7af0542fe3ded4f Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 10 Jan 2012 09:54:10 +0530 Subject: ath6kl: Fix listen interval handling This patch addresses a few problems with the commit: "ath6kl: Implement support for listen interval from userspace" * The debugfs file required for reading/writing the listen interval wasn't created. Fix this. * The interface index was being hardcoded to zero. Fix this. * Two separate parameters, "listen_interval_time and listen_interval_beacons" were being used. This fails to work as expected because the FW assigns higher precedence to "listen_interval_beacons" and "listen_interval_time" ends up being never used at all. To handle this, fix the host driver to exclusively use listen interval based on units of beacon intervals. To set the listen interval, a user would now do something like this: echo "10" > /sys/kernel/debug/ieee80211/*/ath6kl/listen_interval kvalo: fix two checkpatch warnings Signed-off-by: Sujith Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 3 +- drivers/net/wireless/ath/ath6kl/core.h | 3 +- drivers/net/wireless/ath/ath6kl/debug.c | 44 ++++++++++++------------------ drivers/net/wireless/ath/ath6kl/main.c | 7 +++-- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 9b26bbaf124..1a98c9256c6 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2725,8 +2725,7 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev) clear_bit(SKIP_SCAN, &ar->flag); clear_bit(DESTROY_IN_PROGRESS, &ar->flag); - ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL; - ar->listen_intvl_b = 0; + ar->listen_intvl_b = A_DEFAULT_LISTEN_INTERVAL; ar->tx_pwr = 0; ar->intra_bss = 1; diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 793c6a58f0f..f4da5e19a36 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -55,7 +55,7 @@ #define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC) #define DISCON_TIMER_INTVAL 10000 /* in msec */ -#define A_DEFAULT_LISTEN_INTERVAL 100 +#define A_DEFAULT_LISTEN_INTERVAL 1 /* beacon intervals */ #define A_MAX_WOW_LISTEN_INTERVAL 1000 /* includes also the null byte */ @@ -534,7 +534,6 @@ struct ath6kl { spinlock_t lock; struct semaphore sem; u16 listen_intvl_b; - u16 listen_intvl_t; u8 lrssi_roam_threshold; struct ath6kl_version version; u32 target_type; diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index eb808b46f94..fa7243b4144 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -1505,57 +1505,46 @@ static const struct file_operations fops_bgscan_int = { }; static ssize_t ath6kl_listen_int_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) + const char __user *user_buf, + size_t count, loff_t *ppos) { struct ath6kl *ar = file->private_data; - u16 listen_int_t, listen_int_b; + struct ath6kl_vif *vif; + u16 listen_interval; char buf[32]; - char *sptr, *token; ssize_t len; + vif = ath6kl_vif_first(ar); + if (!vif) + return -EIO; + len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; - sptr = buf; - - token = strsep(&sptr, " "); - if (!token) - return -EINVAL; - - if (kstrtou16(token, 0, &listen_int_t)) - return -EINVAL; - - if (kstrtou16(sptr, 0, &listen_int_b)) - return -EINVAL; - - if ((listen_int_t < 15) || (listen_int_t > 5000)) + if (kstrtou16(buf, 0, &listen_interval)) return -EINVAL; - if ((listen_int_b < 1) || (listen_int_b > 50)) + if ((listen_interval < 1) || (listen_interval > 50)) return -EINVAL; - ar->listen_intvl_t = listen_int_t; - ar->listen_intvl_b = listen_int_b; - - ath6kl_wmi_listeninterval_cmd(ar->wmi, 0, ar->listen_intvl_t, + ar->listen_intvl_b = listen_interval; + ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 0, ar->listen_intvl_b); return count; } static ssize_t ath6kl_listen_int_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) + char __user *user_buf, + size_t count, loff_t *ppos) { struct ath6kl *ar = file->private_data; char buf[32]; int len; - len = scnprintf(buf, sizeof(buf), "%u %u\n", ar->listen_intvl_t, - ar->listen_intvl_b); + len = scnprintf(buf, sizeof(buf), "%u\n", ar->listen_intvl_b); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -1710,6 +1699,9 @@ int ath6kl_debug_init(struct ath6kl *ar) debugfs_create_file("bgscan_interval", S_IWUSR, ar->debugfs_phy, ar, &fops_bgscan_int); + debugfs_create_file("listen_interval", S_IRUSR | S_IWUSR, + ar->debugfs_phy, ar, &fops_listen_int); + debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar, &fops_power_params); diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 8742eaa7818..4c26572214c 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -584,10 +584,11 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, memcpy(vif->bssid, bssid, sizeof(vif->bssid)); vif->bss_ch = channel; - if ((vif->nw_type == INFRA_NETWORK)) + if ((vif->nw_type == INFRA_NETWORK)) { + ar->listen_intvl_b = listen_int; ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, - ar->listen_intvl_t, - ar->listen_intvl_b); + 0, ar->listen_intvl_b); + } netif_wake_queue(vif->ndev); -- cgit v1.2.3 From c1762a3fe196483981f91b926f5f6ee18af757f2 Mon Sep 17 00:00:00 2001 From: Thirumalai Pachamuthu Date: Thu, 12 Jan 2012 18:21:39 +0530 Subject: ath6kl: Add support for uAPSD * A new APSD power save queue is added in the station structure. * When a station has APSD capability and goes to power save, the frame designated to the station will be buffered in APSD queue. * When the host receives a frame which the firmware marked as trigger, host delivers the buffered frame from the APSD power save queue. Number of frames to deliver is decided by MAX SP length. * When a station moves from sleep to awake state, all frames buffered in APSD power save queue are sent to the firmware. * When a station is disconnected, all frames bufferes in APSD power save queue are dropped. * When the host queues the first frame to the APSD queue or removes the last frame from the APSD queue, it is indicated to the firmware using WMI_AP_APSD_BUFFERED_TRAFFIC_CMD. kvalo: fix buggy handling of sks queues, made it more obvious the user priority when wmm is disabled, remove unneed else block and combined some variable declarations Signed-off-by: Thirumalai Pachamuthu Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 6 + drivers/net/wireless/ath/ath6kl/core.h | 10 +- drivers/net/wireless/ath/ath6kl/main.c | 9 +- drivers/net/wireless/ath/ath6kl/txrx.c | 249 ++++++++++++++++++++++++----- drivers/net/wireless/ath/ath6kl/wmi.c | 62 ++++++- drivers/net/wireless/ath/ath6kl/wmi.h | 41 ++++- 6 files changed, 324 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 1a98c9256c6..a13ecec0070 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2253,6 +2253,11 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, p.dot11_auth_mode = vif->dot11_auth_mode; p.ch = cpu_to_le16(vif->next_chan); + /* Enable uAPSD support by default */ + res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true); + if (res < 0) + return res; + if (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { p.nw_subtype = SUBTYPE_P2PGO; } else { @@ -2740,6 +2745,7 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev) for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { spin_lock_init(&ar->sta_list[ctr].psq_lock); skb_queue_head_init(&ar->sta_list[ctr].psq); + skb_queue_head_init(&ar->sta_list[ctr].apsdq); } skb_queue_head_init(&ar->mcastpsq); diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index f4da5e19a36..ba3953918e4 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -44,6 +44,10 @@ #define ATH6KL_MAX_ENDPOINTS 4 #define MAX_NODE_NUM 15 +#define ATH6KL_APSD_ALL_FRAME 0xFFFF +#define ATH6KL_APSD_NUM_OF_AC 0x4 +#define ATH6KL_APSD_FRAME_MASK 0xF + /* Extra bytes for htc header alignment */ #define ATH6KL_HTC_ALIGN_BYTES 3 @@ -146,6 +150,8 @@ struct ath6kl_fw_ie { #define STA_PS_AWAKE BIT(0) #define STA_PS_SLEEP BIT(1) #define STA_PS_POLLED BIT(2) +#define STA_PS_APSD_TRIGGER BIT(3) +#define STA_PS_APSD_EOSP BIT(4) /* HTC TX packet tagging definitions */ #define ATH6KL_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED @@ -282,6 +288,8 @@ struct ath6kl_sta { u8 wpa_ie[ATH6KL_MAX_IE]; struct sk_buff_head psq; spinlock_t psq_lock; + u8 apsd_info; + struct sk_buff_head apsdq; }; struct ath6kl_version { @@ -714,7 +722,7 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel); void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, u8 keymgmt, u8 ucipher, u8 auth, - u8 assoc_req_len, u8 *assoc_info); + u8 assoc_req_len, u8 *assoc_info, u8 apsd_info); void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid, u8 assoc_resp_len, u8 *assoc_info, u16 prot_reason_status); diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 4c26572214c..53f97db4a7a 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -53,7 +53,8 @@ struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid) } static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, - size_t ielen, u8 keymgmt, u8 ucipher, u8 auth) + size_t ielen, u8 keymgmt, u8 ucipher, u8 auth, + u8 apsd_info) { struct ath6kl_sta *sta; u8 free_slot; @@ -68,6 +69,7 @@ static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, sta->keymgmt = keymgmt; sta->ucipher = ucipher; sta->auth = auth; + sta->apsd_info = apsd_info; ar->sta_list_index = ar->sta_list_index | (1 << free_slot); ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid); @@ -80,6 +82,7 @@ static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) /* empty the queued pkts in the PS queue if any */ spin_lock_bh(&sta->psq_lock); skb_queue_purge(&sta->psq); + skb_queue_purge(&sta->apsdq); spin_unlock_bh(&sta->psq_lock); memset(&ar->ap_stats.sta[sta->aid - 1], 0, @@ -425,7 +428,7 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel) void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, u8 keymgmt, u8 ucipher, u8 auth, - u8 assoc_req_len, u8 *assoc_info) + u8 assoc_req_len, u8 *assoc_info, u8 apsd_info) { struct ath6kl *ar = vif->ar; u8 *ies = NULL, *wpa_ie = NULL, *pos; @@ -483,7 +486,7 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, ath6kl_add_new_sta(ar, mac_addr, aid, wpa_ie, wpa_ie ? 2 + wpa_ie[1] : 0, - keymgmt, ucipher, auth); + keymgmt, ucipher, auth, apsd_info); /* send event to application */ memset(&sinfo, 0, sizeof(sinfo)); diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index fcea82479cd..91bbc1ffa49 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -77,12 +77,120 @@ static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, return ar->node_map[ep_map].ep_id; } +static bool ath6kl_process_uapsdq(struct ath6kl_sta *conn, + struct ath6kl_vif *vif, + struct sk_buff *skb, + u32 *flags) +{ + struct ath6kl *ar = vif->ar; + bool is_apsdq_empty = false; + struct ethhdr *datap = (struct ethhdr *) skb->data; + u8 up, traffic_class, *ip_hdr; + u16 ether_type; + struct ath6kl_llc_snap_hdr *llc_hdr; + + if (conn->sta_flags & STA_PS_APSD_TRIGGER) { + /* + * This tx is because of a uAPSD trigger, determine + * more and EOSP bit. Set EOSP if queue is empty + * or sufficient frames are delivered for this trigger. + */ + spin_lock_bh(&conn->psq_lock); + if (!skb_queue_empty(&conn->apsdq)) + *flags |= WMI_DATA_HDR_FLAGS_MORE; + else if (conn->sta_flags & STA_PS_APSD_EOSP) + *flags |= WMI_DATA_HDR_FLAGS_EOSP; + *flags |= WMI_DATA_HDR_FLAGS_UAPSD; + spin_unlock_bh(&conn->psq_lock); + return false; + } else if (!conn->apsd_info) + return false; + + if (test_bit(WMM_ENABLED, &vif->flags)) { + ether_type = be16_to_cpu(datap->h_proto); + if (is_ethertype(ether_type)) { + /* packet is in DIX format */ + ip_hdr = (u8 *)(datap + 1); + } else { + /* packet is in 802.3 format */ + llc_hdr = (struct ath6kl_llc_snap_hdr *) + (datap + 1); + ether_type = be16_to_cpu(llc_hdr->eth_type); + ip_hdr = (u8 *)(llc_hdr + 1); + } + + if (ether_type == IP_ETHERTYPE) + up = ath6kl_wmi_determine_user_priority( + ip_hdr, 0); + } else { + up = 0; + } + + traffic_class = ath6kl_wmi_get_traffic_class(up); + + if ((conn->apsd_info & (1 << traffic_class)) == 0) + return false; + + /* Queue the frames if the STA is sleeping */ + spin_lock_bh(&conn->psq_lock); + is_apsdq_empty = skb_queue_empty(&conn->apsdq); + skb_queue_tail(&conn->apsdq, skb); + spin_unlock_bh(&conn->psq_lock); + + /* + * If this is the first pkt getting queued + * for this STA, update the PVB for this STA + */ + if (is_apsdq_empty) { + ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi, + vif->fw_vif_idx, + conn->aid, 1, 0); + } + *flags |= WMI_DATA_HDR_FLAGS_UAPSD; + + return true; +} + +static bool ath6kl_process_psq(struct ath6kl_sta *conn, + struct ath6kl_vif *vif, + struct sk_buff *skb, + u32 *flags) +{ + bool is_psq_empty = false; + struct ath6kl *ar = vif->ar; + + if (conn->sta_flags & STA_PS_POLLED) { + spin_lock_bh(&conn->psq_lock); + if (!skb_queue_empty(&conn->psq)) + *flags |= WMI_DATA_HDR_FLAGS_MORE; + spin_unlock_bh(&conn->psq_lock); + return false; + } + + /* Queue the frames if the STA is sleeping */ + spin_lock_bh(&conn->psq_lock); + is_psq_empty = skb_queue_empty(&conn->psq); + skb_queue_tail(&conn->psq, skb); + spin_unlock_bh(&conn->psq_lock); + + /* + * If this is the first pkt getting queued + * for this STA, update the PVB for this + * STA. + */ + if (is_psq_empty) + ath6kl_wmi_set_pvb_cmd(ar->wmi, + vif->fw_vif_idx, + conn->aid, 1); + return true; +} + static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb, - bool *more_data) + u32 *flags) { struct ethhdr *datap = (struct ethhdr *) skb->data; struct ath6kl_sta *conn = NULL; - bool ps_queued = false, is_psq_empty = false; + bool ps_queued = false; struct ath6kl *ar = vif->ar; if (is_multicast_ether_addr(datap->h_dest)) { @@ -128,7 +236,7 @@ static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb, */ spin_lock_bh(&ar->mcastpsq_lock); if (!skb_queue_empty(&ar->mcastpsq)) - *more_data = true; + *flags |= WMI_DATA_HDR_FLAGS_MORE; spin_unlock_bh(&ar->mcastpsq_lock); } } @@ -142,37 +250,13 @@ static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb, } if (conn->sta_flags & STA_PS_SLEEP) { - if (!(conn->sta_flags & STA_PS_POLLED)) { - /* Queue the frames if the STA is sleeping */ - spin_lock_bh(&conn->psq_lock); - is_psq_empty = skb_queue_empty(&conn->psq); - skb_queue_tail(&conn->psq, skb); - spin_unlock_bh(&conn->psq_lock); - - /* - * If this is the first pkt getting queued - * for this STA, update the PVB for this - * STA. - */ - if (is_psq_empty) - ath6kl_wmi_set_pvb_cmd(ar->wmi, - vif->fw_vif_idx, - conn->aid, 1); - - ps_queued = true; - } else { - /* - * This tx is because of a PsPoll. - * Determine if MoreData bit has to be set. - */ - spin_lock_bh(&conn->psq_lock); - if (!skb_queue_empty(&conn->psq)) - *more_data = true; - spin_unlock_bh(&conn->psq_lock); - } + ps_queued = ath6kl_process_uapsdq(conn, + vif, skb, flags); + if (!(*flags & WMI_DATA_HDR_FLAGS_UAPSD)) + ps_queued = ath6kl_process_psq(conn, + vif, skb, flags); } } - return ps_queued; } @@ -242,12 +326,13 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) u32 map_no = 0; u16 htc_tag = ATH6KL_DATA_PKT_TAG; u8 ac = 99 ; /* initialize to unmapped ac */ - bool chk_adhoc_ps_mapping = false, more_data = false; + bool chk_adhoc_ps_mapping = false; int ret; struct wmi_tx_meta_v2 meta_v2; void *meta; u8 csum_start = 0, csum_dest = 0, csum = skb->ip_summed; u8 meta_ver = 0; + u32 flags = 0; ath6kl_dbg(ATH6KL_DBG_WLAN_TX, "%s: skb=0x%p, data=0x%p, len=0x%x\n", __func__, @@ -264,7 +349,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) /* AP mode Power saving processing */ if (vif->nw_type == AP_NETWORK) { - if (ath6kl_powersave_ap(vif, skb, &more_data)) + if (ath6kl_powersave_ap(vif, skb, &flags)) return 0; } @@ -308,7 +393,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) } ret = ath6kl_wmi_data_hdr_add(ar->wmi, skb, - DATA_MSGTYPE, more_data, 0, + DATA_MSGTYPE, flags, 0, meta_ver, meta, vif->fw_vif_idx); @@ -1093,6 +1178,76 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, return is_queued; } +static void ath6kl_uapsd_trigger_frame_rx(struct ath6kl_vif *vif, + struct ath6kl_sta *conn) +{ + struct ath6kl *ar = vif->ar; + bool is_apsdq_empty, is_apsdq_empty_at_start; + u32 num_frames_to_deliver, flags; + struct sk_buff *skb = NULL; + + /* + * If the APSD q for this STA is not empty, dequeue and + * send a pkt from the head of the q. Also update the + * More data bit in the WMI_DATA_HDR if there are + * more pkts for this STA in the APSD q. + * If there are no more pkts for this STA, + * update the APSD bitmap for this STA. + */ + + num_frames_to_deliver = (conn->apsd_info >> ATH6KL_APSD_NUM_OF_AC) & + ATH6KL_APSD_FRAME_MASK; + /* + * Number of frames to send in a service period is + * indicated by the station + * in the QOS_INFO of the association request + * If it is zero, send all frames + */ + if (!num_frames_to_deliver) + num_frames_to_deliver = ATH6KL_APSD_ALL_FRAME; + + spin_lock_bh(&conn->psq_lock); + is_apsdq_empty = skb_queue_empty(&conn->apsdq); + spin_unlock_bh(&conn->psq_lock); + is_apsdq_empty_at_start = is_apsdq_empty; + + while ((!is_apsdq_empty) && (num_frames_to_deliver)) { + + spin_lock_bh(&conn->psq_lock); + skb = skb_dequeue(&conn->apsdq); + is_apsdq_empty = skb_queue_empty(&conn->apsdq); + spin_unlock_bh(&conn->psq_lock); + + /* + * Set the STA flag to Trigger delivery, + * so that the frame will go out + */ + conn->sta_flags |= STA_PS_APSD_TRIGGER; + num_frames_to_deliver--; + + /* Last frame in the service period, set EOSP or queue empty */ + if ((is_apsdq_empty) || (!num_frames_to_deliver)) + conn->sta_flags |= STA_PS_APSD_EOSP; + + ath6kl_data_tx(skb, vif->ndev); + conn->sta_flags &= ~(STA_PS_APSD_TRIGGER); + conn->sta_flags &= ~(STA_PS_APSD_EOSP); + } + + if (is_apsdq_empty) { + if (is_apsdq_empty_at_start) + flags = WMI_AP_APSD_NO_DELIVERY_FRAMES; + else + flags = 0; + + ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi, + vif->fw_vif_idx, + conn->aid, 0, flags); + } + + return; +} + void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) { struct ath6kl *ar = target->dev->ar; @@ -1104,6 +1259,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) int status = packet->status; enum htc_endpoint_id ept = packet->endpoint; bool is_amsdu, prev_ps, ps_state = false; + bool trig_state = false; struct ath6kl_sta *conn = NULL; struct sk_buff *skb1 = NULL; struct ethhdr *datap = NULL; @@ -1197,6 +1353,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) WMI_DATA_HDR_PS_MASK); offset = sizeof(struct wmi_data_hdr); + trig_state = !!(le16_to_cpu(dhdr->info3) & WMI_DATA_HDR_TRIG); switch (meta_type) { case 0: @@ -1235,18 +1392,36 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) else conn->sta_flags &= ~STA_PS_SLEEP; + /* Accept trigger only when the station is in sleep */ + if ((conn->sta_flags & STA_PS_SLEEP) && trig_state) + ath6kl_uapsd_trigger_frame_rx(vif, conn); + if (prev_ps ^ !!(conn->sta_flags & STA_PS_SLEEP)) { if (!(conn->sta_flags & STA_PS_SLEEP)) { struct sk_buff *skbuff = NULL; + bool is_apsdq_empty; spin_lock_bh(&conn->psq_lock); - while ((skbuff = skb_dequeue(&conn->psq)) - != NULL) { + while ((skbuff = skb_dequeue(&conn->psq))) { + spin_unlock_bh(&conn->psq_lock); + ath6kl_data_tx(skbuff, vif->ndev); + spin_lock_bh(&conn->psq_lock); + } + + is_apsdq_empty = skb_queue_empty(&conn->apsdq); + while ((skbuff = skb_dequeue(&conn->apsdq))) { spin_unlock_bh(&conn->psq_lock); ath6kl_data_tx(skbuff, vif->ndev); spin_lock_bh(&conn->psq_lock); } spin_unlock_bh(&conn->psq_lock); + + if (!is_apsdq_empty) + ath6kl_wmi_set_apsd_bfrd_traf( + ar->wmi, + vif->fw_vif_idx, + conn->aid, 0, 0); + /* Clear the PVB for this STA */ ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx, conn->aid, 0); diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 08fbd9a9be4..c2420f886ed 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -180,7 +180,7 @@ static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb, } int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, - u8 msg_type, bool more_data, + u8 msg_type, u32 flags, enum wmi_data_hdr_data_type data_type, u8 meta_ver, void *tx_meta_info, u8 if_idx) { @@ -204,17 +204,19 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT; data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT; - if (more_data) - data_hdr->info |= - WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT; + if (flags & WMI_DATA_HDR_FLAGS_MORE) + data_hdr->info |= WMI_DATA_HDR_MORE; - data_hdr->info2 = cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT); - data_hdr->info3 = cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK); + if (flags & WMI_DATA_HDR_FLAGS_EOSP) + data_hdr->info3 |= cpu_to_le16(WMI_DATA_HDR_EOSP); + + data_hdr->info2 |= cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT); + data_hdr->info3 |= cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK); return 0; } -static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) +u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) { struct iphdr *ip_hdr = (struct iphdr *) pkt; u8 ip_pri; @@ -236,6 +238,11 @@ static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) return ip_pri; } +u8 ath6kl_wmi_get_traffic_class(u8 user_priority) +{ + return up_to_ac[user_priority & 0x7]; +} + int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx, struct sk_buff *skb, u32 layer2_priority, bool wmm_enabled, @@ -786,12 +793,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, ev->u.ap_sta.keymgmt, le16_to_cpu(ev->u.ap_sta.cipher), ev->u.ap_sta.apsd_info); + ath6kl_connect_ap_mode_sta( vif, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr, ev->u.ap_sta.keymgmt, le16_to_cpu(ev->u.ap_sta.cipher), ev->u.ap_sta.auth, ev->assoc_req_len, - ev->assoc_info + ev->beacon_ie_len); + ev->assoc_info + ev->beacon_ie_len, + ev->u.ap_sta.apsd_info); } return 0; } @@ -2993,6 +3002,43 @@ int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac, NO_SYNC_WMIFLAG); } +/* This command will be used to enable/disable AP uAPSD feature */ +int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable) +{ + struct wmi_ap_set_apsd_cmd *cmd; + struct sk_buff *skb; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_ap_set_apsd_cmd *)skb->data; + cmd->enable = enable; + + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_SET_APSD_CMDID, + NO_SYNC_WMIFLAG); +} + +int ath6kl_wmi_set_apsd_bfrd_traf(struct wmi *wmi, u8 if_idx, + u16 aid, u16 bitmap, u32 flags) +{ + struct wmi_ap_apsd_buffered_traffic_cmd *cmd; + struct sk_buff *skb; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_ap_apsd_buffered_traffic_cmd *)skb->data; + cmd->aid = cpu_to_le16(aid); + cmd->bitmap = cpu_to_le16(bitmap); + cmd->flags = cpu_to_le32(flags); + + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, + WMI_AP_APSD_BUFFERED_TRAFFIC_CMDID, + NO_SYNC_WMIFLAG); +} + static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len, struct ath6kl_vif *vif) { diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index eae0e4e065c..48e9d2641d6 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -149,8 +149,7 @@ enum wmi_msg_type { #define WMI_DATA_HDR_PS_MASK 0x1 #define WMI_DATA_HDR_PS_SHIFT 5 -#define WMI_DATA_HDR_MORE_MASK 0x1 -#define WMI_DATA_HDR_MORE_SHIFT 5 +#define WMI_DATA_HDR_MORE 0x20 enum wmi_data_hdr_data_type { WMI_DATA_HDR_DATA_TYPE_802_3 = 0, @@ -160,6 +159,13 @@ enum wmi_data_hdr_data_type { WMI_DATA_HDR_DATA_TYPE_ACL, }; +/* Bitmap of data header flags */ +enum wmi_data_hdr_flags { + WMI_DATA_HDR_FLAGS_MORE = 0x1, + WMI_DATA_HDR_FLAGS_EOSP = 0x2, + WMI_DATA_HDR_FLAGS_UAPSD = 0x4, +}; + #define WMI_DATA_HDR_DATA_TYPE_MASK 0x3 #define WMI_DATA_HDR_DATA_TYPE_SHIFT 6 @@ -173,8 +179,12 @@ enum wmi_data_hdr_data_type { #define WMI_DATA_HDR_META_MASK 0x7 #define WMI_DATA_HDR_META_SHIFT 13 +/* Macros for operating on WMI_DATA_HDR (info3) field */ #define WMI_DATA_HDR_IF_IDX_MASK 0xF +#define WMI_DATA_HDR_TRIG 0x10 +#define WMI_DATA_HDR_EOSP 0x10 + struct wmi_data_hdr { s8 rssi; @@ -203,7 +213,8 @@ struct wmi_data_hdr { /* * usage of info3, 16-bit: * b3:b0 - Interface index - * b15:b4 - Reserved + * b4 - uAPSD trigger in rx & EOSP in tx + * b15:b5 - Reserved */ __le16 info3; } __packed; @@ -2116,6 +2127,19 @@ struct wmi_rx_frame_format_cmd { } __packed; /* AP mode events */ +struct wmi_ap_set_apsd_cmd { + u8 enable; +} __packed; + +enum wmi_ap_apsd_buffered_traffic_flags { + WMI_AP_APSD_NO_DELIVERY_FRAMES = 0x1, +}; + +struct wmi_ap_apsd_buffered_traffic_cmd { + __le16 aid; + __le16 bitmap; + __le32 flags; +} __packed; /* WMI_PS_POLL_EVENT */ struct wmi_pspoll_event { @@ -2332,7 +2356,7 @@ enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi); void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id); int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb); int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, - u8 msg_type, bool more_data, + u8 msg_type, u32 flags, enum wmi_data_hdr_data_type data_type, u8 meta_ver, void *tx_meta_info, u8 if_idx); @@ -2446,7 +2470,16 @@ int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, u8 *filter, bool add_filter); +/* AP mode uAPSD */ +int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); + +int ath6kl_wmi_set_apsd_bfrd_traf(struct wmi *wmi, + u8 if_idx, u16 aid, + u16 bitmap, u32 flags); + +u8 ath6kl_wmi_get_traffic_class(u8 user_priority); +u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri); /* AP mode */ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, struct wmi_connect_cmd *p); -- cgit v1.2.3 From e80ec84d9352419a7c0482edfbf1b96eaa4c8b95 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Thu, 12 Jan 2012 15:01:48 +0530 Subject: ath6kl: Remove useless initialization in ath6kl_read_fwlogs() ath6kl_read_fwlogs() assigns the value zero to the variable 'ret' at the time of declaration. Later, return value of ath6kl_diag_read32() repalces the init value. Hence removing useless zero assignment. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 53f97db4a7a..0a6d6e2be6e 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -255,7 +255,7 @@ int ath6kl_read_fwlogs(struct ath6kl *ar) struct ath6kl_dbglog_hdr debug_hdr; struct ath6kl_dbglog_buf debug_buf; u32 address, length, dropped, firstbuf, debug_hdr_addr; - int ret = 0, loop; + int ret, loop; u8 *buf; buf = kmalloc(ATH6KL_FWLOG_PAYLOAD_SIZE, GFP_KERNEL); -- cgit v1.2.3 From d6f802612af55cc1b3699d119a04dfa2fc8812a0 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 15:05:19 +0200 Subject: ath6kl: use netdev_features_t Commit c8f44affb7 ("net: introduce and use netdev_features_t for device features sets") added netdev_features_t to ndo_set_features. Change ath6kl to use the new type. This fixes a warning: ath6kl/main.c:1170: warning: initialization from incompatible pointer type Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 0a6d6e2be6e..3a3b2cc9940 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1021,7 +1021,8 @@ static struct net_device_stats *ath6kl_get_stats(struct net_device *dev) return &vif->net_stats; } -static int ath6kl_set_features(struct net_device *dev, u32 features) +static int ath6kl_set_features(struct net_device *dev, + netdev_features_t features) { struct ath6kl_vif *vif = netdev_priv(dev); struct ath6kl *ar = vif->ar; -- cgit v1.2.3 From 3462735dadb90efd5bed9d2b81222ed7da1390a0 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 15:05:32 +0200 Subject: ath6kl: remove -D__CHECK_ENDIAN__ from Makefile As drivers/net/wireless/ath/Makefile contains the flag to enable endian checks there's no need to have it in ath6kl makefile anymore. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index 70706930355..e24b6179915 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile @@ -33,5 +33,3 @@ ath6kl-y += txrx.o ath6kl-y += wmi.o ath6kl-y += sdio.o ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o - -ccflags-y += -D__CHECK_ENDIAN__ -- cgit v1.2.3 From e572602884c4f979cbba4fed413af24797fd01d9 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 15:05:46 +0200 Subject: ath6kl: fix uninitialized warning in ath6kl_process_uapsdq() Before I commited patch c1762a3fe ("ath6kl: Add support for uAPSD") I did a minor change how up variable is initialised in ath6kl_process_uapsdq(). But I was sloppy and caused this compiler warning: txrx.c:88:5: warning: 'up' may be used uninitialized in this function Revert my change to fix the warning. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/txrx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 91bbc1ffa49..dd633714260 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -85,7 +85,7 @@ static bool ath6kl_process_uapsdq(struct ath6kl_sta *conn, struct ath6kl *ar = vif->ar; bool is_apsdq_empty = false; struct ethhdr *datap = (struct ethhdr *) skb->data; - u8 up, traffic_class, *ip_hdr; + u8 up = 0, traffic_class, *ip_hdr; u16 ether_type; struct ath6kl_llc_snap_hdr *llc_hdr; @@ -122,8 +122,6 @@ static bool ath6kl_process_uapsdq(struct ath6kl_sta *conn, if (ether_type == IP_ETHERTYPE) up = ath6kl_wmi_determine_user_priority( ip_hdr, 0); - } else { - up = 0; } traffic_class = ath6kl_wmi_get_traffic_class(up); -- cgit v1.2.3 From cd23c1c9b8a2de64477a795ab5a9cd5278397f24 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Tue, 17 Jan 2012 15:32:29 +0200 Subject: ath6kl: add testmode 2 for 6003 ART Add testmode 2 for 6003 ART. When you insmod ath6kl_sdio.ko testmode=2, ath6kl will load ART firmware utf.bin and testscript nullTestFlow.bin. These files should be put in the firmware folder. kvalo: add "ath6kl:" to the title, word wrap the commit log and remove extra line in the code Signed-off-by: Alex Yang Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.h | 8 +++ drivers/net/wireless/ath/ath6kl/init.c | 108 +++++++++++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index ba3953918e4..f53594f2e53 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -125,6 +125,8 @@ struct ath6kl_fw_ie { #define AR6003_HW_2_1_1_OTP_FILE "otp.bin" #define AR6003_HW_2_1_1_FIRMWARE_FILE "athwlan.bin" #define AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" +#define AR6003_HW_2_1_1_UTF_FIRMWARE_FILE "utf.bin" +#define AR6003_HW_2_1_1_TESTSCRIPT_FILE "nullTestFlow.bin" #define AR6003_HW_2_1_1_PATCH_FILE "data.patch.bin" #define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \ @@ -592,6 +594,7 @@ struct ath6kl { u32 board_addr; u32 refclk_hz; u32 uarttx_pin; + u32 testscript_addr; struct ath6kl_hw_fw { const char *dir; @@ -599,6 +602,8 @@ struct ath6kl { const char *fw; const char *tcmd; const char *patch; + const char *utf; + const char *testscript; } fw; const char *fw_board; @@ -624,6 +629,9 @@ struct ath6kl { u8 *fw_patch; size_t fw_patch_len; + u8 *fw_testscript; + size_t fw_testscript_len; + unsigned int fw_api; unsigned long fw_capabilities[ATH6KL_CAPABILITY_LEN]; diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index e5969c14630..b88f41dc3df 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -69,6 +69,7 @@ static const struct ath6kl_hw hw_list[] = { .reserved_ram_size = 512, .refclk_hz = 26000000, .uarttx_pin = 8, + .testscript_addr = 0x57ef74, .fw = { .dir = AR6003_HW_2_1_1_FW_DIR, @@ -76,6 +77,8 @@ static const struct ath6kl_hw hw_list[] = { .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, .tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, .patch = AR6003_HW_2_1_1_PATCH_FILE, + .utf = AR6003_HW_2_1_1_UTF_FIRMWARE_FILE, + .testscript = AR6003_HW_2_1_1_TESTSCRIPT_FILE, }, .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE, @@ -620,6 +623,7 @@ void ath6kl_core_cleanup(struct ath6kl *ar) kfree(ar->fw_otp); kfree(ar->fw); kfree(ar->fw_patch); + kfree(ar->fw_testscript); ath6kl_deinit_ieee80211_hw(ar); } @@ -771,14 +775,25 @@ static int ath6kl_fetch_fw_file(struct ath6kl *ar) return 0; if (testmode) { - if (ar->hw.fw.tcmd == NULL) { - ath6kl_warn("testmode not supported\n"); - return -EOPNOTSUPP; - } + ath6kl_dbg(ATH6KL_DBG_BOOT, "testmode %d\n", + testmode); + if (testmode == 2) { + if (ar->hw.fw.utf == NULL) { + ath6kl_warn("testmode 2 not supported\n"); + return -EOPNOTSUPP; + } - snprintf(filename, sizeof(filename), "%s/%s", - ar->hw.fw.dir, ar->hw.fw.tcmd); + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.utf); + } else { + if (ar->hw.fw.tcmd == NULL) { + ath6kl_warn("testmode 1 not supported\n"); + return -EOPNOTSUPP; + } + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.tcmd); + } set_bit(TESTMODE, &ar->flag); goto get_fw; @@ -827,6 +842,34 @@ static int ath6kl_fetch_patch_file(struct ath6kl *ar) return 0; } +static int ath6kl_fetch_testscript_file(struct ath6kl *ar) +{ + char filename[100]; + int ret; + + if (testmode != 2) + return 0; + + if (ar->fw_testscript != NULL) + return 0; + + if (ar->hw.fw.testscript == NULL) + return 0; + + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.testscript); + + ret = ath6kl_get_fw(ar, filename, &ar->fw_testscript, + &ar->fw_testscript_len); + if (ret) { + ath6kl_err("Failed to get testscript file %s: %d\n", + filename, ret); + return ret; + } + + return 0; +} + static int ath6kl_fetch_fw_api1(struct ath6kl *ar) { int ret; @@ -843,6 +886,10 @@ static int ath6kl_fetch_fw_api1(struct ath6kl *ar) if (ret) return ret; + ret = ath6kl_fetch_testscript_file(ar); + if (ret) + return ret; + return 0; } @@ -1266,6 +1313,50 @@ static int ath6kl_upload_patch(struct ath6kl *ar) return 0; } +static int ath6kl_upload_testscript(struct ath6kl *ar) +{ + u32 address, param; + int ret; + + if (testmode != 2) + return 0; + + if (ar->fw_testscript == NULL) + return 0; + + address = ar->hw.testscript_addr; + + ath6kl_dbg(ATH6KL_DBG_BOOT, "writing testscript to 0x%x (%zd B)\n", + address, ar->fw_testscript_len); + + ret = ath6kl_bmi_write(ar, address, ar->fw_testscript, + ar->fw_testscript_len); + if (ret) { + ath6kl_err("Failed to write testscript file: %d\n", ret); + return ret; + } + + param = address; + ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_ota_testscript)), + (unsigned char *) ¶m, 4); + + param = 4096; + ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_end_ram_reserve_sz)), + (unsigned char *) ¶m, 4); + + param = 1; + ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_test_apps_related)), + (unsigned char *) ¶m, 4); + + return 0; +} + static int ath6kl_init_upload(struct ath6kl *ar) { u32 param, options, sleep, address; @@ -1374,6 +1465,11 @@ static int ath6kl_init_upload(struct ath6kl *ar) if (status) return status; + /* Download the test script */ + status = ath6kl_upload_testscript(ar); + if (status) + return status; + /* Restore system sleep */ address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; status = ath6kl_bmi_reg_write(ar, address, sleep); -- cgit v1.2.3 From c25889e8a6fdfc54618b192a80c94419ddb7949d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:08:27 +0200 Subject: ath6kl: rename vif init and cleanup functions ath6kl_cfg80211_vif_init/cleanup() follow more closely the style used elsewhere in ath6kl. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 9 ++++----- drivers/net/wireless/ath/ath6kl/cfg80211.h | 2 ++ drivers/net/wireless/ath/ath6kl/core.h | 1 - drivers/net/wireless/ath/ath6kl/init.c | 5 +++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index a13ecec0070..7e92dc9799a 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1401,7 +1401,7 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy, ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); - ath6kl_deinit_if_data(vif); + ath6kl_cfg80211_vif_cleanup(vif); return 0; } @@ -2806,7 +2806,7 @@ int ath6kl_register_ieee80211_hw(struct ath6kl *ar) return 0; } -static int ath6kl_init_if_data(struct ath6kl_vif *vif) +static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) { vif->aggr_cntxt = aggr_init(vif->ndev); if (!vif->aggr_cntxt) { @@ -2827,7 +2827,7 @@ static int ath6kl_init_if_data(struct ath6kl_vif *vif) return 0; } -void ath6kl_deinit_if_data(struct ath6kl_vif *vif) +void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif) { struct ath6kl *ar = vif->ar; struct ath6kl_mc_filter *mc_filter, *tmp; @@ -2880,8 +2880,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, ath6kl_init_control_info(vif); - /* TODO: Pass interface specific pointer instead of ar */ - if (ath6kl_init_if_data(vif)) + if (ath6kl_cfg80211_vif_init(vif)) goto err; if (register_netdevice(ndev)) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index 81f20a57231..aa961694cf9 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h @@ -53,6 +53,8 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, int ath6kl_cfg80211_resume(struct ath6kl *ar); +void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif); + void ath6kl_cfg80211_stop(struct ath6kl_vif *vif); void ath6kl_cfg80211_stop_all(struct ath6kl *ar); diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index f53594f2e53..bdeb254c259 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -753,7 +753,6 @@ void ath6kl_wakeup_event(void *dev); void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, bool wait_fot_compltn, bool cold_reset); void ath6kl_init_control_info(struct ath6kl_vif *vif); -void ath6kl_deinit_if_data(struct ath6kl_vif *vif); void ath6kl_core_free(struct ath6kl *ar); struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready); diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index b88f41dc3df..3cc4e0842ad 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1811,7 +1811,7 @@ err_rxbuf_cleanup: ath6kl_htc_flush_rx_buf(ar->htc_target); ath6kl_cleanup_amsdu_rxbufs(ar); rtnl_lock(); - ath6kl_deinit_if_data(netdev_priv(ndev)); + ath6kl_cfg80211_vif_cleanup(netdev_priv(ndev)); rtnl_unlock(); wiphy_unregister(ar->wiphy); err_debug_init: @@ -1832,6 +1832,7 @@ err_wq: return ret; } +/* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) { static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; @@ -1877,7 +1878,7 @@ void ath6kl_stop_txrx(struct ath6kl *ar) spin_unlock_bh(&ar->list_lock); ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); rtnl_lock(); - ath6kl_deinit_if_data(vif); + ath6kl_cfg80211_vif_cleanup(vif); rtnl_unlock(); spin_lock_bh(&ar->list_lock); } -- cgit v1.2.3 From 46d33a21cfa531f4271c3f0b7b87a295f30f9e6a Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:08:40 +0200 Subject: ath6kl: unify cfg80211 init/cleanup functions Group them together and change the naming to follow the common style in ath6kl. No functional changes. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 109 +++++++++++++++-------------- drivers/net/wireless/ath/ath6kl/cfg80211.h | 6 +- drivers/net/wireless/ath/ath6kl/init.c | 4 +- 3 files changed, 62 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 7e92dc9799a..44fdd39e170 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2755,57 +2755,6 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev) return ar; } -int ath6kl_register_ieee80211_hw(struct ath6kl *ar) -{ - struct wiphy *wiphy = ar->wiphy; - int ret; - - wiphy->mgmt_stypes = ath6kl_mgmt_stypes; - - wiphy->max_remain_on_channel_duration = 5000; - - /* set device pointer for wiphy */ - set_wiphy_dev(wiphy, ar->dev); - - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP); - if (ar->p2p) { - wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_CLIENT); - } - - /* max num of ssids that can be probed during scanning */ - wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; - wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ - wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; - wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; - wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - - wiphy->cipher_suites = cipher_suites; - wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); - - wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | - WIPHY_WOWLAN_DISCONNECT | - WIPHY_WOWLAN_GTK_REKEY_FAILURE | - WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | - WIPHY_WOWLAN_EAP_IDENTITY_REQ | - WIPHY_WOWLAN_4WAY_HANDSHAKE; - wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST; - wiphy->wowlan.pattern_min_len = 1; - wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; - - wiphy->max_sched_scan_ssids = 10; - - ret = wiphy_register(wiphy); - if (ret < 0) { - ath6kl_err("couldn't register wiphy device\n"); - return ret; - } - - return 0; -} - static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) { vif->aggr_cntxt = aggr_init(vif->ndev); @@ -2907,8 +2856,64 @@ err: return NULL; } -void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar) +int ath6kl_cfg80211_init(struct ath6kl *ar) +{ + struct wiphy *wiphy = ar->wiphy; + int ret; + + wiphy->mgmt_stypes = ath6kl_mgmt_stypes; + + wiphy->max_remain_on_channel_duration = 5000; + + /* set device pointer for wiphy */ + set_wiphy_dev(wiphy, ar->dev); + + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_AP); + if (ar->p2p) { + wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_P2P_CLIENT); + } + + /* max num of ssids that can be probed during scanning */ + wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; + wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ + wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; + wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + wiphy->cipher_suites = cipher_suites; + wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + + wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_GTK_REKEY_FAILURE | + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_EAP_IDENTITY_REQ | + WIPHY_WOWLAN_4WAY_HANDSHAKE; + wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST; + wiphy->wowlan.pattern_min_len = 1; + wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; + + wiphy->max_sched_scan_ssids = 10; + + ret = wiphy_register(wiphy); + if (ret < 0) { + ath6kl_err("couldn't register wiphy device\n"); + return ret; + } + + return 0; +} + +void ath6kl_cfg80211_cleanup(struct ath6kl *ar) { wiphy_unregister(ar->wiphy); + + /* + * FIXME: should be removed as we remove wiphy in + * ath6kl_core_free(). Most likely this causes a use after free. + */ wiphy_free(ar->wiphy); } diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index aa961694cf9..08d97691039 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h @@ -27,10 +27,7 @@ enum ath6kl_cfg_suspend_mode { struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, enum nl80211_iftype type, u8 fw_vif_idx, u8 nw_type); -int ath6kl_register_ieee80211_hw(struct ath6kl *ar); struct ath6kl *ath6kl_core_alloc(struct device *dev); -void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar); - void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted); void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, @@ -58,4 +55,7 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif); void ath6kl_cfg80211_stop(struct ath6kl_vif *vif); void ath6kl_cfg80211_stop_all(struct ath6kl *ar); +int ath6kl_cfg80211_init(struct ath6kl *ar); +void ath6kl_cfg80211_cleanup(struct ath6kl *ar); + #endif /* ATH6KL_CFG80211_H */ diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 3cc4e0842ad..7e56a6aa70b 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -625,7 +625,7 @@ void ath6kl_core_cleanup(struct ath6kl *ar) kfree(ar->fw_patch); kfree(ar->fw_testscript); - ath6kl_deinit_ieee80211_hw(ar); + ath6kl_cfg80211_cleanup(ar); } /* firmware upload */ @@ -1722,7 +1722,7 @@ int ath6kl_core_init(struct ath6kl *ar) ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); - ret = ath6kl_register_ieee80211_hw(ar); + ret = ath6kl_cfg80211_init(ar); if (ret) goto err_node_cleanup; -- cgit v1.2.3 From f29af97853599e9537191c4f33f8ac87f3f503a9 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:08:56 +0200 Subject: ath6kl: add ATH6KL_CONF_UART_DEBUG Add ATH6KL_CONF_UART_DEBUG which is set whenever uart_debug module parameter is enabled. This way we can keep the uart_debug parameter static when core.c file is introduced. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.h | 1 + drivers/net/wireless/ath/ath6kl/init.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index bdeb254c259..78c0402e2d3 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -197,6 +197,7 @@ struct ath6kl_fw_ie { #define ATH6KL_CONF_ENABLE_11N BIT(2) #define ATH6KL_CONF_ENABLE_TX_BURST BIT(3) #define ATH6KL_CONF_SUSPEND_CUTPOWER BIT(4) +#define ATH6KL_CONF_UART_DEBUG BIT(5) enum wlan_low_pwr_state { WLAN_POWER_STATE_ON, diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 7e56a6aa70b..2804921d5d8 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -469,7 +469,7 @@ int ath6kl_configure_target(struct ath6kl *ar) u8 fw_iftype, fw_mode = 0, fw_submode = 0; int i, status; - param = uart_debug; + param = !!(ar->conf_flags & ATH6KL_CONF_UART_DEBUG); if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_serial_enable)), (u8 *)¶m, 4)) { ath6kl_err("bmi_write_memory for uart debug failed\n"); @@ -1775,6 +1775,9 @@ int ath6kl_core_init(struct ath6kl *ar) if (suspend_cutpower) ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER; + if (uart_debug) + ar->conf_flags |= ATH6KL_CONF_UART_DEBUG; + ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | -- cgit v1.2.3 From 45eaa78f757b3b3992ca02c753764665e9fba0a4 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:09:05 +0200 Subject: ath6kl: create core.c Currently core functions are spread between various files, group all the functions into file and rename the functions to follow the style used elsewhere in the driver. This will make it easier to a separate core module. Also fix a bug where wiphy is freed too early. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/Makefile | 1 + drivers/net/wireless/ath/ath6kl/cfg80211.c | 94 +++------- drivers/net/wireless/ath/ath6kl/cfg80211.h | 4 +- drivers/net/wireless/ath/ath6kl/common.h | 3 - drivers/net/wireless/ath/ath6kl/core.c | 292 +++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath6kl/core.h | 9 +- drivers/net/wireless/ath/ath6kl/init.c | 213 +-------------------- drivers/net/wireless/ath/ath6kl/sdio.c | 4 +- 8 files changed, 332 insertions(+), 288 deletions(-) create mode 100644 drivers/net/wireless/ath/ath6kl/core.c diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index e24b6179915..854694b26a4 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile @@ -31,5 +31,6 @@ ath6kl-y += init.o ath6kl-y += main.o ath6kl-y += txrx.o ath6kl-y += wmi.o +ath6kl-y += core.o ath6kl-y += sdio.o ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 44fdd39e170..7ff9806de50 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -23,10 +23,6 @@ #include "hif-ops.h" #include "testmode.h" -static unsigned int ath6kl_p2p; - -module_param(ath6kl_p2p, uint, 0644); - #define RATETAB_ENT(_rate, _rateid, _flags) { \ .bitrate = (_rate), \ .flags = (_flags), \ @@ -2693,68 +2689,6 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar) ath6kl_cfg80211_stop(vif); } -struct ath6kl *ath6kl_core_alloc(struct device *dev) -{ - struct ath6kl *ar; - struct wiphy *wiphy; - u8 ctr; - - /* create a new wiphy for use with cfg80211 */ - wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl)); - - if (!wiphy) { - ath6kl_err("couldn't allocate wiphy device\n"); - return NULL; - } - - ar = wiphy_priv(wiphy); - ar->p2p = !!ath6kl_p2p; - ar->wiphy = wiphy; - ar->dev = dev; - - ar->vif_max = 1; - - ar->max_norm_iface = 1; - - spin_lock_init(&ar->lock); - spin_lock_init(&ar->mcastpsq_lock); - spin_lock_init(&ar->list_lock); - - init_waitqueue_head(&ar->event_wq); - sema_init(&ar->sem, 1); - - INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue); - INIT_LIST_HEAD(&ar->vif_list); - - clear_bit(WMI_ENABLED, &ar->flag); - clear_bit(SKIP_SCAN, &ar->flag); - clear_bit(DESTROY_IN_PROGRESS, &ar->flag); - - ar->listen_intvl_b = A_DEFAULT_LISTEN_INTERVAL; - ar->tx_pwr = 0; - - ar->intra_bss = 1; - ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD; - - ar->state = ATH6KL_STATE_OFF; - - memset((u8 *)ar->sta_list, 0, - AP_MAX_NUM_STA * sizeof(struct ath6kl_sta)); - - /* Init the PS queues */ - for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { - spin_lock_init(&ar->sta_list[ctr].psq_lock); - skb_queue_head_init(&ar->sta_list[ctr].psq); - skb_queue_head_init(&ar->sta_list[ctr].apsdq); - } - - skb_queue_head_init(&ar->mcastpsq); - - memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3); - - return ar; -} - static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) { vif->aggr_cntxt = aggr_init(vif->ndev); @@ -2910,10 +2844,30 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) void ath6kl_cfg80211_cleanup(struct ath6kl *ar) { wiphy_unregister(ar->wiphy); +} - /* - * FIXME: should be removed as we remove wiphy in - * ath6kl_core_free(). Most likely this causes a use after free. - */ +struct ath6kl *ath6kl_cfg80211_create(void) +{ + struct ath6kl *ar; + struct wiphy *wiphy; + + /* create a new wiphy for use with cfg80211 */ + wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl)); + + if (!wiphy) { + ath6kl_err("couldn't allocate wiphy device\n"); + return NULL; + } + + ar = wiphy_priv(wiphy); + ar->wiphy = wiphy; + + return ar; +} + +/* Note: ar variable must not be accessed after calling this! */ +void ath6kl_cfg80211_destroy(struct ath6kl *ar) +{ wiphy_free(ar->wiphy); } + diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index 08d97691039..3c693b7c0ef 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h @@ -27,7 +27,6 @@ enum ath6kl_cfg_suspend_mode { struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, enum nl80211_iftype type, u8 fw_vif_idx, u8 nw_type); -struct ath6kl *ath6kl_core_alloc(struct device *dev); void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted); void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, @@ -58,4 +57,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar); int ath6kl_cfg80211_init(struct ath6kl *ar); void ath6kl_cfg80211_cleanup(struct ath6kl *ar); +struct ath6kl *ath6kl_cfg80211_create(void); +void ath6kl_cfg80211_destroy(struct ath6kl *ar); + #endif /* ATH6KL_CFG80211_H */ diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h index bfd6597763d..f89f1e180da 100644 --- a/drivers/net/wireless/ath/ath6kl/common.h +++ b/drivers/net/wireless/ath/ath6kl/common.h @@ -79,8 +79,5 @@ struct ath6kl; enum htc_credit_dist_reason; struct ath6kl_htc_credit_info; -struct ath6kl *ath6kl_core_alloc(struct device *sdev); -int ath6kl_core_init(struct ath6kl *ar); -void ath6kl_core_cleanup(struct ath6kl *ar); struct sk_buff *ath6kl_buf_alloc(int size); #endif /* COMMON_H */ diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c new file mode 100644 index 00000000000..40fad5ec936 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "core.h" + +#include + +#include "debug.h" +#include "hif-ops.h" +#include "cfg80211.h" + +unsigned int debug_mask; +static bool suspend_cutpower; +static unsigned int uart_debug; +static unsigned int ath6kl_p2p; + +module_param(debug_mask, uint, 0644); +module_param(suspend_cutpower, bool, 0444); +module_param(uart_debug, uint, 0644); +module_param(ath6kl_p2p, uint, 0644); + +int ath6kl_core_init(struct ath6kl *ar) +{ + struct ath6kl_bmi_target_info targ_info; + struct net_device *ndev; + int ret = 0, i; + + ar->ath6kl_wq = create_singlethread_workqueue("ath6kl"); + if (!ar->ath6kl_wq) + return -ENOMEM; + + ret = ath6kl_bmi_init(ar); + if (ret) + goto err_wq; + + /* + * Turn on power to get hardware (target) version and leave power + * on delibrately as we will boot the hardware anyway within few + * seconds. + */ + ret = ath6kl_hif_power_on(ar); + if (ret) + goto err_bmi_cleanup; + + ret = ath6kl_bmi_get_target_info(ar, &targ_info); + if (ret) + goto err_power_off; + + ar->version.target_ver = le32_to_cpu(targ_info.version); + ar->target_type = le32_to_cpu(targ_info.type); + ar->wiphy->hw_version = le32_to_cpu(targ_info.version); + + ret = ath6kl_init_hw_params(ar); + if (ret) + goto err_power_off; + + ar->htc_target = ath6kl_htc_create(ar); + + if (!ar->htc_target) { + ret = -ENOMEM; + goto err_power_off; + } + + ret = ath6kl_init_fetch_firmwares(ar); + if (ret) + goto err_htc_cleanup; + + /* FIXME: we should free all firmwares in the error cases below */ + + /* Indicate that WMI is enabled (although not ready yet) */ + set_bit(WMI_ENABLED, &ar->flag); + ar->wmi = ath6kl_wmi_init(ar); + if (!ar->wmi) { + ath6kl_err("failed to initialize wmi\n"); + ret = -EIO; + goto err_htc_cleanup; + } + + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); + + ret = ath6kl_cfg80211_init(ar); + if (ret) + goto err_node_cleanup; + + ret = ath6kl_debug_init(ar); + if (ret) { + wiphy_unregister(ar->wiphy); + goto err_node_cleanup; + } + + for (i = 0; i < ar->vif_max; i++) + ar->avail_idx_map |= BIT(i); + + rtnl_lock(); + + /* Add an initial station interface */ + ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0, + INFRA_NETWORK); + + rtnl_unlock(); + + if (!ndev) { + ath6kl_err("Failed to instantiate a network device\n"); + ret = -ENOMEM; + wiphy_unregister(ar->wiphy); + goto err_debug_init; + } + + + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n", + __func__, ndev->name, ndev, ar); + + /* setup access class priority mappings */ + ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */ + ar->ac_stream_pri_map[WMM_AC_BE] = 1; + ar->ac_stream_pri_map[WMM_AC_VI] = 2; + ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */ + + /* give our connected endpoints some buffers */ + ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep); + ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]); + + /* allocate some buffers that handle larger AMSDU frames */ + ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS); + + ath6kl_cookie_init(ar); + + ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | + ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; + + if (suspend_cutpower) + ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER; + + if (uart_debug) + ar->conf_flags |= ATH6KL_CONF_UART_DEBUG; + + ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | + WIPHY_FLAG_HAVE_AP_SME | + WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | + WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; + + if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) + ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + + ar->wiphy->probe_resp_offload = + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; + + set_bit(FIRST_BOOT, &ar->flag); + + ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; + + ret = ath6kl_init_hw_start(ar); + if (ret) { + ath6kl_err("Failed to start hardware: %d\n", ret); + goto err_rxbuf_cleanup; + } + + /* + * Set mac address which is received in ready event + * FIXME: Move to ath6kl_interface_add() + */ + memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); + + return ret; + +err_rxbuf_cleanup: + ath6kl_htc_flush_rx_buf(ar->htc_target); + ath6kl_cleanup_amsdu_rxbufs(ar); + rtnl_lock(); + ath6kl_cfg80211_vif_cleanup(netdev_priv(ndev)); + rtnl_unlock(); + wiphy_unregister(ar->wiphy); +err_debug_init: + ath6kl_debug_cleanup(ar); +err_node_cleanup: + ath6kl_wmi_shutdown(ar->wmi); + clear_bit(WMI_ENABLED, &ar->flag); + ar->wmi = NULL; +err_htc_cleanup: + ath6kl_htc_cleanup(ar->htc_target); +err_power_off: + ath6kl_hif_power_off(ar); +err_bmi_cleanup: + ath6kl_bmi_cleanup(ar); +err_wq: + destroy_workqueue(ar->ath6kl_wq); + + return ret; +} + +struct ath6kl *ath6kl_core_create(struct device *dev) +{ + struct ath6kl *ar; + u8 ctr; + + ar = ath6kl_cfg80211_create(); + if (!ar) + return NULL; + + ar->p2p = !!ath6kl_p2p; + ar->dev = dev; + + ar->vif_max = 1; + + ar->max_norm_iface = 1; + + spin_lock_init(&ar->lock); + spin_lock_init(&ar->mcastpsq_lock); + spin_lock_init(&ar->list_lock); + + init_waitqueue_head(&ar->event_wq); + sema_init(&ar->sem, 1); + + INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue); + INIT_LIST_HEAD(&ar->vif_list); + + clear_bit(WMI_ENABLED, &ar->flag); + clear_bit(SKIP_SCAN, &ar->flag); + clear_bit(DESTROY_IN_PROGRESS, &ar->flag); + + ar->listen_intvl_b = A_DEFAULT_LISTEN_INTERVAL; + ar->tx_pwr = 0; + + ar->intra_bss = 1; + ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD; + + ar->state = ATH6KL_STATE_OFF; + + memset((u8 *)ar->sta_list, 0, + AP_MAX_NUM_STA * sizeof(struct ath6kl_sta)); + + /* Init the PS queues */ + for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { + spin_lock_init(&ar->sta_list[ctr].psq_lock); + skb_queue_head_init(&ar->sta_list[ctr].psq); + skb_queue_head_init(&ar->sta_list[ctr].apsdq); + } + + skb_queue_head_init(&ar->mcastpsq); + + memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3); + + return ar; +} + +void ath6kl_core_cleanup(struct ath6kl *ar) +{ + ath6kl_hif_power_off(ar); + + destroy_workqueue(ar->ath6kl_wq); + + if (ar->htc_target) + ath6kl_htc_cleanup(ar->htc_target); + + ath6kl_cookie_cleanup(ar); + + ath6kl_cleanup_amsdu_rxbufs(ar); + + ath6kl_bmi_cleanup(ar); + + ath6kl_debug_cleanup(ar); + + kfree(ar->fw_board); + kfree(ar->fw_otp); + kfree(ar->fw); + kfree(ar->fw_patch); + kfree(ar->fw_testscript); + + ath6kl_cfg80211_cleanup(ar); +} + +void ath6kl_core_destroy(struct ath6kl *ar) +{ + ath6kl_cfg80211_destroy(ar); +} + diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 78c0402e2d3..67b22e4bbcc 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -754,11 +754,18 @@ void ath6kl_wakeup_event(void *dev); void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, bool wait_fot_compltn, bool cold_reset); void ath6kl_init_control_info(struct ath6kl_vif *vif); -void ath6kl_core_free(struct ath6kl *ar); struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready); int ath6kl_init_hw_start(struct ath6kl *ar); int ath6kl_init_hw_stop(struct ath6kl *ar); +int ath6kl_init_fetch_firmwares(struct ath6kl *ar); +int ath6kl_init_hw_params(struct ath6kl *ar); + void ath6kl_check_wow_status(struct ath6kl *ar); +struct ath6kl *ath6kl_core_create(struct device *dev); +int ath6kl_core_init(struct ath6kl *ar); +void ath6kl_core_cleanup(struct ath6kl *ar); +void ath6kl_core_destroy(struct ath6kl *ar); + #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 2804921d5d8..b8252ced096 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -25,15 +25,9 @@ #include "debug.h" #include "hif-ops.h" -unsigned int debug_mask; static unsigned int testmode; -static bool suspend_cutpower; -static unsigned int uart_debug; -module_param(debug_mask, uint, 0644); module_param(testmode, uint, 0644); -module_param(suspend_cutpower, bool, 0444); -module_param(uart_debug, uint, 0644); static const struct ath6kl_hw hw_list[] = { { @@ -597,37 +591,6 @@ int ath6kl_configure_target(struct ath6kl *ar) return 0; } -void ath6kl_core_free(struct ath6kl *ar) -{ - wiphy_free(ar->wiphy); -} - -void ath6kl_core_cleanup(struct ath6kl *ar) -{ - ath6kl_hif_power_off(ar); - - destroy_workqueue(ar->ath6kl_wq); - - if (ar->htc_target) - ath6kl_htc_cleanup(ar->htc_target); - - ath6kl_cookie_cleanup(ar); - - ath6kl_cleanup_amsdu_rxbufs(ar); - - ath6kl_bmi_cleanup(ar); - - ath6kl_debug_cleanup(ar); - - kfree(ar->fw_board); - kfree(ar->fw_otp); - kfree(ar->fw); - kfree(ar->fw_patch); - kfree(ar->fw_testscript); - - ath6kl_cfg80211_cleanup(ar); -} - /* firmware upload */ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, u8 **fw, size_t *fw_len) @@ -1065,7 +1028,7 @@ out: return ret; } -static int ath6kl_fetch_firmwares(struct ath6kl *ar) +int ath6kl_init_fetch_firmwares(struct ath6kl *ar) { int ret; @@ -1485,7 +1448,7 @@ static int ath6kl_init_upload(struct ath6kl *ar) return status; } -static int ath6kl_init_hw_params(struct ath6kl *ar) +int ath6kl_init_hw_params(struct ath6kl *ar) { const struct ath6kl_hw *hw; int i; @@ -1663,178 +1626,6 @@ int ath6kl_init_hw_stop(struct ath6kl *ar) return 0; } -int ath6kl_core_init(struct ath6kl *ar) -{ - struct ath6kl_bmi_target_info targ_info; - struct net_device *ndev; - int ret = 0, i; - - ar->ath6kl_wq = create_singlethread_workqueue("ath6kl"); - if (!ar->ath6kl_wq) - return -ENOMEM; - - ret = ath6kl_bmi_init(ar); - if (ret) - goto err_wq; - - /* - * Turn on power to get hardware (target) version and leave power - * on delibrately as we will boot the hardware anyway within few - * seconds. - */ - ret = ath6kl_hif_power_on(ar); - if (ret) - goto err_bmi_cleanup; - - ret = ath6kl_bmi_get_target_info(ar, &targ_info); - if (ret) - goto err_power_off; - - ar->version.target_ver = le32_to_cpu(targ_info.version); - ar->target_type = le32_to_cpu(targ_info.type); - ar->wiphy->hw_version = le32_to_cpu(targ_info.version); - - ret = ath6kl_init_hw_params(ar); - if (ret) - goto err_power_off; - - ar->htc_target = ath6kl_htc_create(ar); - - if (!ar->htc_target) { - ret = -ENOMEM; - goto err_power_off; - } - - ret = ath6kl_fetch_firmwares(ar); - if (ret) - goto err_htc_cleanup; - - /* FIXME: we should free all firmwares in the error cases below */ - - /* Indicate that WMI is enabled (although not ready yet) */ - set_bit(WMI_ENABLED, &ar->flag); - ar->wmi = ath6kl_wmi_init(ar); - if (!ar->wmi) { - ath6kl_err("failed to initialize wmi\n"); - ret = -EIO; - goto err_htc_cleanup; - } - - ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); - - ret = ath6kl_cfg80211_init(ar); - if (ret) - goto err_node_cleanup; - - ret = ath6kl_debug_init(ar); - if (ret) { - wiphy_unregister(ar->wiphy); - goto err_node_cleanup; - } - - for (i = 0; i < ar->vif_max; i++) - ar->avail_idx_map |= BIT(i); - - rtnl_lock(); - - /* Add an initial station interface */ - ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0, - INFRA_NETWORK); - - rtnl_unlock(); - - if (!ndev) { - ath6kl_err("Failed to instantiate a network device\n"); - ret = -ENOMEM; - wiphy_unregister(ar->wiphy); - goto err_debug_init; - } - - - ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n", - __func__, ndev->name, ndev, ar); - - /* setup access class priority mappings */ - ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */ - ar->ac_stream_pri_map[WMM_AC_BE] = 1; - ar->ac_stream_pri_map[WMM_AC_VI] = 2; - ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */ - - /* give our connected endpoints some buffers */ - ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep); - ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]); - - /* allocate some buffers that handle larger AMSDU frames */ - ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS); - - ath6kl_cookie_init(ar); - - ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | - ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; - - if (suspend_cutpower) - ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER; - - if (uart_debug) - ar->conf_flags |= ATH6KL_CONF_UART_DEBUG; - - ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | - WIPHY_FLAG_HAVE_AP_SME | - WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | - WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; - - if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) - ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; - - ar->wiphy->probe_resp_offload = - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; - - set_bit(FIRST_BOOT, &ar->flag); - - ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; - - ret = ath6kl_init_hw_start(ar); - if (ret) { - ath6kl_err("Failed to start hardware: %d\n", ret); - goto err_rxbuf_cleanup; - } - - /* - * Set mac address which is received in ready event - * FIXME: Move to ath6kl_interface_add() - */ - memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); - - return ret; - -err_rxbuf_cleanup: - ath6kl_htc_flush_rx_buf(ar->htc_target); - ath6kl_cleanup_amsdu_rxbufs(ar); - rtnl_lock(); - ath6kl_cfg80211_vif_cleanup(netdev_priv(ndev)); - rtnl_unlock(); - wiphy_unregister(ar->wiphy); -err_debug_init: - ath6kl_debug_cleanup(ar); -err_node_cleanup: - ath6kl_wmi_shutdown(ar->wmi); - clear_bit(WMI_ENABLED, &ar->flag); - ar->wmi = NULL; -err_htc_cleanup: - ath6kl_htc_cleanup(ar->htc_target); -err_power_off: - ath6kl_hif_power_off(ar); -err_bmi_cleanup: - ath6kl_bmi_cleanup(ar); -err_wq: - destroy_workqueue(ar->ath6kl_wq); - - return ret; -} - /* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) { diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 662b47dc71e..bef32ecea79 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -1261,7 +1261,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]); - ar = ath6kl_core_alloc(&ar_sdio->func->dev); + ar = ath6kl_core_create(&ar_sdio->func->dev); if (!ar) { ath6kl_err("Failed to alloc ath6kl core\n"); ret = -ENOMEM; @@ -1291,7 +1291,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, return ret; err_core_alloc: - ath6kl_core_free(ar_sdio->ar); + ath6kl_core_destroy(ar_sdio->ar); err_dma: kfree(ar_sdio->dma_buffer); err_hif: -- cgit v1.2.3 From 5afa5aa79680ee107fef1195c80f5f67c54b6691 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:09:19 +0200 Subject: ath6kl: get rid of AR_DBG_LVL_CHECK() We don't need it as debug calls already have a log level and compiler should be smart enough to optimise away the code when ath6kl debug code is not enabled. Also it makes it easier to abstract core code to ath6kl_core.ko. In ath6kl_dump_registers() I had to change the debug level from ANY to IRQ as I removed the AR_DBG_LVL_CHECK() check before calling the function. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/debug.c | 35 +++++++++++++++------------------ drivers/net/wireless/ath/ath6kl/debug.h | 2 -- drivers/net/wireless/ath/ath6kl/hif.c | 5 ++--- drivers/net/wireless/ath/ath6kl/wmi.c | 3 --- 4 files changed, 18 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index fa7243b4144..bd2f1fae72a 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -82,31 +82,31 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, struct ath6kl_irq_enable_reg *irq_enable_reg) { - ath6kl_dbg(ATH6KL_DBG_ANY, ("<------- Register Table -------->\n")); + ath6kl_dbg(ATH6KL_DBG_IRQ, ("<------- Register Table -------->\n")); if (irq_proc_reg != NULL) { - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Host Int status: 0x%x\n", irq_proc_reg->host_int_status); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "CPU Int status: 0x%x\n", irq_proc_reg->cpu_int_status); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Error Int status: 0x%x\n", irq_proc_reg->error_int_status); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status: 0x%x\n", irq_proc_reg->counter_int_status); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Mbox Frame: 0x%x\n", irq_proc_reg->mbox_frame); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Rx Lookahead Valid: 0x%x\n", irq_proc_reg->rx_lkahd_valid); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Rx Lookahead 0: 0x%x\n", irq_proc_reg->rx_lkahd[0]); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Rx Lookahead 1: 0x%x\n", irq_proc_reg->rx_lkahd[1]); @@ -115,16 +115,16 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, * If the target supports GMBOX hardware, dump some * additional state. */ - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "GMBOX Host Int status 2: 0x%x\n", irq_proc_reg->host_int_status2); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "GMBOX RX Avail: 0x%x\n", irq_proc_reg->gmbox_rx_avail); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "GMBOX lookahead alias 0: 0x%x\n", irq_proc_reg->rx_gmbox_lkahd_alias[0]); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "GMBOX lookahead alias 1: 0x%x\n", irq_proc_reg->rx_gmbox_lkahd_alias[1]); } @@ -132,13 +132,13 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, } if (irq_enable_reg != NULL) { - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Int status Enable: 0x%x\n", irq_enable_reg->int_status_en); - ath6kl_dbg(ATH6KL_DBG_ANY, "Counter Int status Enable: 0x%x\n", + ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status Enable: 0x%x\n", irq_enable_reg->cntr_int_status_en); } - ath6kl_dbg(ATH6KL_DBG_ANY, "<------------------------------->\n"); + ath6kl_dbg(ATH6KL_DBG_IRQ, "<------------------------------->\n"); } static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist) @@ -175,9 +175,6 @@ void dump_cred_dist_stats(struct htc_target *target) { struct htc_endpoint_credit_dist *ep_list; - if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_CREDIT)) - return; - list_for_each_entry(ep_list, &target->cred_dist_list, list) dump_cred_dist(ep_list); diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 9853c9c125c..9dc39754a35 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -55,8 +55,6 @@ int ath6kl_printk(const char *level, const char *fmt, ...); #define ath6kl_warn(fmt, ...) \ ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__) -#define AR_DBG_LVL_CHECK(mask) (debug_mask & mask) - enum ath6kl_war { ATH6KL_WAR_INVALID_RATE, }; diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index e57da35e59f..711886860b5 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c @@ -429,9 +429,8 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) if (status) goto out; - if (AR_DBG_LVL_CHECK(ATH6KL_DBG_IRQ)) - ath6kl_dump_registers(dev, &dev->irq_proc_reg, - &dev->irq_en_reg); + ath6kl_dump_registers(dev, &dev->irq_proc_reg, + &dev->irq_en_reg); /* Update only those registers that are enabled */ host_int_status = dev->irq_proc_reg.host_int_status & diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index c2420f886ed..5d678bf372d 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -426,9 +426,6 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", evt->num_msg, evt->msg_len, evt->msg_type); - if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_WMI)) - return 0; - for (index = 0; index < evt->num_msg; index++) { size = sizeof(struct wmi_tx_complete_event) + (index * sizeof(struct tx_complete_msg_v1)); -- cgit v1.2.3 From 3b1b7d0985fdb26403678e49938a668ef7f772ea Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:09:27 +0200 Subject: ath6kl: convert ath6kl_dbg() and ath6kl_dbg_dump() into functions That way it's possible to not export debug_mask outside the upcoming ath6kl_core.ko and that makes it easier to ath6kl_core.ko in the following patch. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/debug.c | 30 ++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath6kl/debug.h | 25 ++++--------------------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index bd2f1fae72a..4ba6560f0bf 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -57,6 +57,36 @@ int ath6kl_printk(const char *level, const char *fmt, ...) #ifdef CONFIG_ATH6KL_DEBUG +void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + if (!(debug_mask & mask)) + return; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + ath6kl_printk(KERN_DEBUG, "%pV", &vaf); + + va_end(args); +} + +void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, + const char *msg, const char *prefix, + const void *buf, size_t len) +{ + if (debug_mask & mask) { + if (msg) + ath6kl_dbg(mask, "%s\n", msg); + + print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); + } +} + #define REG_OUTPUT_LEN_PER_LINE 25 #define REGTYPE_STR_LEN 100 diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 9dc39754a35..872a8ce5d8f 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -60,28 +60,11 @@ enum ath6kl_war { }; #ifdef CONFIG_ATH6KL_DEBUG -#define ath6kl_dbg(mask, fmt, ...) \ - ({ \ - int rtn; \ - if (debug_mask & mask) \ - rtn = ath6kl_printk(KERN_DEBUG, fmt, ##__VA_ARGS__); \ - else \ - rtn = 0; \ - \ - rtn; \ - }) -static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, - const char *msg, const char *prefix, - const void *buf, size_t len) -{ - if (debug_mask & mask) { - if (msg) - ath6kl_dbg(mask, "%s\n", msg); - - print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); - } -} +void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...); +void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, + const char *msg, const char *prefix, + const void *buf, size_t len); void ath6kl_dump_registers(struct ath6kl_device *dev, struct ath6kl_irq_proc_registers *irq_proc_reg, -- cgit v1.2.3 From d6a434d60e064a5f2bef1c13ca5ed84bfa6b8b4f Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:09:36 +0200 Subject: ath6kl: create ath6kl_core.ko Now ath6kl is ready for splitting core code to ath6kl_core.ko module. This also makes it possible to link both sdio and usb code to kernel at the same time, which earlier failed miserably. Reported-by: Stephen Rothwell Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/Makefile | 28 +++++++++++++++------------- drivers/net/wireless/ath/ath6kl/cfg80211.c | 3 +++ drivers/net/wireless/ath/ath6kl/core.c | 9 +++++++++ drivers/net/wireless/ath/ath6kl/debug.c | 3 +++ drivers/net/wireless/ath/ath6kl/hif.c | 5 +++++ drivers/net/wireless/ath/ath6kl/init.c | 3 +++ 6 files changed, 38 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index 854694b26a4..cbdc31c603f 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile @@ -21,16 +21,18 @@ # Author(s): ="Atheros" #------------------------------------------------------------------------------ -obj-$(CONFIG_ATH6KL) := ath6kl.o -ath6kl-y += debug.o -ath6kl-y += hif.o -ath6kl-y += htc.o -ath6kl-y += bmi.o -ath6kl-y += cfg80211.o -ath6kl-y += init.o -ath6kl-y += main.o -ath6kl-y += txrx.o -ath6kl-y += wmi.o -ath6kl-y += core.o -ath6kl-y += sdio.o -ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o +obj-$(CONFIG_ATH6KL) += ath6kl_core.o +ath6kl_core-y += debug.o +ath6kl_core-y += hif.o +ath6kl_core-y += htc.o +ath6kl_core-y += bmi.o +ath6kl_core-y += cfg80211.o +ath6kl_core-y += init.o +ath6kl_core-y += main.o +ath6kl_core-y += txrx.o +ath6kl_core-y += wmi.o +ath6kl_core-y += core.o +ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o + +obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o +ath6kl_sdio-y += sdio.o diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 7ff9806de50..594d246da8e 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -16,6 +16,7 @@ #include #include +#include #include "core.h" #include "cfg80211.h" @@ -1935,6 +1936,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, return 0; } +EXPORT_SYMBOL(ath6kl_cfg80211_suspend); int ath6kl_cfg80211_resume(struct ath6kl *ar) { @@ -1986,6 +1988,7 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar) return 0; } +EXPORT_SYMBOL(ath6kl_cfg80211_resume); #ifdef CONFIG_PM diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index 40fad5ec936..d764afec395 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -16,7 +16,9 @@ #include "core.h" +#include #include +#include #include "debug.h" #include "hif-ops.h" @@ -203,6 +205,7 @@ err_wq: return ret; } +EXPORT_SYMBOL(ath6kl_core_init); struct ath6kl *ath6kl_core_create(struct device *dev) { @@ -258,6 +261,7 @@ struct ath6kl *ath6kl_core_create(struct device *dev) return ar; } +EXPORT_SYMBOL(ath6kl_core_create); void ath6kl_core_cleanup(struct ath6kl *ar) { @@ -284,9 +288,14 @@ void ath6kl_core_cleanup(struct ath6kl *ar) ath6kl_cfg80211_cleanup(ar); } +EXPORT_SYMBOL(ath6kl_core_cleanup); void ath6kl_core_destroy(struct ath6kl *ar) { ath6kl_cfg80211_destroy(ar); } +EXPORT_SYMBOL(ath6kl_core_destroy); +MODULE_AUTHOR("Qualcomm Atheros"); +MODULE_DESCRIPTION("Core module for AR600x SDIO and USB devices."); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 4ba6560f0bf..6b546dc6672 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -54,6 +54,7 @@ int ath6kl_printk(const char *level, const char *fmt, ...) return rtn; } +EXPORT_SYMBOL(ath6kl_printk); #ifdef CONFIG_ATH6KL_DEBUG @@ -74,6 +75,7 @@ void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) va_end(args); } +EXPORT_SYMBOL(ath6kl_dbg); void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, const char *msg, const char *prefix, @@ -86,6 +88,7 @@ void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); } } +EXPORT_SYMBOL(ath6kl_dbg_dump); #define REG_OUTPUT_LEN_PER_LINE 25 #define REGTYPE_STR_LEN 100 diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index 711886860b5..d912da6ab0d 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c @@ -15,6 +15,8 @@ */ #include "hif.h" +#include + #include "core.h" #include "target.h" #include "hif-ops.h" @@ -59,6 +61,8 @@ int ath6kl_hif_rw_comp_handler(void *context, int status) return 0; } +EXPORT_SYMBOL(ath6kl_hif_rw_comp_handler); + #define REG_DUMP_COUNT_AR6003 60 #define REGISTER_DUMP_LEN_MAX 60 @@ -560,6 +564,7 @@ int ath6kl_hif_intr_bh_handler(struct ath6kl *ar) return status; } +EXPORT_SYMBOL(ath6kl_hif_intr_bh_handler); static int ath6kl_hif_enable_intrs(struct ath6kl_device *dev) { diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index b8252ced096..167dc41af2d 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -17,8 +17,10 @@ #include #include +#include #include #include + #include "core.h" #include "cfg80211.h" #include "target.h" @@ -1707,3 +1709,4 @@ void ath6kl_stop_txrx(struct ath6kl *ar) clear_bit(WLAN_ENABLED, &ar->flag); } +EXPORT_SYMBOL(ath6kl_stop_txrx); -- cgit v1.2.3 From 241b128b6b69ad41fc6f12cba45a3c3e64bce673 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:09:45 +0200 Subject: ath6kl: add back beginnings of USB support John Linville had to revert the part of USB support which was already in ath6kl due to build problems in commit cb00ec382b ("ath6kl: revert USB support"). Now that I fixed the build problems properly by adding ath6kl_core.ko kernel module it's possible to add back the (incomplete) USB support. This patch is a revert of John's patch and adds back the USB code which as already in ath6kl, only difference being minor changes in Makefile and adapting usb.c to new core function names. Note that USB support in ath6kl is not complete yet. This code only makes it possible to boot firmware but as HTC layer does not yet support USB it's not possible to send any WMI commands nor data packets to the firmware. That will be added soon. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/Kconfig | 25 +- drivers/net/wireless/ath/ath6kl/Makefile | 3 + drivers/net/wireless/ath/ath6kl/bmi.c | 10 +- drivers/net/wireless/ath/ath6kl/debug.h | 1 + drivers/net/wireless/ath/ath6kl/hif.c | 5 + drivers/net/wireless/ath/ath6kl/htc.c | 10 +- drivers/net/wireless/ath/ath6kl/sdio.c | 2 +- drivers/net/wireless/ath/ath6kl/usb.c | 431 +++++++++++++++++++++++++++++++ 8 files changed, 479 insertions(+), 8 deletions(-) create mode 100644 drivers/net/wireless/ath/ath6kl/usb.c diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index 3d5f8be20ea..d755a5e7ed2 100644 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig @@ -1,12 +1,29 @@ config ATH6KL - tristate "Atheros ath6kl support" + tristate "Atheros mobile chipsets support" + +config ATH6KL_SDIO + tristate "Atheros ath6kl SDIO support" + depends on ATH6KL depends on MMC depends on CFG80211 ---help--- This module adds support for wireless adapters based on - Atheros AR6003 chipset running over SDIO. If you choose to - build it as a module, it will be called ath6kl. Pls note - that AR6002 and AR6001 are not supported by this driver. + Atheros AR6003 and AR6004 chipsets running over SDIO. If you + choose to build it as a module, it will be called ath6kl_sdio. + Please note that AR6002 and AR6001 are not supported by this + driver. + +config ATH6KL_USB + tristate "Atheros ath6kl USB support" + depends on ATH6KL + depends on USB + depends on CFG80211 + depends on EXPERIMENTAL + ---help--- + This module adds support for wireless adapters based on + Atheros AR6004 chipset running over USB. This is still under + implementation and it isn't functional. If you choose to + build it as a module, it will be called ath6kl_usb. config ATH6KL_DEBUG bool "Atheros ath6kl debugging" diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index cbdc31c603f..9ba42fa0496 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile @@ -36,3 +36,6 @@ ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o ath6kl_sdio-y += sdio.o + +obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o +ath6kl_usb-y += usb.o diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c index bce3575c310..aef00d5a143 100644 --- a/drivers/net/wireless/ath/ath6kl/bmi.c +++ b/drivers/net/wireless/ath/ath6kl/bmi.c @@ -57,8 +57,14 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, return ret; } - ret = ath6kl_hif_bmi_read(ar, (u8 *)&targ_info->version, - sizeof(targ_info->version)); + if (ar->hif_type == ATH6KL_HIF_TYPE_USB) { + ret = ath6kl_hif_bmi_read(ar, (u8 *)targ_info, + sizeof(*targ_info)); + } else { + ret = ath6kl_hif_bmi_read(ar, (u8 *)&targ_info->version, + sizeof(targ_info->version)); + } + if (ret) { ath6kl_err("Unable to recv target info: %d\n", ret); return ret; diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 872a8ce5d8f..c4be6e50996 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -41,6 +41,7 @@ enum ATH6K_DEBUG_MASK { ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */ ATH6KL_DBG_WMI_DUMP = BIT(19), ATH6KL_DBG_SUSPEND = BIT(20), + ATH6KL_DBG_USB = BIT(21), ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ }; diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index d912da6ab0d..e911737ab34 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c @@ -693,6 +693,11 @@ int ath6kl_hif_setup(struct ath6kl_device *dev) ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n", dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr); + /* usb doesn't support enabling interrupts */ + /* FIXME: remove check once USB support is implemented */ + if (dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) + return 0; + status = ath6kl_hif_disable_intrs(dev); fail_setup: diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c index 073ddff3134..2d721903640 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.c +++ b/drivers/net/wireless/ath/ath6kl/htc.c @@ -2544,6 +2544,12 @@ int ath6kl_htc_wait_target(struct htc_target *target) struct htc_service_connect_resp resp; int status; + /* FIXME: remove once USB support is implemented */ + if (target->dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) { + ath6kl_err("HTC doesn't support USB yet. Patience!\n"); + return -EOPNOTSUPP; + } + /* we should be getting 1 control message that the target is ready */ packet = htc_wait_for_ctrl_msg(target); @@ -2773,7 +2779,9 @@ void ath6kl_htc_cleanup(struct htc_target *target) { struct htc_packet *packet, *tmp_packet; - ath6kl_hif_cleanup_scatter(target->dev->ar); + /* FIXME: remove check once USB support is implemented */ + if (target->dev->ar->hif_type != ATH6KL_HIF_TYPE_USB) + ath6kl_hif_cleanup_scatter(target->dev->ar); list_for_each_entry_safe(packet, tmp_packet, &target->free_ctrl_txbuf, list) { diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index bef32ecea79..7bb61077c40 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -1330,7 +1330,7 @@ static const struct sdio_device_id ath6kl_sdio_devices[] = { MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices); static struct sdio_driver ath6kl_sdio_driver = { - .name = "ath6kl", + .name = "ath6kl_sdio", .id_table = ath6kl_sdio_devices, .probe = ath6kl_sdio_probe, .remove = ath6kl_sdio_remove, diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c new file mode 100644 index 00000000000..c72567c6d33 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/usb.c @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2007-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "debug.h" +#include "core.h" + +/* usb device object */ +struct ath6kl_usb { + struct usb_device *udev; + struct usb_interface *interface; + u8 *diag_cmd_buffer; + u8 *diag_resp_buffer; + struct ath6kl *ar; +}; + +/* diagnostic command defnitions */ +#define ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD 1 +#define ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP 2 +#define ATH6KL_USB_CONTROL_REQ_DIAG_CMD 3 +#define ATH6KL_USB_CONTROL_REQ_DIAG_RESP 4 + +#define ATH6KL_USB_CTRL_DIAG_CC_READ 0 +#define ATH6KL_USB_CTRL_DIAG_CC_WRITE 1 + +struct ath6kl_usb_ctrl_diag_cmd_write { + __le32 cmd; + __le32 address; + __le32 value; + __le32 _pad[1]; +} __packed; + +struct ath6kl_usb_ctrl_diag_cmd_read { + __le32 cmd; + __le32 address; +} __packed; + +struct ath6kl_usb_ctrl_diag_resp_read { + __le32 value; +} __packed; + +#define ATH6KL_USB_MAX_DIAG_CMD (sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)) +#define ATH6KL_USB_MAX_DIAG_RESP (sizeof(struct ath6kl_usb_ctrl_diag_resp_read)) + +static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb) +{ + usb_set_intfdata(ar_usb->interface, NULL); + + kfree(ar_usb->diag_cmd_buffer); + kfree(ar_usb->diag_resp_buffer); + + kfree(ar_usb); +} + +static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface) +{ + struct ath6kl_usb *ar_usb = NULL; + struct usb_device *dev = interface_to_usbdev(interface); + int status = 0; + + ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL); + if (ar_usb == NULL) + goto fail_ath6kl_usb_create; + + memset(ar_usb, 0, sizeof(struct ath6kl_usb)); + usb_set_intfdata(interface, ar_usb); + ar_usb->udev = dev; + ar_usb->interface = interface; + + ar_usb->diag_cmd_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_CMD, GFP_KERNEL); + if (ar_usb->diag_cmd_buffer == NULL) { + status = -ENOMEM; + goto fail_ath6kl_usb_create; + } + + ar_usb->diag_resp_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_RESP, + GFP_KERNEL); + if (ar_usb->diag_resp_buffer == NULL) { + status = -ENOMEM; + goto fail_ath6kl_usb_create; + } + +fail_ath6kl_usb_create: + if (status != 0) { + ath6kl_usb_destroy(ar_usb); + ar_usb = NULL; + } + return ar_usb; +} + +static void ath6kl_usb_device_detached(struct usb_interface *interface) +{ + struct ath6kl_usb *ar_usb; + + ar_usb = usb_get_intfdata(interface); + if (ar_usb == NULL) + return; + + ath6kl_stop_txrx(ar_usb->ar); + + ath6kl_core_cleanup(ar_usb->ar); + + ath6kl_usb_destroy(ar_usb); +} + +static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, + u8 req, u16 value, u16 index, void *data, + u32 size) +{ + u8 *buf = NULL; + int ret; + + if (size > 0) { + buf = kmalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + memcpy(buf, data, size); + } + + /* note: if successful returns number of bytes transfered */ + ret = usb_control_msg(ar_usb->udev, + usb_sndctrlpipe(ar_usb->udev, 0), + req, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, buf, + size, 1000); + + if (ret < 0) { + ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", + __func__, ret); + } + + kfree(buf); + + return 0; +} + +static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb, + u8 req, u16 value, u16 index, void *data, + u32 size) +{ + u8 *buf = NULL; + int ret; + + if (size > 0) { + buf = kmalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + } + + /* note: if successful returns number of bytes transfered */ + ret = usb_control_msg(ar_usb->udev, + usb_rcvctrlpipe(ar_usb->udev, 0), + req, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, buf, + size, 2 * HZ); + + if (ret < 0) { + ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", + __func__, ret); + } + + memcpy((u8 *) data, buf, size); + + kfree(buf); + + return 0; +} + +static int ath6kl_usb_ctrl_msg_exchange(struct ath6kl_usb *ar_usb, + u8 req_val, u8 *req_buf, u32 req_len, + u8 resp_val, u8 *resp_buf, u32 *resp_len) +{ + int ret; + + /* send command */ + ret = ath6kl_usb_submit_ctrl_out(ar_usb, req_val, 0, 0, + req_buf, req_len); + + if (ret != 0) + return ret; + + if (resp_buf == NULL) { + /* no expected response */ + return ret; + } + + /* get response */ + ret = ath6kl_usb_submit_ctrl_in(ar_usb, resp_val, 0, 0, + resp_buf, *resp_len); + + return ret; +} + +static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data) +{ + struct ath6kl_usb *ar_usb = ar->hif_priv; + struct ath6kl_usb_ctrl_diag_resp_read *resp; + struct ath6kl_usb_ctrl_diag_cmd_read *cmd; + u32 resp_len; + int ret; + + cmd = (struct ath6kl_usb_ctrl_diag_cmd_read *) ar_usb->diag_cmd_buffer; + + memset(cmd, 0, sizeof(*cmd)); + cmd->cmd = ATH6KL_USB_CTRL_DIAG_CC_READ; + cmd->address = cpu_to_le32(address); + resp_len = sizeof(*resp); + + ret = ath6kl_usb_ctrl_msg_exchange(ar_usb, + ATH6KL_USB_CONTROL_REQ_DIAG_CMD, + (u8 *) cmd, + sizeof(struct ath6kl_usb_ctrl_diag_cmd_write), + ATH6KL_USB_CONTROL_REQ_DIAG_RESP, + ar_usb->diag_resp_buffer, &resp_len); + + if (ret) + return ret; + + resp = (struct ath6kl_usb_ctrl_diag_resp_read *) + ar_usb->diag_resp_buffer; + + *data = le32_to_cpu(resp->value); + + return ret; +} + +static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data) +{ + struct ath6kl_usb *ar_usb = ar->hif_priv; + struct ath6kl_usb_ctrl_diag_cmd_write *cmd; + + cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer; + + memset(cmd, 0, sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)); + cmd->cmd = cpu_to_le32(ATH6KL_USB_CTRL_DIAG_CC_WRITE); + cmd->address = cpu_to_le32(address); + cmd->value = data; + + return ath6kl_usb_ctrl_msg_exchange(ar_usb, + ATH6KL_USB_CONTROL_REQ_DIAG_CMD, + (u8 *) cmd, + sizeof(*cmd), + 0, NULL, NULL); + +} + +static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) +{ + struct ath6kl_usb *ar_usb = ar->hif_priv; + int ret; + + /* get response */ + ret = ath6kl_usb_submit_ctrl_in(ar_usb, + ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP, + 0, 0, buf, len); + if (ret != 0) { + ath6kl_err("Unable to read the bmi data from the device: %d\n", + ret); + return ret; + } + + return 0; +} + +static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) +{ + struct ath6kl_usb *ar_usb = ar->hif_priv; + int ret; + + /* send command */ + ret = ath6kl_usb_submit_ctrl_out(ar_usb, + ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD, + 0, 0, buf, len); + if (ret != 0) { + ath6kl_err("unable to send the bmi data to the device: %d\n", + ret); + return ret; + } + + return 0; +} + +static int ath6kl_usb_power_on(struct ath6kl *ar) +{ + return 0; +} + +static int ath6kl_usb_power_off(struct ath6kl *ar) +{ + return 0; +} + +static const struct ath6kl_hif_ops ath6kl_usb_ops = { + .diag_read32 = ath6kl_usb_diag_read32, + .diag_write32 = ath6kl_usb_diag_write32, + .bmi_read = ath6kl_usb_bmi_read, + .bmi_write = ath6kl_usb_bmi_write, + .power_on = ath6kl_usb_power_on, + .power_off = ath6kl_usb_power_off, +}; + +/* ath6kl usb driver registered functions */ +static int ath6kl_usb_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(interface); + struct ath6kl *ar; + struct ath6kl_usb *ar_usb = NULL; + int vendor_id, product_id; + int ret = 0; + + usb_get_dev(dev); + + vendor_id = le16_to_cpu(dev->descriptor.idVendor); + product_id = le16_to_cpu(dev->descriptor.idProduct); + + ath6kl_dbg(ATH6KL_DBG_USB, "vendor_id = %04x\n", vendor_id); + ath6kl_dbg(ATH6KL_DBG_USB, "product_id = %04x\n", product_id); + + if (interface->cur_altsetting) + ath6kl_dbg(ATH6KL_DBG_USB, "USB Interface %d\n", + interface->cur_altsetting->desc.bInterfaceNumber); + + + if (dev->speed == USB_SPEED_HIGH) + ath6kl_dbg(ATH6KL_DBG_USB, "USB 2.0 Host\n"); + else + ath6kl_dbg(ATH6KL_DBG_USB, "USB 1.1 Host\n"); + + ar_usb = ath6kl_usb_create(interface); + + if (ar_usb == NULL) { + ret = -ENOMEM; + goto err_usb_put; + } + + ar = ath6kl_core_create(&ar_usb->udev->dev); + if (ar == NULL) { + ath6kl_err("Failed to alloc ath6kl core\n"); + ret = -ENOMEM; + goto err_usb_destroy; + } + + ar->hif_priv = ar_usb; + ar->hif_type = ATH6KL_HIF_TYPE_USB; + ar->hif_ops = &ath6kl_usb_ops; + ar->mbox_info.block_size = 16; + ar->bmi.max_data_size = 252; + + ar_usb->ar = ar; + + ret = ath6kl_core_init(ar); + if (ret) { + ath6kl_err("Failed to init ath6kl core: %d\n", ret); + goto err_core_free; + } + + return ret; + +err_core_free: + ath6kl_core_destroy(ar); +err_usb_destroy: + ath6kl_usb_destroy(ar_usb); +err_usb_put: + usb_put_dev(dev); + + return ret; +} + +static void ath6kl_usb_remove(struct usb_interface *interface) +{ + usb_put_dev(interface_to_usbdev(interface)); + ath6kl_usb_device_detached(interface); +} + +/* table of devices that work with this driver */ +static struct usb_device_id ath6kl_usb_ids[] = { + {USB_DEVICE(0x0cf3, 0x9374)}, + { /* Terminating entry */ }, +}; + +MODULE_DEVICE_TABLE(usb, ath6kl_usb_ids); + +static struct usb_driver ath6kl_usb_driver = { + .name = "ath6kl_usb", + .probe = ath6kl_usb_probe, + .disconnect = ath6kl_usb_remove, + .id_table = ath6kl_usb_ids, +}; + +static int ath6kl_usb_init(void) +{ + usb_register(&ath6kl_usb_driver); + return 0; +} + +static void ath6kl_usb_exit(void) +{ + usb_deregister(&ath6kl_usb_driver); +} + +module_init(ath6kl_usb_init); +module_exit(ath6kl_usb_exit); + +MODULE_AUTHOR("Atheros Communications, Inc."); +MODULE_DESCRIPTION("Driver support for Atheros AR600x USB devices"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); -- cgit v1.2.3 From 7a950ea81de6cbf96e721599bfacdb409908cd00 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Sat, 21 Jan 2012 15:22:48 +0530 Subject: ath6kl: Make sure to delete rx aggregation timer in aggr_reset_state() The timer which is used to flush rx aggregation frames needs to be disabled when resetting the aggregation state. This is found in code review. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/txrx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index dd633714260..cb7421a3161 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -1685,6 +1685,11 @@ void aggr_reset_state(struct aggr_info *aggr_info) { u8 tid; + if (aggr_info->timer_scheduled) { + del_timer(&aggr_info->timer); + aggr_info->timer_scheduled = false; + } + for (tid = 0; tid < NUM_OF_TIDS; tid++) aggr_delete_tid_state(aggr_info, tid); } -- cgit v1.2.3 From 0e7de662bcf33567cc957995c38dc10959cc22bf Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Sat, 21 Jan 2012 15:22:49 +0530 Subject: ath6kl: Fix memory leak when unloading ath6kl_sdio The patch "ath6kl: create core.c" removes wiphy_free() from ath6kl_cfg80211_cleanup() and misses to free wiphy in ath6kl_sdio_remove(). This patch fixes this regression. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/sdio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 7bb61077c40..d9f55914b89 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -1314,6 +1314,7 @@ static void ath6kl_sdio_remove(struct sdio_func *func) cancel_work_sync(&ar_sdio->wr_async_work); ath6kl_core_cleanup(ar_sdio->ar); + ath6kl_core_destroy(ar_sdio->ar); kfree(ar_sdio->dma_buffer); kfree(ar_sdio); -- cgit v1.2.3 From 7baef812eb5f02ccacf6fac3888c1cfa36293e91 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Sat, 21 Jan 2012 15:22:50 +0530 Subject: ath6kl: Define a structure for connection specific aggregation information This patch just groups connection specific aggregation information from struct aggr_info into a new structure (struct aggr_info_conn) so that, in softAP mode, this can be used when each connected station is made to have it's own aggregation state. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 +- drivers/net/wireless/ath/ath6kl/core.h | 11 +- drivers/net/wireless/ath/ath6kl/txrx.c | 166 ++++++++++++++++------------- 3 files changed, 98 insertions(+), 81 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 594d246da8e..8bf447a6a84 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2694,7 +2694,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar) static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) { - vif->aggr_cntxt = aggr_init(vif->ndev); + vif->aggr_cntxt = aggr_init(vif); if (!vif->aggr_cntxt) { ath6kl_err("failed to initialize aggr\n"); return -ENOMEM; diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 67b22e4bbcc..1b9054f8f4e 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -242,14 +242,19 @@ struct rxtid_stats { u32 num_bar; }; -struct aggr_info { +struct aggr_info_conn { u8 aggr_sz; u8 timer_scheduled; struct timer_list timer; struct net_device *dev; struct rxtid rx_tid[NUM_OF_TIDS]; - struct sk_buff_head free_q; struct rxtid_stats stat[NUM_OF_TIDS]; + struct aggr_info *aggr_info; +}; + +struct aggr_info { + struct aggr_info_conn *aggr_conn; + struct sk_buff_head rx_amsdu_freeq; }; struct ath6kl_wep_key { @@ -707,7 +712,7 @@ struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar); void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie); int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); -struct aggr_info *aggr_init(struct net_device *dev); +struct aggr_info *aggr_init(struct ath6kl_vif *vif); void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint); void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count); diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index cb7421a3161..8407d0103dc 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -819,10 +819,12 @@ static struct sk_buff *aggr_get_free_skb(struct aggr_info *p_aggr) { struct sk_buff *skb = NULL; - if (skb_queue_len(&p_aggr->free_q) < (AGGR_NUM_OF_FREE_NETBUFS >> 2)) - ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS); + if (skb_queue_len(&p_aggr->rx_amsdu_freeq) < + (AGGR_NUM_OF_FREE_NETBUFS >> 2)) + ath6kl_alloc_netbufs(&p_aggr->rx_amsdu_freeq, + AGGR_NUM_OF_FREE_NETBUFS); - skb = skb_dequeue(&p_aggr->free_q); + skb = skb_dequeue(&p_aggr->rx_amsdu_freeq); return skb; } @@ -998,12 +1000,14 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, struct skb_hold_q *node; u16 idx, idx_end, seq_end; struct rxtid_stats *stats; + struct aggr_info_conn *agg_conn; - if (!p_aggr) + if (!p_aggr || !p_aggr->aggr_conn) return; - rxtid = &p_aggr->rx_tid[tid]; - stats = &p_aggr->stat[tid]; + agg_conn = p_aggr->aggr_conn; + rxtid = &agg_conn->rx_tid[tid]; + stats = &agg_conn->stat[tid]; idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); @@ -1048,7 +1052,7 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, stats->num_delivered += skb_queue_len(&rxtid->q); while ((skb = skb_dequeue(&rxtid->q))) - ath6kl_deliver_frames_to_nw_stack(p_aggr->dev, skb); + ath6kl_deliver_frames_to_nw_stack(agg_conn->dev, skb); } static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, @@ -1062,9 +1066,10 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, u16 idx, st, cur, end; bool is_queued = false; u16 extended_end; + struct aggr_info_conn *agg_conn = agg_info->aggr_conn; - rxtid = &agg_info->rx_tid[tid]; - stats = &agg_info->stat[tid]; + rxtid = &agg_conn->rx_tid[tid]; + stats = &agg_conn->stat[tid]; stats->num_into_aggr++; @@ -1074,7 +1079,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, is_queued = true; stats->num_amsdu++; while ((skb = skb_dequeue(&rxtid->q))) - ath6kl_deliver_frames_to_nw_stack(agg_info->dev, + ath6kl_deliver_frames_to_nw_stack(agg_conn->dev, skb); } return is_queued; @@ -1152,7 +1157,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, aggr_deque_frms(agg_info, tid, 0, 1); - if (agg_info->timer_scheduled) + if (agg_conn->timer_scheduled) rxtid->progress = true; else for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { @@ -1163,8 +1168,8 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, * the frame doesn't remain stuck * forever. */ - agg_info->timer_scheduled = true; - mod_timer(&agg_info->timer, + agg_conn->timer_scheduled = true; + mod_timer(&agg_conn->timer, (jiffies + HZ * (AGGR_RX_TIMEOUT) / 1000)); rxtid->progress = false; @@ -1525,13 +1530,13 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) static void aggr_timeout(unsigned long arg) { u8 i, j; - struct aggr_info *p_aggr = (struct aggr_info *) arg; + struct aggr_info_conn *aggr_conn = (struct aggr_info_conn *) arg; struct rxtid *rxtid; struct rxtid_stats *stats; for (i = 0; i < NUM_OF_TIDS; i++) { - rxtid = &p_aggr->rx_tid[i]; - stats = &p_aggr->stat[i]; + rxtid = &aggr_conn->rx_tid[i]; + stats = &aggr_conn->stat[i]; if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) continue; @@ -1542,18 +1547,18 @@ static void aggr_timeout(unsigned long arg) rxtid->seq_next, ((rxtid->seq_next + rxtid->hold_q_sz-1) & ATH6KL_MAX_SEQ_NO)); - aggr_deque_frms(p_aggr, i, 0, 0); + aggr_deque_frms(aggr_conn->aggr_info, i, 0, 0); } - p_aggr->timer_scheduled = false; + aggr_conn->timer_scheduled = false; for (i = 0; i < NUM_OF_TIDS; i++) { - rxtid = &p_aggr->rx_tid[i]; + rxtid = &aggr_conn->rx_tid[i]; if (rxtid->aggr && rxtid->hold_q) { for (j = 0; j < rxtid->hold_q_sz; j++) { if (rxtid->hold_q[j].skb) { - p_aggr->timer_scheduled = true; + aggr_conn->timer_scheduled = true; rxtid->timer_mon = true; rxtid->progress = false; break; @@ -1565,24 +1570,24 @@ static void aggr_timeout(unsigned long arg) } } - if (p_aggr->timer_scheduled) - mod_timer(&p_aggr->timer, + if (aggr_conn->timer_scheduled) + mod_timer(&aggr_conn->timer, jiffies + msecs_to_jiffies(AGGR_RX_TIMEOUT)); } -static void aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid) +static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid) { struct rxtid *rxtid; struct rxtid_stats *stats; - if (!p_aggr || tid >= NUM_OF_TIDS) + if (!aggr_conn || tid >= NUM_OF_TIDS) return; - rxtid = &p_aggr->rx_tid[tid]; - stats = &p_aggr->stat[tid]; + rxtid = &aggr_conn->rx_tid[tid]; + stats = &aggr_conn->stat[tid]; if (rxtid->aggr) - aggr_deque_frms(p_aggr, tid, 0, 0); + aggr_deque_frms(aggr_conn->aggr_info, tid, 0, 0); rxtid->aggr = false; rxtid->progress = false; @@ -1601,22 +1606,25 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, u8 win_sz) { struct aggr_info *p_aggr = vif->aggr_cntxt; + struct aggr_info_conn *aggr_conn; struct rxtid *rxtid; struct rxtid_stats *stats; u16 hold_q_size; - if (!p_aggr) + if (!p_aggr || !p_aggr->aggr_conn) return; - rxtid = &p_aggr->rx_tid[tid]; - stats = &p_aggr->stat[tid]; + aggr_conn = p_aggr->aggr_conn; + + rxtid = &aggr_conn->rx_tid[tid]; + stats = &aggr_conn->stat[tid]; if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX) ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n", __func__, win_sz, tid); if (rxtid->aggr) - aggr_delete_tid_state(p_aggr, tid); + aggr_delete_tid_state(aggr_conn, tid); rxtid->seq_next = seq_no; hold_q_size = TID_WINDOW_SZ(win_sz) * sizeof(struct skb_hold_q); @@ -1632,31 +1640,23 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, rxtid->aggr = true; } -struct aggr_info *aggr_init(struct net_device *dev) +static void aggr_conn_init(struct ath6kl_vif *vif, + struct aggr_info_conn *aggr_conn) { - struct aggr_info *p_aggr = NULL; struct rxtid *rxtid; u8 i; - p_aggr = kzalloc(sizeof(struct aggr_info), GFP_KERNEL); - if (!p_aggr) { - ath6kl_err("failed to alloc memory for aggr_node\n"); - return NULL; - } - - p_aggr->aggr_sz = AGGR_SZ_DEFAULT; - p_aggr->dev = dev; - init_timer(&p_aggr->timer); - p_aggr->timer.function = aggr_timeout; - p_aggr->timer.data = (unsigned long) p_aggr; - - p_aggr->timer_scheduled = false; - skb_queue_head_init(&p_aggr->free_q); + aggr_conn->aggr_sz = AGGR_SZ_DEFAULT; + aggr_conn->dev = vif->ndev; + init_timer(&aggr_conn->timer); + aggr_conn->timer.function = aggr_timeout; + aggr_conn->timer.data = (unsigned long) aggr_conn; + aggr_conn->aggr_info = vif->aggr_cntxt; - ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS); + aggr_conn->timer_scheduled = false; for (i = 0; i < NUM_OF_TIDS; i++) { - rxtid = &p_aggr->rx_tid[i]; + rxtid = &aggr_conn->rx_tid[i]; rxtid->aggr = false; rxtid->progress = false; rxtid->timer_mon = false; @@ -1664,6 +1664,30 @@ struct aggr_info *aggr_init(struct net_device *dev) spin_lock_init(&rxtid->lock); } +} + +struct aggr_info *aggr_init(struct ath6kl_vif *vif) +{ + struct aggr_info *p_aggr = NULL; + + p_aggr = kzalloc(sizeof(struct aggr_info), GFP_KERNEL); + if (!p_aggr) { + ath6kl_err("failed to alloc memory for aggr_node\n"); + return NULL; + } + + p_aggr->aggr_conn = kzalloc(sizeof(struct aggr_info_conn), GFP_KERNEL); + if (!p_aggr->aggr_conn) { + ath6kl_err("failed to alloc memory for connection specific aggr info\n"); + kfree(p_aggr); + return NULL; + } + + aggr_conn_init(vif, p_aggr->aggr_conn); + + skb_queue_head_init(&p_aggr->rx_amsdu_freeq); + ath6kl_alloc_netbufs(&p_aggr->rx_amsdu_freeq, AGGR_NUM_OF_FREE_NETBUFS); + return p_aggr; } @@ -1671,27 +1695,32 @@ void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid) { struct aggr_info *p_aggr = vif->aggr_cntxt; struct rxtid *rxtid; + struct aggr_info_conn *aggr_conn; - if (!p_aggr) + if (!p_aggr || !p_aggr->aggr_conn) return; - rxtid = &p_aggr->rx_tid[tid]; + aggr_conn = p_aggr->aggr_conn; + rxtid = &aggr_conn->rx_tid[tid]; if (rxtid->aggr) - aggr_delete_tid_state(p_aggr, tid); + aggr_delete_tid_state(aggr_conn, tid); } void aggr_reset_state(struct aggr_info *aggr_info) { u8 tid; - if (aggr_info->timer_scheduled) { - del_timer(&aggr_info->timer); - aggr_info->timer_scheduled = false; + if (!aggr_info || !aggr_info->aggr_conn) + return; + + if (aggr_info->aggr_conn->timer_scheduled) { + del_timer(&aggr_info->aggr_conn->timer); + aggr_info->aggr_conn->timer_scheduled = false; } for (tid = 0; tid < NUM_OF_TIDS; tid++) - aggr_delete_tid_state(aggr_info, tid); + aggr_delete_tid_state(aggr_info->aggr_conn, tid); } /* clean up our amsdu buffer list */ @@ -1718,28 +1747,11 @@ void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar) void aggr_module_destroy(struct aggr_info *aggr_info) { - struct rxtid *rxtid; - u8 i, k; - - if (!aggr_info) + if (!aggr_info || !aggr_info->aggr_conn) return; - if (aggr_info->timer_scheduled) { - del_timer(&aggr_info->timer); - aggr_info->timer_scheduled = false; - } - - for (i = 0; i < NUM_OF_TIDS; i++) { - rxtid = &aggr_info->rx_tid[i]; - if (rxtid->hold_q) { - for (k = 0; k < rxtid->hold_q_sz; k++) - dev_kfree_skb(rxtid->hold_q[k].skb); - kfree(rxtid->hold_q); - } - - skb_queue_purge(&rxtid->q); - } - - skb_queue_purge(&aggr_info->free_q); + aggr_reset_state(aggr_info); + skb_queue_purge(&aggr_info->rx_amsdu_freeq); + kfree(aggr_info->aggr_conn); kfree(aggr_info); } -- cgit v1.2.3 From 17741c8db4f53200a51600d1644ee6a2b76f0984 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Sat, 21 Jan 2012 15:22:51 +0530 Subject: ath6kl: Pass vif instead of ar to ath6kl_add_new_sta() This will be used when initializing station specific aggregation information. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 3a3b2cc9940..acb4acb7171 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -52,10 +52,11 @@ struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid) return conn; } -static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, - size_t ielen, u8 keymgmt, u8 ucipher, u8 auth, - u8 apsd_info) +static void ath6kl_add_new_sta(struct ath6kl_vif *vif, u8 *mac, u16 aid, + u8 *wpaie, size_t ielen, u8 keymgmt, + u8 ucipher, u8 auth, u8 apsd_info) { + struct ath6kl *ar = vif->ar; struct ath6kl_sta *sta; u8 free_slot; @@ -430,7 +431,6 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, u8 keymgmt, u8 ucipher, u8 auth, u8 assoc_req_len, u8 *assoc_info, u8 apsd_info) { - struct ath6kl *ar = vif->ar; u8 *ies = NULL, *wpa_ie = NULL, *pos; size_t ies_len = 0; struct station_info sinfo; @@ -484,7 +484,7 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, pos += 2 + pos[1]; } - ath6kl_add_new_sta(ar, mac_addr, aid, wpa_ie, + ath6kl_add_new_sta(vif, mac_addr, aid, wpa_ie, wpa_ie ? 2 + wpa_ie[1] : 0, keymgmt, ucipher, auth, apsd_info); -- cgit v1.2.3 From 3fdc099109e75359e5de54c56478c06255850741 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Sat, 21 Jan 2012 15:22:52 +0530 Subject: ath6kl: Fix bug in using tid given by addba/delba req events The tid which is given in addba/delba req event is not just tid but also muxed with the assoc id (MSB 4 bits) which can be used to determine the corresponding connected station in softap mode. The actual tid is LSB 4 bits. Using the tid as it is with rx_tid[] would result in OOB or invalid memory access in AP mode. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/txrx.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 8407d0103dc..8cf7b2fa0f4 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -17,6 +17,17 @@ #include "core.h" #include "debug.h" +/* + * tid - tid_mux0..tid_mux3 + * aid - tid_mux4..tid_mux7 + */ +#define ATH6KL_TID_MASK 0xf + +static inline u8 ath6kl_get_tid(u8 tid_mux) +{ + return tid_mux & ATH6KL_TID_MASK; +} + static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, u32 *map_no) { @@ -1602,7 +1613,7 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid) memset(stats, 0, sizeof(struct rxtid_stats)); } -void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, +void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no, u8 win_sz) { struct aggr_info *p_aggr = vif->aggr_cntxt; @@ -1610,12 +1621,17 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, struct rxtid *rxtid; struct rxtid_stats *stats; u16 hold_q_size; + u8 tid; if (!p_aggr || !p_aggr->aggr_conn) return; aggr_conn = p_aggr->aggr_conn; + tid = ath6kl_get_tid(tid_mux); + if (tid >= NUM_OF_TIDS) + return; + rxtid = &aggr_conn->rx_tid[tid]; stats = &aggr_conn->stat[tid]; @@ -1691,15 +1707,20 @@ struct aggr_info *aggr_init(struct ath6kl_vif *vif) return p_aggr; } -void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid) +void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid_mux) { struct aggr_info *p_aggr = vif->aggr_cntxt; struct rxtid *rxtid; struct aggr_info_conn *aggr_conn; + u8 tid; if (!p_aggr || !p_aggr->aggr_conn) return; + tid = ath6kl_get_tid(tid_mux); + if (tid >= NUM_OF_TIDS) + return; + aggr_conn = p_aggr->aggr_conn; rxtid = &aggr_conn->rx_tid[tid]; -- cgit v1.2.3 From 1d2a4456de20db73362c86c88fe9c02169f29d0a Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Sat, 21 Jan 2012 15:22:53 +0530 Subject: ath6kl: Fix bug in maintaining aggregation state in AP mode Currently rx aggregation related states are maintained per vif, but this will not properly work when operating in AP mode. Aggregation is completely broken when more than one 11n stations are connected to AP mode vif. Fix this issue by keeping station specific aggregation state in sta_list. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 5 ++ drivers/net/wireless/ath/ath6kl/core.c | 7 ++ drivers/net/wireless/ath/ath6kl/core.h | 4 +- drivers/net/wireless/ath/ath6kl/init.c | 4 ++ drivers/net/wireless/ath/ath6kl/main.c | 7 +- drivers/net/wireless/ath/ath6kl/txrx.c | 106 ++++++++++++++++++----------- 6 files changed, 88 insertions(+), 45 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 8bf447a6a84..fed7b8077f5 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2871,6 +2871,11 @@ struct ath6kl *ath6kl_cfg80211_create(void) /* Note: ar variable must not be accessed after calling this! */ void ath6kl_cfg80211_destroy(struct ath6kl *ar) { + int i; + + for (i = 0; i < AP_MAX_NUM_STA; i++) + kfree(ar->sta_list[i].aggr_conn); + wiphy_free(ar->wiphy); } diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index d764afec395..0d92e7179f8 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -253,6 +253,13 @@ struct ath6kl *ath6kl_core_create(struct device *dev) spin_lock_init(&ar->sta_list[ctr].psq_lock); skb_queue_head_init(&ar->sta_list[ctr].psq); skb_queue_head_init(&ar->sta_list[ctr].apsdq); + ar->sta_list[ctr].aggr_conn = + kzalloc(sizeof(struct aggr_info_conn), GFP_KERNEL); + if (!ar->sta_list[ctr].aggr_conn) { + ath6kl_err("Failed to allocate memory for sta aggregation information\n"); + ath6kl_core_destroy(ar); + return NULL; + } } skb_queue_head_init(&ar->mcastpsq); diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 1b9054f8f4e..ed9fcc11b5f 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -298,6 +298,7 @@ struct ath6kl_sta { spinlock_t psq_lock; u8 apsd_info; struct sk_buff_head apsdq; + struct aggr_info_conn *aggr_conn; }; struct ath6kl_version { @@ -713,6 +714,7 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie); int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); struct aggr_info *aggr_init(struct ath6kl_vif *vif); +void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info_conn *aggr_conn); void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint); void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count); @@ -720,7 +722,7 @@ struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target, enum htc_endpoint_id endpoint, int len); void aggr_module_destroy(struct aggr_info *aggr_info); -void aggr_reset_state(struct aggr_info *aggr_info); +void aggr_reset_state(struct aggr_info_conn *aggr_conn); struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 * node_addr); struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 167dc41af2d..4d8eb1cca6e 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1660,6 +1660,7 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) void ath6kl_stop_txrx(struct ath6kl *ar) { struct ath6kl_vif *vif, *tmp_vif; + int i; set_bit(DESTROY_IN_PROGRESS, &ar->flag); @@ -1668,6 +1669,9 @@ void ath6kl_stop_txrx(struct ath6kl *ar) return; } + for (i = 0; i < AP_MAX_NUM_STA; i++) + aggr_reset_state(ar->sta_list[i].aggr_conn); + spin_lock_bh(&ar->list_lock); list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) { list_del(&vif->list); diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index acb4acb7171..39da1f98da8 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -74,6 +74,7 @@ static void ath6kl_add_new_sta(struct ath6kl_vif *vif, u8 *mac, u16 aid, ar->sta_list_index = ar->sta_list_index | (1 << free_slot); ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid); + aggr_conn_init(vif, sta->aggr_conn); } static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) @@ -94,7 +95,7 @@ static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) sta->sta_flags = 0; ar->sta_list_index = ar->sta_list_index & ~(1 << i); - + aggr_reset_state(sta->aggr_conn); } static u8 ath6kl_remove_sta(struct ath6kl *ar, u8 *mac, u16 reason) @@ -602,7 +603,7 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, netif_carrier_on(vif->ndev); spin_unlock_bh(&vif->if_lock); - aggr_reset_state(vif->aggr_cntxt); + aggr_reset_state(vif->aggr_cntxt->aggr_conn); vif->reconnect_flag = 0; if ((vif->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) { @@ -924,7 +925,7 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid, assoc_resp_len, assoc_info, prot_reason_status); - aggr_reset_state(vif->aggr_cntxt); + aggr_reset_state(vif->aggr_cntxt->aggr_conn); del_timer(&vif->disconnect_timer); diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 8cf7b2fa0f4..62c12102e14 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -22,12 +22,18 @@ * aid - tid_mux4..tid_mux7 */ #define ATH6KL_TID_MASK 0xf +#define ATH6KL_AID_SHIFT 4 static inline u8 ath6kl_get_tid(u8 tid_mux) { return tid_mux & ATH6KL_TID_MASK; } +static inline u8 ath6kl_get_aid(u8 tid_mux) +{ + return tid_mux >> ATH6KL_AID_SHIFT; +} + static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, u32 *map_no) { @@ -1003,7 +1009,7 @@ static void aggr_slice_amsdu(struct aggr_info *p_aggr, dev_kfree_skb(skb); } -static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, +static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid, u16 seq_no, u8 order) { struct sk_buff *skb; @@ -1011,12 +1017,7 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, struct skb_hold_q *node; u16 idx, idx_end, seq_end; struct rxtid_stats *stats; - struct aggr_info_conn *agg_conn; - if (!p_aggr || !p_aggr->aggr_conn) - return; - - agg_conn = p_aggr->aggr_conn; rxtid = &agg_conn->rx_tid[tid]; stats = &agg_conn->stat[tid]; @@ -1047,7 +1048,8 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, if (node->skb) { if (node->is_amsdu) - aggr_slice_amsdu(p_aggr, rxtid, node->skb); + aggr_slice_amsdu(agg_conn->aggr_info, rxtid, + node->skb); else skb_queue_tail(&rxtid->q, node->skb); node->skb = NULL; @@ -1066,7 +1068,7 @@ static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, ath6kl_deliver_frames_to_nw_stack(agg_conn->dev, skb); } -static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, +static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid, u16 seq_no, bool is_amsdu, struct sk_buff *frame) { @@ -1077,7 +1079,6 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, u16 idx, st, cur, end; bool is_queued = false; u16 extended_end; - struct aggr_info_conn *agg_conn = agg_info->aggr_conn; rxtid = &agg_conn->rx_tid[tid]; stats = &agg_conn->stat[tid]; @@ -1086,7 +1087,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, if (!rxtid->aggr) { if (is_amsdu) { - aggr_slice_amsdu(agg_info, rxtid, frame); + aggr_slice_amsdu(agg_conn->aggr_info, rxtid, frame); is_queued = true; stats->num_amsdu++; while ((skb = skb_dequeue(&rxtid->q))) @@ -1110,7 +1111,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, (cur < end || cur > extended_end)) || ((end > extended_end) && (cur > extended_end) && (cur < end))) { - aggr_deque_frms(agg_info, tid, 0, 0); + aggr_deque_frms(agg_conn, tid, 0, 0); if (cur >= rxtid->hold_q_sz - 1) rxtid->seq_next = cur - (rxtid->hold_q_sz - 1); else @@ -1127,7 +1128,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, st = ATH6KL_MAX_SEQ_NO - (rxtid->hold_q_sz - 2 - cur); - aggr_deque_frms(agg_info, tid, st, 0); + aggr_deque_frms(agg_conn, tid, st, 0); } stats->num_oow++; @@ -1166,7 +1167,7 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, spin_unlock_bh(&rxtid->lock); - aggr_deque_frms(agg_info, tid, 0, 1); + aggr_deque_frms(agg_conn, tid, 0, 1); if (agg_conn->timer_scheduled) rxtid->progress = true; @@ -1278,6 +1279,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) struct sk_buff *skb1 = NULL; struct ethhdr *datap = NULL; struct ath6kl_vif *vif; + struct aggr_info_conn *aggr_conn; u16 seq_no, offset; u8 tid, if_idx; @@ -1529,11 +1531,21 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) datap = (struct ethhdr *) skb->data; - if (is_unicast_ether_addr(datap->h_dest) && - aggr_process_recv_frm(vif->aggr_cntxt, tid, seq_no, - is_amsdu, skb)) - /* aggregation code will handle the skb */ - return; + if (is_unicast_ether_addr(datap->h_dest)) { + if (vif->nw_type == AP_NETWORK) { + conn = ath6kl_find_sta(vif, datap->h_source); + if (!conn) + return; + aggr_conn = conn->aggr_conn; + } else + aggr_conn = vif->aggr_cntxt->aggr_conn; + + if (aggr_process_recv_frm(aggr_conn, tid, seq_no, + is_amsdu, skb)) { + /* aggregation code will handle the skb */ + return; + } + } ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb); } @@ -1558,7 +1570,7 @@ static void aggr_timeout(unsigned long arg) rxtid->seq_next, ((rxtid->seq_next + rxtid->hold_q_sz-1) & ATH6KL_MAX_SEQ_NO)); - aggr_deque_frms(aggr_conn->aggr_info, i, 0, 0); + aggr_deque_frms(aggr_conn, i, 0, 0); } aggr_conn->timer_scheduled = false; @@ -1598,7 +1610,7 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid) stats = &aggr_conn->stat[tid]; if (rxtid->aggr) - aggr_deque_frms(aggr_conn->aggr_info, tid, 0, 0); + aggr_deque_frms(aggr_conn, tid, 0, 0); rxtid->aggr = false; rxtid->progress = false; @@ -1616,17 +1628,23 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid) void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no, u8 win_sz) { - struct aggr_info *p_aggr = vif->aggr_cntxt; - struct aggr_info_conn *aggr_conn; + struct ath6kl_sta *sta; + struct aggr_info_conn *aggr_conn = NULL; struct rxtid *rxtid; struct rxtid_stats *stats; u16 hold_q_size; - u8 tid; + u8 tid, aid; - if (!p_aggr || !p_aggr->aggr_conn) - return; + if (vif->nw_type == AP_NETWORK) { + aid = ath6kl_get_aid(tid_mux); + sta = ath6kl_find_sta_by_aid(vif->ar, aid); + if (sta) + aggr_conn = sta->aggr_conn; + } else + aggr_conn = vif->aggr_cntxt->aggr_conn; - aggr_conn = p_aggr->aggr_conn; + if (!aggr_conn) + return; tid = ath6kl_get_tid(tid_mux); if (tid >= NUM_OF_TIDS) @@ -1656,8 +1674,7 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no, rxtid->aggr = true; } -static void aggr_conn_init(struct ath6kl_vif *vif, - struct aggr_info_conn *aggr_conn) +void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info_conn *aggr_conn) { struct rxtid *rxtid; u8 i; @@ -1709,39 +1726,46 @@ struct aggr_info *aggr_init(struct ath6kl_vif *vif) void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid_mux) { - struct aggr_info *p_aggr = vif->aggr_cntxt; + struct ath6kl_sta *sta; struct rxtid *rxtid; - struct aggr_info_conn *aggr_conn; - u8 tid; + struct aggr_info_conn *aggr_conn = NULL; + u8 tid, aid; + + if (vif->nw_type == AP_NETWORK) { + aid = ath6kl_get_aid(tid_mux); + sta = ath6kl_find_sta_by_aid(vif->ar, aid); + if (sta) + aggr_conn = sta->aggr_conn; + } else + aggr_conn = vif->aggr_cntxt->aggr_conn; - if (!p_aggr || !p_aggr->aggr_conn) + if (!aggr_conn) return; tid = ath6kl_get_tid(tid_mux); if (tid >= NUM_OF_TIDS) return; - aggr_conn = p_aggr->aggr_conn; rxtid = &aggr_conn->rx_tid[tid]; if (rxtid->aggr) aggr_delete_tid_state(aggr_conn, tid); } -void aggr_reset_state(struct aggr_info *aggr_info) +void aggr_reset_state(struct aggr_info_conn *aggr_conn) { u8 tid; - if (!aggr_info || !aggr_info->aggr_conn) + if (!aggr_conn) return; - if (aggr_info->aggr_conn->timer_scheduled) { - del_timer(&aggr_info->aggr_conn->timer); - aggr_info->aggr_conn->timer_scheduled = false; + if (aggr_conn->timer_scheduled) { + del_timer(&aggr_conn->timer); + aggr_conn->timer_scheduled = false; } for (tid = 0; tid < NUM_OF_TIDS; tid++) - aggr_delete_tid_state(aggr_info->aggr_conn, tid); + aggr_delete_tid_state(aggr_conn, tid); } /* clean up our amsdu buffer list */ @@ -1768,10 +1792,10 @@ void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar) void aggr_module_destroy(struct aggr_info *aggr_info) { - if (!aggr_info || !aggr_info->aggr_conn) + if (!aggr_info) return; - aggr_reset_state(aggr_info); + aggr_reset_state(aggr_info->aggr_conn); skb_queue_purge(&aggr_info->rx_amsdu_freeq); kfree(aggr_info->aggr_conn); kfree(aggr_info); -- cgit v1.2.3 From de46fb079ff16fabb3bdf7892c9a2900a9880329 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 6 Jan 2012 15:47:59 -0800 Subject: iwlwifi: fix typo Fix few places of typo Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-testmode.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 185b69ef753..f97d06169b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -111,17 +111,17 @@ * * @IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: * @IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32: - * commands from user applicaiton to indirectly access peripheral register + * commands from user application to indirectly access peripheral register * * @IWL_TM_CMD_APP2DEV_READ_SRAM: * @IWL_TM_CMD_APP2DEV_DUMP_SRAM: - * commands from user applicaiton to read data in sram + * commands from user application to read data in sram * - * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Weak On Wireless LAN uCode image + * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Wake On Wireless LAN uCode image * @IWL_TM_CMD_APP2DEV_GET_FW_VERSION: retrieve uCode version * @IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: retrieve ID information in device * @IWL_TM_CMD_APP2DEV_GET_FW_INFO: - * retrieve informration of existing loaded uCode image + * retrieve information of existing loaded uCode image * */ enum iwl_tm_cmd_t { -- cgit v1.2.3 From 98d4bf0c49de0d7c68fa7e1f7bd0a37420f712ca Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 13 Jan 2012 11:56:11 +0100 Subject: iwlwifi: fix uCode event tracing Fix multiple bugs in event tracing: 1) If you enable uCode tracing with the device down, it will still attempt to access the device and continuously log "MAC is in deep sleep!" errors. Fix this by only starting logging when the device is actually alive. 2) Now you can set the flag when the device is down, but logging doesn't happen when you bring it up. To fix that, start logging when the device comes alive. This means we don't log before -- we could do that but I don't need it right now. 3) For some reason we read the error instead of the event log -- use the right pointer. 4) Optimise SRAM reading of event log header. 5) Fix reading write pointer == capacity, which can happen due to racy SRAM access 6) Most importantly: fix an error where we would try to read WAY too many events (like 2^32-300) when we read the wrap counter before it is updated by the uCode -- this does happen in practice and will cause the driver to hang the machine. 7) Finally, change the timer to 10ms instead of 100ms as 100ms is too slow to capture all data with a normal event log and with 100ms the log will wrap multiple times before we have a chance to read it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 99 +++++++++++++++++++++--------- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 7 ++- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- 3 files changed, 76 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7321e7d3140..3e429a3e518 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -315,7 +315,7 @@ static void iwl_bg_statistics_periodic(unsigned long data) static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, u32 start_idx, u32 num_events, - u32 mode) + u32 capacity, u32 mode) { u32 i; u32 ptr; /* SRAM byte address of log data */ @@ -338,6 +338,15 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr); rmb(); + /* + * Refuse to read more than would have fit into the log from + * the current start_idx. This used to happen due to the race + * described below, but now WARN because the code below should + * prevent it from happening here. + */ + if (WARN_ON(num_events > capacity - start_idx)) + num_events = capacity - start_idx; + /* * "time" is actually "data" for mode 0 (no timestamp). * place event id # at far right for easier visual parsing. @@ -346,12 +355,11 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); if (mode == 0) { - trace_iwlwifi_dev_ucode_cont_event(priv, - 0, time, ev); + trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev); } else { data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); - trace_iwlwifi_dev_ucode_cont_event(priv, - time, data, ev); + trace_iwlwifi_dev_ucode_cont_event(priv, time, + data, ev); } } /* Allow device to power down */ @@ -362,53 +370,83 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, static void iwl_continuous_event_trace(struct iwl_priv *priv) { u32 capacity; /* event log capacity in # entries */ + struct { + u32 capacity; + u32 mode; + u32 wrap_counter; + u32 write_counter; + } __packed read; u32 base; /* SRAM byte address of event log header */ u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ u32 num_wraps; /* # times uCode wrapped to top of log */ u32 next_entry; /* index of next entry to be written by uCode */ - base = priv->shrd->device_pointers.error_event_table; + base = priv->shrd->device_pointers.log_event_table; if (iwlagn_hw_valid_rtc_data_addr(base)) { - capacity = iwl_read_targ_mem(bus(priv), base); - num_wraps = iwl_read_targ_mem(bus(priv), - base + (2 * sizeof(u32))); - mode = iwl_read_targ_mem(bus(priv), base + (1 * sizeof(u32))); - next_entry = iwl_read_targ_mem(bus(priv), - base + (3 * sizeof(u32))); + iwl_read_targ_mem_words(bus(priv), base, &read, sizeof(read)); + + capacity = read.capacity; + mode = read.mode; + num_wraps = read.wrap_counter; + next_entry = read.write_counter; } else return; + /* + * Unfortunately, the uCode doesn't use temporary variables. + * Therefore, it can happen that we read next_entry == capacity, + * which really means next_entry == 0. + */ + if (unlikely(next_entry == capacity)) + next_entry = 0; + /* + * Additionally, the uCode increases the write pointer before + * the wraps counter, so if the write pointer is smaller than + * the old write pointer (wrap occurred) but we read that no + * wrap occurred, we actually read between the next_entry and + * num_wraps update (this does happen in practice!!) -- take + * that into account by increasing num_wraps. + */ + if (unlikely(next_entry < priv->event_log.next_entry && + num_wraps == priv->event_log.num_wraps)) + num_wraps++; + if (num_wraps == priv->event_log.num_wraps) { - iwl_print_cont_event_trace(priv, - base, priv->event_log.next_entry, - next_entry - priv->event_log.next_entry, - mode); + iwl_print_cont_event_trace( + priv, base, priv->event_log.next_entry, + next_entry - priv->event_log.next_entry, + capacity, mode); + priv->event_log.non_wraps_count++; } else { - if ((num_wraps - priv->event_log.num_wraps) > 1) + if (num_wraps - priv->event_log.num_wraps > 1) priv->event_log.wraps_more_count++; else priv->event_log.wraps_once_count++; + trace_iwlwifi_dev_ucode_wrap_event(priv, num_wraps - priv->event_log.num_wraps, next_entry, priv->event_log.next_entry); + if (next_entry < priv->event_log.next_entry) { - iwl_print_cont_event_trace(priv, base, - priv->event_log.next_entry, - capacity - priv->event_log.next_entry, - mode); + iwl_print_cont_event_trace( + priv, base, priv->event_log.next_entry, + capacity - priv->event_log.next_entry, + capacity, mode); - iwl_print_cont_event_trace(priv, base, 0, - next_entry, mode); + iwl_print_cont_event_trace( + priv, base, 0, next_entry, capacity, mode); } else { - iwl_print_cont_event_trace(priv, base, - next_entry, capacity - next_entry, - mode); + iwl_print_cont_event_trace( + priv, base, next_entry, + capacity - next_entry, + capacity, mode); - iwl_print_cont_event_trace(priv, base, 0, - next_entry, mode); + iwl_print_cont_event_trace( + priv, base, 0, next_entry, capacity, mode); } } + priv->event_log.num_wraps = num_wraps; priv->event_log.next_entry = next_entry; } @@ -1219,6 +1257,11 @@ int iwl_alive_start(struct iwl_priv *priv) if (iwl_is_rfkill(priv->shrd)) return -ERFKILL; + if (priv->event_log.ucode_trace) { + /* start collecting data now */ + mod_timer(&priv->ucode_trace, jiffies); + } + /* download priority table before any calibration request */ if (cfg(priv)->bt_params && cfg(priv)->bt_params->advanced_bt_coexist) { diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index f837f32bb71..978a1d4c6a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2131,9 +2131,10 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, if (trace) { priv->event_log.ucode_trace = true; - /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */ - mod_timer(&priv->ucode_trace, - jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); + if (iwl_is_alive(priv->shrd)) { + /* start collecting data now */ + mod_timer(&priv->ucode_trace, jiffies); + } } else { priv->event_log.ucode_trace = false; del_timer_sync(&priv->ucode_trace); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 4579d61da25..af846002150 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -661,7 +661,7 @@ struct traffic_stats { * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds * to perform continuous uCode event logging operation if enabled */ -#define UCODE_TRACE_PERIOD (100) +#define UCODE_TRACE_PERIOD (10) /* * iwl_event_log: current uCode event log position -- cgit v1.2.3 From 42602dd419177b0de1b1093a420399132ed75ca6 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 19 Jan 2012 12:16:46 -0800 Subject: iwlwifi: add option to disalbe LED Led has no use for some platform. Add additional module parameter option to disable LED Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-led.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl-shared.h | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3e429a3e518..90315c69cdf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2097,7 +2097,7 @@ MODULE_PARM_DESC(bt_coex_active, "enable wifi/bt co-exist (default: enable)"); module_param_named(led_mode, iwlagn_mod_params.led_mode, int, S_IRUGO); MODULE_PARM_DESC(led_mode, "0=system default, " - "1=On(RF On)/Off(RF Off), 2=blinking (default: 0)"); + "1=On(RF On)/Off(RF Off), 2=blinking, 3=Off (default: 0)"); module_param_named(power_save, iwlagn_mod_params.power_save, bool, S_IRUGO); diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index eca79087afb..8761438f153 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -177,6 +177,10 @@ void iwl_leds_init(struct iwl_priv *priv) int mode = iwlagn_mod_params.led_mode; int ret; + if (mode == IWL_LED_DISABLE) { + IWL_INFO(priv, "Led disabled\n"); + return; + } if (mode == IWL_LED_DEFAULT) mode = cfg(priv)->led_mode; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index e406d49f418..04975b7b65b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -264,11 +264,13 @@ enum iwl_pa_type { * LED ON = RF ON * LED OFF = RF OFF * IWL_LED_BLINK: adjust led blink rate based on blink table + * IWL_LED_DISABLE: led disabled */ enum iwl_led_mode { IWL_LED_DEFAULT, IWL_LED_RF_STATE, IWL_LED_BLINK, + IWL_LED_DISABLE, }; /** -- cgit v1.2.3 From 4c7d2fe9b116f749bc8362da33a628d6654e42b4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 14:39:19 +0100 Subject: iwlwifi: always restrict scan dwell in P2P Whenever the PAN (P2P) context is active, it has timers in the uCode that prevent sleep, so scanning can't be out of channel for more than the beacon interval programmed into the device. Before this patch, a full scan including any passive channels when P2P was active would stall forever because it wouldn't find time to execute the passive requests (for default beacon intervals of 100 TU.) Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-scan.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 2aea20bf0f1..7f2e3a1c80e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -414,10 +414,25 @@ static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time) for_each_context(priv, ctx) { u16 value; - if (!iwl_is_associated_ctx(ctx)) - continue; - if (ctx->staging.dev_type == RXON_DEV_TYPE_P2P) + switch (ctx->staging.dev_type) { + case RXON_DEV_TYPE_P2P: + /* no timing constraints */ continue; + case RXON_DEV_TYPE_ESS: + default: + /* timing constraints if associated */ + if (!iwl_is_associated_ctx(ctx)) + continue; + break; + case RXON_DEV_TYPE_CP: + case RXON_DEV_TYPE_2STA: + /* + * These seem to always have timers for TBTT + * active in uCode even when not associated yet. + */ + break; + } + value = ctx->beacon_int; if (!value) value = IWL_PASSIVE_DWELL_BASE; -- cgit v1.2.3 From 5f1127ffbae3029fde5dc1464ec3c26cdf34cb80 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 24 Jan 2012 13:50:16 +0200 Subject: ath6kl: fix testmode when fw-2.bin or fw-3.bin is used Testmode (TCMD and ART) was not enabled when fw-2.bin or fw-3.bin files were available, fix that by fetching testmode file just after the board file but before rest of the firmware files are fetched. I also added testmode field to struct ath6kl and moved the module parameter to core.c. Now all module parameters are grouped in one place. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.c | 4 ++ drivers/net/wireless/ath/ath6kl/core.h | 1 + drivers/net/wireless/ath/ath6kl/init.c | 74 +++++++++++++++++++++------------- 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index 0d92e7179f8..2a5198185d5 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -28,11 +28,13 @@ unsigned int debug_mask; static bool suspend_cutpower; static unsigned int uart_debug; static unsigned int ath6kl_p2p; +static unsigned int testmode; module_param(debug_mask, uint, 0644); module_param(suspend_cutpower, bool, 0444); module_param(uart_debug, uint, 0644); module_param(ath6kl_p2p, uint, 0644); +module_param(testmode, uint, 0644); int ath6kl_core_init(struct ath6kl *ar) { @@ -76,6 +78,8 @@ int ath6kl_core_init(struct ath6kl *ar) goto err_power_off; } + ar->testmode = testmode; + ret = ath6kl_init_fetch_firmwares(ar); if (ret) goto err_htc_cleanup; diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index ed9fcc11b5f..7f1869d00d7 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -532,6 +532,7 @@ struct ath6kl { struct wiphy *wiphy; enum ath6kl_state state; + unsigned int testmode; struct ath6kl_bmi bmi; const struct ath6kl_hif_ops *hif_ops; diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 4d8eb1cca6e..bf56e5f1761 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -27,10 +27,6 @@ #include "debug.h" #include "hif-ops.h" -static unsigned int testmode; - -module_param(testmode, uint, 0644); - static const struct ath6kl_hw hw_list[] = { { .id = AR6003_HW_2_0_VERSION, @@ -731,39 +727,54 @@ static int ath6kl_fetch_otp_file(struct ath6kl *ar) return 0; } -static int ath6kl_fetch_fw_file(struct ath6kl *ar) +static int ath6kl_fetch_testmode_file(struct ath6kl *ar) { char filename[100]; int ret; - if (ar->fw != NULL) + if (ar->testmode == 0) return 0; - if (testmode) { - ath6kl_dbg(ATH6KL_DBG_BOOT, "testmode %d\n", - testmode); - if (testmode == 2) { - if (ar->hw.fw.utf == NULL) { - ath6kl_warn("testmode 2 not supported\n"); - return -EOPNOTSUPP; - } + ath6kl_dbg(ATH6KL_DBG_BOOT, "testmode %d\n", ar->testmode); - snprintf(filename, sizeof(filename), "%s/%s", - ar->hw.fw.dir, ar->hw.fw.utf); - } else { - if (ar->hw.fw.tcmd == NULL) { - ath6kl_warn("testmode 1 not supported\n"); - return -EOPNOTSUPP; - } + if (ar->testmode == 2) { + if (ar->hw.fw.utf == NULL) { + ath6kl_warn("testmode 2 not supported\n"); + return -EOPNOTSUPP; + } - snprintf(filename, sizeof(filename), "%s/%s", - ar->hw.fw.dir, ar->hw.fw.tcmd); + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.utf); + } else { + if (ar->hw.fw.tcmd == NULL) { + ath6kl_warn("testmode 1 not supported\n"); + return -EOPNOTSUPP; } - set_bit(TESTMODE, &ar->flag); - goto get_fw; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.tcmd); } + set_bit(TESTMODE, &ar->flag); + + ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); + if (ret) { + ath6kl_err("Failed to get testmode %d firmware file %s: %d\n", + ar->testmode, filename, ret); + return ret; + } + + return 0; +} + +static int ath6kl_fetch_fw_file(struct ath6kl *ar) +{ + char filename[100]; + int ret; + + if (ar->fw != NULL) + return 0; + /* FIXME: remove WARN_ON() as we won't support FW API 1 for long */ if (WARN_ON(ar->hw.fw.fw == NULL)) return -EINVAL; @@ -771,7 +782,6 @@ static int ath6kl_fetch_fw_file(struct ath6kl *ar) snprintf(filename, sizeof(filename), "%s/%s", ar->hw.fw.dir, ar->hw.fw.fw); -get_fw: ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); if (ret) { ath6kl_err("Failed to get firmware file %s: %d\n", @@ -812,7 +822,7 @@ static int ath6kl_fetch_testscript_file(struct ath6kl *ar) char filename[100]; int ret; - if (testmode != 2) + if (ar->testmode != 2) return 0; if (ar->fw_testscript != NULL) @@ -927,6 +937,10 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n", ie_len); + /* in testmode we already might have a fw file */ + if (ar->fw != NULL) + break; + ar->fw = kmemdup(data, ie_len, GFP_KERNEL); if (ar->fw == NULL) { @@ -1038,6 +1052,10 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar) if (ret) return ret; + ret = ath6kl_fetch_testmode_file(ar); + if (ret) + return ret; + ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API3_FILE); if (ret == 0) { ar->fw_api = 3; @@ -1283,7 +1301,7 @@ static int ath6kl_upload_testscript(struct ath6kl *ar) u32 address, param; int ret; - if (testmode != 2) + if (ar->testmode != 2) return 0; if (ar->fw_testscript == NULL) -- cgit v1.2.3 From c86515412f0c364f2d45029b45d5909614087af3 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 26 Jan 2012 13:17:18 +0530 Subject: ath6kl: Fix kernel panic during rx aggregation "ath6kl: Define a structure for connection specific aggregation information" introduces this. In aggr_conn_init(), vif->aggr_cntxt is assigned to aggr_conn->aggr_info, but vif->aggr_cntxt is not initialized at this point, this would end up accessing an invalid pointer in aggregation receive path. Fix this by passing the correct aggr_info to aggr_conn_init(). The panic trace would look like. [] panic+0xa1/0x1c6 [] ? kmsg_dump+0xfd/0x160 [] oops_end+0xea/0xf0 [] no_context+0x11d/0x2d0 [] __bad_area_nosemaphore+0x14d/0x230 [] ? do_page_fault+0x30d/0x520 [] bad_area_nosemaphore+0x13/0x20 [] do_page_fault+0x3bd/0x520 [] ? __lock_acquire+0x320/0x1680 [] ? trace_hardirqs_off_thunk+0x3a/0x3c [] page_fault+0x25/0x30 [] ? aggr_slice_amsdu+0xdf/0x170 [ath6kl_core] [] aggr_deque_frms+0xbc/0x190 [ath6kl_core] [] ath6kl_rx+0x3e4/0xae0 [ath6kl_core] [] ath6kl_htc_rxmsg_pending_handler+0x8b7/0xf10 [ath6kl_core] [] ? mmc_do_release_host+0x70/0x90 [mmc_core] [] ? mmc_release_host+0x2a/0x50 [mmc_core] [] ? ath6kl_alloc_amsdu_rxbuf+0x140/0x140 [ath6kl_core] [] ath6kl_hif_intr_bh_handler+0x362/0x510 [ath6kl_core] [] ath6kl_sdio_irq_handler+0x60/0xb0 [ath6kl_sdio] [] sdio_irq_thread+0xec/0x320 [mmc_core] [] ? sdio_claim_irq+0x220/0x220 [mmc_core] [] ? sdio_claim_irq+0x220/0x220 [mmc_core] [] kthread+0xbe/0xd0 [] kernel_thread_helper+0x4/0x10 [] ? retint_restore_args+0x13/0x13 [] ? __init_kthread_worker+0x70/0x70 [] ? gs_change+0x13/0x13 Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.h | 3 ++- drivers/net/wireless/ath/ath6kl/main.c | 2 +- drivers/net/wireless/ath/ath6kl/txrx.c | 7 ++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 7f1869d00d7..426f269e8ab 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -715,7 +715,8 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie); int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); struct aggr_info *aggr_init(struct ath6kl_vif *vif); -void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info_conn *aggr_conn); +void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info, + struct aggr_info_conn *aggr_conn); void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint); void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count); diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 39da1f98da8..b96d01a7919 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -74,7 +74,7 @@ static void ath6kl_add_new_sta(struct ath6kl_vif *vif, u8 *mac, u16 aid, ar->sta_list_index = ar->sta_list_index | (1 << free_slot); ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid); - aggr_conn_init(vif, sta->aggr_conn); + aggr_conn_init(vif, vif->aggr_cntxt, sta->aggr_conn); } static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 62c12102e14..a3dc6943c7f 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -1674,7 +1674,8 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid_mux, u16 seq_no, rxtid->aggr = true; } -void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info_conn *aggr_conn) +void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info, + struct aggr_info_conn *aggr_conn) { struct rxtid *rxtid; u8 i; @@ -1684,7 +1685,7 @@ void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info_conn *aggr_conn) init_timer(&aggr_conn->timer); aggr_conn->timer.function = aggr_timeout; aggr_conn->timer.data = (unsigned long) aggr_conn; - aggr_conn->aggr_info = vif->aggr_cntxt; + aggr_conn->aggr_info = aggr_info; aggr_conn->timer_scheduled = false; @@ -1716,7 +1717,7 @@ struct aggr_info *aggr_init(struct ath6kl_vif *vif) return NULL; } - aggr_conn_init(vif, p_aggr->aggr_conn); + aggr_conn_init(vif, p_aggr, p_aggr->aggr_conn); skb_queue_head_init(&p_aggr->rx_amsdu_freeq); ath6kl_alloc_netbufs(&p_aggr->rx_amsdu_freeq, AGGR_NUM_OF_FREE_NETBUFS); -- cgit v1.2.3 From e390af779dc671551800514d391928f5a798089a Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Mon, 30 Jan 2012 17:13:09 +0530 Subject: ath6kl: Re-architect suspend mode handling in ath6kl_sdio_suspend Using this patch, the user can bypass existing auto suspend mode selection logic and force ath6kl to enter into the suspend mode what he/she wants. If the user doesn't choose any suspend mode while doing insmod of the driver, auto suspend mode selection logic will kick in and choose suspend mode based on the host SDIO controller capability. Generic module parameter is required to specify suspend mode including Deep Sleep and WOW while doing insmod. Renaming existing mod param variable suspend_cutpower would be sufficient to meet this requirement. New module parameter suspend_mode can take any one of the below suspend state, 1. cut power 2. deep sleep 3. wow Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.c | 12 +++-- drivers/net/wireless/ath/ath6kl/core.h | 4 +- drivers/net/wireless/ath/ath6kl/sdio.c | 86 +++++++++++++++++++++------------- 3 files changed, 64 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index 2a5198185d5..722ca59b88c 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -25,13 +25,13 @@ #include "cfg80211.h" unsigned int debug_mask; -static bool suspend_cutpower; +static unsigned int suspend_mode; static unsigned int uart_debug; static unsigned int ath6kl_p2p; static unsigned int testmode; module_param(debug_mask, uint, 0644); -module_param(suspend_cutpower, bool, 0444); +module_param(suspend_mode, uint, 0644); module_param(uart_debug, uint, 0644); module_param(ath6kl_p2p, uint, 0644); module_param(testmode, uint, 0644); @@ -147,8 +147,12 @@ int ath6kl_core_init(struct ath6kl *ar) ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; - if (suspend_cutpower) - ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER; + if (suspend_mode && + suspend_mode >= WLAN_POWER_STATE_CUT_PWR && + suspend_mode <= WLAN_POWER_STATE_WOW) + ar->suspend_mode = suspend_mode; + else + ar->suspend_mode = 0; if (uart_debug) ar->conf_flags |= ATH6KL_CONF_UART_DEBUG; diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 426f269e8ab..ce572c04b92 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -196,8 +196,7 @@ struct ath6kl_fw_ie { #define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN BIT(1) #define ATH6KL_CONF_ENABLE_11N BIT(2) #define ATH6KL_CONF_ENABLE_TX_BURST BIT(3) -#define ATH6KL_CONF_SUSPEND_CUTPOWER BIT(4) -#define ATH6KL_CONF_UART_DEBUG BIT(5) +#define ATH6KL_CONF_UART_DEBUG BIT(4) enum wlan_low_pwr_state { WLAN_POWER_STATE_ON, @@ -619,6 +618,7 @@ struct ath6kl { } hw; u16 conf_flags; + u16 suspend_mode; wait_queue_head_t event_wq; struct ath6kl_mbox_info mbox_info; diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index d9f55914b89..07dcf00ca1a 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -779,7 +779,7 @@ out: return ret; } -static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) +static int ath6kl_set_sdio_pm_caps(struct ath6kl *ar) { struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); struct sdio_func *func = ar_sdio->func; @@ -790,60 +790,82 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio suspend pm_caps 0x%x\n", flags); - if (!(flags & MMC_PM_KEEP_POWER) || - (ar->conf_flags & ATH6KL_CONF_SUSPEND_CUTPOWER)) { - /* as host doesn't support keep power we need to cut power */ - return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, - NULL); - } + if (!(flags & MMC_PM_WAKE_SDIO_IRQ) || + !(flags & MMC_PM_KEEP_POWER)) + return -EINVAL; ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); if (ret) { - printk(KERN_ERR "ath6kl: set sdio pm flags failed: %d\n", - ret); + ath6kl_err("set sdio keep pwr flag failed: %d\n", ret); return ret; } - if (!(flags & MMC_PM_WAKE_SDIO_IRQ)) - goto deepsleep; - /* sdio irq wakes up host */ + ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ); + if (ret) + ath6kl_err("set sdio wake irq flag failed: %d\n", ret); + + return ret; +} + +static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) +{ + struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); + struct sdio_func *func = ar_sdio->func; + mmc_pm_flag_t flags; + int ret; if (ar->state == ATH6KL_STATE_SCHED_SCAN) { + ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sched scan is in progress\n"); + + ret = ath6kl_set_sdio_pm_caps(ar); + if (ret) + goto cut_pwr; + ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_SCHED_SCAN, NULL); - if (ret) { - ath6kl_warn("Schedule scan suspend failed: %d", ret); - return ret; - } - - ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ); if (ret) - ath6kl_warn("set sdio wake irq flag failed: %d\n", ret); + goto cut_pwr; - return ret; + return 0; } - if (wow) { - /* - * The host sdio controller is capable of keep power and - * sdio irq wake up at this point. It's fine to continue - * wow suspend operation. - */ + if (ar->suspend_mode == WLAN_POWER_STATE_WOW || + (!ar->suspend_mode && wow)) { + + ret = ath6kl_set_sdio_pm_caps(ar); + if (ret) + goto cut_pwr; + ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_WOW, wow); if (ret) - return ret; + goto cut_pwr; + + return 0; + } + + if (ar->suspend_mode == WLAN_POWER_STATE_DEEP_SLEEP || + !ar->suspend_mode) { - ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ); + flags = sdio_get_host_pm_caps(func); + if (!(flags & MMC_PM_KEEP_POWER)) + goto cut_pwr; + + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); if (ret) - ath6kl_err("set sdio wake irq flag failed: %d\n", ret); + goto cut_pwr; - return ret; + ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP, + NULL); + if (ret) + goto cut_pwr; + + return 0; } -deepsleep: - return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP, NULL); +cut_pwr: + return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, NULL); } static int ath6kl_sdio_resume(struct ath6kl *ar) -- cgit v1.2.3 From d91e8eee046e0d4ae7a8a585616b5ce800f54568 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Mon, 30 Jan 2012 17:13:10 +0530 Subject: ath6kl: Configure WOW patterns while going to wow_suspend First preference is given to the user configured WOW patterns. If the user doesn't configure any patterns (for ex, via iw command), the default patterns will be configured based on the current mode (vif->nw_type) while going to WOW suspend. Summary of changes: * ath6kl_wow_ap() is added to configure the below default patterns when the system enters into WOW suspend in AP mode. + Unicast IP, EAPOL-like and ARP packet pattern + ARP packet pattern + mDNS/SSDP/LLMNR pattern + DHCP broadcast pattern * ath6kl_wow_sta() is added to configure the below default patterns when the system enters into WOW suspend in STA mode. + Unicast packet pattern + mDNS/SSDP/LLMNR pattern * Move the user provided WOW patterns configuration code from ath6kl_wow_suspend() to a separate function called ath6kl_wow_usr(). * Two argument variable's ('filter' and 'mask) data type in ath6kl_wmi_add_wow_pattern_cmd() are changed from 'u8 *' to 'const u8 *'. This is needed to make all pattern and mask arrays to be 'static const u8' in the caller function. * New conditional check is added to make sure user configured pattern count is within the limit (WOW_MAX_FILTERS_PER_LIST). Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 231 +++++++++++++++++++++++------ drivers/net/wireless/ath/ath6kl/wmi.c | 3 +- drivers/net/wireless/ath/ath6kl/wmi.h | 3 +- 3 files changed, 193 insertions(+), 44 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index fed7b8077f5..e676cfccedf 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1723,32 +1723,14 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) return 0; } -static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) +static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif, + struct cfg80211_wowlan *wow, u32 *filter) { - struct in_device *in_dev; - struct in_ifaddr *ifa; - struct ath6kl_vif *vif; - int ret, pos, left; - u32 filter = 0; + int ret, pos; + u8 mask[WOW_MASK_SIZE]; u16 i; - u8 mask[WOW_MASK_SIZE], index = 0; - __be32 ips[MAX_IP_ADDRS]; - - vif = ath6kl_vif_first(ar); - if (!vif) - return -EIO; - - if (!ath6kl_cfg80211_ready(vif)) - return -EIO; - - if (!test_bit(CONNECTED, &vif->flags)) - return -EINVAL; - /* Clear existing WOW patterns */ - for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) - ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, - WOW_LIST_ID, i); - /* Configure new WOW patterns */ + /* Configure the patterns that we received from the user. */ for (i = 0; i < wow->n_patterns; i++) { /* @@ -1771,14 +1753,194 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) * matched from the first byte of received pkt in the firmware. */ ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, - vif->fw_vif_idx, WOW_LIST_ID, - wow->patterns[i].pattern_len, - 0 /* pattern offset */, - wow->patterns[i].pattern, mask); + vif->fw_vif_idx, WOW_LIST_ID, + wow->patterns[i].pattern_len, + 0 /* pattern offset */, + wow->patterns[i].pattern, mask); if (ret) return ret; } + if (wow->disconnect) + *filter |= WOW_FILTER_OPTION_NWK_DISASSOC; + + if (wow->magic_pkt) + *filter |= WOW_FILTER_OPTION_MAGIC_PACKET; + + if (wow->gtk_rekey_failure) + *filter |= WOW_FILTER_OPTION_GTK_ERROR; + + if (wow->eap_identity_req) + *filter |= WOW_FILTER_OPTION_EAP_REQ; + + if (wow->four_way_handshake) + *filter |= WOW_FILTER_OPTION_8021X_4WAYHS; + + return 0; +} + +static int ath6kl_wow_ap(struct ath6kl *ar, struct ath6kl_vif *vif) +{ + static const u8 unicst_pattern[] = { 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08 }; + static const u8 unicst_mask[] = { 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f }; + u8 unicst_offset = 0; + static const u8 arp_pattern[] = { 0x08, 0x06 }; + static const u8 arp_mask[] = { 0xff, 0xff }; + u8 arp_offset = 20; + static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 }; + static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 }; + u8 discvr_offset = 38; + static const u8 dhcp_pattern[] = { 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 /* port 67 */ }; + static const u8 dhcp_mask[] = { 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff /* port 67 */ }; + u8 dhcp_offset = 0; + int ret; + + /* Setup unicast IP, EAPOL-like and ARP pkt pattern */ + ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, + vif->fw_vif_idx, WOW_LIST_ID, + sizeof(unicst_pattern), unicst_offset, + unicst_pattern, unicst_mask); + if (ret) { + ath6kl_err("failed to add WOW unicast IP pattern\n"); + return ret; + } + + /* Setup all ARP pkt pattern */ + ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, + vif->fw_vif_idx, WOW_LIST_ID, + sizeof(arp_pattern), arp_offset, + arp_pattern, arp_mask); + if (ret) { + ath6kl_err("failed to add WOW ARP pattern\n"); + return ret; + } + + /* + * Setup multicast pattern for mDNS 224.0.0.251, + * SSDP 239.255.255.250 and LLMNR 224.0.0.252 + */ + ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, + vif->fw_vif_idx, WOW_LIST_ID, + sizeof(discvr_pattern), discvr_offset, + discvr_pattern, discvr_mask); + if (ret) { + ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n"); + return ret; + } + + /* Setup all DHCP broadcast pkt pattern */ + ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, + vif->fw_vif_idx, WOW_LIST_ID, + sizeof(dhcp_pattern), dhcp_offset, + dhcp_pattern, dhcp_mask); + if (ret) { + ath6kl_err("failed to add WOW DHCP broadcast pattern\n"); + return ret; + } + + return 0; +} + +static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif) +{ + struct net_device *ndev = vif->ndev; + static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 }; + static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 }; + u8 discvr_offset = 38; + u8 mac_mask[ETH_ALEN]; + int ret; + + /* Setup unicast pkt pattern */ + memset(mac_mask, 0xff, ETH_ALEN); + ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, + vif->fw_vif_idx, WOW_LIST_ID, + ETH_ALEN, 0, ndev->dev_addr, + mac_mask); + if (ret) { + ath6kl_err("failed to add WOW unicast pattern\n"); + return ret; + } + + /* + * Setup multicast pattern for mDNS 224.0.0.251, + * SSDP 239.255.255.250 and LLMNR 224.0.0.252 + */ + if ((ndev->flags & IFF_ALLMULTI) || + (ndev->flags & IFF_MULTICAST && netdev_mc_count(ndev) > 0)) { + ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi, + vif->fw_vif_idx, WOW_LIST_ID, + sizeof(discvr_pattern), discvr_offset, + discvr_pattern, discvr_mask); + if (ret) { + ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR " + "pattern\n"); + return ret; + } + } + + return 0; +} + +static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) +{ + struct in_device *in_dev; + struct in_ifaddr *ifa; + struct ath6kl_vif *vif; + int ret, left; + u32 filter = 0; + u16 i; + u8 index = 0; + __be32 ips[MAX_IP_ADDRS]; + + vif = ath6kl_vif_first(ar); + if (!vif) + return -EIO; + + if (!ath6kl_cfg80211_ready(vif)) + return -EIO; + + if (!test_bit(CONNECTED, &vif->flags)) + return -EINVAL; + + if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) + return -EINVAL; + + /* Clear existing WOW patterns */ + for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) + ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, + WOW_LIST_ID, i); + + /* + * Skip the default WOW pattern configuration + * if the driver receives any WOW patterns from + * the user. + */ + if (wow) + ret = ath6kl_wow_usr(ar, vif, wow, &filter); + else if (vif->nw_type == AP_NETWORK) + ret = ath6kl_wow_ap(ar, vif); + else + ret = ath6kl_wow_sta(ar, vif); + + if (ret) + return ret; + /* Setup own IP addr for ARP agent. */ in_dev = __in_dev_get_rtnl(vif->ndev); if (!in_dev) @@ -1806,21 +1968,6 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) } skip_arp: - if (wow->disconnect) - filter |= WOW_FILTER_OPTION_NWK_DISASSOC; - - if (wow->magic_pkt) - filter |= WOW_FILTER_OPTION_MAGIC_PACKET; - - if (wow->gtk_rekey_failure) - filter |= WOW_FILTER_OPTION_GTK_ERROR; - - if (wow->eap_identity_req) - filter |= WOW_FILTER_OPTION_EAP_REQ; - - if (wow->four_way_handshake) - filter |= WOW_FILTER_OPTION_8021X_4WAYHS; - ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, ATH6KL_WOW_MODE_ENABLE, filter, diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 5d678bf372d..9c8e4dfbfa0 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -2620,7 +2620,8 @@ int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, u8 list_id, u8 filter_size, - u8 filter_offset, u8 *filter, u8 *mask) + u8 filter_offset, const u8 *filter, + const u8 *mask) { struct sk_buff *skb; struct wmi_add_wow_pattern_cmd *cmd; diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 48e9d2641d6..85698ef2dd8 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -2461,7 +2461,8 @@ int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, u32 filter, u16 host_req_delay); int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, u8 list_id, u8 filter_size, - u8 filter_offset, u8 *filter, u8 *mask); + u8 filter_offset, const u8 *filter, + const u8 *mask); int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, u16 list_id, u16 filter_id); int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); -- cgit v1.2.3 From 081c7a84e969453716e2a7bd315417067c3643ad Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Mon, 30 Jan 2012 17:13:11 +0530 Subject: ath6kl: Wait for host sleep mode cmd processed event during WOW suspend For every WMI_SET_HOST_SLEEP_MODE_CMDID command (send from the host), the firmware sends WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID as an acknowledgement to the host. In order to being sync with the firmware, the host has to wait for WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENT event before going to the suspend state. This patch ensures ath6kl_wow_suspend() waits until it gets this event after sending set host sleep mode command. This patch adds, * New command WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID in WMI event table. * New WMI function ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx() to process the event. * New flag HOST_SLEEP_MODE_CMD_PROCESSED in VIF flags to record the arrival of the event. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 15 +++++++++++++++ drivers/net/wireless/ath/ath6kl/core.h | 1 + drivers/net/wireless/ath/ath6kl/wmi.c | 17 +++++++++++++++++ drivers/net/wireless/ath/ath6kl/wmi.h | 2 ++ 4 files changed, 35 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index e676cfccedf..1902e2fa1a6 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1975,11 +1975,26 @@ skip_arp: if (ret) return ret; + clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags); + ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, ATH6KL_HOST_MODE_ASLEEP); if (ret) return ret; + left = wait_event_interruptible_timeout(ar->event_wq, + test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags), + WMI_TIMEOUT); + if (left == 0) { + ath6kl_warn("timeout, didn't get host sleep cmd " + "processed event\n"); + ret = -ETIMEDOUT; + } else if (left < 0) { + ath6kl_warn("error while waiting for host sleep cmd " + "processed event %d\n", left); + ret = left; + } + if (ar->tx_pending[ar->ctrl_ep]) { left = wait_event_interruptible_timeout(ar->event_wq, ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT); diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index ce572c04b92..c4d66e066dc 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -451,6 +451,7 @@ enum ath6kl_vif_state { DTIM_PERIOD_AVAIL, WLAN_ENABLED, STATS_UPDATE_PEND, + HOST_SLEEP_MODE_CMD_PROCESSED, }; struct ath6kl_vif { diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 9c8e4dfbfa0..18fa9aa8af9 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -2590,6 +2590,18 @@ int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, return ret; } +/* This command has zero length payload */ +static int ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(struct wmi *wmi, + struct ath6kl_vif *vif) +{ + struct ath6kl *ar = wmi->parent_dev; + + set_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags); + wake_up(&ar->event_wq); + + return 0; +} + int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, enum ath6kl_wow_mode wow_mode, u32 filter, u16 host_req_delay) @@ -3556,6 +3568,11 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n"); ret = ath6kl_wmi_tx_complete_event_rx(datap, len); break; + case WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID: + ath6kl_dbg(ATH6KL_DBG_WMI, + "WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID"); + ret = ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(wmi, vif); + break; case WMI_REMAIN_ON_CHNL_EVENTID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n"); ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif); diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 85698ef2dd8..e7919869725 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -1357,6 +1357,8 @@ enum wmi_event_id { WMI_P2P_START_SDPD_EVENTID, WMI_P2P_SDPD_RX_EVENTID, + WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID = 0x1047, + WMI_THIN_RESERVED_START_EVENTID = 0x8000, /* Events in this range are reserved for thinmode */ WMI_THIN_RESERVED_END_EVENTID = 0x8fff, -- cgit v1.2.3 From 3c411a434414f4320ce926bee3733e34ba0ea407 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Mon, 30 Jan 2012 17:13:12 +0530 Subject: ath6kl: Return a proper error code when not in connected state Error code ENOTCONN is more suitable than EINVAL to report when the driver is not in connected state in ath6kl_wow_suspend(). I found this during code review. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 1902e2fa1a6..5934e40ee55 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1916,7 +1916,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) return -EIO; if (!test_bit(CONNECTED, &vif->flags)) - return -EINVAL; + return -ENOTCONN; if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) return -EINVAL; -- cgit v1.2.3 From cca4d5adcff515b4bf5402dc23792f5123872906 Mon Sep 17 00:00:00 2001 From: Santosh Sajjan Date: Mon, 30 Jan 2012 22:02:26 +0200 Subject: ath6kl: Workaround to support Deep Sleep with MSM. Set the host pm flag MMC_PM_WAKE_SDIO_IRQ to allow host to disable the sdc2_clk and sdc2_h_clk,so that the MSM device enter into TCXO shutdown. Signed-off-by: Santosh Sajjan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/sdio.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 07dcf00ca1a..4febee72349 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -856,6 +856,19 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) if (ret) goto cut_pwr; + /* + * Workaround to support Deep Sleep with MSM, set the host pm + * flag as MMC_PM_WAKE_SDIO_IRQ to allow SDCC deiver to disable + * the sdc2_clock and internally allows MSM to enter + * TCXO shutdown properly. + */ + if ((flags & MMC_PM_WAKE_SDIO_IRQ)) { + ret = sdio_set_host_pm_flags(func, + MMC_PM_WAKE_SDIO_IRQ); + if (ret) + goto cut_pwr; + } + ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP, NULL); if (ret) -- cgit v1.2.3 From 3c325fbd0cdb4f83b7761cd8ba7519d7a236de38 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Tue, 31 Jan 2012 23:32:55 +0900 Subject: ath6kl: Fix typo in cfg80211.c Correct spelling "spported" to "supported" in drivers/net/wireless/ath/ath6kl/cfg80211.c Signed-off-by: Masanari Iida Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 5934e40ee55..d1922d8eb3b 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -194,7 +194,7 @@ static int ath6kl_set_auth_type(struct ath6kl_vif *vif, break; default: - ath6kl_err("%s: 0x%x not spported\n", __func__, auth_type); + ath6kl_err("%s: 0x%x not supported\n", __func__, auth_type); return -ENOTSUPP; } -- cgit v1.2.3 From 1b46dc04866a4962644ef32d7398e34b40f7ac21 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 31 Jan 2012 21:26:22 +0200 Subject: ath6kl: fix compiler warning in ath6kl_init_hw_params() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both Luis and John reported that they see a compiler warning: drivers/net/wireless/ath/ath6kl/init.c: In function 'ath6kl_init_hw_params': drivers/net/wireless/ath/ath6kl/init.c:1377:26: warning: ‘hw’ may be used uninitialized in this function Oddly enough I have never seen it. But AFAICT the code is correct and hw is not used uninitalized so add uninitialized_var() to inform that to the compiler. Reported-by: Luis R. Rodriguez Reported-by: John W. Linville Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index bf56e5f1761..0d76c377810 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1470,7 +1470,7 @@ static int ath6kl_init_upload(struct ath6kl *ar) int ath6kl_init_hw_params(struct ath6kl *ar) { - const struct ath6kl_hw *hw; + const struct ath6kl_hw *uninitialized_var(hw); int i; for (i = 0; i < ARRAY_SIZE(hw_list); i++) { -- cgit v1.2.3 From 5fbea5dcc05415474bae7108803e324f112d5b58 Mon Sep 17 00:00:00 2001 From: Chilam Ng Date: Wed, 1 Feb 2012 01:03:37 -0800 Subject: ath6kl: initialize the 'nominal_phy' field in the 'wmi_create_pstream_cmd' struct for create_qos command The nominal_phy field is uninitialized. Initialize it to min_phy_rate for create_qos. kvalo: simplified the equation as checkpatch complained for a too long line Signed-off-by: Chilam Ng Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/debug.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 6b546dc6672..d832058816f 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -1441,6 +1441,8 @@ static ssize_t ath6kl_create_qos_write(struct file *file, return -EINVAL; pstream.medium_time = cpu_to_le32(val32); + pstream.nominal_phy = le32_to_cpu(pstream.min_phy_rate) / 1000000; + ath6kl_wmi_create_pstream_cmd(ar->wmi, vif->fw_vif_idx, &pstream); return count; -- cgit v1.2.3 From ed6a3803408f18da387463d569b4edc5078fd9aa Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 2 Jan 2012 16:10:08 +0200 Subject: iwlwifi: add fw_alive to transport layer API, kill tx_start Define a new handler in the transport layer API: fw_alive. Move iwl_reset_ict to this new handler, and move the content of tx_start to this handler. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 --- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 -- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 6 ++---- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 10 ++++++++-- drivers/net/wireless/iwlwifi/iwl-trans.h | 15 +++++++-------- drivers/net/wireless/iwlwifi/iwl-ucode.c | 2 +- 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 90315c69cdf..9d9185ffc39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1243,9 +1243,6 @@ int iwl_alive_start(struct iwl_priv *priv) int ret = 0; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - /*TODO: this should go to the transport layer */ - iwl_reset_ict(trans(priv)); - IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); /* After the ALIVE response, we can send host commands to the uCode */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 39cbe1a1577..0f5133ac357 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -73,8 +73,6 @@ struct iwlagn_ucode_capabilities { extern struct ieee80211_ops iwlagn_hw_ops; -int iwl_reset_ict(struct iwl_trans *trans); - static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) { hdr->op_code = cmd; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 0ac9b4d3027..0f73778b73f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -258,7 +258,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, /***************************************************** * ICT ******************************************************/ -int iwl_reset_ict(struct iwl_trans *trans); +void iwl_reset_ict(struct iwl_trans *trans); void iwl_disable_ict(struct iwl_trans *trans); int iwl_alloc_isr_ict(struct iwl_trans *trans); void iwl_free_isr_ict(struct iwl_trans *trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 848c598bfad..2822b7e8bca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1213,7 +1213,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans) /* Device is going up inform it about using ICT interrupt table, * also we need to tell the driver to start using ICT interrupt. */ -int iwl_reset_ict(struct iwl_trans *trans) +void iwl_reset_ict(struct iwl_trans *trans) { u32 val; unsigned long flags; @@ -1221,7 +1221,7 @@ int iwl_reset_ict(struct iwl_trans *trans) IWL_TRANS_GET_PCIE_TRANS(trans); if (!trans_pcie->ict_tbl) - return 0; + return; spin_lock_irqsave(&trans->shrd->lock, flags); iwl_disable_interrupts(trans); @@ -1241,8 +1241,6 @@ int iwl_reset_ict(struct iwl_trans *trans) iwl_write32(bus(trans), CSR_INT, trans_pcie->inta_mask); iwl_enable_interrupts(trans); spin_unlock_irqrestore(&trans->shrd->lock, flags); - - return 0; } /* Device is going down disable ict interrupt usage */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 5e6af4ba965..affa56fafdb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -835,7 +835,7 @@ static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) iwl_write_prph(bus(trans), SCD_TXFACT, mask); } -static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) +static void iwl_tx_start(struct iwl_trans *trans) { const struct queue_to_fifo_ac *queue_to_fifo; struct iwl_trans_pcie *trans_pcie = @@ -948,6 +948,12 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) APMG_PCIDEV_STT_VAL_L1_ACT_DIS); } +static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans) +{ + iwl_reset_ict(trans); + iwl_tx_start(trans); +} + /** * iwlagn_txq_ctx_stop - Stop all Tx DMA channels */ @@ -1903,11 +1909,11 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, const struct iwl_trans_ops trans_ops_pcie = { .alloc = iwl_trans_pcie_alloc, .request_irq = iwl_trans_pcie_request_irq, + .fw_alive = iwl_trans_pcie_fw_alive, .start_device = iwl_trans_pcie_start_device, .prepare_card_hw = iwl_trans_pcie_prepare_card_hw, .stop_device = iwl_trans_pcie_stop_device, - .tx_start = iwl_trans_pcie_tx_start, .wake_any_queue = iwl_trans_pcie_wake_any_queue, .send_cmd = iwl_trans_pcie_send_cmd, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 42a9f303f54..9795a23ee94 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -139,8 +139,7 @@ struct iwl_host_cmd { * layer. * @prepare_card_hw: claim the ownership on the HW. Will be called during * probe. - * @tx_start: starts and configures all the Tx fifo - usually done once the fw - * is alive. + * @fw_alive: called when the fw sends alive notification * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* * @stop_device:stops the whole device (embedded CPU put to reset) * @send_cmd:send a host command @@ -166,9 +165,9 @@ struct iwl_trans_ops { struct iwl_trans *(*alloc)(struct iwl_shared *shrd); int (*request_irq)(struct iwl_trans *iwl_trans); int (*start_device)(struct iwl_trans *trans); + void (*fw_alive)(struct iwl_trans *trans); int (*prepare_card_hw)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans); - void (*tx_start)(struct iwl_trans *trans); void (*wake_any_queue)(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, @@ -264,6 +263,11 @@ static inline int iwl_trans_request_irq(struct iwl_trans *trans) return trans->ops->request_irq(trans); } +static inline void iwl_trans_fw_alive(struct iwl_trans *trans) +{ + trans->ops->fw_alive(trans); +} + static inline int iwl_trans_start_device(struct iwl_trans *trans) { return trans->ops->start_device(trans); @@ -279,11 +283,6 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans) trans->ops->stop_device(trans); } -static inline void iwl_trans_tx_start(struct iwl_trans *trans) -{ - trans->ops->tx_start(trans); -} - static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, const char *msg) diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 2edf0ef65a5..0d7f207ac61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -447,7 +447,7 @@ static int iwl_alive_notify(struct iwl_trans *trans) if (!priv->tx_cmd_pool) return -ENOMEM; - iwl_trans_tx_start(trans); + iwl_trans_fw_alive(trans); for_each_context(priv, ctx) ctx->last_tx_rejected = false; -- cgit v1.2.3 From a591697730a3c416cd384bc199eb5dde622c4c78 Mon Sep 17 00:00:00 2001 From: Gregory Greenman Date: Tue, 10 Jan 2012 19:22:56 +0200 Subject: iwlwifi: Connect IDI transport to driver. This patch connects IDI transport to driver. It does so by using a number of ifdefs at this stage. IDI is a new transport that is under development. Signed-off-by: Gregory Greenman Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-pci.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 13 ++++++++++++- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 7 ++++++- drivers/net/wireless/iwlwifi/iwl-trans.h | 1 + 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 03702a2e913..2c46063522c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -454,7 +454,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bus->irq = pdev->irq; bus->ops = &bus_ops_pci; +#ifdef CONFIG_IWLWIFI_IDI + err = iwl_probe(bus, &trans_ops_idi, cfg); +#else err = iwl_probe(bus, &trans_ops_pcie, cfg); +#endif if (err) goto out_disable_msi; return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 2822b7e8bca..b94c95370b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -35,6 +35,10 @@ #include "iwl-io.h" #include "iwl-trans-pcie-int.h" +#ifdef CONFIG_IWLWIFI_IDI +#include "iwl-amfh.h" +#endif + /****************************************************************************** * * RX path functions @@ -1100,8 +1104,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* Disable periodic interrupt; we use it as just a one-shot. */ iwl_write8(bus(trans), CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_DIS); +#ifdef CONFIG_IWLWIFI_IDI + iwl_amfh_rx_handler(); +#else iwl_rx_handle(trans); - +#endif /* * Enable periodic interrupt in 8 msec only if we received * real RX interrupt (instead of just periodic int), to catch @@ -1123,7 +1130,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans) isr_stats->tx++; handled |= CSR_INT_BIT_FH_TX; /* Wake up uCode load routine, now that load is complete */ +#ifdef CONFIG_IWLWIFI_IDI + trans->shrd->trans->ucode_write_complete = 1; +#else trans->ucode_write_complete = 1; +#endif wake_up(&trans->shrd->wait_command_queue); } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index affa56fafdb..0b4280c9258 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -647,8 +647,10 @@ static int iwl_nic_init(struct iwl_trans *trans) iwl_nic_config(priv(trans)); +#ifndef CONFIG_IWLWIFI_IDI /* Allocate the RX queue, or reset if it is already allocated */ iwl_rx_init(trans); +#endif /* Allocate or reset and init all Tx and Command queues */ if (iwl_tx_init(trans)) @@ -1016,8 +1018,9 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) */ if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) { iwl_trans_tx_stop(trans); +#ifndef CONFIG_IWLWIFI_IDI iwl_trans_rx_stop(trans); - +#endif /* Power-down device's busmaster DMA clocks */ iwl_write_prph(bus(trans), APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); @@ -1298,7 +1301,9 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans) { iwl_calib_free_results(trans); iwl_trans_pcie_tx_free(trans); +#ifndef CONFIG_IWLWIFI_IDI iwl_trans_pcie_rx_free(trans); +#endif free_irq(bus(trans)->irq, trans); iwl_free_isr_ict(trans); trans->shrd->trans = NULL; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 9795a23ee94..2a6649c9ca4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -383,6 +383,7 @@ static inline int iwl_trans_resume(struct iwl_trans *trans) * Transport layers implementations ******************************************************/ extern const struct iwl_trans_ops trans_ops_pcie; +extern const struct iwl_trans_ops trans_ops_idi; int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, const void *data, size_t len); -- cgit v1.2.3 From 8747bb4936c137bb93b91afd70eedd65069d26cd Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 4 Jan 2012 16:57:09 +0200 Subject: iwlwifi: separate the APM from the EEPROM There is no link between the two. Ensure that the NIC is on outside the code of the EEPROM handling. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl-eeprom.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 9d9185ffc39..f3bd6a3eec3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1848,8 +1848,12 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, /***************** * 4. Read EEPROM *****************/ + /* switch the NIC on before accessing the EEPROM */ + iwl_apm_init(priv); /* Read the EEPROM */ err = iwl_eeprom_init(priv, hw_rev); + /* Reset chip to save power until we load uCode during "up". */ + iwl_apm_stop(priv); if (err) { IWL_ERR(priv, "Unable to init EEPROM\n"); goto out_free_trans; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index e27d9f55267..ce214e0ab49 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -676,8 +676,6 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) } e = (__le16 *)shrd->eeprom; - iwl_apm_init(priv); - ret = iwl_eeprom_verify_signature(trans(priv)); if (ret < 0) { IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); @@ -758,8 +756,6 @@ done: err: if (ret) iwl_eeprom_free(priv->shrd); - /* Reset chip to save power until we load uCode during "up". */ - iwl_apm_stop(priv); alloc_err: return ret; } -- cgit v1.2.3 From e81fb554cfe082dc59a707767c426cbd2e361033 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 2 Feb 2012 14:08:57 -0800 Subject: iwlwifi: move the shrd memory from priv Allocating the shrd area dynamically will allow more agility while revamping the flows. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 +--- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-pci.c | 10 ++++++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f3bd6a3eec3..b42be308450 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1780,9 +1780,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, } priv = hw->priv; - priv->shrd = &priv->_shrd; - bus->shrd = priv->shrd; - priv->shrd->bus = bus; + priv->shrd = bus->shrd; priv->shrd->priv = priv; priv->shrd->trans = trans_ops->alloc(priv->shrd); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index af846002150..fff5b620927 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -821,7 +821,6 @@ struct iwl_wipan_noa_data { struct iwl_priv { /*data shared among all the driver's layers */ - struct iwl_shared _shrd; struct iwl_shared *shrd; /* ieee device used by generic ieee processing code */ diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 2c46063522c..a3ca0a78336 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -374,10 +374,18 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (!bus) { dev_printk(KERN_ERR, &pdev->dev, "Couldn't allocate iwl_pci_bus"); + return -ENOMEM; + } + + bus->shrd = kzalloc(sizeof(*bus->shrd), GFP_KERNEL); + if (!bus->shrd) { + dev_printk(KERN_ERR, &pdev->dev, + "Couldn't allocate iwl_shared"); err = -ENOMEM; goto out_no_pci; } + bus->shrd->bus = bus; pci_bus = IWL_BUS_GET_PCI_BUS(bus); pci_bus->pci_dev = pdev; @@ -472,6 +480,7 @@ out_pci_release_regions: out_pci_disable_device: pci_disable_device(pdev); out_no_pci: + kfree(bus->shrd); kfree(bus); return err; } @@ -491,6 +500,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) pci_disable_device(pci_dev); pci_set_drvdata(pci_dev, NULL); + kfree(bus->shrd); kfree(bus); } -- cgit v1.2.3 From b52e7ea109cfe4ea7fea99b1cd20f57ccd95476a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 2 Feb 2012 14:16:59 -0800 Subject: iwlwifi: allocate the transport from the bus layer Change the way we alloc the transport on the way. Since the transport is allocated from a bus specific area, we can give the bus specific parameters (i.e. pci_dev for PCI) to the transport. This will be useful when the bus layer will be killed. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 16 +++------------- drivers/net/wireless/iwlwifi/iwl-pci.c | 17 ++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 24 ++++++++++++++---------- drivers/net/wireless/iwlwifi/iwl-trans.h | 21 +++++++++++++++------ 4 files changed, 48 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b42be308450..1a4ba9de99b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1783,12 +1783,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, priv->shrd = bus->shrd; priv->shrd->priv = priv; - priv->shrd->trans = trans_ops->alloc(priv->shrd); - if (priv->shrd->trans == NULL) { - err = -ENOMEM; - goto out_free_traffic_mem; - } - /* At this point both hw and priv are allocated. */ SET_IEEE80211_DEV(hw, bus(priv)->dev); @@ -1835,12 +1829,12 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, err = iwl_trans_request_irq(trans(priv)); if (err) - goto out_free_trans; + goto out_free_traffic_mem; if (iwl_trans_prepare_card_hw(trans(priv))) { err = -EIO; IWL_WARN(priv, "Failed, HW not ready\n"); - goto out_free_trans; + goto out_free_traffic_mem; } /***************** @@ -1854,7 +1848,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, iwl_apm_stop(priv); if (err) { IWL_ERR(priv, "Unable to init EEPROM\n"); - goto out_free_trans; + goto out_free_traffic_mem; } err = iwl_eeprom_check_version(priv); if (err) @@ -1935,8 +1929,6 @@ out_destroy_workqueue: iwl_uninit_drv(priv); out_free_eeprom: iwl_eeprom_free(priv->shrd); -out_free_trans: - iwl_trans_free(trans(priv)); out_free_traffic_mem: iwl_free_traffic_mem(priv); ieee80211_free_hw(priv->hw); @@ -1980,8 +1972,6 @@ void __devexit iwl_remove(struct iwl_priv * priv) priv->shrd->workqueue = NULL; iwl_free_traffic_mem(priv); - iwl_trans_free(trans(priv)); - iwl_uninit_drv(priv); dev_kfree_skb(priv->beacon_skb); diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index a3ca0a78336..c0d62e72495 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -463,14 +463,28 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bus->ops = &bus_ops_pci; #ifdef CONFIG_IWLWIFI_IDI + trans(bus) = iwl_trans_idi_alloc(bus->shrd, pdev, ent); + if (trans(bus) == NULL) { + err = -ENOMEM; + goto out_disable_msi; + } + err = iwl_probe(bus, &trans_ops_idi, cfg); #else + trans(bus) = iwl_trans_pcie_alloc(bus->shrd, pdev, ent); + if (trans(bus) == NULL) { + err = -ENOMEM; + goto out_disable_msi; + } + err = iwl_probe(bus, &trans_ops_pcie, cfg); #endif if (err) - goto out_disable_msi; + goto out_free_trans; return 0; +out_free_trans: + iwl_trans_free(trans(bus)); out_disable_msi: pci_disable_msi(pdev); pci_iounmap(pdev, pci_bus->hw_base); @@ -493,6 +507,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) struct iwl_shared *shrd = bus->shrd; iwl_remove(shrd->priv); + iwl_trans_free(shrd->trans); pci_disable_msi(pci_dev); pci_iounmap(pci_dev, pci_bus->hw_base); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 0b4280c9258..f0d8cccbcb1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1376,19 +1376,24 @@ static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, const struct iwl_trans_ops trans_ops_pcie; -static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) +struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, + struct pci_dev *pdev, + const struct pci_device_id *ent) { + struct iwl_trans_pcie *trans_pcie; struct iwl_trans *iwl_trans = kzalloc(sizeof(struct iwl_trans) + sizeof(struct iwl_trans_pcie), GFP_KERNEL); - if (iwl_trans) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(iwl_trans); - iwl_trans->ops = &trans_ops_pcie; - iwl_trans->shrd = shrd; - trans_pcie->trans = iwl_trans; - spin_lock_init(&iwl_trans->hcmd_lock); - } + + if (WARN_ON(!iwl_trans)) + return NULL; + + trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans); + + iwl_trans->ops = &trans_ops_pcie; + iwl_trans->shrd = shrd; + trans_pcie->trans = iwl_trans; + spin_lock_init(&iwl_trans->hcmd_lock); return iwl_trans; } @@ -1912,7 +1917,6 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, #endif /*CONFIG_IWLWIFI_DEBUGFS */ const struct iwl_trans_ops trans_ops_pcie = { - .alloc = iwl_trans_pcie_alloc, .request_irq = iwl_trans_pcie_request_irq, .fw_alive = iwl_trans_pcie_fw_alive, .start_device = iwl_trans_pcie_start_device, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 2a6649c9ca4..b1a7af26c57 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -133,7 +133,6 @@ struct iwl_host_cmd { /** * struct iwl_trans_ops - transport specific operations - * @alloc: allocates the meta data (not the queues themselves) * @request_irq: requests IRQ - will be called before the FW load in probe flow * @start_device: allocates and inits all the resources for the transport * layer. @@ -162,7 +161,6 @@ struct iwl_host_cmd { */ struct iwl_trans_ops { - struct iwl_trans *(*alloc)(struct iwl_shared *shrd); int (*request_irq)(struct iwl_trans *iwl_trans); int (*start_device)(struct iwl_trans *trans); void (*fw_alive)(struct iwl_trans *trans); @@ -380,11 +378,8 @@ static inline int iwl_trans_resume(struct iwl_trans *trans) #endif /***************************************************** -* Transport layers implementations +* Utils functions ******************************************************/ -extern const struct iwl_trans_ops trans_ops_pcie; -extern const struct iwl_trans_ops trans_ops_idi; - int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, const void *data, size_t len); void iwl_dealloc_ucode(struct iwl_trans *trans); @@ -394,4 +389,18 @@ int iwl_calib_set(struct iwl_trans *trans, const struct iwl_calib_hdr *cmd, int len); void iwl_calib_free_results(struct iwl_trans *trans); +/***************************************************** +* Transport layers implementations + their allocation function +******************************************************/ +struct pci_dev; +struct pci_device_id; +extern const struct iwl_trans_ops trans_ops_pcie; +struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, + struct pci_dev *pdev, + const struct pci_device_id *ent); + +extern const struct iwl_trans_ops trans_ops_idi; +struct iwl_trans *iwl_trans_idi_alloc(struct iwl_shared *shrd, + void *pdev_void, + const void *ent_void); #endif /* __iwl_trans_h__ */ -- cgit v1.2.3 From a42a184458ae95937893cb873c988385637c5e14 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 2 Feb 2012 14:33:08 -0800 Subject: iwlwifi: move the bus configuration to transport All the bus configuration is now done in the transport allocation fucntion. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-bus.h | 2 - drivers/net/wireless/iwlwifi/iwl-pci.c | 93 +----------- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 6 + drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 169 ++++++++++++++++++---- drivers/net/wireless/iwlwifi/iwl-trans.h | 5 + 5 files changed, 158 insertions(+), 117 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 941b9cb2344..37ed7b60aaf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -148,7 +148,6 @@ struct iwl_bus_ops { * @shrd - pointer to iwl_shared which holds shared data from the upper layer * NB: for the time being this needs to be set by the upper layer since * it allocates the shared data - * @irq - the irq number for the device * @reg_lock - protect hw register access */ struct iwl_bus { @@ -156,7 +155,6 @@ struct iwl_bus { const struct iwl_bus_ops *ops; struct iwl_shared *shrd; - unsigned int irq; spinlock_t reg_lock; /* pointer to bus specific struct */ diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index c0d62e72495..631b67ca2b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -367,7 +367,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); struct iwl_bus *bus; struct iwl_pci_bus *pci_bus; - u16 pci_cmd; int err; bus = kzalloc(sizeof(*bus) + sizeof(*pci_bus), GFP_KERNEL); @@ -382,7 +381,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_printk(KERN_ERR, &pdev->dev, "Couldn't allocate iwl_shared"); err = -ENOMEM; - goto out_no_pci; + goto out_free_bus; } bus->shrd->bus = bus; @@ -391,82 +390,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, bus); - /* W/A - seems to solve weird behavior. We need to remove this if we - * don't want to stay in L1 all the time. This wastes a lot of power */ - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | - PCIE_LINK_STATE_CLKPM); - - if (pci_enable_device(pdev)) { - err = -ENODEV; - goto out_no_pci; - } - - pci_set_master(pdev); - - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); - if (err) { - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, - DMA_BIT_MASK(32)); - /* both attempts failed: */ - if (err) { - dev_printk(KERN_ERR, bus->dev, - "No suitable DMA available.\n"); - goto out_pci_disable_device; - } - } - - err = pci_request_regions(pdev, DRV_NAME); - if (err) { - dev_printk(KERN_ERR, bus->dev, "pci_request_regions failed"); - goto out_pci_disable_device; - } - - pci_bus->hw_base = pci_iomap(pdev, 0, 0); - if (!pci_bus->hw_base) { - dev_printk(KERN_ERR, bus->dev, "pci_iomap failed"); - err = -ENODEV; - goto out_pci_release_regions; - } - - dev_printk(KERN_INFO, &pdev->dev, - "pci_resource_len = 0x%08llx\n", - (unsigned long long) pci_resource_len(pdev, 0)); - dev_printk(KERN_INFO, &pdev->dev, - "pci_resource_base = %p\n", pci_bus->hw_base); - - dev_printk(KERN_INFO, &pdev->dev, - "HW Revision ID = 0x%X\n", pdev->revision); - - /* We disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state */ - pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - - err = pci_enable_msi(pdev); - if (err) - dev_printk(KERN_ERR, &pdev->dev, - "pci_enable_msi failed(0X%x)", err); - - /* TODO: Move this away, not needed if not MSI */ - /* enable rfkill interrupt: hw bug w/a */ - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { - pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - } - bus->dev = &pdev->dev; - bus->irq = pdev->irq; bus->ops = &bus_ops_pci; #ifdef CONFIG_IWLWIFI_IDI trans(bus) = iwl_trans_idi_alloc(bus->shrd, pdev, ent); if (trans(bus) == NULL) { err = -ENOMEM; - goto out_disable_msi; + goto out_free_bus; } err = iwl_probe(bus, &trans_ops_idi, cfg); @@ -474,26 +405,20 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) trans(bus) = iwl_trans_pcie_alloc(bus->shrd, pdev, ent); if (trans(bus) == NULL) { err = -ENOMEM; - goto out_disable_msi; + goto out_free_bus; } err = iwl_probe(bus, &trans_ops_pcie, cfg); #endif if (err) goto out_free_trans; + return 0; out_free_trans: iwl_trans_free(trans(bus)); -out_disable_msi: - pci_disable_msi(pdev); - pci_iounmap(pdev, pci_bus->hw_base); -out_pci_release_regions: pci_set_drvdata(pdev, NULL); - pci_release_regions(pdev); -out_pci_disable_device: - pci_disable_device(pdev); -out_no_pci: +out_free_bus: kfree(bus->shrd); kfree(bus); return err; @@ -502,18 +427,12 @@ out_no_pci: static void __devexit iwl_pci_remove(struct pci_dev *pdev) { struct iwl_bus *bus = pci_get_drvdata(pdev); - struct iwl_pci_bus *pci_bus = IWL_BUS_GET_PCI_BUS(bus); - struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); struct iwl_shared *shrd = bus->shrd; iwl_remove(shrd->priv); iwl_trans_free(shrd->trans); - pci_disable_msi(pci_dev); - pci_iounmap(pci_dev, pci_bus->hw_base); - pci_release_regions(pci_dev); - pci_disable_device(pci_dev); - pci_set_drvdata(pci_dev, NULL); + pci_set_drvdata(pdev, NULL); kfree(bus->shrd); kfree(bus); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 0f73778b73f..47d27bdf2df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -211,6 +211,8 @@ struct iwl_tx_queue { * @txq_ctx_active_msk: what queue is active * queue_stopped: tracks what queue is stopped * queue_stop_count: tracks what SW queue is stopped + * @pci_dev: basic pci-network driver stuff + * @hw_base: pci hardware address support */ struct iwl_trans_pcie { struct iwl_rx_queue rxq; @@ -241,6 +243,10 @@ struct iwl_trans_pcie { #define IWL_MAX_HW_QUEUES 32 unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; atomic_t queue_stop_count[4]; + + /* PCI bus related data */ + struct pci_dev *pci_dev; + void __iomem *hw_base; }; #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index f0d8cccbcb1..5d0cfe03340 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -60,6 +60,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ +#include +#include #include #include #include @@ -1042,7 +1044,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) spin_unlock_irqrestore(&trans->shrd->lock, flags); /* wait to make sure we flush pending tasklet*/ - synchronize_irq(bus(trans)->irq); + synchronize_irq(trans->irq); tasklet_kill(&trans_pcie->irq_tasklet); /* stop and reset the on-board processor */ @@ -1246,10 +1248,10 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) iwl_alloc_isr_ict(trans); - err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED, + err = request_irq(trans->irq, iwl_isr_ict, IRQF_SHARED, DRV_NAME, trans); if (err) { - IWL_ERR(trans, "Error allocating IRQ %d\n", bus(trans)->irq); + IWL_ERR(trans, "Error allocating IRQ %d\n", trans->irq); iwl_free_isr_ict(trans); return err; } @@ -1299,13 +1301,22 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, static void iwl_trans_pcie_free(struct iwl_trans *trans) { + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + iwl_calib_free_results(trans); iwl_trans_pcie_tx_free(trans); #ifndef CONFIG_IWLWIFI_IDI iwl_trans_pcie_rx_free(trans); #endif - free_irq(bus(trans)->irq, trans); + free_irq(trans->irq, trans); iwl_free_isr_ict(trans); + + pci_disable_msi(trans_pcie->pci_dev); + pci_iounmap(trans_pcie->pci_dev, trans_pcie->hw_base); + pci_release_regions(trans_pcie->pci_dev); + pci_disable_device(trans_pcie->pci_dev); + trans->shrd->trans = NULL; kfree(trans); } @@ -1374,30 +1385,6 @@ static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, } } -const struct iwl_trans_ops trans_ops_pcie; - -struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, - struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct iwl_trans_pcie *trans_pcie; - struct iwl_trans *iwl_trans = kzalloc(sizeof(struct iwl_trans) + - sizeof(struct iwl_trans_pcie), - GFP_KERNEL); - - if (WARN_ON(!iwl_trans)) - return NULL; - - trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans); - - iwl_trans->ops = &trans_ops_pcie; - iwl_trans->shrd = shrd; - trans_pcie->trans = iwl_trans; - spin_lock_init(&iwl_trans->hcmd_lock); - - return iwl_trans; -} - static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id, const char *msg) { @@ -1949,3 +1936,129 @@ const struct iwl_trans_ops trans_ops_pcie = { .resume = iwl_trans_pcie_resume, #endif }; + +/* TODO: remove this hack - will be possible when all the io{write/read} ops + * will be done through the transport + */ +struct iwl_pci_bus { + /* basic pci-network driver stuff */ + struct pci_dev *pci_dev; + + /* pci hardware address support */ + void __iomem *hw_base; +}; + +#define IWL_BUS_GET_PCI_BUS(_iwl_bus) \ + ((struct iwl_pci_bus *) ((_iwl_bus)->bus_specific)) + +/* PCI registers */ +#define PCI_CFG_RETRY_TIMEOUT 0x041 + +struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, + struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct iwl_pci_bus *iwl_pci_bus = IWL_BUS_GET_PCI_BUS(shrd->bus); + struct iwl_trans_pcie *trans_pcie; + struct iwl_trans *trans; + u16 pci_cmd; + int err; + + trans = kzalloc(sizeof(struct iwl_trans) + + sizeof(struct iwl_trans_pcie), GFP_KERNEL); + + if (WARN_ON(!trans)) + return NULL; + + trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + trans->ops = &trans_ops_pcie; + trans->shrd = shrd; + trans_pcie->trans = trans; + spin_lock_init(&trans->hcmd_lock); + + /* W/A - seems to solve weird behavior. We need to remove this if we + * don't want to stay in L1 all the time. This wastes a lot of power */ + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | + PCIE_LINK_STATE_CLKPM); + + if (pci_enable_device(pdev)) { + err = -ENODEV; + goto out_no_pci; + } + + pci_set_master(pdev); + + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); + if (!err) + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); + if (err) { + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (!err) + err = pci_set_consistent_dma_mask(pdev, + DMA_BIT_MASK(32)); + /* both attempts failed: */ + if (err) { + dev_printk(KERN_ERR, &pdev->dev, + "No suitable DMA available.\n"); + goto out_pci_disable_device; + } + } + + err = pci_request_regions(pdev, DRV_NAME); + if (err) { + dev_printk(KERN_ERR, &pdev->dev, "pci_request_regions failed"); + goto out_pci_disable_device; + } + + trans_pcie->hw_base = pci_iomap(pdev, 0, 0); + if (!trans_pcie->hw_base) { + dev_printk(KERN_ERR, &pdev->dev, "pci_iomap failed"); + err = -ENODEV; + goto out_pci_release_regions; + } + + /* TODO: remove this hack */ + iwl_pci_bus->hw_base = trans_pcie->hw_base; + + dev_printk(KERN_INFO, &pdev->dev, + "pci_resource_len = 0x%08llx\n", + (unsigned long long) pci_resource_len(pdev, 0)); + dev_printk(KERN_INFO, &pdev->dev, + "pci_resource_base = %p\n", trans_pcie->hw_base); + + dev_printk(KERN_INFO, &pdev->dev, + "HW Revision ID = 0x%X\n", pdev->revision); + + /* We disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state */ + pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); + + err = pci_enable_msi(pdev); + if (err) + dev_printk(KERN_ERR, &pdev->dev, + "pci_enable_msi failed(0X%x)", err); + + trans->dev = &pdev->dev; + trans->irq = pdev->irq; + trans_pcie->pci_dev = pdev; + + /* TODO: Move this away, not needed if not MSI */ + /* enable rfkill interrupt: hw bug w/a */ + pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); + if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { + pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; + pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); + } + + return trans; + +out_pci_release_regions: + pci_release_regions(pdev); +out_pci_disable_device: + pci_disable_device(pdev); +out_no_pci: + kfree(trans); + return NULL; +} + diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index b1a7af26c57..9a807619486 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -228,6 +228,8 @@ struct iwl_calib_result { * @ops - pointer to iwl_trans_ops * @shrd - pointer to iwl_shared which holds shared data from the upper layer * @hcmd_lock: protects HCMD + * @dev - pointer to struct device * that represents the device + * @irq - the irq number for the device * @ucode_write_complete: indicates that the ucode has been copied. * @ucode_rt: run time ucode image * @ucode_init: init ucode image @@ -240,6 +242,9 @@ struct iwl_trans { struct iwl_shared *shrd; spinlock_t hcmd_lock; + struct device *dev; + unsigned int irq; + u8 ucode_write_complete; /* the image write is complete */ struct fw_img ucode_rt; struct fw_img ucode_init; -- cgit v1.2.3 From 0390549571cb614ac5cd3327b63f95155a75c673 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 3 Jan 2012 13:48:07 +0200 Subject: iwlwifi: the read / write register ops move to transport Most of the accesses to the registers are done from the transport layer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-bus.h | 21 --------------- drivers/net/wireless/iwlwifi/iwl-io.h | 11 +++++--- drivers/net/wireless/iwlwifi/iwl-pci.c | 22 ---------------- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 37 ++++++++++++++------------- drivers/net/wireless/iwlwifi/iwl-trans.h | 21 +++++++++++++++ 5 files changed, 48 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 37ed7b60aaf..981f7b79d39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -124,18 +124,12 @@ struct iwl_bus; * @apm_config: will be called during the config of the APM * @get_hw_id_string: prints the hw_id in the provided buffer * @get_hw_id: get hw_id in u32 - * @write8: write a byte to register at offset ofs - * @write32: write a dword to register at offset ofs - * @wread32: read a dword at register at offset ofs */ struct iwl_bus_ops { bool (*get_pm_support)(struct iwl_bus *bus); void (*apm_config)(struct iwl_bus *bus); void (*get_hw_id_string)(struct iwl_bus *bus, char buf[], int buf_len); u32 (*get_hw_id)(struct iwl_bus *bus); - void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); - void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); - u32 (*read32)(struct iwl_bus *bus, u32 ofs); }; /** @@ -183,21 +177,6 @@ static inline u32 bus_get_hw_id(struct iwl_bus *bus) return bus->ops->get_hw_id(bus); } -static inline void bus_write8(struct iwl_bus *bus, u32 ofs, u8 val) -{ - bus->ops->write8(bus, ofs, val); -} - -static inline void bus_write32(struct iwl_bus *bus, u32 ofs, u32 val) -{ - bus->ops->write32(bus, ofs, val); -} - -static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs) -{ - return bus->ops->read32(bus, ofs); -} - /***************************************************** * Bus layer registration functions ******************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 427d065435c..b8e00cd7b1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -31,23 +31,28 @@ #include "iwl-devtrace.h" #include "iwl-shared.h" +/* TODO: remove when not needed any more */ #include "iwl-bus.h" +#include "iwl-trans.h" static inline void iwl_write8(struct iwl_bus *bus, u32 ofs, u8 val) { + /* TODO: get trans instead of bus */ trace_iwlwifi_dev_iowrite8(priv(bus), ofs, val); - bus_write8(bus, ofs, val); + iwl_trans_write8(trans(bus), ofs, val); } static inline void iwl_write32(struct iwl_bus *bus, u32 ofs, u32 val) { + /* TODO: get trans instead of bus */ trace_iwlwifi_dev_iowrite32(priv(bus), ofs, val); - bus_write32(bus, ofs, val); + iwl_trans_write32(trans(bus), ofs, val); } static inline u32 iwl_read32(struct iwl_bus *bus, u32 ofs) { - u32 val = bus_read32(bus, ofs); + /* TODO: get trans instead of bus */ + u32 val = iwl_trans_read32(trans(bus), ofs); trace_iwlwifi_dev_ioread32(priv(bus), ofs, val); return val; } diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 631b67ca2b6..ab462337d7a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -79,9 +79,6 @@ struct iwl_pci_bus { /* basic pci-network driver stuff */ struct pci_dev *pci_dev; - - /* pci hardware address support */ - void __iomem *hw_base; }; #define IWL_BUS_GET_PCI_BUS(_iwl_bus) \ @@ -151,30 +148,11 @@ static u32 iwl_pci_get_hw_id(struct iwl_bus *bus) return (pci_dev->device << 16) + pci_dev->subsystem_device; } -static void iwl_pci_write8(struct iwl_bus *bus, u32 ofs, u8 val) -{ - iowrite8(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); -} - -static void iwl_pci_write32(struct iwl_bus *bus, u32 ofs, u32 val) -{ - iowrite32(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); -} - -static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs) -{ - u32 val = ioread32(IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); - return val; -} - static const struct iwl_bus_ops bus_ops_pci = { .get_pm_support = iwl_pci_is_pm_supported, .apm_config = iwl_pci_apm_config, .get_hw_id_string = iwl_pci_get_hw_id_string, .get_hw_id = iwl_pci_get_hw_id, - .write8 = iwl_pci_write8, - .write32 = iwl_pci_write32, - .read32 = iwl_pci_read32, }; #define IWL_PCI_DEVICE(dev, subdev, cfg) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 5d0cfe03340..80f531844f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1299,6 +1299,22 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, return 0; } +static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) +{ + iowrite8(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); +} + +static void iwl_trans_pcie_write32(struct iwl_trans *trans, u32 ofs, u32 val) +{ + iowrite32(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); +} + +static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs) +{ + u32 val = ioread32(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); + return val; +} + static void iwl_trans_pcie_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = @@ -1935,22 +1951,11 @@ const struct iwl_trans_ops trans_ops_pcie = { .suspend = iwl_trans_pcie_suspend, .resume = iwl_trans_pcie_resume, #endif + .write8 = iwl_trans_pcie_write8, + .write32 = iwl_trans_pcie_write32, + .read32 = iwl_trans_pcie_read32, }; -/* TODO: remove this hack - will be possible when all the io{write/read} ops - * will be done through the transport - */ -struct iwl_pci_bus { - /* basic pci-network driver stuff */ - struct pci_dev *pci_dev; - - /* pci hardware address support */ - void __iomem *hw_base; -}; - -#define IWL_BUS_GET_PCI_BUS(_iwl_bus) \ - ((struct iwl_pci_bus *) ((_iwl_bus)->bus_specific)) - /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 @@ -1958,7 +1963,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, struct pci_dev *pdev, const struct pci_device_id *ent) { - struct iwl_pci_bus *iwl_pci_bus = IWL_BUS_GET_PCI_BUS(shrd->bus); struct iwl_trans_pcie *trans_pcie; struct iwl_trans *trans; u16 pci_cmd; @@ -2018,9 +2022,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, goto out_pci_release_regions; } - /* TODO: remove this hack */ - iwl_pci_bus->hw_base = trans_pcie->hw_base; - dev_printk(KERN_INFO, &pdev->dev, "pci_resource_len = 0x%08llx\n", (unsigned long long) pci_resource_len(pdev, 0)); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 9a807619486..0a3727dac6a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -158,6 +158,9 @@ struct iwl_host_cmd { * automatically deleted. * @suspend: stop the device unless WoWLAN is configured * @resume: resume activity of the device + * @write8: write a u8 to a register at offset ofs from the BAR + * @write32: write a u32 to a register at offset ofs from the BAR + * @read32: read a u32 register at offset ofs from the BAR */ struct iwl_trans_ops { @@ -201,6 +204,9 @@ struct iwl_trans_ops { int (*suspend)(struct iwl_trans *trans); int (*resume)(struct iwl_trans *trans); #endif + void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val); + void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val); + u32 (*read32)(struct iwl_trans *trans, u32 ofs); }; /* one for each uCode image (inst/data, boot/init/runtime) */ @@ -382,6 +388,21 @@ static inline int iwl_trans_resume(struct iwl_trans *trans) } #endif +static inline void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val) +{ + trans->ops->write8(trans, ofs, val); +} + +static inline void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val) +{ + trans->ops->write32(trans, ofs, val); +} + +static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs) +{ + return trans->ops->read32(trans, ofs); +} + /***************************************************** * Utils functions ******************************************************/ -- cgit v1.2.3 From 1042db2af183b96cdce5972014d85e8bca0634ad Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 3 Jan 2012 16:56:15 +0200 Subject: iwlwifi: give trans to all the read / write functions From now on, the transport layer in charge of providing access to the device. So change all the driver to give a pointer to the transport to all the low level functions that actually access the device. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 +- drivers/net/wireless/iwlwifi/iwl-2000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 8 +- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 8 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 14 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 42 ++--- drivers/net/wireless/iwlwifi/iwl-bus.h | 3 - drivers/net/wireless/iwlwifi/iwl-core.c | 28 ++-- drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 6 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 61 +++---- drivers/net/wireless/iwlwifi/iwl-io.c | 193 +++++++++++----------- drivers/net/wireless/iwlwifi/iwl-io.h | 63 ++++--- drivers/net/wireless/iwlwifi/iwl-led.c | 9 +- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 27 +-- drivers/net/wireless/iwlwifi/iwl-pci.c | 4 +- drivers/net/wireless/iwlwifi/iwl-testmode.c | 16 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 8 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 82 ++++----- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 46 +++--- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 144 ++++++++-------- drivers/net/wireless/iwlwifi/iwl-trans.h | 2 + drivers/net/wireless/iwlwifi/iwl-ucode.c | 37 ++--- 24 files changed, 405 insertions(+), 406 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index cc04cce1156..f7a555b9d24 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -84,13 +84,13 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) static void iwl1000_nic_config(struct iwl_priv *priv) { /* set CSR_HW_CONFIG_REG for uCode use */ - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(trans(priv), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); /* Setting digital SVR for 1000 card to 1.32V */ /* locking is acquired in iwl_set_bits_mask_prph() function */ - iwl_set_bits_mask_prph(bus(priv), APMG_DIGITAL_SVR_REG, + iwl_set_bits_mask_prph(trans(priv), APMG_DIGITAL_SVR_REG, APMG_SVR_DIGITAL_VOLTAGE_1_32, ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); } diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 00db092d8cd..87600345010 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -87,7 +87,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv) iwl_rf_config(priv); if (cfg(priv)->iq_invert) - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); } diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 47fd98b3652..5245a1422a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -73,7 +73,7 @@ static void iwl5000_nic_config(struct iwl_priv *priv) * (PCIe power is lost before PERST# is asserted), * causing ME FW to lose ownership and not being able to obtain it back. */ - iwl_set_bits_mask_prph(bus(priv), APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(trans(priv), APMG_PS_CTRL_REG, APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index ab62c018fcd..464b8878467 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -82,7 +82,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv) { /* Indicate calibration version to uCode. */ if (iwl_eeprom_calib_version(priv->shrd) >= 6) - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); } @@ -90,9 +90,9 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv) { /* Indicate calibration version to uCode. */ if (iwl_eeprom_calib_version(priv->shrd) >= 6) - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_6050_1x2); } @@ -104,7 +104,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv) /* no locking required for register write */ if (cfg(priv)->pa_type == IWL_PA_INTERNAL) { /* 2x2 IPA phy type */ - iwl_write32(bus(priv), CSR_GP_DRIVER_REG, + iwl_write32(trans(priv), CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); } /* do additional nic configuration if needed */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index f127f913e5a..a14ddab783e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -628,16 +628,16 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv, if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | CT_CARD_DISABLED)) { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, + iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C, + iwl_write_direct32(trans(priv), HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); if (!(flags & RXON_CARD_DISABLED)) { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C, + iwl_write_direct32(trans(priv), HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); } if (flags & CT_CARD_DISABLED) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 56c6def015a..c728ed75584 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -178,19 +178,19 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) if (tt->state == IWL_TI_CT_KILL) { if (priv->thermal_throttle.ct_kill_toggle) { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); priv->thermal_throttle.ct_kill_toggle = false; } else { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, + iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); priv->thermal_throttle.ct_kill_toggle = true; } - iwl_read32(bus(priv), CSR_UCODE_DRV_GP1); - spin_lock_irqsave(&bus(priv)->reg_lock, flags); - if (!iwl_grab_nic_access(bus(priv))) - iwl_release_nic_access(bus(priv)); - spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); + iwl_read32(trans(priv), CSR_UCODE_DRV_GP1); + spin_lock_irqsave(&trans(priv)->reg_lock, flags); + if (!iwl_grab_nic_access(trans(priv))) + iwl_release_nic_access(trans(priv)); + spin_unlock_irqrestore(&trans(priv)->reg_lock, flags); /* Reschedule the ct_kill timer to occur in * CT_KILL_EXIT_DURATION seconds to ensure we get a diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1a4ba9de99b..f79791500a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -328,14 +328,14 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); /* Make sure device is powered up for SRAM reads */ - spin_lock_irqsave(&bus(priv)->reg_lock, reg_flags); - if (iwl_grab_nic_access(bus(priv))) { - spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); + spin_lock_irqsave(&trans(priv)->reg_lock, reg_flags); + if (iwl_grab_nic_access(trans(priv))) { + spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags); return; } /* Set starting address; reads will auto-increment */ - iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr); + iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, ptr); rmb(); /* @@ -352,19 +352,19 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); - time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + ev = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); + time = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); if (mode == 0) { trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev); } else { - data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + data = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); trace_iwlwifi_dev_ucode_cont_event(priv, time, data, ev); } } /* Allow device to power down */ - iwl_release_nic_access(bus(priv)); - spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); + iwl_release_nic_access(trans(priv)); + spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags); } static void iwl_continuous_event_trace(struct iwl_priv *priv) @@ -383,7 +383,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) base = priv->shrd->device_pointers.log_event_table; if (iwlagn_hw_valid_rtc_data_addr(base)) { - iwl_read_targ_mem_words(bus(priv), base, &read, sizeof(read)); + iwl_read_targ_mem_words(trans(priv), base, &read, sizeof(read)); capacity = read.capacity; mode = read.mode; @@ -583,7 +583,7 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) priv->firmware_name); return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, - bus(priv)->dev, + trans(priv)->dev, GFP_KERNEL, priv, iwl_ucode_callback); } @@ -1158,7 +1158,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) int ret = 0; spin_lock_irqsave(&priv->shrd->lock, flags); - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); spin_unlock_irqrestore(&priv->shrd->lock, flags); priv->thermal_throttle.ct_kill_toggle = false; @@ -1693,7 +1693,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv) static u32 iwl_hw_detect(struct iwl_priv *priv) { - return iwl_read32(bus(priv), CSR_HW_REV); + return iwl_read32(trans(priv), CSR_HW_REV); } /* Size of one Rx buffer in host DRAM */ @@ -1727,32 +1727,32 @@ static int iwl_set_hw_params(struct iwl_priv *priv) static void iwl_debug_config(struct iwl_priv *priv) { - dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEBUG " + dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEBUG " #ifdef CONFIG_IWLWIFI_DEBUG "enabled\n"); #else "disabled\n"); #endif - dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEBUGFS " + dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEBUGFS " #ifdef CONFIG_IWLWIFI_DEBUGFS "enabled\n"); #else "disabled\n"); #endif - dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TRACING " + dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TRACING " #ifdef CONFIG_IWLWIFI_DEVICE_TRACING "enabled\n"); #else "disabled\n"); #endif - dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TESTMODE " + dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TESTMODE " #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE "enabled\n"); #else "disabled\n"); #endif - dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_P2P " + dev_printk(KERN_INFO, trans(priv)->dev, "CONFIG_IWLWIFI_P2P " #ifdef CONFIG_IWLWIFI_P2P "enabled\n"); #else @@ -1810,7 +1810,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, /* these spin locks will be used in apm_ops.init and EEPROM access * we should init now */ - spin_lock_init(&bus(priv)->reg_lock); + spin_lock_init(&trans(priv)->reg_lock); spin_lock_init(&priv->shrd->lock); /* @@ -1818,7 +1818,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, * strange state ... like being left stranded by a primary kernel * and this is now the kdump kernel trying to start up */ - iwl_write32(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_write32(trans(priv), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /*********************** * 3. Read REV register @@ -1903,7 +1903,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, iwl_enable_rfkill_int(priv); /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(bus(priv), + if (iwl_read32(trans(priv), CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); else diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 981f7b79d39..ce1a9cc106e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -142,15 +142,12 @@ struct iwl_bus_ops { * @shrd - pointer to iwl_shared which holds shared data from the upper layer * NB: for the time being this needs to be set by the upper layer since * it allocates the shared data - * @reg_lock - protect hw register access */ struct iwl_bus { struct device *dev; const struct iwl_bus_ops *ops; struct iwl_shared *shrd; - spinlock_t reg_lock; - /* pointer to bus specific struct */ /*Ensure that this pointer will always be aligned to sizeof pointer */ char bus_specific[0] __attribute__((__aligned__(sizeof(void *)))); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 7d6eef96454..c9022c5fa81 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -888,9 +888,9 @@ static int iwl_apm_stop_master(struct iwl_priv *priv) int ret = 0; /* stop device's busmaster DMA activity */ - iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); + iwl_set_bit(trans(priv), CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - ret = iwl_poll_bit(bus(priv), CSR_RESET, + ret = iwl_poll_bit(trans(priv), CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); if (ret) @@ -911,7 +911,7 @@ void iwl_apm_stop(struct iwl_priv *priv) iwl_apm_stop_master(priv); /* Reset the entire device */ - iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + iwl_set_bit(trans(priv), CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); udelay(10); @@ -919,7 +919,8 @@ void iwl_apm_stop(struct iwl_priv *priv) * Clear "initialization complete" bit to move adapter from * D0A* (powered-up Active) --> D0U* (Uninitialized) state. */ - iwl_clear_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_clear_bit(trans(priv), CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } @@ -939,45 +940,46 @@ int iwl_apm_init(struct iwl_priv *priv) */ /* Disable L0S exit timer (platform NMI Work/Around) */ - iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS, + iwl_set_bit(trans(priv), CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); /* * Disable L0s without affecting L1; * don't wait for ICH L0s (ICH bug W/A) */ - iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS, + iwl_set_bit(trans(priv), CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); /* Set FH wait threshold to maximum (HW error during stress W/A) */ - iwl_set_bit(bus(priv), CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); + iwl_set_bit(trans(priv), CSR_DBG_HPET_MEM_REG, + CSR_DBG_HPET_MEM_REG_VAL); /* * Enable HAP INTA (interrupt from management bus) to * wake device's PCI Express link L1a -> L0s */ - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(trans(priv), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); bus_apm_config(bus(priv)); /* Configure analog phase-lock-loop before activating to D0A */ if (cfg(priv)->base_params->pll_cfg_val) - iwl_set_bit(bus(priv), CSR_ANA_PLL_CFG, + iwl_set_bit(trans(priv), CSR_ANA_PLL_CFG, cfg(priv)->base_params->pll_cfg_val); /* * Set "initialization complete" bit to move adapter from * D0U* --> D0A* (powered-up active) state. */ - iwl_set_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_set_bit(trans(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* * Wait for clock stabilization; once stabilized, access to * device-internal resources is supported, e.g. iwl_write_prph() * and accesses to uCode SRAM. */ - ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL, + ret = iwl_poll_bit(trans(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) { @@ -992,11 +994,11 @@ int iwl_apm_init(struct iwl_priv *priv) * do not disable clocks. This preserves any hardware bits already * set by default in "CLK_CTRL_REG" after reset. */ - iwl_write_prph(bus(priv), APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); + iwl_write_prph(trans(priv), APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(20); /* Disable L1-Active */ - iwl_set_bits_prph(bus(priv), APMG_PCIDEV_STT_REG, + iwl_set_bits_prph(trans(priv), APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); set_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 63f29111da1..e74bfb7bbb2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -300,7 +300,7 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) { IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); - iwl_write32(bus(priv), CSR_INT_MASK, CSR_INT_BIT_RF_KILL); + iwl_write32(trans(priv), CSR_INT_MASK, CSR_INT_BIT_RF_KILL); } extern bool bt_siso_mode; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 978a1d4c6a0..136de6fb3fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -263,7 +263,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, sram = priv->dbgfs_sram_offset & ~0x3; /* read the first u32 from sram */ - val = iwl_read_targ_mem(bus(priv), sram); + val = iwl_read_targ_mem(trans(priv), sram); for (; len; len--) { /* put the address at the start of every line */ @@ -282,7 +282,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, if (++offset == 4) { sram += 4; offset = 0; - val = iwl_read_targ_mem(bus(priv), sram); + val = iwl_read_targ_mem(trans(priv), sram); } /* put in extra spaces and split lines for human readability */ @@ -2055,7 +2055,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, const size_t bufsz = sizeof(buf); u32 pwrsave_status; - pwrsave_status = iwl_read32(bus(priv), CSR_GP_CNTRL) & + pwrsave_status = iwl_read32(trans(priv), CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK; pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index ce214e0ab49..d1fd1cdb29c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -156,16 +156,16 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus) for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { /* Request semaphore */ - iwl_set_bit(bus, CSR_HW_IF_CONFIG_REG, + iwl_set_bit(trans(bus), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); /* See if we got it */ - ret = iwl_poll_bit(bus, CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(trans(bus), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, EEPROM_SEM_TIMEOUT); if (ret >= 0) { - IWL_DEBUG_EEPROM(bus, + IWL_DEBUG_EEPROM(trans(bus), "Acquired semaphore after %d tries.\n", count+1); return ret; @@ -177,14 +177,15 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus) static void iwl_eeprom_release_semaphore(struct iwl_bus *bus) { - iwl_clear_bit(bus, CSR_HW_IF_CONFIG_REG, + iwl_clear_bit(trans(bus), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); } static int iwl_eeprom_verify_signature(struct iwl_trans *trans) { - u32 gp = iwl_read32(bus(trans), CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; + u32 gp = iwl_read32(trans, CSR_EEPROM_GP) & + CSR_EEPROM_GP_VALID_MSK; int ret = 0; IWL_DEBUG_EEPROM(trans, "EEPROM signature=0x%08x\n", gp); @@ -305,13 +306,13 @@ void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac) static void iwl_set_otp_access(struct iwl_bus *bus, enum iwl_access_mode mode) { - iwl_read32(bus, CSR_OTP_GP_REG); + iwl_read32(trans(bus), CSR_OTP_GP_REG); if (mode == IWL_OTP_ACCESS_ABSOLUTE) - iwl_clear_bit(bus, CSR_OTP_GP_REG, + iwl_clear_bit(trans(bus), CSR_OTP_GP_REG, CSR_OTP_GP_REG_OTP_ACCESS_MODE); else - iwl_set_bit(bus, CSR_OTP_GP_REG, + iwl_set_bit(trans(bus), CSR_OTP_GP_REG, CSR_OTP_GP_REG_OTP_ACCESS_MODE); } @@ -332,7 +333,7 @@ static int iwl_get_nvm_type(struct iwl_bus *bus, u32 hw_rev) nvm_type = NVM_DEVICE_TYPE_EEPROM; break; default: - otpgp = iwl_read32(bus, CSR_OTP_GP_REG); + otpgp = iwl_read32(trans(bus), CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) nvm_type = NVM_DEVICE_TYPE_OTP; else @@ -347,22 +348,22 @@ static int iwl_init_otp_access(struct iwl_bus *bus) int ret; /* Enable 40MHz radio clock */ - iwl_write32(bus, CSR_GP_CNTRL, - iwl_read32(bus, CSR_GP_CNTRL) | + iwl_write32(trans(bus), CSR_GP_CNTRL, + iwl_read32(trans(bus), CSR_GP_CNTRL) | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* wait for clock to be ready */ - ret = iwl_poll_bit(bus, CSR_GP_CNTRL, + ret = iwl_poll_bit(trans(bus), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) IWL_ERR(bus, "Time out access OTP\n"); else { - iwl_set_bits_prph(bus, APMG_PS_CTRL_REG, + iwl_set_bits_prph(trans(bus), APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); udelay(5); - iwl_clear_bits_prph(bus, APMG_PS_CTRL_REG, + iwl_clear_bits_prph(trans(bus), APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); /* @@ -370,7 +371,7 @@ static int iwl_init_otp_access(struct iwl_bus *bus) * this is only applicable for HW with OTP shadow RAM */ if (cfg(bus)->base_params->shadow_ram_support) - iwl_set_bit(bus, CSR_DBG_LINK_PWR_MGMT_REG, + iwl_set_bit(trans(bus), CSR_DBG_LINK_PWR_MGMT_REG, CSR_RESET_LINK_PWR_MGMT_DISABLED); } return ret; @@ -382,9 +383,9 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data) u32 r; u32 otpgp; - iwl_write32(bus, CSR_EEPROM_REG, + iwl_write32(trans(bus), CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_bit(bus, CSR_EEPROM_REG, + ret = iwl_poll_bit(trans(bus), CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); @@ -392,13 +393,13 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data) IWL_ERR(bus, "Time out reading OTP[%d]\n", addr); return ret; } - r = iwl_read32(bus, CSR_EEPROM_REG); + r = iwl_read32(trans(bus), CSR_EEPROM_REG); /* check for ECC errors: */ - otpgp = iwl_read32(bus, CSR_OTP_GP_REG); + otpgp = iwl_read32(trans(bus), CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { /* stop in this case */ /* set the uncorrectable OTP ECC bit for acknowledgement */ - iwl_set_bit(bus, CSR_OTP_GP_REG, + iwl_set_bit(trans(bus), CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); IWL_ERR(bus, "Uncorrectable OTP ECC error, abort OTP read\n"); return -EINVAL; @@ -406,7 +407,7 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data) if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { /* continue in this case */ /* set the correctable OTP ECC bit for acknowledgement */ - iwl_set_bit(bus, CSR_OTP_GP_REG, + iwl_set_bit(trans(bus), CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); IWL_ERR(bus, "Correctable OTP ECC error, continue read\n"); } @@ -656,7 +657,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) { struct iwl_shared *shrd = priv->shrd; __le16 *e; - u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP); + u32 gp = iwl_read32(trans(priv), CSR_EEPROM_GP); int sz; int ret; u16 addr; @@ -699,11 +700,11 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) ret = -ENOENT; goto done; } - iwl_write32(bus(priv), CSR_EEPROM_GP, - iwl_read32(bus(priv), CSR_EEPROM_GP) & + iwl_write32(trans(priv), CSR_EEPROM_GP, + iwl_read32(trans(priv), CSR_EEPROM_GP) & ~CSR_EEPROM_GP_IF_OWNER_MSK); - iwl_set_bit(bus(priv), CSR_OTP_GP_REG, + iwl_set_bit(trans(priv), CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); /* traversing the linked list if no shadow ram supported */ @@ -728,10 +729,10 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) for (addr = 0; addr < sz; addr += sizeof(u16)) { u32 r; - iwl_write32(bus(priv), CSR_EEPROM_REG, + iwl_write32(trans(priv), CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG, + ret = iwl_poll_bit(trans(priv), CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); @@ -739,7 +740,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); goto done; } - r = iwl_read32(bus(priv), CSR_EEPROM_REG); + r = iwl_read32(trans(priv), CSR_EEPROM_REG); e[addr / 2] = cpu_to_le16(r >> 16); } } @@ -1068,7 +1069,7 @@ void iwl_rf_config(struct iwl_priv *priv) /* write radio config values to register */ if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(trans(priv), CSR_HW_IF_CONFIG_REG, EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); @@ -1080,7 +1081,7 @@ void iwl_rf_config(struct iwl_priv *priv) WARN_ON(1); /* set CSR_HW_CONFIG_REG for uCode use */ - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(trans(priv), CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); } diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 83fdff38115..e2e3b5c9cf7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -34,41 +34,41 @@ #define IWL_POLL_INTERVAL 10 /* microseconds */ -static inline void __iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask) +static inline void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) { - iwl_write32(bus, reg, iwl_read32(bus, reg) | mask); + iwl_write32(trans, reg, iwl_read32(trans, reg) | mask); } -static inline void __iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask) +static inline void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) { - iwl_write32(bus, reg, iwl_read32(bus, reg) & ~mask); + iwl_write32(trans, reg, iwl_read32(trans, reg) & ~mask); } -void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - __iwl_set_bit(bus, reg, mask); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&trans->reg_lock, flags); + __iwl_set_bit(trans, reg, mask); + spin_unlock_irqrestore(&trans->reg_lock, flags); } -void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - __iwl_clear_bit(bus, reg, mask); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&trans->reg_lock, flags); + __iwl_clear_bit(trans, reg, mask); + spin_unlock_irqrestore(&trans->reg_lock, flags); } -int iwl_poll_bit(struct iwl_bus *bus, u32 addr, +int iwl_poll_bit(struct iwl_trans *trans, u32 addr, u32 bits, u32 mask, int timeout) { int t = 0; do { - if ((iwl_read32(bus, addr) & mask) == (bits & mask)) + if ((iwl_read32(trans, addr) & mask) == (bits & mask)) return t; udelay(IWL_POLL_INTERVAL); t += IWL_POLL_INTERVAL; @@ -77,14 +77,15 @@ int iwl_poll_bit(struct iwl_bus *bus, u32 addr, return -ETIMEDOUT; } -int iwl_grab_nic_access_silent(struct iwl_bus *bus) +int iwl_grab_nic_access_silent(struct iwl_trans *trans) { int ret; - lockdep_assert_held(&bus->reg_lock); + lockdep_assert_held(&trans->reg_lock); /* this bit wakes up the NIC */ - __iwl_set_bit(bus, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + __iwl_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* * These bits say the device is running, and should keep running for @@ -105,70 +106,70 @@ int iwl_grab_nic_access_silent(struct iwl_bus *bus) * 5000 series and later (including 1000 series) have non-volatile SRAM, * and do not save/restore SRAM when power cycling. */ - ret = iwl_poll_bit(bus, CSR_GP_CNTRL, + ret = iwl_poll_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); if (ret < 0) { - iwl_write32(bus, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); + iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); return -EIO; } return 0; } -int iwl_grab_nic_access(struct iwl_bus *bus) +int iwl_grab_nic_access(struct iwl_trans *trans) { - int ret = iwl_grab_nic_access_silent(bus); + int ret = iwl_grab_nic_access_silent(trans); if (ret) { - u32 val = iwl_read32(bus, CSR_GP_CNTRL); - IWL_ERR(bus, + u32 val = iwl_read32(trans, CSR_GP_CNTRL); + IWL_ERR(trans, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); } return ret; } -void iwl_release_nic_access(struct iwl_bus *bus) +void iwl_release_nic_access(struct iwl_trans *trans) { - lockdep_assert_held(&bus->reg_lock); - __iwl_clear_bit(bus, CSR_GP_CNTRL, + lockdep_assert_held(&trans->reg_lock); + __iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } -u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg) +u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) { u32 value; unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - value = iwl_read32(bus, reg); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&trans->reg_lock, flags); + iwl_grab_nic_access(trans); + value = iwl_read32(trans, reg); + iwl_release_nic_access(trans); + spin_unlock_irqrestore(&trans->reg_lock, flags); return value; } -void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value) +void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - if (!iwl_grab_nic_access(bus)) { - iwl_write32(bus, reg, value); - iwl_release_nic_access(bus); + spin_lock_irqsave(&trans->reg_lock, flags); + if (!iwl_grab_nic_access(trans)) { + iwl_write32(trans, reg, value); + iwl_release_nic_access(trans); } - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_unlock_irqrestore(&trans->reg_lock, flags); } -int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, +int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, int timeout) { int t = 0; do { - if ((iwl_read_direct32(bus, addr) & mask) == mask) + if ((iwl_read_direct32(trans, addr) & mask) == mask) return t; udelay(IWL_POLL_INTERVAL); t += IWL_POLL_INTERVAL; @@ -177,135 +178,135 @@ int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, return -ETIMEDOUT; } -static inline u32 __iwl_read_prph(struct iwl_bus *bus, u32 reg) +static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg) { - iwl_write32(bus, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); + iwl_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); rmb(); - return iwl_read32(bus, HBUS_TARG_PRPH_RDAT); + return iwl_read32(trans, HBUS_TARG_PRPH_RDAT); } -static inline void __iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val) +static inline void __iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val) { - iwl_write32(bus, HBUS_TARG_PRPH_WADDR, + iwl_write32(trans, HBUS_TARG_PRPH_WADDR, ((addr & 0x0000FFFF) | (3 << 24))); wmb(); - iwl_write32(bus, HBUS_TARG_PRPH_WDAT, val); + iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); } -u32 iwl_read_prph(struct iwl_bus *bus, u32 reg) +u32 iwl_read_prph(struct iwl_trans *trans, u32 reg) { unsigned long flags; u32 val; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - val = __iwl_read_prph(bus, reg); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&trans->reg_lock, flags); + iwl_grab_nic_access(trans); + val = __iwl_read_prph(trans, reg); + iwl_release_nic_access(trans); + spin_unlock_irqrestore(&trans->reg_lock, flags); return val; } -void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val) +void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - if (!iwl_grab_nic_access(bus)) { - __iwl_write_prph(bus, addr, val); - iwl_release_nic_access(bus); + spin_lock_irqsave(&trans->reg_lock, flags); + if (!iwl_grab_nic_access(trans)) { + __iwl_write_prph(trans, addr, val); + iwl_release_nic_access(trans); } - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_unlock_irqrestore(&trans->reg_lock, flags); } -void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - __iwl_write_prph(bus, reg, __iwl_read_prph(bus, reg) | mask); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&trans->reg_lock, flags); + iwl_grab_nic_access(trans); + __iwl_write_prph(trans, reg, __iwl_read_prph(trans, reg) | mask); + iwl_release_nic_access(trans); + spin_unlock_irqrestore(&trans->reg_lock, flags); } -void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg, +void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg, u32 bits, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - __iwl_write_prph(bus, reg, - (__iwl_read_prph(bus, reg) & mask) | bits); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&trans->reg_lock, flags); + iwl_grab_nic_access(trans); + __iwl_write_prph(trans, reg, + (__iwl_read_prph(trans, reg) & mask) | bits); + iwl_release_nic_access(trans); + spin_unlock_irqrestore(&trans->reg_lock, flags); } -void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) { unsigned long flags; u32 val; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - val = __iwl_read_prph(bus, reg); - __iwl_write_prph(bus, reg, (val & ~mask)); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&trans->reg_lock, flags); + iwl_grab_nic_access(trans); + val = __iwl_read_prph(trans, reg); + __iwl_write_prph(trans, reg, (val & ~mask)); + iwl_release_nic_access(trans); + spin_unlock_irqrestore(&trans->reg_lock, flags); } -void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr, +void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, void *buf, int words) { unsigned long flags; int offs; u32 *vals = buf; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); + spin_lock_irqsave(&trans->reg_lock, flags); + iwl_grab_nic_access(trans); - iwl_write32(bus, HBUS_TARG_MEM_RADDR, addr); + iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); rmb(); for (offs = 0; offs < words; offs++) - vals[offs] = iwl_read32(bus, HBUS_TARG_MEM_RDAT); + vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + iwl_release_nic_access(trans); + spin_unlock_irqrestore(&trans->reg_lock, flags); } -u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr) +u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr) { u32 value; - _iwl_read_targ_mem_words(bus, addr, &value, 1); + _iwl_read_targ_mem_words(trans, addr, &value, 1); return value; } -int _iwl_write_targ_mem_words(struct iwl_bus *bus, u32 addr, +int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, void *buf, int words) { unsigned long flags; int offs, result = 0; u32 *vals = buf; - spin_lock_irqsave(&bus->reg_lock, flags); - if (!iwl_grab_nic_access(bus)) { - iwl_write32(bus, HBUS_TARG_MEM_WADDR, addr); + spin_lock_irqsave(&trans->reg_lock, flags); + if (!iwl_grab_nic_access(trans)) { + iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); wmb(); for (offs = 0; offs < words; offs++) - iwl_write32(bus, HBUS_TARG_MEM_WDAT, vals[offs]); - iwl_release_nic_access(bus); + iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]); + iwl_release_nic_access(trans); } else result = -EBUSY; - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_unlock_irqrestore(&trans->reg_lock, flags); return result; } -int iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val) +int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val) { - return _iwl_write_targ_mem_words(bus, addr, &val, 1); + return _iwl_write_targ_mem_words(trans, addr, &val, 1); } diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index b8e00cd7b1f..782486fc2f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -31,68 +31,63 @@ #include "iwl-devtrace.h" #include "iwl-shared.h" -/* TODO: remove when not needed any more */ -#include "iwl-bus.h" #include "iwl-trans.h" -static inline void iwl_write8(struct iwl_bus *bus, u32 ofs, u8 val) +static inline void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) { - /* TODO: get trans instead of bus */ - trace_iwlwifi_dev_iowrite8(priv(bus), ofs, val); - iwl_trans_write8(trans(bus), ofs, val); + trace_iwlwifi_dev_iowrite8(priv(trans), ofs, val); + iwl_trans_write8(trans, ofs, val); } -static inline void iwl_write32(struct iwl_bus *bus, u32 ofs, u32 val) +static inline void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val) { - /* TODO: get trans instead of bus */ - trace_iwlwifi_dev_iowrite32(priv(bus), ofs, val); - iwl_trans_write32(trans(bus), ofs, val); + trace_iwlwifi_dev_iowrite32(priv(trans), ofs, val); + iwl_trans_write32(trans, ofs, val); } -static inline u32 iwl_read32(struct iwl_bus *bus, u32 ofs) +static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs) { - /* TODO: get trans instead of bus */ - u32 val = iwl_trans_read32(trans(bus), ofs); - trace_iwlwifi_dev_ioread32(priv(bus), ofs, val); + u32 val = iwl_trans_read32(trans, ofs); + trace_iwlwifi_dev_ioread32(priv(trans), ofs, val); return val; } -void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask); -void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask); +void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); +void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask); -int iwl_poll_bit(struct iwl_bus *bus, u32 addr, +int iwl_poll_bit(struct iwl_trans *trans, u32 addr, u32 bits, u32 mask, int timeout); -int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, +int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, int timeout); -int iwl_grab_nic_access_silent(struct iwl_bus *bus); -int iwl_grab_nic_access(struct iwl_bus *bus); -void iwl_release_nic_access(struct iwl_bus *bus); +int iwl_grab_nic_access_silent(struct iwl_trans *trans); +int iwl_grab_nic_access(struct iwl_trans *trans); +void iwl_release_nic_access(struct iwl_trans *trans); -u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg); -void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value); +u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg); +void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); -u32 iwl_read_prph(struct iwl_bus *bus, u32 reg); -void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val); -void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask); -void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg, +u32 iwl_read_prph(struct iwl_trans *trans, u32 reg); +void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val); +void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask); +void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg, u32 bits, u32 mask); -void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask); +void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask); -void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr, +void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, void *buf, int words); -#define iwl_read_targ_mem_words(bus, addr, buf, bufsize) \ +#define iwl_read_targ_mem_words(trans, addr, buf, bufsize) \ do { \ BUILD_BUG_ON((bufsize) % sizeof(u32)); \ - _iwl_read_targ_mem_words(bus, addr, buf, \ + _iwl_read_targ_mem_words(trans, addr, buf, \ (bufsize) / sizeof(u32));\ } while (0) -int _iwl_write_targ_mem_words(struct iwl_bus *bus, u32 addr, +int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, void *buf, int words); -u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr); -int iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val); +u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr); +int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val); #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 8761438f153..5c7741f07aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -71,7 +71,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = { /* Set led register off */ void iwlagn_led_enable(struct iwl_priv *priv) { - iwl_write32(bus(priv), CSR_LED_REG, CSR_LED_REG_TRUN_ON); + iwl_write32(trans(priv), CSR_LED_REG, CSR_LED_REG_TRUN_ON); } /* @@ -107,9 +107,10 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) }; u32 reg; - reg = iwl_read32(bus(priv), CSR_LED_REG); + reg = iwl_read32(trans(priv), CSR_LED_REG); if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) - iwl_write32(bus(priv), CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); + iwl_write32(trans(priv), CSR_LED_REG, + reg & CSR_LED_BSM_CTRL_MSK); return iwl_trans_send_cmd(trans(priv), &cmd); } @@ -206,7 +207,7 @@ void iwl_leds_init(struct iwl_priv *priv) break; } - ret = led_classdev_register(bus(priv)->dev, &priv->led); + ret = led_classdev_register(trans(priv)->dev, &priv->led); if (ret) { kfree(priv->led.name); return; diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 965d0475aff..b911837b04f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -196,7 +196,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, WIPHY_FLAG_IBSS_RSN; if (trans(priv)->ucode_wowlan.code.len && - device_can_wakeup(bus(priv)->dev)) { + device_can_wakeup(trans(priv)->dev)) { hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_EAP_IDENTITY_REQ | @@ -347,7 +347,7 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) /* User space software may expect getting rfkill changes * even if interface is down */ - iwl_write32(bus(priv), CSR_INT, 0xFFFFFFFF); + iwl_write32(trans(priv), CSR_INT, 0xFFFFFFFF); iwl_enable_rfkill_int(priv); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -405,10 +405,10 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, if (ret) goto error; - device_set_wakeup_enable(bus(priv)->dev, true); + device_set_wakeup_enable(trans(priv)->dev, true); /* Now let the ucode operate on its own */ - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, + iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); goto out; @@ -436,19 +436,19 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "enter\n"); mutex_lock(&priv->shrd->mutex); - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); base = priv->shrd->device_pointers.error_event_table; if (iwlagn_hw_valid_rtc_data_addr(base)) { - spin_lock_irqsave(&bus(priv)->reg_lock, flags); - ret = iwl_grab_nic_access_silent(bus(priv)); + spin_lock_irqsave(&trans(priv)->reg_lock, flags); + ret = iwl_grab_nic_access_silent(trans(priv)); if (ret == 0) { - iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, base); - status = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); - iwl_release_nic_access(bus(priv)); + iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, base); + status = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); + iwl_release_nic_access(trans(priv)); } - spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); + spin_unlock_irqrestore(&trans(priv)->reg_lock, flags); #ifdef CONFIG_IWLWIFI_DEBUGFS if (ret == 0) { @@ -460,7 +460,8 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) if (priv->wowlan_sram) _iwl_read_targ_mem_words( - bus(priv), 0x800000, priv->wowlan_sram, + trans(priv), 0x800000, + priv->wowlan_sram, trans->ucode_wowlan.data.len / 4); } #endif @@ -471,7 +472,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) priv->shrd->wowlan = false; - device_set_wakeup_enable(bus(priv)->dev, false); + device_set_wakeup_enable(trans(priv)->dev, false); iwlagn_prepare_restart(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index ab462337d7a..7bab8192848 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -121,12 +121,12 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) { /* L1-ASPM enabled; disable(!) L0S */ - iwl_set_bit(bus, CSR_GIO_REG, + iwl_set_bit(trans(bus), CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n"); } else { /* L1-ASPM disabled; enable(!) L0S */ - iwl_clear_bit(bus, CSR_GIO_REG, + iwl_clear_bit(trans(bus), CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n"); } diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index a56a77b8f92..922d841faba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -208,7 +208,7 @@ static void iwl_trace_cleanup(struct iwl_priv *priv) if (priv->testmode_trace.trace_enabled) { if (priv->testmode_trace.cpu_addr && priv->testmode_trace.dma_addr) - dma_free_coherent(bus(priv)->dev, + dma_free_coherent(trans(priv)->dev, priv->testmode_trace.total_size, priv->testmode_trace.cpu_addr, priv->testmode_trace.dma_addr); @@ -302,7 +302,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: - val32 = iwl_read_direct32(bus(priv), ofs); + val32 = iwl_read_direct32(trans(priv), ofs); IWL_INFO(priv, "32bit value to read 0x%x\n", val32); skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); @@ -324,7 +324,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } else { val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); IWL_INFO(priv, "32bit value to write 0x%x\n", val32); - iwl_write_direct32(bus(priv), ofs, val32); + iwl_write_direct32(trans(priv), ofs, val32); } break; case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: @@ -334,11 +334,11 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } else { val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); IWL_INFO(priv, "8bit value to write 0x%x\n", val8); - iwl_write8(bus(priv), ofs, val8); + iwl_write8(trans(priv), ofs, val8); } break; case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: - val32 = iwl_read_prph(bus(priv), ofs); + val32 = iwl_read_prph(trans(priv), ofs); IWL_INFO(priv, "32bit value to read 0x%x\n", val32); skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); @@ -360,7 +360,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } else { val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); IWL_INFO(priv, "32bit value to write 0x%x\n", val32); - iwl_write_prph(bus(priv), ofs, val32); + iwl_write_prph(trans(priv), ofs, val32); } break; default: @@ -615,7 +615,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) struct iwl_priv *priv = hw->priv; struct sk_buff *skb; int status = 0; - struct device *dev = bus(priv)->dev; + struct device *dev = trans(priv)->dev; switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: @@ -814,7 +814,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) IWL_ERR(priv, "Error allocating memory\n"); return -ENOMEM; } - _iwl_read_targ_mem_words(bus(priv), ofs, + _iwl_read_targ_mem_words(trans(priv), ofs, priv->testmode_sram.buff_addr, priv->testmode_sram.buff_size / 4); priv->testmode_sram.num_chunks = diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 47d27bdf2df..555175ff4f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -317,12 +317,12 @@ static inline void iwl_disable_interrupts(struct iwl_trans *trans) clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); /* disable interrupts from uCode/NIC to host */ - iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); + iwl_write32(trans, CSR_INT_MASK, 0x00000000); /* acknowledge/clear/reset any interrupts still pending * from uCode or flow handler (Rx/Tx DMA) */ - iwl_write32(bus(trans), CSR_INT, 0xffffffff); - iwl_write32(bus(trans), CSR_FH_INT_STATUS, 0xffffffff); + iwl_write32(trans, CSR_INT, 0xffffffff); + iwl_write32(trans, CSR_FH_INT_STATUS, 0xffffffff); IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); } @@ -333,7 +333,7 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans) IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); set_bit(STATUS_INT_ENABLED, &trans->shrd->status); - iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask); + iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); } /* diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index b94c95370b7..ebea2435dac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -144,30 +144,30 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, /* shadow register enabled */ /* Device expects a multiple of 8 */ q->write_actual = (q->write & ~0x7); - iwl_write32(bus(trans), FH_RSCSR_CHNL0_WPTR, q->write_actual); + iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, q->write_actual); } else { /* If power-saving is in use, make sure device is awake */ if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { - reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1); + reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup," " GP1 = 0x%x\n", reg); - iwl_set_bit(bus(trans), CSR_GP_CNTRL, + iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); goto exit_unlock; } q->write_actual = (q->write & ~0x7); - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR, + iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR, q->write_actual); /* Else device is assumed to be awake */ } else { /* Device expects a multiple of 8 */ q->write_actual = (q->write & ~0x7); - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR, + iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR, q->write_actual); } } @@ -312,7 +312,7 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) BUG_ON(rxb->page); rxb->page = page; /* Get physical address of the RB */ - rxb->page_dma = dma_map_page(bus(trans)->dev, page, 0, + rxb->page_dma = dma_map_page(trans->dev, page, 0, PAGE_SIZE << hw_params(trans).rx_page_order, DMA_FROM_DEVICE); /* dma address must be no more than 36 bits */ @@ -418,7 +418,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) rxq->queue[i] = NULL; - dma_unmap_page(bus(trans)->dev, rxb->page_dma, + dma_unmap_page(trans->dev, rxb->page_dma, PAGE_SIZE << hw_params(trans).rx_page_order, DMA_FROM_DEVICE); pkt = rxb_addr(rxb); @@ -489,7 +489,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) * rx_free list for reuse later. */ spin_lock_irqsave(&rxq->lock, flags); if (rxb->page != NULL) { - rxb->page_dma = dma_map_page(bus(trans)->dev, rxb->page, + rxb->page_dma = dma_map_page(trans->dev, rxb->page, 0, PAGE_SIZE << hw_params(trans).rx_page_order, DMA_FROM_DEVICE); @@ -616,7 +616,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) return; } - iwl_read_targ_mem_words(bus(priv), base, &table, sizeof(table)); + iwl_read_targ_mem_words(trans(priv), base, &table, sizeof(table)); if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { IWL_ERR(trans, "Start IWL Error Log Dump:\n"); @@ -677,9 +677,9 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) struct iwl_priv *priv = priv(trans); /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ if (cfg(priv)->internal_wimax_coex && - (!(iwl_read_prph(bus(trans), APMG_CLK_CTRL_REG) & + (!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) & APMS_CLK_VAL_MRB_FUNC_MODE) || - (iwl_read_prph(bus(trans), APMG_PS_CTRL_REG) & + (iwl_read_prph(trans, APMG_PS_CTRL_REG) & APMG_PS_CTRL_VAL_RESET_REQ))) { /* * Keep the restart process from trying to send host @@ -745,18 +745,18 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, ptr = base + EVENT_START_OFFSET + (start_idx * event_size); /* Make sure device is powered up for SRAM reads */ - spin_lock_irqsave(&bus(trans)->reg_lock, reg_flags); - iwl_grab_nic_access(bus(trans)); + spin_lock_irqsave(&trans->reg_lock, reg_flags); + iwl_grab_nic_access(trans); /* Set starting address; reads will auto-increment */ - iwl_write32(bus(trans), HBUS_TARG_MEM_RADDR, ptr); + iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr); rmb(); /* "time" is actually "data" for mode 0 (no timestamp). * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT); - time = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT); + ev = iwl_read32(trans, HBUS_TARG_MEM_RDAT); + time = iwl_read32(trans, HBUS_TARG_MEM_RDAT); if (mode == 0) { /* data, ev */ if (bufsz) { @@ -770,7 +770,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, time, ev); } } else { - data = iwl_read32(bus(trans), HBUS_TARG_MEM_RDAT); + data = iwl_read32(trans, HBUS_TARG_MEM_RDAT); if (bufsz) { pos += scnprintf(*buf + pos, bufsz - pos, "EVT_LOGT:%010u:0x%08x:%04u\n", @@ -785,8 +785,8 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, } /* Allow device to power down */ - iwl_release_nic_access(bus(trans)); - spin_unlock_irqrestore(&bus(trans)->reg_lock, reg_flags); + iwl_release_nic_access(trans); + spin_unlock_irqrestore(&trans->reg_lock, reg_flags); return pos; } @@ -863,10 +863,10 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, } /* event log header */ - capacity = iwl_read_targ_mem(bus(trans), base); - mode = iwl_read_targ_mem(bus(trans), base + (1 * sizeof(u32))); - num_wraps = iwl_read_targ_mem(bus(trans), base + (2 * sizeof(u32))); - next_entry = iwl_read_targ_mem(bus(trans), base + (3 * sizeof(u32))); + capacity = iwl_read_targ_mem(trans, base); + mode = iwl_read_targ_mem(trans, base + (1 * sizeof(u32))); + num_wraps = iwl_read_targ_mem(trans, base + (2 * sizeof(u32))); + next_entry = iwl_read_targ_mem(trans, base + (3 * sizeof(u32))); if (capacity > logsize) { IWL_ERR(trans, "Log capacity %d is bogus, limit to %d " @@ -962,7 +962,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * hardware bugs here by ACKing all the possible interrupts so that * interrupt coalescing can still be achieved. */ - iwl_write32(bus(trans), CSR_INT, + iwl_write32(trans, CSR_INT, trans_pcie->inta | ~trans_pcie->inta_mask); inta = trans_pcie->inta; @@ -970,7 +970,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) { /* just for debug */ - inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); + inta_mask = iwl_read32(trans, CSR_INT_MASK); IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ", inta, inta_mask); } @@ -1018,7 +1018,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { int hw_rf_kill = 0; - if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & + if (!(iwl_read32(trans, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rf_kill = 1; @@ -1082,12 +1082,12 @@ void iwl_irq_tasklet(struct iwl_trans *trans) IWL_DEBUG_ISR(trans, "Rx interrupt\n"); if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - iwl_write32(bus(trans), CSR_FH_INT_STATUS, + iwl_write32(trans, CSR_FH_INT_STATUS, CSR_FH_INT_RX_MASK); } if (inta & CSR_INT_BIT_RX_PERIODIC) { handled |= CSR_INT_BIT_RX_PERIODIC; - iwl_write32(bus(trans), + iwl_write32(trans, CSR_INT, CSR_INT_BIT_RX_PERIODIC); } /* Sending RX interrupt require many steps to be done in the @@ -1102,7 +1102,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) */ /* Disable periodic interrupt; we use it as just a one-shot. */ - iwl_write8(bus(trans), CSR_INT_PERIODIC_REG, + iwl_write8(trans, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_DIS); #ifdef CONFIG_IWLWIFI_IDI iwl_amfh_rx_handler(); @@ -1117,7 +1117,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * to extend the periodic interrupt; one-shot is enough. */ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) - iwl_write8(bus(trans), CSR_INT_PERIODIC_REG, + iwl_write8(trans, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_ENA); isr_stats->rx++; @@ -1125,7 +1125,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) { - iwl_write32(bus(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); + iwl_write32(trans, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); isr_stats->tx++; handled |= CSR_INT_BIT_FH_TX; @@ -1175,7 +1175,7 @@ void iwl_free_isr_ict(struct iwl_trans *trans) IWL_TRANS_GET_PCIE_TRANS(trans); if (trans_pcie->ict_tbl) { - dma_free_coherent(bus(trans)->dev, ICT_SIZE, + dma_free_coherent(trans->dev, ICT_SIZE, trans_pcie->ict_tbl, trans_pcie->ict_tbl_dma); trans_pcie->ict_tbl = NULL; @@ -1195,7 +1195,7 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans) IWL_TRANS_GET_PCIE_TRANS(trans); trans_pcie->ict_tbl = - dma_alloc_coherent(bus(trans)->dev, ICT_SIZE, + dma_alloc_coherent(trans->dev, ICT_SIZE, &trans_pcie->ict_tbl_dma, GFP_KERNEL); if (!trans_pcie->ict_tbl) @@ -1246,10 +1246,10 @@ void iwl_reset_ict(struct iwl_trans *trans) IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%x\n", val); - iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val); + iwl_write32(trans, CSR_DRAM_INT_TBL_REG, val); trans_pcie->use_ict = true; trans_pcie->ict_index = 0; - iwl_write32(bus(trans), CSR_INT, trans_pcie->inta_mask); + iwl_write32(trans, CSR_INT, trans_pcie->inta_mask); iwl_enable_interrupts(trans); spin_unlock_irqrestore(&trans->shrd->lock, flags); } @@ -1289,11 +1289,11 @@ static irqreturn_t iwl_isr(int irq, void *data) * back-to-back ISRs and sporadic interrupts from our NIC. * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); /* just for debug */ - iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ + iwl_write32(trans, CSR_INT_MASK, 0x00000000); /* Discover which interrupts are active/pending */ - inta = iwl_read32(bus(trans), CSR_INT); + inta = iwl_read32(trans, CSR_INT); /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, @@ -1312,7 +1312,7 @@ static irqreturn_t iwl_isr(int irq, void *data) #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { - inta_fh = iwl_read32(bus(trans), CSR_FH_INT_STATUS); + inta_fh = iwl_read32(trans, CSR_FH_INT_STATUS); IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, " "fh 0x%08x\n", inta, inta_mask, inta_fh); } @@ -1378,8 +1378,8 @@ irqreturn_t iwl_isr_ict(int irq, void *data) * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); /* just for debug */ - iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ + iwl_write32(trans, CSR_INT_MASK, 0x00000000); /* Ignore interrupt if there's nothing in NIC to service. diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 30814b55705..5e095ac5076 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -100,7 +100,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) if (hw_params(trans).shadow_reg_enable) { /* shadow register enabled */ - iwl_write32(bus(trans), HBUS_TARG_WRPTR, + iwl_write32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); } else { /* if we're trying to save power */ @@ -108,18 +108,18 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) /* wake up nic if it's powered down ... * uCode will wake up, and interrupt us again, so next * time we'll skip this part. */ - reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1); + reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup," " GP1 = 0x%x\n", txq_id, reg); - iwl_set_bit(bus(trans), CSR_GP_CNTRL, + iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); return; } - iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, + iwl_write_direct32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); /* @@ -128,7 +128,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) * trying to tx (during RFKILL, we're not trying to tx). */ } else - iwl_write32(bus(trans), HBUS_TARG_WRPTR, + iwl_write32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); } txq->need_update = 0; @@ -190,14 +190,14 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, /* Unmap tx_cmd */ if (num_tbs) - dma_unmap_single(bus(trans)->dev, + dma_unmap_single(trans->dev, dma_unmap_addr(meta, mapping), dma_unmap_len(meta, len), DMA_BIDIRECTIONAL); /* Unmap chunks, if any. */ for (i = 1; i < num_tbs; i++) - dma_unmap_single(bus(trans)->dev, iwl_tfd_tb_get_addr(tfd, i), + dma_unmap_single(trans->dev, iwl_tfd_tb_get_addr(tfd, i), iwl_tfd_tb_get_len(tfd, i), dma_dir); } @@ -383,14 +383,14 @@ static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid, tbl_dw_addr = trans_pcie->scd_base_addr + SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); - tbl_dw = iwl_read_targ_mem(bus(trans), tbl_dw_addr); + tbl_dw = iwl_read_targ_mem(trans, tbl_dw_addr); if (txq_id & 0x1) tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); else tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); - iwl_write_targ_mem(bus(trans), tbl_dw_addr, tbl_dw); + iwl_write_targ_mem(trans, tbl_dw_addr, tbl_dw); return 0; } @@ -399,7 +399,7 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id) { /* Simply stop the queue, but don't change any configuration; * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl_write_prph(bus(trans), + iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); @@ -409,9 +409,9 @@ void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index) { IWL_DEBUG_TX_QUEUES(trans, "Q %d WrPtr: %d", txq_id, index & 0xff); - iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, + iwl_write_direct32(trans, HBUS_TARG_WRPTR, (index & 0xff) | (txq_id << 8)); - iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index); + iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), index); } void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, @@ -423,7 +423,7 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, int active = test_bit(txq_id, &trans_pcie->txq_ctx_active_msk) ? 1 : 0; - iwl_write_prph(bus(trans), SCD_QUEUE_STATUS_BITS(txq_id), + iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | @@ -498,10 +498,10 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(bus(trans), SCD_QUEUECHAIN_SEL, (1<scd_base_addr + + iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), ((frame_limit << @@ -520,7 +520,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - iwl_set_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_set_bits_prph(trans, SCD_INTERRUPT_MASK, (1 << txq_id)); /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], @@ -584,7 +584,7 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid) iwlagn_tx_queue_stop_scheduler(trans, txq_id); - iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id)); + iwl_clear_bits_prph(trans, SCD_AGGR_SEL, (1 << txq_id)); trans_pcie->agg_txq[sta_id][tid] = 0; trans_pcie->txq[txq_id].q.read_ptr = 0; @@ -592,7 +592,7 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid) /* supposes that ssn_idx is valid (!= 0xFFF) */ iwl_trans_set_wr_ptrs(trans, txq_id, 0); - iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_clear_bits_prph(trans, SCD_INTERRUPT_MASK, (1 << txq_id)); iwl_txq_ctx_deactivate(trans_pcie, txq_id); iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0); return 0; @@ -725,9 +725,9 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) le16_to_cpu(out_cmd->hdr.sequence), cmd_size, q->write_ptr, idx, trans->shrd->cmd_queue); - phys_addr = dma_map_single(bus(trans)->dev, &out_cmd->hdr, copy_size, + phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { + if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { idx = -ENOMEM; goto out; } @@ -748,10 +748,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) continue; if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) continue; - phys_addr = dma_map_single(bus(trans)->dev, + phys_addr = dma_map_single(trans->dev, (void *)cmd->data[i], cmd->len[i], DMA_BIDIRECTIONAL); - if (dma_mapping_error(bus(trans)->dev, phys_addr)) { + if (dma_mapping_error(trans->dev, phys_addr)) { iwlagn_unmap_tfd(trans, out_meta, &txq->tfds[q->write_ptr], DMA_BIDIRECTIONAL); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 80f531844f3..a1ee2e4b0ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -80,7 +80,7 @@ static int iwl_trans_rx_alloc(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_queue *rxq = &trans_pcie->rxq; - struct device *dev = bus(trans)->dev; + struct device *dev = trans->dev; memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); @@ -124,7 +124,7 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) /* In the reset function, these buffers may have been allocated * to an SKB, so we need to unmap and free potential storage */ if (rxq->pool[i].page != NULL) { - dma_unmap_page(bus(trans)->dev, rxq->pool[i].page_dma, + dma_unmap_page(trans->dev, rxq->pool[i].page_dma, PAGE_SIZE << hw_params(trans).rx_page_order, DMA_FROM_DEVICE); __free_pages(rxq->pool[i].page, @@ -148,17 +148,17 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; /* Stop Rx DMA */ - iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); /* Reset driver's Rx queue write index */ - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); + iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); /* Tell device where to find RBD circular buffer in DRAM */ - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_BASE_REG, + iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_BASE_REG, (u32)(rxq->bd_dma >> 8)); /* Tell device where in DRAM to update its Rx status */ - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_STTS_WPTR_REG, + iwl_write_direct32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG, rxq->rb_stts_dma >> 4); /* Enable Rx DMA @@ -169,7 +169,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, * RB timeout 0x10 * 256 RBDs */ - iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, + iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | @@ -179,7 +179,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); /* Set interrupt coalescing timer to default (2048 usecs) */ - iwl_write8(bus(trans), CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); + iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); } static int iwl_rx_init(struct iwl_trans *trans) @@ -244,13 +244,13 @@ static void iwl_trans_pcie_rx_free(struct iwl_trans *trans) iwl_trans_rxq_free_rx_bufs(trans); spin_unlock_irqrestore(&rxq->lock, flags); - dma_free_coherent(bus(trans)->dev, sizeof(__le32) * RX_QUEUE_SIZE, + dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE, rxq->bd, rxq->bd_dma); memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); rxq->bd = NULL; if (rxq->rb_stts) - dma_free_coherent(bus(trans)->dev, + dma_free_coherent(trans->dev, sizeof(struct iwl_rb_status), rxq->rb_stts, rxq->rb_stts_dma); else @@ -263,8 +263,8 @@ static int iwl_trans_rx_stop(struct iwl_trans *trans) { /* stop Rx DMA */ - iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - return iwl_poll_direct_bit(bus(trans), FH_MEM_RSSR_RX_STATUS_REG, + iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG, FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); } @@ -274,7 +274,7 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, if (WARN_ON(ptr->addr)) return -EINVAL; - ptr->addr = dma_alloc_coherent(bus(trans)->dev, size, + ptr->addr = dma_alloc_coherent(trans->dev, size, &ptr->dma, GFP_KERNEL); if (!ptr->addr) return -ENOMEM; @@ -288,7 +288,7 @@ static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans, if (unlikely(!ptr->addr)) return; - dma_free_coherent(bus(trans)->dev, ptr->size, ptr->addr, ptr->dma); + dma_free_coherent(trans->dev, ptr->size, ptr->addr, ptr->dma); memset(ptr, 0, sizeof(*ptr)); } @@ -335,7 +335,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ - txq->tfds = dma_alloc_coherent(bus(trans)->dev, tfd_sz, + txq->tfds = dma_alloc_coherent(trans->dev, tfd_sz, &txq->q.dma_addr, GFP_KERNEL); if (!txq->tfds) { IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); @@ -391,7 +391,7 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, * Tell nic where to find circular buffer of Tx Frame Descriptors for * given Tx queue, and enable the DMA channel used for that queue. * Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(bus(trans), FH_MEM_CBBC_QUEUE(txq_id), + iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(txq_id), txq->q.dma_addr >> 8); return 0; @@ -445,7 +445,7 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; - struct device *dev = bus(trans)->dev; + struct device *dev = trans->dev; int i; if (WARN_ON(!txq)) return; @@ -586,10 +586,10 @@ static int iwl_tx_init(struct iwl_trans *trans) spin_lock_irqsave(&trans->shrd->lock, flags); /* Turn off all Tx DMA fifos */ - iwl_write_prph(bus(trans), SCD_TXFACT, 0); + iwl_write_prph(trans, SCD_TXFACT, 0); /* Tell NIC where to find the "keep warm" buffer */ - iwl_write_direct32(bus(trans), FH_KW_MEM_ADDR_REG, + iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, trans_pcie->kw.dma >> 4); spin_unlock_irqrestore(&trans->shrd->lock, flags); @@ -621,12 +621,12 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans) * to set power to V_AUX, do: if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) - iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VAUX, ~APMG_PS_CTRL_MSK_PWR_SRC); */ - iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, ~APMG_PS_CTRL_MSK_PWR_SRC); } @@ -640,7 +640,7 @@ static int iwl_nic_init(struct iwl_trans *trans) iwl_apm_init(priv(trans)); /* Set interrupt coalescing calibration timer to default (512 usecs) */ - iwl_write8(bus(trans), CSR_INT_COALESCING, + iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); spin_unlock_irqrestore(&trans->shrd->lock, flags); @@ -660,7 +660,7 @@ static int iwl_nic_init(struct iwl_trans *trans) if (hw_params(trans).shadow_reg_enable) { /* enable shadow regs in HW */ - iwl_set_bit(bus(trans), CSR_MAC_SHADOW_REG_CTRL, + iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); } @@ -676,11 +676,11 @@ static int iwl_set_hw_ready(struct iwl_trans *trans) { int ret; - iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); /* See if we got it */ - ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, HW_READY_TIMEOUT); @@ -701,10 +701,10 @@ static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) return 0; /* If HW is not ready, prepare the conditions to check again */ - iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PREPARE); - ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); @@ -794,7 +794,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) } /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(bus(trans), CSR_GP_CNTRL) & + if (iwl_read32(trans, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); else @@ -806,7 +806,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) return -ERFKILL; } - iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); + iwl_write32(trans, CSR_INT, 0xFFFFFFFF); ret = iwl_nic_init(trans); if (ret) { @@ -815,17 +815,17 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) } /* make sure rfkill handshake bits are cleared */ - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); /* clear (again), then enable host interrupts */ - iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); + iwl_write32(trans, CSR_INT, 0xFFFFFFFF); iwl_enable_interrupts(trans); /* really make sure rfkill handshake bits are cleared */ - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); return 0; } @@ -836,7 +836,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) */ static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) { - iwl_write_prph(bus(trans), SCD_TXFACT, mask); + iwl_write_prph(trans, SCD_TXFACT, mask); } static void iwl_tx_start(struct iwl_trans *trans) @@ -852,46 +852,46 @@ static void iwl_tx_start(struct iwl_trans *trans) spin_lock_irqsave(&trans->shrd->lock, flags); trans_pcie->scd_base_addr = - iwl_read_prph(bus(trans), SCD_SRAM_BASE_ADDR); + iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; /* reset conext data memory */ for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; a += 4) - iwl_write_targ_mem(bus(trans), a, 0); + iwl_write_targ_mem(trans, a, 0); /* reset tx status memory */ for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; a += 4) - iwl_write_targ_mem(bus(trans), a, 0); + iwl_write_targ_mem(trans, a, 0); for (; a < trans_pcie->scd_base_addr + SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num); a += 4) - iwl_write_targ_mem(bus(trans), a, 0); + iwl_write_targ_mem(trans, a, 0); - iwl_write_prph(bus(trans), SCD_DRAM_BASE_ADDR, + iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, trans_pcie->scd_bc_tbls.dma >> 10); /* Enable DMA channel */ for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) - iwl_write_direct32(bus(trans), FH_TCSR_CHNL_TX_CONFIG_REG(chan), + iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); /* Update FH chicken bits */ - reg_val = iwl_read_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG); - iwl_write_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG, + reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); + iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); - iwl_write_prph(bus(trans), SCD_QUEUECHAIN_SEL, + iwl_write_prph(trans, SCD_QUEUECHAIN_SEL, SCD_QUEUECHAIN_SEL_ALL(trans)); - iwl_write_prph(bus(trans), SCD_AGGR_SEL, 0); + iwl_write_prph(trans, SCD_AGGR_SEL, 0); /* initiate the queues */ for (i = 0; i < hw_params(trans).max_txq_num; i++) { - iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(i), 0); - iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, 0 | (i << 8)); - iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + + iwl_write_prph(trans, SCD_QUEUE_RDPTR(i), 0); + iwl_write_direct32(trans, HBUS_TARG_WRPTR, 0 | (i << 8)); + iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i), 0); - iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + + iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i) + sizeof(u32), ((SCD_WIN_SIZE << @@ -902,7 +902,7 @@ static void iwl_tx_start(struct iwl_trans *trans) SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); } - iwl_write_prph(bus(trans), SCD_INTERRUPT_MASK, + iwl_write_prph(trans, SCD_INTERRUPT_MASK, IWL_MASK(0, hw_params(trans).max_txq_num)); /* Activate all Tx DMA/FIFO channels */ @@ -948,7 +948,7 @@ static void iwl_tx_start(struct iwl_trans *trans) spin_unlock_irqrestore(&trans->shrd->lock, flags); /* Enable L1-Active */ - iwl_clear_bits_prph(bus(trans), APMG_PCIDEV_STT_REG, + iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); } @@ -974,14 +974,14 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) /* Stop each Tx DMA channel, and wait for it to be idle */ for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { - iwl_write_direct32(bus(trans), + iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); - if (iwl_poll_direct_bit(bus(trans), FH_TSSR_TX_STATUS_REG, + if (iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG, FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000)) IWL_ERR(trans, "Failing on timeout while stopping" " DMA channel %d [0x%08x]", ch, - iwl_read_direct32(bus(trans), + iwl_read_direct32(trans, FH_TSSR_TX_STATUS_REG)); } spin_unlock_irqrestore(&trans->shrd->lock, flags); @@ -1024,13 +1024,13 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) iwl_trans_rx_stop(trans); #endif /* Power-down device's busmaster DMA clocks */ - iwl_write_prph(bus(trans), APMG_CLK_DIS_REG, + iwl_write_prph(trans, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(5); } /* Make sure (redundant) we've released our request to stay awake */ - iwl_clear_bit(bus(trans), CSR_GP_CNTRL, + iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ @@ -1048,7 +1048,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) tasklet_kill(&trans_pcie->irq_tasklet); /* stop and reset the on-board processor */ - iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); } static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, @@ -1145,10 +1145,10 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ - txcmd_phys = dma_map_single(bus(trans)->dev, + txcmd_phys = dma_map_single(trans->dev, &dev_cmd->hdr, firstlen, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(bus(trans)->dev, txcmd_phys))) + if (unlikely(dma_mapping_error(trans->dev, txcmd_phys))) return -1; dma_unmap_addr_set(out_meta, mapping, txcmd_phys); dma_unmap_len_set(out_meta, len, firstlen); @@ -1164,10 +1164,10 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, * if any (802.11 null frames have no payload). */ secondlen = skb->len - hdr_len; if (secondlen > 0) { - phys_addr = dma_map_single(bus(trans)->dev, skb->data + hdr_len, + phys_addr = dma_map_single(trans->dev, skb->data + hdr_len, secondlen, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { - dma_unmap_single(bus(trans)->dev, + if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { + dma_unmap_single(trans->dev, dma_unmap_addr(out_meta, mapping), dma_unmap_len(out_meta, len), DMA_BIDIRECTIONAL); @@ -1185,7 +1185,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, offsetof(struct iwl_tx_cmd, scratch); /* take back ownership of DMA buffer to enable update */ - dma_sync_single_for_cpu(bus(trans)->dev, txcmd_phys, firstlen, + dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); @@ -1199,7 +1199,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, /* Set up entry for this TFD in Tx byte-count array */ iwl_trans_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); - dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen, + dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); trace_iwlwifi_dev_tx(priv(trans), @@ -1232,7 +1232,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans) { /* Remove all resets to allow NIC to operate */ - iwl_write32(bus(trans), CSR_RESET, 0); + iwl_write32(trans, CSR_RESET, 0); } static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) @@ -1355,7 +1355,7 @@ static int iwl_trans_pcie_suspend(struct iwl_trans *trans) iwl_apm_stop(priv(trans)); } else { iwl_disable_interrupts(trans); - iwl_clear_bit(bus(trans), CSR_GP_CNTRL, + iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } @@ -1368,7 +1368,7 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) iwl_enable_interrupts(trans); - if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & + if (!(iwl_read32(trans, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rfkill = true; @@ -1464,9 +1464,9 @@ static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt) IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", q->read_ptr, q->write_ptr); IWL_ERR(trans, "Current HW read_ptr %d write_ptr %d\n", - iwl_read_prph(bus(trans), SCD_QUEUE_RDPTR(cnt)) + iwl_read_prph(trans, SCD_QUEUE_RDPTR(cnt)) & (TFD_QUEUE_SIZE_MAX - 1), - iwl_read_prph(bus(trans), SCD_QUEUE_WRPTR(cnt))); + iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt))); return 1; } @@ -1520,7 +1520,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) pos += scnprintf(*buf + pos, bufsz - pos, " %34s: 0X%08x\n", get_fh_string(fh_tbl[i]), - iwl_read_direct32(bus(trans), fh_tbl[i])); + iwl_read_direct32(trans, fh_tbl[i])); } return pos; } @@ -1529,7 +1529,7 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { IWL_ERR(trans, " %34s: 0X%08x\n", get_fh_string(fh_tbl[i]), - iwl_read_direct32(bus(trans), fh_tbl[i])); + iwl_read_direct32(trans, fh_tbl[i])); } return 0; } @@ -1599,7 +1599,7 @@ void iwl_dump_csr(struct iwl_trans *trans) for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { IWL_ERR(trans, " %25s: 0X%08x\n", get_csr_string(csr_tbl[i]), - iwl_read32(bus(trans), csr_tbl[i])); + iwl_read32(trans, csr_tbl[i])); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0a3727dac6a..dec935a84a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -234,6 +234,7 @@ struct iwl_calib_result { * @ops - pointer to iwl_trans_ops * @shrd - pointer to iwl_shared which holds shared data from the upper layer * @hcmd_lock: protects HCMD + * @reg_lock - protect hw register access * @dev - pointer to struct device * that represents the device * @irq - the irq number for the device * @ucode_write_complete: indicates that the ucode has been copied. @@ -247,6 +248,7 @@ struct iwl_trans { const struct iwl_trans_ops *ops; struct iwl_shared *shrd; spinlock_t hcmd_lock; + spinlock_t reg_lock; struct device *dev; unsigned int irq; diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 0d7f207ac61..5de8b5beb09 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -126,42 +126,41 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, static int iwl_load_section(struct iwl_trans *trans, const char *name, struct fw_desc *image, u32 dst_addr) { - struct iwl_bus *bus = bus(trans); dma_addr_t phy_addr = image->p_addr; u32 byte_cnt = image->len; int ret; trans->ucode_write_complete = 0; - iwl_write_direct32(bus, + iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); - iwl_write_direct32(bus, + iwl_write_direct32(trans, FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); - iwl_write_direct32(bus, + iwl_write_direct32(trans, FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); - iwl_write_direct32(bus, + iwl_write_direct32(trans, FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), (iwl_get_dma_hi_addr(phy_addr) << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); - iwl_write_direct32(bus, + iwl_write_direct32(trans, FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); - iwl_write_direct32(bus, + iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); - IWL_DEBUG_FW(bus, "%s uCode section being loaded...\n", name); + IWL_DEBUG_FW(trans, "%s uCode section being loaded...\n", name); ret = wait_event_timeout(trans->shrd->wait_command_queue, trans->ucode_write_complete, 5 * HZ); if (!ret) { @@ -470,7 +469,7 @@ static int iwl_alive_notify(struct iwl_trans *trans) * using sample data 100 bytes apart. If these sample points are good, * it's a pretty good bet that everything between them is good, too. */ -static int iwl_verify_inst_sparse(struct iwl_bus *bus, +static int iwl_verify_inst_sparse(struct iwl_trans *trans, struct fw_desc *fw_desc) { __le32 *image = (__le32 *)fw_desc->v_addr; @@ -478,15 +477,15 @@ static int iwl_verify_inst_sparse(struct iwl_bus *bus, u32 val; u32 i; - IWL_DEBUG_FW(bus, "ucode inst image size is %u\n", len); + IWL_DEBUG_FW(trans, "ucode inst image size is %u\n", len); for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { /* read data comes through single port, auto-incr addr */ /* NOTE: Use the debugless read so we don't flood kernel log * if IWL_DL_IO is set */ - iwl_write_direct32(bus, HBUS_TARG_MEM_RADDR, + iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR, i + IWLAGN_RTC_INST_LOWER_BOUND); - val = iwl_read32(bus, HBUS_TARG_MEM_RDAT); + val = iwl_read32(trans, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) return -EIO; } @@ -494,7 +493,7 @@ static int iwl_verify_inst_sparse(struct iwl_bus *bus, return 0; } -static void iwl_print_mismatch_inst(struct iwl_bus *bus, +static void iwl_print_mismatch_inst(struct iwl_trans *trans, struct fw_desc *fw_desc) { __le32 *image = (__le32 *)fw_desc->v_addr; @@ -503,18 +502,18 @@ static void iwl_print_mismatch_inst(struct iwl_bus *bus, u32 offs; int errors = 0; - IWL_DEBUG_FW(bus, "ucode inst image size is %u\n", len); + IWL_DEBUG_FW(trans, "ucode inst image size is %u\n", len); - iwl_write_direct32(bus, HBUS_TARG_MEM_RADDR, + iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR, IWLAGN_RTC_INST_LOWER_BOUND); for (offs = 0; offs < len && errors < 20; offs += sizeof(u32), image++) { /* read data comes through single port, auto-incr addr */ - val = iwl_read32(bus, HBUS_TARG_MEM_RDAT); + val = iwl_read32(trans, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { - IWL_ERR(bus, "uCode INST section at " + IWL_ERR(trans, "uCode INST section at " "offset 0x%x, is 0x%x, s/b 0x%x\n", offs, val, le32_to_cpu(*image)); errors++; @@ -536,14 +535,14 @@ static int iwl_verify_ucode(struct iwl_trans *trans, return -EINVAL; } - if (!iwl_verify_inst_sparse(bus(trans), &img->code)) { + if (!iwl_verify_inst_sparse(trans, &img->code)) { IWL_DEBUG_FW(trans, "uCode is good in inst SRAM\n"); return 0; } IWL_ERR(trans, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); - iwl_print_mismatch_inst(bus(trans), &img->code); + iwl_print_mismatch_inst(trans, &img->code); return -EIO; } -- cgit v1.2.3 From ea4caade104490de0fadb64660f9e228c050fb3d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 4 Jan 2012 14:23:20 +0200 Subject: iwlwifi: remove the pointer to dev from the bus layer Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-bus.h | 2 -- drivers/net/wireless/iwlwifi/iwl-debug.h | 16 ++++++++-------- drivers/net/wireless/iwlwifi/iwl-pci.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-ucode.c | 4 ++-- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f79791500a9..d890b6481b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1146,7 +1146,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) iwl_dealloc_ucode(trans(priv)); out_unbind: complete(&priv->firmware_loading_complete); - device_release_driver(bus(priv)->dev); + device_release_driver(trans(priv)->dev); release_firmware(ucode_raw); } @@ -1785,7 +1785,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, /* At this point both hw and priv are allocated. */ - SET_IEEE80211_DEV(hw, bus(priv)->dev); + SET_IEEE80211_DEV(hw, trans(priv)->dev); /* what debugging capabilities we have */ iwl_debug_config(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index ce1a9cc106e..2065c5b7416 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -137,14 +137,12 @@ struct iwl_bus_ops { * * This data is common to all bus layer implementations. * - * @dev - pointer to struct device * that represents the device * @ops - pointer to iwl_bus_ops * @shrd - pointer to iwl_shared which holds shared data from the upper layer * NB: for the time being this needs to be set by the upper layer since * it allocates the shared data */ struct iwl_bus { - struct device *dev; const struct iwl_bus_ops *ops; struct iwl_shared *shrd; diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 6f7612781e0..351b41d7f4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -35,10 +35,10 @@ struct iwl_priv; /*No matter what is m (priv, bus, trans), this will work */ -#define IWL_ERR(m, f, a...) dev_err(bus(m)->dev, f, ## a) -#define IWL_WARN(m, f, a...) dev_warn(bus(m)->dev, f, ## a) -#define IWL_INFO(m, f, a...) dev_info(bus(m)->dev, f, ## a) -#define IWL_CRIT(m, f, a...) dev_crit(bus(m)->dev, f, ## a) +#define IWL_ERR(m, f, a...) dev_err(trans(m)->dev, f, ## a) +#define IWL_WARN(m, f, a...) dev_warn(trans(m)->dev, f, ## a) +#define IWL_INFO(m, f, a...) dev_info(trans(m)->dev, f, ## a) +#define IWL_CRIT(m, f, a...) dev_crit(trans(m)->dev, f, ## a) #define iwl_print_hex_error(m, p, len) \ do { \ @@ -50,7 +50,7 @@ do { \ #define IWL_DEBUG(m, level, fmt, ...) \ do { \ if (iwl_get_debug_level((m)->shrd) & (level)) \ - dev_err(bus(m)->dev, "%c %s " fmt, \ + dev_err(trans(m)->dev, "%c %s " fmt, \ in_interrupt() ? 'I' : 'U', __func__, \ ##__VA_ARGS__); \ } while (0) @@ -59,7 +59,7 @@ do { \ do { \ if (iwl_get_debug_level((m)->shrd) & (level) && \ net_ratelimit()) \ - dev_err(bus(m)->dev, "%c %s " fmt, \ + dev_err(trans(m)->dev, "%c %s " fmt, \ in_interrupt() ? 'I' : 'U', __func__, \ ##__VA_ARGS__); \ } while (0) @@ -74,12 +74,12 @@ do { \ #define IWL_DEBUG_QUIET_RFKILL(p, fmt, ...) \ do { \ if (!iwl_is_rfkill(p->shrd)) \ - dev_err(bus(p)->dev, "%s%c %s " fmt, \ + dev_err(trans(p)->dev, "%s%c %s " fmt, \ "", \ in_interrupt() ? 'I' : 'U', __func__, \ ##__VA_ARGS__); \ else if (iwl_get_debug_level(p->shrd) & IWL_DL_RADIO) \ - dev_err(bus(p)->dev, "%s%c %s " fmt, \ + dev_err(trans(p)->dev, "%s%c %s " fmt, \ "(RFKILL) ", \ in_interrupt() ? 'I' : 'U', __func__, \ ##__VA_ARGS__); \ diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 7bab8192848..6451739aed2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -123,12 +123,14 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) /* L1-ASPM enabled; disable(!) L0S */ iwl_set_bit(trans(bus), CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); - dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n"); + dev_printk(KERN_INFO, trans(bus)->dev, + "L1 Enabled; Disabling L0S\n"); } else { /* L1-ASPM disabled; enable(!) L0S */ iwl_clear_bit(trans(bus), CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); - dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n"); + dev_printk(KERN_INFO, trans(bus)->dev, + "L1 Disabled; Enabling L0S\n"); } } @@ -368,7 +370,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, bus); - bus->dev = &pdev->dev; bus->ops = &bus_ops_pci; #ifdef CONFIG_IWLWIFI_IDI diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 5de8b5beb09..08483d785e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -83,7 +83,7 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { static void iwl_free_fw_desc(struct iwl_bus *bus, struct fw_desc *desc) { if (desc->v_addr) - dma_free_coherent(bus->dev, desc->len, + dma_free_coherent(trans(bus)->dev, desc->len, desc->v_addr, desc->p_addr); desc->v_addr = NULL; desc->len = 0; @@ -110,7 +110,7 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, return -EINVAL; } - desc->v_addr = dma_alloc_coherent(bus->dev, len, + desc->v_addr = dma_alloc_coherent(trans(bus)->dev, len, &desc->p_addr, GFP_KERNEL); if (!desc->v_addr) return -ENOMEM; -- cgit v1.2.3 From 8467ab4f42396a3714b59ca187f470542970ff9d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 3 Jan 2012 16:28:12 +0200 Subject: iwlwifi: don't use the bus for ucode fw_desc any more This is transport related Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 14 ++++++++------ drivers/net/wireless/iwlwifi/iwl-trans.h | 2 +- drivers/net/wireless/iwlwifi/iwl-ucode.c | 20 ++++++++++---------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d890b6481b8..8b1839aec40 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1023,31 +1023,33 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* Runtime instructions and 2 copies of data: * 1) unmodified from disk * 2) backup cache for save/restore during power-downs */ - if (iwl_alloc_fw_desc(bus(priv), &trans(priv)->ucode_rt.code, + if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.code, pieces.inst, pieces.inst_size)) goto err_pci_alloc; - if (iwl_alloc_fw_desc(bus(priv), &trans(priv)->ucode_rt.data, + if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.data, pieces.data, pieces.data_size)) goto err_pci_alloc; /* Initialization instructions and data */ if (pieces.init_size && pieces.init_data_size) { - if (iwl_alloc_fw_desc(bus(priv), &trans(priv)->ucode_init.code, + if (iwl_alloc_fw_desc(trans(priv), + &trans(priv)->ucode_init.code, pieces.init, pieces.init_size)) goto err_pci_alloc; - if (iwl_alloc_fw_desc(bus(priv), &trans(priv)->ucode_init.data, + if (iwl_alloc_fw_desc(trans(priv), + &trans(priv)->ucode_init.data, pieces.init_data, pieces.init_data_size)) goto err_pci_alloc; } /* WoWLAN instructions and data */ if (pieces.wowlan_inst_size && pieces.wowlan_data_size) { - if (iwl_alloc_fw_desc(bus(priv), + if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_wowlan.code, pieces.wowlan_inst, pieces.wowlan_inst_size)) goto err_pci_alloc; - if (iwl_alloc_fw_desc(bus(priv), + if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_wowlan.data, pieces.wowlan_data, pieces.wowlan_data_size)) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index dec935a84a7..d5195998417 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -408,7 +408,7 @@ static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs) /***************************************************** * Utils functions ******************************************************/ -int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, +int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc, const void *data, size_t len); void iwl_dealloc_ucode(struct iwl_trans *trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 08483d785e2..793524a3ed7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -80,29 +80,29 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { * ******************************************************************************/ -static void iwl_free_fw_desc(struct iwl_bus *bus, struct fw_desc *desc) +static void iwl_free_fw_desc(struct iwl_trans *trans, struct fw_desc *desc) { if (desc->v_addr) - dma_free_coherent(trans(bus)->dev, desc->len, + dma_free_coherent(trans->dev, desc->len, desc->v_addr, desc->p_addr); desc->v_addr = NULL; desc->len = 0; } -static void iwl_free_fw_img(struct iwl_bus *bus, struct fw_img *img) +static void iwl_free_fw_img(struct iwl_trans *trans, struct fw_img *img) { - iwl_free_fw_desc(bus, &img->code); - iwl_free_fw_desc(bus, &img->data); + iwl_free_fw_desc(trans, &img->code); + iwl_free_fw_desc(trans, &img->data); } void iwl_dealloc_ucode(struct iwl_trans *trans) { - iwl_free_fw_img(bus(trans), &trans->ucode_rt); - iwl_free_fw_img(bus(trans), &trans->ucode_init); - iwl_free_fw_img(bus(trans), &trans->ucode_wowlan); + iwl_free_fw_img(trans, &trans->ucode_rt); + iwl_free_fw_img(trans, &trans->ucode_init); + iwl_free_fw_img(trans, &trans->ucode_wowlan); } -int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, +int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc, const void *data, size_t len) { if (!len) { @@ -110,7 +110,7 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, return -EINVAL; } - desc->v_addr = dma_alloc_coherent(trans(bus)->dev, len, + desc->v_addr = dma_alloc_coherent(trans->dev, len, &desc->p_addr, GFP_KERNEL); if (!desc->v_addr) return -ENOMEM; -- cgit v1.2.3 From 57a1dc89097982874f50a0e6f68ab08f62e9e5aa Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 8 Jan 2012 13:22:16 +0200 Subject: iwlwifi: rename trans_ops->request_irq to trans_ops->start_hw This handler will become thicker, reflect its real role now. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 36 ++++++++++++++--------- drivers/net/wireless/iwlwifi/iwl-trans.h | 8 ++--- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8b1839aec40..1c00691c9f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1829,7 +1829,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, IWL_INFO(priv, "Detected %s, REV=0x%X\n", cfg(priv)->name, hw_rev); - err = iwl_trans_request_irq(trans(priv)); + err = iwl_trans_start_hw(trans(priv)); if (err) goto out_free_traffic_mem; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 555175ff4f9..561865f29d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -201,6 +201,7 @@ struct iwl_tx_queue { * @rxq: all the RX queue data * @rx_replenish: work that will be called when buffers need to be allocated * @trans: pointer to the generic transport area + * @irq_requested: true when the irq has been requested * @scd_base_addr: scheduler sram base address in SRAM * @scd_bc_tbls: pointer to the byte count table of the scheduler * @kw: keep warm address @@ -225,6 +226,7 @@ struct iwl_trans_pcie { int ict_index; u32 inta; bool use_ict; + bool irq_requested; struct tasklet_struct irq_tasklet; struct isr_statistics isr_stats; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index a1ee2e4b0ce..ffbafb9e447 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1235,7 +1235,7 @@ static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans) iwl_write32(trans, CSR_RESET, 0); } -static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) +static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1243,20 +1243,26 @@ static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) trans_pcie->inta_mask = CSR_INI_SET_MASK; - tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet, (unsigned long)trans); + if (!trans_pcie->irq_requested) { + tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) + iwl_irq_tasklet, (unsigned long)trans); - iwl_alloc_isr_ict(trans); + iwl_alloc_isr_ict(trans); - err = request_irq(trans->irq, iwl_isr_ict, IRQF_SHARED, - DRV_NAME, trans); - if (err) { - IWL_ERR(trans, "Error allocating IRQ %d\n", trans->irq); - iwl_free_isr_ict(trans); - return err; + err = request_irq(trans->irq, iwl_isr_ict, IRQF_SHARED, + DRV_NAME, trans); + if (err) { + IWL_ERR(trans, "Error allocating IRQ %d\n", + trans->irq); + iwl_free_isr_ict(trans); + tasklet_kill(&trans_pcie->irq_tasklet); + return err; + } + + INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish); + trans_pcie->irq_requested = true; } - INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish); return 0; } @@ -1325,8 +1331,10 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans) #ifndef CONFIG_IWLWIFI_IDI iwl_trans_pcie_rx_free(trans); #endif - free_irq(trans->irq, trans); - iwl_free_isr_ict(trans); + if (trans_pcie->irq_requested == true) { + free_irq(trans->irq, trans); + iwl_free_isr_ict(trans); + } pci_disable_msi(trans_pcie->pci_dev); pci_iounmap(trans_pcie->pci_dev, trans_pcie->hw_base); @@ -1920,7 +1928,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, #endif /*CONFIG_IWLWIFI_DEBUGFS */ const struct iwl_trans_ops trans_ops_pcie = { - .request_irq = iwl_trans_pcie_request_irq, + .start_hw = iwl_trans_pcie_start_hw, .fw_alive = iwl_trans_pcie_fw_alive, .start_device = iwl_trans_pcie_start_device, .prepare_card_hw = iwl_trans_pcie_prepare_card_hw, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index d5195998417..ddc3a0627dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -133,7 +133,7 @@ struct iwl_host_cmd { /** * struct iwl_trans_ops - transport specific operations - * @request_irq: requests IRQ - will be called before the FW load in probe flow + * @start_hw: starts the HW- from that point on, the HW can send interrupts * @start_device: allocates and inits all the resources for the transport * layer. * @prepare_card_hw: claim the ownership on the HW. Will be called during @@ -164,7 +164,7 @@ struct iwl_host_cmd { */ struct iwl_trans_ops { - int (*request_irq)(struct iwl_trans *iwl_trans); + int (*start_hw)(struct iwl_trans *iwl_trans); int (*start_device)(struct iwl_trans *trans); void (*fw_alive)(struct iwl_trans *trans); int (*prepare_card_hw)(struct iwl_trans *trans); @@ -269,9 +269,9 @@ struct iwl_trans { char trans_specific[0] __attribute__((__aligned__(sizeof(void *)))); }; -static inline int iwl_trans_request_irq(struct iwl_trans *trans) +static inline int iwl_trans_start_hw(struct iwl_trans *trans) { - return trans->ops->request_irq(trans); + return trans->ops->start_hw(trans); } static inline void iwl_trans_fw_alive(struct iwl_trans *trans) -- cgit v1.2.3 From ebb7678d00b2fa0d7db76b5303a5bf46a5aed8f3 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 8 Jan 2012 13:24:57 +0200 Subject: iwlwifi: move prepare_card_hw to start_hw Kill the trans_ops->prepare_card_hw which is now useless. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 22 +++++++++++++++------- drivers/net/wireless/iwlwifi/iwl-trans.h | 8 -------- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1c00691c9f0..5ab7f681991 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1833,12 +1833,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, if (err) goto out_free_traffic_mem; - if (iwl_trans_prepare_card_hw(trans(priv))) { - err = -EIO; - IWL_WARN(priv, "Failed, HW not ready\n"); - goto out_free_traffic_mem; - } - /***************** * 4. Read EEPROM *****************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index ffbafb9e447..d1ab57a7988 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -690,13 +690,14 @@ static int iwl_set_hw_ready(struct iwl_trans *trans) } /* Note: returns standard 0/-ERROR code */ -static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) +static int iwl_prepare_card_hw(struct iwl_trans *trans) { int ret; IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); ret = iwl_set_hw_ready(trans); + /* If the card is ready, exit 0 */ if (ret >= 0) return 0; @@ -788,7 +789,7 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) && - iwl_trans_pcie_prepare_card_hw(trans)) { + iwl_prepare_card_hw(trans)) { IWL_WARN(trans, "Exit HW not ready\n"); return -EIO; } @@ -1254,16 +1255,24 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) if (err) { IWL_ERR(trans, "Error allocating IRQ %d\n", trans->irq); - iwl_free_isr_ict(trans); - tasklet_kill(&trans_pcie->irq_tasklet); - return err; + goto error; } INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish); trans_pcie->irq_requested = true; } - return 0; + err = iwl_prepare_card_hw(trans); + if (err) { + IWL_ERR(trans, "Error while preparing HW: %d", err); + goto error; + } + return err; + +error: + iwl_free_isr_ict(trans); + tasklet_kill(&trans_pcie->irq_tasklet); + return err; } static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, @@ -1931,7 +1940,6 @@ const struct iwl_trans_ops trans_ops_pcie = { .start_hw = iwl_trans_pcie_start_hw, .fw_alive = iwl_trans_pcie_fw_alive, .start_device = iwl_trans_pcie_start_device, - .prepare_card_hw = iwl_trans_pcie_prepare_card_hw, .stop_device = iwl_trans_pcie_stop_device, .wake_any_queue = iwl_trans_pcie_wake_any_queue, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index ddc3a0627dd..55b5dc3b5dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -136,8 +136,6 @@ struct iwl_host_cmd { * @start_hw: starts the HW- from that point on, the HW can send interrupts * @start_device: allocates and inits all the resources for the transport * layer. - * @prepare_card_hw: claim the ownership on the HW. Will be called during - * probe. * @fw_alive: called when the fw sends alive notification * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* * @stop_device:stops the whole device (embedded CPU put to reset) @@ -167,7 +165,6 @@ struct iwl_trans_ops { int (*start_hw)(struct iwl_trans *iwl_trans); int (*start_device)(struct iwl_trans *trans); void (*fw_alive)(struct iwl_trans *trans); - int (*prepare_card_hw)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans); void (*wake_any_queue)(struct iwl_trans *trans, @@ -284,11 +281,6 @@ static inline int iwl_trans_start_device(struct iwl_trans *trans) return trans->ops->start_device(trans); } -static inline int iwl_trans_prepare_card_hw(struct iwl_trans *trans) -{ - return trans->ops->prepare_card_hw(trans); -} - static inline void iwl_trans_stop_device(struct iwl_trans *trans) { trans->ops->stop_device(trans); -- cgit v1.2.3 From a6c684ee489a99a54f978aa92a9bf1e82f8c633b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 8 Jan 2012 13:24:57 +0200 Subject: iwlwifi: move apm_init to start_hw This is transport related Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 - drivers/net/wireless/iwlwifi/iwl-core.c | 85 -------------------------- drivers/net/wireless/iwlwifi/iwl-shared.h | 1 - drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 88 ++++++++++++++++++++++++++- 4 files changed, 87 insertions(+), 89 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5ab7f681991..3aeaa890e64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1836,8 +1836,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, /***************** * 4. Read EEPROM *****************/ - /* switch the NIC on before accessing the EEPROM */ - iwl_apm_init(priv); /* Read the EEPROM */ err = iwl_eeprom_init(priv, hw_rev); /* Reset chip to save power until we load uCode during "up". */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c9022c5fa81..3ba59fa3108 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -923,91 +923,6 @@ void iwl_apm_stop(struct iwl_priv *priv) CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } - -/* - * Start up NIC's basic functionality after it has been reset - * (e.g. after platform boot, or shutdown via iwl_apm_stop()) - * NOTE: This does not load uCode nor start the embedded processor - */ -int iwl_apm_init(struct iwl_priv *priv) -{ - int ret = 0; - IWL_DEBUG_INFO(priv, "Init card's basic functions\n"); - - /* - * Use "set_bit" below rather than "write", to preserve any hardware - * bits already set by default after reset. - */ - - /* Disable L0S exit timer (platform NMI Work/Around) */ - iwl_set_bit(trans(priv), CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); - - /* - * Disable L0s without affecting L1; - * don't wait for ICH L0s (ICH bug W/A) - */ - iwl_set_bit(trans(priv), CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); - - /* Set FH wait threshold to maximum (HW error during stress W/A) */ - iwl_set_bit(trans(priv), CSR_DBG_HPET_MEM_REG, - CSR_DBG_HPET_MEM_REG_VAL); - - /* - * Enable HAP INTA (interrupt from management bus) to - * wake device's PCI Express link L1a -> L0s - */ - iwl_set_bit(trans(priv), CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); - - bus_apm_config(bus(priv)); - - /* Configure analog phase-lock-loop before activating to D0A */ - if (cfg(priv)->base_params->pll_cfg_val) - iwl_set_bit(trans(priv), CSR_ANA_PLL_CFG, - cfg(priv)->base_params->pll_cfg_val); - - /* - * Set "initialization complete" bit to move adapter from - * D0U* --> D0A* (powered-up active) state. - */ - iwl_set_bit(trans(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - - /* - * Wait for clock stabilization; once stabilized, access to - * device-internal resources is supported, e.g. iwl_write_prph() - * and accesses to uCode SRAM. - */ - ret = iwl_poll_bit(trans(priv), CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - if (ret < 0) { - IWL_DEBUG_INFO(priv, "Failed to init the card\n"); - goto out; - } - - /* - * Enable DMA clock and wait for it to stabilize. - * - * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits - * do not disable clocks. This preserves any hardware bits already - * set by default in "CLK_CTRL_REG" after reset. - */ - iwl_write_prph(trans(priv), APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); - udelay(20); - - /* Disable L1-Active */ - iwl_set_bits_prph(trans(priv), APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - - set_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); - -out: - return ret; -} - - int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) { int ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 04975b7b65b..338a55f403d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -544,7 +544,6 @@ void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state); void iwl_nic_config(struct iwl_priv *priv); void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb); void iwl_apm_stop(struct iwl_priv *priv); -int iwl_apm_init(struct iwl_priv *priv); void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); const char *get_cmd_string(u8 cmd); bool iwl_check_for_ct_kill(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index d1ab57a7988..335d4b1508c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -74,6 +74,7 @@ #include "iwl-shared.h" #include "iwl-eeprom.h" #include "iwl-agn-hw.h" +#include "iwl-core.h" static int iwl_trans_rx_alloc(struct iwl_trans *trans) { @@ -631,13 +632,95 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans) ~APMG_PS_CTRL_MSK_PWR_SRC); } +/* + * Start up NIC's basic functionality after it has been reset + * (e.g. after platform boot, or shutdown via iwl_apm_stop()) + * NOTE: This does not load uCode nor start the embedded processor + */ +static int iwl_apm_init(struct iwl_trans *trans) +{ + int ret = 0; + IWL_DEBUG_INFO(trans, "Init card's basic functions\n"); + + /* + * Use "set_bit" below rather than "write", to preserve any hardware + * bits already set by default after reset. + */ + + /* Disable L0S exit timer (platform NMI Work/Around) */ + iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, + CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); + + /* + * Disable L0s without affecting L1; + * don't wait for ICH L0s (ICH bug W/A) + */ + iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, + CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); + + /* Set FH wait threshold to maximum (HW error during stress W/A) */ + iwl_set_bit(trans, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); + + /* + * Enable HAP INTA (interrupt from management bus) to + * wake device's PCI Express link L1a -> L0s + */ + iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); + + bus_apm_config(bus(trans)); + + /* Configure analog phase-lock-loop before activating to D0A */ + if (cfg(trans)->base_params->pll_cfg_val) + iwl_set_bit(trans, CSR_ANA_PLL_CFG, + cfg(trans)->base_params->pll_cfg_val); + + /* + * Set "initialization complete" bit to move adapter from + * D0U* --> D0A* (powered-up active) state. + */ + iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + + /* + * Wait for clock stabilization; once stabilized, access to + * device-internal resources is supported, e.g. iwl_write_prph() + * and accesses to uCode SRAM. + */ + ret = iwl_poll_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); + if (ret < 0) { + IWL_DEBUG_INFO(trans, "Failed to init the card\n"); + goto out; + } + + /* + * Enable DMA clock and wait for it to stabilize. + * + * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits + * do not disable clocks. This preserves any hardware bits already + * set by default in "CLK_CTRL_REG" after reset. + */ + iwl_write_prph(trans, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); + udelay(20); + + /* Disable L1-Active */ + iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG, + APMG_PCIDEV_STT_VAL_L1_ACT_DIS); + + set_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status); + +out: + return ret; +} + static int iwl_nic_init(struct iwl_trans *trans) { unsigned long flags; /* nic_init */ spin_lock_irqsave(&trans->shrd->lock, flags); - iwl_apm_init(priv(trans)); + iwl_apm_init(trans); /* Set interrupt coalescing calibration timer to default (512 usecs) */ iwl_write8(trans, CSR_INT_COALESCING, @@ -1267,6 +1350,9 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) IWL_ERR(trans, "Error while preparing HW: %d", err); goto error; } + + iwl_apm_init(trans); + return err; error: -- cgit v1.2.3 From cc56feb2eb06a0a80a8f07e4adab7e6626009cca Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 8 Jan 2012 13:37:59 +0200 Subject: iwlwifi: introduce trans_ops->stop_hw This handler stops the HW and puts it in low power state. It will allow to clean up the flows in the upper layers. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 40 -------------------- drivers/net/wireless/iwlwifi/iwl-shared.h | 1 - drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 54 ++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-trans.h | 8 ++++ 5 files changed, 61 insertions(+), 44 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3aeaa890e64..88462467a95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1839,7 +1839,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, /* Read the EEPROM */ err = iwl_eeprom_init(priv, hw_rev); /* Reset chip to save power until we load uCode during "up". */ - iwl_apm_stop(priv); + iwl_trans_stop_hw(trans(priv)); if (err) { IWL_ERR(priv, "Unable to init EEPROM\n"); goto out_free_traffic_mem; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 3ba59fa3108..95f2c33695b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -883,46 +883,6 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) } } -static int iwl_apm_stop_master(struct iwl_priv *priv) -{ - int ret = 0; - - /* stop device's busmaster DMA activity */ - iwl_set_bit(trans(priv), CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - - ret = iwl_poll_bit(trans(priv), CSR_RESET, - CSR_RESET_REG_FLAG_MASTER_DISABLED, - CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); - if (ret) - IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n"); - - IWL_DEBUG_INFO(priv, "stop master\n"); - - return ret; -} - -void iwl_apm_stop(struct iwl_priv *priv) -{ - IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); - - clear_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); - - /* Stop device's DMA activity */ - iwl_apm_stop_master(priv); - - /* Reset the entire device */ - iwl_set_bit(trans(priv), CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); - - udelay(10); - - /* - * Clear "initialization complete" bit to move adapter from - * D0A* (powered-up Active) --> D0U* (Uninitialized) state. - */ - iwl_clear_bit(trans(priv), CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_INIT_DONE); -} - int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) { int ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 338a55f403d..63d4a4fc5b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -543,7 +543,6 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr); void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state); void iwl_nic_config(struct iwl_priv *priv); void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb); -void iwl_apm_stop(struct iwl_priv *priv); void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); const char *get_cmd_string(u8 cmd); bool iwl_check_for_ct_kill(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 335d4b1508c..43e894f6737 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -714,6 +714,46 @@ out: return ret; } +static int iwl_apm_stop_master(struct iwl_trans *trans) +{ + int ret = 0; + + /* stop device's busmaster DMA activity */ + iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); + + ret = iwl_poll_bit(trans, CSR_RESET, + CSR_RESET_REG_FLAG_MASTER_DISABLED, + CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); + if (ret) + IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n"); + + IWL_DEBUG_INFO(trans, "stop master\n"); + + return ret; +} + +static void iwl_apm_stop(struct iwl_trans *trans) +{ + IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n"); + + clear_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status); + + /* Stop device's DMA activity */ + iwl_apm_stop_master(trans); + + /* Reset the entire device */ + iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + + udelay(10); + + /* + * Clear "initialization complete" bit to move adapter from + * D0A* (powered-up Active) --> D0U* (Uninitialized) state. + */ + iwl_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_INIT_DONE); +} + static int iwl_nic_init(struct iwl_trans *trans) { unsigned long flags; @@ -1118,7 +1158,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ - iwl_apm_stop(priv(trans)); + iwl_apm_stop(trans); /* Upon stop, the APM issues an interrupt if HW RF kill is set. * Clean again the interrupt here @@ -1361,6 +1401,15 @@ error: return err; } +static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans) +{ + iwl_apm_stop(trans); + + /* Even if we stop the HW, we still want the RF kill interrupt */ + IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); + iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); +} + static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, int txq_id, int ssn, u32 status, struct sk_buff_head *skbs) @@ -1455,7 +1504,7 @@ static int iwl_trans_pcie_suspend(struct iwl_trans *trans) * things already :-) */ if (!trans->shrd->wowlan) { - iwl_apm_stop(priv(trans)); + iwl_apm_stop(trans); } else { iwl_disable_interrupts(trans); iwl_clear_bit(trans, CSR_GP_CNTRL, @@ -2024,6 +2073,7 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, const struct iwl_trans_ops trans_ops_pcie = { .start_hw = iwl_trans_pcie_start_hw, + .stop_hw = iwl_trans_pcie_stop_hw, .fw_alive = iwl_trans_pcie_fw_alive, .start_device = iwl_trans_pcie_start_device, .stop_device = iwl_trans_pcie_stop_device, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 55b5dc3b5dd..d0b6146b097 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -134,6 +134,8 @@ struct iwl_host_cmd { /** * struct iwl_trans_ops - transport specific operations * @start_hw: starts the HW- from that point on, the HW can send interrupts + * @stop_hw: stops the HW- from that point on, the HW will be in low power but + * will still issue interrupt if the HW RF kill is triggered. * @start_device: allocates and inits all the resources for the transport * layer. * @fw_alive: called when the fw sends alive notification @@ -163,6 +165,7 @@ struct iwl_host_cmd { struct iwl_trans_ops { int (*start_hw)(struct iwl_trans *iwl_trans); + void (*stop_hw)(struct iwl_trans *iwl_trans); int (*start_device)(struct iwl_trans *trans); void (*fw_alive)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans); @@ -271,6 +274,11 @@ static inline int iwl_trans_start_hw(struct iwl_trans *trans) return trans->ops->start_hw(trans); } +static inline void iwl_trans_stop_hw(struct iwl_trans *trans) +{ + trans->ops->stop_hw(trans); +} + static inline void iwl_trans_fw_alive(struct iwl_trans *trans) { trans->ops->fw_alive(trans); -- cgit v1.2.3 From d48e2074e240192e8a0396e1ae0082dd0e78aa8e Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 8 Jan 2012 13:48:21 +0200 Subject: iwlwifi: move the RF kill logic from iwl_probe to transport This is another clean up of the proble flow. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 23 ----------------------- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 88462467a95..14f8b750c7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1815,13 +1815,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, spin_lock_init(&trans(priv)->reg_lock); spin_lock_init(&priv->shrd->lock); - /* - * stop and reset the on-board processor just in case it is in a - * strange state ... like being left stranded by a primary kernel - * and this is now the kdump kernel trying to start up - */ - iwl_write32(trans(priv), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); - /*********************** * 3. Read REV register ***********************/ @@ -1890,22 +1883,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, iwl_setup_rx_handlers(priv); iwl_testmode_init(priv); - /********************************************* - * 8. Enable interrupts - *********************************************/ - - iwl_enable_rfkill_int(priv); - - /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(trans(priv), - CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); - else - set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); - - wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); - iwl_power_initialize(priv); iwl_tt_initialize(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 43e894f6737..362444a7ed5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1393,6 +1393,17 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) iwl_apm_init(trans); + /* If platform's RF_KILL switch is NOT set to KILL */ + if (iwl_read32(trans, + CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); + else + set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); + + iwl_set_hw_rfkill_state(priv(trans), + test_bit(STATUS_RF_KILL_HW, + &trans->shrd->status)); + return err; error: -- cgit v1.2.3 From cf6142975bcbb731bc131ee9d2a68b7561076545 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 8 Jan 2012 16:33:58 +0200 Subject: iwlwifi: consolidate the start_device flow Now there is only one transport function that launch a specific fw: trans_ops->start_fw. This one replaces trans_ops->start_device and trans_ops->kick_nic. The code that actually loads the fw to the device has been moved to the transport specific code. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 4 -- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 88 +++++++++++++++++++++--- drivers/net/wireless/iwlwifi/iwl-trans.h | 44 +++++------- drivers/net/wireless/iwlwifi/iwl-ucode.c | 87 ++--------------------- 4 files changed, 103 insertions(+), 120 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index ebea2435dac..731f287c0f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1130,11 +1130,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) isr_stats->tx++; handled |= CSR_INT_BIT_FH_TX; /* Wake up uCode load routine, now that load is complete */ -#ifdef CONFIG_IWLWIFI_IDI - trans->shrd->trans->ucode_write_complete = 1; -#else trans->ucode_write_complete = 1; -#endif wake_up(&trans->shrd->wait_command_queue); } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 362444a7ed5..1030a252405 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include @@ -895,7 +896,79 @@ static const u8 iwlagn_pan_ac_to_queue[] = { 7, 6, 5, 4, }; -static int iwl_trans_pcie_start_device(struct iwl_trans *trans) +/* + * ucode + */ +static int iwl_load_section(struct iwl_trans *trans, const char *name, + struct fw_desc *image, u32 dst_addr) +{ + dma_addr_t phy_addr = image->p_addr; + u32 byte_cnt = image->len; + int ret; + + trans->ucode_write_complete = 0; + + iwl_write_direct32(trans, + FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); + + iwl_write_direct32(trans, + FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); + + iwl_write_direct32(trans, + FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), + phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); + + iwl_write_direct32(trans, + FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), + (iwl_get_dma_hi_addr(phy_addr) + << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); + + iwl_write_direct32(trans, + FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), + 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | + 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | + FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); + + iwl_write_direct32(trans, + FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | + FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); + + IWL_DEBUG_FW(trans, "%s uCode section being loaded...\n", name); + ret = wait_event_timeout(trans->shrd->wait_command_queue, + trans->ucode_write_complete, 5 * HZ); + if (!ret) { + IWL_ERR(trans, "Could not load the %s uCode section\n", + name); + return -ETIMEDOUT; + } + + return 0; +} + +static int iwl_load_given_ucode(struct iwl_trans *trans, struct fw_img *image) +{ + int ret = 0; + + ret = iwl_load_section(trans, "INST", &image->code, + IWLAGN_RTC_INST_LOWER_BOUND); + if (ret) + return ret; + + ret = iwl_load_section(trans, "DATA", &image->data, + IWLAGN_RTC_DATA_LOWER_BOUND); + if (ret) + return ret; + + /* Remove all resets to allow NIC to operate */ + iwl_write32(trans, CSR_RESET, 0); + + return 0; +} + +static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw) { int ret; struct iwl_trans_pcie *trans_pcie = @@ -951,6 +1024,9 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + /* Load the given image to the HW */ + iwl_load_given_ucode(trans, fw); + return 0; } @@ -1353,12 +1429,6 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, return 0; } -static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans) -{ - /* Remove all resets to allow NIC to operate */ - iwl_write32(trans, CSR_RESET, 0); -} - static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = @@ -2086,7 +2156,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .start_hw = iwl_trans_pcie_start_hw, .stop_hw = iwl_trans_pcie_stop_hw, .fw_alive = iwl_trans_pcie_fw_alive, - .start_device = iwl_trans_pcie_start_device, + .start_fw = iwl_trans_pcie_start_fw, .stop_device = iwl_trans_pcie_stop_device, .wake_any_queue = iwl_trans_pcie_wake_any_queue, @@ -2100,8 +2170,6 @@ const struct iwl_trans_ops trans_ops_pcie = { .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, - .kick_nic = iwl_trans_pcie_kick_nic, - .free = iwl_trans_pcie_free, .stop_queue = iwl_trans_pcie_stop_queue, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index d0b6146b097..4d1ae65b68e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -131,13 +131,25 @@ struct iwl_host_cmd { u8 id; }; +/* one for each uCode image (inst/data, boot/init/runtime) */ +struct fw_desc { + dma_addr_t p_addr; /* hardware address */ + void *v_addr; /* software address */ + u32 len; /* size in bytes */ +}; + +struct fw_img { + struct fw_desc code; /* firmware code image */ + struct fw_desc data; /* firmware data image */ +}; + /** * struct iwl_trans_ops - transport specific operations * @start_hw: starts the HW- from that point on, the HW can send interrupts * @stop_hw: stops the HW- from that point on, the HW will be in low power but * will still issue interrupt if the HW RF kill is triggered. - * @start_device: allocates and inits all the resources for the transport - * layer. + * @start_fw: allocates and inits all the resources for the transport + * layer. Also kick a fw image. This handler may sleep. * @fw_alive: called when the fw sends alive notification * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* * @stop_device:stops the whole device (embedded CPU put to reset) @@ -148,7 +160,6 @@ struct iwl_host_cmd { * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is * ready and a successful ADDBA response has been received. * @tx_agg_disable: de-configure a Tx queue to send AMPDUs - * @kick_nic: remove the RESET from the embedded CPU and let it run * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... * @stop_queue: stop a specific queue @@ -166,7 +177,7 @@ struct iwl_trans_ops { int (*start_hw)(struct iwl_trans *iwl_trans); void (*stop_hw)(struct iwl_trans *iwl_trans); - int (*start_device)(struct iwl_trans *trans); + int (*start_fw)(struct iwl_trans *trans, struct fw_img *fw); void (*fw_alive)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans); @@ -191,8 +202,6 @@ struct iwl_trans_ops { enum iwl_rxon_context_id ctx, int sta_id, int tid, int frame_limit, u16 ssn); - void (*kick_nic)(struct iwl_trans *trans); - void (*free)(struct iwl_trans *trans); void (*stop_queue)(struct iwl_trans *trans, int q, const char *msg); @@ -209,18 +218,6 @@ struct iwl_trans_ops { u32 (*read32)(struct iwl_trans *trans, u32 ofs); }; -/* one for each uCode image (inst/data, boot/init/runtime) */ -struct fw_desc { - dma_addr_t p_addr; /* hardware address */ - void *v_addr; /* software address */ - u32 len; /* size in bytes */ -}; - -struct fw_img { - struct fw_desc code; /* firmware code image */ - struct fw_desc data; /* firmware data image */ -}; - /* Opaque calibration results */ struct iwl_calib_result { struct list_head list; @@ -284,9 +281,11 @@ static inline void iwl_trans_fw_alive(struct iwl_trans *trans) trans->ops->fw_alive(trans); } -static inline int iwl_trans_start_device(struct iwl_trans *trans) +static inline int iwl_trans_start_fw(struct iwl_trans *trans, struct fw_img *fw) { - return trans->ops->start_device(trans); + might_sleep(); + + return trans->ops->start_fw(trans, fw); } static inline void iwl_trans_stop_device(struct iwl_trans *trans) @@ -347,11 +346,6 @@ static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit, ssn); } -static inline void iwl_trans_kick_nic(struct iwl_trans *trans) -{ - trans->ops->kick_nic(trans); -} - static inline void iwl_trans_free(struct iwl_trans *trans) { trans->ops->free(trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 793524a3ed7..87ce587d7d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -120,58 +120,6 @@ int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc, return 0; } -/* - * ucode - */ -static int iwl_load_section(struct iwl_trans *trans, const char *name, - struct fw_desc *image, u32 dst_addr) -{ - dma_addr_t phy_addr = image->p_addr; - u32 byte_cnt = image->len; - int ret; - - trans->ucode_write_complete = 0; - - iwl_write_direct32(trans, - FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); - - iwl_write_direct32(trans, - FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); - - iwl_write_direct32(trans, - FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), - phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); - - iwl_write_direct32(trans, - FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), - (iwl_get_dma_hi_addr(phy_addr) - << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); - - iwl_write_direct32(trans, - FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), - 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | - 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | - FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); - - iwl_write_direct32(trans, - FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | - FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); - - IWL_DEBUG_FW(trans, "%s uCode section being loaded...\n", name); - ret = wait_event_timeout(trans->shrd->wait_command_queue, - trans->ucode_write_complete, 5 * HZ); - if (!ret) { - IWL_ERR(trans, "Could not load the %s uCode section\n", - name); - return -ETIMEDOUT; - } - - return 0; -} - static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, enum iwl_ucode_type ucode_type) { @@ -188,28 +136,6 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, return NULL; } -static int iwl_load_given_ucode(struct iwl_trans *trans, - enum iwl_ucode_type ucode_type) -{ - int ret = 0; - struct fw_img *image = iwl_get_ucode_image(trans, ucode_type); - - - if (!image) { - IWL_ERR(trans, "Invalid ucode requested (%d)\n", - ucode_type); - return -EINVAL; - } - - ret = iwl_load_section(trans, "INST", &image->code, - IWLAGN_RTC_INST_LOWER_BOUND); - if (ret) - return ret; - - return iwl_load_section(trans, "DATA", &image->data, - IWLAGN_RTC_DATA_LOWER_BOUND); -} - /* * Calibration */ @@ -646,28 +572,27 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans, { struct iwl_notification_wait alive_wait; struct iwl_alive_data alive_data; + struct fw_img *fw; int ret; enum iwl_ucode_type old_type; - ret = iwl_trans_start_device(trans); - if (ret) - return ret; - iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE, iwl_alive_fn, &alive_data); old_type = trans->shrd->ucode_type; trans->shrd->ucode_type = ucode_type; + fw = iwl_get_ucode_image(trans, ucode_type); - ret = iwl_load_given_ucode(trans, ucode_type); + if (!fw) + return -EINVAL; + + ret = iwl_trans_start_fw(trans, fw); if (ret) { trans->shrd->ucode_type = old_type; iwl_remove_notification(trans->shrd, &alive_wait); return ret; } - iwl_trans_kick_nic(trans); - /* * Some things may run in the background now, but we * just wait for the ALIVE notification here. -- cgit v1.2.3 From af634bee8c4a15629da5e114c491acb8ee50e1e9 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 8 Jan 2012 21:12:22 +0200 Subject: iwlwifi: kill bus_apm_config This handler was called from the transport layer only. Merge it to the transport's apm_init. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-bus.h | 7 ---- drivers/net/wireless/iwlwifi/iwl-pci.c | 29 ---------------- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 50 ++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 2065c5b7416..d385f692ef1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -121,13 +121,11 @@ struct iwl_bus; /** * struct iwl_bus_ops - bus specific operations * @get_pm_support: must returns true if the bus can go to sleep - * @apm_config: will be called during the config of the APM * @get_hw_id_string: prints the hw_id in the provided buffer * @get_hw_id: get hw_id in u32 */ struct iwl_bus_ops { bool (*get_pm_support)(struct iwl_bus *bus); - void (*apm_config)(struct iwl_bus *bus); void (*get_hw_id_string)(struct iwl_bus *bus, char buf[], int buf_len); u32 (*get_hw_id)(struct iwl_bus *bus); }; @@ -156,11 +154,6 @@ static inline bool bus_get_pm_support(struct iwl_bus *bus) return bus->ops->get_pm_support(bus); } -static inline void bus_apm_config(struct iwl_bus *bus) -{ - bus->ops->apm_config(bus); -} - static inline void bus_get_hw_id_string(struct iwl_bus *bus, char buf[], int buf_len) { diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 6451739aed2..353022d406e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -106,34 +106,6 @@ static bool iwl_pci_is_pm_supported(struct iwl_bus *bus) return !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN); } -static void iwl_pci_apm_config(struct iwl_bus *bus) -{ - /* - * HW bug W/A for instability in PCIe bus L0S->L1 transition. - * Check if BIOS (or OS) enabled L1-ASPM on this device. - * If so (likely), disable L0S, so device moves directly L0->L1; - * costs negligible amount of power savings. - * If not (unlikely), enable L0S, so there is at least some - * power savings, even without L1. - */ - u16 lctl = iwl_pciexp_link_ctrl(bus); - - if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == - PCI_CFG_LINK_CTRL_VAL_L1_EN) { - /* L1-ASPM enabled; disable(!) L0S */ - iwl_set_bit(trans(bus), CSR_GIO_REG, - CSR_GIO_REG_VAL_L0S_ENABLED); - dev_printk(KERN_INFO, trans(bus)->dev, - "L1 Enabled; Disabling L0S\n"); - } else { - /* L1-ASPM disabled; enable(!) L0S */ - iwl_clear_bit(trans(bus), CSR_GIO_REG, - CSR_GIO_REG_VAL_L0S_ENABLED); - dev_printk(KERN_INFO, trans(bus)->dev, - "L1 Disabled; Enabling L0S\n"); - } -} - static void iwl_pci_get_hw_id_string(struct iwl_bus *bus, char buf[], int buf_len) { @@ -152,7 +124,6 @@ static u32 iwl_pci_get_hw_id(struct iwl_bus *bus) static const struct iwl_bus_ops bus_ops_pci = { .get_pm_support = iwl_pci_is_pm_supported, - .apm_config = iwl_pci_apm_config, .get_hw_id_string = iwl_pci_get_hw_id_string, .get_hw_id = iwl_pci_get_hw_id, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 1030a252405..c9fe8889ad8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -633,6 +633,51 @@ static void iwl_set_pwr_vmain(struct iwl_trans *trans) ~APMG_PS_CTRL_MSK_PWR_SRC); } +/* PCI registers */ +#define PCI_CFG_RETRY_TIMEOUT 0x041 +#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 +#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 + +static u16 iwl_pciexp_link_ctrl(struct iwl_trans *trans) +{ + int pos; + u16 pci_lnk_ctl; + struct iwl_trans_pcie *trans_pcie = + IWL_TRANS_GET_PCIE_TRANS(trans); + + struct pci_dev *pci_dev = trans_pcie->pci_dev; + + pos = pci_pcie_cap(pci_dev); + pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); + return pci_lnk_ctl; +} + +static void iwl_apm_config(struct iwl_trans *trans) +{ + /* + * HW bug W/A for instability in PCIe bus L0S->L1 transition. + * Check if BIOS (or OS) enabled L1-ASPM on this device. + * If so (likely), disable L0S, so device moves directly L0->L1; + * costs negligible amount of power savings. + * If not (unlikely), enable L0S, so there is at least some + * power savings, even without L1. + */ + u16 lctl = iwl_pciexp_link_ctrl(trans); + + if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == + PCI_CFG_LINK_CTRL_VAL_L1_EN) { + /* L1-ASPM enabled; disable(!) L0S */ + iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); + dev_printk(KERN_INFO, trans->dev, + "L1 Enabled; Disabling L0S\n"); + } else { + /* L1-ASPM disabled; enable(!) L0S */ + iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); + dev_printk(KERN_INFO, trans->dev, + "L1 Disabled; Enabling L0S\n"); + } +} + /* * Start up NIC's basic functionality after it has been reset * (e.g. after platform boot, or shutdown via iwl_apm_stop()) @@ -669,7 +714,7 @@ static int iwl_apm_init(struct iwl_trans *trans) iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); - bus_apm_config(bus(trans)); + iwl_apm_config(trans); /* Configure analog phase-lock-loop before activating to D0A */ if (cfg(trans)->base_params->pll_cfg_val) @@ -2187,9 +2232,6 @@ const struct iwl_trans_ops trans_ops_pcie = { .read32 = iwl_trans_pcie_read32, }; -/* PCI registers */ -#define PCI_CFG_RETRY_TIMEOUT 0x041 - struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, struct pci_dev *pdev, const struct pci_device_id *ent) -- cgit v1.2.3 From f6d0e9be6580ba607f730d7e056518c95a864601 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 8 Jan 2012 21:19:45 +0200 Subject: iwlwifi: kill bus_is_pm_supported Get this information from the transport layer which is now in charge of the APM too. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-bus.h | 7 ------- drivers/net/wireless/iwlwifi/iwl-pci.c | 20 -------------------- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 1 + drivers/net/wireless/iwlwifi/iwl-trans.h | 2 ++ 5 files changed, 4 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index d385f692ef1..2b0b48edf28 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -120,12 +120,10 @@ struct iwl_bus; /** * struct iwl_bus_ops - bus specific operations - * @get_pm_support: must returns true if the bus can go to sleep * @get_hw_id_string: prints the hw_id in the provided buffer * @get_hw_id: get hw_id in u32 */ struct iwl_bus_ops { - bool (*get_pm_support)(struct iwl_bus *bus); void (*get_hw_id_string)(struct iwl_bus *bus, char buf[], int buf_len); u32 (*get_hw_id)(struct iwl_bus *bus); }; @@ -149,11 +147,6 @@ struct iwl_bus { char bus_specific[0] __attribute__((__aligned__(sizeof(void *)))); }; -static inline bool bus_get_pm_support(struct iwl_bus *bus) -{ - return bus->ops->get_pm_support(bus); -} - static inline void bus_get_hw_id_string(struct iwl_bus *bus, char buf[], int buf_len) { diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 353022d406e..0c16efebf93 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -87,25 +87,6 @@ struct iwl_pci_bus { #define IWL_BUS_GET_PCI_DEV(_iwl_bus) \ ((IWL_BUS_GET_PCI_BUS(_iwl_bus))->pci_dev) -static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus) -{ - int pos; - u16 pci_lnk_ctl; - - struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); - - pos = pci_pcie_cap(pci_dev); - pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); - return pci_lnk_ctl; -} - -static bool iwl_pci_is_pm_supported(struct iwl_bus *bus) -{ - u16 lctl = iwl_pciexp_link_ctrl(bus); - - return !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN); -} - static void iwl_pci_get_hw_id_string(struct iwl_bus *bus, char buf[], int buf_len) { @@ -123,7 +104,6 @@ static u32 iwl_pci_get_hw_id(struct iwl_bus *bus) } static const struct iwl_bus_ops bus_ops_pci = { - .get_pm_support = iwl_pci_is_pm_supported, .get_hw_id_string = iwl_pci_get_hw_id_string, .get_hw_id = iwl_pci_get_hw_id, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index c7394ef2e49..fd008c4e41f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -436,7 +436,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) /* initialize to default */ void iwl_power_initialize(struct iwl_priv *priv) { - priv->power_data.bus_pm = bus_get_pm_support(bus(priv)); + priv->power_data.bus_pm = trans(priv)->pm_support; priv->power_data.debug_sleep_level_override = -1; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index c9fe8889ad8..8ebb5a54441 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -676,6 +676,7 @@ static void iwl_apm_config(struct iwl_trans *trans) dev_printk(KERN_INFO, trans->dev, "L1 Disabled; Enabling L0S\n"); } + trans->pm_support = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN); } /* diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 4d1ae65b68e..7f6963ffa7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -239,6 +239,7 @@ struct iwl_calib_result { * @ucode_init: init ucode image * @ucode_wowlan: wake on wireless ucode image (optional) * @nvm_device_type: indicates OTP or eeprom + * @pm_support: set to true in start_hw if link pm is supported * @calib_results: list head for init calibration results */ struct iwl_trans { @@ -257,6 +258,7 @@ struct iwl_trans { /* eeprom related variables */ int nvm_device_type; + bool pm_support; /* init calibration results */ struct list_head calib_results; -- cgit v1.2.3 From 9ca859615212deb7dd0aee26972799d1910d050f Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 8 Jan 2012 21:19:45 +0200 Subject: iwlwifi: kill bus_get_hw_id_string Get this information from the transport layer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-bus.h | 8 -------- drivers/net/wireless/iwlwifi/iwl-core.c | 5 ++--- drivers/net/wireless/iwlwifi/iwl-pci.c | 10 ---------- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-trans.h | 2 ++ 5 files changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 2b0b48edf28..61130895428 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -120,11 +120,9 @@ struct iwl_bus; /** * struct iwl_bus_ops - bus specific operations - * @get_hw_id_string: prints the hw_id in the provided buffer * @get_hw_id: get hw_id in u32 */ struct iwl_bus_ops { - void (*get_hw_id_string)(struct iwl_bus *bus, char buf[], int buf_len); u32 (*get_hw_id)(struct iwl_bus *bus); }; @@ -147,12 +145,6 @@ struct iwl_bus { char bus_specific[0] __attribute__((__aligned__(sizeof(void *)))); }; -static inline void bus_get_hw_id_string(struct iwl_bus *bus, char buf[], - int buf_len) -{ - bus->ops->get_hw_id_string(bus, buf, buf_len); -} - static inline u32 bus_get_hw_id(struct iwl_bus *bus) { return bus->ops->get_hw_id(bus); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 95f2c33695b..0677b3dfbfb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -203,10 +203,9 @@ int iwl_init_geos(struct iwl_priv *priv) if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && cfg(priv)->sku & EEPROM_SKU_CAP_BAND_52GHZ) { - char buf[32]; - bus_get_hw_id_string(bus(priv), buf, sizeof(buf)); IWL_INFO(priv, "Incorrectly detected BG card as ABG. " - "Please send your %s to maintainer.\n", buf); + "Please send your %s to maintainer.\n", + trans(priv)->hw_id_str); cfg(priv)->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; } diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 0c16efebf93..15864760733 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -87,15 +87,6 @@ struct iwl_pci_bus { #define IWL_BUS_GET_PCI_DEV(_iwl_bus) \ ((IWL_BUS_GET_PCI_BUS(_iwl_bus))->pci_dev) -static void iwl_pci_get_hw_id_string(struct iwl_bus *bus, char buf[], - int buf_len) -{ - struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); - - snprintf(buf, buf_len, "PCI ID: 0x%04X:0x%04X", pci_dev->device, - pci_dev->subsystem_device); -} - static u32 iwl_pci_get_hw_id(struct iwl_bus *bus) { struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); @@ -104,7 +95,6 @@ static u32 iwl_pci_get_hw_id(struct iwl_bus *bus) } static const struct iwl_bus_ops bus_ops_pci = { - .get_hw_id_string = iwl_pci_get_hw_id_string, .get_hw_id = iwl_pci_get_hw_id, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 8ebb5a54441..73ff68ac7c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -2317,6 +2317,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, trans->dev = &pdev->dev; trans->irq = pdev->irq; trans_pcie->pci_dev = pdev; + snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), + "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); /* TODO: Move this away, not needed if not MSI */ /* enable rfkill interrupt: hw bug w/a */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 7f6963ffa7c..593102d89c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -234,6 +234,7 @@ struct iwl_calib_result { * @reg_lock - protect hw register access * @dev - pointer to struct device * that represents the device * @irq - the irq number for the device + * @hw_id_str: a string with info about HW ID. Set during transport allocation. * @ucode_write_complete: indicates that the ucode has been copied. * @ucode_rt: run time ucode image * @ucode_init: init ucode image @@ -250,6 +251,7 @@ struct iwl_trans { struct device *dev; unsigned int irq; + char hw_id_str[52]; u8 ucode_write_complete; /* the image write is complete */ struct fw_img ucode_rt; -- cgit v1.2.3 From 99673ee556fce2fb973eaa571adb12663330caa9 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 8 Jan 2012 21:19:45 +0200 Subject: iwlwifi: kill bus_get_hw_id Get this information from the transport layer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-bus.h | 14 ---------- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 2 +- drivers/net/wireless/iwlwifi/iwl-pci.c | 37 +++------------------------ drivers/net/wireless/iwlwifi/iwl-testmode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 1 + drivers/net/wireless/iwlwifi/iwl-trans.h | 3 +++ 6 files changed, 10 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 61130895428..30965e0e8ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -118,14 +118,6 @@ struct iwl_shared; struct iwl_bus; -/** - * struct iwl_bus_ops - bus specific operations - * @get_hw_id: get hw_id in u32 - */ -struct iwl_bus_ops { - u32 (*get_hw_id)(struct iwl_bus *bus); -}; - /** * struct iwl_bus - bus common data * @@ -137,7 +129,6 @@ struct iwl_bus_ops { * it allocates the shared data */ struct iwl_bus { - const struct iwl_bus_ops *ops; struct iwl_shared *shrd; /* pointer to bus specific struct */ @@ -145,11 +136,6 @@ struct iwl_bus { char bus_specific[0] __attribute__((__aligned__(sizeof(void *)))); }; -static inline u32 bus_get_hw_id(struct iwl_bus *bus) -{ - return bus->ops->get_hw_id(bus); -} - /***************************************************** * Bus layer registration functions ******************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index b911837b04f..78bc1e857b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -234,7 +234,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ]; - hw->wiphy->hw_version = bus_get_hw_id(bus(priv)); + hw->wiphy->hw_version = trans(priv)->hw_id; iwl_leds_init(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 15864760733..3e2fce4ce00 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -71,33 +71,6 @@ #include "iwl-csr.h" #include "iwl-cfg.h" -/* PCI registers */ -#define PCI_CFG_RETRY_TIMEOUT 0x041 -#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 -#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 - -struct iwl_pci_bus { - /* basic pci-network driver stuff */ - struct pci_dev *pci_dev; -}; - -#define IWL_BUS_GET_PCI_BUS(_iwl_bus) \ - ((struct iwl_pci_bus *) ((_iwl_bus)->bus_specific)) - -#define IWL_BUS_GET_PCI_DEV(_iwl_bus) \ - ((IWL_BUS_GET_PCI_BUS(_iwl_bus))->pci_dev) - -static u32 iwl_pci_get_hw_id(struct iwl_bus *bus) -{ - struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); - - return (pci_dev->device << 16) + pci_dev->subsystem_device; -} - -static const struct iwl_bus_ops bus_ops_pci = { - .get_hw_id = iwl_pci_get_hw_id, -}; - #define IWL_PCI_DEVICE(dev, subdev, cfg) \ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ @@ -283,14 +256,16 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { }; MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); +/* PCI registers */ +#define PCI_CFG_RETRY_TIMEOUT 0x041 + static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); struct iwl_bus *bus; - struct iwl_pci_bus *pci_bus; int err; - bus = kzalloc(sizeof(*bus) + sizeof(*pci_bus), GFP_KERNEL); + bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (!bus) { dev_printk(KERN_ERR, &pdev->dev, "Couldn't allocate iwl_pci_bus"); @@ -306,13 +281,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } bus->shrd->bus = bus; - pci_bus = IWL_BUS_GET_PCI_BUS(bus); - pci_bus->pci_dev = pdev; pci_set_drvdata(pdev, bus); - bus->ops = &bus_ops_pci; - #ifdef CONFIG_IWLWIFI_IDI trans(bus) = iwl_trans_idi_alloc(bus->shrd, pdev, ent); if (trans(bus) == NULL) { diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 922d841faba..7c17b9d5217 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -536,7 +536,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) break; case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: - devid = bus_get_hw_id(bus(priv)); + devid = trans(priv)->hw_id; IWL_INFO(priv, "hw version: 0x%x\n", devid); skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 73ff68ac7c4..4b711b790a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -2317,6 +2317,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, trans->dev = &pdev->dev; trans->irq = pdev->irq; trans_pcie->pci_dev = pdev; + trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 593102d89c7..0359d71e554 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -234,6 +234,8 @@ struct iwl_calib_result { * @reg_lock - protect hw register access * @dev - pointer to struct device * that represents the device * @irq - the irq number for the device + * @hw_id: a u32 with the ID of the device / subdevice. + * Set during transport alloaction. * @hw_id_str: a string with info about HW ID. Set during transport allocation. * @ucode_write_complete: indicates that the ucode has been copied. * @ucode_rt: run time ucode image @@ -251,6 +253,7 @@ struct iwl_trans { struct device *dev; unsigned int irq; + u32 hw_id; char hw_id_str[52]; u8 ucode_write_complete; /* the image write is complete */ -- cgit v1.2.3 From 08079a4919ca960c0f46d244cae3a6ec2c39041d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 9 Jan 2012 16:23:00 +0200 Subject: iwlwifi: move hw_rev to transport layer The HW revision is now read by the transport layer in its allocation. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 13 ++----------- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 1 + drivers/net/wireless/iwlwifi/iwl-trans.h | 1 + 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 14f8b750c7c..36f7adeb176 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1691,13 +1691,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv) #endif } - - -static u32 iwl_hw_detect(struct iwl_priv *priv) -{ - return iwl_read32(trans(priv), CSR_HW_REV); -} - /* Size of one Rx buffer in host DRAM */ #define IWL_RX_BUF_SIZE_4K (4 * 1024) #define IWL_RX_BUF_SIZE_8K (8 * 1024) @@ -1769,7 +1762,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, struct iwl_priv *priv; struct ieee80211_hw *hw; u16 num_mac; - u32 hw_rev; /************************ * 1. Allocating HW data @@ -1818,9 +1810,8 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, /*********************** * 3. Read REV register ***********************/ - hw_rev = iwl_hw_detect(priv); IWL_INFO(priv, "Detected %s, REV=0x%X\n", - cfg(priv)->name, hw_rev); + cfg(priv)->name, trans(priv)->hw_rev); err = iwl_trans_start_hw(trans(priv)); if (err) @@ -1830,7 +1821,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, * 4. Read EEPROM *****************/ /* Read the EEPROM */ - err = iwl_eeprom_init(priv, hw_rev); + err = iwl_eeprom_init(priv, trans(priv)->hw_rev); /* Reset chip to save power until we load uCode during "up". */ iwl_trans_stop_hw(trans(priv)); if (err) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 4b711b790a9..ed2a9216d80 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -2317,6 +2317,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, trans->dev = &pdev->dev; trans->irq = pdev->irq; trans_pcie->pci_dev = pdev; + trans->hw_rev = iwl_read32(trans, CSR_HW_REV); trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0359d71e554..a305e96d82a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -253,6 +253,7 @@ struct iwl_trans { struct device *dev; unsigned int irq; + u32 hw_rev; u32 hw_id; char hw_id_str[52]; -- cgit v1.2.3 From 1df06bdc6fb26d13af18c5dbb3144f13cf55de3c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 9 Jan 2012 16:35:08 +0200 Subject: iwlwifi: stop_hw replace enable_rfkill_int This trans_ops->stop_hw leaves the RFKILL interrupt enabled, we can call that one instead of enable_rfkill_int. By that, we reduce the numbers of acceesses to the NIC from the upper layers. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.h | 6 ------ drivers/net/wireless/iwlwifi/iwl-mac80211.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 6 ++++-- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 2 ++ 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e74bfb7bbb2..8d60dcf6f2e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -297,12 +297,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) cfg(priv)->bt_params->advanced_bt_coexist; } -static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) -{ - IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); - iwl_write32(trans(priv), CSR_INT_MASK, CSR_INT_BIT_RF_KILL); -} - extern bool bt_siso_mode; #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 78bc1e857b0..7177fd76e28 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -346,9 +346,10 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) flush_workqueue(priv->shrd->workqueue); /* User space software may expect getting rfkill changes - * even if interface is down */ - iwl_write32(trans(priv), CSR_INT, 0xFFFFFFFF); - iwl_enable_rfkill_int(priv); + * even if interface is down, trans->down will leave the RF + * kill interrupt enabled + */ + iwl_trans_stop_hw(trans(priv)); IWL_DEBUG_MAC80211(priv, "leave\n"); } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 731f287c0f3..78abff00453 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1149,8 +1149,10 @@ void iwl_irq_tasklet(struct iwl_trans *trans) if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status)) iwl_enable_interrupts(trans); /* Re-enable RF_KILL if it occurred */ - else if (handled & CSR_INT_BIT_RF_KILL) - iwl_enable_rfkill_int(priv(trans)); + else if (handled & CSR_INT_BIT_RF_KILL) { + IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); + iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); + } } /****************************************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index ed2a9216d80..ec26950ebb5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1532,6 +1532,8 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans) { iwl_apm_stop(trans); + iwl_write32(trans, CSR_INT, 0xFFFFFFFF); + /* Even if we stop the HW, we still want the RF kill interrupt */ IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); -- cgit v1.2.3 From 1dcedc8e07902b32027e4cf00dc8150774a492e2 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 19 Jan 2012 08:27:03 +0200 Subject: iwlwifi: debug print in tx_queue_set_status is more clear The message was misleading when a queue is deactivated. The fifo number is irrelevant then, so don't print it. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 5e095ac5076..08e0a7da48a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -431,9 +431,12 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, txq->sched_retry = scd_retry; - IWL_DEBUG_TX_QUEUES(trans, "%s %s Queue %d on FIFO %d\n", - active ? "Activate" : "Deactivate", - scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); + if (active) + IWL_DEBUG_TX_QUEUES(trans, "Activate %s Queue %d on FIFO %d\n", + scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); + else + IWL_DEBUG_TX_QUEUES(trans, "Deactivate %s Queue %d\n", + scd_retry ? "BA" : "AC/CMD", txq_id); } static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie, -- cgit v1.2.3 From 1589c5629c336dbb813accec03619940695339ec Mon Sep 17 00:00:00 2001 From: Don Fry Date: Fri, 27 Jan 2012 13:15:54 -0800 Subject: iwlwifi: clarify comment change a comment to be a little more clear Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 36f7adeb176..82f8836f304 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1781,7 +1781,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, SET_IEEE80211_DEV(hw, trans(priv)->dev); - /* what debugging capabilities we have */ + /* show what debugging capabilities we have */ iwl_debug_config(priv); IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); -- cgit v1.2.3 From 87272af74e98225672c9165a20b0604a7db758cf Mon Sep 17 00:00:00 2001 From: Don Fry Date: Wed, 25 Jan 2012 15:26:34 -0800 Subject: iwlwifi: move bcast_sta_id init to common routine There is nothing device specific in the initialization of the bcast_sta_id so move it to the common inititalization routine. Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-2000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 + 5 files changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index f7a555b9d24..8c1466c907f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -128,8 +128,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) iwlagn_mod_params.num_of_queues; hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; - priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 87600345010..d4f5f3b8757 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -124,8 +124,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) iwlagn_mod_params.num_of_queues; hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; - priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 5245a1422a6..dc9317d0343 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -170,8 +170,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) iwlagn_mod_params.num_of_queues; hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; - priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; @@ -199,8 +197,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) iwlagn_mod_params.num_of_queues; hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; - priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 464b8878467..c36fb858a45 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -145,8 +145,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) iwlagn_mod_params.num_of_queues; hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; - priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 82f8836f304..c41c394de2c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -513,6 +513,7 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; + priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = BIT(NL80211_IFTYPE_ADHOC); priv->contexts[IWL_RXON_CTX_BSS].interface_modes = -- cgit v1.2.3 From edf38334061cb87c68cfc7fdc192c850b7e02320 Mon Sep 17 00:00:00 2001 From: Don Fry Date: Wed, 25 Jan 2012 16:18:52 -0800 Subject: iwlwifi: move all ucode routines to iwl-ucode.c The routines dealing with the ucode are spread through several files. Move them all to the same file and create a iwl-ucode.h file with the ucode file definitions. Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 609 +-------------------------- drivers/net/wireless/iwlwifi/iwl-agn.h | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 108 ----- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans.h | 2 - drivers/net/wireless/iwlwifi/iwl-ucode.c | 610 +++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-ucode.h | 178 ++++++++ 7 files changed, 791 insertions(+), 719 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-ucode.h diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c41c394de2c..8837171ad55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -42,6 +41,7 @@ #include +#include "iwl-ucode.h" #include "iwl-eeprom.h" #include "iwl-wifi.h" #include "iwl-dev.h" @@ -490,7 +490,7 @@ static void iwl_bg_tx_flush(struct work_struct *work) iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); } -static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) +void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) { int i; @@ -548,611 +548,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); } -static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); - -#define UCODE_EXPERIMENTAL_INDEX 100 -#define UCODE_EXPERIMENTAL_TAG "exp" - -static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) -{ - const char *name_pre = cfg(priv)->fw_name_pre; - char tag[8]; - - if (first) { -#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE - priv->fw_index = UCODE_EXPERIMENTAL_INDEX; - strcpy(tag, UCODE_EXPERIMENTAL_TAG); - } else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) { -#endif - priv->fw_index = cfg(priv)->ucode_api_max; - sprintf(tag, "%d", priv->fw_index); - } else { - priv->fw_index--; - sprintf(tag, "%d", priv->fw_index); - } - - if (priv->fw_index < cfg(priv)->ucode_api_min) { - IWL_ERR(priv, "no suitable firmware found!\n"); - return -ENOENT; - } - - sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode"); - - IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n", - (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) - ? "EXPERIMENTAL " : "", - priv->firmware_name); - - return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, - trans(priv)->dev, - GFP_KERNEL, priv, iwl_ucode_callback); -} - -struct iwlagn_firmware_pieces { - const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data; - size_t inst_size, data_size, init_size, init_data_size, - wowlan_inst_size, wowlan_data_size; - - u32 build; - - u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; - u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; -}; - -static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, - const struct firmware *ucode_raw, - struct iwlagn_firmware_pieces *pieces) -{ - struct iwl_ucode_header *ucode = (void *)ucode_raw->data; - u32 api_ver, hdr_size; - const u8 *src; - - priv->ucode_ver = le32_to_cpu(ucode->ver); - api_ver = IWL_UCODE_API(priv->ucode_ver); - - switch (api_ver) { - default: - hdr_size = 28; - if (ucode_raw->size < hdr_size) { - IWL_ERR(priv, "File size too small!\n"); - return -EINVAL; - } - pieces->build = le32_to_cpu(ucode->u.v2.build); - pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); - pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); - pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); - pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); - src = ucode->u.v2.data; - break; - case 0: - case 1: - case 2: - hdr_size = 24; - if (ucode_raw->size < hdr_size) { - IWL_ERR(priv, "File size too small!\n"); - return -EINVAL; - } - pieces->build = 0; - pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size); - pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); - pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); - pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size); - src = ucode->u.v1.data; - break; - } - - /* Verify size of file vs. image size info in file's header */ - if (ucode_raw->size != hdr_size + pieces->inst_size + - pieces->data_size + pieces->init_size + - pieces->init_data_size) { - - IWL_ERR(priv, - "uCode file size %d does not match expected size\n", - (int)ucode_raw->size); - return -EINVAL; - } - - pieces->inst = src; - src += pieces->inst_size; - pieces->data = src; - src += pieces->data_size; - pieces->init = src; - src += pieces->init_size; - pieces->init_data = src; - src += pieces->init_data_size; - - return 0; -} - -static int iwlagn_load_firmware(struct iwl_priv *priv, - const struct firmware *ucode_raw, - struct iwlagn_firmware_pieces *pieces, - struct iwlagn_ucode_capabilities *capa) -{ - struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data; - struct iwl_ucode_tlv *tlv; - size_t len = ucode_raw->size; - const u8 *data; - int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative; - int tmp; - u64 alternatives; - u32 tlv_len; - enum iwl_ucode_tlv_type tlv_type; - const u8 *tlv_data; - - if (len < sizeof(*ucode)) { - IWL_ERR(priv, "uCode has invalid length: %zd\n", len); - return -EINVAL; - } - - if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) { - IWL_ERR(priv, "invalid uCode magic: 0X%x\n", - le32_to_cpu(ucode->magic)); - return -EINVAL; - } - - /* - * Check which alternatives are present, and "downgrade" - * when the chosen alternative is not present, warning - * the user when that happens. Some files may not have - * any alternatives, so don't warn in that case. - */ - alternatives = le64_to_cpu(ucode->alternatives); - tmp = wanted_alternative; - if (wanted_alternative > 63) - wanted_alternative = 63; - while (wanted_alternative && !(alternatives & BIT(wanted_alternative))) - wanted_alternative--; - if (wanted_alternative && wanted_alternative != tmp) - IWL_WARN(priv, - "uCode alternative %d not available, choosing %d\n", - tmp, wanted_alternative); - - priv->ucode_ver = le32_to_cpu(ucode->ver); - pieces->build = le32_to_cpu(ucode->build); - data = ucode->data; - - len -= sizeof(*ucode); - - while (len >= sizeof(*tlv)) { - u16 tlv_alt; - - len -= sizeof(*tlv); - tlv = (void *)data; - - tlv_len = le32_to_cpu(tlv->length); - tlv_type = le16_to_cpu(tlv->type); - tlv_alt = le16_to_cpu(tlv->alternative); - tlv_data = tlv->data; - - if (len < tlv_len) { - IWL_ERR(priv, "invalid TLV len: %zd/%u\n", - len, tlv_len); - return -EINVAL; - } - len -= ALIGN(tlv_len, 4); - data += sizeof(*tlv) + ALIGN(tlv_len, 4); - - /* - * Alternative 0 is always valid. - * - * Skip alternative TLVs that are not selected. - */ - if (tlv_alt != 0 && tlv_alt != wanted_alternative) - continue; - - switch (tlv_type) { - case IWL_UCODE_TLV_INST: - pieces->inst = tlv_data; - pieces->inst_size = tlv_len; - break; - case IWL_UCODE_TLV_DATA: - pieces->data = tlv_data; - pieces->data_size = tlv_len; - break; - case IWL_UCODE_TLV_INIT: - pieces->init = tlv_data; - pieces->init_size = tlv_len; - break; - case IWL_UCODE_TLV_INIT_DATA: - pieces->init_data = tlv_data; - pieces->init_data_size = tlv_len; - break; - case IWL_UCODE_TLV_BOOT: - IWL_ERR(priv, "Found unexpected BOOT ucode\n"); - break; - case IWL_UCODE_TLV_PROBE_MAX_LEN: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - capa->max_probe_length = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_PAN: - if (tlv_len) - goto invalid_tlv_len; - capa->flags |= IWL_UCODE_TLV_FLAGS_PAN; - break; - case IWL_UCODE_TLV_FLAGS: - /* must be at least one u32 */ - if (tlv_len < sizeof(u32)) - goto invalid_tlv_len; - /* and a proper number of u32s */ - if (tlv_len % sizeof(u32)) - goto invalid_tlv_len; - /* - * This driver only reads the first u32 as - * right now no more features are defined, - * if that changes then either the driver - * will not work with the new firmware, or - * it'll not take advantage of new features. - */ - capa->flags = le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_INIT_EVTLOG_PTR: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->init_evtlog_ptr = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->init_evtlog_size = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_INIT_ERRLOG_PTR: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->init_errlog_ptr = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->inst_evtlog_ptr = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->inst_evtlog_size = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->inst_errlog_ptr = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_ENHANCE_SENS_TBL: - if (tlv_len) - goto invalid_tlv_len; - priv->enhance_sensitivity_table = true; - break; - case IWL_UCODE_TLV_WOWLAN_INST: - pieces->wowlan_inst = tlv_data; - pieces->wowlan_inst_size = tlv_len; - break; - case IWL_UCODE_TLV_WOWLAN_DATA: - pieces->wowlan_data = tlv_data; - pieces->wowlan_data_size = tlv_len; - break; - case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - capa->standard_phy_calibration_size = - le32_to_cpup((__le32 *)tlv_data); - break; - default: - IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type); - break; - } - } - - if (len) { - IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len); - iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len); - return -EINVAL; - } - - return 0; - - invalid_tlv_len: - IWL_ERR(priv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len); - iwl_print_hex_dump(priv, IWL_DL_FW, tlv_data, tlv_len); - - return -EINVAL; -} - -/** - * iwl_ucode_callback - callback when firmware was loaded - * - * If loaded successfully, copies the firmware into buffers - * for the card to fetch (via DMA). - */ -static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) -{ - struct iwl_priv *priv = context; - struct iwl_ucode_header *ucode; - int err; - struct iwlagn_firmware_pieces pieces; - const unsigned int api_max = cfg(priv)->ucode_api_max; - unsigned int api_ok = cfg(priv)->ucode_api_ok; - const unsigned int api_min = cfg(priv)->ucode_api_min; - u32 api_ver; - char buildstr[25]; - u32 build; - struct iwlagn_ucode_capabilities ucode_capa = { - .max_probe_length = 200, - .standard_phy_calibration_size = - IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE, - }; - - if (!api_ok) - api_ok = api_max; - - memset(&pieces, 0, sizeof(pieces)); - - if (!ucode_raw) { - if (priv->fw_index <= api_ok) - IWL_ERR(priv, - "request for firmware file '%s' failed.\n", - priv->firmware_name); - goto try_again; - } - - IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", - priv->firmware_name, ucode_raw->size); - - /* Make sure that we got at least the API version number */ - if (ucode_raw->size < 4) { - IWL_ERR(priv, "File size way too small!\n"); - goto try_again; - } - - /* Data from ucode file: header followed by uCode images */ - ucode = (struct iwl_ucode_header *)ucode_raw->data; - - if (ucode->ver) - err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces); - else - err = iwlagn_load_firmware(priv, ucode_raw, &pieces, - &ucode_capa); - - if (err) - goto try_again; - - api_ver = IWL_UCODE_API(priv->ucode_ver); - build = pieces.build; - - /* - * api_ver should match the api version forming part of the - * firmware filename ... but we don't check for that and only rely - * on the API version read from firmware header from here on forward - */ - /* no api version check required for experimental uCode */ - if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) { - if (api_ver < api_min || api_ver > api_max) { - IWL_ERR(priv, - "Driver unable to support your firmware API. " - "Driver supports v%u, firmware is v%u.\n", - api_max, api_ver); - goto try_again; - } - - if (api_ver < api_ok) { - if (api_ok != api_max) - IWL_ERR(priv, "Firmware has old API version, " - "expected v%u through v%u, got v%u.\n", - api_ok, api_max, api_ver); - else - IWL_ERR(priv, "Firmware has old API version, " - "expected v%u, got v%u.\n", - api_max, api_ver); - IWL_ERR(priv, "New firmware can be obtained from " - "http://www.intellinuxwireless.org/.\n"); - } - } - - if (build) - sprintf(buildstr, " build %u%s", build, - (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) - ? " (EXP)" : ""); - else - buildstr[0] = '\0'; - - IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u%s\n", - IWL_UCODE_MAJOR(priv->ucode_ver), - IWL_UCODE_MINOR(priv->ucode_ver), - IWL_UCODE_API(priv->ucode_ver), - IWL_UCODE_SERIAL(priv->ucode_ver), - buildstr); - - snprintf(priv->hw->wiphy->fw_version, - sizeof(priv->hw->wiphy->fw_version), - "%u.%u.%u.%u%s", - IWL_UCODE_MAJOR(priv->ucode_ver), - IWL_UCODE_MINOR(priv->ucode_ver), - IWL_UCODE_API(priv->ucode_ver), - IWL_UCODE_SERIAL(priv->ucode_ver), - buildstr); - - /* - * For any of the failures below (before allocating pci memory) - * we will try to load a version with a smaller API -- maybe the - * user just got a corrupted version of the latest API. - */ - - IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", - priv->ucode_ver); - IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n", - pieces.inst_size); - IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n", - pieces.data_size); - IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n", - pieces.init_size); - IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n", - pieces.init_data_size); - - /* Verify that uCode images will fit in card's SRAM */ - if (pieces.inst_size > hw_params(priv).max_inst_size) { - IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n", - pieces.inst_size); - goto try_again; - } - - if (pieces.data_size > hw_params(priv).max_data_size) { - IWL_ERR(priv, "uCode data len %Zd too large to fit in\n", - pieces.data_size); - goto try_again; - } - - if (pieces.init_size > hw_params(priv).max_inst_size) { - IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n", - pieces.init_size); - goto try_again; - } - - if (pieces.init_data_size > hw_params(priv).max_data_size) { - IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n", - pieces.init_data_size); - goto try_again; - } - - /* Allocate ucode buffers for card's bus-master loading ... */ - - /* Runtime instructions and 2 copies of data: - * 1) unmodified from disk - * 2) backup cache for save/restore during power-downs */ - if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.code, - pieces.inst, pieces.inst_size)) - goto err_pci_alloc; - if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.data, - pieces.data, pieces.data_size)) - goto err_pci_alloc; - - /* Initialization instructions and data */ - if (pieces.init_size && pieces.init_data_size) { - if (iwl_alloc_fw_desc(trans(priv), - &trans(priv)->ucode_init.code, - pieces.init, pieces.init_size)) - goto err_pci_alloc; - if (iwl_alloc_fw_desc(trans(priv), - &trans(priv)->ucode_init.data, - pieces.init_data, pieces.init_data_size)) - goto err_pci_alloc; - } - - /* WoWLAN instructions and data */ - if (pieces.wowlan_inst_size && pieces.wowlan_data_size) { - if (iwl_alloc_fw_desc(trans(priv), - &trans(priv)->ucode_wowlan.code, - pieces.wowlan_inst, - pieces.wowlan_inst_size)) - goto err_pci_alloc; - if (iwl_alloc_fw_desc(trans(priv), - &trans(priv)->ucode_wowlan.data, - pieces.wowlan_data, - pieces.wowlan_data_size)) - goto err_pci_alloc; - } - - /* Now that we can no longer fail, copy information */ - - /* - * The (size - 16) / 12 formula is based on the information recorded - * for each event, which is of mode 1 (including timestamp) for all - * new microcodes that include this information. - */ - priv->init_evtlog_ptr = pieces.init_evtlog_ptr; - if (pieces.init_evtlog_size) - priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; - else - priv->init_evtlog_size = - cfg(priv)->base_params->max_event_log_size; - priv->init_errlog_ptr = pieces.init_errlog_ptr; - priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr; - if (pieces.inst_evtlog_size) - priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; - else - priv->inst_evtlog_size = - cfg(priv)->base_params->max_event_log_size; - priv->inst_errlog_ptr = pieces.inst_errlog_ptr; -#ifndef CONFIG_IWLWIFI_P2P - ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN; -#endif - - priv->new_scan_threshold_behaviour = - !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); - - if (!(cfg(priv)->sku & EEPROM_SKU_CAP_IPAN_ENABLE)) - ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN; - - /* - * if not PAN, then don't support P2P -- might be a uCode - * packaging bug or due to the eeprom check above - */ - if (!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) - ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P; - - if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { - priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; - priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; - } else { - priv->sta_key_max_num = STA_KEY_MAX_NUM; - priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; - } - /* - * figure out the offset of chain noise reset and gain commands - * base on the size of standard phy calibration commands table size - */ - if (ucode_capa.standard_phy_calibration_size > - IWL_MAX_PHY_CALIBRATE_TBL_SIZE) - ucode_capa.standard_phy_calibration_size = - IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE; - - priv->phy_calib_chain_noise_reset_cmd = - ucode_capa.standard_phy_calibration_size; - priv->phy_calib_chain_noise_gain_cmd = - ucode_capa.standard_phy_calibration_size + 1; - - /* initialize all valid contexts */ - iwl_init_context(priv, ucode_capa.flags); - - /************************************************** - * This is still part of probe() in a sense... - * - * 9. Setup and register with mac80211 and debugfs - **************************************************/ - err = iwlagn_mac_setup_register(priv, &ucode_capa); - if (err) - goto out_unbind; - - err = iwl_dbgfs_register(priv, DRV_NAME); - if (err) - IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); - - /* We have our copies now, allow OS release its copies */ - release_firmware(ucode_raw); - complete(&priv->firmware_loading_complete); - return; - - try_again: - /* try next, if any */ - if (iwl_request_firmware(priv, false)) - goto out_unbind; - release_firmware(ucode_raw); - return; - - err_pci_alloc: - IWL_ERR(priv, "failed to allocate pci memory\n"); - iwl_dealloc_ucode(trans(priv)); - out_unbind: - complete(&priv->firmware_loading_complete); - device_release_driver(trans(priv)->dev); - release_firmware(ucode_raw); -} - static void iwl_rf_kill_ct_config(struct iwl_priv *priv) { struct iwl_ct_kill_config cmd; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 0f5133ac357..37c325ff6e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -107,6 +107,7 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf, int iwlagn_rx_calib_result(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, struct iwl_device_cmd *cmd); +void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); /* lib */ int iwlagn_send_tx_power(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index fff5b620927..aa99457c3a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -292,114 +292,6 @@ struct iwl_vif_priv { u8 ibss_bssid_sta_id; }; -/* v1/v2 uCode file layout */ -struct iwl_ucode_header { - __le32 ver; /* major/minor/API/serial */ - union { - struct { - __le32 inst_size; /* bytes of runtime code */ - __le32 data_size; /* bytes of runtime data */ - __le32 init_size; /* bytes of init code */ - __le32 init_data_size; /* bytes of init data */ - __le32 boot_size; /* bytes of bootstrap code */ - u8 data[0]; /* in same order as sizes */ - } v1; - struct { - __le32 build; /* build number */ - __le32 inst_size; /* bytes of runtime code */ - __le32 data_size; /* bytes of runtime data */ - __le32 init_size; /* bytes of init code */ - __le32 init_data_size; /* bytes of init data */ - __le32 boot_size; /* bytes of bootstrap code */ - u8 data[0]; /* in same order as sizes */ - } v2; - } u; -}; - -/* - * new TLV uCode file layout - * - * The new TLV file format contains TLVs, that each specify - * some piece of data. To facilitate "groups", for example - * different instruction image with different capabilities, - * bundled with the same init image, an alternative mechanism - * is provided: - * When the alternative field is 0, that means that the item - * is always valid. When it is non-zero, then it is only - * valid in conjunction with items of the same alternative, - * in which case the driver (user) selects one alternative - * to use. - */ - -enum iwl_ucode_tlv_type { - IWL_UCODE_TLV_INVALID = 0, /* unused */ - IWL_UCODE_TLV_INST = 1, - IWL_UCODE_TLV_DATA = 2, - IWL_UCODE_TLV_INIT = 3, - IWL_UCODE_TLV_INIT_DATA = 4, - IWL_UCODE_TLV_BOOT = 5, - IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ - IWL_UCODE_TLV_PAN = 7, - IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8, - IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, - IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, - IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, - IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, - IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, - IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, - IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, - IWL_UCODE_TLV_WOWLAN_INST = 16, - IWL_UCODE_TLV_WOWLAN_DATA = 17, - IWL_UCODE_TLV_FLAGS = 18, -}; - -/** - * enum iwl_ucode_tlv_flag - ucode API flags - * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously - * was a separate TLV but moved here to save space. - * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID, - * treats good CRC threshold as a boolean - * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). - * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. - */ -enum iwl_ucode_tlv_flag { - IWL_UCODE_TLV_FLAGS_PAN = BIT(0), - IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), - IWL_UCODE_TLV_FLAGS_MFP = BIT(2), - IWL_UCODE_TLV_FLAGS_P2P = BIT(3), -}; - -struct iwl_ucode_tlv { - __le16 type; /* see above */ - __le16 alternative; /* see comment */ - __le32 length; /* not including type/length fields */ - u8 data[0]; -} __packed; - -#define IWL_TLV_UCODE_MAGIC 0x0a4c5749 - -struct iwl_tlv_ucode_header { - /* - * The TLV style ucode header is distinguished from - * the v1/v2 style header by first four bytes being - * zero, as such is an invalid combination of - * major/minor/API/serial versions. - */ - __le32 zero; - __le32 magic; - u8 human_readable[64]; - __le32 ver; /* major/minor/API/serial */ - __le32 build; - __le64 alternatives; /* bitmask of valid alternatives */ - /* - * The data contained herein has a TLV layout, - * see above for the TLV header and types. - * Note that each TLV is padded to a length - * that is a multiple of 4 for alignment. - */ - u8 data[0]; -}; - struct iwl_sensitivity_ranges { u16 min_nrg_cck; u16 max_nrg_cck; diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 7177fd76e28..d8025fee7e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -43,6 +42,7 @@ #include +#include "iwl-ucode.h" #include "iwl-eeprom.h" #include "iwl-wifi.h" #include "iwl-dev.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index a305e96d82a..ae68c51e532 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -410,8 +410,6 @@ static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs) /***************************************************** * Utils functions ******************************************************/ -int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc, - const void *data, size_t len); void iwl_dealloc_ucode(struct iwl_trans *trans); int iwl_send_calib_results(struct iwl_trans *trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 87ce587d7d5..11b659ab261 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -32,7 +32,9 @@ #include #include #include +#include +#include "iwl-ucode.h" #include "iwl-wifi.h" #include "iwl-dev.h" #include "iwl-core.h" @@ -102,7 +104,7 @@ void iwl_dealloc_ucode(struct iwl_trans *trans) iwl_free_fw_img(trans, &trans->ucode_wowlan); } -int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc, +static int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc, const void *data, size_t len) { if (!len) { @@ -680,3 +682,609 @@ int iwl_run_init_ucode(struct iwl_trans *trans) iwl_trans_stop_device(trans); return ret; } + +static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); + +#define UCODE_EXPERIMENTAL_INDEX 100 +#define UCODE_EXPERIMENTAL_TAG "exp" + +int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) +{ + const char *name_pre = cfg(priv)->fw_name_pre; + char tag[8]; + + if (first) { +#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE + priv->fw_index = UCODE_EXPERIMENTAL_INDEX; + strcpy(tag, UCODE_EXPERIMENTAL_TAG); + } else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) { +#endif + priv->fw_index = cfg(priv)->ucode_api_max; + sprintf(tag, "%d", priv->fw_index); + } else { + priv->fw_index--; + sprintf(tag, "%d", priv->fw_index); + } + + if (priv->fw_index < cfg(priv)->ucode_api_min) { + IWL_ERR(priv, "no suitable firmware found!\n"); + return -ENOENT; + } + + sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode"); + + IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n", + (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) + ? "EXPERIMENTAL " : "", + priv->firmware_name); + + return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, + trans(priv)->dev, + GFP_KERNEL, priv, iwl_ucode_callback); +} + +struct iwlagn_firmware_pieces { + const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data; + size_t inst_size, data_size, init_size, init_data_size, + wowlan_inst_size, wowlan_data_size; + + u32 build; + + u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; + u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; +}; + +static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, + const struct firmware *ucode_raw, + struct iwlagn_firmware_pieces *pieces) +{ + struct iwl_ucode_header *ucode = (void *)ucode_raw->data; + u32 api_ver, hdr_size; + const u8 *src; + + priv->ucode_ver = le32_to_cpu(ucode->ver); + api_ver = IWL_UCODE_API(priv->ucode_ver); + + switch (api_ver) { + default: + hdr_size = 28; + if (ucode_raw->size < hdr_size) { + IWL_ERR(priv, "File size too small!\n"); + return -EINVAL; + } + pieces->build = le32_to_cpu(ucode->u.v2.build); + pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); + pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); + pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); + pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); + src = ucode->u.v2.data; + break; + case 0: + case 1: + case 2: + hdr_size = 24; + if (ucode_raw->size < hdr_size) { + IWL_ERR(priv, "File size too small!\n"); + return -EINVAL; + } + pieces->build = 0; + pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size); + pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); + pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); + pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size); + src = ucode->u.v1.data; + break; + } + + /* Verify size of file vs. image size info in file's header */ + if (ucode_raw->size != hdr_size + pieces->inst_size + + pieces->data_size + pieces->init_size + + pieces->init_data_size) { + + IWL_ERR(priv, + "uCode file size %d does not match expected size\n", + (int)ucode_raw->size); + return -EINVAL; + } + + pieces->inst = src; + src += pieces->inst_size; + pieces->data = src; + src += pieces->data_size; + pieces->init = src; + src += pieces->init_size; + pieces->init_data = src; + src += pieces->init_data_size; + + return 0; +} + +static int iwlagn_load_firmware(struct iwl_priv *priv, + const struct firmware *ucode_raw, + struct iwlagn_firmware_pieces *pieces, + struct iwlagn_ucode_capabilities *capa) +{ + struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data; + struct iwl_ucode_tlv *tlv; + size_t len = ucode_raw->size; + const u8 *data; + int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative; + int tmp; + u64 alternatives; + u32 tlv_len; + enum iwl_ucode_tlv_type tlv_type; + const u8 *tlv_data; + + if (len < sizeof(*ucode)) { + IWL_ERR(priv, "uCode has invalid length: %zd\n", len); + return -EINVAL; + } + + if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) { + IWL_ERR(priv, "invalid uCode magic: 0X%x\n", + le32_to_cpu(ucode->magic)); + return -EINVAL; + } + + /* + * Check which alternatives are present, and "downgrade" + * when the chosen alternative is not present, warning + * the user when that happens. Some files may not have + * any alternatives, so don't warn in that case. + */ + alternatives = le64_to_cpu(ucode->alternatives); + tmp = wanted_alternative; + if (wanted_alternative > 63) + wanted_alternative = 63; + while (wanted_alternative && !(alternatives & BIT(wanted_alternative))) + wanted_alternative--; + if (wanted_alternative && wanted_alternative != tmp) + IWL_WARN(priv, + "uCode alternative %d not available, choosing %d\n", + tmp, wanted_alternative); + + priv->ucode_ver = le32_to_cpu(ucode->ver); + pieces->build = le32_to_cpu(ucode->build); + data = ucode->data; + + len -= sizeof(*ucode); + + while (len >= sizeof(*tlv)) { + u16 tlv_alt; + + len -= sizeof(*tlv); + tlv = (void *)data; + + tlv_len = le32_to_cpu(tlv->length); + tlv_type = le16_to_cpu(tlv->type); + tlv_alt = le16_to_cpu(tlv->alternative); + tlv_data = tlv->data; + + if (len < tlv_len) { + IWL_ERR(priv, "invalid TLV len: %zd/%u\n", + len, tlv_len); + return -EINVAL; + } + len -= ALIGN(tlv_len, 4); + data += sizeof(*tlv) + ALIGN(tlv_len, 4); + + /* + * Alternative 0 is always valid. + * + * Skip alternative TLVs that are not selected. + */ + if (tlv_alt != 0 && tlv_alt != wanted_alternative) + continue; + + switch (tlv_type) { + case IWL_UCODE_TLV_INST: + pieces->inst = tlv_data; + pieces->inst_size = tlv_len; + break; + case IWL_UCODE_TLV_DATA: + pieces->data = tlv_data; + pieces->data_size = tlv_len; + break; + case IWL_UCODE_TLV_INIT: + pieces->init = tlv_data; + pieces->init_size = tlv_len; + break; + case IWL_UCODE_TLV_INIT_DATA: + pieces->init_data = tlv_data; + pieces->init_data_size = tlv_len; + break; + case IWL_UCODE_TLV_BOOT: + IWL_ERR(priv, "Found unexpected BOOT ucode\n"); + break; + case IWL_UCODE_TLV_PROBE_MAX_LEN: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + capa->max_probe_length = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_PAN: + if (tlv_len) + goto invalid_tlv_len; + capa->flags |= IWL_UCODE_TLV_FLAGS_PAN; + break; + case IWL_UCODE_TLV_FLAGS: + /* must be at least one u32 */ + if (tlv_len < sizeof(u32)) + goto invalid_tlv_len; + /* and a proper number of u32s */ + if (tlv_len % sizeof(u32)) + goto invalid_tlv_len; + /* + * This driver only reads the first u32 as + * right now no more features are defined, + * if that changes then either the driver + * will not work with the new firmware, or + * it'll not take advantage of new features. + */ + capa->flags = le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_INIT_EVTLOG_PTR: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_evtlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_evtlog_size = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_INIT_ERRLOG_PTR: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_errlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_evtlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_evtlog_size = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_errlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_ENHANCE_SENS_TBL: + if (tlv_len) + goto invalid_tlv_len; + priv->enhance_sensitivity_table = true; + break; + case IWL_UCODE_TLV_WOWLAN_INST: + pieces->wowlan_inst = tlv_data; + pieces->wowlan_inst_size = tlv_len; + break; + case IWL_UCODE_TLV_WOWLAN_DATA: + pieces->wowlan_data = tlv_data; + pieces->wowlan_data_size = tlv_len; + break; + case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + capa->standard_phy_calibration_size = + le32_to_cpup((__le32 *)tlv_data); + break; + default: + IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type); + break; + } + } + + if (len) { + IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len); + iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len); + return -EINVAL; + } + + return 0; + + invalid_tlv_len: + IWL_ERR(priv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len); + iwl_print_hex_dump(priv, IWL_DL_FW, tlv_data, tlv_len); + + return -EINVAL; +} + +/** + * iwl_ucode_callback - callback when firmware was loaded + * + * If loaded successfully, copies the firmware into buffers + * for the card to fetch (via DMA). + */ +static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) +{ + struct iwl_priv *priv = context; + struct iwl_ucode_header *ucode; + int err; + struct iwlagn_firmware_pieces pieces; + const unsigned int api_max = cfg(priv)->ucode_api_max; + unsigned int api_ok = cfg(priv)->ucode_api_ok; + const unsigned int api_min = cfg(priv)->ucode_api_min; + u32 api_ver; + char buildstr[25]; + u32 build; + struct iwlagn_ucode_capabilities ucode_capa = { + .max_probe_length = 200, + .standard_phy_calibration_size = + IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE, + }; + + if (!api_ok) + api_ok = api_max; + + memset(&pieces, 0, sizeof(pieces)); + + if (!ucode_raw) { + if (priv->fw_index <= api_ok) + IWL_ERR(priv, + "request for firmware file '%s' failed.\n", + priv->firmware_name); + goto try_again; + } + + IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", + priv->firmware_name, ucode_raw->size); + + /* Make sure that we got at least the API version number */ + if (ucode_raw->size < 4) { + IWL_ERR(priv, "File size way too small!\n"); + goto try_again; + } + + /* Data from ucode file: header followed by uCode images */ + ucode = (struct iwl_ucode_header *)ucode_raw->data; + + if (ucode->ver) + err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces); + else + err = iwlagn_load_firmware(priv, ucode_raw, &pieces, + &ucode_capa); + + if (err) + goto try_again; + + api_ver = IWL_UCODE_API(priv->ucode_ver); + build = pieces.build; + + /* + * api_ver should match the api version forming part of the + * firmware filename ... but we don't check for that and only rely + * on the API version read from firmware header from here on forward + */ + /* no api version check required for experimental uCode */ + if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) { + if (api_ver < api_min || api_ver > api_max) { + IWL_ERR(priv, + "Driver unable to support your firmware API. " + "Driver supports v%u, firmware is v%u.\n", + api_max, api_ver); + goto try_again; + } + + if (api_ver < api_ok) { + if (api_ok != api_max) + IWL_ERR(priv, "Firmware has old API version, " + "expected v%u through v%u, got v%u.\n", + api_ok, api_max, api_ver); + else + IWL_ERR(priv, "Firmware has old API version, " + "expected v%u, got v%u.\n", + api_max, api_ver); + IWL_ERR(priv, "New firmware can be obtained from " + "http://www.intellinuxwireless.org/.\n"); + } + } + + if (build) + sprintf(buildstr, " build %u%s", build, + (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) + ? " (EXP)" : ""); + else + buildstr[0] = '\0'; + + IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u%s\n", + IWL_UCODE_MAJOR(priv->ucode_ver), + IWL_UCODE_MINOR(priv->ucode_ver), + IWL_UCODE_API(priv->ucode_ver), + IWL_UCODE_SERIAL(priv->ucode_ver), + buildstr); + + snprintf(priv->hw->wiphy->fw_version, + sizeof(priv->hw->wiphy->fw_version), + "%u.%u.%u.%u%s", + IWL_UCODE_MAJOR(priv->ucode_ver), + IWL_UCODE_MINOR(priv->ucode_ver), + IWL_UCODE_API(priv->ucode_ver), + IWL_UCODE_SERIAL(priv->ucode_ver), + buildstr); + + /* + * For any of the failures below (before allocating pci memory) + * we will try to load a version with a smaller API -- maybe the + * user just got a corrupted version of the latest API. + */ + + IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", + priv->ucode_ver); + IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n", + pieces.inst_size); + IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n", + pieces.data_size); + IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n", + pieces.init_size); + IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n", + pieces.init_data_size); + + /* Verify that uCode images will fit in card's SRAM */ + if (pieces.inst_size > hw_params(priv).max_inst_size) { + IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n", + pieces.inst_size); + goto try_again; + } + + if (pieces.data_size > hw_params(priv).max_data_size) { + IWL_ERR(priv, "uCode data len %Zd too large to fit in\n", + pieces.data_size); + goto try_again; + } + + if (pieces.init_size > hw_params(priv).max_inst_size) { + IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n", + pieces.init_size); + goto try_again; + } + + if (pieces.init_data_size > hw_params(priv).max_data_size) { + IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n", + pieces.init_data_size); + goto try_again; + } + + /* Allocate ucode buffers for card's bus-master loading ... */ + + /* Runtime instructions and 2 copies of data: + * 1) unmodified from disk + * 2) backup cache for save/restore during power-downs */ + if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.code, + pieces.inst, pieces.inst_size)) + goto err_pci_alloc; + if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.data, + pieces.data, pieces.data_size)) + goto err_pci_alloc; + + /* Initialization instructions and data */ + if (pieces.init_size && pieces.init_data_size) { + if (iwl_alloc_fw_desc(trans(priv), + &trans(priv)->ucode_init.code, + pieces.init, pieces.init_size)) + goto err_pci_alloc; + if (iwl_alloc_fw_desc(trans(priv), + &trans(priv)->ucode_init.data, + pieces.init_data, pieces.init_data_size)) + goto err_pci_alloc; + } + + /* WoWLAN instructions and data */ + if (pieces.wowlan_inst_size && pieces.wowlan_data_size) { + if (iwl_alloc_fw_desc(trans(priv), + &trans(priv)->ucode_wowlan.code, + pieces.wowlan_inst, + pieces.wowlan_inst_size)) + goto err_pci_alloc; + if (iwl_alloc_fw_desc(trans(priv), + &trans(priv)->ucode_wowlan.data, + pieces.wowlan_data, + pieces.wowlan_data_size)) + goto err_pci_alloc; + } + + /* Now that we can no longer fail, copy information */ + + /* + * The (size - 16) / 12 formula is based on the information recorded + * for each event, which is of mode 1 (including timestamp) for all + * new microcodes that include this information. + */ + priv->init_evtlog_ptr = pieces.init_evtlog_ptr; + if (pieces.init_evtlog_size) + priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; + else + priv->init_evtlog_size = + cfg(priv)->base_params->max_event_log_size; + priv->init_errlog_ptr = pieces.init_errlog_ptr; + priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr; + if (pieces.inst_evtlog_size) + priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; + else + priv->inst_evtlog_size = + cfg(priv)->base_params->max_event_log_size; + priv->inst_errlog_ptr = pieces.inst_errlog_ptr; +#ifndef CONFIG_IWLWIFI_P2P + ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN; +#endif + + priv->new_scan_threshold_behaviour = + !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); + + if (!(cfg(priv)->sku & EEPROM_SKU_CAP_IPAN_ENABLE)) + ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN; + + /* + * if not PAN, then don't support P2P -- might be a uCode + * packaging bug or due to the eeprom check above + */ + if (!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) + ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P; + + if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { + priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; + priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; + } else { + priv->sta_key_max_num = STA_KEY_MAX_NUM; + priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + } + /* + * figure out the offset of chain noise reset and gain commands + * base on the size of standard phy calibration commands table size + */ + if (ucode_capa.standard_phy_calibration_size > + IWL_MAX_PHY_CALIBRATE_TBL_SIZE) + ucode_capa.standard_phy_calibration_size = + IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE; + + priv->phy_calib_chain_noise_reset_cmd = + ucode_capa.standard_phy_calibration_size; + priv->phy_calib_chain_noise_gain_cmd = + ucode_capa.standard_phy_calibration_size + 1; + + /* initialize all valid contexts */ + iwl_init_context(priv, ucode_capa.flags); + + /************************************************** + * This is still part of probe() in a sense... + * + * 9. Setup and register with mac80211 and debugfs + **************************************************/ + err = iwlagn_mac_setup_register(priv, &ucode_capa); + if (err) + goto out_unbind; + + err = iwl_dbgfs_register(priv, DRV_NAME); + if (err) + IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); + + /* We have our copies now, allow OS release its copies */ + release_firmware(ucode_raw); + complete(&priv->firmware_loading_complete); + return; + + try_again: + /* try next, if any */ + if (iwl_request_firmware(priv, false)) + goto out_unbind; + release_firmware(ucode_raw); + return; + + err_pci_alloc: + IWL_ERR(priv, "failed to allocate pci memory\n"); + iwl_dealloc_ucode(trans(priv)); + out_unbind: + complete(&priv->firmware_loading_complete); + device_release_driver(trans(priv)->dev); + release_firmware(ucode_raw); +} + diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.h b/drivers/net/wireless/iwlwifi/iwl-ucode.h new file mode 100644 index 00000000000..eccf92519a8 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.h @@ -0,0 +1,178 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef __iwl_ucode_h__ +#define __iwl_ucode_h__ + +/* v1/v2 uCode file layout */ +struct iwl_ucode_header { + __le32 ver; /* major/minor/API/serial */ + union { + struct { + __le32 inst_size; /* bytes of runtime code */ + __le32 data_size; /* bytes of runtime data */ + __le32 init_size; /* bytes of init code */ + __le32 init_data_size; /* bytes of init data */ + __le32 boot_size; /* bytes of bootstrap code */ + u8 data[0]; /* in same order as sizes */ + } v1; + struct { + __le32 build; /* build number */ + __le32 inst_size; /* bytes of runtime code */ + __le32 data_size; /* bytes of runtime data */ + __le32 init_size; /* bytes of init code */ + __le32 init_data_size; /* bytes of init data */ + __le32 boot_size; /* bytes of bootstrap code */ + u8 data[0]; /* in same order as sizes */ + } v2; + } u; +}; + +/* + * new TLV uCode file layout + * + * The new TLV file format contains TLVs, that each specify + * some piece of data. To facilitate "groups", for example + * different instruction image with different capabilities, + * bundled with the same init image, an alternative mechanism + * is provided: + * When the alternative field is 0, that means that the item + * is always valid. When it is non-zero, then it is only + * valid in conjunction with items of the same alternative, + * in which case the driver (user) selects one alternative + * to use. + */ + +enum iwl_ucode_tlv_type { + IWL_UCODE_TLV_INVALID = 0, /* unused */ + IWL_UCODE_TLV_INST = 1, + IWL_UCODE_TLV_DATA = 2, + IWL_UCODE_TLV_INIT = 3, + IWL_UCODE_TLV_INIT_DATA = 4, + IWL_UCODE_TLV_BOOT = 5, + IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ + IWL_UCODE_TLV_PAN = 7, + IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8, + IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, + IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, + IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, + IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, + IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, + IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, + IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, + IWL_UCODE_TLV_WOWLAN_INST = 16, + IWL_UCODE_TLV_WOWLAN_DATA = 17, + IWL_UCODE_TLV_FLAGS = 18, +}; + +/** + * enum iwl_ucode_tlv_flag - ucode API flags + * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously + * was a separate TLV but moved here to save space. + * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID, + * treats good CRC threshold as a boolean + * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). + * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. + */ +enum iwl_ucode_tlv_flag { + IWL_UCODE_TLV_FLAGS_PAN = BIT(0), + IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), + IWL_UCODE_TLV_FLAGS_MFP = BIT(2), + IWL_UCODE_TLV_FLAGS_P2P = BIT(3), +}; + +struct iwl_ucode_tlv { + __le16 type; /* see above */ + __le16 alternative; /* see comment */ + __le32 length; /* not including type/length fields */ + u8 data[0]; +}; + +#define IWL_TLV_UCODE_MAGIC 0x0a4c5749 + +struct iwl_tlv_ucode_header { + /* + * The TLV style ucode header is distinguished from + * the v1/v2 style header by first four bytes being + * zero, as such is an invalid combination of + * major/minor/API/serial versions. + */ + __le32 zero; + __le32 magic; + u8 human_readable[64]; + __le32 ver; /* major/minor/API/serial */ + __le32 build; + __le64 alternatives; /* bitmask of valid alternatives */ + /* + * The data contained herein has a TLV layout, + * see above for the TLV header and types. + * Note that each TLV is padded to a length + * that is a multiple of 4 for alignment. + */ + u8 data[0]; +}; + +struct iwl_priv; + +int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first); + +#endif /* __iwl_ucode_h__ */ -- cgit v1.2.3 From f057ac4ed77d3390b517ee2be8e88615b9994272 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 29 Jan 2012 18:36:01 -0800 Subject: iwlwifi: release IRQ in error path smatch correctly complains: iwl-trans-pcie.c +1528 iwl_trans_pcie_start_hw(50) warn: 'trans->irq' was not released on error Fix it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi W Guy --- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index ec26950ebb5..836caf9c68b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1504,7 +1504,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) err = iwl_prepare_card_hw(trans); if (err) { IWL_ERR(trans, "Error while preparing HW: %d", err); - goto error; + goto err_free_irq; } iwl_apm_init(trans); @@ -1522,6 +1522,8 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) return err; +err_free_irq: + free_irq(trans->irq, trans); error: iwl_free_isr_ict(trans); tasklet_kill(&trans_pcie->irq_tasklet); -- cgit v1.2.3 From 6fe7dd0db0af18a8792d8551fd19a184f39a732c Mon Sep 17 00:00:00 2001 From: Amit Beka Date: Wed, 25 Jan 2012 09:19:24 +0200 Subject: iwlwifi: range check to testmode direct reg access Added a check on the direct register access. Checks that the address is in the lower ragnge (0x0-0x2000), which belongs to CSR, HBUS and FH registers. Signed-off-by: Amit Beka Signed-off-by: Wey-Yi W Guy --- drivers/net/wireless/iwlwifi/iwl-testmode.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 7c17b9d5217..df7ab332c83 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -79,6 +79,7 @@ #include "iwl-testmode.h" #include "iwl-trans.h" #include "iwl-bus.h" +#include "iwl-fh.h" /* The TLVs used in the gnl message policy between the kernel module and * user space application. iwl_testmode_gnl_msg_policy is to be carried @@ -288,7 +289,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) { struct iwl_priv *priv = hw->priv; - u32 ofs, val32; + u32 ofs, val32, cmd; u8 val8; struct sk_buff *skb; int status = 0; @@ -300,7 +301,20 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]); IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs); - switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { + /* Allow access only to FH/CSR/HBUS in direct mode. + Since we don't have the upper bounds for the CSR and HBUS segments, + we will use only the upper bound of FH for sanity check. */ + cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); + if ((cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32 || + cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32 || + cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8) && + (ofs >= FH_MEM_UPPER_BOUND)) { + IWL_DEBUG_INFO(priv, "offset out of segment (0x0 - 0x%x)\n", + FH_MEM_UPPER_BOUND); + return -EINVAL; + } + + switch (cmd) { case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: val32 = iwl_read_direct32(trans(priv), ofs); IWL_INFO(priv, "32bit value to read 0x%x\n", val32); -- cgit v1.2.3 From c8987876e9bf9b7b83e75b325586bc77ea8ac825 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:17 +0100 Subject: mac80211: move managed mode station state modification Move the station state modification right before insert, this just makes the current code more readable (you can tell that it's before insertion looking at a single screenful of code) right now, but some upcoming changes will require this. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 49fd1acd5d1..40b929d57a9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1587,20 +1587,6 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, return false; } - err = sta_info_move_state(sta, IEEE80211_STA_AUTH); - if (!err) - err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); - if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) - err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); - if (err) { - printk(KERN_DEBUG - "%s: failed to move station %pM to desired state\n", - sdata->name, sta->sta.addr); - WARN_ON(__sta_info_destroy(sta)); - mutex_unlock(&sdata->local->sta_mtx); - return false; - } - rates = 0; basic_rates = 0; sband = local->hw.wiphy->bands[wk->chan->band]; @@ -1648,6 +1634,20 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, if (elems.wmm_param) set_sta_flag(sta, WLAN_STA_WME); + err = sta_info_move_state(sta, IEEE80211_STA_AUTH); + if (!err) + err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); + if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) + err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); + if (err) { + printk(KERN_DEBUG + "%s: failed to move station %pM to desired state\n", + sdata->name, sta->sta.addr); + WARN_ON(__sta_info_destroy(sta)); + mutex_unlock(&sdata->local->sta_mtx); + return false; + } + /* sta_info_reinsert will also unlock the mutex lock */ err = sta_info_reinsert(sta); sta = NULL; -- cgit v1.2.3 From 077f49392819608084c6d8d20e3dcca230afe07d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:18 +0100 Subject: mac80211: simplify AP_VLAN handling Setting keys and updating TKIP keys must use the BSS sdata (not AP_VLAN), so we translate. Move the translation into driver-ops wrappers instead of having it inline in the code to simplify the normal code flow. The same can be done for sta_add/remove which already does the translation in the wrapper. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/driver-ops.h | 2 ++ net/mac80211/key.c | 8 -------- net/mac80211/pm.c | 11 ++--------- net/mac80211/sta_info.c | 8 +------- net/mac80211/util.c | 11 ++--------- 5 files changed, 7 insertions(+), 33 deletions(-) diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index e8960ae3986..b8673f6100d 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -253,6 +253,7 @@ static inline int drv_set_key(struct ieee80211_local *local, might_sleep(); + sdata = get_bss_sdata(sdata); check_sdata_in_driver(sdata); trace_drv_set_key(local, cmd, sdata, sta, key); @@ -272,6 +273,7 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, if (sta) ista = &sta->sta; + sdata = get_bss_sdata(sdata); check_sdata_in_driver(sdata); trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 87a89741432..94f02b577d4 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -123,9 +123,6 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) */ if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) goto out_unsupported; - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); } ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); @@ -187,11 +184,6 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))) increment_tailroom_need_count(sdata); - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); - ret = drv_set_key(key->local, DISABLE_KEY, sdata, sta, &key->conf); diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 596efaf50e0..c65ff471acc 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -97,15 +97,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) /* tear down aggregation sessions and remove STAs */ mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { - if (sta->uploaded) { - sdata = sta->sdata; - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); - - drv_sta_remove(local, sdata, &sta->sta); - } + if (sta->uploaded) + drv_sta_remove(local, sta->sdata, &sta->sta); mesh_plink_quiesce(sta); } diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index fa0823892b2..8e1e361c223 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -764,14 +764,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta) } } - if (sta->uploaded) { - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); + if (sta->uploaded) drv_sta_remove(local, sdata, &sta->sta); - sdata = sta->sdata; - } /* * At this point, after we wait for an RCU grace period, diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d82d886d086..d4966e88aa4 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1184,15 +1184,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) /* add STAs back */ mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { - if (sta->uploaded) { - sdata = sta->sdata; - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); - - WARN_ON(drv_sta_add(local, sdata, &sta->sta)); - } + if (sta->uploaded) + WARN_ON(drv_sta_add(local, sta->sdata, &sta->sta)); } mutex_unlock(&local->sta_mtx); -- cgit v1.2.3 From 89c91caeccf45bbeb86104445125fe1eaec12079 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:19 +0100 Subject: mac80211: dont program keys for stations not uploaded If a station couldn't be uploaded to the driver but is still kept (only in IBSS mode) we still shouldn't try to program the keys for it into hardware; fix this bug by skipping the key upload in this case. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/key.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 94f02b577d4..e8616b3ff63 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -54,14 +54,6 @@ static void assert_key_lock(struct ieee80211_local *local) lockdep_assert_held(&local->key_mtx); } -static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) -{ - if (key->sta) - return &key->sta->sta; - - return NULL; -} - static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) { /* @@ -95,7 +87,7 @@ static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata) static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) { struct ieee80211_sub_if_data *sdata; - struct ieee80211_sta *sta; + struct sta_info *sta; int ret; might_sleep(); @@ -105,7 +97,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) assert_key_lock(key->local); - sta = get_sta_for_key(key); + sta = key->sta; /* * If this is a per-STA GTK, check if it @@ -115,6 +107,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) !(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK)) goto out_unsupported; + if (sta && !sta->uploaded) + goto out_unsupported; + sdata = key->sdata; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { /* @@ -125,7 +120,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) goto out_unsupported; } - ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); + ret = drv_set_key(key->local, SET_KEY, sdata, + sta ? &sta->sta : NULL, &key->conf); if (!ret) { key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; @@ -144,7 +140,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) if (ret != -ENOSPC && ret != -EOPNOTSUPP) wiphy_err(key->local->hw.wiphy, "failed to set key (%d, %pM) to hardware (%d)\n", - key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); + key->conf.keyidx, + sta ? sta->sta.addr : bcast_addr, ret); out_unsupported: switch (key->conf.cipher) { @@ -163,7 +160,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) { struct ieee80211_sub_if_data *sdata; - struct ieee80211_sta *sta; + struct sta_info *sta; int ret; might_sleep(); @@ -176,7 +173,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) return; - sta = get_sta_for_key(key); + sta = key->sta; sdata = key->sdata; if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) || @@ -185,12 +182,13 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) increment_tailroom_need_count(sdata); ret = drv_set_key(key->local, DISABLE_KEY, sdata, - sta, &key->conf); + sta ? &sta->sta : NULL, &key->conf); if (ret) wiphy_err(key->local->hw.wiphy, "failed to remove key (%d, %pM) from hardware (%d)\n", - key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); + key->conf.keyidx, + sta ? sta->sta.addr : bcast_addr, ret); key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; } -- cgit v1.2.3 From 71ec375c75095002f36f083ceb32bbb8725734ae Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:20 +0100 Subject: mac80211: add NOTEXIST station state This will be used by drivers later if they need to have stations inserted all the time, in mac80211 has no purpose, is never used and sta_state starts out in NONE. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/sta_info.c | 2 ++ net/mac80211/sta_info.h | 1 + 2 files changed, 3 insertions(+) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 8e1e361c223..464bc691644 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -293,6 +293,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, sta->sdata = sdata; sta->last_rx = jiffies; + sta->sta_state = IEEE80211_STA_NONE; + do_posix_clock_monotonic_gettime(&uptime); sta->last_connected = uptime.tv_sec; ewma_init(&sta->avg_signal, 1024, 8); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 381de37d247..da4b03c1c3b 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -77,6 +77,7 @@ enum ieee80211_sta_info_flags { enum ieee80211_sta_state { /* NOTE: These need to be ordered correctly! */ + IEEE80211_STA_NOTEXIST, IEEE80211_STA_NONE, IEEE80211_STA_AUTH, IEEE80211_STA_ASSOC, -- cgit v1.2.3 From f09603a259ffef69ad4516a04eb06cd65ac522fe Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:21 +0100 Subject: mac80211: add sta_state callback (based on Eliad's patch) Add a callback to notify the low-level driver whenever the state of a station changes. The driver is only notified when the station is actually in the mac80211 hash table, not for pre-insert state transitions. To allow the driver to replace sta_add/remove calls with this, call extra transitions with the NOTEXIST state. This callback can fail, so we need to be careful in handling it when a station is inserted, particularly in the IBSS case where we still keep the station entry around for mac80211 purposes. Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 30 +++++++++++++ net/mac80211/driver-ops.h | 22 +++++++++ net/mac80211/driver-trace.h | 32 +++++++++++++ net/mac80211/main.c | 3 ++ net/mac80211/pm.c | 10 ++++- net/mac80211/sta_info.c | 106 +++++++++++++++++++++++++++++++++++++------- net/mac80211/sta_info.h | 9 ---- net/mac80211/util.c | 10 ++++- 8 files changed, 194 insertions(+), 28 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 520eb4c5e5a..922313f0b39 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -981,6 +981,25 @@ enum set_key_cmd { SET_KEY, DISABLE_KEY, }; +/** + * enum ieee80211_sta_state - station state + * + * @IEEE80211_STA_NOTEXIST: station doesn't exist at all, + * this is a special state for add/remove transitions + * @IEEE80211_STA_NONE: station exists without special state + * @IEEE80211_STA_AUTH: station is authenticated + * @IEEE80211_STA_ASSOC: station is associated + * @IEEE80211_STA_AUTHORIZED: station is authorized (802.1X) + */ +enum ieee80211_sta_state { + /* NOTE: These need to be ordered correctly! */ + IEEE80211_STA_NOTEXIST, + IEEE80211_STA_NONE, + IEEE80211_STA_AUTH, + IEEE80211_STA_ASSOC, + IEEE80211_STA_AUTHORIZED, +}; + /** * struct ieee80211_sta - station table entry * @@ -1974,6 +1993,13 @@ enum ieee80211_frame_release_type { * in AP mode, this callback will not be called when the flag * %IEEE80211_HW_AP_LINK_PS is set. Must be atomic. * + * @sta_state: Notifies low level driver about state transition of a + * station (which can be the AP, a client, IBSS/WDS/mesh peer etc.) + * This callback is mutually exclusive with @sta_add/@sta_remove. + * It must not fail for down transitions but may fail for transitions + * up the list of states. + * The callback can sleep. + * * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), * bursting) for a hardware TX queue. * Returns a negative error code on failure. @@ -2193,6 +2219,10 @@ struct ieee80211_ops { struct ieee80211_sta *sta); void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd, struct ieee80211_sta *sta); + int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + enum ieee80211_sta_state old_state, + enum ieee80211_sta_state new_state); int (*conf_tx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index b8673f6100d..4bd266ec533 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -478,6 +478,28 @@ static inline void drv_sta_remove(struct ieee80211_local *local, trace_drv_return_void(local); } +static inline __must_check +int drv_sta_state(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta, + enum ieee80211_sta_state old_state, + enum ieee80211_sta_state new_state) +{ + int ret = 0; + + might_sleep(); + + sdata = get_bss_sdata(sdata); + check_sdata_in_driver(sdata); + + trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); + if (local->ops->sta_state) + ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta, + old_state, new_state); + trace_drv_return_int(local, ret); + return ret; +} + static inline int drv_conf_tx(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, u16 queue, const struct ieee80211_tx_queue_params *params) diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 6e9df8fd8fb..384e2f08c18 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -635,6 +635,38 @@ TRACE_EVENT(drv_sta_notify, ) ); +TRACE_EVENT(drv_sta_state, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta, + enum ieee80211_sta_state old_state, + enum ieee80211_sta_state new_state), + + TP_ARGS(local, sdata, sta, old_state, new_state), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + STA_ENTRY + __field(u32, old_state) + __field(u32, new_state) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + STA_ASSIGN; + __entry->old_state = old_state; + __entry->new_state = new_state; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " state: %d->%d", + LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, + __entry->old_state, __entry->new_state + ) +); + TRACE_EVENT(drv_sta_add, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6192caadfab..f4fc540aac1 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -535,6 +535,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, int priv_size, i; struct wiphy *wiphy; + if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove))) + return NULL; + /* Ensure 32-byte alignment of our private data and hw private data. * We use the wiphy priv data for both our ieee80211_local and for * the driver's private data diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index c65ff471acc..af49ac4f082 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -97,9 +97,17 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) /* tear down aggregation sessions and remove STAs */ mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { - if (sta->uploaded) + if (sta->uploaded) { + enum ieee80211_sta_state state; + drv_sta_remove(local, sta->sdata, &sta->sta); + state = sta->sta_state; + for (; state > IEEE80211_STA_NOTEXIST; state--) + WARN_ON(drv_sta_state(local, sdata, sta, + state, state - 1)); + } + mesh_plink_quiesce(sta); } mutex_unlock(&local->sta_mtx); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 464bc691644..fcd9027c669 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -351,6 +351,38 @@ static int sta_info_insert_check(struct sta_info *sta) return 0; } +static int sta_info_insert_drv_state(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta) +{ + enum ieee80211_sta_state state; + int err = 0; + + for (state = IEEE80211_STA_NOTEXIST; state < sta->sta_state; state++) { + err = drv_sta_state(local, sdata, sta, state, state + 1); + if (err) + break; + } + + if (!err) { + sta->uploaded = true; + return 0; + } + + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { + printk(KERN_DEBUG + "%s: failed to move IBSS STA %pM to state %d (%d) - keeping it anyway.\n", + sdata->name, sta->sta.addr, state + 1, err); + err = 0; + } + + /* unwind on error */ + for (; state > IEEE80211_STA_NOTEXIST; state--) + WARN_ON(drv_sta_state(local, sdata, sta, state, state - 1)); + + return err; +} + /* * should be called with sta_mtx locked * this function replaces the mutex lock @@ -392,8 +424,11 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " "driver (%d) - keeping it anyway.\n", sdata->name, sta->sta.addr, err); - } else - sta->uploaded = true; + } else { + err = sta_info_insert_drv_state(local, sdata, sta); + if (err) + goto out_err; + } } if (!dummy_reinsert) { @@ -759,15 +794,19 @@ int __must_check __sta_info_destroy(struct sta_info *sta) RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); while (sta->sta_state > IEEE80211_STA_NONE) { - int err = sta_info_move_state(sta, sta->sta_state - 1); - if (err) { + ret = sta_info_move_state(sta, sta->sta_state - 1); + if (ret) { WARN_ON_ONCE(1); break; } } - if (sta->uploaded) + if (sta->uploaded) { drv_sta_remove(local, sdata, &sta->sta); + ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE, + IEEE80211_STA_NOTEXIST); + WARN_ON_ONCE(ret != 0); + } /* * At this point, after we wait for an RCU grace period, @@ -1404,20 +1443,58 @@ int sta_info_move_state(struct sta_info *sta, if (sta->sta_state == new_state) return 0; + /* check allowed transitions first */ + + switch (new_state) { + case IEEE80211_STA_NONE: + if (sta->sta_state != IEEE80211_STA_AUTH) + return -EINVAL; + break; + case IEEE80211_STA_AUTH: + if (sta->sta_state != IEEE80211_STA_NONE && + sta->sta_state != IEEE80211_STA_ASSOC) + return -EINVAL; + break; + case IEEE80211_STA_ASSOC: + if (sta->sta_state != IEEE80211_STA_AUTH && + sta->sta_state != IEEE80211_STA_AUTHORIZED) + return -EINVAL; + break; + case IEEE80211_STA_AUTHORIZED: + if (sta->sta_state != IEEE80211_STA_ASSOC) + return -EINVAL; + break; + default: + WARN(1, "invalid state %d", new_state); + return -EINVAL; + } + + printk(KERN_DEBUG "%s: moving STA %pM to state %d\n", + sta->sdata->name, sta->sta.addr, new_state); + + /* + * notify the driver before the actual changes so it can + * fail the transition + */ + if (test_sta_flag(sta, WLAN_STA_INSERTED)) { + int err = drv_sta_state(sta->local, sta->sdata, sta, + sta->sta_state, new_state); + if (err) + return err; + } + + /* reflect the change in all state variables */ + switch (new_state) { case IEEE80211_STA_NONE: if (sta->sta_state == IEEE80211_STA_AUTH) clear_bit(WLAN_STA_AUTH, &sta->_flags); - else - return -EINVAL; break; case IEEE80211_STA_AUTH: if (sta->sta_state == IEEE80211_STA_NONE) set_bit(WLAN_STA_AUTH, &sta->_flags); else if (sta->sta_state == IEEE80211_STA_ASSOC) clear_bit(WLAN_STA_ASSOC, &sta->_flags); - else - return -EINVAL; break; case IEEE80211_STA_ASSOC: if (sta->sta_state == IEEE80211_STA_AUTH) { @@ -1426,24 +1503,19 @@ int sta_info_move_state(struct sta_info *sta, if (sta->sdata->vif.type == NL80211_IFTYPE_AP) atomic_dec(&sta->sdata->u.ap.num_sta_authorized); clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags); - } else - return -EINVAL; + } break; case IEEE80211_STA_AUTHORIZED: if (sta->sta_state == IEEE80211_STA_ASSOC) { if (sta->sdata->vif.type == NL80211_IFTYPE_AP) atomic_inc(&sta->sdata->u.ap.num_sta_authorized); set_bit(WLAN_STA_AUTHORIZED, &sta->_flags); - } else - return -EINVAL; + } break; default: - WARN(1, "invalid state %d", new_state); - return -EINVAL; + break; } - printk(KERN_DEBUG "%s: moving STA %pM to state %d\n", - sta->sdata->name, sta->sta.addr, new_state); sta->sta_state = new_state; return 0; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index da4b03c1c3b..2ee80886000 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -75,15 +75,6 @@ enum ieee80211_sta_info_flags { WLAN_STA_INSERTED, }; -enum ieee80211_sta_state { - /* NOTE: These need to be ordered correctly! */ - IEEE80211_STA_NOTEXIST, - IEEE80211_STA_NONE, - IEEE80211_STA_AUTH, - IEEE80211_STA_ASSOC, - IEEE80211_STA_AUTHORIZED, -}; - #define STA_TID_NUM 16 #define ADDBA_RESP_INTERVAL HZ #define HT_AGG_MAX_RETRIES 15 diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d4966e88aa4..8f8b4ecc776 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1184,8 +1184,16 @@ int ieee80211_reconfig(struct ieee80211_local *local) /* add STAs back */ mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { - if (sta->uploaded) + if (sta->uploaded) { + enum ieee80211_sta_state state; + WARN_ON(drv_sta_add(local, sta->sdata, &sta->sta)); + + for (state = IEEE80211_STA_NOTEXIST; + state < sta->sta_state - 1; state++) + WARN_ON(drv_sta_state(local, sta->sdata, sta, + state, state + 1)); + } } mutex_unlock(&local->sta_mtx); -- cgit v1.2.3 From a4ec45a421b80bc36fd37578accf081f32527a7f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:22 +0100 Subject: mac80211: implement sta_add/sta_remove in sta_state Instead of maintaining separate sta_add/sta_remove callsites, implement it in sta_state when the driver has no sta_state implementation. The only behavioural change this should cause is in secure mesh mode: with this the station entries will only be created after the stations are set to AUTH. Given which drivers support mesh, this seems to not be a problem. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/driver-ops.h | 11 ++++++++++- net/mac80211/pm.c | 2 -- net/mac80211/sta_info.c | 23 +++++++++-------------- net/mac80211/util.c | 2 -- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 4bd266ec533..70dfb6415c2 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -493,9 +493,18 @@ int drv_sta_state(struct ieee80211_local *local, check_sdata_in_driver(sdata); trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); - if (local->ops->sta_state) + if (local->ops->sta_state) { ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta, old_state, new_state); + } else if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC) { + ret = drv_sta_add(local, sdata, &sta->sta); + if (ret == 0) + sta->uploaded = true; + } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTH) { + drv_sta_remove(local, sdata, &sta->sta); + } trace_drv_return_int(local, ret); return ret; } diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index af49ac4f082..2b53a5348ac 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -100,8 +100,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) if (sta->uploaded) { enum ieee80211_sta_state state; - drv_sta_remove(local, sta->sdata, &sta->sta); - state = sta->sta_state; for (; state > IEEE80211_STA_NOTEXIST; state--) WARN_ON(drv_sta_state(local, sdata, sta, diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index fcd9027c669..5e577bd0e6a 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -365,7 +365,12 @@ static int sta_info_insert_drv_state(struct ieee80211_local *local, } if (!err) { - sta->uploaded = true; + /* + * Drivers using legacy sta_add/sta_remove callbacks only + * get uploaded set to true after sta_add is called. + */ + if (!local->ops->sta_add) + sta->uploaded = true; return 0; } @@ -417,18 +422,9 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) if (!sta->dummy || dummy_reinsert) { /* notify driver */ - err = drv_sta_add(local, sdata, &sta->sta); - if (err) { - if (sdata->vif.type != NL80211_IFTYPE_ADHOC) - goto out_err; - printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " - "driver (%d) - keeping it anyway.\n", - sdata->name, sta->sta.addr, err); - } else { - err = sta_info_insert_drv_state(local, sdata, sta); - if (err) - goto out_err; - } + err = sta_info_insert_drv_state(local, sdata, sta); + if (err) + goto out_err; } if (!dummy_reinsert) { @@ -802,7 +798,6 @@ int __must_check __sta_info_destroy(struct sta_info *sta) } if (sta->uploaded) { - drv_sta_remove(local, sdata, &sta->sta); ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE, IEEE80211_STA_NOTEXIST); WARN_ON_ONCE(ret != 0); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 8f8b4ecc776..264397aee81 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1187,8 +1187,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) if (sta->uploaded) { enum ieee80211_sta_state state; - WARN_ON(drv_sta_add(local, sta->sdata, &sta->sta)); - for (state = IEEE80211_STA_NOTEXIST; state < sta->sta_state - 1; state++) WARN_ON(drv_sta_state(local, sta->sdata, sta, -- cgit v1.2.3 From 7852e36186d2a1983c215836d7e3d7b8927c930d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:24 +0100 Subject: mac80211: remove dummy STA support The dummy STA support was added because I didn't want to change the driver API at the time. Now that we have state transitions triggering station add/remove in the driver, we only call add once a station reaches ASSOCIATED, so we can remove the dummy station stuff again. While at it, tighten the RX check and accept only port control (EAP) frames from the AP station if it's not associated yet -- in other cases there's no race. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 15 ++---- net/mac80211/rx.c | 13 +++-- net/mac80211/sta_info.c | 135 +++++++++--------------------------------------- net/mac80211/sta_info.h | 30 +---------- 4 files changed, 38 insertions(+), 155 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 40b929d57a9..d04811a29cd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1581,7 +1581,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, * station info was already allocated and inserted before * the association and should be available to us */ - sta = sta_info_get_rx(sdata, cbss->bssid); + sta = sta_info_get(sdata, cbss->bssid); if (WARN_ON(!sta)) { mutex_unlock(&sdata->local->sta_mtx); return false; @@ -1648,14 +1648,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, return false; } - /* sta_info_reinsert will also unlock the mutex lock */ - err = sta_info_reinsert(sta); - sta = NULL; - if (err) { - printk(KERN_DEBUG "%s: failed to insert STA entry for" - " the AP (error %d)\n", sdata->name, err); - return false; - } + mutex_unlock(&sdata->local->sta_mtx); /* * Always handle WMM once after association regardless @@ -2536,12 +2529,10 @@ static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata, if (!sta) return -ENOMEM; - sta->dummy = true; - err = sta_info_insert(sta); sta = NULL; if (err) { - printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for" + printk(KERN_DEBUG "%s: failed to insert STA entry for" " the AP (error %d)\n", sdata->name, err); return err; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ab29253fb4f..8d6fa674f53 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -859,7 +859,12 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && rx->sdata->vif.type != NL80211_IFTYPE_WDS && (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) { - if (rx->sta && rx->sta->dummy && + /* + * accept port control frames from the AP even when it's not + * yet marked ASSOC to prevent a race where we don't set the + * assoc bit quickly enough before it sends the first frame + */ + if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && ieee80211_is_data_present(hdr->frame_control)) { u16 ethertype; u8 *payload; @@ -2949,7 +2954,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, if (ieee80211_is_data(fc)) { prev_sta = NULL; - for_each_sta_info_rx(local, hdr->addr2, sta, tmp) { + for_each_sta_info(local, hdr->addr2, sta, tmp) { if (!prev_sta) { prev_sta = sta; continue; @@ -2993,7 +2998,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, continue; } - rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); + rx.sta = sta_info_get_bss(prev, hdr->addr2); rx.sdata = prev; ieee80211_prepare_and_rx_handle(&rx, skb, false); @@ -3001,7 +3006,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, } if (prev) { - rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); + rx.sta = sta_info_get_bss(prev, hdr->addr2); rx.sdata = prev; if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 5e577bd0e6a..31cd6d92531 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -97,25 +97,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sta_info *sta; - sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], - lockdep_is_held(&local->sta_mtx)); - while (sta) { - if (sta->sdata == sdata && !sta->dummy && - memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) - break; - sta = rcu_dereference_check(sta->hnext, - lockdep_is_held(&local->sta_mtx)); - } - return sta; -} - -/* get a station info entry even if it is a dummy station*/ -struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, - const u8 *addr) -{ - struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], lockdep_is_held(&local->sta_mtx)); while (sta) { @@ -138,30 +119,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sta_info *sta; - sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], - lockdep_is_held(&local->sta_mtx)); - while (sta) { - if ((sta->sdata == sdata || - (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && - !sta->dummy && - memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) - break; - sta = rcu_dereference_check(sta->hnext, - lockdep_is_held(&local->sta_mtx)); - } - return sta; -} - -/* - * Get sta info either from the specified interface - * or from one of its vlans (including dummy stations) - */ -struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, - const u8 *addr) -{ - struct ieee80211_local *local = sdata->local; - struct sta_info *sta; - sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], lockdep_is_held(&local->sta_mtx)); while (sta) { @@ -397,66 +354,43 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) { struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; - struct sta_info *exist_sta; - bool dummy_reinsert = false; + struct station_info sinfo; int err = 0; lockdep_assert_held(&local->sta_mtx); - /* - * check if STA exists already. - * only accept a scenario of a second call to sta_info_insert_finish - * with a dummy station entry that was inserted earlier - * in that case - assume that the dummy station flag should - * be removed. - */ - exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr); - if (exist_sta) { - if (exist_sta == sta && sta->dummy) { - dummy_reinsert = true; - } else { - err = -EEXIST; - goto out_err; - } - } - - if (!sta->dummy || dummy_reinsert) { - /* notify driver */ - err = sta_info_insert_drv_state(local, sdata, sta); - if (err) - goto out_err; + /* check if STA exists already */ + if (sta_info_get_bss(sdata, sta->sta.addr)) { + err = -EEXIST; + goto out_err; } - if (!dummy_reinsert) { - local->num_sta++; - local->sta_generation++; - smp_mb(); + /* notify driver */ + err = sta_info_insert_drv_state(local, sdata, sta); + if (err) + goto out_err; - /* make the station visible */ - sta_info_hash_add(local, sta); + local->num_sta++; + local->sta_generation++; + smp_mb(); - list_add(&sta->list, &local->sta_list); + /* make the station visible */ + sta_info_hash_add(local, sta); - set_sta_flag(sta, WLAN_STA_INSERTED); - } else { - sta->dummy = false; - } + list_add(&sta->list, &local->sta_list); - if (!sta->dummy) { - struct station_info sinfo; + set_sta_flag(sta, WLAN_STA_INSERTED); - ieee80211_sta_debugfs_add(sta); - rate_control_add_sta_debugfs(sta); + ieee80211_sta_debugfs_add(sta); + rate_control_add_sta_debugfs(sta); - memset(&sinfo, 0, sizeof(sinfo)); - sinfo.filled = 0; - sinfo.generation = local->sta_generation; - cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); - } + memset(&sinfo, 0, sizeof(sinfo)); + sinfo.filled = 0; + sinfo.generation = local->sta_generation; + cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n", - sta->dummy ? "dummy " : "", sta->sta.addr); + wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ /* move reference to rcu-protected */ @@ -508,25 +442,6 @@ int sta_info_insert(struct sta_info *sta) return err; } -/* Caller must hold sta->local->sta_mtx */ -int sta_info_reinsert(struct sta_info *sta) -{ - struct ieee80211_local *local = sta->local; - int err = 0; - - err = sta_info_insert_check(sta); - if (err) { - mutex_unlock(&local->sta_mtx); - return err; - } - - might_sleep(); - - err = sta_info_insert_finish(sta); - rcu_read_unlock(); - return err; -} - static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) { /* @@ -873,7 +788,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) int ret; mutex_lock(&sdata->local->sta_mtx); - sta = sta_info_get_rx(sdata, addr); + sta = sta_info_get(sdata, addr); ret = __sta_info_destroy(sta); mutex_unlock(&sdata->local->sta_mtx); @@ -887,7 +802,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, int ret; mutex_lock(&sdata->local->sta_mtx); - sta = sta_info_get_bss_rx(sdata, addr); + sta = sta_info_get_bss(sdata, addr); ret = __sta_info_destroy(sta); mutex_unlock(&sdata->local->sta_mtx); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 2ee80886000..03f249bc276 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -265,8 +265,6 @@ struct sta_ampdu_mlme { * @dead: set to true when sta is unlinked * @uploaded: set to true when sta is uploaded to the driver * @lost_packets: number of consecutive lost packets - * @dummy: indicate a dummy station created for receiving - * EAP frames before association * @sta: station information we share with the driver * @sta_state: duplicates information about station state (for debug) * @beacon_loss_count: number of times beacon loss has triggered @@ -364,9 +362,6 @@ struct sta_info { unsigned int lost_packets; unsigned int beacon_loss_count; - /* should be right in front of sta to be in the same cache line */ - bool dummy; - /* keep last! */ struct ieee80211_sta sta; }; @@ -468,15 +463,9 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid) struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, const u8 *addr); -struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, - const u8 *addr); - struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, const u8 *addr); -struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, - const u8 *addr); - static inline void for_each_sta_info_type_check(struct ieee80211_local *local, const u8 *addr, @@ -485,23 +474,7 @@ void for_each_sta_info_type_check(struct ieee80211_local *local, { } -#define for_each_sta_info(local, _addr, _sta, nxt) \ - for ( /* initialise loop */ \ - _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ - nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ - /* typecheck */ \ - for_each_sta_info_type_check(local, (_addr), _sta, nxt),\ - /* continue condition */ \ - _sta; \ - /* advance loop */ \ - _sta = nxt, \ - nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ - ) \ - /* run code only if address matches and it's not a dummy sta */ \ - if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \ - !_sta->dummy) - -#define for_each_sta_info_rx(local, _addr, _sta, nxt) \ +#define for_each_sta_info(local, _addr, _sta, nxt) \ for ( /* initialise loop */ \ _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ @@ -540,7 +513,6 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta); */ int sta_info_insert(struct sta_info *sta); int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); -int sta_info_reinsert(struct sta_info *sta); int __must_check __sta_info_destroy(struct sta_info *sta); int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, -- cgit v1.2.3 From 95de817b9034d50860319f6033ec85d25024694c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:25 +0100 Subject: cfg80211: stop tracking authenticated state To track authenticated state seems to have been a design mistake in cfg80211. It is possible to have out of band authentication (FT), tracking multiple authentications caused more problems than it ever helped, and the implementation in mac80211 is too complex. Remove all this complexity, and let userspace do whatever it wants to, mac80211 can deal with that just fine. Association is still tracked of course, but authentication no longer is. Local auth state changes are thus no longer of value, so ignore them completely. This will also help implement SAE -- asking the driver to do an authentication is now almost equivalent to sending an authentication frame, with the exception of shared key authentication which is still handled completely. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/DocBook/80211.tmpl | 1 - include/net/cfg80211.h | 39 ++--- net/mac80211/mlme.c | 23 +-- net/wireless/core.h | 9 +- net/wireless/mlme.c | 322 +++++++-------------------------------- net/wireless/nl80211.c | 18 +-- net/wireless/sme.c | 41 +---- 7 files changed, 91 insertions(+), 362 deletions(-) diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 2014155c899..c5ac6929c41 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -129,7 +129,6 @@ !Finclude/net/cfg80211.h cfg80211_pmksa !Finclude/net/cfg80211.h cfg80211_send_rx_auth !Finclude/net/cfg80211.h cfg80211_send_auth_timeout -!Finclude/net/cfg80211.h __cfg80211_auth_canceled !Finclude/net/cfg80211.h cfg80211_send_rx_assoc !Finclude/net/cfg80211.h cfg80211_send_assoc_timeout !Finclude/net/cfg80211.h cfg80211_send_deauth diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2964205332f..6cfecb02a34 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1039,10 +1039,6 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); * @key_len: length of WEP key for shared key authentication * @key_idx: index of WEP key for shared key authentication * @key: WEP key for shared key authentication - * @local_state_change: This is a request for a local state only, i.e., no - * Authentication frame is to be transmitted and authentication state is - * to be changed without having to wait for a response from the peer STA - * (AP). */ struct cfg80211_auth_request { struct cfg80211_bss *bss; @@ -1051,7 +1047,6 @@ struct cfg80211_auth_request { enum nl80211_auth_type auth_type; const u8 *key; u8 key_len, key_idx; - bool local_state_change; }; /** @@ -1068,7 +1063,11 @@ enum cfg80211_assoc_req_flags { * * This structure provides information needed to complete IEEE 802.11 * (re)association. - * @bss: The BSS to associate with. + * @bss: The BSS to associate with. If the call is successful the driver + * is given a reference that it must release, normally via a call to + * cfg80211_send_rx_assoc(), or, if association timed out, with a + * call to cfg80211_put_bss() (in addition to calling + * cfg80211_send_assoc_timeout()) * @ie: Extra IEs to add to (Re)Association Request frame or %NULL * @ie_len: Length of ie buffer in octets * @use_mfp: Use management frame protection (IEEE 802.11w) in this association @@ -1096,19 +1095,16 @@ struct cfg80211_assoc_request { * This structure provides information needed to complete IEEE 802.11 * deauthentication. * - * @bss: the BSS to deauthenticate from + * @bssid: the BSSID of the BSS to deauthenticate from * @ie: Extra IEs to add to Deauthentication frame or %NULL * @ie_len: Length of ie buffer in octets * @reason_code: The reason code for the deauthentication - * @local_state_change: This is a request for a local state only, i.e., no - * Deauthentication frame is to be transmitted. */ struct cfg80211_deauth_request { - struct cfg80211_bss *bss; + const u8 *bssid; const u8 *ie; size_t ie_len; u16 reason_code; - bool local_state_change; }; /** @@ -2206,8 +2202,6 @@ struct cfg80211_conn; struct cfg80211_internal_bss; struct cfg80211_cached_keys; -#define MAX_AUTH_BSSES 4 - /** * struct wireless_dev - wireless per-netdev state * @@ -2271,8 +2265,6 @@ struct wireless_dev { struct list_head event_list; spinlock_t event_lock; - struct cfg80211_internal_bss *authtry_bsses[MAX_AUTH_BSSES]; - struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES]; struct cfg80211_internal_bss *current_bss; /* associated / joined */ struct ieee80211_channel *channel; @@ -2763,21 +2755,11 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); */ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); -/** - * __cfg80211_auth_canceled - notify cfg80211 that authentication was canceled - * @dev: network device - * @addr: The MAC address of the device with which the authentication timed out - * - * When a pending authentication had no action yet, the driver may decide - * to not send a deauth frame, but in that case must calls this function - * to tell cfg80211 about this decision. It is only valid to call this - * function within the deauth() callback. - */ -void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr); - /** * cfg80211_send_rx_assoc - notification of processed association * @dev: network device + * @bss: the BSS struct association was requested for, the struct reference + * is owned by cfg80211 after this call * @buf: (re)association response frame (header + body) * @len: length of the frame data * @@ -2786,7 +2768,8 @@ void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr); * function or cfg80211_send_assoc_timeout() to indicate the result of * cfg80211_ops::assoc() call. This function may sleep. */ -void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len); +void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, + const u8 *buf, size_t len); /** * cfg80211_send_assoc_timeout - notification of timed out association diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d04811a29cd..082fcda5778 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2459,9 +2459,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_work *wk; u16 auth_alg; - if (req->local_state_change) - return 0; /* no need to update mac80211 state */ - switch (req->auth_type) { case NL80211_AUTHTYPE_OPEN_SYSTEM: auth_alg = WLAN_AUTH_OPEN; @@ -2593,7 +2590,7 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, sta_info_destroy_addr(wk->sdata, cbss->bssid); } - cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); + cfg80211_send_rx_assoc(wk->sdata->dev, cbss, skb->data, skb->len); destroy: if (wk->assoc.synced) drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, @@ -2750,13 +2747,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - u8 bssid[ETH_ALEN]; bool assoc_bss = false; mutex_lock(&ifmgd->mtx); - memcpy(bssid, req->bss->bssid, ETH_ALEN); - if (ifmgd->associated == req->bss) { + if (ifmgd->associated && + memcmp(ifmgd->associated->bssid, req->bssid, ETH_ALEN) == 0) { ieee80211_set_disassoc(sdata, false, true); mutex_unlock(&ifmgd->mtx); assoc_bss = true; @@ -2777,7 +2773,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) continue; - if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN)) + if (memcmp(req->bssid, tmp->filter_ta, ETH_ALEN)) continue; not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE; @@ -2811,18 +2807,15 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, * frame, and if it's IDLE we have completed the auth * process already. */ - if (not_auth_yet) { - __cfg80211_auth_canceled(sdata->dev, bssid); + if (not_auth_yet) return 0; - } } printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", - sdata->name, bssid, req->reason_code); + sdata->name, req->bssid, req->reason_code); - ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH, - req->reason_code, cookie, - !req->local_state_change); + ieee80211_send_deauth_disassoc(sdata, req->bssid, IEEE80211_STYPE_DEAUTH, + req->reason_code, cookie, true); if (assoc_bss) sta_info_flush(sdata->local, sdata); diff --git a/net/wireless/core.h b/net/wireless/core.h index 43ad9c81efc..2b454caf439 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -325,15 +325,13 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx, - bool local_state_change); + const u8 *key, int key_len, int key_idx); int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_auth_type auth_type, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx, - bool local_state_change); + const u8 *key, int key_len, int key_idx); int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, @@ -421,7 +419,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, size_t ie_len, u16 reason, bool from_ap); void cfg80211_sme_scan_done(struct net_device *dev); void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); -void cfg80211_sme_disassoc(struct net_device *dev, int idx); +void cfg80211_sme_disassoc(struct net_device *dev, + struct cfg80211_internal_bss *bss); void __cfg80211_scan_done(struct work_struct *wk); void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); void __cfg80211_sched_scan_results(struct work_struct *wk); diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 438dfc105b4..d553d365e75 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -20,40 +20,18 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; - u8 *bssid = mgmt->bssid; - int i; - u16 status = le16_to_cpu(mgmt->u.auth.status_code); - bool done = false; wdev_lock(wdev); - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->authtry_bsses[i] && - memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, - ETH_ALEN) == 0) { - if (status == WLAN_STATUS_SUCCESS) { - wdev->auth_bsses[i] = wdev->authtry_bsses[i]; - } else { - cfg80211_unhold_bss(wdev->authtry_bsses[i]); - cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); - } - wdev->authtry_bsses[i] = NULL; - done = true; - break; - } - } - - if (done) { - nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); - cfg80211_sme_rx_auth(dev, buf, len); - } + nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); + cfg80211_sme_rx_auth(dev, buf, len); wdev_unlock(wdev); } EXPORT_SYMBOL(cfg80211_send_rx_auth); -void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) +void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, + const u8 *buf, size_t len) { u16 status_code; struct wireless_dev *wdev = dev->ieee80211_ptr; @@ -61,8 +39,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; u8 *ie = mgmt->u.assoc_resp.variable; - int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); - struct cfg80211_internal_bss *bss = NULL; + int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); wdev_lock(wdev); @@ -75,43 +52,20 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) * frame instead of reassoc. */ if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && - cfg80211_sme_failed_reassoc(wdev)) + cfg80211_sme_failed_reassoc(wdev)) { + cfg80211_put_bss(bss); goto out; + } nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); - if (status_code == WLAN_STATUS_SUCCESS) { - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (!wdev->auth_bsses[i]) - continue; - if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid, - ETH_ALEN) == 0) { - bss = wdev->auth_bsses[i]; - wdev->auth_bsses[i] = NULL; - /* additional reference to drop hold */ - cfg80211_ref_bss(bss); - break; - } - } - - /* - * We might be coming here because the driver reported - * a successful association at the same time as the - * user requested a deauth. In that case, we will have - * removed the BSS from the auth_bsses list due to the - * deauth request when the assoc response makes it. If - * the two code paths acquire the lock the other way - * around, that's just the standard situation of a - * deauth being requested while connected. - */ - if (!bss) - goto out; - } else if (wdev->conn) { + if (status_code != WLAN_STATUS_SUCCESS && wdev->conn) { cfg80211_sme_failed_assoc(wdev); /* * do not call connect_result() now because the * sme will schedule work that does it later. */ + cfg80211_put_bss(bss); goto out; } @@ -124,17 +78,10 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) wdev->sme_state = CFG80211_SME_CONNECTING; } - /* this consumes one bss reference (unless bss is NULL) */ + /* this consumes the bss reference */ __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, status_code, - status_code == WLAN_STATUS_SUCCESS, - bss ? &bss->pub : NULL); - /* drop hold now, and also reference acquired above */ - if (bss) { - cfg80211_unhold_bss(bss); - cfg80211_put_bss(&bss->pub); - } - + status_code == WLAN_STATUS_SUCCESS, bss); out: wdev_unlock(wdev); } @@ -148,8 +95,7 @@ void __cfg80211_send_deauth(struct net_device *dev, struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; - int i; - bool found = false, was_current = false; + bool was_current = false; ASSERT_WDEV_LOCK(wdev); @@ -158,32 +104,9 @@ void __cfg80211_send_deauth(struct net_device *dev, cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; - found = true; was_current = true; - } else for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->auth_bsses[i] && - memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { - cfg80211_unhold_bss(wdev->auth_bsses[i]); - cfg80211_put_bss(&wdev->auth_bsses[i]->pub); - wdev->auth_bsses[i] = NULL; - found = true; - break; - } - if (wdev->authtry_bsses[i] && - memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, - ETH_ALEN) == 0 && - memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) == 0) { - cfg80211_unhold_bss(wdev->authtry_bsses[i]); - cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); - wdev->authtry_bsses[i] = NULL; - found = true; - break; - } } - if (!found) - return; - nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { @@ -220,10 +143,8 @@ void __cfg80211_send_disassoc(struct net_device *dev, struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; - int i; u16 reason_code; bool from_ap; - bool done = false; ASSERT_WDEV_LOCK(wdev); @@ -234,16 +155,10 @@ void __cfg80211_send_disassoc(struct net_device *dev, if (wdev->current_bss && memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->authtry_bsses[i] || wdev->auth_bsses[i]) - continue; - wdev->auth_bsses[i] = wdev->current_bss; - wdev->current_bss = NULL; - done = true; - cfg80211_sme_disassoc(dev, i); - break; - } - WARN_ON(!done); + cfg80211_sme_disassoc(dev, wdev->current_bss); + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(&wdev->current_bss->pub); + wdev->current_bss = NULL; } else WARN_ON(1); @@ -287,34 +202,6 @@ void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, } EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); -static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) -{ - int i; - bool done = false; - - ASSERT_WDEV_LOCK(wdev); - - for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { - if (wdev->authtry_bsses[i] && - memcmp(wdev->authtry_bsses[i]->pub.bssid, - addr, ETH_ALEN) == 0) { - cfg80211_unhold_bss(wdev->authtry_bsses[i]); - cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); - wdev->authtry_bsses[i] = NULL; - done = true; - break; - } - } - - WARN_ON(!done); -} - -void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr) -{ - __cfg80211_auth_remove(dev->ieee80211_ptr, addr); -} -EXPORT_SYMBOL(__cfg80211_auth_canceled); - void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) { struct wireless_dev *wdev = dev->ieee80211_ptr; @@ -329,8 +216,6 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); - __cfg80211_auth_remove(wdev, addr); - wdev_unlock(wdev); } EXPORT_SYMBOL(cfg80211_send_auth_timeout); @@ -340,8 +225,6 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - int i; - bool done = false; wdev_lock(wdev); @@ -351,20 +234,6 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); - for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { - if (wdev->auth_bsses[i] && - memcmp(wdev->auth_bsses[i]->pub.bssid, - addr, ETH_ALEN) == 0) { - cfg80211_unhold_bss(wdev->auth_bsses[i]); - cfg80211_put_bss(&wdev->auth_bsses[i]->pub); - wdev->auth_bsses[i] = NULL; - done = true; - break; - } - } - - WARN_ON(!done); - wdev_unlock(wdev); } EXPORT_SYMBOL(cfg80211_send_assoc_timeout); @@ -403,13 +272,11 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx, - bool local_state_change) + const u8 *key, int key_len, int key_idx) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_auth_request req; - struct cfg80211_internal_bss *bss; - int i, err, slot = -1, nfree = 0; + int err; ASSERT_WDEV_LOCK(wdev); @@ -421,20 +288,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) return -EALREADY; - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->authtry_bsses[i] && - memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, - ETH_ALEN) == 0) - return -EALREADY; - if (wdev->auth_bsses[i] && - memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, - ETH_ALEN) == 0) - return -EALREADY; - } - memset(&req, 0, sizeof(req)); - req.local_state_change = local_state_change; req.ie = ie; req.ie_len = ie_len; req.auth_type = auth_type; @@ -446,39 +301,9 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, if (!req.bss) return -ENOENT; - bss = bss_from_pub(req.bss); - - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) { - slot = i; - nfree++; - } - } - - /* we need one free slot for disassoc and one for this auth */ - if (nfree < 2) { - err = -ENOSPC; - goto out; - } - - if (local_state_change) - wdev->auth_bsses[slot] = bss; - else - wdev->authtry_bsses[slot] = bss; - cfg80211_hold_bss(bss); - err = rdev->ops->auth(&rdev->wiphy, dev, &req); - if (err) { - if (local_state_change) - wdev->auth_bsses[slot] = NULL; - else - wdev->authtry_bsses[slot] = NULL; - cfg80211_unhold_bss(bss); - } - out: - if (err) - cfg80211_put_bss(req.bss); + cfg80211_put_bss(req.bss); return err; } @@ -487,15 +312,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, enum nl80211_auth_type auth_type, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx, - bool local_state_change) + const u8 *key, int key_len, int key_idx) { int err; wdev_lock(dev->ieee80211_ptr); err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, ssid, ssid_len, ie, ie_len, - key, key_len, key_idx, local_state_change); + key, key_len, key_idx); wdev_unlock(dev->ieee80211_ptr); return err; @@ -530,8 +354,7 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_assoc_request req; - struct cfg80211_internal_bss *bss; - int i, err, slot = -1; + int err; bool was_connected = false; ASSERT_WDEV_LOCK(wdev); @@ -573,26 +396,14 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, return -ENOENT; } - bss = bss_from_pub(req.bss); - - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (bss == wdev->auth_bsses[i]) { - slot = i; - break; - } - } + err = rdev->ops->assoc(&rdev->wiphy, dev, &req); - if (slot < 0) { - err = -ENOTCONN; - goto out; + if (err) { + if (was_connected) + wdev->sme_state = CFG80211_SME_CONNECTED; + cfg80211_put_bss(req.bss); } - err = rdev->ops->assoc(&rdev->wiphy, dev, &req); - out: - if (err && was_connected) - wdev->sme_state = CFG80211_SME_CONNECTED; - /* still a reference in wdev->auth_bsses[slot] */ - cfg80211_put_bss(req.bss); return err; } @@ -624,34 +435,25 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, bool local_state_change) { struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_deauth_request req; - int i; + struct cfg80211_deauth_request req = { + .bssid = bssid, + .reason_code = reason, + .ie = ie, + .ie_len = ie_len, + }; ASSERT_WDEV_LOCK(wdev); - memset(&req, 0, sizeof(req)); - req.reason_code = reason; - req.local_state_change = local_state_change; - req.ie = ie; - req.ie_len = ie_len; - if (wdev->current_bss && - memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { - req.bss = &wdev->current_bss->pub; - } else for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->auth_bsses[i] && - memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) { - req.bss = &wdev->auth_bsses[i]->pub; - break; - } - if (wdev->authtry_bsses[i] && - memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) { - req.bss = &wdev->authtry_bsses[i]->pub; - break; + if (local_state_change) { + if (wdev->current_bss && + memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(&wdev->current_bss->pub); + wdev->current_bss = NULL; } - } - if (!req.bss) - return -ENOTCONN; + return 0; + } return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); } @@ -722,7 +524,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_deauth_request req; - int i; + u8 bssid[ETH_ALEN]; ASSERT_WDEV_LOCK(wdev); @@ -734,35 +536,17 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, req.ie = NULL; req.ie_len = 0; - if (wdev->current_bss) { - req.bss = &wdev->current_bss->pub; - rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); - if (wdev->current_bss) { - cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(&wdev->current_bss->pub); - wdev->current_bss = NULL; - } - } + if (!wdev->current_bss) + return; - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (wdev->auth_bsses[i]) { - req.bss = &wdev->auth_bsses[i]->pub; - rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); - if (wdev->auth_bsses[i]) { - cfg80211_unhold_bss(wdev->auth_bsses[i]); - cfg80211_put_bss(&wdev->auth_bsses[i]->pub); - wdev->auth_bsses[i] = NULL; - } - } - if (wdev->authtry_bsses[i]) { - req.bss = &wdev->authtry_bsses[i]->pub; - rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); - if (wdev->authtry_bsses[i]) { - cfg80211_unhold_bss(wdev->authtry_bsses[i]); - cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); - wdev->authtry_bsses[i] = NULL; - } - } + memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); + req.bssid = bssid; + rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); + + if (wdev->current_bss) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(&wdev->current_bss->pub); + wdev->current_bss = NULL; } } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c910b0750dc..e1fd1bf9072 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -4083,7 +4083,6 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, struct cfg80211_bss *res = &intbss->pub; void *hdr; struct nlattr *bss; - int i; ASSERT_WDEV_LOCK(wdev); @@ -4136,13 +4135,6 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, if (intbss == wdev->current_bss) NLA_PUT_U32(msg, NL80211_BSS_STATUS, NL80211_BSS_STATUS_ASSOCIATED); - else for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (intbss != wdev->auth_bsses[i]) - continue; - NLA_PUT_U32(msg, NL80211_BSS_STATUS, - NL80211_BSS_STATUS_AUTHENTICATED); - break; - } break; case NL80211_IFTYPE_ADHOC: if (intbss == wdev->current_bss) @@ -4410,10 +4402,16 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; + /* + * Since we no longer track auth state, ignore + * requests to only change local state. + */ + if (local_state_change) + return 0; + return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, ssid, ssid_len, ie, ie_len, - key.p.key, key.p.key_len, key.idx, - local_state_change); + key.p.key, key.p.key_len, key.idx); } static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 7b9ecaed96b..f7e937ff897 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -179,7 +179,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) params->ssid, params->ssid_len, NULL, 0, params->key, params->key_len, - params->key_idx, false); + params->key_idx); case CFG80211_CONN_ASSOCIATE_NEXT: BUG_ON(!rdev->ops->assoc); wdev->conn->state = CFG80211_CONN_ASSOCIATING; @@ -477,6 +477,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, kfree(wdev->connect_keys); wdev->connect_keys = NULL; wdev->ssid_len = 0; + cfg80211_put_bss(bss); return; } @@ -701,31 +702,10 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, wdev->ssid_len = 0; if (wdev->conn) { - const u8 *bssid; - int ret; - kfree(wdev->conn->ie); wdev->conn->ie = NULL; kfree(wdev->conn); wdev->conn = NULL; - - /* - * If this disconnect was due to a disassoc, we - * we might still have an auth BSS around. For - * the userspace SME that's currently expected, - * but for the kernel SME (nl80211 CONNECT or - * wireless extensions) we want to clear up all - * state. - */ - for (i = 0; i < MAX_AUTH_BSSES; i++) { - if (!wdev->auth_bsses[i]) - continue; - bssid = wdev->auth_bsses[i]->pub.bssid; - ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, - WLAN_REASON_DEAUTH_LEAVING, - false); - WARN(ret, "deauth failed: %d\n", ret); - } } nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); @@ -1012,7 +992,8 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev, return err; } -void cfg80211_sme_disassoc(struct net_device *dev, int idx) +void cfg80211_sme_disassoc(struct net_device *dev, + struct cfg80211_internal_bss *bss) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); @@ -1031,16 +1012,8 @@ void cfg80211_sme_disassoc(struct net_device *dev, int idx) * want it any more so deauthenticate too. */ - if (!wdev->auth_bsses[idx]) - return; + memcpy(bssid, bss->pub.bssid, ETH_ALEN); - memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); - if (__cfg80211_mlme_deauth(rdev, dev, bssid, - NULL, 0, WLAN_REASON_DEAUTH_LEAVING, - false)) { - /* whatever -- assume gone anyway */ - cfg80211_unhold_bss(wdev->auth_bsses[idx]); - cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); - wdev->auth_bsses[idx] = NULL; - } + __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, + WLAN_REASON_DEAUTH_LEAVING, false); } -- cgit v1.2.3 From 4c0c0b75e0c35ddb8f61c06bcbffede63ab4f4a2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:26 +0100 Subject: cfg80211: export cfg80211_ref_bss This is needed by mac80211 to keep a reference to a BSS alive for the auth process. Remove the old version of cfg80211_ref_bss() since it's not actually used. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 14 ++++++++++++++ net/wireless/core.h | 5 ----- net/wireless/scan.c | 12 ++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6cfecb02a34..229edc526cf 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2719,6 +2719,20 @@ struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy, struct ieee80211_channel *channel, const u8 *meshid, size_t meshidlen, const u8 *meshcfg); +/** + * cfg80211_ref_bss - reference BSS struct + * @bss: the BSS struct to reference + * + * Increments the refcount of the given BSS struct. + */ +void cfg80211_ref_bss(struct cfg80211_bss *bss); + +/** + * cfg80211_put_bss - unref BSS struct + * @bss: the BSS struct + * + * Decrements the refcount of the given BSS struct. + */ void cfg80211_put_bss(struct cfg80211_bss *bss); /** diff --git a/net/wireless/core.h b/net/wireless/core.h index 2b454caf439..3ac2dd00d71 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -144,11 +144,6 @@ static inline struct cfg80211_internal_bss *bss_from_pub(struct cfg80211_bss *pu return container_of(pub, struct cfg80211_internal_bss, pub); } -static inline void cfg80211_ref_bss(struct cfg80211_internal_bss *bss) -{ - kref_get(&bss->ref); -} - static inline void cfg80211_hold_bss(struct cfg80211_internal_bss *bss) { atomic_inc(&bss->hold); diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 31119e32e09..afde7e5f001 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -861,6 +861,18 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_inform_bss_frame); +void cfg80211_ref_bss(struct cfg80211_bss *pub) +{ + struct cfg80211_internal_bss *bss; + + if (!pub) + return; + + bss = container_of(pub, struct cfg80211_internal_bss, pub); + kref_get(&bss->ref); +} +EXPORT_SYMBOL(cfg80211_ref_bss); + void cfg80211_put_bss(struct cfg80211_bss *pub) { struct cfg80211_internal_bss *bss; -- cgit v1.2.3 From 66e67e418908442389d3a9e6509985f01cbaf9b0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:27 +0100 Subject: mac80211: redesign auth/assoc This is the second part of the auth/assoc redesign, the mac80211 part. This moves the auth/assoc code out of the work abstraction and into the MLME, so that we don't flip channels all the time etc. The only downside is that when we are associated, we need to drop the association in order to create a connection to another AP, but for most drivers this is actually desirable and the ability to do was never used by any applications. If we want to implement resource reservation with FT-OTA, we'd probably best do it with explicit R-O-C in wpa_s. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/Makefile | 4 +- net/mac80211/cfg.c | 6 +- net/mac80211/ieee80211_i.h | 77 +-- net/mac80211/iface.c | 4 +- net/mac80211/main.c | 10 +- net/mac80211/mlme.c | 1340 ++++++++++++++++++++++++++++++++------------ net/mac80211/rx.c | 9 +- net/mac80211/work.c | 815 --------------------------- 8 files changed, 1038 insertions(+), 1227 deletions(-) diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index d540c3b160f..1be7a454aa7 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -9,7 +9,7 @@ mac80211-y := \ scan.o offchannel.o \ ht.o agg-tx.o agg-rx.o \ ibss.o \ - mlme.o work.o \ + work.o \ iface.o \ rate.o \ michael.o \ @@ -25,7 +25,7 @@ mac80211-y := \ wme.o \ event.o \ chan.o \ - driver-trace.o + driver-trace.o mlme.o mac80211-$(CONFIG_MAC80211_LEDS) += led.o mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d15ba0d0de9..c3de921c8cf 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2028,7 +2028,7 @@ ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) if (wk->offchan_tx.wait && !wk->offchan_tx.status) cfg80211_mgmt_tx_status(wk->sdata->dev, (unsigned long) wk->offchan_tx.frame, - wk->ie, wk->ie_len, false, GFP_KERNEL); + wk->data, wk->data_len, false, GFP_KERNEL); return WORK_DONE_DESTROY; } @@ -2179,8 +2179,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, wk->done = ieee80211_offchan_tx_done; wk->offchan_tx.frame = skb; wk->offchan_tx.wait = wait; - wk->ie_len = len; - memcpy(wk->ie, buf, len); + wk->data_len = len; + memcpy(wk->data, buf, len); ieee80211_add_work(wk); return 0; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d47e8c110b1..a146b1177cb 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -280,10 +280,6 @@ struct mesh_preq_queue { enum ieee80211_work_type { IEEE80211_WORK_ABORT, - IEEE80211_WORK_DIRECT_PROBE, - IEEE80211_WORK_AUTH, - IEEE80211_WORK_ASSOC_BEACON_WAIT, - IEEE80211_WORK_ASSOC, IEEE80211_WORK_REMAIN_ON_CHANNEL, IEEE80211_WORK_OFFCHANNEL_TX, }; @@ -316,35 +312,9 @@ struct ieee80211_work { unsigned long timeout; enum ieee80211_work_type type; - u8 filter_ta[ETH_ALEN]; - bool started; union { - struct { - int tries; - u16 algorithm, transaction; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ssid_len; - u8 key[WLAN_KEY_LEN_WEP104]; - u8 key_len, key_idx; - bool privacy; - bool synced; - } probe_auth; - struct { - struct cfg80211_bss *bss; - const u8 *supp_rates; - const u8 *ht_information_ie; - enum ieee80211_smps_mode smps; - int tries; - u16 capability; - u8 prev_bssid[ETH_ALEN]; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ssid_len; - u8 supp_rates_len; - bool wmm_used, use_11n, uapsd_used; - bool synced; - } assoc; struct { u32 duration; } remain; @@ -355,9 +325,8 @@ struct ieee80211_work { } offchan_tx; }; - int ie_len; - /* must be last */ - u8 ie[0]; + size_t data_len; + u8 data[]; }; /* flags used in struct ieee80211_if_managed.flags */ @@ -373,6 +342,43 @@ enum ieee80211_sta_flags { IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), }; +struct ieee80211_mgd_auth_data { + struct cfg80211_bss *bss; + unsigned long timeout; + int tries; + u16 algorithm, expected_transaction; + + u8 key[WLAN_KEY_LEN_WEP104]; + u8 key_len, key_idx; + bool synced; + bool done; + + size_t ie_len; + u8 ie[]; +}; + +struct ieee80211_mgd_assoc_data { + struct cfg80211_bss *bss; + const u8 *supp_rates; + const u8 *ht_information_ie; + + unsigned long timeout; + int tries; + + u16 capability; + u8 prev_bssid[ETH_ALEN]; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_len; + u8 supp_rates_len; + bool wmm_used, uapsd_used; + bool have_beacon; + bool sent_assoc; + bool synced; + + size_t ie_len; + u8 ie[]; +}; + struct ieee80211_if_managed { struct timer_list timer; struct timer_list conn_mon_timer; @@ -389,6 +395,8 @@ struct ieee80211_if_managed { struct mutex mtx; struct cfg80211_bss *associated; + struct ieee80211_mgd_auth_data *auth_data; + struct ieee80211_mgd_assoc_data *assoc_data; u8 bssid[ETH_ALEN]; @@ -770,7 +778,6 @@ struct ieee80211_local { struct list_head work_list; struct timer_list work_timer; struct work_struct work_work; - struct sk_buff_head work_skb_queue; /* * private workqueue to mac80211. mac80211 makes this accessible @@ -1437,8 +1444,6 @@ void ieee80211_work_init(struct ieee80211_local *local); void ieee80211_add_work(struct ieee80211_work *wk); void free_work(struct ieee80211_work *wk); void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); -ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb); int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 2efd595b2f7..19f0818eba7 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1310,7 +1310,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) /* do not count disabled managed interfaces */ if (sdata->vif.type == NL80211_IFTYPE_STATION && - !sdata->u.mgd.associated) { + !sdata->u.mgd.associated && + !sdata->u.mgd.auth_data && + !sdata->u.mgd.assoc_data) { sdata->vif.bss_conf.idle = true; continue; } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f4fc540aac1..362e89d6d46 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -199,15 +199,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, return; if (sdata->vif.type == NL80211_IFTYPE_STATION) { - /* - * While not associated, claim a BSSID of all-zeroes - * so that drivers don't do any weird things with the - * BSSID at that time. - */ - if (sdata->vif.bss_conf.assoc) - sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; - else - sdata->vif.bss_conf.bssid = zero; + sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; else if (sdata->vif.type == NL80211_IFTYPE_AP) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 082fcda5778..52133dab929 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -30,6 +30,12 @@ #include "rate.h" #include "led.h" +#define IEEE80211_AUTH_TIMEOUT (HZ / 5) +#define IEEE80211_AUTH_MAX_TRIES 3 +#define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) +#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) +#define IEEE80211_ASSOC_MAX_TRIES 3 + static int max_nullfunc_tries = 2; module_param(max_nullfunc_tries, int, 0644); MODULE_PARM_DESC(max_nullfunc_tries, @@ -97,6 +103,15 @@ enum rx_mgmt_action { /* caller must call cfg80211_send_disassoc() */ RX_MGMT_CFG80211_DISASSOC, + + /* caller must call cfg80211_send_rx_auth() */ + RX_MGMT_CFG80211_RX_AUTH, + + /* caller must call cfg80211_send_rx_assoc() */ + RX_MGMT_CFG80211_RX_ASSOC, + + /* caller must call cfg80211_send_assoc_timeout() */ + RX_MGMT_CFG80211_ASSOC_TIMEOUT, }; /* utils */ @@ -115,8 +130,7 @@ static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) * has happened -- the work that runs from this timer will * do that. */ -static void run_again(struct ieee80211_if_managed *ifmgd, - unsigned long timeout) +static void run_again(struct ieee80211_if_managed *ifmgd, unsigned long timeout) { ASSERT_MGD_MTX(ifmgd); @@ -284,6 +298,319 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, /* frame sending functions */ +static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, + struct ieee80211_supported_band *sband, + u32 *rates) +{ + int i, j, count; + *rates = 0; + count = 0; + for (i = 0; i < supp_rates_len; i++) { + int rate = (supp_rates[i] & 0x7F) * 5; + + for (j = 0; j < sband->n_bitrates; j++) + if (sband->bitrates[j].bitrate == rate) { + *rates |= BIT(j); + count++; + break; + } + } + + return count; +} + +static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, const u8 *ht_info_ie, + struct ieee80211_supported_band *sband, + struct ieee80211_channel *channel, + enum ieee80211_smps_mode smps) +{ + struct ieee80211_ht_info *ht_info; + u8 *pos; + u32 flags = channel->flags; + u16 cap; + struct ieee80211_sta_ht_cap ht_cap; + + BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); + + if (!sband->ht_cap.ht_supported) + return; + + if (!ht_info_ie) + return; + + if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) + return; + + memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); + ieee80211_apply_htcap_overrides(sdata, &ht_cap); + + ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); + + /* determine capability flags */ + cap = ht_cap.cap; + + switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + if (flags & IEEE80211_CHAN_NO_HT40PLUS) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + if (flags & IEEE80211_CHAN_NO_HT40MINUS) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + break; + } + + /* set SM PS mode properly */ + cap &= ~IEEE80211_HT_CAP_SM_PS; + switch (smps) { + case IEEE80211_SMPS_AUTOMATIC: + case IEEE80211_SMPS_NUM_MODES: + WARN_ON(1); + case IEEE80211_SMPS_OFF: + cap |= WLAN_HT_CAP_SM_PS_DISABLED << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + case IEEE80211_SMPS_STATIC: + cap |= WLAN_HT_CAP_SM_PS_STATIC << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + case IEEE80211_SMPS_DYNAMIC: + cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + } + + /* reserve and fill IE */ + pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); + ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); +} + +static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + u8 *pos, qos_info; + size_t offset = 0, noffset; + int i, count, rates_len, supp_rates_len; + u16 capab; + struct ieee80211_supported_band *sband; + u32 rates = 0; + struct ieee80211_bss *bss = (void *)assoc_data->bss->priv; + + lockdep_assert_held(&ifmgd->mtx); + + sband = local->hw.wiphy->bands[local->oper_channel->band]; + + if (assoc_data->supp_rates_len) { + /* + * Get all rates supported by the device and the AP as + * some APs don't like getting a superset of their rates + * in the association request (e.g. D-Link DAP 1353 in + * b-only mode)... + */ + rates_len = ieee80211_compatible_rates(assoc_data->supp_rates, + assoc_data->supp_rates_len, + sband, &rates); + } else { + /* + * In case AP not provide any supported rates information + * before association, we send information element(s) with + * all rates that we support. + */ + rates = ~0; + rates_len = sband->n_bitrates; + } + + skb = alloc_skb(local->hw.extra_tx_headroom + + sizeof(*mgmt) + /* bit too much but doesn't matter */ + 2 + assoc_data->ssid_len + /* SSID */ + 4 + rates_len + /* (extended) rates */ + 4 + /* power capability */ + 2 + 2 * sband->n_channels + /* supported channels */ + 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ + assoc_data->ie_len + /* extra IEs */ + 9, /* WMM */ + GFP_KERNEL); + if (!skb) + return; + + skb_reserve(skb, local->hw.extra_tx_headroom); + + capab = WLAN_CAPABILITY_ESS; + + if (sband->band == IEEE80211_BAND_2GHZ) { + if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) + capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; + if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) + capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; + } + + if (assoc_data->capability & WLAN_CAPABILITY_PRIVACY) + capab |= WLAN_CAPABILITY_PRIVACY; + + if ((assoc_data->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && + (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) + capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; + + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); + memset(mgmt, 0, 24); + memcpy(mgmt->da, assoc_data->bss->bssid, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); + memcpy(mgmt->bssid, assoc_data->bss->bssid, ETH_ALEN); + + if (!is_zero_ether_addr(assoc_data->prev_bssid)) { + skb_put(skb, 10); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_REASSOC_REQ); + mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); + mgmt->u.reassoc_req.listen_interval = + cpu_to_le16(local->hw.conf.listen_interval); + memcpy(mgmt->u.reassoc_req.current_ap, assoc_data->prev_bssid, + ETH_ALEN); + } else { + skb_put(skb, 4); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ASSOC_REQ); + mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); + mgmt->u.assoc_req.listen_interval = + cpu_to_le16(local->hw.conf.listen_interval); + } + + /* SSID */ + pos = skb_put(skb, 2 + assoc_data->ssid_len); + *pos++ = WLAN_EID_SSID; + *pos++ = assoc_data->ssid_len; + memcpy(pos, assoc_data->ssid, assoc_data->ssid_len); + + /* add all rates which were marked to be used above */ + supp_rates_len = rates_len; + if (supp_rates_len > 8) + supp_rates_len = 8; + + pos = skb_put(skb, supp_rates_len + 2); + *pos++ = WLAN_EID_SUPP_RATES; + *pos++ = supp_rates_len; + + count = 0; + for (i = 0; i < sband->n_bitrates; i++) { + if (BIT(i) & rates) { + int rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + if (++count == 8) + break; + } + } + + if (rates_len > count) { + pos = skb_put(skb, rates_len - count + 2); + *pos++ = WLAN_EID_EXT_SUPP_RATES; + *pos++ = rates_len - count; + + for (i++; i < sband->n_bitrates; i++) { + if (BIT(i) & rates) { + int rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + } + } + } + + if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { + /* 1. power capabilities */ + pos = skb_put(skb, 4); + *pos++ = WLAN_EID_PWR_CAPABILITY; + *pos++ = 2; + *pos++ = 0; /* min tx power */ + *pos++ = local->oper_channel->max_power; /* max tx power */ + + /* 2. supported channels */ + /* TODO: get this in reg domain format */ + pos = skb_put(skb, 2 * sband->n_channels + 2); + *pos++ = WLAN_EID_SUPPORTED_CHANNELS; + *pos++ = 2 * sband->n_channels; + for (i = 0; i < sband->n_channels; i++) { + *pos++ = ieee80211_frequency_to_channel( + sband->channels[i].center_freq); + *pos++ = 1; /* one channel in the subband*/ + } + } + + /* if present, add any custom IEs that go before HT */ + if (assoc_data->ie_len && assoc_data->ie) { + static const u8 before_ht[] = { + WLAN_EID_SSID, + WLAN_EID_SUPP_RATES, + WLAN_EID_EXT_SUPP_RATES, + WLAN_EID_PWR_CAPABILITY, + WLAN_EID_SUPPORTED_CHANNELS, + WLAN_EID_RSN, + WLAN_EID_QOS_CAPA, + WLAN_EID_RRM_ENABLED_CAPABILITIES, + WLAN_EID_MOBILITY_DOMAIN, + WLAN_EID_SUPPORTED_REGULATORY_CLASSES, + }; + noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len, + before_ht, ARRAY_SIZE(before_ht), + offset); + pos = skb_put(skb, noffset - offset); + memcpy(pos, assoc_data->ie + offset, noffset - offset); + offset = noffset; + } + + if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N) && + bss->wmm_used && local->hw.queues >= 4) + ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie, + sband, local->oper_channel, ifmgd->ap_smps); + + /* if present, add any custom non-vendor IEs that go after HT */ + if (assoc_data->ie_len && assoc_data->ie) { + noffset = ieee80211_ie_split_vendor(assoc_data->ie, + assoc_data->ie_len, + offset); + pos = skb_put(skb, noffset - offset); + memcpy(pos, assoc_data->ie + offset, noffset - offset); + offset = noffset; + } + + if (assoc_data->wmm_used && local->hw.queues >= 4) { + if (assoc_data->uapsd_used) { + qos_info = local->uapsd_queues; + qos_info |= (local->uapsd_max_sp_len << + IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT); + } else { + qos_info = 0; + } + + pos = skb_put(skb, 9); + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 7; /* len */ + *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ + *pos++ = 0x50; + *pos++ = 0xf2; + *pos++ = 2; /* WME */ + *pos++ = 0; /* WME info */ + *pos++ = 1; /* WME ver */ + *pos++ = qos_info; + } + + /* add any remaining custom (i.e. vendor specific here) IEs */ + if (assoc_data->ie_len && assoc_data->ie) { + noffset = assoc_data->ie_len; + pos = skb_put(skb, noffset - offset); + memcpy(pos, assoc_data->ie + offset, noffset - offset); + } + + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; + ieee80211_tx_skb(sdata, skb); +} + static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, const u8 *bssid, u16 stype, u16 reason, void *cookie, bool send_frame) @@ -1423,6 +1750,135 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif) EXPORT_SYMBOL(ieee80211_connection_loss); +static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, + bool assoc) +{ + struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data; + + lockdep_assert_held(&sdata->u.mgd.mtx); + + if (auth_data->synced) + drv_finish_tx_sync(sdata->local, sdata, + auth_data->bss->bssid, + IEEE80211_TX_SYNC_AUTH); + + if (!assoc) { + sta_info_destroy_addr(sdata, auth_data->bss->bssid); + + memset(sdata->u.mgd.bssid, 0, ETH_ALEN); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); + } + + cfg80211_put_bss(auth_data->bss); + kfree(auth_data); + sdata->u.mgd.auth_data = NULL; +} + +static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len) +{ + struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data; + u8 *pos; + struct ieee802_11_elems elems; + + pos = mgmt->u.auth.variable; + ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); + if (!elems.challenge) + return; + auth_data->expected_transaction = 4; + ieee80211_send_auth(sdata, 3, auth_data->algorithm, + elems.challenge - 2, elems.challenge_len + 2, + auth_data->bss->bssid, auth_data->bss->bssid, + auth_data->key, auth_data->key_len, + auth_data->key_idx); +} + +static enum rx_mgmt_action __must_check +ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len) +{ + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + u8 bssid[ETH_ALEN]; + u16 auth_alg, auth_transaction, status_code; + struct sta_info *sta; + + lockdep_assert_held(&ifmgd->mtx); + + if (len < 24 + 6) + return RX_MGMT_NONE; + + if (!ifmgd->auth_data || ifmgd->auth_data->done) + return RX_MGMT_NONE; + + memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN); + + if (memcmp(bssid, mgmt->bssid, ETH_ALEN)) + return RX_MGMT_NONE; + + auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); + auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); + status_code = le16_to_cpu(mgmt->u.auth.status_code); + + if (auth_alg != ifmgd->auth_data->algorithm || + auth_transaction != ifmgd->auth_data->expected_transaction) + return RX_MGMT_NONE; + + if (status_code != WLAN_STATUS_SUCCESS) { + printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", + sdata->name, mgmt->sa, status_code); + goto out; + } + + switch (ifmgd->auth_data->algorithm) { + case WLAN_AUTH_OPEN: + case WLAN_AUTH_LEAP: + case WLAN_AUTH_FT: + break; + case WLAN_AUTH_SHARED_KEY: + if (ifmgd->auth_data->expected_transaction != 4) { + ieee80211_auth_challenge(sdata, mgmt, len); + /* need another frame */ + return RX_MGMT_NONE; + } + break; + default: + WARN_ONCE(1, "invalid auth alg %d", + ifmgd->auth_data->algorithm); + return RX_MGMT_NONE; + } + + printk(KERN_DEBUG "%s: authenticated\n", sdata->name); + out: + if (ifmgd->auth_data->synced) + drv_finish_tx_sync(sdata->local, sdata, bssid, + IEEE80211_TX_SYNC_AUTH); + ifmgd->auth_data->synced = false; + ifmgd->auth_data->done = true; + ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; + run_again(ifmgd, ifmgd->auth_data->timeout); + + /* move station state to auth */ + mutex_lock(&sdata->local->sta_mtx); + sta = sta_info_get(sdata, bssid); + if (!sta) { + WARN_ONCE(1, "%s: STA %pM not found", sdata->name, bssid); + goto out_err; + } + if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) { + printk(KERN_DEBUG "%s: failed moving %pM to auth\n", + sdata->name, bssid); + goto out_err; + } + mutex_unlock(&sdata->local->sta_mtx); + + return RX_MGMT_CFG80211_RX_AUTH; + out_err: + mutex_unlock(&sdata->local->sta_mtx); + /* ignore frame -- wait for timeout */ + return RX_MGMT_NONE; +} + + static enum rx_mgmt_action __must_check ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) @@ -1431,10 +1887,14 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, const u8 *bssid = NULL; u16 reason_code; + lockdep_assert_held(&ifmgd->mtx); + if (len < 24 + 2) return RX_MGMT_NONE; - ASSERT_MGD_MTX(ifmgd); + if (!ifmgd->associated || + memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN)) + return RX_MGMT_NONE; bssid = ifmgd->associated->bssid; @@ -1459,15 +1919,13 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u16 reason_code; - if (len < 24 + 2) - return RX_MGMT_NONE; - - ASSERT_MGD_MTX(ifmgd); + lockdep_assert_held(&ifmgd->mtx); - if (WARN_ON(!ifmgd->associated)) + if (len < 24 + 2) return RX_MGMT_NONE; - if (WARN_ON(memcmp(ifmgd->associated->bssid, mgmt->sa, ETH_ALEN))) + if (!ifmgd->associated || + memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN)) return RX_MGMT_NONE; reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); @@ -1524,15 +1982,37 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, } } -static bool ieee80211_assoc_success(struct ieee80211_work *wk, +static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, + bool assoc) +{ + struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; + + lockdep_assert_held(&sdata->u.mgd.mtx); + + if (assoc_data->synced) + drv_finish_tx_sync(sdata->local, sdata, + assoc_data->bss->bssid, + IEEE80211_TX_SYNC_ASSOC); + + if (!assoc) { + sta_info_destroy_addr(sdata, assoc_data->bss->bssid); + + memset(sdata->u.mgd.bssid, 0, ETH_ALEN); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); + } + + kfree(assoc_data); + sdata->u.mgd.assoc_data = NULL; +} + +static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + struct cfg80211_bss *cbss, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_sub_if_data *sdata = wk->sdata; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct sta_info *sta; - struct cfg80211_bss *cbss = wk->assoc.bss; u8 *pos; u32 rates, basic_rates; u16 capab_info, aid; @@ -1589,7 +2069,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, rates = 0; basic_rates = 0; - sband = local->hw.wiphy->bands[wk->chan->band]; + sband = local->hw.wiphy->bands[local->oper_channel->band]; ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len, &rates, &basic_rates, &have_higher_than_11mbit, @@ -1610,11 +2090,11 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, basic_rates = BIT(min_rate_index); } - sta->sta.supp_rates[wk->chan->band] = rates; + sta->sta.supp_rates[local->oper_channel->band] = rates; sdata->vif.bss_conf.basic_rates = basic_rates; /* cf. IEEE 802.11 9.2.12 */ - if (wk->chan->band == IEEE80211_BAND_2GHZ && + if (local->oper_channel->band == IEEE80211_BAND_2GHZ && have_higher_than_11mbit) sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; else @@ -1664,8 +2144,6 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, else ieee80211_set_wmm_default(sdata); - local->oper_channel = wk->chan; - if (elems.ht_info_elem && elems.wmm_param && (sdata->local->hw.queues >= 4) && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) @@ -1696,7 +2174,82 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, return true; } +static enum rx_mgmt_action __must_check +ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len, + struct cfg80211_bss **bss) +{ + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; + u16 capab_info, status_code, aid; + struct ieee802_11_elems elems; + u8 *pos; + bool reassoc; + + lockdep_assert_held(&ifmgd->mtx); + + if (!assoc_data) + return RX_MGMT_NONE; + if (memcmp(assoc_data->bss->bssid, mgmt->bssid, ETH_ALEN)) + return RX_MGMT_NONE; + + /* + * AssocResp and ReassocResp have identical structure, so process both + * of them in this function. + */ + + if (len < 24 + 6) + return RX_MGMT_NONE; + + reassoc = ieee80211_is_reassoc_req(mgmt->frame_control); + capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); + status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); + aid = le16_to_cpu(mgmt->u.assoc_resp.aid); + + printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " + "status=%d aid=%d)\n", + sdata->name, reassoc ? "Rea" : "A", mgmt->sa, + 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); + + if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && + elems.timeout_int && elems.timeout_int_len == 5 && + elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { + u32 tu, ms; + tu = get_unaligned_le32(elems.timeout_int + 1); + ms = tu * 1024 / 1000; + printk(KERN_DEBUG "%s: %pM rejected association temporarily; " + "comeback duration %u TU (%u ms)\n", + sdata->name, mgmt->sa, tu, ms); + assoc_data->timeout = jiffies + msecs_to_jiffies(ms); + if (ms > IEEE80211_ASSOC_TIMEOUT) + run_again(ifmgd, assoc_data->timeout); + return RX_MGMT_NONE; + } + + *bss = assoc_data->bss; + + if (status_code != WLAN_STATUS_SUCCESS) { + printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n", + sdata->name, mgmt->sa, status_code); + ieee80211_destroy_assoc_data(sdata, false); + } else { + printk(KERN_DEBUG "%s: associated\n", sdata->name); + + ieee80211_destroy_assoc_data(sdata, true); + if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { + /* oops -- internal error -- send timeout for now */ + sta_info_destroy_addr(sdata, mgmt->bssid); + cfg80211_put_bss(*bss); + return RX_MGMT_CFG80211_ASSOC_TIMEOUT; + } + } + + return RX_MGMT_CFG80211_RX_ASSOC; +} static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, @@ -1710,7 +2263,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *channel; bool need_ps = false; - if (sdata->u.mgd.associated) { + if (sdata->u.mgd.associated && + memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, + ETH_ALEN) == 0) { bss = (void *)sdata->u.mgd.associated->priv; /* not previously set so we may need to recalc */ need_ps = !bss->dtim_period; @@ -1780,6 +2335,15 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, if (ifmgd->associated && memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0) ieee80211_reset_ap_probe(sdata); + + if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies && + memcmp(mgmt->bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN) == 0) { + /* got probe response, continue with auth */ + printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); + ifmgd->auth_data->tries = 0; + ifmgd->auth_data->timeout = jiffies; + run_again(ifmgd, ifmgd->auth_data->timeout); + } } /* @@ -1819,7 +2383,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, u32 ncrc; u8 *bssid; - ASSERT_MGD_MTX(ifmgd); + lockdep_assert_held(&ifmgd->mtx); /* Process beacon from the current BSS */ baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; @@ -1829,21 +2393,25 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, if (rx_status->freq != local->hw.conf.channel->center_freq) return; - /* - * We might have received a number of frames, among them a - * disassoc frame and a beacon... - */ - if (!ifmgd->associated) - return; + if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && + memcmp(mgmt->bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN) == 0) { + ieee802_11_parse_elems(mgmt->u.beacon.variable, + len - baselen, &elems); - bssid = ifmgd->associated->bssid; + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, + false); + ifmgd->assoc_data->have_beacon = true; + ifmgd->assoc_data->sent_assoc = false; + /* continue assoc process */ + ifmgd->assoc_data->timeout = jiffies; + run_again(ifmgd, ifmgd->assoc_data->timeout); + return; + } - /* - * And in theory even frames from a different AP we were just - * associated to a split-second ago! - */ - if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) + if (!ifmgd->associated || + memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN)) return; + bssid = ifmgd->associated->bssid; /* Track average RSSI from the Beacon frames of the current AP */ ifmgd->last_beacon_signal = rx_status->signal; @@ -2027,6 +2595,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_rx_status *rx_status; struct ieee80211_mgmt *mgmt; + struct cfg80211_bss *bss = NULL; enum rx_mgmt_action rma = RX_MGMT_NONE; u16 fc; @@ -2036,92 +2605,59 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, mutex_lock(&ifmgd->mtx); - if (ifmgd->associated && - memcmp(ifmgd->associated->bssid, mgmt->bssid, ETH_ALEN) == 0) { - switch (fc & IEEE80211_FCTL_STYPE) { - case IEEE80211_STYPE_BEACON: - ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, - rx_status); - break; - case IEEE80211_STYPE_PROBE_RESP: - ieee80211_rx_mgmt_probe_resp(sdata, skb); - break; - case IEEE80211_STYPE_DEAUTH: - rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); - break; - case IEEE80211_STYPE_DISASSOC: - rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); - break; - case IEEE80211_STYPE_ACTION: - switch (mgmt->u.action.category) { - case WLAN_CATEGORY_SPECTRUM_MGMT: - ieee80211_sta_process_chanswitch(sdata, - &mgmt->u.action.u.chan_switch.sw_elem, - (void *)ifmgd->associated->priv, - rx_status->mactime); - break; - } - } - mutex_unlock(&ifmgd->mtx); - - switch (rma) { - case RX_MGMT_NONE: - /* no action */ - break; - case RX_MGMT_CFG80211_DEAUTH: - cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); - break; - case RX_MGMT_CFG80211_DISASSOC: - cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); + switch (fc & IEEE80211_FCTL_STYPE) { + case IEEE80211_STYPE_BEACON: + ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); + break; + case IEEE80211_STYPE_PROBE_RESP: + ieee80211_rx_mgmt_probe_resp(sdata, skb); + break; + case IEEE80211_STYPE_AUTH: + rma = ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len); + break; + case IEEE80211_STYPE_DEAUTH: + rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); + break; + case IEEE80211_STYPE_DISASSOC: + rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); + break; + case IEEE80211_STYPE_ASSOC_RESP: + case IEEE80211_STYPE_REASSOC_RESP: + 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: + ieee80211_sta_process_chanswitch(sdata, + &mgmt->u.action.u.chan_switch.sw_elem, + (void *)ifmgd->associated->priv, + rx_status->mactime); break; - default: - WARN(1, "unexpected: %d", rma); } - return; } - mutex_unlock(&ifmgd->mtx); - if (skb->len >= 24 + 2 /* mgmt + deauth reason */ && - (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) { - struct ieee80211_local *local = sdata->local; - struct ieee80211_work *wk; - - mutex_lock(&local->mtx); - list_for_each_entry(wk, &local->work_list, list) { - if (wk->sdata != sdata) - continue; - - if (wk->type != IEEE80211_WORK_ASSOC && - wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) - continue; - - if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN)) - continue; - if (memcmp(mgmt->sa, wk->filter_ta, ETH_ALEN)) - continue; - - /* - * Printing the message only here means we can't - * spuriously print it, but it also means that it - * won't be printed when the frame comes in before - * we even tried to associate or in similar cases. - * - * Ultimately, I suspect cfg80211 should print the - * messages instead. - */ - printk(KERN_DEBUG - "%s: deauthenticated from %pM (Reason: %u)\n", - sdata->name, mgmt->bssid, - le16_to_cpu(mgmt->u.deauth.reason_code)); - - list_del_rcu(&wk->list); - free_work(wk); - break; - } - mutex_unlock(&local->mtx); - + switch (rma) { + case RX_MGMT_NONE: + /* no action */ + break; + case RX_MGMT_CFG80211_DEAUTH: cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); + break; + case RX_MGMT_CFG80211_DISASSOC: + cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); + break; + case RX_MGMT_CFG80211_RX_AUTH: + cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, skb->len); + break; + case RX_MGMT_CFG80211_RX_ASSOC: + cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, skb->len); + break; + case RX_MGMT_CFG80211_ASSOC_TIMEOUT: + cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); + break; + default: + WARN(1, "unexpected: %d", rma); } } @@ -2166,14 +2702,160 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, mutex_lock(&ifmgd->mtx); } +static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data; + + lockdep_assert_held(&ifmgd->mtx); + + if (WARN_ON_ONCE(!auth_data)) + return -EINVAL; + + if (!auth_data->synced) { + int ret = drv_tx_sync(local, sdata, auth_data->bss->bssid, + IEEE80211_TX_SYNC_AUTH); + if (ret) + return ret; + } + auth_data->synced = true; + + auth_data->tries++; + + if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { + printk(KERN_DEBUG "%s: authentication with %pM timed out\n", + sdata->name, auth_data->bss->bssid); + + /* + * Most likely AP is not in the range so remove the + * bss struct for that AP. + */ + cfg80211_unlink_bss(local->hw.wiphy, auth_data->bss); + + return -ETIMEDOUT; + } + + if (auth_data->bss->proberesp_ies) { + printk(KERN_DEBUG "%s: send auth to %pM (try %d/%d)\n", + sdata->name, auth_data->bss->bssid, auth_data->tries, + IEEE80211_AUTH_MAX_TRIES); + + auth_data->expected_transaction = 2; + ieee80211_send_auth(sdata, 1, auth_data->algorithm, + auth_data->ie, auth_data->ie_len, + auth_data->bss->bssid, + auth_data->bss->bssid, NULL, 0, 0); + } else { + const u8 *ssidie; + + printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n", + sdata->name, auth_data->bss->bssid, auth_data->tries, + IEEE80211_AUTH_MAX_TRIES); + + ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); + if (!ssidie) + return -EINVAL; + /* + * Direct probe is sent to broadcast address as some APs + * will not answer to direct packet in unassociated state. + */ + ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], + NULL, 0, (u32) -1, true, false); + } + + auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; + run_again(ifmgd, auth_data->timeout); + + return 0; +} + +static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; + struct ieee80211_local *local = sdata->local; + + lockdep_assert_held(&sdata->u.mgd.mtx); + + if (!assoc_data->synced) { + int ret = drv_tx_sync(local, sdata, assoc_data->bss->bssid, + IEEE80211_TX_SYNC_ASSOC); + if (ret) + return ret; + } + assoc_data->synced = true; + + assoc_data->tries++; + if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { + printk(KERN_DEBUG "%s: association with %pM timed out\n", + sdata->name, assoc_data->bss->bssid); + + /* + * Most likely AP is not in the range so remove the + * bss struct for that AP. + */ + cfg80211_unlink_bss(local->hw.wiphy, assoc_data->bss); + + return -ETIMEDOUT; + } + + printk(KERN_DEBUG "%s: associate with %pM (try %d/%d)\n", + sdata->name, assoc_data->bss->bssid, assoc_data->tries, + IEEE80211_ASSOC_MAX_TRIES); + ieee80211_send_assoc(sdata); + + assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; + run_again(&sdata->u.mgd, assoc_data->timeout); + + return 0; +} + void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - /* then process the rest of the work */ mutex_lock(&ifmgd->mtx); + if (ifmgd->auth_data && + time_after(jiffies, ifmgd->auth_data->timeout)) { + if (ifmgd->auth_data->done) { + /* + * ok ... we waited for assoc but userspace didn't, + * so let's just kill the auth data + */ + ieee80211_destroy_auth_data(sdata, false); + } else if (ieee80211_probe_auth(sdata)) { + u8 bssid[ETH_ALEN]; + + memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN); + + ieee80211_destroy_auth_data(sdata, false); + + mutex_unlock(&ifmgd->mtx); + cfg80211_send_auth_timeout(sdata->dev, bssid); + mutex_lock(&ifmgd->mtx); + } + } else if (ifmgd->auth_data) + run_again(ifmgd, ifmgd->auth_data->timeout); + + if (ifmgd->assoc_data && + time_after(jiffies, ifmgd->assoc_data->timeout)) { + if (!ifmgd->assoc_data->have_beacon || + ieee80211_do_assoc(sdata)) { + u8 bssid[ETH_ALEN]; + + memcpy(bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN); + + ieee80211_destroy_assoc_data(sdata, false); + + mutex_unlock(&ifmgd->mtx); + cfg80211_send_assoc_timeout(sdata->dev, bssid); + mutex_lock(&ifmgd->mtx); + } + } else if (ifmgd->assoc_data) + run_again(ifmgd, ifmgd->assoc_data->timeout); + if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | IEEE80211_STA_CONNECTION_POLL) && ifmgd->associated) { @@ -2249,6 +2931,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) } mutex_unlock(&ifmgd->mtx); + + mutex_lock(&local->mtx); + ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); } static void ieee80211_sta_bcn_mon_timer(unsigned long data) @@ -2421,50 +3107,24 @@ int ieee80211_max_network_latency(struct notifier_block *nb, } /* config hooks */ -static enum work_done_result -ieee80211_probe_auth_done(struct ieee80211_work *wk, - struct sk_buff *skb) -{ - struct ieee80211_local *local = wk->sdata->local; - - if (!skb) { - cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta); - goto destroy; - } - - if (wk->type == IEEE80211_WORK_AUTH) { - cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len); - goto destroy; - } - - mutex_lock(&wk->sdata->u.mgd.mtx); - ieee80211_rx_mgmt_probe_resp(wk->sdata, skb); - mutex_unlock(&wk->sdata->u.mgd.mtx); - - wk->type = IEEE80211_WORK_AUTH; - wk->probe_auth.tries = 0; - return WORK_DONE_REQUEUE; - destroy: - if (wk->probe_auth.synced) - drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, - IEEE80211_TX_SYNC_AUTH); - - return WORK_DONE_DESTROY; -} - int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, struct cfg80211_auth_request *req) { - const u8 *ssid; - struct ieee80211_work *wk; + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_mgd_auth_data *auth_data; + struct sta_info *sta; u16 auth_alg; + int err; + + /* prepare auth data structure */ switch (req->auth_type) { case NL80211_AUTHTYPE_OPEN_SYSTEM: auth_alg = WLAN_AUTH_OPEN; break; case NL80211_AUTHTYPE_SHARED_KEY: - if (IS_ERR(sdata->local->wep_tx_tfm)) + if (IS_ERR(local->wep_tx_tfm)) return -EOPNOTSUPP; auth_alg = WLAN_AUTH_SHARED_KEY; break; @@ -2478,169 +3138,142 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, return -EOPNOTSUPP; } - wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL); - if (!wk) + auth_data = kzalloc(sizeof(*auth_data) + req->ie_len, GFP_KERNEL); + if (!auth_data) return -ENOMEM; - memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); + auth_data->bss = req->bss; if (req->ie && req->ie_len) { - memcpy(wk->ie, req->ie, req->ie_len); - wk->ie_len = req->ie_len; + memcpy(auth_data->ie, req->ie, req->ie_len); + auth_data->ie_len = req->ie_len; } if (req->key && req->key_len) { - wk->probe_auth.key_len = req->key_len; - wk->probe_auth.key_idx = req->key_idx; - memcpy(wk->probe_auth.key, req->key, req->key_len); + auth_data->key_len = req->key_len; + auth_data->key_idx = req->key_idx; + memcpy(auth_data->key, req->key, req->key_len); } - ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); - memcpy(wk->probe_auth.ssid, ssid + 2, ssid[1]); - wk->probe_auth.ssid_len = ssid[1]; - - wk->probe_auth.algorithm = auth_alg; - wk->probe_auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY; - - /* if we already have a probe, don't probe again */ - if (req->bss->proberesp_ies) - wk->type = IEEE80211_WORK_AUTH; - else - wk->type = IEEE80211_WORK_DIRECT_PROBE; - wk->chan = req->bss->channel; - wk->chan_type = NL80211_CHAN_NO_HT; - wk->sdata = sdata; - wk->done = ieee80211_probe_auth_done; - - ieee80211_add_work(wk); - return 0; -} + auth_data->algorithm = auth_alg; -/* create and insert a dummy station entry */ -static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata, - u8 *bssid) { - struct sta_info *sta; - int err; + /* try to authenticate/probe */ - sta = sta_info_alloc(sdata, bssid, GFP_KERNEL); - if (!sta) - return -ENOMEM; + mutex_lock(&ifmgd->mtx); - err = sta_info_insert(sta); - sta = NULL; - if (err) { - printk(KERN_DEBUG "%s: failed to insert STA entry for" - " the AP (error %d)\n", sdata->name, err); - return err; + if ((ifmgd->auth_data && !ifmgd->auth_data->done) || + ifmgd->assoc_data) { + err = -EBUSY; + goto err_free; } - return 0; -} + if (ifmgd->auth_data) + ieee80211_destroy_auth_data(sdata, false); -static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, - struct sk_buff *skb) -{ - struct ieee80211_local *local = wk->sdata->local; - struct ieee80211_mgmt *mgmt; - struct ieee80211_rx_status *rx_status; - struct ieee802_11_elems elems; - struct cfg80211_bss *cbss = wk->assoc.bss; - u16 status; + /* prep auth_data so we don't go into idle on disassoc */ + ifmgd->auth_data = auth_data; - if (!skb) { - sta_info_destroy_addr(wk->sdata, cbss->bssid); - cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); - goto destroy; - } + if (ifmgd->associated) + ieee80211_set_disassoc(sdata, true, false); - if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) { - mutex_lock(&wk->sdata->u.mgd.mtx); - rx_status = (void *) skb->cb; - ieee802_11_parse_elems(skb->data + 24 + 12, skb->len - 24 - 12, &elems); - ieee80211_rx_bss_info(wk->sdata, (void *)skb->data, skb->len, rx_status, - &elems, true); - mutex_unlock(&wk->sdata->u.mgd.mtx); + printk(KERN_DEBUG "%s: authenticate with %pM\n", + sdata->name, req->bss->bssid); - wk->type = IEEE80211_WORK_ASSOC; - /* not really done yet */ - return WORK_DONE_REQUEUE; - } + mutex_lock(&local->mtx); + ieee80211_recalc_idle(sdata->local); + mutex_unlock(&local->mtx); - mgmt = (void *)skb->data; - status = le16_to_cpu(mgmt->u.assoc_resp.status_code); + /* switch to the right channel */ + local->oper_channel = req->bss->channel; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - if (status == WLAN_STATUS_SUCCESS) { - if (wk->assoc.synced) - drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, - IEEE80211_TX_SYNC_ASSOC); + /* set BSSID */ + memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); - mutex_lock(&wk->sdata->u.mgd.mtx); - if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { - mutex_unlock(&wk->sdata->u.mgd.mtx); - /* oops -- internal error -- send timeout for now */ - sta_info_destroy_addr(wk->sdata, cbss->bssid); - cfg80211_send_assoc_timeout(wk->sdata->dev, - wk->filter_ta); - return WORK_DONE_DESTROY; - } + /* add station entry */ + sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL); + if (!sta) { + err = -ENOMEM; + goto err_clear; + } - mutex_unlock(&wk->sdata->u.mgd.mtx); - } else { - /* assoc failed - destroy the dummy station entry */ - sta_info_destroy_addr(wk->sdata, cbss->bssid); + err = sta_info_insert(sta); + if (err) { + printk(KERN_DEBUG + "%s: failed to insert STA entry for the AP %pM (error %d)\n", + sdata->name, req->bss->bssid, err); + goto err_clear; } - cfg80211_send_rx_assoc(wk->sdata->dev, cbss, skb->data, skb->len); - destroy: - if (wk->assoc.synced) - drv_finish_tx_sync(local, wk->sdata, wk->filter_ta, - IEEE80211_TX_SYNC_ASSOC); + err = ieee80211_probe_auth(sdata); + if (err) { + if (auth_data->synced) + drv_finish_tx_sync(local, sdata, req->bss->bssid, + IEEE80211_TX_SYNC_AUTH); + sta_info_destroy_addr(sdata, req->bss->bssid); + goto err_clear; + } + + /* hold our own reference */ + cfg80211_ref_bss(auth_data->bss); + err = 0; + goto out_unlock; + + err_clear: + ifmgd->auth_data = NULL; + err_free: + kfree(auth_data); + out_unlock: + mutex_unlock(&ifmgd->mtx); - return WORK_DONE_DESTROY; + return err; } int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, struct cfg80211_assoc_request *req) { + struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_bss *bss = (void *)req->bss->priv; - struct ieee80211_work *wk; - const u8 *ssid; + struct ieee80211_mgd_assoc_data *assoc_data; + struct sta_info *sta; + const u8 *ssidie; int i, err; + ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); + if (!ssidie) + return -EINVAL; + + assoc_data = kzalloc(sizeof(*assoc_data) + req->ie_len, GFP_KERNEL); + if (!assoc_data) + return -ENOMEM; + mutex_lock(&ifmgd->mtx); - if (ifmgd->associated) { - if (!req->prev_bssid || - memcmp(req->prev_bssid, ifmgd->associated->bssid, - ETH_ALEN)) { - /* - * We are already associated and the request was not a - * reassociation request from the current BSS, so - * reject it. - */ - mutex_unlock(&ifmgd->mtx); - return -EALREADY; - } - /* Trying to reassociate - clear previous association state */ + if (ifmgd->associated) ieee80211_set_disassoc(sdata, true, false); + + if (ifmgd->auth_data && !ifmgd->auth_data->done) { + err = -EBUSY; + goto err_free; } - mutex_unlock(&ifmgd->mtx); - wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL); - if (!wk) - return -ENOMEM; + if (ifmgd->assoc_data) { + err = -EBUSY; + goto err_free; + } - /* - * create a dummy station info entry in order - * to start accepting incoming EAPOL packets from the station - */ - err = ieee80211_pre_assoc(sdata, req->bss->bssid); - if (err) { - kfree(wk); - return err; + if (ifmgd->auth_data) { + bool match; + + /* keep sta info, bssid if matching */ + match = memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN) == 0; + ieee80211_destroy_auth_data(sdata, match); } + /* prepare assoc data */ + ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; @@ -2652,7 +3285,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) ifmgd->flags |= IEEE80211_STA_DISABLE_11N; - if (req->flags & ASSOC_REQ_DISABLE_HT) ifmgd->flags |= IEEE80211_STA_DISABLE_11N; @@ -2661,16 +3293,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, sizeof(ifmgd->ht_capa_mask)); if (req->ie && req->ie_len) { - memcpy(wk->ie, req->ie, req->ie_len); - wk->ie_len = req->ie_len; - } else - wk->ie_len = 0; - - wk->assoc.bss = req->bss; + memcpy(assoc_data->ie, req->ie, req->ie_len); + assoc_data->ie_len = req->ie_len; + } - memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); + assoc_data->bss = req->bss; - /* new association always uses requested smps mode */ if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { if (ifmgd->powersave) ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; @@ -2679,7 +3307,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, } else ifmgd->ap_smps = ifmgd->req_smps; - wk->assoc.smps = ifmgd->ap_smps; /* * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. * We still associate in non-HT mode (11a/b/g) if any one of these @@ -2687,39 +3314,27 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, * We can set this to true for non-11n hardware, that'll be checked * separately along with the peer capabilities. */ - wk->assoc.use_11n = !(ifmgd->flags & IEEE80211_STA_DISABLE_11N); - wk->assoc.capability = req->bss->capability; - wk->assoc.wmm_used = bss->wmm_used; - wk->assoc.supp_rates = bss->supp_rates; - wk->assoc.supp_rates_len = bss->supp_rates_len; - wk->assoc.ht_information_ie = + assoc_data->capability = req->bss->capability; + assoc_data->wmm_used = bss->wmm_used; + assoc_data->supp_rates = bss->supp_rates; + assoc_data->supp_rates_len = bss->supp_rates_len; + assoc_data->ht_information_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION); if (bss->wmm_used && bss->uapsd_supported && (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { - wk->assoc.uapsd_used = true; + assoc_data->uapsd_used = true; ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; } else { - wk->assoc.uapsd_used = false; + assoc_data->uapsd_used = false; ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; } - ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); - memcpy(wk->assoc.ssid, ssid + 2, ssid[1]); - wk->assoc.ssid_len = ssid[1]; + memcpy(assoc_data->ssid, ssidie + 2, ssidie[1]); + assoc_data->ssid_len = ssidie[1]; if (req->prev_bssid) - memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN); - - wk->chan = req->bss->channel; - wk->chan_type = NL80211_CHAN_NO_HT; - wk->sdata = sdata; - wk->done = ieee80211_assoc_done; - if (!bss->dtim_period && - sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) - wk->type = IEEE80211_WORK_ASSOC_BEACON_WAIT; - else - wk->type = IEEE80211_WORK_ASSOC; + memcpy(assoc_data->prev_bssid, req->prev_bssid, ETH_ALEN); if (req->use_mfp) { ifmgd->mfp = IEEE80211_MFP_REQUIRED; @@ -2737,15 +3352,79 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, sdata->control_port_protocol = req->crypto.control_port_ethertype; sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt; - ieee80211_add_work(wk); - return 0; + /* kick off associate process */ + + ifmgd->assoc_data = assoc_data; + + mutex_lock(&local->mtx); + ieee80211_recalc_idle(sdata->local); + mutex_unlock(&local->mtx); + + /* switch to the right channel */ + local->oper_channel = req->bss->channel; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + + rcu_read_lock(); + sta = sta_info_get(sdata, req->bss->bssid); + rcu_read_unlock(); + + if (!sta) { + /* set BSSID */ + memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); + + sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL); + if (!sta) { + err = -ENOMEM; + goto err_clear; + } + + sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); + + err = sta_info_insert(sta); + sta = NULL; + if (err) { + printk(KERN_DEBUG + "%s: failed to insert STA entry for the AP (error %d)\n", + sdata->name, err); + goto err_clear; + } + } else + WARN_ON_ONCE(memcmp(ifmgd->bssid, req->bss->bssid, ETH_ALEN)); + + if (!bss->dtim_period && + sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { + /* + * Wait up to one beacon interval ... + * should this be more if we miss one? + */ + printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", + sdata->name, ifmgd->bssid); + assoc_data->timeout = jiffies + + TU_TO_EXP_TIME(req->bss->beacon_interval); + } else { + assoc_data->have_beacon = true; + assoc_data->sent_assoc = false; + assoc_data->timeout = jiffies; + } + run_again(ifmgd, assoc_data->timeout); + + err = 0; + goto out; + err_clear: + ifmgd->assoc_data = NULL; + err_free: + kfree(assoc_data); + out: + mutex_unlock(&ifmgd->mtx); + + return err; } int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, struct cfg80211_deauth_request *req, void *cookie) { - struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; bool assoc_bss = false; @@ -2754,62 +3433,13 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, if (ifmgd->associated && memcmp(ifmgd->associated->bssid, req->bssid, ETH_ALEN) == 0) { ieee80211_set_disassoc(sdata, false, true); - mutex_unlock(&ifmgd->mtx); assoc_bss = true; - } else { - bool not_auth_yet = false; - struct ieee80211_work *tmp, *wk = NULL; - + } else if (ifmgd->auth_data) { + ieee80211_destroy_auth_data(sdata, false); mutex_unlock(&ifmgd->mtx); - - mutex_lock(&local->mtx); - list_for_each_entry(tmp, &local->work_list, list) { - if (tmp->sdata != sdata) - continue; - - if (tmp->type != IEEE80211_WORK_DIRECT_PROBE && - tmp->type != IEEE80211_WORK_AUTH && - tmp->type != IEEE80211_WORK_ASSOC && - tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) - continue; - - if (memcmp(req->bssid, tmp->filter_ta, ETH_ALEN)) - continue; - - not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE; - list_del_rcu(&tmp->list); - synchronize_rcu(); - wk = tmp; - break; - } - mutex_unlock(&local->mtx); - - if (wk && wk->type == IEEE80211_WORK_ASSOC) { - /* clean up dummy sta & TX sync */ - sta_info_destroy_addr(wk->sdata, wk->filter_ta); - if (wk->assoc.synced) - drv_finish_tx_sync(local, wk->sdata, - wk->filter_ta, - IEEE80211_TX_SYNC_ASSOC); - } else if (wk && wk->type == IEEE80211_WORK_AUTH) { - if (wk->probe_auth.synced) - drv_finish_tx_sync(local, wk->sdata, - wk->filter_ta, - IEEE80211_TX_SYNC_AUTH); - } - kfree(wk); - - /* - * If somebody requests authentication and we haven't - * sent out an auth frame yet there's no need to send - * out a deauth frame either. If the state was PROBE, - * then this is the case. If it's AUTH we have sent a - * frame, and if it's IDLE we have completed the auth - * process already. - */ - if (not_auth_yet) - return 0; + return 0; } + mutex_unlock(&ifmgd->mtx); printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", sdata->name, req->bssid, req->reason_code); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 8d6fa674f53..2b5b1194dfc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2484,14 +2484,9 @@ static ieee80211_rx_result debug_noinline ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) { struct ieee80211_sub_if_data *sdata = rx->sdata; - ieee80211_rx_result rxs; struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; __le16 stype; - rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); - if (rxs != RX_CONTINUE) - return rxs; - stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE); if (!ieee80211_vif_is_mesh(&sdata->vif) && @@ -2500,10 +2495,13 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) return RX_DROP_MONITOR; switch (stype) { + case cpu_to_le16(IEEE80211_STYPE_AUTH): case cpu_to_le16(IEEE80211_STYPE_BEACON): case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): /* process for all: mesh, mlme, ibss */ break; + case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): + case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): case cpu_to_le16(IEEE80211_STYPE_DEAUTH): case cpu_to_le16(IEEE80211_STYPE_DISASSOC): if (is_multicast_ether_addr(mgmt->da) && @@ -2515,7 +2513,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) return RX_DROP_MONITOR; break; case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): - case cpu_to_le16(IEEE80211_STYPE_AUTH): /* process only for ibss */ if (sdata->vif.type != NL80211_IFTYPE_ADHOC) return RX_DROP_MONITOR; diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 0a1a176fbe9..c6e230efa04 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -27,16 +27,9 @@ #include "rate.h" #include "driver-ops.h" -#define IEEE80211_AUTH_TIMEOUT (HZ / 5) -#define IEEE80211_AUTH_MAX_TRIES 3 -#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) -#define IEEE80211_ASSOC_MAX_TRIES 3 - enum work_action { - WORK_ACT_MISMATCH, WORK_ACT_NONE, WORK_ACT_TIMEOUT, - WORK_ACT_DONE, }; @@ -71,465 +64,6 @@ void free_work(struct ieee80211_work *wk) kfree_rcu(wk, rcu_head); } -static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, - struct ieee80211_supported_band *sband, - u32 *rates) -{ - int i, j, count; - *rates = 0; - count = 0; - for (i = 0; i < supp_rates_len; i++) { - int rate = (supp_rates[i] & 0x7F) * 5; - - for (j = 0; j < sband->n_bitrates; j++) - if (sband->bitrates[j].bitrate == rate) { - *rates |= BIT(j); - count++; - break; - } - } - - return count; -} - -/* frame sending functions */ - -static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb, const u8 *ht_info_ie, - struct ieee80211_supported_band *sband, - struct ieee80211_channel *channel, - enum ieee80211_smps_mode smps) -{ - struct ieee80211_ht_info *ht_info; - u8 *pos; - u32 flags = channel->flags; - u16 cap; - struct ieee80211_sta_ht_cap ht_cap; - - BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); - - if (!sband->ht_cap.ht_supported) - return; - - if (!ht_info_ie) - return; - - if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) - return; - - memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); - ieee80211_apply_htcap_overrides(sdata, &ht_cap); - - ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); - - /* determine capability flags */ - cap = ht_cap.cap; - - switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - if (flags & IEEE80211_CHAN_NO_HT40PLUS) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - if (flags & IEEE80211_CHAN_NO_HT40MINUS) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - break; - } - - /* set SM PS mode properly */ - cap &= ~IEEE80211_HT_CAP_SM_PS; - switch (smps) { - case IEEE80211_SMPS_AUTOMATIC: - case IEEE80211_SMPS_NUM_MODES: - WARN_ON(1); - case IEEE80211_SMPS_OFF: - cap |= WLAN_HT_CAP_SM_PS_DISABLED << - IEEE80211_HT_CAP_SM_PS_SHIFT; - break; - case IEEE80211_SMPS_STATIC: - cap |= WLAN_HT_CAP_SM_PS_STATIC << - IEEE80211_HT_CAP_SM_PS_SHIFT; - break; - case IEEE80211_SMPS_DYNAMIC: - cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << - IEEE80211_HT_CAP_SM_PS_SHIFT; - break; - } - - /* reserve and fill IE */ - pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); - ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); -} - -static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, - struct ieee80211_work *wk) -{ - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - u8 *pos, qos_info; - size_t offset = 0, noffset; - int i, count, rates_len, supp_rates_len; - u16 capab; - struct ieee80211_supported_band *sband; - u32 rates = 0; - - sband = local->hw.wiphy->bands[wk->chan->band]; - - if (wk->assoc.supp_rates_len) { - /* - * Get all rates supported by the device and the AP as - * some APs don't like getting a superset of their rates - * in the association request (e.g. D-Link DAP 1353 in - * b-only mode)... - */ - rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, - wk->assoc.supp_rates_len, - sband, &rates); - } else { - /* - * In case AP not provide any supported rates information - * before association, we send information element(s) with - * all rates that we support. - */ - rates = ~0; - rates_len = sband->n_bitrates; - } - - skb = alloc_skb(local->hw.extra_tx_headroom + - sizeof(*mgmt) + /* bit too much but doesn't matter */ - 2 + wk->assoc.ssid_len + /* SSID */ - 4 + rates_len + /* (extended) rates */ - 4 + /* power capability */ - 2 + 2 * sband->n_channels + /* supported channels */ - 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ - wk->ie_len + /* extra IEs */ - 9, /* WMM */ - GFP_KERNEL); - if (!skb) - return; - - skb_reserve(skb, local->hw.extra_tx_headroom); - - capab = WLAN_CAPABILITY_ESS; - - if (sband->band == IEEE80211_BAND_2GHZ) { - if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) - capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; - if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) - capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; - } - - if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY) - capab |= WLAN_CAPABILITY_PRIVACY; - - if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && - (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) - capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, wk->filter_ta, ETH_ALEN); - memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); - memcpy(mgmt->bssid, wk->filter_ta, ETH_ALEN); - - if (!is_zero_ether_addr(wk->assoc.prev_bssid)) { - skb_put(skb, 10); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_REASSOC_REQ); - mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); - mgmt->u.reassoc_req.listen_interval = - cpu_to_le16(local->hw.conf.listen_interval); - memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid, - ETH_ALEN); - } else { - skb_put(skb, 4); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ASSOC_REQ); - mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); - mgmt->u.assoc_req.listen_interval = - cpu_to_le16(local->hw.conf.listen_interval); - } - - /* SSID */ - pos = skb_put(skb, 2 + wk->assoc.ssid_len); - *pos++ = WLAN_EID_SSID; - *pos++ = wk->assoc.ssid_len; - memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len); - - /* add all rates which were marked to be used above */ - supp_rates_len = rates_len; - if (supp_rates_len > 8) - supp_rates_len = 8; - - pos = skb_put(skb, supp_rates_len + 2); - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = supp_rates_len; - - count = 0; - for (i = 0; i < sband->n_bitrates; i++) { - if (BIT(i) & rates) { - int rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); - if (++count == 8) - break; - } - } - - if (rates_len > count) { - pos = skb_put(skb, rates_len - count + 2); - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = rates_len - count; - - for (i++; i < sband->n_bitrates; i++) { - if (BIT(i) & rates) { - int rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); - } - } - } - - if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { - /* 1. power capabilities */ - pos = skb_put(skb, 4); - *pos++ = WLAN_EID_PWR_CAPABILITY; - *pos++ = 2; - *pos++ = 0; /* min tx power */ - *pos++ = wk->chan->max_power; /* max tx power */ - - /* 2. supported channels */ - /* TODO: get this in reg domain format */ - pos = skb_put(skb, 2 * sband->n_channels + 2); - *pos++ = WLAN_EID_SUPPORTED_CHANNELS; - *pos++ = 2 * sband->n_channels; - for (i = 0; i < sband->n_channels; i++) { - *pos++ = ieee80211_frequency_to_channel( - sband->channels[i].center_freq); - *pos++ = 1; /* one channel in the subband*/ - } - } - - /* if present, add any custom IEs that go before HT */ - if (wk->ie_len && wk->ie) { - static const u8 before_ht[] = { - WLAN_EID_SSID, - WLAN_EID_SUPP_RATES, - WLAN_EID_EXT_SUPP_RATES, - WLAN_EID_PWR_CAPABILITY, - WLAN_EID_SUPPORTED_CHANNELS, - WLAN_EID_RSN, - WLAN_EID_QOS_CAPA, - WLAN_EID_RRM_ENABLED_CAPABILITIES, - WLAN_EID_MOBILITY_DOMAIN, - WLAN_EID_SUPPORTED_REGULATORY_CLASSES, - }; - noffset = ieee80211_ie_split(wk->ie, wk->ie_len, - before_ht, ARRAY_SIZE(before_ht), - offset); - pos = skb_put(skb, noffset - offset); - memcpy(pos, wk->ie + offset, noffset - offset); - offset = noffset; - } - - if (wk->assoc.use_11n && wk->assoc.wmm_used && - local->hw.queues >= 4) - ieee80211_add_ht_ie(sdata, skb, wk->assoc.ht_information_ie, - sband, wk->chan, wk->assoc.smps); - - /* if present, add any custom non-vendor IEs that go after HT */ - if (wk->ie_len && wk->ie) { - noffset = ieee80211_ie_split_vendor(wk->ie, wk->ie_len, - offset); - pos = skb_put(skb, noffset - offset); - memcpy(pos, wk->ie + offset, noffset - offset); - offset = noffset; - } - - if (wk->assoc.wmm_used && local->hw.queues >= 4) { - if (wk->assoc.uapsd_used) { - qos_info = local->uapsd_queues; - qos_info |= (local->uapsd_max_sp_len << - IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT); - } else { - qos_info = 0; - } - - pos = skb_put(skb, 9); - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = 7; /* len */ - *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ - *pos++ = 0x50; - *pos++ = 0xf2; - *pos++ = 2; /* WME */ - *pos++ = 0; /* WME info */ - *pos++ = 1; /* WME ver */ - *pos++ = qos_info; - } - - /* add any remaining custom (i.e. vendor specific here) IEs */ - if (wk->ie_len && wk->ie) { - noffset = wk->ie_len; - pos = skb_put(skb, noffset - offset); - memcpy(pos, wk->ie + offset, noffset - offset); - } - - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; - ieee80211_tx_skb(sdata, skb); -} - -static void ieee80211_remove_auth_bss(struct ieee80211_local *local, - struct ieee80211_work *wk) -{ - struct cfg80211_bss *cbss; - u16 capa_val = WLAN_CAPABILITY_ESS; - - if (wk->probe_auth.privacy) - capa_val |= WLAN_CAPABILITY_PRIVACY; - - cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->filter_ta, - wk->probe_auth.ssid, wk->probe_auth.ssid_len, - WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY, - capa_val); - if (!cbss) - return; - - cfg80211_unlink_bss(local->hw.wiphy, cbss); - cfg80211_put_bss(cbss); -} - -static enum work_action __must_check -ieee80211_direct_probe(struct ieee80211_work *wk) -{ - struct ieee80211_sub_if_data *sdata = wk->sdata; - struct ieee80211_local *local = sdata->local; - - if (!wk->probe_auth.synced) { - int ret = drv_tx_sync(local, sdata, wk->filter_ta, - IEEE80211_TX_SYNC_AUTH); - if (ret) - return WORK_ACT_TIMEOUT; - } - wk->probe_auth.synced = true; - - wk->probe_auth.tries++; - if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { - printk(KERN_DEBUG "%s: direct probe to %pM timed out\n", - sdata->name, wk->filter_ta); - - /* - * Most likely AP is not in the range so remove the - * bss struct for that AP. - */ - ieee80211_remove_auth_bss(local, wk); - - return WORK_ACT_TIMEOUT; - } - - printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n", - sdata->name, wk->filter_ta, wk->probe_auth.tries, - IEEE80211_AUTH_MAX_TRIES); - - /* - * Direct probe is sent to broadcast address as some APs - * will not answer to direct packet in unassociated state. - */ - ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, - wk->probe_auth.ssid_len, NULL, 0, - (u32) -1, true, false); - - wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; - run_again(local, wk->timeout); - - return WORK_ACT_NONE; -} - - -static enum work_action __must_check -ieee80211_authenticate(struct ieee80211_work *wk) -{ - struct ieee80211_sub_if_data *sdata = wk->sdata; - struct ieee80211_local *local = sdata->local; - - if (!wk->probe_auth.synced) { - int ret = drv_tx_sync(local, sdata, wk->filter_ta, - IEEE80211_TX_SYNC_AUTH); - if (ret) - return WORK_ACT_TIMEOUT; - } - wk->probe_auth.synced = true; - - wk->probe_auth.tries++; - if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { - printk(KERN_DEBUG "%s: authentication with %pM" - " timed out\n", sdata->name, wk->filter_ta); - - /* - * Most likely AP is not in the range so remove the - * bss struct for that AP. - */ - ieee80211_remove_auth_bss(local, wk); - - return WORK_ACT_TIMEOUT; - } - - printk(KERN_DEBUG "%s: authenticate with %pM (try %d)\n", - sdata->name, wk->filter_ta, wk->probe_auth.tries); - - ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie, - wk->ie_len, wk->filter_ta, wk->filter_ta, NULL, 0, - 0); - wk->probe_auth.transaction = 2; - - wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; - run_again(local, wk->timeout); - - return WORK_ACT_NONE; -} - -static enum work_action __must_check -ieee80211_associate(struct ieee80211_work *wk) -{ - struct ieee80211_sub_if_data *sdata = wk->sdata; - struct ieee80211_local *local = sdata->local; - - if (!wk->assoc.synced) { - int ret = drv_tx_sync(local, sdata, wk->filter_ta, - IEEE80211_TX_SYNC_ASSOC); - if (ret) - return WORK_ACT_TIMEOUT; - } - wk->assoc.synced = true; - - wk->assoc.tries++; - if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { - printk(KERN_DEBUG "%s: association with %pM" - " timed out\n", - sdata->name, wk->filter_ta); - - /* - * Most likely AP is not in the range so remove the - * bss struct for that AP. - */ - if (wk->assoc.bss) - cfg80211_unlink_bss(local->hw.wiphy, wk->assoc.bss); - - return WORK_ACT_TIMEOUT; - } - - printk(KERN_DEBUG "%s: associate with %pM (try %d)\n", - sdata->name, wk->filter_ta, wk->assoc.tries); - ieee80211_send_assoc(sdata, wk); - - wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; - run_again(local, wk->timeout); - - return WORK_ACT_NONE; -} - static enum work_action __must_check ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) { @@ -569,300 +103,6 @@ ieee80211_offchannel_tx(struct ieee80211_work *wk) return WORK_ACT_TIMEOUT; } -static enum work_action __must_check -ieee80211_assoc_beacon_wait(struct ieee80211_work *wk) -{ - if (wk->started) - return WORK_ACT_TIMEOUT; - - /* - * Wait up to one beacon interval ... - * should this be more if we miss one? - */ - printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", - wk->sdata->name, wk->filter_ta); - wk->timeout = TU_TO_EXP_TIME(wk->assoc.bss->beacon_interval); - return WORK_ACT_NONE; -} - -static void ieee80211_auth_challenge(struct ieee80211_work *wk, - struct ieee80211_mgmt *mgmt, - size_t len) -{ - struct ieee80211_sub_if_data *sdata = wk->sdata; - u8 *pos; - struct ieee802_11_elems elems; - - pos = mgmt->u.auth.variable; - ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); - if (!elems.challenge) - return; - ieee80211_send_auth(sdata, 3, wk->probe_auth.algorithm, - elems.challenge - 2, elems.challenge_len + 2, - wk->filter_ta, wk->filter_ta, wk->probe_auth.key, - wk->probe_auth.key_len, wk->probe_auth.key_idx); - wk->probe_auth.transaction = 4; -} - -static enum work_action __must_check -ieee80211_rx_mgmt_auth(struct ieee80211_work *wk, - struct ieee80211_mgmt *mgmt, size_t len) -{ - u16 auth_alg, auth_transaction, status_code; - - if (wk->type != IEEE80211_WORK_AUTH) - return WORK_ACT_MISMATCH; - - if (len < 24 + 6) - return WORK_ACT_NONE; - - auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); - auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); - status_code = le16_to_cpu(mgmt->u.auth.status_code); - - if (auth_alg != wk->probe_auth.algorithm || - auth_transaction != wk->probe_auth.transaction) - return WORK_ACT_NONE; - - if (status_code != WLAN_STATUS_SUCCESS) { - printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", - wk->sdata->name, mgmt->sa, status_code); - return WORK_ACT_DONE; - } - - switch (wk->probe_auth.algorithm) { - case WLAN_AUTH_OPEN: - case WLAN_AUTH_LEAP: - case WLAN_AUTH_FT: - break; - case WLAN_AUTH_SHARED_KEY: - if (wk->probe_auth.transaction != 4) { - ieee80211_auth_challenge(wk, mgmt, len); - /* need another frame */ - return WORK_ACT_NONE; - } - break; - default: - WARN_ON(1); - return WORK_ACT_NONE; - } - - printk(KERN_DEBUG "%s: authenticated\n", wk->sdata->name); - return WORK_ACT_DONE; -} - -static enum work_action __must_check -ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, - struct ieee80211_mgmt *mgmt, size_t len, - bool reassoc) -{ - struct ieee80211_sub_if_data *sdata = wk->sdata; - struct ieee80211_local *local = sdata->local; - u16 capab_info, status_code, aid; - struct ieee802_11_elems elems; - u8 *pos; - - if (wk->type != IEEE80211_WORK_ASSOC) - return WORK_ACT_MISMATCH; - - /* - * AssocResp and ReassocResp have identical structure, so process both - * of them in this function. - */ - - if (len < 24 + 6) - return WORK_ACT_NONE; - - capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); - status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); - aid = le16_to_cpu(mgmt->u.assoc_resp.aid); - - printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " - "status=%d aid=%d)\n", - sdata->name, reassoc ? "Rea" : "A", mgmt->sa, - 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); - - if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && - elems.timeout_int && elems.timeout_int_len == 5 && - elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { - u32 tu, ms; - tu = get_unaligned_le32(elems.timeout_int + 1); - ms = tu * 1024 / 1000; - printk(KERN_DEBUG "%s: %pM rejected association temporarily; " - "comeback duration %u TU (%u ms)\n", - sdata->name, mgmt->sa, tu, ms); - wk->timeout = jiffies + msecs_to_jiffies(ms); - if (ms > IEEE80211_ASSOC_TIMEOUT) - run_again(local, wk->timeout); - return WORK_ACT_NONE; - } - - if (status_code != WLAN_STATUS_SUCCESS) - printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n", - sdata->name, mgmt->sa, status_code); - else - printk(KERN_DEBUG "%s: associated\n", sdata->name); - - return WORK_ACT_DONE; -} - -static enum work_action __must_check -ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk, - struct ieee80211_mgmt *mgmt, size_t len, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_sub_if_data *sdata = wk->sdata; - struct ieee80211_local *local = sdata->local; - size_t baselen; - - ASSERT_WORK_MTX(local); - - if (wk->type != IEEE80211_WORK_DIRECT_PROBE) - return WORK_ACT_MISMATCH; - - if (len < 24 + 12) - return WORK_ACT_NONE; - - baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; - if (baselen > len) - return WORK_ACT_NONE; - - printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); - return WORK_ACT_DONE; -} - -static enum work_action __must_check -ieee80211_rx_mgmt_beacon(struct ieee80211_work *wk, - struct ieee80211_mgmt *mgmt, size_t len) -{ - struct ieee80211_sub_if_data *sdata = wk->sdata; - struct ieee80211_local *local = sdata->local; - - ASSERT_WORK_MTX(local); - - if (wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT) - return WORK_ACT_MISMATCH; - - if (len < 24 + 12) - return WORK_ACT_NONE; - - printk(KERN_DEBUG "%s: beacon received\n", sdata->name); - return WORK_ACT_DONE; -} - -static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, - struct sk_buff *skb) -{ - struct ieee80211_rx_status *rx_status; - struct ieee80211_mgmt *mgmt; - struct ieee80211_work *wk; - enum work_action rma = WORK_ACT_NONE; - u16 fc; - - rx_status = (struct ieee80211_rx_status *) skb->cb; - mgmt = (struct ieee80211_mgmt *) skb->data; - fc = le16_to_cpu(mgmt->frame_control); - - mutex_lock(&local->mtx); - - list_for_each_entry(wk, &local->work_list, list) { - const u8 *bssid = NULL; - - switch (wk->type) { - case IEEE80211_WORK_DIRECT_PROBE: - case IEEE80211_WORK_AUTH: - case IEEE80211_WORK_ASSOC: - case IEEE80211_WORK_ASSOC_BEACON_WAIT: - bssid = wk->filter_ta; - break; - default: - continue; - } - - /* - * Before queuing, we already verified mgmt->sa, - * so this is needed just for matching. - */ - if (compare_ether_addr(bssid, mgmt->bssid)) - continue; - - switch (fc & IEEE80211_FCTL_STYPE) { - case IEEE80211_STYPE_BEACON: - rma = ieee80211_rx_mgmt_beacon(wk, mgmt, skb->len); - break; - case IEEE80211_STYPE_PROBE_RESP: - rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len, - rx_status); - break; - case IEEE80211_STYPE_AUTH: - rma = ieee80211_rx_mgmt_auth(wk, mgmt, skb->len); - break; - case IEEE80211_STYPE_ASSOC_RESP: - rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt, - skb->len, false); - break; - case IEEE80211_STYPE_REASSOC_RESP: - rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt, - skb->len, true); - break; - default: - WARN_ON(1); - rma = WORK_ACT_NONE; - } - - /* - * We've either received an unexpected frame, or we have - * multiple work items and need to match the frame to the - * right one. - */ - if (rma == WORK_ACT_MISMATCH) - continue; - - /* - * We've processed this frame for that work, so it can't - * belong to another work struct. - * NB: this is also required for correctness for 'rma'! - */ - break; - } - - switch (rma) { - case WORK_ACT_MISMATCH: - /* ignore this unmatched frame */ - break; - case WORK_ACT_NONE: - break; - case WORK_ACT_DONE: - list_del_rcu(&wk->list); - break; - default: - WARN(1, "unexpected: %d", rma); - } - - mutex_unlock(&local->mtx); - - if (rma != WORK_ACT_DONE) - goto out; - - switch (wk->done(wk, skb)) { - case WORK_DONE_DESTROY: - free_work(wk); - break; - case WORK_DONE_REQUEUE: - synchronize_rcu(); - wk->started = false; /* restart */ - mutex_lock(&local->mtx); - list_add_tail(&wk->list, &local->work_list); - mutex_unlock(&local->mtx); - } - - out: - kfree_skb(skb); -} - static void ieee80211_work_timer(unsigned long data) { struct ieee80211_local *local = (void *) data; @@ -877,7 +117,6 @@ static void ieee80211_work_work(struct work_struct *work) { struct ieee80211_local *local = container_of(work, struct ieee80211_local, work_work); - struct sk_buff *skb; struct ieee80211_work *wk, *tmp; LIST_HEAD(free_work); enum work_action rma; @@ -893,10 +132,6 @@ static void ieee80211_work_work(struct work_struct *work) if (WARN(local->suspended, "work scheduled while going to suspend\n")) return; - /* first process frames to avoid timing out while a frame is pending */ - while ((skb = skb_dequeue(&local->work_skb_queue))) - ieee80211_work_rx_queued_mgmt(local, skb); - mutex_lock(&local->mtx); ieee80211_recalc_idle(local); @@ -947,24 +182,12 @@ static void ieee80211_work_work(struct work_struct *work) case IEEE80211_WORK_ABORT: rma = WORK_ACT_TIMEOUT; break; - case IEEE80211_WORK_DIRECT_PROBE: - rma = ieee80211_direct_probe(wk); - break; - case IEEE80211_WORK_AUTH: - rma = ieee80211_authenticate(wk); - break; - case IEEE80211_WORK_ASSOC: - rma = ieee80211_associate(wk); - break; case IEEE80211_WORK_REMAIN_ON_CHANNEL: rma = ieee80211_remain_on_channel_timeout(wk); break; case IEEE80211_WORK_OFFCHANNEL_TX: rma = ieee80211_offchannel_tx(wk); break; - case IEEE80211_WORK_ASSOC_BEACON_WAIT: - rma = ieee80211_assoc_beacon_wait(wk); - break; } wk->started = started; @@ -1052,7 +275,6 @@ void ieee80211_work_init(struct ieee80211_local *local) setup_timer(&local->work_timer, ieee80211_work_timer, (unsigned long)local); INIT_WORK(&local->work_work, ieee80211_work_work); - skb_queue_head_init(&local->work_skb_queue); } void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) @@ -1086,43 +308,6 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) mutex_unlock(&local->mtx); } -ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_mgmt *mgmt; - struct ieee80211_work *wk; - u16 fc; - - if (skb->len < 24) - return RX_DROP_MONITOR; - - mgmt = (struct ieee80211_mgmt *) skb->data; - fc = le16_to_cpu(mgmt->frame_control); - - list_for_each_entry_rcu(wk, &local->work_list, list) { - if (sdata != wk->sdata) - continue; - if (compare_ether_addr(wk->filter_ta, mgmt->sa)) - continue; - if (compare_ether_addr(wk->filter_ta, mgmt->bssid)) - continue; - - switch (fc & IEEE80211_FCTL_STYPE) { - case IEEE80211_STYPE_AUTH: - case IEEE80211_STYPE_PROBE_RESP: - case IEEE80211_STYPE_ASSOC_RESP: - case IEEE80211_STYPE_REASSOC_RESP: - case IEEE80211_STYPE_BEACON: - skb_queue_tail(&local->work_skb_queue, skb); - ieee80211_queue_work(&local->hw, &local->work_work); - return RX_QUEUED; - } - } - - return RX_CONTINUE; -} - static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk, struct sk_buff *skb) { -- cgit v1.2.3 From 5718b134b1fe09087ca225b0e475ef65536d02b4 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Mon, 30 Jan 2012 22:52:10 +0900 Subject: net: Fix typo in ipw2x00/libipw_rx.c Correct spelling in "suppported" to "supported" in drivers/net/wireless/ipw2x00/libipw_rx.c Signed-off-by: Masanari Iida Reviewed-by: Jesper Juhl Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/libipw_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 32a9966c3bf..c4955d25a19 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -172,7 +172,7 @@ libipw_rx_frame_mgmt(struct libipw_device *ieee, struct sk_buff *skb, u16 stype) { if (ieee->iw_mode == IW_MODE_MASTER) { - printk(KERN_DEBUG "%s: Master mode not yet suppported.\n", + printk(KERN_DEBUG "%s: Master mode not yet supported.\n", ieee->dev->name); return 0; /* -- cgit v1.2.3 From 7f4666ab3fd656513bffd449410a4d7c189081ec Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 30 Jan 2012 16:17:56 +0100 Subject: rt2800: radio 3xxx: reprogram only lower bits of RF_R3 Synchronize code with Ralink driver: 2011_0719_RT3070_RT3370_RT5370_RT5372_Linux_STA_V2.5.0.3_DPO (functions: RT33xx_ChipSwitchChannel() and RT30xx_ChipSwitchChannel()) Acked-by: Gertjan van Wingerde Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 5 +++++ drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 2571a2fa3d0..abf2ae58816 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1795,6 +1795,11 @@ struct mac_iveiv_entry { */ #define RFCSR2_RESCAL_EN FIELD8(0x80) +/* + * RFCSR 3: + */ +#define RFCSR3_K FIELD8(0x0f) + /* * FRCSR 5: */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 165535cc507..006347e4d6e 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1648,7 +1648,10 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, u8 rfcsr; rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); - rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3); + + rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR3_K, rf->rf3); + rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2); -- cgit v1.2.3 From e3bab197622276faac83eac3dfb993967d8d47e3 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 30 Jan 2012 16:17:57 +0100 Subject: rt2800: radio 3xxx: program RF_R1 during channel switch Synchronize code with Ralink driver: 2011_0719_RT3070_RT3370_RT5370_RT5372_Linux_STA_V2.5.0.3_DPO Based on functions: RT33xx_ChipSwitchChannel RT30xx_ChipSwitchChannel RT33xx_Init Signed-off-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 006347e4d6e..1bdf1ec33cd 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1665,6 +1665,40 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2); rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); + rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); + if (rt2x00_rt(rt2x00dev, RT3390)) { + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, + rt2x00dev->default_ant.rx_chain_num == 1); + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, + rt2x00dev->default_ant.tx_chain_num == 1); + } else { + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); + + switch (rt2x00dev->default_ant.tx_chain_num) { + case 1: + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); + /* fall through */ + case 2: + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); + break; + } + + switch (rt2x00dev->default_ant.rx_chain_num) { + case 1: + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); + /* fall through */ + case 2: + rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); + break; + } + } + rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); -- cgit v1.2.3 From 3e0c7643c561c7052430f5c033d5b1b1289c962e Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 30 Jan 2012 16:17:58 +0100 Subject: rt2800: radio 3xxx: add channel switch calibration routines Synchronize code with Ralink driver: 2011_0719_RT3070_RT3370_RT5370_RT5372_Linux_STA_V2.5.0.3_DPO Based on functions: RT33xx_ChipSwitchChannel RT30xx_ChipSwitchChannel Acked-by: Gertjan van Wingerde Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 1bdf1ec33cd..0076bc7a9b3 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1699,6 +1699,13 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, } rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + 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); + rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); @@ -1709,6 +1716,13 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); + + 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); } static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, -- cgit v1.2.3 From f1f12f9894c48dc8284762bc71e4a3ed5caf546f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 30 Jan 2012 16:17:59 +0100 Subject: rt2800: radio 3xxxx: channel switch RX/TX calibration fixes Synchronize code with Ralink driver: 2011_0719_RT3070_RT3370_RT5370_RT5372_Linux_STA_V2.5.0.3_DPO Based on functions: RT30xx_ChipSwitchChannel RT33xx_ChipSwitchChannel NICInitRT3370RFRegisters and defines from: include/chip/rt33xx.h Signed-off-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 8 ++++++++ drivers/net/wireless/rt2x00/rt2800lib.c | 19 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index abf2ae58816..c92fb2eee92 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1871,6 +1871,13 @@ struct mac_iveiv_entry { */ #define RFCSR23_FREQ_OFFSET FIELD8(0x7f) +/* + * RFCSR 24: + */ +#define RFCSR24_TX_AGC_FC FIELD8(0x1f) +#define RFCSR24_TX_H20M FIELD8(0x20) +#define RFCSR24_TX_CALIB FIELD8(0x7f) + /* * RFCSR 27: */ @@ -1892,6 +1899,7 @@ struct mac_iveiv_entry { */ #define RFCSR31_RX_AGC_FC FIELD8(0x1f) #define RFCSR31_RX_H20M FIELD8(0x20) +#define RFCSR31_RX_CALIB FIELD8(0x7f) /* * RFCSR 38: diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 0076bc7a9b3..c326e7b1c37 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1645,7 +1645,7 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, struct rf_channel *rf, struct channel_info *info) { - u8 rfcsr; + u8 rfcsr, calib_tx, calib_rx; rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); @@ -1710,8 +1710,21 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); - rt2800_rfcsr_write(rt2x00dev, 24, - rt2x00dev->calibration[conf_is_ht40(conf)]); + if (rt2x00_rt(rt2x00dev, RT3390)) { + calib_tx = conf_is_ht40(conf) ? 0x68 : 0x4f; + calib_rx = conf_is_ht40(conf) ? 0x6f : 0x4f; + } else { + calib_tx = rt2x00dev->calibration[conf_is_ht40(conf)]; + calib_rx = rt2x00dev->calibration[conf_is_ht40(conf)]; + } + + rt2800_rfcsr_read(rt2x00dev, 24, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR24_TX_CALIB, calib_tx); + rt2800_rfcsr_write(rt2x00dev, 24, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR31_RX_CALIB, calib_rx); + rt2800_rfcsr_write(rt2x00dev, 31, rfcsr); rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); -- cgit v1.2.3 From 268bd858df5052f97722b123e990119c89171fd7 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 1 Feb 2012 16:17:40 +0100 Subject: rt2800: document RF_R03 register bits [7:4] Taken from: 2011_0719_RT3070_RT3370_RT5370_RT5372_Linux_STA_V2.5.0.3_DPO (based on function RT33xx_ChipSwitchChannel) Signed-off-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index c92fb2eee92..fac9ece22b2 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1799,6 +1799,9 @@ struct mac_iveiv_entry { * RFCSR 3: */ #define RFCSR3_K FIELD8(0x0f) +/* Bits [7-4] for RF3320 (RT3370/RT3390), on other chipsets reserved */ +#define RFCSR3_PA1_BIAS_CCK FIELD8(0x70); +#define RFCSR3_PA2_CASCODE_BIAS_CCKK FIELD8(0x80); /* * FRCSR 5: -- cgit v1.2.3 From 5f2d6171e1e70584b9819771443485750453fd16 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 31 Jan 2012 00:03:31 +0100 Subject: bcma: add the core unit number Some SoCs have two pcie or gmac cores and we need to know the number of the specific core on the bus. This is the case for the BCM4706. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/scan.c | 14 ++++++++++++++ include/linux/bcma/bcma.h | 1 + 2 files changed, 15 insertions(+) diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index cad99485768..e513aa83ec2 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -212,6 +212,17 @@ static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus, return NULL; } +static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 coreid) +{ + struct bcma_device *core; + + list_for_each_entry_reverse(core, &bus->cores, list) { + if (core->id.id == coreid) + return core; + } + return NULL; +} + static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, struct bcma_device_id *match, int core_num, struct bcma_device *core) @@ -392,6 +403,7 @@ int bcma_bus_scan(struct bcma_bus *bus) bcma_scan_switch_core(bus, erombase); while (eromptr < eromend) { + struct bcma_device *other_core; struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL); if (!core) return -ENOMEM; @@ -411,6 +423,8 @@ int bcma_bus_scan(struct bcma_bus *bus) core->core_index = core_num++; bus->nr_cores++; + other_core = bcma_find_core_reverse(bus, core->id.id); + core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1; pr_info("Core %d found: %s " "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 83c209f3949..024a6e2a908 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -136,6 +136,7 @@ struct bcma_device { bool dev_registered; u8 core_index; + u8 core_unit; u32 addr; u32 wrap; -- cgit v1.2.3 From 2be25cac8402fab56bb51166f464d1b420bcf744 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 31 Jan 2012 00:03:32 +0100 Subject: bcma: add constants for PCI and use them There are many magic numbers used in the PCIe code. Replace them with some constants from the Broadcom SDK and also use them in the pcie host controller. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/driver_pci.c | 124 ++++++++++++++++++++--------------- include/linux/bcma/bcma_driver_pci.h | 85 ++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 54 deletions(-) diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index 4fde6254f04..fc462b4a099 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c @@ -4,6 +4,7 @@ * * Copyright 2005, Broadcom Corporation * Copyright 2006, 2007, Michael Buesch + * Copyright 2011, 2012, Hauke Mehrtens * * Licensed under the GNU/GPL. See COPYING for details. */ @@ -18,38 +19,39 @@ static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) { - pcicore_write32(pc, 0x130, address); - pcicore_read32(pc, 0x130); - return pcicore_read32(pc, 0x134); + pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address); + pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR); + return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA); } #if 0 static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) { - pcicore_write32(pc, 0x130, address); - pcicore_read32(pc, 0x130); - pcicore_write32(pc, 0x134, data); + pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address); + pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR); + pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data); } #endif static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) { - const u16 mdio_control = 0x128; - const u16 mdio_data = 0x12C; u32 v; int i; - v = (1 << 30); /* Start of Transaction */ - v |= (1 << 28); /* Write Transaction */ - v |= (1 << 17); /* Turnaround */ - v |= (0x1F << 18); + v = BCMA_CORE_PCI_MDIODATA_START; + v |= BCMA_CORE_PCI_MDIODATA_WRITE; + v |= (BCMA_CORE_PCI_MDIODATA_DEV_ADDR << + BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF); + v |= (BCMA_CORE_PCI_MDIODATA_BLK_ADDR << + BCMA_CORE_PCI_MDIODATA_REGADDR_SHF); + v |= BCMA_CORE_PCI_MDIODATA_TA; v |= (phy << 4); - pcicore_write32(pc, mdio_data, v); + pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v); udelay(10); for (i = 0; i < 200; i++) { - v = pcicore_read32(pc, mdio_control); - if (v & 0x100 /* Trans complete */) + v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); + if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) break; msleep(1); } @@ -57,79 +59,84 @@ static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) { - const u16 mdio_control = 0x128; - const u16 mdio_data = 0x12C; int max_retries = 10; u16 ret = 0; u32 v; int i; - v = 0x80; /* Enable Preamble Sequence */ - v |= 0x2; /* MDIO Clock Divisor */ - pcicore_write32(pc, mdio_control, v); + /* enable mdio access to SERDES */ + v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN; + v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL; + pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v); if (pc->core->id.rev >= 10) { max_retries = 200; bcma_pcie_mdio_set_phy(pc, device); + v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR << + BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF); + v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF); + } else { + v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD); + v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD); } - v = (1 << 30); /* Start of Transaction */ - v |= (1 << 29); /* Read Transaction */ - v |= (1 << 17); /* Turnaround */ - if (pc->core->id.rev < 10) - v |= (u32)device << 22; - v |= (u32)address << 18; - pcicore_write32(pc, mdio_data, v); + v = BCMA_CORE_PCI_MDIODATA_START; + v |= BCMA_CORE_PCI_MDIODATA_READ; + v |= BCMA_CORE_PCI_MDIODATA_TA; + + pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v); /* Wait for the device to complete the transaction */ udelay(10); for (i = 0; i < max_retries; i++) { - v = pcicore_read32(pc, mdio_control); - if (v & 0x100 /* Trans complete */) { + v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); + if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) { udelay(10); - ret = pcicore_read32(pc, mdio_data); + ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA); break; } msleep(1); } - pcicore_write32(pc, mdio_control, 0); + pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); return ret; } static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, u8 address, u16 data) { - const u16 mdio_control = 0x128; - const u16 mdio_data = 0x12C; int max_retries = 10; u32 v; int i; - v = 0x80; /* Enable Preamble Sequence */ - v |= 0x2; /* MDIO Clock Divisor */ - pcicore_write32(pc, mdio_control, v); + /* enable mdio access to SERDES */ + v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN; + v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL; + pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v); if (pc->core->id.rev >= 10) { max_retries = 200; bcma_pcie_mdio_set_phy(pc, device); + v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR << + BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF); + v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF); + } else { + v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD); + v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD); } - v = (1 << 30); /* Start of Transaction */ - v |= (1 << 28); /* Write Transaction */ - v |= (1 << 17); /* Turnaround */ - if (pc->core->id.rev < 10) - v |= (u32)device << 22; - v |= (u32)address << 18; + v = BCMA_CORE_PCI_MDIODATA_START; + v |= BCMA_CORE_PCI_MDIODATA_WRITE; + v |= BCMA_CORE_PCI_MDIODATA_TA; v |= data; - pcicore_write32(pc, mdio_data, v); + pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v); /* Wait for the device to complete the transaction */ udelay(10); for (i = 0; i < max_retries; i++) { - v = pcicore_read32(pc, mdio_control); - if (v & 0x100 /* Trans complete */) + v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); + if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) break; msleep(1); } - pcicore_write32(pc, mdio_control, 0); + pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); } /************************************************** @@ -138,20 +145,29 @@ static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc) { - return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; + u32 tmp; + + tmp = bcma_pcie_read(pc, BCMA_CORE_PCI_PLP_STATUSREG); + if (tmp & BCMA_CORE_PCI_PLP_POLARITYINV_STAT) + return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE | + BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY; + else + return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE; } static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) { - const u8 serdes_pll_device = 0x1D; - const u8 serdes_rx_device = 0x1F; u16 tmp; - bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, - bcma_pcicore_polarity_workaround(pc)); - tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); - if (tmp & 0x4000) - bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); + bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_RX, + BCMA_CORE_PCI_SERDES_RX_CTRL, + bcma_pcicore_polarity_workaround(pc)); + tmp = bcma_pcie_mdio_read(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL, + BCMA_CORE_PCI_SERDES_PLL_CTRL); + if (tmp & BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN) + bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL, + BCMA_CORE_PCI_SERDES_PLL_CTRL, + tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN); } /************************************************** diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h index 3871b668caf..67ea7beff9f 100644 --- a/include/linux/bcma/bcma_driver_pci.h +++ b/include/linux/bcma/bcma_driver_pci.h @@ -53,6 +53,35 @@ struct pci_dev; #define BCMA_CORE_PCI_SBTOPCI1_MASK 0xFC000000 #define BCMA_CORE_PCI_SBTOPCI2 0x0108 /* Backplane to PCI translation 2 (sbtopci2) */ #define BCMA_CORE_PCI_SBTOPCI2_MASK 0xC0000000 +#define BCMA_CORE_PCI_CONFIG_ADDR 0x0120 /* pcie config space access */ +#define BCMA_CORE_PCI_CONFIG_DATA 0x0124 /* pcie config space access */ +#define BCMA_CORE_PCI_MDIO_CONTROL 0x0128 /* controls the mdio access */ +#define BCMA_CORE_PCI_MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */ +#define BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL 0x2 +#define BCMA_CORE_PCI_MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */ +#define BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE 0x100 /* Tranaction complete */ +#define BCMA_CORE_PCI_MDIO_DATA 0x012c /* Data to the mdio access */ +#define BCMA_CORE_PCI_MDIODATA_MASK 0x0000ffff /* data 2 bytes */ +#define BCMA_CORE_PCI_MDIODATA_TA 0x00020000 /* Turnaround */ +#define BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift (rev < 10) */ +#define BCMA_CORE_PCI_MDIODATA_REGADDR_MASK_OLD 0x003c0000 /* Regaddr Mask (rev < 10) */ +#define BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift (rev < 10) */ +#define BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK_OLD 0x0fc00000 /* Physmedia devaddr Mask (rev < 10) */ +#define BCMA_CORE_PCI_MDIODATA_REGADDR_SHF 18 /* Regaddr shift */ +#define BCMA_CORE_PCI_MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */ +#define BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */ +#define BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK 0x0f800000 /* Physmedia devaddr Mask */ +#define BCMA_CORE_PCI_MDIODATA_WRITE 0x10000000 /* write Transaction */ +#define BCMA_CORE_PCI_MDIODATA_READ 0x20000000 /* Read Transaction */ +#define BCMA_CORE_PCI_MDIODATA_START 0x40000000 /* start of Transaction */ +#define BCMA_CORE_PCI_MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */ +#define BCMA_CORE_PCI_MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */ +#define BCMA_CORE_PCI_MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */ +#define BCMA_CORE_PCI_MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */ +#define BCMA_CORE_PCI_MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */ +#define BCMA_CORE_PCI_PCIEIND_ADDR 0x0130 /* indirect access to the internal register */ +#define BCMA_CORE_PCI_PCIEIND_DATA 0x0134 /* Data to/from the internal regsiter */ +#define BCMA_CORE_PCI_CLKREQENCTRL 0x0138 /* >= rev 6, Clkreq rdma control */ #define BCMA_CORE_PCI_PCICFG0 0x0400 /* PCI config space 0 (rev >= 8) */ #define BCMA_CORE_PCI_PCICFG1 0x0500 /* PCI config space 1 (rev >= 8) */ #define BCMA_CORE_PCI_PCICFG2 0x0600 /* PCI config space 2 (rev >= 8) */ @@ -72,6 +101,62 @@ struct pci_dev; #define BCMA_CORE_PCI_SBTOPCI_RC_READL 0x00000010 /* Memory read line */ #define BCMA_CORE_PCI_SBTOPCI_RC_READM 0x00000020 /* Memory read multiple */ +/* PCIE protocol PHY diagnostic registers */ +#define BCMA_CORE_PCI_PLP_MODEREG 0x200 /* Mode */ +#define BCMA_CORE_PCI_PLP_STATUSREG 0x204 /* Status */ +#define BCMA_CORE_PCI_PLP_POLARITYINV_STAT 0x10 /* Status reg PCIE_PLP_STATUSREG */ +#define BCMA_CORE_PCI_PLP_LTSSMCTRLREG 0x208 /* LTSSM control */ +#define BCMA_CORE_PCI_PLP_LTLINKNUMREG 0x20c /* Link Training Link number */ +#define BCMA_CORE_PCI_PLP_LTLANENUMREG 0x210 /* Link Training Lane number */ +#define BCMA_CORE_PCI_PLP_LTNFTSREG 0x214 /* Link Training N_FTS */ +#define BCMA_CORE_PCI_PLP_ATTNREG 0x218 /* Attention */ +#define BCMA_CORE_PCI_PLP_ATTNMASKREG 0x21C /* Attention Mask */ +#define BCMA_CORE_PCI_PLP_RXERRCTR 0x220 /* Rx Error */ +#define BCMA_CORE_PCI_PLP_RXFRMERRCTR 0x224 /* Rx Framing Error */ +#define BCMA_CORE_PCI_PLP_RXERRTHRESHREG 0x228 /* Rx Error threshold */ +#define BCMA_CORE_PCI_PLP_TESTCTRLREG 0x22C /* Test Control reg */ +#define BCMA_CORE_PCI_PLP_SERDESCTRLOVRDREG 0x230 /* SERDES Control Override */ +#define BCMA_CORE_PCI_PLP_TIMINGOVRDREG 0x234 /* Timing param override */ +#define BCMA_CORE_PCI_PLP_RXTXSMDIAGREG 0x238 /* RXTX State Machine Diag */ +#define BCMA_CORE_PCI_PLP_LTSSMDIAGREG 0x23C /* LTSSM State Machine Diag */ + +/* PCIE protocol DLLP diagnostic registers */ +#define BCMA_CORE_PCI_DLLP_LCREG 0x100 /* Link Control */ +#define BCMA_CORE_PCI_DLLP_LSREG 0x104 /* Link Status */ +#define BCMA_CORE_PCI_DLLP_LAREG 0x108 /* Link Attention */ +#define BCMA_CORE_PCI_DLLP_LSREG_LINKUP (1 << 16) +#define BCMA_CORE_PCI_DLLP_LAMASKREG 0x10C /* Link Attention Mask */ +#define BCMA_CORE_PCI_DLLP_NEXTTXSEQNUMREG 0x110 /* Next Tx Seq Num */ +#define BCMA_CORE_PCI_DLLP_ACKEDTXSEQNUMREG 0x114 /* Acked Tx Seq Num */ +#define BCMA_CORE_PCI_DLLP_PURGEDTXSEQNUMREG 0x118 /* Purged Tx Seq Num */ +#define BCMA_CORE_PCI_DLLP_RXSEQNUMREG 0x11C /* Rx Sequence Number */ +#define BCMA_CORE_PCI_DLLP_LRREG 0x120 /* Link Replay */ +#define BCMA_CORE_PCI_DLLP_LACKTOREG 0x124 /* Link Ack Timeout */ +#define BCMA_CORE_PCI_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */ +#define BCMA_CORE_PCI_DLLP_RTRYWPREG 0x12C /* Retry buffer write ptr */ +#define BCMA_CORE_PCI_DLLP_RTRYRPREG 0x130 /* Retry buffer Read ptr */ +#define BCMA_CORE_PCI_DLLP_RTRYPPREG 0x134 /* Retry buffer Purged ptr */ +#define BCMA_CORE_PCI_DLLP_RTRRWREG 0x138 /* Retry buffer Read/Write */ +#define BCMA_CORE_PCI_DLLP_ECTHRESHREG 0x13C /* Error Count Threshold */ +#define BCMA_CORE_PCI_DLLP_TLPERRCTRREG 0x140 /* TLP Error Counter */ +#define BCMA_CORE_PCI_DLLP_ERRCTRREG 0x144 /* Error Counter */ +#define BCMA_CORE_PCI_DLLP_NAKRXCTRREG 0x148 /* NAK Received Counter */ +#define BCMA_CORE_PCI_DLLP_TESTREG 0x14C /* Test */ +#define BCMA_CORE_PCI_DLLP_PKTBIST 0x150 /* Packet BIST */ +#define BCMA_CORE_PCI_DLLP_PCIE11 0x154 /* DLLP PCIE 1.1 reg */ + +/* SERDES RX registers */ +#define BCMA_CORE_PCI_SERDES_RX_CTRL 1 /* Rx cntrl */ +#define BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */ +#define BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */ +#define BCMA_CORE_PCI_SERDES_RX_TIMER1 2 /* Rx Timer1 */ +#define BCMA_CORE_PCI_SERDES_RX_CDR 6 /* CDR */ +#define BCMA_CORE_PCI_SERDES_RX_CDRBW 7 /* CDR BW */ + +/* SERDES PLL registers */ +#define BCMA_CORE_PCI_SERDES_PLL_CTRL 1 /* PLL control reg */ +#define BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */ + /* PCIcore specific boardflags */ #define BCMA_CORE_PCI_BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ -- cgit v1.2.3 From 4b259a5cc5ea967fa243dfc1f95a59ae74106f5b Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 31 Jan 2012 00:03:33 +0100 Subject: bcma: export bcma_pcie_read() This will be needed by the host controller. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/bcma_private.h | 3 +++ drivers/bcma/driver_pci.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 0def898a1d1..6109da5d883 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -48,6 +48,9 @@ extern int __init bcma_host_pci_init(void); extern void __exit bcma_host_pci_exit(void); #endif /* CONFIG_BCMA_HOST_PCI */ +/* driver_pci.c */ +u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address); + #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index fc462b4a099..22dc9fca6dc 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c @@ -17,7 +17,7 @@ * R/W ops. **************************************************/ -static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) +u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) { pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address); pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR); -- cgit v1.2.3 From d1a7a8e1d367e34e5adce91f48cae07dc08d9e6c Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 31 Jan 2012 00:03:34 +0100 Subject: bcma: make some functions __devinit bcma_core_pci_hostmode_init() has to be in __devinit as it will call a function in that section and so all functions calling it also have to be in __devinit. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/bcma_private.h | 4 ++-- drivers/bcma/driver_pci.c | 6 +++--- drivers/bcma/driver_pci_host.c | 2 +- drivers/bcma/host_pci.c | 4 ++-- drivers/bcma/main.c | 2 +- include/linux/bcma/bcma_driver_pci.h | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 6109da5d883..63c5242159f 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -13,7 +13,7 @@ struct bcma_bus; /* main.c */ -int bcma_bus_register(struct bcma_bus *bus); +int __devinit bcma_bus_register(struct bcma_bus *bus); void bcma_bus_unregister(struct bcma_bus *bus); int __init bcma_bus_early_register(struct bcma_bus *bus, struct bcma_device *core_cc, @@ -52,7 +52,7 @@ extern void __exit bcma_host_pci_exit(void); u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address); #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE -void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); +void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ #endif diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index 22dc9fca6dc..155d953dba7 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c @@ -174,12 +174,12 @@ static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) * Init. **************************************************/ -static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) +static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) { bcma_pcicore_serdes_workaround(pc); } -static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) +static bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) { struct bcma_bus *bus = pc->core->bus; u16 chipid_top; @@ -204,7 +204,7 @@ static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) return true; } -void bcma_core_pci_init(struct bcma_drv_pci *pc) +void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc) { if (pc->setup_done) return; diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index eb332b75ce8..99e040b607a 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c @@ -8,7 +8,7 @@ #include "bcma_private.h" #include -void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) +void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) { pr_err("No support for PCI core in hostmode yet\n"); } diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index f59244e3397..e3928d68802 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -154,8 +154,8 @@ const struct bcma_host_ops bcma_host_pci_ops = { .awrite32 = bcma_host_pci_awrite32, }; -static int bcma_host_pci_probe(struct pci_dev *dev, - const struct pci_device_id *id) +static int __devinit bcma_host_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) { struct bcma_bus *bus; int err = -ENOMEM; diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index febbc0a1222..3363036f23d 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -132,7 +132,7 @@ static void bcma_unregister_cores(struct bcma_bus *bus) } } -int bcma_bus_register(struct bcma_bus *bus) +int __devinit bcma_bus_register(struct bcma_bus *bus) { int err; struct bcma_device *core; diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h index 67ea7beff9f..679d4cab454 100644 --- a/include/linux/bcma/bcma_driver_pci.h +++ b/include/linux/bcma/bcma_driver_pci.h @@ -169,7 +169,7 @@ struct bcma_drv_pci { #define pcicore_read32(pc, offset) bcma_read32((pc)->core, offset) #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) -extern void bcma_core_pci_init(struct bcma_drv_pci *pc); +extern void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc); extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, bool enable); -- cgit v1.2.3 From 49dc9577155576b10ff79f0c1486c816b01f58bf Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 31 Jan 2012 00:03:35 +0100 Subject: bcma: add PCIe host controller Some SoCs have a PCIe host controller to make it possible to attach some other devices to it, like an other Wifi card. This code was tested with an Netgear WNDR3400 (bcm4716 based), but should work with all bcma based SoCs. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- arch/mips/pci/pci-bcm47xx.c | 49 ++- drivers/bcma/bcma_private.h | 1 + drivers/bcma/driver_pci.c | 38 +-- drivers/bcma/driver_pci_host.c | 576 ++++++++++++++++++++++++++++++++++- include/linux/bcma/bcma_driver_pci.h | 38 +++ include/linux/bcma/bcma_regs.h | 27 ++ 6 files changed, 690 insertions(+), 39 deletions(-) diff --git a/arch/mips/pci/pci-bcm47xx.c b/arch/mips/pci/pci-bcm47xx.c index 400535a955d..c682468010c 100644 --- a/arch/mips/pci/pci-bcm47xx.c +++ b/arch/mips/pci/pci-bcm47xx.c @@ -25,6 +25,7 @@ #include #include #include +#include #include int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) @@ -32,15 +33,12 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) return 0; } -int pcibios_plat_dev_init(struct pci_dev *dev) -{ #ifdef CONFIG_BCM47XX_SSB +static int bcm47xx_pcibios_plat_dev_init_ssb(struct pci_dev *dev) +{ int res; u8 slot, pin; - if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB) - return 0; - res = ssb_pcibios_plat_dev_init(dev); if (res < 0) { printk(KERN_ALERT "PCI: Failed to init device %s\n", @@ -60,6 +58,47 @@ int pcibios_plat_dev_init(struct pci_dev *dev) } dev->irq = res; + return 0; +} #endif + +#ifdef CONFIG_BCM47XX_BCMA +static int bcm47xx_pcibios_plat_dev_init_bcma(struct pci_dev *dev) +{ + int res; + + res = bcma_core_pci_plat_dev_init(dev); + if (res < 0) { + printk(KERN_ALERT "PCI: Failed to init device %s\n", + pci_name(dev)); + return res; + } + + res = bcma_core_pci_pcibios_map_irq(dev); + + /* IRQ-0 and IRQ-1 are software interrupts. */ + if (res < 2) { + printk(KERN_ALERT "PCI: Failed to map IRQ of device %s\n", + pci_name(dev)); + return res; + } + + dev->irq = res; return 0; } +#endif + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ +#ifdef CONFIG_BCM47XX_SSB + if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_SSB) + return bcm47xx_pcibios_plat_dev_init_ssb(dev); + else +#endif +#ifdef CONFIG_BCM47XX_BCMA + if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) + return bcm47xx_pcibios_plat_dev_init_bcma(dev); + else +#endif + return 0; +} diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 63c5242159f..b81755bb479 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -52,6 +52,7 @@ extern void __exit bcma_host_pci_exit(void); u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address); #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE +bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index 155d953dba7..4d38ae179b4 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c @@ -2,7 +2,7 @@ * Broadcom specific AMBA * PCI Core * - * Copyright 2005, Broadcom Corporation + * Copyright 2005, 2011, Broadcom Corporation * Copyright 2006, 2007, Michael Buesch * Copyright 2011, 2012, Hauke Mehrtens * @@ -179,47 +179,19 @@ static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) bcma_pcicore_serdes_workaround(pc); } -static bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) -{ - struct bcma_bus *bus = pc->core->bus; - u16 chipid_top; - - chipid_top = (bus->chipinfo.id & 0xFF00); - if (chipid_top != 0x4700 && - chipid_top != 0x5300) - return false; - -#ifdef CONFIG_SSB_DRIVER_PCICORE - if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI) - return false; -#endif /* CONFIG_SSB_DRIVER_PCICORE */ - -#if 0 - /* TODO: on BCMA we use address from EROM instead of magic formula */ - u32 tmp; - return !mips_busprobe32(tmp, (bus->mmio + - (pc->core->core_index * BCMA_CORE_SIZE))); -#endif - - return true; -} - void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc) { if (pc->setup_done) return; - if (bcma_core_pci_is_in_hostmode(pc)) { #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE + pc->hostmode = bcma_core_pci_is_in_hostmode(pc); + if (pc->hostmode) bcma_core_pci_hostmode_init(pc); -#else - pr_err("Driver compiled without support for hostmode PCI\n"); #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ - } else { - bcma_core_pci_clientmode_init(pc); - } - pc->setup_done = true; + if (!pc->hostmode) + bcma_core_pci_clientmode_init(pc); } int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index 99e040b607a..4e20bcfa7ec 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c @@ -2,13 +2,587 @@ * Broadcom specific AMBA * PCI Core in hostmode * + * Copyright 2005 - 2011, Broadcom Corporation + * Copyright 2006, 2007, Michael Buesch + * Copyright 2011, 2012, Hauke Mehrtens + * * Licensed under the GNU/GPL. See COPYING for details. */ #include "bcma_private.h" +#include #include +#include + +/* Probe a 32bit value on the bus and catch bus exceptions. + * Returns nonzero on a bus exception. + * This is MIPS specific */ +#define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr))) + +/* Assume one-hot slot wiring */ +#define BCMA_PCI_SLOT_MAX 16 +#define PCI_CONFIG_SPACE_SIZE 256 + +bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) +{ + struct bcma_bus *bus = pc->core->bus; + u16 chipid_top; + u32 tmp; + + chipid_top = (bus->chipinfo.id & 0xFF00); + if (chipid_top != 0x4700 && + chipid_top != 0x5300) + return false; + + if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { + pr_info("This PCI core is disabled and not working\n"); + return false; + } + + bcma_core_enable(pc->core, 0); + + return !mips_busprobe32(tmp, pc->core->io_addr); +} + +static u32 bcma_pcie_read_config(struct bcma_drv_pci *pc, u32 address) +{ + pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address); + pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR); + return pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_DATA); +} + +static void bcma_pcie_write_config(struct bcma_drv_pci *pc, u32 address, + u32 data) +{ + pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address); + pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR); + pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_DATA, data); +} + +static u32 bcma_get_cfgspace_addr(struct bcma_drv_pci *pc, unsigned int dev, + unsigned int func, unsigned int off) +{ + u32 addr = 0; + + /* Issue config commands only when the data link is up (atleast + * one external pcie device is present). + */ + if (dev >= 2 || !(bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_LSREG) + & BCMA_CORE_PCI_DLLP_LSREG_LINKUP)) + goto out; + + /* Type 0 transaction */ + /* Slide the PCI window to the appropriate slot */ + pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0); + /* Calculate the address */ + addr = pc->host_controller->host_cfg_addr; + addr |= (dev << BCMA_CORE_PCI_CFG_SLOT_SHIFT); + addr |= (func << BCMA_CORE_PCI_CFG_FUN_SHIFT); + addr |= (off & ~3); + +out: + return addr; +} + +static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, + unsigned int func, unsigned int off, + void *buf, int len) +{ + int err = -EINVAL; + u32 addr, val; + void __iomem *mmio = 0; + + WARN_ON(!pc->hostmode); + if (unlikely(len != 1 && len != 2 && len != 4)) + goto out; + if (dev == 0) { + /* we support only two functions on device 0 */ + if (func > 1) + return -EINVAL; + + /* accesses to config registers with offsets >= 256 + * requires indirect access. + */ + if (off >= PCI_CONFIG_SPACE_SIZE) { + addr = (func << 12); + addr |= (off & 0x0FFF); + val = bcma_pcie_read_config(pc, addr); + } else { + addr = BCMA_CORE_PCI_PCICFG0; + addr |= (func << 8); + addr |= (off & 0xfc); + val = pcicore_read32(pc, addr); + } + } else { + addr = bcma_get_cfgspace_addr(pc, dev, func, off); + if (unlikely(!addr)) + goto out; + err = -ENOMEM; + mmio = ioremap_nocache(addr, len); + if (!mmio) + goto out; + + if (mips_busprobe32(val, mmio)) { + val = 0xffffffff; + goto unmap; + } + + val = readl(mmio); + } + val >>= (8 * (off & 3)); + + switch (len) { + case 1: + *((u8 *)buf) = (u8)val; + break; + case 2: + *((u16 *)buf) = (u16)val; + break; + case 4: + *((u32 *)buf) = (u32)val; + break; + } + err = 0; +unmap: + if (mmio) + iounmap(mmio); +out: + return err; +} + +static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, + unsigned int func, unsigned int off, + const void *buf, int len) +{ + int err = -EINVAL; + u32 addr = 0, val = 0; + void __iomem *mmio = 0; + u16 chipid = pc->core->bus->chipinfo.id; + + WARN_ON(!pc->hostmode); + if (unlikely(len != 1 && len != 2 && len != 4)) + goto out; + if (dev == 0) { + /* accesses to config registers with offsets >= 256 + * requires indirect access. + */ + if (off < PCI_CONFIG_SPACE_SIZE) { + addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0; + addr |= (func << 8); + addr |= (off & 0xfc); + mmio = ioremap_nocache(addr, len); + if (!mmio) + goto out; + } + } else { + addr = bcma_get_cfgspace_addr(pc, dev, func, off); + if (unlikely(!addr)) + goto out; + err = -ENOMEM; + mmio = ioremap_nocache(addr, len); + if (!mmio) + goto out; + + if (mips_busprobe32(val, mmio)) { + val = 0xffffffff; + goto unmap; + } + } + + switch (len) { + case 1: + val = readl(mmio); + val &= ~(0xFF << (8 * (off & 3))); + val |= *((const u8 *)buf) << (8 * (off & 3)); + break; + case 2: + val = readl(mmio); + val &= ~(0xFFFF << (8 * (off & 3))); + val |= *((const u16 *)buf) << (8 * (off & 3)); + break; + case 4: + val = *((const u32 *)buf); + break; + } + if (dev == 0 && !addr) { + /* accesses to config registers with offsets >= 256 + * requires indirect access. + */ + addr = (func << 12); + addr |= (off & 0x0FFF); + bcma_pcie_write_config(pc, addr, val); + } else { + writel(val, mmio); + + if (chipid == 0x4716 || chipid == 0x4748) + readl(mmio); + } + + err = 0; +unmap: + if (mmio) + iounmap(mmio); +out: + return err; +} + +static int bcma_core_pci_hostmode_read_config(struct pci_bus *bus, + unsigned int devfn, + int reg, int size, u32 *val) +{ + unsigned long flags; + int err; + struct bcma_drv_pci *pc; + struct bcma_drv_pci_host *pc_host; + + pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops); + pc = pc_host->pdev; + + spin_lock_irqsave(&pc_host->cfgspace_lock, flags); + err = bcma_extpci_read_config(pc, PCI_SLOT(devfn), + PCI_FUNC(devfn), reg, val, size); + spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags); + + return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; +} + +static int bcma_core_pci_hostmode_write_config(struct pci_bus *bus, + unsigned int devfn, + int reg, int size, u32 val) +{ + unsigned long flags; + int err; + struct bcma_drv_pci *pc; + struct bcma_drv_pci_host *pc_host; + + pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops); + pc = pc_host->pdev; + + spin_lock_irqsave(&pc_host->cfgspace_lock, flags); + err = bcma_extpci_write_config(pc, PCI_SLOT(devfn), + PCI_FUNC(devfn), reg, &val, size); + spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags); + + return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; +} + +/* return cap_offset if requested capability exists in the PCI config space */ +static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc, + unsigned int dev, + unsigned int func, u8 req_cap_id, + unsigned char *buf, u32 *buflen) +{ + u8 cap_id; + u8 cap_ptr = 0; + u32 bufsize; + u8 byte_val; + + /* check for Header type 0 */ + bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, + sizeof(u8)); + if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) + return cap_ptr; + + /* check if the capability pointer field exists */ + bcma_extpci_read_config(pc, dev, func, PCI_STATUS, &byte_val, + sizeof(u8)); + if (!(byte_val & PCI_STATUS_CAP_LIST)) + return cap_ptr; + + /* check if the capability pointer is 0x00 */ + bcma_extpci_read_config(pc, dev, func, PCI_CAPABILITY_LIST, &cap_ptr, + sizeof(u8)); + if (cap_ptr == 0x00) + return cap_ptr; + + /* loop thr'u the capability list and see if the requested capabilty + * exists */ + bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8)); + while (cap_id != req_cap_id) { + bcma_extpci_read_config(pc, dev, func, cap_ptr + 1, &cap_ptr, + sizeof(u8)); + if (cap_ptr == 0x00) + return cap_ptr; + bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, + sizeof(u8)); + } + + /* found the caller requested capability */ + if ((buf != NULL) && (buflen != NULL)) { + u8 cap_data; + + bufsize = *buflen; + if (!bufsize) + return cap_ptr; + + *buflen = 0; + + /* copy the cpability data excluding cap ID and next ptr */ + cap_data = cap_ptr + 2; + if ((bufsize + cap_data) > PCI_CONFIG_SPACE_SIZE) + bufsize = PCI_CONFIG_SPACE_SIZE - cap_data; + *buflen = bufsize; + while (bufsize--) { + bcma_extpci_read_config(pc, dev, func, cap_data, buf, + sizeof(u8)); + cap_data++; + buf++; + } + } + + return cap_ptr; +} + +/* If the root port is capable of returning Config Request + * Retry Status (CRS) Completion Status to software then + * enable the feature. + */ +static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc) +{ + u8 cap_ptr, root_ctrl, root_cap, dev; + u16 val16; + int i; + + cap_ptr = bcma_find_pci_capability(pc, 0, 0, PCI_CAP_ID_EXP, NULL, + NULL); + root_cap = cap_ptr + PCI_EXP_RTCAP; + bcma_extpci_read_config(pc, 0, 0, root_cap, &val16, sizeof(u16)); + if (val16 & BCMA_CORE_PCI_RC_CRS_VISIBILITY) { + /* Enable CRS software visibility */ + root_ctrl = cap_ptr + PCI_EXP_RTCTL; + val16 = PCI_EXP_RTCTL_CRSSVE; + bcma_extpci_read_config(pc, 0, 0, root_ctrl, &val16, + sizeof(u16)); + + /* Initiate a configuration request to read the vendor id + * field of the device function's config space header after + * 100 ms wait time from the end of Reset. If the device is + * not done with its internal initialization, it must at + * least return a completion TLP, with a completion status + * of "Configuration Request Retry Status (CRS)". The root + * complex must complete the request to the host by returning + * a read-data value of 0001h for the Vendor ID field and + * all 1s for any additional bytes included in the request. + * Poll using the config reads for max wait time of 1 sec or + * until we receive the successful completion status. Repeat + * the procedure for all the devices. + */ + for (dev = 1; dev < BCMA_PCI_SLOT_MAX; dev++) { + for (i = 0; i < 100000; i++) { + bcma_extpci_read_config(pc, dev, 0, + PCI_VENDOR_ID, &val16, + sizeof(val16)); + if (val16 != 0x1) + break; + udelay(10); + } + if (val16 == 0x1) + pr_err("PCI: Broken device in slot %d\n", dev); + } + } +} void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) { - pr_err("No support for PCI core in hostmode yet\n"); + struct bcma_bus *bus = pc->core->bus; + struct bcma_drv_pci_host *pc_host; + u32 tmp; + u32 pci_membase_1G; + unsigned long io_map_base; + + pr_info("PCIEcore in host mode found\n"); + + pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); + if (!pc_host) { + pr_err("can not allocate memory"); + return; + } + + pc->host_controller = pc_host; + pc_host->pci_controller.io_resource = &pc_host->io_resource; + pc_host->pci_controller.mem_resource = &pc_host->mem_resource; + pc_host->pci_controller.pci_ops = &pc_host->pci_ops; + pc_host->pdev = pc; + + pci_membase_1G = BCMA_SOC_PCI_DMA; + pc_host->host_cfg_addr = BCMA_SOC_PCI_CFG; + + pc_host->pci_ops.read = bcma_core_pci_hostmode_read_config; + pc_host->pci_ops.write = bcma_core_pci_hostmode_write_config; + + pc_host->mem_resource.name = "BCMA PCIcore external memory", + pc_host->mem_resource.start = BCMA_SOC_PCI_DMA; + pc_host->mem_resource.end = BCMA_SOC_PCI_DMA + BCMA_SOC_PCI_DMA_SZ - 1; + pc_host->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED; + + pc_host->io_resource.name = "BCMA PCIcore external I/O", + pc_host->io_resource.start = 0x100; + pc_host->io_resource.end = 0x7FF; + pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED; + + /* Reset RC */ + udelay(3000); + pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); + udelay(1000); + pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | + BCMA_CORE_PCI_CTL_RST_OE); + + /* 64 MB I/O access window. On 4716, use + * sbtopcie0 to access the device registers. We + * can't use address match 2 (1 GB window) region + * as mips can't generate 64-bit address on the + * backplane. + */ + if (bus->chipinfo.id == 0x4716 || bus->chipinfo.id == 0x4748) { + pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; + pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + + BCMA_SOC_PCI_MEM_SZ - 1; + pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, + BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM); + } else if (bus->chipinfo.id == 0x5300) { + tmp = BCMA_CORE_PCI_SBTOPCI_MEM; + tmp |= BCMA_CORE_PCI_SBTOPCI_PREF; + tmp |= BCMA_CORE_PCI_SBTOPCI_BURST; + if (pc->core->core_unit == 0) { + pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; + pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + + BCMA_SOC_PCI_MEM_SZ - 1; + pci_membase_1G = BCMA_SOC_PCIE_DMA_H32; + pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, + tmp | BCMA_SOC_PCI_MEM); + } else if (pc->core->core_unit == 1) { + pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM; + pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM + + BCMA_SOC_PCI_MEM_SZ - 1; + pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32; + pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG; + pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, + tmp | BCMA_SOC_PCI1_MEM); + } + } else + pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, + BCMA_CORE_PCI_SBTOPCI_IO); + + /* 64 MB configuration access window */ + pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0); + + /* 1 GB memory access window */ + pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI2, + BCMA_CORE_PCI_SBTOPCI_MEM | pci_membase_1G); + + + /* As per PCI Express Base Spec 1.1 we need to wait for + * at least 100 ms from the end of a reset (cold/warm/hot) + * before issuing configuration requests to PCI Express + * devices. + */ + udelay(100000); + + bcma_core_pci_enable_crs(pc); + + /* Enable PCI bridge BAR0 memory & master access */ + tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); + + /* Enable PCI interrupts */ + pcicore_write32(pc, BCMA_CORE_PCI_IMASK, BCMA_CORE_PCI_IMASK_INTA); + + /* Ok, ready to run, register it to the system. + * The following needs change, if we want to port hostmode + * to non-MIPS platform. */ + io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM, + 0x04000000); + pc_host->pci_controller.io_map_base = io_map_base; + set_io_port_base(pc_host->pci_controller.io_map_base); + /* Give some time to the PCI controller to configure itself with the new + * values. Not waiting at this point causes crashes of the machine. */ + mdelay(10); + register_pci_controller(&pc_host->pci_controller); + return; +} + +/* Early PCI fixup for a device on the PCI-core bridge. */ +static void bcma_core_pci_fixup_pcibridge(struct pci_dev *dev) +{ + if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { + /* This is not a device on the PCI-core bridge. */ + return; + } + if (PCI_SLOT(dev->devfn) != 0) + return; + + pr_info("PCI: Fixing up bridge %s\n", pci_name(dev)); + + /* Enable PCI bridge bus mastering and memory space */ + pci_set_master(dev); + if (pcibios_enable_device(dev, ~0) < 0) { + pr_err("PCI: BCMA bridge enable failed\n"); + return; + } + + /* Enable PCI bridge BAR1 prefetch and burst */ + pci_write_config_dword(dev, BCMA_PCI_BAR1_CONTROL, 3); +} +DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge); + +/* Early PCI fixup for all PCI-cores to set the correct memory address. */ +static void bcma_core_pci_fixup_addresses(struct pci_dev *dev) +{ + struct resource *res; + int pos; + + if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { + /* This is not a device on the PCI-core bridge. */ + return; + } + if (PCI_SLOT(dev->devfn) == 0) + return; + + pr_info("PCI: Fixing up addresses %s\n", pci_name(dev)); + + for (pos = 0; pos < 6; pos++) { + res = &dev->resource[pos]; + if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) + pci_assign_resource(dev, pos); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses); + +/* This function is called when doing a pci_enable_device(). + * We must first check if the device is a device on the PCI-core bridge. */ +int bcma_core_pci_plat_dev_init(struct pci_dev *dev) +{ + struct bcma_drv_pci_host *pc_host; + + if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { + /* This is not a device on the PCI-core bridge. */ + return -ENODEV; + } + pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, + pci_ops); + + pr_info("PCI: Fixing up device %s\n", pci_name(dev)); + + /* Fix up interrupt lines */ + dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + + return 0; +} +EXPORT_SYMBOL(bcma_core_pci_plat_dev_init); + +/* PCI device IRQ mapping. */ +int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev) +{ + struct bcma_drv_pci_host *pc_host; + + if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) { + /* This is not a device on the PCI-core bridge. */ + return -ENODEV; + } + + pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, + pci_ops); + return bcma_core_mips_irq(pc_host->pdev->core) + 2; } +EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h index 679d4cab454..46c71e27d31 100644 --- a/include/linux/bcma/bcma_driver_pci.h +++ b/include/linux/bcma/bcma_driver_pci.h @@ -160,9 +160,44 @@ struct pci_dev; /* PCIcore specific boardflags */ #define BCMA_CORE_PCI_BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ +/* PCIE Config space accessing MACROS */ +#define BCMA_CORE_PCI_CFG_BUS_SHIFT 24 /* Bus shift */ +#define BCMA_CORE_PCI_CFG_SLOT_SHIFT 19 /* Slot/Device shift */ +#define BCMA_CORE_PCI_CFG_FUN_SHIFT 16 /* Function shift */ +#define BCMA_CORE_PCI_CFG_OFF_SHIFT 0 /* Register shift */ + +#define BCMA_CORE_PCI_CFG_BUS_MASK 0xff /* Bus mask */ +#define BCMA_CORE_PCI_CFG_SLOT_MASK 0x1f /* Slot/Device mask */ +#define BCMA_CORE_PCI_CFG_FUN_MASK 7 /* Function mask */ +#define BCMA_CORE_PCI_CFG_OFF_MASK 0xfff /* Register mask */ + +/* PCIE Root Capability Register bits (Host mode only) */ +#define BCMA_CORE_PCI_RC_CRS_VISIBILITY 0x0001 + +struct bcma_drv_pci; + +#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE +struct bcma_drv_pci_host { + struct bcma_drv_pci *pdev; + + u32 host_cfg_addr; + spinlock_t cfgspace_lock; + + struct pci_controller pci_controller; + struct pci_ops pci_ops; + struct resource mem_resource; + struct resource io_resource; +}; +#endif + struct bcma_drv_pci { struct bcma_device *core; u8 setup_done:1; + u8 hostmode:1; + +#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE + struct bcma_drv_pci_host *host_controller; +#endif }; /* Register access */ @@ -173,4 +208,7 @@ extern void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc); extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, bool enable); +extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev); +extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev); + #endif /* LINUX_BCMA_DRIVER_PCI_H_ */ diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h index 9faae2ae02e..5a71d571964 100644 --- a/include/linux/bcma/bcma_regs.h +++ b/include/linux/bcma/bcma_regs.h @@ -56,4 +56,31 @@ #define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ #define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ +/* SiliconBackplane Address Map. + * All regions may not exist on all chips. + */ +#define BCMA_SOC_SDRAM_BASE 0x00000000U /* Physical SDRAM */ +#define BCMA_SOC_PCI_MEM 0x08000000U /* Host Mode sb2pcitranslation0 (64 MB) */ +#define BCMA_SOC_PCI_MEM_SZ (64 * 1024 * 1024) +#define BCMA_SOC_PCI_CFG 0x0c000000U /* Host Mode sb2pcitranslation1 (64 MB) */ +#define BCMA_SOC_SDRAM_SWAPPED 0x10000000U /* Byteswapped Physical SDRAM */ +#define BCMA_SOC_SDRAM_R2 0x80000000U /* Region 2 for sdram (512 MB) */ + + +#define BCMA_SOC_PCI_DMA 0x40000000U /* Client Mode sb2pcitranslation2 (1 GB) */ +#define BCMA_SOC_PCI_DMA2 0x80000000U /* Client Mode sb2pcitranslation2 (1 GB) */ +#define BCMA_SOC_PCI_DMA_SZ 0x40000000U /* Client Mode sb2pcitranslation2 size in bytes */ +#define BCMA_SOC_PCIE_DMA_L32 0x00000000U /* PCIE Client Mode sb2pcitranslation2 + * (2 ZettaBytes), low 32 bits + */ +#define BCMA_SOC_PCIE_DMA_H32 0x80000000U /* PCIE Client Mode sb2pcitranslation2 + * (2 ZettaBytes), high 32 bits + */ + +#define BCMA_SOC_PCI1_MEM 0x40000000U /* Host Mode sb2pcitranslation0 (64 MB) */ +#define BCMA_SOC_PCI1_CFG 0x44000000U /* Host Mode sb2pcitranslation1 (64 MB) */ +#define BCMA_SOC_PCIE1_DMA_H32 0xc0000000U /* PCIE Client Mode sb2pcitranslation2 + * (2 ZettaBytes), high 32 bits + */ + #endif /* LINUX_BCMA_REGS_H_ */ -- cgit v1.2.3 From 8f9ada4fa1926e540b1562cb9bacb3e51a698c35 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 31 Jan 2012 00:03:36 +0100 Subject: bcma: add bus num counter If we have two bcma buses on one computer the second will not work without this patch. Now each bus gets an own number. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/main.c | 12 +++++++++++- include/linux/bcma/bcma.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 3363036f23d..bcd1c01cde9 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -13,6 +13,12 @@ MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); MODULE_LICENSE("GPL"); +/* contains the number the next bus should get. */ +static unsigned int bcma_bus_next_num = 0; + +/* bcma_buses_mutex locks the bcma_bus_next_num */ +static DEFINE_MUTEX(bcma_buses_mutex); + static int bcma_bus_match(struct device *dev, struct device_driver *drv); static int bcma_device_probe(struct device *dev); static int bcma_device_remove(struct device *dev); @@ -93,7 +99,7 @@ static int bcma_register_cores(struct bcma_bus *bus) core->dev.release = bcma_release_core_dev; core->dev.bus = &bcma_bus_type; - dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id); + dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id); switch (bus->hosttype) { case BCMA_HOSTTYPE_PCI: @@ -137,6 +143,10 @@ int __devinit bcma_bus_register(struct bcma_bus *bus) int err; struct bcma_device *core; + mutex_lock(&bcma_buses_mutex); + bus->num = bcma_bus_next_num++; + mutex_unlock(&bcma_buses_mutex); + /* Scan for devices (cores) */ err = bcma_bus_scan(bus); if (err) { diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 024a6e2a908..b9f65fbee42 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -196,6 +196,7 @@ struct bcma_bus { struct list_head cores; u8 nr_cores; u8 init_done:1; + u8 num; struct bcma_drv_cc drv_cc; struct bcma_drv_pci drv_pci; -- cgit v1.2.3 From d6865dcc58f252480515101fd13532f0fc420b53 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 31 Jan 2012 00:03:37 +0100 Subject: bcma: add extra sprom check This check is needed on the BCM43224 device as it says in the capabilities it has an sprom but is extra check says it has not. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/sprom.c | 7 +++++++ include/linux/bcma/bcma_driver_chipcommon.h | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index e35134f724f..ca7752510d5 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -250,6 +250,7 @@ int bcma_sprom_get(struct bcma_bus *bus) { u16 offset; u16 *sprom; + u32 sromctrl; int err = 0; if (!bus->drv_cc.core) @@ -258,6 +259,12 @@ int bcma_sprom_get(struct bcma_bus *bus) if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) return -ENOENT; + if (bus->drv_cc.core->id.rev >= 32) { + sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL); + if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT)) + return -ENOENT; + } + sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), GFP_KERNEL); if (!sprom) diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index a33086a7530..e72938b1071 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -181,6 +181,22 @@ #define BCMA_CC_FLASH_CFG 0x0128 #define BCMA_CC_FLASH_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ #define BCMA_CC_FLASH_WAITCNT 0x012C +#define BCMA_CC_SROM_CONTROL 0x0190 +#define BCMA_CC_SROM_CONTROL_START 0x80000000 +#define BCMA_CC_SROM_CONTROL_BUSY 0x80000000 +#define BCMA_CC_SROM_CONTROL_OPCODE 0x60000000 +#define BCMA_CC_SROM_CONTROL_OP_READ 0x00000000 +#define BCMA_CC_SROM_CONTROL_OP_WRITE 0x20000000 +#define BCMA_CC_SROM_CONTROL_OP_WRDIS 0x40000000 +#define BCMA_CC_SROM_CONTROL_OP_WREN 0x60000000 +#define BCMA_CC_SROM_CONTROL_OTPSEL 0x00000010 +#define BCMA_CC_SROM_CONTROL_LOCK 0x00000008 +#define BCMA_CC_SROM_CONTROL_SIZE_MASK 0x00000006 +#define BCMA_CC_SROM_CONTROL_SIZE_1K 0x00000000 +#define BCMA_CC_SROM_CONTROL_SIZE_4K 0x00000002 +#define BCMA_CC_SROM_CONTROL_SIZE_16K 0x00000004 +#define BCMA_CC_SROM_CONTROL_SIZE_SHIFT 1 +#define BCMA_CC_SROM_CONTROL_PRESENT 0x00000001 /* 0x1E0 is defined as shared BCMA_CLKCTLST */ #define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ #define BCMA_CC_UART0_DATA 0x0300 -- cgit v1.2.3 From 1d73c51a8476847d96a6c5a2ae3715d7099c58c9 Mon Sep 17 00:00:00 2001 From: "Devendra.Naga" Date: Tue, 31 Jan 2012 01:28:15 -0500 Subject: rtlwifi: remove return in _rtl_pci_switch_clk_req the return value from _rtl_pci_switch_clk_req is not used by any of its callers. Signed-off-by: Devendra.Naga Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 5cb2199435d..9a0190944de 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -198,7 +198,7 @@ static bool _rtl_pci_platform_switch_device_pci_aspm( } /*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/ -static bool _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) +static void _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -207,8 +207,6 @@ static bool _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) udelay(100); - - return true; } /*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/ -- cgit v1.2.3 From f3e1b97f036ee477c49b8ec561027db8e3863eab Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Tue, 31 Jan 2012 23:23:45 +0900 Subject: iwmc3200wifi: Fix typo in trace.h Correct spelling "embeded" to "embedded" in drivers/net/wireless/iwmc3200wifi/trace.h Signed-off-by: Masanari Iida Acked-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/trace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwmc3200wifi/trace.h b/drivers/net/wireless/iwmc3200wifi/trace.h index abb4805fa8d..f5f7070b7e2 100644 --- a/drivers/net/wireless/iwmc3200wifi/trace.h +++ b/drivers/net/wireless/iwmc3200wifi/trace.h @@ -144,7 +144,7 @@ TRACE_EVENT(iwm_tx_packets, TP_printk( IWM_PR_FMT " Tx %spacket: eot %d, seq 0x%x, sta_color 0x%x, " - "ra_tid 0x%x, credit_group 0x%x, embeded_packets %d, %d bytes", + "ra_tid 0x%x, credit_group 0x%x, embedded_packets %d, %d bytes", IWM_PR_ARG, !__entry->eot ? "concatenated " : "", __entry->eot, __entry->seq, __entry->color, __entry->ra_tid, __entry->credit_group, __entry->npkt, __entry->bytes -- cgit v1.2.3 From 5aff4e74dc69105b95b799b036aa597ce0726e07 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Tue, 31 Jan 2012 09:42:58 -0600 Subject: rtlwifi: Fix typo in dm.c Correct a spelling "disconnet" to "disconnect" in drivers/net/wireless/rtlwifi/rtl8192de/dm.c Signed-off-by: Masanari Iida Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192de/dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c index 181ed6fc90e..9fda1af44b3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c @@ -294,7 +294,7 @@ static void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw) de_digtable.min_undecorated_pwdb_for_dm = rtlpriv->dm.UNDEC_SM_PWDB; RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "AP Ext Port or disconnet PWDB = 0x%x\n", + "AP Ext Port or disconnect PWDB = 0x%x\n", de_digtable.min_undecorated_pwdb_for_dm); } -- cgit v1.2.3 From 3eda95de19e1781612091869e866a5014257f462 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 31 Jan 2012 10:29:22 -0600 Subject: rtlwifi: Remove extra debugging message accidentally left in In commit b0302aba812bcc39291cdab9ad7e37008f352a91, an extra debugging message that is spamming the logs was not deleted before submission. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index f231b918043..278e9f957e0 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -296,12 +296,10 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) * because that will cause nullfunc send by mac80211 * fail, and cause pkt loss, we have tested that 5mA * is worked very well */ - if (!rtlpriv->psc.multi_buffered) { + if (!rtlpriv->psc.multi_buffered) queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_work, MSECS(5)); - pr_info("In section\n"); - } } else { rtl_swlps_rf_awake(hw); rtlpriv->psc.sw_ps_enabled = false; -- cgit v1.2.3 From 267335d63b808dc861f3a4dc81a605489a8a13ac Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 31 Jan 2012 20:25:47 +0100 Subject: cfg80211/mac80211: userspace peer authorization in IBSS If the IBSS network is RSN-protected, let userspace authorize the stations instead of adding them as AUTHORIZED by default. Signed-off-by: Antonio Quartulli Signed-off-by: John W. Linville --- include/net/cfg80211.h | 5 +++++ net/mac80211/ibss.c | 6 +++++- net/mac80211/ieee80211_i.h | 2 ++ net/wireless/nl80211.c | 20 ++++++++++++-------- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 229edc526cf..e0c9ff3a197 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1147,6 +1147,10 @@ struct cfg80211_disassoc_request { * @beacon_interval: beacon interval to use * @privacy: this is a protected network, keys will be configured * after joining + * @control_port: whether user space controls IEEE 802.1X port, i.e., + * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is + * required to assume that the port is unauthorized until authorized by + * user space. Otherwise, port is marked authorized by default. * @basic_rates: bitmap of basic rates to use when creating the IBSS * @mcast_rate: per-band multicast rate index + 1 (0: disabled) */ @@ -1161,6 +1165,7 @@ struct cfg80211_ibss_params { u32 basic_rates; bool channel_fixed; bool privacy; + bool control_port; int mcast_rate[IEEE80211_NUM_BANDS]; }; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 7b3a0b0aa24..8361da4b36a 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -268,7 +268,10 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); - sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); + /* authorize the station only if the network is not RSN protected. If + * not wait for the userspace to authorize it */ + if (!sta->sdata->u.ibss.control_port) + sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); rate_control_rate_init(sta); @@ -1075,6 +1078,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.fixed_bssid = false; sdata->u.ibss.privacy = params->privacy; + sdata->u.ibss.control_port = params->control_port; sdata->u.ibss.basic_rates = params->basic_rates; memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate, sizeof(params->mcast_rate)); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a146b1177cb..74594f012cd 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -478,6 +478,8 @@ struct ieee80211_if_ibss { bool fixed_channel; bool privacy; + bool control_port; + u8 bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid_len, ie_len; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e1fd1bf9072..f1681e2c594 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2654,13 +2654,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) break; case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_STATION: - /* disallow things sta doesn't support */ - if (params.plink_action) - return -EINVAL; - if (params.ht_capa) - return -EINVAL; - if (params.listen_interval >= 0) - return -EINVAL; /* * Don't allow userspace to change the TDLS_PEER flag, * but silently ignore attempts to change it since we @@ -2668,7 +2661,15 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) * to change the flag. */ params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); - + /* fall through */ + case NL80211_IFTYPE_ADHOC: + /* disallow things sta doesn't support */ + if (params.plink_action) + return -EINVAL; + if (params.ht_capa) + return -EINVAL; + if (params.listen_interval >= 0) + return -EINVAL; /* reject any changes other than AUTHORIZED */ if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) return -EINVAL; @@ -4802,6 +4803,9 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) return PTR_ERR(connkeys); } + ibss.control_port = + nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]); + err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); if (err) kfree(connkeys); -- cgit v1.2.3 From f0d4724b2a663089d21e19933ca591d842b63230 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 1 Feb 2012 00:13:54 +0100 Subject: bcma: log the id, rev and pkg of the chip found This makes us see what type of hardware someone uses by the dmesg output. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/scan.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index e513aa83ec2..6621b2221b4 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -364,6 +364,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, void bcma_init_bus(struct bcma_bus *bus) { s32 tmp; + struct bcma_chipinfo *chipinfo = &(bus->chipinfo); if (bus->init_done) return; @@ -374,9 +375,12 @@ void bcma_init_bus(struct bcma_bus *bus) bcma_scan_switch_core(bus, BCMA_ADDR_BASE); tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); - bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; - bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; - bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; + chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; + chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; + chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; + pr_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", + chipinfo->id, chipinfo->rev, chipinfo->pkg); + bus->init_done = true; } -- cgit v1.2.3 From bedb2a18af0a4e7565182c07fadd854e3ae8c9bc Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 1 Feb 2012 00:13:55 +0100 Subject: ssb: log the id, rev and pkg of the chip found This makes us see what type of hardware someone uses by the dmesg output. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/ssb/scan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index 3e844874631..266c7c5c86d 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c @@ -318,6 +318,9 @@ int ssb_bus_scan(struct ssb_bus *bus, bus->chip_package = 0; } } + ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and " + "package 0x%02X\n", bus->chip_id, bus->chip_rev, + bus->chip_package); if (!bus->nr_devices) bus->nr_devices = chipid_to_nrcores(bus->chip_id); if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { -- cgit v1.2.3 From d486a5b4996d2fffd10098725781f2c5690774bc Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 1 Feb 2012 00:13:56 +0100 Subject: ssb: add support for bcm5354 This patch adds support the the BCM5354 SoC. It has a PMU and a constant not configurable clock. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/ssb/driver_chipcommon_pmu.c | 48 +++++++++++++++++++++++++++++++++---- drivers/ssb/driver_mipscore.c | 3 +++ drivers/ssb/main.c | 3 +++ drivers/ssb/ssb_private.h | 4 ++++ 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index e5a2e0e9bc1..b58fef780ea 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c @@ -13,6 +13,9 @@ #include #include #include +#ifdef CONFIG_BCM47XX +#include +#endif #include "ssb_private.h" @@ -92,10 +95,6 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, u32 pmuctl, tmp, pllctl; unsigned int i; - if ((bus->chip_id == 0x5354) && !crystalfreq) { - /* The 5354 crystal freq is 25MHz */ - crystalfreq = 25000; - } if (crystalfreq) e = pmu0_plltab_find_entry(crystalfreq); if (!e) @@ -321,7 +320,11 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */ if (bus->bustype == SSB_BUSTYPE_SSB) { - /* TODO: The user may override the crystal frequency. */ +#ifdef CONFIG_BCM47XX + char buf[20]; + if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0) + crystalfreq = simple_strtoul(buf, NULL, 0); +#endif } switch (bus->chip_id) { @@ -330,7 +333,11 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) ssb_pmu1_pllinit_r0(cc, crystalfreq); break; case 0x4328: + ssb_pmu0_pllinit_r0(cc, crystalfreq); + break; case 0x5354: + if (crystalfreq == 0) + crystalfreq = 25000; ssb_pmu0_pllinit_r0(cc, crystalfreq); break; case 0x4322: @@ -607,3 +614,34 @@ void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on) EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); + +u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc) +{ + struct ssb_bus *bus = cc->dev->bus; + + switch (bus->chip_id) { + case 0x5354: + /* 5354 chip uses a non programmable PLL of frequency 240MHz */ + return 240000000; + default: + ssb_printk(KERN_ERR PFX + "ERROR: PMU cpu clock unknown for device %04X\n", + bus->chip_id); + return 0; + } +} + +u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc) +{ + struct ssb_bus *bus = cc->dev->bus; + + switch (bus->chip_id) { + case 0x5354: + return 120000000; + default: + ssb_printk(KERN_ERR PFX + "ERROR: PMU controlclock unknown for device %04X\n", + bus->chip_id); + return 0; + } +} diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index ced50156859..7e2ddc042f5 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c @@ -208,6 +208,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *mcore) struct ssb_bus *bus = mcore->dev->bus; u32 pll_type, n, m, rate = 0; + if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) + return ssb_pmu_get_cpu_clock(&bus->chipco); + if (bus->extif.dev) { ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m); } else if (bus->chipco.dev) { diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index bb6317fb925..2a0a1b99e0e 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1094,6 +1094,9 @@ u32 ssb_clockspeed(struct ssb_bus *bus) u32 plltype; u32 clkctl_n, clkctl_m; + if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) + return ssb_pmu_get_controlclock(&bus->chipco); + if (ssb_extif_available(&bus->extif)) ssb_extif_get_clockcontrol(&bus->extif, &plltype, &clkctl_n, &clkctl_m); diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 77653014db0..a305550b4b6 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h @@ -207,4 +207,8 @@ static inline void b43_pci_ssb_bridge_exit(void) } #endif /* CONFIG_SSB_B43_PCI_BRIDGE */ +/* driver_chipcommon_pmu.c */ +extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc); +extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc); + #endif /* LINUX_SSB_PRIVATE_H_ */ -- cgit v1.2.3 From 910570b5f4dbf75b73389010704ca6442a767a41 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 1 Feb 2012 10:42:11 +0300 Subject: mac80211: off by one in mcs mask handling "ridx" is used as an index into the mcs_mask[] array which has IEEE80211_HT_MCS_MASK_LEN elements. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- net/mac80211/rate.c | 2 +- net/wireless/nl80211.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 3fef26d8898..22fc28e9026 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -324,7 +324,7 @@ static bool rate_idx_match_mcs_mask(struct ieee80211_tx_rate *rate, rbit = rate->idx % 8; /* sanity check */ - if (ridx < 0 || ridx > IEEE80211_HT_MCS_MASK_LEN) + if (ridx < 0 || ridx >= IEEE80211_HT_MCS_MASK_LEN) return false; /* See whether the selected rate or anything below it is allowed. */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f1681e2c594..fe274765356 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5410,7 +5410,7 @@ static bool ht_rateset_to_mask(struct ieee80211_supported_band *sband, rbit = BIT(rates[i] % 8); /* check validity */ - if ((ridx < 0) || (ridx > IEEE80211_HT_MCS_MASK_LEN)) + if ((ridx < 0) || (ridx >= IEEE80211_HT_MCS_MASK_LEN)) return false; /* check availability */ -- cgit v1.2.3 From 291689fcfbf0046d17c83c36fc983400f499dec3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 1 Feb 2012 10:43:31 +0300 Subject: ath9k: cleanup a min_t() cast If the firmware was over 2G, it would cause memory corruption and the system would die here. Obviously we all know the firmware isn't going to be that large but static checkers get upset. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index f317515d8bf..424aabb2c73 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -981,7 +981,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) return -ENOMEM; while (len) { - transfer = min_t(int, len, 4096); + transfer = min_t(size_t, len, 4096); memcpy(buf, data, transfer); err = usb_control_msg(hif_dev->udev, -- cgit v1.2.3 From 197a4e4e1f7ef11458f09b4dd74397baf6758133 Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Wed, 1 Feb 2012 16:19:54 +0530 Subject: mwl8k: Remove BSSID from the firmware when the BSS is stopped Using command DEL_MAC_ADDR, remove the mac address of the BSS when it is stopped i.e the corresponding vif is removed. Without this, the stale bss entry will still be maintained in the firmware which causes issues when the BSS's are recreated. Signed-off-by: Nishant Sarmukadam Signed-off-by: Yogesh Ashok Powar Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index fd125473be7..ac7c983f163 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -402,6 +402,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { #define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */ #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 #define MWL8K_CMD_GET_WATCHDOG_BITMAP 0x0205 +#define MWL8K_CMD_DEL_MAC_ADDR 0x0206 /* per-vif */ #define MWL8K_CMD_BSS_START 0x1100 /* per-vif */ #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ #define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */ @@ -3430,10 +3431,7 @@ static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable) return rc; } -/* - * CMD_SET_MAC_ADDR. - */ -struct mwl8k_cmd_set_mac_addr { +struct mwl8k_cmd_update_mac_addr { struct mwl8k_cmd_pkt header; union { struct { @@ -3449,12 +3447,12 @@ struct mwl8k_cmd_set_mac_addr { #define MWL8K_MAC_TYPE_PRIMARY_AP 2 #define MWL8K_MAC_TYPE_SECONDARY_AP 3 -static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u8 *mac) +static int mwl8k_cmd_update_mac_addr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *mac, bool set) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); - struct mwl8k_cmd_set_mac_addr *cmd; + struct mwl8k_cmd_update_mac_addr *cmd; int mac_type; int rc; @@ -3475,7 +3473,11 @@ static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, if (cmd == NULL) return -ENOMEM; - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); + if (set) + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); + else + cmd->header.code = cpu_to_le16(MWL8K_CMD_DEL_MAC_ADDR); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); if (priv->ap_fw) { cmd->mbss.mac_type = cpu_to_le16(mac_type); @@ -3490,6 +3492,24 @@ static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, return rc; } +/* + * MWL8K_CMD_SET_MAC_ADDR. + */ +static inline int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *mac) +{ + return mwl8k_cmd_update_mac_addr(hw, vif, mac, true); +} + +/* + * MWL8K_CMD_DEL_MAC_ADDR. + */ +static inline int mwl8k_cmd_del_mac_addr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *mac) +{ + return mwl8k_cmd_update_mac_addr(hw, vif, mac, false); +} + /* * CMD_SET_RATEADAPT_MODE. */ @@ -4542,7 +4562,7 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw, if (priv->ap_fw) mwl8k_cmd_set_new_stn_del(hw, vif, vif->addr); - mwl8k_cmd_set_mac_addr(hw, vif, "\x00\x00\x00\x00\x00\x00"); + mwl8k_cmd_del_mac_addr(hw, vif, vif->addr); mwl8k_remove_vif(priv, mwl8k_vif); } -- cgit v1.2.3 From 477778bb0e7c671860528946b412294684337c5e Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 1 Feb 2012 20:41:44 -0800 Subject: mwifiex: fix NULL pointer dereference in set_channel() In set_channel() callback handler, "priv" pointer is derived from net_device. Sometimes net_device pointer coming from the stack is NULL which causes kernel crash. This patch fixes the problem by deriving "priv" from wiphy when net_device pointer is NULL. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 6fef4925d13..54e45c829c5 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -376,7 +376,12 @@ mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) { - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + struct mwifiex_private *priv; + + if (dev) + priv = mwifiex_netdev_get_priv(dev); + else + priv = mwifiex_cfg80211_get_priv(wiphy); if (priv->media_connected) { wiphy_err(wiphy, "This setting is valid only when station " -- cgit v1.2.3 From 3dc5e1751803e812806d7aa46150af92f91ef489 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 1 Feb 2012 20:41:45 -0800 Subject: mwifiex: enable HT operating mode This patch sets default adapter channel_type as HT. Hence the device will opearate in HT mode. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index e13b6d99171..83cc10fca4b 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -280,6 +280,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) adapter->adhoc_awake_period = 0; memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); adapter->arp_filter_size = 0; + adapter->channel_type = NL80211_CHAN_HT20; } /* -- cgit v1.2.3 From 885bd8eca6ac172e299750d99bd5c9fddbed89b9 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 2 Feb 2012 17:44:55 +0200 Subject: mac80211: support hw scan while idle Currently, mac80211 goes to idle-off before starting a scan. However, some devices that implement hw scan might not need going idle-off in order to perform a hw scan, and thus saving some energy and simplifying their state machine. (Note that this is also the case for sched scan - it currently doesn't make mac80211 go idle-off) Add a new flag to indicate support for hw scan while idle. Signed-off-by: Eliad Peller Signed-off-by: John W. Linville --- include/net/mac80211.h | 5 +++++ net/mac80211/debugfs.c | 2 ++ net/mac80211/iface.c | 3 ++- net/mac80211/main.c | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 922313f0b39..cbff4f94a20 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1164,6 +1164,10 @@ enum sta_notify_cmd { * @IEEE80211_HW_TX_AMPDU_SETUP_IN_HW: The device handles TX A-MPDU session * setup strictly in HW. mac80211 should not attempt to do this in * software. + * + * @IEEE80211_HW_SCAN_WHILE_IDLE: The device can do hw scan while + * being idle (i.e. mac80211 doesn't have to go idle-off during the + * the scan). */ enum ieee80211_hw_flags { IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, @@ -1190,6 +1194,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_SCAN_WHILE_IDLE = 1<<24, }; /** diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index affe64be909..483e96ed95c 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -263,6 +263,8 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); + if (local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE) + sf += snprintf(buf + sf, mxln - sf, "SCAN_WHILE_IDLE\n"); rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); kfree(buf); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 19f0818eba7..6b3cd65d1e0 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1332,7 +1332,8 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) wk->sdata->vif.bss_conf.idle = false; } - if (local->scan_sdata) { + if (local->scan_sdata && + !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { scanning = true; local->scan_sdata->vif.bss_conf.idle = false; } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 362e89d6d46..831a5bd44fd 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -697,6 +697,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ) return -EINVAL; + if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) + return -EINVAL; + if (hw->max_report_rates == 0) hw->max_report_rates = hw->max_rates; -- cgit v1.2.3 From 3d86b93064c7f18378a2008bab9608ca7d11bdbb Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Thu, 2 Feb 2012 13:48:06 -0700 Subject: rtlwifi: Fix PCI probe error path orphaned memory Memory allocated by ieee80211_alloc_hw() will get orphaned if any subsequent initializations fail. Also don't pci_set_drvdata(pdev, NULL) until just before disabling the PCI device. Functions called by rtl_deinit_core(hw) may eventually need the context (when its actually implemented). Cc: Larry Finger Cc: Chaoming Li Cc: John W. Linville Cc: linux-wireless@vger.kernel.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Tim Gardner Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 9a0190944de..c5f6a322feb 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1758,8 +1758,8 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { RT_ASSERT(false, "Unable to obtain 32bit DMA for consistent allocations\n"); - pci_disable_device(pdev); - return -ENOMEM; + err = -ENOMEM; + goto fail1; } } @@ -1801,7 +1801,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, err = pci_request_regions(pdev, KBUILD_MODNAME); if (err) { RT_ASSERT(false, "Can't obtain PCI resources\n"); - goto fail2; + goto fail1; } pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); @@ -1814,6 +1814,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, rtlpriv->cfg->bar_id, pmem_len); if (rtlpriv->io.pci_mem_start == 0) { RT_ASSERT(false, "Can't map PCI mem\n"); + err = -ENOMEM; goto fail2; } @@ -1830,8 +1831,10 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, pci_write_config_byte(pdev, 0x04, 0x07); /* find adapter */ - if (!_rtl_pci_find_adapter(pdev, hw)) + if (!_rtl_pci_find_adapter(pdev, hw)) { + err = -ENODEV; goto fail3; + } /* Init IO handler */ _rtl_pci_io_handler_init(&pdev->dev, hw); @@ -1841,6 +1844,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, if (rtlpriv->cfg->ops->init_sw_vars(hw)) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n"); + err = -ENODEV; goto fail3; } @@ -1885,7 +1889,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, return 0; fail3: - pci_set_drvdata(pdev, NULL); rtl_deinit_core(hw); _rtl_pci_io_handler_release(hw); @@ -1897,10 +1900,12 @@ fail2: complete(&rtlpriv->firmware_loading_complete); fail1: - + if (hw) + ieee80211_free_hw(hw); + pci_set_drvdata(pdev, NULL); pci_disable_device(pdev); - return -ENODEV; + return err; } EXPORT_SYMBOL(rtl_pci_probe); -- cgit v1.2.3 From f3c8d2591fa7278abe58ee0278a41d5b130d1718 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 2 Feb 2012 20:48:57 -0800 Subject: mwifiex: cleanup in snmp_mib command preparation code 1) Remove unnecessary switch case usage. 2) Replace "X=cpu_to_le16(le16_to_cpu(X) + Y)" by "le16_add_cpu(X, Y)" 3) Declare "ul_temp" variable as u16 instead of u32 to avoid unnecessary typecasting Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_cmd.c | 60 +++++----------------------------- 1 file changed, 8 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 6e443ffa046..324c651527c 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -103,7 +103,7 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv, static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, u16 cmd_action, u32 cmd_oid, - u32 *ul_temp) + u16 *ul_temp) { struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib; @@ -112,62 +112,18 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv, cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib) - 1 + S_DS_GEN); + snmp_mib->oid = cpu_to_le16((u16)cmd_oid); if (cmd_action == HostCmd_ACT_GEN_GET) { snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_GET); snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) - + MAX_SNMP_BUF_SIZE); + le16_add_cpu(&cmd->size, MAX_SNMP_BUF_SIZE); + } else if (cmd_action == HostCmd_ACT_GEN_SET) { + snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); + snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); + *((__le16 *) (snmp_mib->value)) = cpu_to_le16(*ul_temp); + le16_add_cpu(&cmd->size, sizeof(u16)); } - switch (cmd_oid) { - case FRAG_THRESH_I: - snmp_mib->oid = cpu_to_le16((u16) FRAG_THRESH_I); - if (cmd_action == HostCmd_ACT_GEN_SET) { - snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); - snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); - *((__le16 *) (snmp_mib->value)) = - cpu_to_le16((u16) *ul_temp); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) - + sizeof(u16)); - } - break; - case RTS_THRESH_I: - snmp_mib->oid = cpu_to_le16((u16) RTS_THRESH_I); - if (cmd_action == HostCmd_ACT_GEN_SET) { - snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); - snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); - *(__le16 *) (snmp_mib->value) = - cpu_to_le16((u16) *ul_temp); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) - + sizeof(u16)); - } - break; - - case SHORT_RETRY_LIM_I: - snmp_mib->oid = cpu_to_le16((u16) SHORT_RETRY_LIM_I); - if (cmd_action == HostCmd_ACT_GEN_SET) { - snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); - snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); - *((__le16 *) (snmp_mib->value)) = - cpu_to_le16((u16) *ul_temp); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) - + sizeof(u16)); - } - break; - case DOT11D_I: - snmp_mib->oid = cpu_to_le16((u16) DOT11D_I); - if (cmd_action == HostCmd_ACT_GEN_SET) { - snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); - snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); - *((__le16 *) (snmp_mib->value)) = - cpu_to_le16((u16) *ul_temp); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) - + sizeof(u16)); - } - break; - default: - break; - } dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x," " Value=0x%x\n", -- cgit v1.2.3 From caf60a6c957e7a35837a41f845e57b4433e20276 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 2 Feb 2012 20:48:58 -0800 Subject: mwifiex: update correct dtim_period in dump_station() Earlier we were using dtim period extracted from scan response buffer provided by FW in scan operation. But it is observed that sometimes the buffer doesn't contain dtim period tlv, and wrong value (0) was sent to user space. After association FW will start listening to beacon frames of connected AP and store dtim period. Therefore we can get it from FW in dump_station() instead of using wrong value obtained in scanning. Redundant code after adapting new approach for dtim period is also removed in this patch. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 8 ++++++-- drivers/net/wireless/mwifiex/main.h | 2 +- drivers/net/wireless/mwifiex/scan.c | 6 ------ drivers/net/wireless/mwifiex/sta_cmdresp.c | 3 +++ 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 54e45c829c5..478d2f12c02 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -539,6 +539,11 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, ret = -EFAULT; } + /* Get DTIM period information from firmware */ + mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_GET, DTIM_PERIOD_I, + &priv->dtim_period); + /* * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid * MCS index values for us are 0 to 7. @@ -573,8 +578,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, WLAN_CAPABILITY_SHORT_SLOT_TIME) sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; - sinfo->bss_param.dtim_period = - priv->curr_bss_params.bss_descriptor.dtim_period; + sinfo->bss_param.dtim_period = priv->dtim_period; sinfo->bss_param.beacon_interval = priv->curr_bss_params.bss_descriptor.beacon_period; } diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 3dc0f721c1d..52810b1497e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -249,7 +249,6 @@ struct mwifiex_bssdescriptor { u32 channel; u32 freq; u16 beacon_period; - u8 dtim_period; u8 erp_flags; u32 bss_mode; u8 supported_rates[MWIFIEX_SUPPORTED_RATES]; @@ -392,6 +391,7 @@ struct mwifiex_private { u8 prev_bssid[ETH_ALEN]; struct mwifiex_current_bss_params curr_bss_params; u16 beacon_period; + u8 dtim_period; u16 listen_interval; u16 atim_window; u8 adhoc_channel; diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 135208596af..98f1ca9cd6d 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1086,7 +1086,6 @@ mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, struct ieee_types_vendor_specific *vendor_ie; const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; - struct ieee80211_tim_ie *tim_ie; found_data_rate_ie = false; rate_size = 0; @@ -1259,11 +1258,6 @@ mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, sizeof(struct ieee_types_header) - bss_entry->beacon_buf); break; - case WLAN_EID_TIM: - tim_ie = (void *) (current_ptr + - sizeof(struct ieee_types_header)); - bss_entry->dtim_period = tim_ie->dtim_period; - break; default: break; } diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index e812db8b695..0d8618a8443 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -210,6 +210,9 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv, dev_dbg(priv->adapter->dev, "info: SNMP_RESP: TxRetryCount=%u\n", ul_temp); break; + case DTIM_PERIOD_I: + dev_dbg(priv->adapter->dev, + "info: SNMP_RESP: DTIM period=%u\n", ul_temp); default: break; } -- cgit v1.2.3 From c8b03958d4b23dc48932ec095a391f3d6447e0e9 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:37 +0100 Subject: iwlegacy: move rxon commands out of ctx structure Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 82 +++++++-------- drivers/net/wireless/iwlegacy/3945-rs.c | 2 +- drivers/net/wireless/iwlegacy/3945.c | 22 ++-- drivers/net/wireless/iwlegacy/4965-calib.c | 6 +- drivers/net/wireless/iwlegacy/4965-mac.c | 31 +++--- drivers/net/wireless/iwlegacy/4965.c | 99 +++++++++--------- drivers/net/wireless/iwlegacy/common.c | 157 ++++++++++++++--------------- drivers/net/wireless/iwlegacy/common.h | 30 +++--- drivers/net/wireless/iwlegacy/debug.c | 4 +- 9 files changed, 205 insertions(+), 228 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 54b2d391e91..980566fdb81 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -672,15 +672,13 @@ il3945_get_measurement(struct il_priv *il, int rc; int spectrum_resp_status; int duration = le16_to_cpu(params->duration); - struct il_rxon_context *ctx = &il->ctx; if (il_is_associated(il)) add_time = il_usecs_to_beacons(il, le64_to_cpu(params->start_time) - il->_3945.last_tsf, - le16_to_cpu(ctx->timing. - beacon_interval)); + le16_to_cpu(il->timing.beacon_interval)); memset(&spectrum, 0, sizeof(spectrum)); @@ -694,15 +692,14 @@ il3945_get_measurement(struct il_priv *il, if (il_is_associated(il)) spectrum.start_time = il_add_beacon_time(il, il->_3945.last_beacon_time, add_time, - le16_to_cpu(ctx->timing. - beacon_interval)); + le16_to_cpu(il->timing.beacon_interval)); else spectrum.start_time = 0; spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); spectrum.channels[0].channel = params->channel; spectrum.channels[0].type = type; - if (ctx->active.flags & RXON_FLG_BAND_24G_MSK) + if (il->active.flags & RXON_FLG_BAND_24G_MSK) spectrum.flags |= RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; @@ -2150,7 +2147,6 @@ il3945_alive_start(struct il_priv *il) { int thermal_spin = 0; u32 rfkill; - struct il_rxon_context *ctx = &il->ctx; D_INFO("Runtime Alive received.\n"); @@ -2206,13 +2202,13 @@ il3945_alive_start(struct il_priv *il) if (il_is_associated(il)) { struct il3945_rxon_cmd *active_rxon = - (struct il3945_rxon_cmd *)(&ctx->active); + (struct il3945_rxon_cmd *)(&il->active); - ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ - il_connection_init_rx_config(il, ctx); + il_connection_init_rx_config(il, &il->ctx); } /* Configure Bluetooth device coexistence support */ @@ -2221,7 +2217,7 @@ il3945_alive_start(struct il_priv *il) set_bit(S_READY, &il->status); /* Configure the adapter for unassociated operation */ - il3945_commit_rxon(il, ctx); + il3945_commit_rxon(il, &il->ctx); il3945_reg_txpower_periodic(il); @@ -2670,7 +2666,7 @@ il3945_post_scan(struct il_priv *il) * Since setting the RXON may have been deferred while * performing the scan, fire one off if needed */ - if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) + if (memcmp(&il->staging, &il->active, sizeof(il->staging))) il3945_commit_rxon(il, ctx); } @@ -2728,7 +2724,7 @@ il3945_post_associate(struct il_priv *il) return; D_ASSOC("Associated as %d to: %pM\n", ctx->vif->bss_conf.aid, - ctx->active.bssid_addr); + il->active.bssid_addr); if (test_bit(S_EXIT_PENDING, &il->status)) return; @@ -2737,30 +2733,30 @@ il3945_post_associate(struct il_priv *il) conf = &il->hw->conf; - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; il3945_commit_rxon(il, ctx); rc = il_send_rxon_timing(il, ctx); if (rc) IL_WARN("C_RXON_TIMING failed - " "Attempting to continue.\n"); - ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid); + il->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid); D_ASSOC("assoc id %d beacon interval %d\n", ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int); if (ctx->vif->bss_conf.use_short_preamble) - ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { + if (il->staging.flags & RXON_FLG_BAND_24G_MSK) { if (ctx->vif->bss_conf.use_short_slot) - ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; + il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else - ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } il3945_commit_rxon(il, ctx); @@ -2902,7 +2898,7 @@ il3945_config_ap(struct il_priv *il) if (!(il_is_associated(il))) { /* RXON - unassoc (to set timing command) */ - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; il3945_commit_rxon(il, ctx); /* RXON Timing */ @@ -2911,21 +2907,21 @@ il3945_config_ap(struct il_priv *il) IL_WARN("C_RXON_TIMING failed - " "Attempting to continue.\n"); - ctx->staging.assoc_id = 0; + il->staging.assoc_id = 0; if (vif->bss_conf.use_short_preamble) - ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { + if (il->staging.flags & RXON_FLG_BAND_24G_MSK) { if (vif->bss_conf.use_short_slot) - ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; + il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else - ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } /* restore RXON assoc */ - ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; il3945_commit_rxon(il, ctx); } il3945_send_beacon_cmd(il); @@ -3032,7 +3028,6 @@ il3945_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, { struct il_priv *il = hw->priv; __le32 filter_or = 0, filter_nand = 0; - struct il_rxon_context *ctx = &il->ctx; #define CHK(test, flag) do { \ if (*total_flags & (test)) \ @@ -3052,8 +3047,8 @@ il3945_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, mutex_lock(&il->mutex); - ctx->staging.filter_flags &= ~filter_nand; - ctx->staging.filter_flags |= filter_or; + il->staging.filter_flags &= ~filter_nand; + il->staging.filter_flags |= filter_or; /* * Not committing directly because hardware can perform a scan, @@ -3170,9 +3165,8 @@ static ssize_t il3945_show_flags(struct device *d, struct device_attribute *attr, char *buf) { struct il_priv *il = dev_get_drvdata(d); - struct il_rxon_context *ctx = &il->ctx; - return sprintf(buf, "0x%04X\n", ctx->active.flags); + return sprintf(buf, "0x%04X\n", il->active.flags); } static ssize_t @@ -3181,17 +3175,16 @@ il3945_store_flags(struct device *d, struct device_attribute *attr, { struct il_priv *il = dev_get_drvdata(d); u32 flags = simple_strtoul(buf, NULL, 0); - struct il_rxon_context *ctx = &il->ctx; mutex_lock(&il->mutex); - if (le32_to_cpu(ctx->staging.flags) != flags) { + if (le32_to_cpu(il->staging.flags) != flags) { /* Cancel any currently running scans... */ if (il_scan_cancel_timeout(il, 100)) IL_WARN("Could not cancel scan.\n"); else { D_INFO("Committing rxon.flags = 0x%04X\n", flags); - ctx->staging.flags = cpu_to_le32(flags); - il3945_commit_rxon(il, ctx); + il->staging.flags = cpu_to_le32(flags); + il3945_commit_rxon(il, &il->ctx); } } mutex_unlock(&il->mutex); @@ -3207,9 +3200,8 @@ il3945_show_filter_flags(struct device *d, struct device_attribute *attr, char *buf) { struct il_priv *il = dev_get_drvdata(d); - struct il_rxon_context *ctx = &il->ctx; - return sprintf(buf, "0x%04X\n", le32_to_cpu(ctx->active.filter_flags)); + return sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags)); } static ssize_t @@ -3217,19 +3209,18 @@ il3945_store_filter_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { struct il_priv *il = dev_get_drvdata(d); - struct il_rxon_context *ctx = &il->ctx; u32 filter_flags = simple_strtoul(buf, NULL, 0); mutex_lock(&il->mutex); - if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) { + if (le32_to_cpu(il->staging.filter_flags) != filter_flags) { /* Cancel any currently running scans... */ if (il_scan_cancel_timeout(il, 100)) IL_WARN("Could not cancel scan.\n"); else { D_INFO("Committing rxon.filter_flags = " "0x%04X\n", filter_flags); - ctx->staging.filter_flags = cpu_to_le32(filter_flags); - il3945_commit_rxon(il, ctx); + il->staging.filter_flags = cpu_to_le32(filter_flags); + il3945_commit_rxon(il, &il->ctx); } } mutex_unlock(&il->mutex); @@ -3278,9 +3269,8 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { struct il_priv *il = dev_get_drvdata(d); - struct il_rxon_context *ctx = &il->ctx; struct ieee80211_measurement_params params = { - .channel = le16_to_cpu(ctx->active.channel), + .channel = le16_to_cpu(il->active.channel), .start_time = cpu_to_le64(il->_3945.last_tsf), .duration = cpu_to_le16(1), }; diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c index d7a83f22919..40d17d7fcfe 100644 --- a/drivers/net/wireless/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/iwlegacy/3945-rs.c @@ -944,7 +944,7 @@ il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) switch (il->band) { case IEEE80211_BAND_2GHZ: /* TODO: this always does G, not a regression */ - if (il->ctx.active.flags & RXON_FLG_TGG_PROTECT_MSK) { + if (il->active.flags & RXON_FLG_TGG_PROTECT_MSK) { rs_sta->tgg = 1; rs_sta->expected_tpt = il3945_expected_tpt_g_prot; } else diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index 1489b1573a6..dc0433f6801 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -1388,7 +1388,7 @@ il3945_send_tx_power(struct il_priv *il) int rate_idx, i; const struct il_channel_info *ch_info = NULL; struct il3945_txpowertable_cmd txpower = { - .channel = il->ctx.active.channel, + .channel = il->active.channel, }; u16 chan; @@ -1397,7 +1397,7 @@ il3945_send_tx_power(struct il_priv *il) "TX Power requested while scanning!\n")) return -EAGAIN; - chan = le16_to_cpu(il->ctx.active.channel); + chan = le16_to_cpu(il->active.channel); txpower.band = (il->band == IEEE80211_BAND_5GHZ) ? 0 : 1; ch_info = il_get_channel_info(il, il->band, chan); @@ -1673,8 +1673,8 @@ il3945_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) .flags = CMD_WANT_SKB, .data = &rxon_assoc, }; - const struct il_rxon_cmd *rxon1 = &ctx->staging; - const struct il_rxon_cmd *rxon2 = &ctx->active; + const struct il_rxon_cmd *rxon1 = &il->staging; + const struct il_rxon_cmd *rxon2 = &il->active; if (rxon1->flags == rxon2->flags && rxon1->filter_flags == rxon2->filter_flags && @@ -1684,10 +1684,10 @@ il3945_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) return 0; } - rxon_assoc.flags = ctx->staging.flags; - rxon_assoc.filter_flags = ctx->staging.filter_flags; - rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; + rxon_assoc.flags = il->staging.flags; + rxon_assoc.filter_flags = il->staging.filter_flags; + rxon_assoc.ofdm_basic_rates = il->staging.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = il->staging.cck_basic_rates; rxon_assoc.reserved = 0; rc = il_send_cmd_sync(il, &cmd); @@ -1717,8 +1717,8 @@ int il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) { /* cast away the const for active_rxon in this function */ - struct il3945_rxon_cmd *active_rxon = (void *)&ctx->active; - struct il3945_rxon_cmd *staging_rxon = (void *)&ctx->staging; + struct il3945_rxon_cmd *active_rxon = (void *)&il->active; + struct il3945_rxon_cmd *staging_rxon = (void *)&il->staging; int rc = 0; bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK); @@ -1776,7 +1776,7 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) active_rxon->reserved4 = 0; active_rxon->reserved5 = 0; rc = il_send_cmd_pdu(il, C_RXON, sizeof(struct il3945_rxon_cmd), - &il->ctx.active); + &il->active); /* If the mask clearing failed then we set * active_rxon back to what it was previously */ diff --git a/drivers/net/wireless/iwlegacy/4965-calib.c b/drivers/net/wireless/iwlegacy/4965-calib.c index d3248e3ef23..f302a6ac628 100644 --- a/drivers/net/wireless/iwlegacy/4965-calib.c +++ b/drivers/net/wireless/iwlegacy/4965-calib.c @@ -806,8 +806,6 @@ il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp) unsigned long flags; struct stats_rx_non_phy *rx_info; - struct il_rxon_context *ctx = &il->ctx; - if (il->disable_chain_noise_cal) return; @@ -833,8 +831,8 @@ il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp) return; } - rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK); - rxon_chnum = le16_to_cpu(ctx->staging.channel); + rxon_band24 = !!(il->staging.flags & RXON_FLG_BAND_24G_MSK); + rxon_chnum = le16_to_cpu(il->staging.channel); stat_band24 = !!(((struct il_notif_stats *)stat_resp)-> diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 1667232af64..6a77f41dd36 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -926,8 +926,7 @@ il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif) case IEEE80211_BAND_2GHZ: scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; chan_mod = - le32_to_cpu(il->ctx.active. - flags & RXON_FLG_CHANNEL_MODE_MSK) >> + le32_to_cpu(il->active.flags & RXON_FLG_CHANNEL_MODE_MSK) >> RXON_FLG_CHANNEL_MODE_POS; if (chan_mod == CHANNEL_MODE_PURE_40) { rate = RATE_6M_PLCP; @@ -1164,14 +1163,14 @@ il4965_set_rxon_chain(struct il_priv *il, struct il_rxon_context *ctx) rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; - ctx->staging.rx_chain = cpu_to_le16(rx_chain); + il->staging.rx_chain = cpu_to_le16(rx_chain); if (!is_single && active_rx_cnt >= IL_NUM_RX_CHAINS_SINGLE && is_cam) - ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; + il->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; else - ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; + il->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; - D_ASSOC("rx_chain=0x%X active=%d idle=%d\n", ctx->staging.rx_chain, + D_ASSOC("rx_chain=0x%X active=%d idle=%d\n", il->staging.rx_chain, active_rx_cnt, idle_rx_cnt); WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 || @@ -3378,7 +3377,7 @@ il4965_update_chain_flags(struct il_priv *il) { if (il->cfg->ops->hcmd->set_rxon_chain) { il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx); - if (il->ctx.active.rx_chain != il->ctx.staging.rx_chain) + if (il->active.rx_chain != il->staging.rx_chain) il_commit_rxon(il, &il->ctx); } } @@ -5019,11 +5018,11 @@ il4965_alive_start(struct il_priv *il) il->active_rate = RATES_MASK; - if (il_is_associated_ctx(ctx)) { + if (il_is_associated(il)) { struct il_rxon_cmd *active_rxon = - (struct il_rxon_cmd *)&ctx->active; + (struct il_rxon_cmd *)&il->active; /* apply any changes in staging */ - ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ @@ -5768,14 +5767,14 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, test_bit(S_CHANNEL_SWITCH_PENDING, &il->status)) goto out; - if (!il_is_associated_ctx(ctx)) + if (!il_is_associated(il)) goto out; if (!il->cfg->ops->lib->set_channel_switch) goto out; ch = channel->hw_value; - if (le16_to_cpu(ctx->active.channel) == ch) + if (le16_to_cpu(il->active.channel) == ch) goto out; ch_info = il_get_channel_info(il, channel->band, ch); @@ -5807,8 +5806,8 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, } else ctx->ht.is_40mhz = false; - if ((le16_to_cpu(ctx->staging.channel) != ch)) - ctx->staging.flags = 0; + if ((le16_to_cpu(il->staging.channel) != ch)) + il->staging.flags = 0; il_set_rxon_channel(il, channel, ctx); il_set_rxon_ht(il, ht_conf); @@ -5860,8 +5859,8 @@ il4965_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, mutex_lock(&il->mutex); - il->ctx.staging.filter_flags &= ~filter_nand; - il->ctx.staging.filter_flags |= filter_or; + il->staging.filter_flags &= ~filter_nand; + il->staging.filter_flags |= filter_or; /* * Not committing directly because hardware can perform a scan, diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index cacbc03880b..b34de143312 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c @@ -1342,7 +1342,6 @@ il4965_send_tx_power(struct il_priv *il) u8 band = 0; bool is_ht40 = false; u8 ctrl_chan_high = 0; - struct il_rxon_context *ctx = &il->ctx; if (WARN_ONCE (test_bit(S_SCAN_HW, &il->status), @@ -1351,16 +1350,16 @@ il4965_send_tx_power(struct il_priv *il) band = il->band == IEEE80211_BAND_2GHZ; - is_ht40 = iw4965_is_ht40_channel(ctx->active.flags); + is_ht40 = iw4965_is_ht40_channel(il->active.flags); - if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) + if (is_ht40 && (il->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) ctrl_chan_high = 1; cmd.band = band; - cmd.channel = ctx->active.channel; + cmd.channel = il->active.channel; ret = - il4965_fill_txpower_tbl(il, band, le16_to_cpu(ctx->active.channel), + il4965_fill_txpower_tbl(il, band, le16_to_cpu(il->active.channel), is_ht40, ctrl_chan_high, &cmd.tx_power); if (ret) goto out; @@ -1376,8 +1375,8 @@ il4965_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) { int ret = 0; struct il4965_rxon_assoc_cmd rxon_assoc; - const struct il_rxon_cmd *rxon1 = &ctx->staging; - const struct il_rxon_cmd *rxon2 = &ctx->active; + const struct il_rxon_cmd *rxon1 = &il->staging; + const struct il_rxon_cmd *rxon2 = &il->active; if (rxon1->flags == rxon2->flags && rxon1->filter_flags == rxon2->filter_flags && @@ -1392,16 +1391,16 @@ il4965_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) return 0; } - rxon_assoc.flags = ctx->staging.flags; - rxon_assoc.filter_flags = ctx->staging.filter_flags; - rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; + rxon_assoc.flags = il->staging.flags; + rxon_assoc.filter_flags = il->staging.filter_flags; + rxon_assoc.ofdm_basic_rates = il->staging.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = il->staging.cck_basic_rates; rxon_assoc.reserved = 0; rxon_assoc.ofdm_ht_single_stream_basic_rates = - ctx->staging.ofdm_ht_single_stream_basic_rates; + il->staging.ofdm_ht_single_stream_basic_rates; rxon_assoc.ofdm_ht_dual_stream_basic_rates = - ctx->staging.ofdm_ht_dual_stream_basic_rates; - rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain; + il->staging.ofdm_ht_dual_stream_basic_rates; + rxon_assoc.rx_chain_select_flags = il->staging.rx_chain; ret = il_send_cmd_pdu_async(il, C_RXON_ASSOC, sizeof(rxon_assoc), @@ -1414,9 +1413,9 @@ static int il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) { /* cast away the const for active_rxon in this function */ - struct il_rxon_cmd *active_rxon = (void *)&ctx->active; + struct il_rxon_cmd *active_rxon = (void *)&il->active; int ret; - bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); + bool new_assoc = !!(il->staging.filter_flags & RXON_FILTER_ASSOC_MSK); if (!il_is_alive(il)) return -EBUSY; @@ -1425,7 +1424,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) return 0; /* always get timestamp with Rx frame */ - ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; + il->staging.flags |= RXON_FLG_TSF2HOST_MSK; ret = il_check_rxon_cmd(il, ctx); if (ret) { @@ -1438,7 +1437,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) * abort any previous channel switch if still in process */ if (test_bit(S_CHANNEL_SWITCH_PENDING, &il->status) && - il->switch_channel != ctx->staging.channel) { + il->switch_channel != il->staging.channel) { D_11H("abort channel switch on %d\n", le16_to_cpu(il->switch_channel)); il_chswitch_done(il, false); @@ -1454,7 +1453,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) return ret; } - memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); + memcpy(active_rxon, &il->staging, sizeof(*active_rxon)); il_print_rx_config_cmd(il, ctx); /* * We do not commit tx power settings while channel changing, @@ -1468,7 +1467,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) * an RXON_ASSOC and the new config wants the associated mask enabled, * we must clear the associated from the active configuration * before we apply the new config */ - if (il_is_associated_ctx(ctx) && new_assoc) { + if (il_is_associated(il) && new_assoc) { D_INFO("Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -1494,7 +1493,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) D_INFO("Sending RXON\n" "* with%s RXON_FILTER_ASSOC_MSK\n" "* channel = %d\n" "* bssid = %pM\n", (new_assoc ? "" : "out"), - le16_to_cpu(ctx->staging.channel), ctx->staging.bssid_addr); + le16_to_cpu(il->staging.channel), il->staging.bssid_addr); il_set_rxon_hwcrypto(il, ctx, !il->cfg->mod_params->sw_crypto); @@ -1505,13 +1504,13 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) if (!new_assoc) { ret = il_send_cmd_pdu(il, ctx->rxon_cmd, - sizeof(struct il_rxon_cmd), &ctx->staging); + sizeof(struct il_rxon_cmd), &il->staging); if (ret) { IL_ERR("Error setting new RXON (%d)\n", ret); return ret; } D_INFO("Return from !new_assoc RXON.\n"); - memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); + memcpy(active_rxon, &il->staging, sizeof(*active_rxon)); il_clear_ucode_stations(il, ctx); il_restore_stations(il, ctx); ret = il4965_restore_default_wep_keys(il, ctx); @@ -1527,12 +1526,12 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) */ ret = il_send_cmd_pdu(il, ctx->rxon_cmd, - sizeof(struct il_rxon_cmd), &ctx->staging); + sizeof(struct il_rxon_cmd), &il->staging); if (ret) { IL_ERR("Error setting new RXON (%d)\n", ret); return ret; } - memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon)); + memcpy(active_rxon, &il->staging, sizeof(*active_rxon)); } il_print_rx_config_cmd(il, ctx); @@ -1564,21 +1563,21 @@ il4965_hw_channel_switch(struct il_priv *il, u16 ch; u32 tsf_low; u8 switch_count; - u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); + u16 beacon_interval = le16_to_cpu(il->timing.beacon_interval); struct ieee80211_vif *vif = ctx->vif; band = il->band == IEEE80211_BAND_2GHZ; - is_ht40 = iw4965_is_ht40_channel(ctx->staging.flags); + is_ht40 = iw4965_is_ht40_channel(il->staging.flags); - if (is_ht40 && (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) + if (is_ht40 && (il->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) ctrl_chan_high = 1; cmd.band = band; cmd.expect_beacon = 0; ch = ch_switch->channel->hw_value; cmd.channel = cpu_to_le16(ch); - cmd.rxon_flags = ctx->staging.flags; - cmd.rxon_filter_flags = ctx->staging.filter_flags; + cmd.rxon_flags = il->staging.flags; + cmd.rxon_filter_flags = il->staging.filter_flags; switch_count = ch_switch->count; tsf_low = ch_switch->timestamp & 0x0ffffffff; /* @@ -1611,7 +1610,7 @@ il4965_hw_channel_switch(struct il_priv *il, cmd.expect_beacon = il_is_channel_radar(ch_info); else { IL_ERR("invalid channel switch from %u to %u\n", - ctx->active.channel, ch); + il->active.channel, ch); return -EFAULT; } @@ -2139,7 +2138,7 @@ il4965_post_scan(struct il_priv *il) * Since setting the RXON may have been deferred while * performing the scan, fire one off if needed */ - if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) + if (memcmp(&il->staging, &il->active, sizeof(il->staging))) il_commit_rxon(il, ctx); } @@ -2161,41 +2160,41 @@ il4965_post_associate(struct il_priv *il) conf = &il->hw->conf; - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; il_commit_rxon(il, ctx); ret = il_send_rxon_timing(il, ctx); if (ret) IL_WARN("RXON timing - " "Attempting to continue.\n"); - ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; il_set_rxon_ht(il, &il->current_ht_config); if (il->cfg->ops->hcmd->set_rxon_chain) il->cfg->ops->hcmd->set_rxon_chain(il, ctx); - ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); + il->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); D_ASSOC("assoc id %d beacon interval %d\n", vif->bss_conf.aid, vif->bss_conf.beacon_int); if (vif->bss_conf.use_short_preamble) - ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { + if (il->staging.flags & RXON_FLG_BAND_24G_MSK) { if (vif->bss_conf.use_short_slot) - ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; + il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else - ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } il_commit_rxon(il, ctx); D_ASSOC("Associated as %d to: %pM\n", vif->bss_conf.aid, - ctx->active.bssid_addr); + il->active.bssid_addr); switch (vif->type) { case NL80211_IFTYPE_STATION: @@ -2233,10 +2232,10 @@ il4965_config_ap(struct il_priv *il) return; /* The following should be done only at AP bring up */ - if (!il_is_associated_ctx(ctx)) { + if (!il_is_associated(il)) { /* RXON - unassoc (to set timing command) */ - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; il_commit_rxon(il, ctx); /* RXON Timing */ @@ -2251,23 +2250,23 @@ il4965_config_ap(struct il_priv *il) if (il->cfg->ops->hcmd->set_rxon_chain) il->cfg->ops->hcmd->set_rxon_chain(il, ctx); - ctx->staging.assoc_id = 0; + il->staging.assoc_id = 0; if (vif->bss_conf.use_short_preamble) - ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) { + if (il->staging.flags & RXON_FLG_BAND_24G_MSK) { if (vif->bss_conf.use_short_slot) - ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; + il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else - ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } /* need to send beacon cmd before committing assoc RXON! */ il4965_send_beacon_cmd(il); /* restore RXON assoc */ - ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; il_commit_rxon(il, ctx); } il4965_send_beacon_cmd(il); diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 36454d0bbee..2b5622695cc 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -2361,7 +2361,7 @@ il_is_lq_table_valid(struct il_priv *il, struct il_rxon_context *ctx, if (ctx->ht.enabled) return true; - D_INFO("Channel %u is not an HT channel\n", ctx->active.channel); + D_INFO("Channel %u is not an HT channel\n", il->active.channel); for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) { D_INFO("idx %d of LQ expects HT channel\n", i); @@ -2648,7 +2648,7 @@ il_set_decrypted_flag(struct il_priv *il, struct ieee80211_hdr *hdr, * All contexts have the same setting here due to it being * a module parameter, so OK to check any context. */ - if (il->ctx.active.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) + if (il->active.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) return 0; if (!(fc & IEEE80211_FCTL_PROTECTED)) @@ -3581,7 +3581,7 @@ il_is_ht40_tx_allowed(struct il_priv *il, struct il_rxon_context *ctx, #endif return il_is_channel_extension(il, il->band, - le16_to_cpu(ctx->staging.channel), + le16_to_cpu(il->staging.channel), ctx->ht.extension_chan_offset); } EXPORT_SYMBOL(il_is_ht40_tx_allowed); @@ -3633,10 +3633,10 @@ il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx) lockdep_assert_held(&il->mutex); - memset(&ctx->timing, 0, sizeof(struct il_rxon_time_cmd)); + memset(&il->timing, 0, sizeof(struct il_rxon_time_cmd)); - ctx->timing.timestamp = cpu_to_le64(il->timestamp); - ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval); + il->timing.timestamp = cpu_to_le64(il->timestamp); + il->timing.listen_interval = cpu_to_le16(conf->listen_interval); beacon_int = vif ? vif->bss_conf.beacon_int : 0; @@ -3644,28 +3644,28 @@ il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx) * TODO: For IBSS we need to get atim_win from mac80211, * for now just always use 0 */ - ctx->timing.atim_win = 0; + il->timing.atim_win = 0; beacon_int = il_adjust_beacon_interval(beacon_int, il->hw_params.max_beacon_itrvl * TIME_UNIT); - ctx->timing.beacon_interval = cpu_to_le16(beacon_int); + il->timing.beacon_interval = cpu_to_le16(beacon_int); tsf = il->timestamp; /* tsf is modifed by do_div: copy it */ interval_tm = beacon_int * TIME_UNIT; rem = do_div(tsf, interval_tm); - ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); + il->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); - ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ? : 1) : 1; + il->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ? : 1) : 1; D_ASSOC("beacon interval %d beacon timer %d beacon tim %d\n", - le16_to_cpu(ctx->timing.beacon_interval), - le32_to_cpu(ctx->timing.beacon_init_val), - le16_to_cpu(ctx->timing.atim_win)); + le16_to_cpu(il->timing.beacon_interval), + le32_to_cpu(il->timing.beacon_init_val), + le16_to_cpu(il->timing.atim_win)); - return il_send_cmd_pdu(il, ctx->rxon_timing_cmd, sizeof(ctx->timing), - &ctx->timing); + return il_send_cmd_pdu(il, il->ctx.rxon_timing_cmd, sizeof(il->timing), + &il->timing); } EXPORT_SYMBOL(il_send_rxon_timing); @@ -3673,7 +3673,7 @@ void il_set_rxon_hwcrypto(struct il_priv *il, struct il_rxon_context *ctx, int hw_decrypt) { - struct il_rxon_cmd *rxon = &ctx->staging; + struct il_rxon_cmd *rxon = &il->staging; if (hw_decrypt) rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; @@ -3687,7 +3687,7 @@ EXPORT_SYMBOL(il_set_rxon_hwcrypto); int il_check_rxon_cmd(struct il_priv *il, struct il_rxon_context *ctx) { - struct il_rxon_cmd *rxon = &ctx->staging; + struct il_rxon_cmd *rxon = &il->staging; bool error = false; if (rxon->flags & RXON_FLG_BAND_24G_MSK) { @@ -3767,8 +3767,8 @@ EXPORT_SYMBOL(il_check_rxon_cmd); int il_full_rxon_required(struct il_priv *il, struct il_rxon_context *ctx) { - const struct il_rxon_cmd *staging = &ctx->staging; - const struct il_rxon_cmd *active = &ctx->active; + const struct il_rxon_cmd *staging = &il->staging; + const struct il_rxon_cmd *active = &il->active; #define CHK(cond) \ if ((cond)) { \ @@ -3785,7 +3785,7 @@ il_full_rxon_required(struct il_priv *il, struct il_rxon_context *ctx) } /* These items are only settable from the full RXON command */ - CHK(!il_is_associated_ctx(ctx)); + CHK(!il_is_associated(il)); CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr)); CHK(compare_ether_addr(staging->node_addr, active->node_addr)); CHK(compare_ether_addr @@ -3825,7 +3825,7 @@ il_get_lowest_plcp(struct il_priv *il, struct il_rxon_context *ctx) * Assign the lowest rate -- should really get this from * the beacon skb from mac80211. */ - if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) + if (il->staging.flags & RXON_FLG_BAND_24G_MSK) return RATE_1M_PLCP; else return RATE_6M_PLCP; @@ -3836,7 +3836,7 @@ static void _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, struct il_rxon_context *ctx) { - struct il_rxon_cmd *rxon = &ctx->staging; + struct il_rxon_cmd *rxon = &il->staging; if (!ctx->ht.enabled) { rxon->flags &= @@ -3925,7 +3925,7 @@ il_get_single_channel_number(struct il_priv *il, enum ieee80211_band band) for (i = min; i < max; i++) { channel = il->channel_info[i].channel; - if (channel == le16_to_cpu(il->ctx.staging.channel)) + if (channel == le16_to_cpu(il->staging.channel)) continue; ch_info = il_get_channel_info(il, band, channel); @@ -3951,14 +3951,14 @@ il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch, enum ieee80211_band band = ch->band; u16 channel = ch->hw_value; - if (le16_to_cpu(ctx->staging.channel) == channel && il->band == band) + if (le16_to_cpu(il->staging.channel) == channel && il->band == band) return 0; - ctx->staging.channel = cpu_to_le16(channel); + il->staging.channel = cpu_to_le16(channel); if (band == IEEE80211_BAND_5GHZ) - ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK; + il->staging.flags &= ~RXON_FLG_BAND_24G_MSK; else - ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; + il->staging.flags |= RXON_FLG_BAND_24G_MSK; il->band = band; @@ -3973,20 +3973,20 @@ il_set_flags_for_band(struct il_priv *il, struct il_rxon_context *ctx, enum ieee80211_band band, struct ieee80211_vif *vif) { if (band == IEEE80211_BAND_5GHZ) { - ctx->staging.flags &= + il->staging.flags &= ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_CCK_MSK); - ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; + il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; } else { /* Copied from il_post_associate() */ if (vif && vif->bss_conf.use_short_slot) - ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; + il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else - ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; + il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; - ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK; - ctx->staging.flags &= ~RXON_FLG_CCK_MSK; + il->staging.flags |= RXON_FLG_BAND_24G_MSK; + il->staging.flags |= RXON_FLG_AUTO_DETECT_MSK; + il->staging.flags &= ~RXON_FLG_CCK_MSK; } } EXPORT_SYMBOL(il_set_flags_for_band); @@ -3999,22 +3999,22 @@ il_connection_init_rx_config(struct il_priv *il, struct il_rxon_context *ctx) { const struct il_channel_info *ch_info; - memset(&ctx->staging, 0, sizeof(ctx->staging)); + memset(&il->staging, 0, sizeof(il->staging)); if (!ctx->vif) { - ctx->staging.dev_type = ctx->unused_devtype; + il->staging.dev_type = ctx->unused_devtype; } else switch (ctx->vif->type) { case NL80211_IFTYPE_STATION: - ctx->staging.dev_type = ctx->station_devtype; - ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; + il->staging.dev_type = ctx->station_devtype; + il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; break; case NL80211_IFTYPE_ADHOC: - ctx->staging.dev_type = ctx->ibss_devtype; - ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; - ctx->staging.filter_flags = + il->staging.dev_type = ctx->ibss_devtype; + il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; @@ -4029,35 +4029,35 @@ il_connection_init_rx_config(struct il_priv *il, struct il_rxon_context *ctx) /* TODO: Figure out when short_preamble would be set and cache from * that */ if (!hw_to_local(il->hw)->short_preamble) - ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; else - ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; #endif ch_info = - il_get_channel_info(il, il->band, le16_to_cpu(ctx->active.channel)); + il_get_channel_info(il, il->band, le16_to_cpu(il->active.channel)); if (!ch_info) ch_info = &il->channel_info[0]; - ctx->staging.channel = cpu_to_le16(ch_info->channel); + il->staging.channel = cpu_to_le16(ch_info->channel); il->band = ch_info->band; il_set_flags_for_band(il, ctx, il->band, ctx->vif); - ctx->staging.ofdm_basic_rates = + il->staging.ofdm_basic_rates = (IL_OFDM_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF; - ctx->staging.cck_basic_rates = + il->staging.cck_basic_rates = (IL_CCK_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF; /* clear both MIX and PURE40 mode flag */ - ctx->staging.flags &= + il->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | RXON_FLG_CHANNEL_MODE_PURE_40); if (ctx->vif) - memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN); + memcpy(il->staging.node_addr, ctx->vif->addr, ETH_ALEN); - ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff; - ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; + il->staging.ofdm_ht_single_stream_basic_rates = 0xff; + il->staging.ofdm_ht_dual_stream_basic_rates = 0xff; } EXPORT_SYMBOL(il_connection_init_rx_config); @@ -4084,10 +4084,10 @@ il_set_rate(struct il_priv *il) D_RATE("Set active_rate = %0x\n", il->active_rate); - il->ctx.staging.cck_basic_rates = + il->staging.cck_basic_rates = (IL_CCK_BASIC_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF; - il->ctx.staging.ofdm_basic_rates = + il->staging.ofdm_basic_rates = (IL_OFDM_BASIC_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF; } EXPORT_SYMBOL(il_set_rate); @@ -4110,16 +4110,14 @@ il_hdl_csa(struct il_priv *il, struct il_rx_buf *rxb) { struct il_rx_pkt *pkt = rxb_addr(rxb); struct il_csa_notification *csa = &(pkt->u.csa_notif); - - struct il_rxon_context *ctx = &il->ctx; - struct il_rxon_cmd *rxon = (void *)&ctx->active; + struct il_rxon_cmd *rxon = (void *)&il->active; if (!test_bit(S_CHANNEL_SWITCH_PENDING, &il->status)) return; if (!le32_to_cpu(csa->status) && csa->channel == il->switch_channel) { rxon->channel = csa->channel; - ctx->staging.channel = csa->channel; + il->staging.channel = csa->channel; D_11H("CSA notif: channel %d\n", le16_to_cpu(csa->channel)); il_chswitch_done(il, true); } else { @@ -4134,7 +4132,7 @@ EXPORT_SYMBOL(il_hdl_csa); void il_print_rx_config_cmd(struct il_priv *il, struct il_rxon_context *ctx) { - struct il_rxon_cmd *rxon = &ctx->staging; + struct il_rxon_cmd *rxon = &il->staging; D_RADIO("RX CONFIG:\n"); il_print_hex_dump(il, IL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); @@ -4347,7 +4345,6 @@ il_set_tx_power(struct il_priv *il, s8 tx_power, bool force) int ret; s8 prev_tx_power; bool defer; - struct il_rxon_context *ctx = &il->ctx; lockdep_assert_held(&il->mutex); @@ -4378,7 +4375,7 @@ il_set_tx_power(struct il_priv *il, s8 tx_power, bool force) /* do not set tx power when scanning or channel changing */ defer = test_bit(S_SCANNING, &il->status) || - memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); + memcmp(&il->active, &il->staging, sizeof(il->staging)); if (defer && !force) { D_INFO("Deferring tx power set\n"); return 0; @@ -5379,8 +5376,8 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) /* if we are switching from ht to 2.4 clear flags * from any ht related info since 2.4 does not * support ht */ - if ((le16_to_cpu(ctx->staging.channel) != ch)) - ctx->staging.flags = 0; + if ((le16_to_cpu(il->staging.channel) != ch)) + il->staging.flags = 0; il_set_rxon_channel(il, channel, ctx); il_set_rxon_ht(il, ht_conf); @@ -5420,7 +5417,7 @@ set_ch_out: if (scan_active) goto out; - if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging))) + if (memcmp(&il->active, &il->staging, sizeof(il->staging))) il_commit_rxon(il, ctx); else D_INFO("Not re-sending same RXON configuration.\n"); @@ -5473,7 +5470,7 @@ il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) /* we are restarting association process * clear RXON_FILTER_ASSOC_MSK bit */ - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; il_commit_rxon(il, ctx); il_set_rate(il); @@ -5555,8 +5552,8 @@ il_set_no_assoc(struct il_priv *il, struct ieee80211_vif *vif) * association and that no more packets should be * sent */ - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ctx->staging.assoc_id = 0; + il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + il->staging.assoc_id = 0; il_commit_rxon(il, ctx); } @@ -5660,13 +5657,13 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* mac80211 only sets assoc when in STATION mode */ if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { - memcpy(ctx->staging.bssid_addr, bss_conf->bssid, + memcpy(il->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); /* currently needed in a few places */ memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); } else { - ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; } } @@ -5682,21 +5679,21 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (changes & BSS_CHANGED_ERP_PREAMBLE) { D_MAC80211("ERP_PREAMBLE %d\n", bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) - ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else - ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; } if (changes & BSS_CHANGED_ERP_CTS_PROT) { D_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && il->band != IEEE80211_BAND_5GHZ) - ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; + il->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; else - ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + il->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; if (bss_conf->use_cts_prot) - ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; + il->staging.flags |= RXON_FLG_SELF_CTS_EN; else - ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; + il->staging.flags &= ~RXON_FLG_SELF_CTS_EN; } if (changes & BSS_CHANGED_BASIC_RATES) { @@ -5706,12 +5703,12 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, * like this here: * if (A-band) - ctx->staging.ofdm_basic_rates = + il->staging.ofdm_basic_rates = bss_conf->basic_rates; else - ctx->staging.ofdm_basic_rates = + il->staging.ofdm_basic_rates = bss_conf->basic_rates >> 4; - ctx->staging.cck_basic_rates = + il->staging.cck_basic_rates = bss_conf->basic_rates & 0xF; */ } @@ -5734,19 +5731,19 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, il_set_no_assoc(il, vif); } - if (changes && il_is_associated_ctx(ctx) && bss_conf->aid) { + if (changes && il_is_associated(il) && bss_conf->aid) { D_MAC80211("Changes (%#x) while associated\n", changes); ret = il_send_rxon_assoc(il, ctx); if (!ret) { /* Sync active_rxon with latest change. */ - memcpy((void *)&ctx->active, &ctx->staging, + memcpy((void *)&il->active, &il->staging, sizeof(struct il_rxon_cmd)); } } if (changes & BSS_CHANGED_BEACON_ENABLED) { if (vif->bss_conf.enable_beacon) { - memcpy(ctx->staging.bssid_addr, bss_conf->bssid, + memcpy(il->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); il->cfg->ops->legacy->config_ap(il); diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index abfa388588b..ba801c7d9ad 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1171,17 +1171,6 @@ struct il_rxon_context { u32 interface_modes, exclusive_interface_modes; u8 unused_devtype, ap_devtype, ibss_devtype, station_devtype; - /* - * We declare this const so it can only be - * changed via explicit cast within the - * routines that actually update the physical - * hardware. - */ - const struct il_rxon_cmd active; - struct il_rxon_cmd staging; - - struct il_rxon_time_cmd timing; - struct il_qos_info qos_data; u8 bcast_sta_id, ap_sta_id; @@ -1306,6 +1295,17 @@ struct il_priv { struct il_rxon_context ctx; + /* + * We declare this const so it can only be + * changed via explicit cast within the + * routines that actually update the physical + * hardware. + */ + const struct il_rxon_cmd active; + struct il_rxon_cmd staging; + + struct il_rxon_time_cmd timing; + __le16 switch_channel; /* 1st responses from initialize and runtime uCode images. @@ -1530,7 +1530,7 @@ il_rxon_ctx_from_vif(struct ieee80211_vif *vif) static inline int il_is_associated(struct il_priv *il) { - return (il->ctx.active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; + return (il->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; } static inline int @@ -1539,12 +1539,6 @@ il_is_any_associated(struct il_priv *il) return il_is_associated(il); } -static inline int -il_is_associated_ctx(struct il_rxon_context *ctx) -{ - return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; -} - static inline int il_is_channel_valid(const struct il_channel_info *ch_info) { diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c index b1b8926a9c7..6e3841beb1d 100644 --- a/drivers/net/wireless/iwlegacy/debug.c +++ b/drivers/net/wireless/iwlegacy/debug.c @@ -1153,7 +1153,7 @@ il_dbgfs_rxon_flags_read(struct file *file, char __user *user_buf, int len = 0; char buf[20]; - len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->ctx.active.flags)); + len = sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.flags)); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -1167,7 +1167,7 @@ il_dbgfs_rxon_filter_flags_read(struct file *file, char __user *user_buf, char buf[20]; len = - sprintf(buf, "0x%04X\n", le32_to_cpu(il->ctx.active.filter_flags)); + sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags)); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } -- cgit v1.2.3 From 6122d18236837ed7f264632e6b27d5cb3005add2 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:38 +0100 Subject: iwlegacy: get rid of ctx->rxon_cmd Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 1 - drivers/net/wireless/iwlegacy/4965-mac.c | 1 - drivers/net/wireless/iwlegacy/4965.c | 6 +++--- drivers/net/wireless/iwlegacy/common.h | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 980566fdb81..8de8355c523 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3619,7 +3619,6 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.ctxid = 0; - il->ctx.rxon_cmd = C_RXON; il->ctx.rxon_timing_cmd = C_RXON_TIMING; il->ctx.rxon_assoc_cmd = C_RXON_ASSOC; il->ctx.qos_cmd = C_QOS_PARAM; diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 6a77f41dd36..2368f3ab02b 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -6135,7 +6135,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.always_active = true; il->ctx.is_active = true; - il->ctx.rxon_cmd = C_RXON; il->ctx.rxon_timing_cmd = C_RXON_TIMING; il->ctx.rxon_assoc_cmd = C_RXON_ASSOC; il->ctx.qos_cmd = C_QOS_PARAM; diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index b34de143312..8926108118f 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c @@ -1472,7 +1472,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; ret = - il_send_cmd_pdu(il, ctx->rxon_cmd, + il_send_cmd_pdu(il, C_RXON, sizeof(struct il_rxon_cmd), active_rxon); /* If the mask clearing failed then we set @@ -1503,7 +1503,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) */ if (!new_assoc) { ret = - il_send_cmd_pdu(il, ctx->rxon_cmd, + il_send_cmd_pdu(il, C_RXON, sizeof(struct il_rxon_cmd), &il->staging); if (ret) { IL_ERR("Error setting new RXON (%d)\n", ret); @@ -1525,7 +1525,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) * RXON assoc doesn't clear the station table in uCode, */ ret = - il_send_cmd_pdu(il, ctx->rxon_cmd, + il_send_cmd_pdu(il, C_RXON, sizeof(struct il_rxon_cmd), &il->staging); if (ret) { IL_ERR("Error setting new RXON (%d)\n", ret); diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index ba801c7d9ad..80c60e57de3 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1175,7 +1175,7 @@ struct il_rxon_context { u8 bcast_sta_id, ap_sta_id; - u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd; + u8 rxon_assoc_cmd, rxon_timing_cmd; u8 qos_cmd; u8 wep_key_cmd; -- cgit v1.2.3 From 63d0f0c5512e29f87ed2e1612bb637d857f3b345 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:39 +0100 Subject: iwlegacy: get rid of ctx->rxon_timing_cmd Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 1 - drivers/net/wireless/iwlegacy/4965-mac.c | 1 - drivers/net/wireless/iwlegacy/common.c | 2 +- drivers/net/wireless/iwlegacy/common.h | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 8de8355c523..5ca8a784436 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3619,7 +3619,6 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.ctxid = 0; - il->ctx.rxon_timing_cmd = C_RXON_TIMING; il->ctx.rxon_assoc_cmd = C_RXON_ASSOC; il->ctx.qos_cmd = C_QOS_PARAM; il->ctx.ap_sta_id = IL_AP_ID; diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 2368f3ab02b..9539acc132a 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -6135,7 +6135,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.always_active = true; il->ctx.is_active = true; - il->ctx.rxon_timing_cmd = C_RXON_TIMING; il->ctx.rxon_assoc_cmd = C_RXON_ASSOC; il->ctx.qos_cmd = C_QOS_PARAM; il->ctx.ap_sta_id = IL_AP_ID; diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 2b5622695cc..902521469e1 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -3664,7 +3664,7 @@ il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx) le32_to_cpu(il->timing.beacon_init_val), le16_to_cpu(il->timing.atim_win)); - return il_send_cmd_pdu(il, il->ctx.rxon_timing_cmd, sizeof(il->timing), + return il_send_cmd_pdu(il, C_RXON_TIMING, sizeof(il->timing), &il->timing); } EXPORT_SYMBOL(il_send_rxon_timing); diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 80c60e57de3..d1d505580b1 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1175,7 +1175,7 @@ struct il_rxon_context { u8 bcast_sta_id, ap_sta_id; - u8 rxon_assoc_cmd, rxon_timing_cmd; + u8 rxon_assoc_cmd; u8 qos_cmd; u8 wep_key_cmd; -- cgit v1.2.3 From 5e349f02963acc2c3607119e6e64f0cbc8d23e17 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:40 +0100 Subject: iwlegacy: get rid of rxon_assoc_cmd Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 1 - drivers/net/wireless/iwlegacy/4965-mac.c | 1 - drivers/net/wireless/iwlegacy/common.h | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 5ca8a784436..e5857df2df2 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3619,7 +3619,6 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.ctxid = 0; - il->ctx.rxon_assoc_cmd = C_RXON_ASSOC; il->ctx.qos_cmd = C_QOS_PARAM; il->ctx.ap_sta_id = IL_AP_ID; il->ctx.wep_key_cmd = C_WEPKEY; diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 9539acc132a..bd83299be31 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -6135,7 +6135,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.always_active = true; il->ctx.is_active = true; - il->ctx.rxon_assoc_cmd = C_RXON_ASSOC; il->ctx.qos_cmd = C_QOS_PARAM; il->ctx.ap_sta_id = IL_AP_ID; il->ctx.wep_key_cmd = C_WEPKEY; diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index d1d505580b1..d8e309a1756 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1175,7 +1175,6 @@ struct il_rxon_context { u8 bcast_sta_id, ap_sta_id; - u8 rxon_assoc_cmd; u8 qos_cmd; u8 wep_key_cmd; -- cgit v1.2.3 From b96ed60cd0c352891fd04f4aa748f4d36a6cec5b Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:41 +0100 Subject: iwlegacy: get rid of qos_cmd Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 1 - drivers/net/wireless/iwlegacy/4965-mac.c | 1 - drivers/net/wireless/iwlegacy/common.c | 2 +- drivers/net/wireless/iwlegacy/common.h | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index e5857df2df2..bbbac26d8f4 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3619,7 +3619,6 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.ctxid = 0; - il->ctx.qos_cmd = C_QOS_PARAM; il->ctx.ap_sta_id = IL_AP_ID; il->ctx.wep_key_cmd = C_WEPKEY; il->ctx.interface_modes = diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index bd83299be31..2ee5de38bb3 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -6135,7 +6135,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.always_active = true; il->ctx.is_active = true; - il->ctx.qos_cmd = C_QOS_PARAM; il->ctx.ap_sta_id = IL_AP_ID; il->ctx.wep_key_cmd = C_WEPKEY; il->ctx.ac_to_fifo = il4965_bss_ac_to_fifo; diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 902521469e1..b95f832b14e 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -5269,7 +5269,7 @@ il_update_qos(struct il_priv *il, struct il_rxon_context *ctx) D_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", ctx->qos_data.qos_active, ctx->qos_data.def_qos_parm.qos_flags); - il_send_cmd_pdu_async(il, ctx->qos_cmd, sizeof(struct il_qosparam_cmd), + il_send_cmd_pdu_async(il, C_QOS_PARAM, sizeof(struct il_qosparam_cmd), &ctx->qos_data.def_qos_parm, NULL); } diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index d8e309a1756..b08ddd13443 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1175,7 +1175,6 @@ struct il_rxon_context { u8 bcast_sta_id, ap_sta_id; - u8 qos_cmd; u8 wep_key_cmd; struct il_wep_key wep_keys[WEP_KEYS_MAX]; -- cgit v1.2.3 From d98e294231a29699848fd0e923d91fe979e13802 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:42 +0100 Subject: iwlegacy: get rid of wep_key_cmd Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 1 - drivers/net/wireless/iwlegacy/4965-mac.c | 3 +-- drivers/net/wireless/iwlegacy/common.h | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index bbbac26d8f4..4a01acbf3a2 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3620,7 +3620,6 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.ctxid = 0; il->ctx.ap_sta_id = IL_AP_ID; - il->ctx.wep_key_cmd = C_WEPKEY; il->ctx.interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); il->ctx.ibss_devtype = RXON_DEV_TYPE_IBSS; diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 2ee5de38bb3..a2955a45c33 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -2823,7 +2823,7 @@ il4965_static_wepkey_cmd(struct il_priv *il, struct il_rxon_context *ctx, struct il_wep_cmd *wep_cmd = (struct il_wep_cmd *)buff; size_t cmd_size = sizeof(struct il_wep_cmd); struct il_host_cmd cmd = { - .id = ctx->wep_key_cmd, + .id = C_WEPKEY, .data = wep_cmd, .flags = CMD_SYNC, }; @@ -6136,7 +6136,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.always_active = true; il->ctx.is_active = true; il->ctx.ap_sta_id = IL_AP_ID; - il->ctx.wep_key_cmd = C_WEPKEY; il->ctx.ac_to_fifo = il4965_bss_ac_to_fifo; il->ctx.ac_to_queue = il4965_bss_ac_to_queue; il->ctx.exclusive_interface_modes = BIT(NL80211_IFTYPE_ADHOC); diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index b08ddd13443..46835f932bf 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1175,8 +1175,6 @@ struct il_rxon_context { u8 bcast_sta_id, ap_sta_id; - u8 wep_key_cmd; - struct il_wep_key wep_keys[WEP_KEYS_MAX]; u8 key_mapping_keys; -- cgit v1.2.3 From 8f9e56455310a3d75e8239db9729acb2b31dbdad Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:43 +0100 Subject: iwlegacy: get rid of ap_sta_id Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 1 - drivers/net/wireless/iwlegacy/4965-mac.c | 3 +-- drivers/net/wireless/iwlegacy/common.c | 2 +- drivers/net/wireless/iwlegacy/common.h | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 4a01acbf3a2..8072ae8b0ce 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3619,7 +3619,6 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.ctxid = 0; - il->ctx.ap_sta_id = IL_AP_ID; il->ctx.interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); il->ctx.ibss_devtype = RXON_DEV_TYPE_IBSS; diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index a2955a45c33..f2b03cd243b 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -2906,7 +2906,7 @@ il4965_set_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; keyconf->hw_key_idx = HW_KEY_DEFAULT; - il->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher; + il->stations[IL_AP_ID].keyinfo.cipher = keyconf->cipher; ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key, @@ -6135,7 +6135,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.always_active = true; il->ctx.is_active = true; - il->ctx.ap_sta_id = IL_AP_ID; il->ctx.ac_to_fifo = il4965_bss_ac_to_fifo; il->ctx.ac_to_queue = il4965_bss_ac_to_queue; il->ctx.exclusive_interface_modes = BIT(NL80211_IFTYPE_ADHOC); diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index b95f832b14e..d30a2062992 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -1899,7 +1899,7 @@ il_prep_station(struct il_priv *il, struct il_rxon_context *ctx, u16 rate; if (is_ap) - sta_id = ctx->ap_sta_id; + sta_id = IL_AP_ID; else if (is_broadcast_ether_addr(addr)) sta_id = ctx->bcast_sta_id; else diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 46835f932bf..cf7352f45cd 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1173,7 +1173,7 @@ struct il_rxon_context { struct il_qos_info qos_data; - u8 bcast_sta_id, ap_sta_id; + u8 bcast_sta_id; struct il_wep_key wep_keys[WEP_KEYS_MAX]; u8 key_mapping_keys; -- cgit v1.2.3 From b16db50a6dc486c3a6c32cd7982a75452cb785c2 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:44 +0100 Subject: iwlegacy: move bcast_sta_id to hw_params Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 4 ++-- drivers/net/wireless/iwlegacy/3945-rs.c | 2 +- drivers/net/wireless/iwlegacy/3945.c | 5 +++-- drivers/net/wireless/iwlegacy/4965-mac.c | 15 ++++++++------- drivers/net/wireless/iwlegacy/4965.c | 3 +-- drivers/net/wireless/iwlegacy/common.c | 2 +- drivers/net/wireless/iwlegacy/common.h | 6 +++--- 7 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 8072ae8b0ce..b11701f5874 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -140,7 +140,7 @@ il3945_set_ccmp_dynamic_key_info(struct il_priv *il, key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - if (sta_id == il->ctx.bcast_sta_id) + if (sta_id == il->hw_params.bcast_id) key_flags |= STA_KEY_MULTICAST_MSK; keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; @@ -2598,7 +2598,7 @@ il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif) /* We don't build a direct scan probe request; the uCode will do * that based on the direct_mask added to each channel entry */ scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = il->ctx.bcast_sta_id; + scan->tx_cmd.sta_id = il->hw_params.bcast_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; /* flags + rate selection */ diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c index 40d17d7fcfe..6a782b5c0c5 100644 --- a/drivers/net/wireless/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/iwlegacy/3945-rs.c @@ -342,7 +342,7 @@ il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id) int i; D_INFO("enter\n"); - if (sta_id == il->ctx.bcast_sta_id) + if (sta_id == il->hw_params.bcast_id) goto out; psta = (struct il3945_sta_priv *)sta->drv_priv; diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index dc0433f6801..3024645a6be 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -2396,6 +2396,8 @@ il3945_hw_set_hw_params(struct il_priv *il) return -ENOMEM; } + il->hw_params.bcast_id = IL3945_BROADCAST_ID; + /* Assign number of Usable TX queues */ il->hw_params.max_txq_num = il->cfg->base_params->num_of_queues; @@ -2404,7 +2406,6 @@ il3945_hw_set_hw_params(struct il_priv *il) il->hw_params.max_rxq_size = RX_QUEUE_SIZE; il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; il->hw_params.max_stations = IL3945_STATION_COUNT; - il->ctx.bcast_sta_id = IL3945_BROADCAST_ID; il->sta_key_max_num = STA_KEY_MAX_NUM; @@ -2425,7 +2426,7 @@ il3945_hw_get_beacon_cmd(struct il_priv *il, struct il3945_frame *frame, tx_beacon_cmd = (struct il3945_tx_beacon_cmd *)&frame->u; memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); - tx_beacon_cmd->tx.sta_id = il->ctx.bcast_sta_id; + tx_beacon_cmd->tx.sta_id = il->hw_params.bcast_id; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; frame_size = diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index f2b03cd243b..af7886243fe 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -919,7 +919,7 @@ il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif) D_SCAN("Start passive scan.\n"); scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = ctx->bcast_sta_id; + scan->tx_cmd.sta_id = il->hw_params.bcast_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; switch (il->scan_band) { @@ -1678,7 +1678,7 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) /* For management frames use broadcast id to do not break aggregation */ if (!ieee80211_is_data(fc)) - sta_id = ctx->bcast_sta_id; + sta_id = il->hw_params.bcast_id; else { /* Find idx into station table for destination station */ sta_id = il_sta_id_or_broadcast(il, ctx, info->control.sta); @@ -2938,7 +2938,7 @@ il4965_set_wep_dynamic_key_info(struct il_priv *il, struct il_rxon_context *ctx, if (keyconf->keylen == WEP_KEY_LEN_128) key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; - if (sta_id == ctx->bcast_sta_id) + if (sta_id == il->hw_params.bcast_id) key_flags |= STA_KEY_MULTICAST_MSK; spin_lock_irqsave(&il->sta_lock, flags); @@ -2988,7 +2988,7 @@ il4965_set_ccmp_dynamic_key_info(struct il_priv *il, key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags &= ~STA_KEY_FLG_INVALID; - if (sta_id == ctx->bcast_sta_id) + if (sta_id == il->hw_params.bcast_id) key_flags |= STA_KEY_MULTICAST_MSK; keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; @@ -3035,7 +3035,7 @@ il4965_set_tkip_dynamic_key_info(struct il_priv *il, key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags &= ~STA_KEY_FLG_INVALID; - if (sta_id == ctx->bcast_sta_id) + if (sta_id == il->hw_params.bcast_id) key_flags |= STA_KEY_MULTICAST_MSK; keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; @@ -3253,7 +3253,7 @@ il4965_update_bcast_station(struct il_priv *il, struct il_rxon_context *ctx) { unsigned long flags; struct il_link_quality_cmd *link_cmd; - u8 sta_id = ctx->bcast_sta_id; + u8 sta_id = il->hw_params.bcast_id; link_cmd = il4965_sta_alloc_lq(il, sta_id); if (!link_cmd) { @@ -3510,7 +3510,7 @@ il4965_hw_get_beacon_cmd(struct il_priv *il, struct il_frame *frame) /* Set up TX command fields */ tx_beacon_cmd->tx.len = cpu_to_le16((u16) frame_size); - tx_beacon_cmd->tx.sta_id = il->beacon_ctx->bcast_sta_id; + tx_beacon_cmd->tx.sta_id = il->hw_params.bcast_id; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK | @@ -6082,6 +6082,7 @@ il4965_hw_detect(struct il_priv *il) static int il4965_set_hw_params(struct il_priv *il) { + il->hw_params.bcast_id = IL4965_BROADCAST_ID; il->hw_params.max_rxq_size = RX_QUEUE_SIZE; il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; if (il->cfg->mod_params->amsdu_size_8K) diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index 8926108118f..8d0fd60bc49 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c @@ -624,7 +624,6 @@ il4965_hw_set_hw_params(struct il_priv *il) sizeof(struct il4965_scd_bc_tbl); il->hw_params.tfd_size = sizeof(struct il_tfd); il->hw_params.max_stations = IL4965_STATION_COUNT; - il->ctx.bcast_sta_id = IL4965_BROADCAST_ID; il->hw_params.max_data_size = IL49_RTC_DATA_SIZE; il->hw_params.max_inst_size = IL49_RTC_INST_SIZE; il->hw_params.max_bsm_size = BSM_SRAM_SIZE; @@ -1968,7 +1967,7 @@ il4965_find_station(struct il_priv *il, const u8 * addr) start = IL_STA_ID; if (is_broadcast_ether_addr(addr)) - return il->ctx.bcast_sta_id; + return il->hw_params.bcast_id; spin_lock_irqsave(&il->sta_lock, flags); for (i = start; i < il->hw_params.max_stations; i++) diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index d30a2062992..b7567a8063b 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -1901,7 +1901,7 @@ il_prep_station(struct il_priv *il, struct il_rxon_context *ctx, if (is_ap) sta_id = IL_AP_ID; else if (is_broadcast_ether_addr(addr)) - sta_id = ctx->bcast_sta_id; + sta_id = il->hw_params.bcast_id; else for (i = IL_STA_ID; i < il->hw_params.max_stations; i++) { if (!compare_ether_addr diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index cf7352f45cd..66d0c1dd589 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -816,6 +816,7 @@ struct il_sensitivity_ranges { /** * struct il_hw_params + * @bcast_id: f/w broadcast station ID * @max_txq_num: Max # Tx queues supported * @dma_chnl_num: Number of Tx DMA/FIFO channels * @scd_bc_tbls_size: size of scheduler byte count tables @@ -836,6 +837,7 @@ struct il_sensitivity_ranges { * @struct il_sensitivity_ranges: range of sensitivity values */ struct il_hw_params { + u8 bcast_id; u8 max_txq_num; u8 dma_chnl_num; u16 scd_bc_tbls_size; @@ -1173,8 +1175,6 @@ struct il_rxon_context { struct il_qos_info qos_data; - u8 bcast_sta_id; - struct il_wep_key wep_keys[WEP_KEYS_MAX]; u8 key_mapping_keys; @@ -2372,7 +2372,7 @@ il_sta_id_or_broadcast(struct il_priv *il, struct il_rxon_context *context, int sta_id; if (!sta) - return context->bcast_sta_id; + return il->hw_params.bcast_id; sta_id = il_sta_id(sta); -- cgit v1.2.3 From 0f8b90f526f097a5c897f52b3595e9af55fc9b59 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:45 +0100 Subject: iwlegacy: get rid of *_devtype Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 3 --- drivers/net/wireless/iwlegacy/4965-mac.c | 4 ---- drivers/net/wireless/iwlegacy/common.c | 6 +++--- drivers/net/wireless/iwlegacy/common.h | 1 - 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index b11701f5874..15dcafbf29d 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3621,9 +3621,6 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); - il->ctx.ibss_devtype = RXON_DEV_TYPE_IBSS; - il->ctx.station_devtype = RXON_DEV_TYPE_ESS; - il->ctx.unused_devtype = RXON_DEV_TYPE_ESS; /* * Disabling hardware scan means that mac80211 will perform scans diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index af7886243fe..33725e14e14 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -6140,10 +6140,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.ac_to_queue = il4965_bss_ac_to_queue; il->ctx.exclusive_interface_modes = BIT(NL80211_IFTYPE_ADHOC); il->ctx.interface_modes = BIT(NL80211_IFTYPE_STATION); - il->ctx.ap_devtype = RXON_DEV_TYPE_AP; - il->ctx.ibss_devtype = RXON_DEV_TYPE_IBSS; - il->ctx.station_devtype = RXON_DEV_TYPE_ESS; - il->ctx.unused_devtype = RXON_DEV_TYPE_ESS; SET_IEEE80211_DEV(hw, &pdev->dev); diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index b7567a8063b..19ed86771a2 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -4002,17 +4002,17 @@ il_connection_init_rx_config(struct il_priv *il, struct il_rxon_context *ctx) memset(&il->staging, 0, sizeof(il->staging)); if (!ctx->vif) { - il->staging.dev_type = ctx->unused_devtype; + il->staging.dev_type = RXON_DEV_TYPE_ESS; } else switch (ctx->vif->type) { case NL80211_IFTYPE_STATION: - il->staging.dev_type = ctx->station_devtype; + il->staging.dev_type = RXON_DEV_TYPE_ESS; il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; break; case NL80211_IFTYPE_ADHOC: - il->staging.dev_type = ctx->ibss_devtype; + il->staging.dev_type = RXON_DEV_TYPE_IBSS; il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; il->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 66d0c1dd589..8eac5712415 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1171,7 +1171,6 @@ struct il_rxon_context { int ctxid; u32 interface_modes, exclusive_interface_modes; - u8 unused_devtype, ap_devtype, ibss_devtype, station_devtype; struct il_qos_info qos_data; -- cgit v1.2.3 From 6aa0c25435e6383d4a4af88fae8d128200dcd471 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:46 +0100 Subject: iwlegacy: get rid of ctxid Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 2 -- drivers/net/wireless/iwlegacy/4965-mac.c | 2 -- drivers/net/wireless/iwlegacy/common.c | 6 ------ drivers/net/wireless/iwlegacy/common.h | 4 +--- drivers/net/wireless/iwlegacy/debug.c | 1 - 5 files changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 15dcafbf29d..52cac0cd106 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3617,8 +3617,6 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->cmd_queue = IL39_CMD_QUEUE_NUM; - il->ctx.ctxid = 0; - il->ctx.interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 33725e14e14..3209970cf45 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -6132,8 +6132,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il = hw->priv; /* At this point both hw and il are allocated. */ - il->ctx.ctxid = 0; - il->ctx.always_active = true; il->ctx.is_active = true; il->ctx.ac_to_fifo = il4965_bss_ac_to_fifo; diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 19ed86771a2..7c7ea778d21 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -1951,7 +1951,6 @@ il_prep_station(struct il_priv *il, struct il_rxon_context *ctx, station->sta.mode = 0; station->sta.sta.sta_id = sta_id; station->sta.station_flags = ctx->station_flags; - station->ctxid = ctx->ctxid; if (sta) { struct il_station_priv_common *sta_priv; @@ -2191,9 +2190,6 @@ il_clear_ucode_stations(struct il_priv *il, struct il_rxon_context *ctx) spin_lock_irqsave(&il->sta_lock, flags_spin); for (i = 0; i < il->hw_params.max_stations; i++) { - if (ctx && ctx->ctxid != il->stations[i].ctxid) - continue; - if (il->stations[i].used & IL_STA_UCODE_ACTIVE) { D_INFO("Clearing ucode active for station %d\n", i); il->stations[i].used &= ~IL_STA_UCODE_ACTIVE; @@ -2234,8 +2230,6 @@ il_restore_stations(struct il_priv *il, struct il_rxon_context *ctx) D_ASSOC("Restoring all known stations ... start.\n"); spin_lock_irqsave(&il->sta_lock, flags_spin); for (i = 0; i < il->hw_params.max_stations; i++) { - if (ctx->ctxid != il->stations[i].ctxid) - continue; if ((il->stations[i].used & IL_STA_DRIVER_ACTIVE) && !(il->stations[i].used & IL_STA_UCODE_ACTIVE)) { D_ASSOC("Restoring sta %pM\n", diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 8eac5712415..8df2286ea05 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -735,7 +735,7 @@ struct il_qos_info { struct il_station_entry { struct il_addsta_cmd sta; struct il_tid_data tid[MAX_TID_COUNT]; - u8 used, ctxid; + u8 used; struct il_hw_key keyinfo; struct il_link_quality_cmd *lq; }; @@ -1168,8 +1168,6 @@ struct il_rxon_context { bool ht_need_multiple_chains; - int ctxid; - u32 interface_modes, exclusive_interface_modes; struct il_qos_info qos_data; diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c index 6e3841beb1d..f3cb45e53c0 100644 --- a/drivers/net/wireless/iwlegacy/debug.c +++ b/drivers/net/wireless/iwlegacy/debug.c @@ -649,7 +649,6 @@ il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count, char buf[256]; const size_t bufsz = sizeof(buf); - pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n", ctx->ctxid); for (i = 0; i < AC_NUM; i++) { pos += scnprintf(buf + pos, bufsz - pos, -- cgit v1.2.3 From d1e14e942430cd42df9913337aebbcaef53e4515 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:47 +0100 Subject: iwlegacy: get rid of mcast_queue Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/4965-mac.c | 17 ++++------------- drivers/net/wireless/iwlegacy/common.h | 3 --- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 3209970cf45..ecb7b542b96 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -1708,19 +1708,10 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) il4965_sta_modify_sleep_tx_count(il, sta_id, 1); } - /* - * Send this frame after DTIM -- there's a special queue - * reserved for this for contexts that support AP mode. - */ - if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { - txq_id = ctx->mcast_queue; - /* - * The microcode will clear the more data - * bit in the last frame it transmits. - */ - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); - } else - txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; + /* FIXME: remove me ? */ + WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM); + + txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; /* irqs already disabled/saved above when locking il->lock */ spin_lock(&il->sta_lock); diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 8df2286ea05..89922e0a70d 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1157,7 +1157,6 @@ struct il_rxon_context { const u8 *ac_to_fifo; const u8 *ac_to_queue; - u8 mcast_queue; /* * We could use the vif to indicate active, but we @@ -1166,8 +1165,6 @@ struct il_rxon_context { */ bool always_active, is_active; - bool ht_need_multiple_chains; - u32 interface_modes, exclusive_interface_modes; struct il_qos_info qos_data; -- cgit v1.2.3 From d735f9213d11e34e6ed074acea30b6743b3385e6 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:48 +0100 Subject: iwlegacy: move wep_keys out of context Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/4965-mac.c | 58 ++++++++++++++++++++------------ drivers/net/wireless/iwlegacy/common.h | 19 ++--------- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index ecb7b542b96..35d868c4ba9 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -2808,7 +2808,7 @@ static int il4965_static_wepkey_cmd(struct il_priv *il, struct il_rxon_context *ctx, bool send_if_empty) { - int i, not_empty = 0; + int i; u8 buff[sizeof(struct il_wep_cmd) + sizeof(struct il_wep_key) * WEP_KEYS_MAX]; struct il_wep_cmd *wep_cmd = (struct il_wep_cmd *)buff; @@ -2818,6 +2818,7 @@ il4965_static_wepkey_cmd(struct il_priv *il, struct il_rxon_context *ctx, .data = wep_cmd, .flags = CMD_SYNC, }; + bool not_empty = false; might_sleep(); @@ -2825,24 +2826,23 @@ il4965_static_wepkey_cmd(struct il_priv *il, struct il_rxon_context *ctx, cmd_size + (sizeof(struct il_wep_key) * WEP_KEYS_MAX)); for (i = 0; i < WEP_KEYS_MAX; i++) { + u8 key_size = il->_4965.wep_keys[i].key_size; + wep_cmd->key[i].key_idx = i; - if (ctx->wep_keys[i].key_size) { + if (key_size) { wep_cmd->key[i].key_offset = i; - not_empty = 1; - } else { + not_empty = true; + } else wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; - } - wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size; - memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key, - ctx->wep_keys[i].key_size); + wep_cmd->key[i].key_size = key_size; + memcpy(&wep_cmd->key[i].key[3], il->_4965.wep_keys[i].key, key_size); } wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; wep_cmd->num_keys = WEP_KEYS_MAX; cmd_size += sizeof(struct il_wep_key) * WEP_KEYS_MAX; - cmd.len = cmd_size; if (not_empty || send_if_empty) @@ -2864,19 +2864,20 @@ il4965_remove_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, struct ieee80211_key_conf *keyconf) { int ret; + int idx = keyconf->keyidx; lockdep_assert_held(&il->mutex); - D_WEP("Removing default WEP key: idx=%d\n", keyconf->keyidx); + D_WEP("Removing default WEP key: idx=%d\n", idx); - memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); + memset(&il->_4965.wep_keys[idx], 0, sizeof(struct il_wep_key)); if (il_is_rfkill(il)) { D_WEP("Not sending C_WEPKEY command due to RFKILL.\n"); /* but keys in device are clear anyway so return success */ return 0; } ret = il4965_static_wepkey_cmd(il, ctx, 1); - D_WEP("Remove default WEP key: idx=%d ret=%d\n", keyconf->keyidx, ret); + D_WEP("Remove default WEP key: idx=%d ret=%d\n", idx, ret); return ret; } @@ -2886,11 +2887,12 @@ il4965_set_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, struct ieee80211_key_conf *keyconf) { int ret; + int len = keyconf->keylen; + int idx = keyconf->keyidx; lockdep_assert_held(&il->mutex); - if (keyconf->keylen != WEP_KEY_LEN_128 && - keyconf->keylen != WEP_KEY_LEN_64) { + if (len != WEP_KEY_LEN_128 && len != WEP_KEY_LEN_64) { D_WEP("Bad WEP key length %d\n", keyconf->keylen); return -EINVAL; } @@ -2899,14 +2901,12 @@ il4965_set_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, keyconf->hw_key_idx = HW_KEY_DEFAULT; il->stations[IL_AP_ID].keyinfo.cipher = keyconf->cipher; - ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; - memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key, - keyconf->keylen); + il->_4965.wep_keys[idx].key_size = len; + memcpy(&il->_4965.wep_keys[idx].key, &keyconf->key, len); ret = il4965_static_wepkey_cmd(il, ctx, false); - D_WEP("Set default WEP key: len=%d idx=%d ret=%d\n", keyconf->keylen, - keyconf->keyidx, ret); + D_WEP("Set default WEP key: len=%d idx=%d ret=%d\n", len, idx, ret); return ret; } @@ -3106,7 +3106,7 @@ il4965_remove_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, lockdep_assert_held(&il->mutex); - ctx->key_mapping_keys--; + il->_4965.key_mapping_keys--; spin_lock_irqsave(&il->sta_lock, flags); key_flags = le16_to_cpu(il->stations[sta_id].sta.key.key_flags); @@ -3164,7 +3164,7 @@ il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, lockdep_assert_held(&il->mutex); - ctx->key_mapping_keys++; + il->_4965.key_mapping_keys++; keyconf->hw_key_idx = HW_KEY_DYNAMIC; switch (keyconf->cipher) { @@ -5067,6 +5067,20 @@ __il4965_down(struct il_priv *il) del_timer_sync(&il->watchdog); il_clear_ucode_stations(il, NULL); + + /* FIXME: race conditions ? */ + spin_lock_irq(&il->sta_lock); + /* + * Remove all key information that is not stored as part + * of station information since mac80211 may not have had + * a chance to remove all the keys. When device is + * reconfigured by mac80211 after an error all keys will + * be reconfigured. + */ + memset(il->_4965.wep_keys, 0, sizeof(il->_4965.wep_keys)); + il->_4965.key_mapping_keys = 0; + spin_unlock_irq(&il->sta_lock); + il_dealloc_bcast_stations(il); il_clear_driver_stations(il); @@ -5613,7 +5627,7 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) && !sta) { if (cmd == SET_KEY) - is_default_wep_key = !ctx->key_mapping_keys; + is_default_wep_key = !il->_4965.key_mapping_keys; else is_default_wep_key = (key->hw_key_idx == HW_KEY_DEFAULT); diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 89922e0a70d..811e768637c 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1169,9 +1169,6 @@ struct il_rxon_context { struct il_qos_info qos_data; - struct il_wep_key wep_keys[WEP_KEYS_MAX]; - u8 key_mapping_keys; - __le32 station_flags; struct { @@ -1417,6 +1414,9 @@ struct il_priv { u8 phy_calib_chain_noise_reset_cmd; u8 phy_calib_chain_noise_gain_cmd; + u8 key_mapping_keys; + struct il_wep_key wep_keys[WEP_KEYS_MAX]; + struct il_notif_stats stats; #ifdef CONFIG_IWLEGACY_DEBUGFS struct il_notif_stats accum_stats; @@ -2318,24 +2318,11 @@ static inline void il_clear_driver_stations(struct il_priv *il) { unsigned long flags; - struct il_rxon_context *ctx = &il->ctx; spin_lock_irqsave(&il->sta_lock, flags); memset(il->stations, 0, sizeof(il->stations)); il->num_stations = 0; - il->ucode_key_table = 0; - - /* - * Remove all key information that is not stored as part - * of station information since mac80211 may not have had - * a chance to remove all the keys. When device is - * reconfigured by mac80211 after an error all keys will - * be reconfigured. - */ - memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys)); - ctx->key_mapping_keys = 0; - spin_unlock_irqrestore(&il->sta_lock, flags); } -- cgit v1.2.3 From fd6415bcfb303e37052c72a3f44b7f81089d7336 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:49 +0100 Subject: iwlegacy: get rid of ctx->station_flags Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/common.c | 2 +- drivers/net/wireless/iwlegacy/common.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 7c7ea778d21..ac269856be1 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -1950,7 +1950,7 @@ il_prep_station(struct il_priv *il, struct il_rxon_context *ctx, memcpy(station->sta.sta.addr, addr, ETH_ALEN); station->sta.mode = 0; station->sta.sta.sta_id = sta_id; - station->sta.station_flags = ctx->station_flags; + station->sta.station_flags = 0; if (sta) { struct il_station_priv_common *sta_priv; diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 811e768637c..a872175f164 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1169,8 +1169,6 @@ struct il_rxon_context { struct il_qos_info qos_data; - __le32 station_flags; - struct { bool non_gf_sta_present; u8 protection; -- cgit v1.2.3 From 8c9c48d5a9ca5e1426372f8a747846bd0609dc08 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:50 +0100 Subject: iwlegacy: remove ctx interface_modes Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 6 ++---- drivers/net/wireless/iwlegacy/4965-mac.c | 6 ++---- drivers/net/wireless/iwlegacy/common.c | 29 ++++------------------------- drivers/net/wireless/iwlegacy/common.h | 2 -- 4 files changed, 8 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 52cac0cd106..7c81f5aaf7a 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3557,7 +3557,8 @@ il3945_setup_mac(struct il_priv *il) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SPECTRUM_MGMT; - hw->wiphy->interface_modes = il->ctx.interface_modes; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | @@ -3617,9 +3618,6 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->cmd_queue = IL39_CMD_QUEUE_NUM; - il->ctx.interface_modes = - BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); - /* * Disabling hardware scan means that mac80211 will perform scans * "the hard way", rather than using device's scan. diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 35d868c4ba9..1dd00147552 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5454,8 +5454,8 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) hw->sta_data_size = sizeof(struct il_station_priv); hw->vif_data_size = sizeof(struct il_vif_priv); - hw->wiphy->interface_modes |= il->ctx.interface_modes; - hw->wiphy->interface_modes |= il->ctx.exclusive_interface_modes; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS; @@ -6141,8 +6141,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.is_active = true; il->ctx.ac_to_fifo = il4965_bss_ac_to_fifo; il->ctx.ac_to_queue = il4965_bss_ac_to_queue; - il->ctx.exclusive_interface_modes = BIT(NL80211_IFTYPE_ADHOC); - il->ctx.interface_modes = BIT(NL80211_IFTYPE_STATION); SET_IEEE80211_DEV(hw, &pdev->dev); diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index ac269856be1..7f4c6bf4199 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -4566,7 +4566,6 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct il_priv *il = hw->priv; struct il_vif_priv *vif_priv = (void *)vif->drv_priv; int err; - u32 modes; D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); @@ -4578,15 +4577,7 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) goto out; } - /* check if busy context is exclusive */ - if (il->ctx.vif && - (il->ctx.exclusive_interface_modes & BIT(il->ctx.vif->type))) { - err = -EINVAL; - goto out; - } - - modes = il->ctx.interface_modes | il->ctx.exclusive_interface_modes; - if (!(modes & BIT(vif->type))) { + if (il->ctx.vif) { err = -EOPNOTSUPP; goto out; } @@ -4979,10 +4970,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct il_priv *il = hw->priv; struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); - u32 modes; int err; - newtype = ieee80211_iftype_p2p(newtype, newp2p); + if (newp2p) + return -EOPNOTSUPP; mutex_lock(&il->mutex); @@ -4995,22 +4986,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, goto out; } - modes = ctx->interface_modes | ctx->exclusive_interface_modes; - if (!(modes & BIT(newtype))) { - err = -EOPNOTSUPP; - goto out; - } - - if ((il->ctx.exclusive_interface_modes & BIT(il->ctx.vif->type)) || - (il->ctx.exclusive_interface_modes & BIT(newtype))) { - err = -EINVAL; - goto out; - } - /* success */ il_teardown_interface(il, vif, true); vif->type = newtype; - vif->p2p = newp2p; + vif->p2p = false; err = il_setup_interface(il, ctx); WARN_ON(err); /* diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index a872175f164..eddf22d4f1b 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1165,8 +1165,6 @@ struct il_rxon_context { */ bool always_active, is_active; - u32 interface_modes, exclusive_interface_modes; - struct il_qos_info qos_data; struct { -- cgit v1.2.3 From 8d44f2bd7554734913f1256e4f45c35454167161 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:51 +0100 Subject: iwlegacy: move qos_data out of ctx structure Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/common.c | 24 ++++++++++++------------ drivers/net/wireless/iwlegacy/common.h | 4 ++-- drivers/net/wireless/iwlegacy/debug.c | 9 ++++----- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 7f4c6bf4199..c93fa1b85da 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -4496,15 +4496,15 @@ il_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, spin_lock_irqsave(&il->lock, flags); - il->ctx.qos_data.def_qos_parm.ac[q].cw_min = + il->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); - il->ctx.qos_data.def_qos_parm.ac[q].cw_max = + il->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); - il->ctx.qos_data.def_qos_parm.ac[q].aifsn = params->aifs; - il->ctx.qos_data.def_qos_parm.ac[q].edca_txop = + il->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; + il->qos_data.def_qos_parm.ac[q].edca_txop = cpu_to_le16((params->txop * 32)); - il->ctx.qos_data.def_qos_parm.ac[q].reserved1 = 0; + il->qos_data.def_qos_parm.ac[q].reserved1 = 0; spin_unlock_irqrestore(&il->lock, flags); @@ -5230,20 +5230,20 @@ il_update_qos(struct il_priv *il, struct il_rxon_context *ctx) if (!ctx->is_active) return; - ctx->qos_data.def_qos_parm.qos_flags = 0; + il->qos_data.def_qos_parm.qos_flags = 0; - if (ctx->qos_data.qos_active) - ctx->qos_data.def_qos_parm.qos_flags |= + if (il->qos_data.qos_active) + il->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_UPDATE_EDCA_MSK; if (ctx->ht.enabled) - ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; + il->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; D_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", - ctx->qos_data.qos_active, ctx->qos_data.def_qos_parm.qos_flags); + il->qos_data.qos_active, il->qos_data.def_qos_parm.qos_flags); il_send_cmd_pdu_async(il, C_QOS_PARAM, sizeof(struct il_qosparam_cmd), - &ctx->qos_data.def_qos_parm, NULL); + &il->qos_data.def_qos_parm, NULL); } /** @@ -5596,7 +5596,7 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, unsigned long flags; spin_lock_irqsave(&il->lock, flags); - ctx->qos_data.qos_active = bss_conf->qos; + il->qos_data.qos_active = bss_conf->qos; il_update_qos(il, ctx); spin_unlock_irqrestore(&il->lock, flags); } diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index eddf22d4f1b..18375cb7904 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1165,8 +1165,6 @@ struct il_rxon_context { */ bool always_active, is_active; - struct il_qos_info qos_data; - struct { bool non_gf_sta_present; u8 protection; @@ -1278,6 +1276,8 @@ struct il_priv { struct il_rxon_context ctx; + struct il_qos_info qos_data; + /* * We declare this const so it can only be * changed via explicit cast within the diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c index f3cb45e53c0..3a9609a8874 100644 --- a/drivers/net/wireless/iwlegacy/debug.c +++ b/drivers/net/wireless/iwlegacy/debug.c @@ -644,7 +644,6 @@ il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct il_priv *il = file->private_data; - struct il_rxon_context *ctx = &il->ctx; int pos = 0, i; char buf[256]; const size_t bufsz = sizeof(buf); @@ -656,10 +655,10 @@ il_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count, pos += scnprintf(buf + pos, bufsz - pos, "AC[%d]\t%u\t%u\t%u\t%u\n", i, - ctx->qos_data.def_qos_parm.ac[i].cw_min, - ctx->qos_data.def_qos_parm.ac[i].cw_max, - ctx->qos_data.def_qos_parm.ac[i].aifsn, - ctx->qos_data.def_qos_parm.ac[i].edca_txop); + il->qos_data.def_qos_parm.ac[i].cw_min, + il->qos_data.def_qos_parm.ac[i].cw_max, + il->qos_data.def_qos_parm.ac[i].aifsn, + il->qos_data.def_qos_parm.ac[i].edca_txop); } return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -- cgit v1.2.3 From 1c03c4620edc551b5bbcc87c7aca02b482d8bc51 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:52 +0100 Subject: iwlegacy: move ht out of ctx structure Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/4965-mac.c | 18 ++++++------ drivers/net/wireless/iwlegacy/4965-rs.c | 13 ++++----- drivers/net/wireless/iwlegacy/common.c | 49 ++++++++++++++++---------------- drivers/net/wireless/iwlegacy/common.h | 15 +++++----- 4 files changed, 46 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 1dd00147552..94984c850e8 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5793,23 +5793,23 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, il->current_ht_config.smps = conf->smps_mode; /* Configure HT40 channels */ - ctx->ht.enabled = conf_is_ht(conf); - if (ctx->ht.enabled) { + il->ht.enabled = conf_is_ht(conf); + if (il->ht.enabled) { if (conf_is_ht40_minus(conf)) { - ctx->ht.extension_chan_offset = + il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ctx->ht.is_40mhz = true; + il->ht.is_40mhz = true; } else if (conf_is_ht40_plus(conf)) { - ctx->ht.extension_chan_offset = + il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ctx->ht.is_40mhz = true; + il->ht.is_40mhz = true; } else { - ctx->ht.extension_chan_offset = + il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; - ctx->ht.is_40mhz = false; + il->ht.is_40mhz = false; } } else - ctx->ht.is_40mhz = false; + il->ht.is_40mhz = false; 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 467d0cb14ec..ad186d9a598 100644 --- a/drivers/net/wireless/iwlegacy/4965-rs.c +++ b/drivers/net/wireless/iwlegacy/4965-rs.c @@ -641,13 +641,10 @@ il4965_rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, * there are no non-GF stations present in the BSS. */ static bool -il4965_rs_use_green(struct ieee80211_sta *sta) +il4965_rs_use_green(struct il_priv *il, struct ieee80211_sta *sta) { - struct il_station_priv *sta_priv = (void *)sta->drv_priv; - struct il_rxon_context *ctx = sta_priv->common.ctx; - return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && - !(ctx->ht.non_gf_sta_present); + !il->ht.non_gf_sta_present; } /** @@ -1815,7 +1812,7 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb, if (is_legacy(tbl->lq_type)) lq_sta->is_green = 0; else - lq_sta->is_green = il4965_rs_use_green(sta); + lq_sta->is_green = il4965_rs_use_green(il, sta); is_green = lq_sta->is_green; /* current tx rate */ @@ -2166,7 +2163,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf, int rate_idx; int i; u32 rate; - u8 use_green = il4965_rs_use_green(sta); + u8 use_green = il4965_rs_use_green(il, sta); u8 active_tbl = 0; u8 valid_tx_ant; struct il_station_priv *sta_priv; @@ -2341,7 +2338,7 @@ il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id) lq_sta->is_dup = 0; lq_sta->max_rate_idx = -1; lq_sta->missed_rate_counter = IL_MISSED_RATE_MAX; - lq_sta->is_green = il4965_rs_use_green(sta); + lq_sta->is_green = il4965_rs_use_green(il, sta); lq_sta->active_legacy_rate = il->active_rate & ~(0x1000); lq_sta->band = il->band; /* diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index c93fa1b85da..db2e8bb11fa 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -2352,7 +2352,7 @@ il_is_lq_table_valid(struct il_priv *il, struct il_rxon_context *ctx, { int i; - if (ctx->ht.enabled) + if (il->ht.enabled) return true; D_INFO("Channel %u is not an HT channel\n", il->active.channel); @@ -3559,7 +3559,7 @@ bool il_is_ht40_tx_allowed(struct il_priv *il, struct il_rxon_context *ctx, struct ieee80211_sta_ht_cap *ht_cap) { - if (!ctx->ht.enabled || !ctx->ht.is_40mhz) + if (!il->ht.enabled || !il->ht.is_40mhz) return false; /* @@ -3576,7 +3576,7 @@ il_is_ht40_tx_allowed(struct il_priv *il, struct il_rxon_context *ctx, return il_is_channel_extension(il, il->band, le16_to_cpu(il->staging.channel), - ctx->ht.extension_chan_offset); + il->ht.extension_chan_offset); } EXPORT_SYMBOL(il_is_ht40_tx_allowed); @@ -3832,7 +3832,7 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, { struct il_rxon_cmd *rxon = &il->staging; - if (!ctx->ht.enabled) { + if (!il->ht.enabled) { rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | RXON_FLG_HT40_PROT_MSK @@ -3841,7 +3841,7 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, } rxon->flags |= - cpu_to_le32(ctx->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS); + cpu_to_le32(il->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS); /* Set up channel bandwidth: * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ @@ -3850,10 +3850,10 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, ~(RXON_FLG_CHANNEL_MODE_MSK | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); if (il_is_ht40_tx_allowed(il, ctx, NULL)) { /* pure ht40 */ - if (ctx->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { + if (il->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; /* Note: control channel is opposite of extension channel */ - switch (ctx->ht.extension_chan_offset) { + switch (il->ht.extension_chan_offset) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; @@ -3864,7 +3864,7 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, } } else { /* Note: control channel is opposite of extension channel */ - switch (ctx->ht.extension_chan_offset) { + switch (il->ht.extension_chan_offset) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); @@ -3890,7 +3890,7 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, D_ASSOC("rxon flags 0x%X operation mode :0x%X " "extension channel offset 0x%x\n", le32_to_cpu(rxon->flags), - ctx->ht.protection, ctx->ht.extension_chan_offset); + il->ht.protection, il->ht.extension_chan_offset); } void @@ -5236,7 +5236,7 @@ il_update_qos(struct il_priv *il, struct il_rxon_context *ctx) il->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_UPDATE_EDCA_MSK; - if (ctx->ht.enabled) + if (il->ht.enabled) il->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; D_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", @@ -5319,32 +5319,32 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) spin_lock_irqsave(&il->lock, flags); /* Configure HT40 channels */ - if (ctx->ht.enabled != conf_is_ht(conf)) { - ctx->ht.enabled = conf_is_ht(conf); + if (il->ht.enabled != conf_is_ht(conf)) { + il->ht.enabled = conf_is_ht(conf); ht_changed = true; } - if (ctx->ht.enabled) { + if (il->ht.enabled) { if (conf_is_ht40_minus(conf)) { - ctx->ht.extension_chan_offset = + il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ctx->ht.is_40mhz = true; + il->ht.is_40mhz = true; } else if (conf_is_ht40_plus(conf)) { - ctx->ht.extension_chan_offset = + il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ctx->ht.is_40mhz = true; + il->ht.is_40mhz = true; } else { - ctx->ht.extension_chan_offset = + il->ht.extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; - ctx->ht.is_40mhz = false; + il->ht.is_40mhz = false; } } else - ctx->ht.is_40mhz = false; + il->ht.is_40mhz = false; /* * Default to no protection. Protection mode will * later be set from BSS config in il_ht_conf */ - ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; + il->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; /* if we are switching from ht to 2.4 clear flags * from any ht related info since 2.4 does not @@ -5460,16 +5460,15 @@ il_ht_conf(struct il_priv *il, struct ieee80211_vif *vif) struct il_ht_config *ht_conf = &il->current_ht_config; struct ieee80211_sta *sta; struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); D_ASSOC("enter:\n"); - if (!ctx->ht.enabled) + if (!il->ht.enabled) return; - ctx->ht.protection = + il->ht.protection = bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; - ctx->ht.non_gf_sta_present = + il->ht.non_gf_sta_present = !!(bss_conf-> ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 18375cb7904..df4d1602289 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1164,13 +1164,6 @@ struct il_rxon_context { * we already removed the vif for type setting. */ bool always_active, is_active; - - struct { - bool non_gf_sta_present; - u8 protection; - bool enabled, is_40mhz; - u8 extension_chan_offset; - } ht; }; struct il_power_mgr { @@ -1278,6 +1271,14 @@ struct il_priv { struct il_qos_info qos_data; + struct { + bool enabled; + bool is_40mhz; + bool non_gf_sta_present; + u8 protection; + u8 extension_chan_offset; + } ht; + /* * We declare this const so it can only be * changed via explicit cast within the -- cgit v1.2.3 From b75b3a70a623e6c39512e3ed9a0fd76cea19c085 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:53 +0100 Subject: iwlegacy: get rid of ctx->ac_to_fifo Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/4965-mac.c | 17 ++++++++--------- drivers/net/wireless/iwlegacy/common.h | 1 - 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 94984c850e8..731bb8c10b4 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -1458,8 +1458,15 @@ il4965_get_ac_from_tid(u16 tid) static inline int il4965_get_fifo_from_tid(struct il_rxon_context *ctx, u16 tid) { + const u8 ac_to_fifo[] = { + IL_TX_FIFO_VO, + IL_TX_FIFO_VI, + IL_TX_FIFO_BE, + IL_TX_FIFO_BK, + }; + if (likely(tid < ARRAY_SIZE(tid_to_ac))) - return ctx->ac_to_fifo[tid_to_ac[tid]]; + return ac_to_fifo[tid_to_ac[tid]]; /* no support for TIDs 8-15 yet */ return -EINVAL; @@ -6104,13 +6111,6 @@ il4965_set_hw_params(struct il_priv *il) return il->cfg->ops->lib->set_hw_params(il); } -static const u8 il4965_bss_ac_to_fifo[] = { - IL_TX_FIFO_VO, - IL_TX_FIFO_VI, - IL_TX_FIFO_BE, - IL_TX_FIFO_BK, -}; - static const u8 il4965_bss_ac_to_queue[] = { 0, 1, 2, 3, }; @@ -6139,7 +6139,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.always_active = true; il->ctx.is_active = true; - il->ctx.ac_to_fifo = il4965_bss_ac_to_fifo; il->ctx.ac_to_queue = il4965_bss_ac_to_queue; SET_IEEE80211_DEV(hw, &pdev->dev); diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index df4d1602289..e0e4d013660 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1155,7 +1155,6 @@ struct il_force_reset { struct il_rxon_context { struct ieee80211_vif *vif; - const u8 *ac_to_fifo; const u8 *ac_to_queue; /* -- cgit v1.2.3 From eb123af3d1e038c486fc8fcf19518133883792d5 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:54 +0100 Subject: iwlegacy: get rid of ctx->ac_to_queue Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/4965-mac.c | 8 ++------ drivers/net/wireless/iwlegacy/common.h | 2 -- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 731bb8c10b4..1c3c85ec111 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -1718,7 +1718,8 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) /* FIXME: remove me ? */ WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM); - txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; + /* Access category (AC) is also the queue number */ + txq_id = skb_get_queue_mapping(skb); /* irqs already disabled/saved above when locking il->lock */ spin_lock(&il->sta_lock); @@ -6111,10 +6112,6 @@ il4965_set_hw_params(struct il_priv *il) return il->cfg->ops->lib->set_hw_params(il); } -static const u8 il4965_bss_ac_to_queue[] = { - 0, 1, 2, 3, -}; - static int il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -6139,7 +6136,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il->ctx.always_active = true; il->ctx.is_active = true; - il->ctx.ac_to_queue = il4965_bss_ac_to_queue; SET_IEEE80211_DEV(hw, &pdev->dev); diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index e0e4d013660..e085131a457 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1155,8 +1155,6 @@ struct il_force_reset { struct il_rxon_context { struct ieee80211_vif *vif; - const u8 *ac_to_queue; - /* * We could use the vif to indicate active, but we * also need it to be active during disabling when -- cgit v1.2.3 From dee9a09eb34a272494a315fe0c19e49b6375a000 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:55 +0100 Subject: iwlegacy: get rid of ctx->is_active Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/4965-mac.c | 3 --- drivers/net/wireless/iwlegacy/4965.c | 3 --- drivers/net/wireless/iwlegacy/common.c | 21 +++------------------ drivers/net/wireless/iwlegacy/common.h | 7 ------- 4 files changed, 3 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 1c3c85ec111..1a54c1a812d 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -6134,9 +6134,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) il = hw->priv; /* At this point both hw and il are allocated. */ - il->ctx.always_active = true; - il->ctx.is_active = true; - SET_IEEE80211_DEV(hw, &pdev->dev); D_INFO("*** LOAD DRIVER ***\n"); diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index 8d0fd60bc49..7b0192aff83 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c @@ -1419,9 +1419,6 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) if (!il_is_alive(il)) return -EBUSY; - if (!ctx->is_active) - return 0; - /* always get timestamp with Rx frame */ il->staging.flags |= RXON_FLG_TSF2HOST_MSK; diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index db2e8bb11fa..13bd3a8c21b 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -4537,7 +4537,6 @@ static int il_setup_interface(struct il_priv *il, struct il_rxon_context *ctx) { struct ieee80211_vif *vif = ctx->vif; - int err; lockdep_assert_held(&il->mutex); @@ -4548,16 +4547,7 @@ il_setup_interface(struct il_priv *il, struct il_rxon_context *ctx) */ il->iw_mode = vif->type; - ctx->is_active = true; - - err = il_set_mode(il, ctx); - if (err) { - if (!ctx->always_active) - ctx->is_active = false; - return err; - } - - return 0; + return il_set_mode(il, ctx); } int @@ -4612,11 +4602,9 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, il_force_scan_end(il); } - if (!mode_change) { + if (!mode_change) il_set_mode(il, ctx); - if (!ctx->always_active) - ctx->is_active = false; - } + } void @@ -5227,9 +5215,6 @@ il_update_qos(struct il_priv *il, struct il_rxon_context *ctx) if (test_bit(S_EXIT_PENDING, &il->status)) return; - if (!ctx->is_active) - return; - il->qos_data.def_qos_parm.qos_flags = 0; if (il->qos_data.qos_active) diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index e085131a457..51c1eecf751 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1154,13 +1154,6 @@ struct il_force_reset { struct il_rxon_context { struct ieee80211_vif *vif; - - /* - * We could use the vif to indicate active, but we - * also need it to be active during disabling when - * we already removed the vif for type setting. - */ - bool always_active, is_active; }; struct il_power_mgr { -- cgit v1.2.3 From 20c47eba7001680e62878c5b20e487a8b0b873ad Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:56 +0100 Subject: iwlegacy: remove il_setup_interface() Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/common.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 13bd3a8c21b..ea2fa97fa36 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -4533,23 +4533,6 @@ il_set_mode(struct il_priv *il, struct il_rxon_context *ctx) return il_commit_rxon(il, ctx); } -static int -il_setup_interface(struct il_priv *il, struct il_rxon_context *ctx) -{ - struct ieee80211_vif *vif = ctx->vif; - - lockdep_assert_held(&il->mutex); - - /* - * This variable will be correct only when there's just - * a single context, but all code using it is for hardware - * that supports only one context. - */ - il->iw_mode = vif->type; - - return il_set_mode(il, ctx); -} - int il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -4574,8 +4557,9 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) vif_priv->ctx = &il->ctx; il->ctx.vif = vif; + il->iw_mode = vif->type; - err = il_setup_interface(il, &il->ctx); + err = il_set_mode(il, &il->ctx); if (err) { il->ctx.vif = NULL; il->iw_mode = NL80211_IFTYPE_STATION; @@ -4978,7 +4962,7 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, il_teardown_interface(il, vif, true); vif->type = newtype; vif->p2p = false; - err = il_setup_interface(il, ctx); + err = il_set_mode(il, ctx); WARN_ON(err); /* * We've switched internally, but submitting to the -- cgit v1.2.3 From 83007196037cc2d0bffd9f7afbe56d675779a6cb Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:57 +0100 Subject: iwlegacy: get rid of ctx structure Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 67 +++++------ drivers/net/wireless/iwlegacy/3945-rs.c | 3 +- drivers/net/wireless/iwlegacy/3945.c | 23 ++-- drivers/net/wireless/iwlegacy/3945.h | 2 +- drivers/net/wireless/iwlegacy/4965-mac.c | 150 ++++++++++------------- drivers/net/wireless/iwlegacy/4965-rs.c | 35 ++---- drivers/net/wireless/iwlegacy/4965.c | 62 +++++----- drivers/net/wireless/iwlegacy/4965.h | 19 ++- drivers/net/wireless/iwlegacy/common.c | 199 ++++++++++++------------------- drivers/net/wireless/iwlegacy/common.h | 79 +++++------- 10 files changed, 261 insertions(+), 378 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 7c81f5aaf7a..b2e04c591c6 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -341,7 +341,7 @@ il3945_send_beacon_cmd(struct il_priv *il) return -ENOMEM; } - rate = il_get_lowest_plcp(il, &il->ctx); + rate = il_get_lowest_plcp(il); frame_size = il3945_hw_get_beacon_cmd(il, frame, rate); @@ -512,7 +512,7 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); /* Find idx into station table for destination station */ - sta_id = il_sta_id_or_broadcast(il, &il->ctx, info->control.sta); + sta_id = il_sta_id_or_broadcast(il, info->control.sta); if (sta_id == IL_INVALID_STATION) { D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1); goto drop; @@ -541,7 +541,6 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) /* Set up driver data for this TFD */ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct il_tx_info)); txq->txb[q->write_ptr].skb = skb; - txq->txb[q->write_ptr].ctx = &il->ctx; /* Init first empty entry in queue's array of Tx/cmd buffers */ out_cmd = txq->cmd[idx]; @@ -2208,7 +2207,7 @@ il3945_alive_start(struct il_priv *il) active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ - il_connection_init_rx_config(il, &il->ctx); + il_connection_init_rx_config(il); } /* Configure Bluetooth device coexistence support */ @@ -2217,7 +2216,7 @@ il3945_alive_start(struct il_priv *il) set_bit(S_READY, &il->status); /* Configure the adapter for unassociated operation */ - il3945_commit_rxon(il, &il->ctx); + il3945_commit_rxon(il); il3945_reg_txpower_periodic(il); @@ -2249,7 +2248,7 @@ __il3945_down(struct il_priv *il) del_timer_sync(&il->watchdog); /* Station information will now be cleared in device */ - il_clear_ucode_stations(il, NULL); + il_clear_ucode_stations(il); il_dealloc_bcast_stations(il); il_clear_driver_stations(il); @@ -2335,12 +2334,11 @@ il3945_down(struct il_priv *il) static int il3945_alloc_bcast_station(struct il_priv *il) { - struct il_rxon_context *ctx = &il->ctx; unsigned long flags; u8 sta_id; spin_lock_irqsave(&il->sta_lock, flags); - sta_id = il_prep_station(il, ctx, il_bcast_addr, false, NULL); + sta_id = il_prep_station(il, il_bcast_addr, false, NULL); if (sta_id == IL_INVALID_STATION) { IL_ERR("Unable to prepare broadcast station\n"); spin_unlock_irqrestore(&il->sta_lock, flags); @@ -2660,14 +2658,12 @@ il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif) void il3945_post_scan(struct il_priv *il) { - struct il_rxon_context *ctx = &il->ctx; - /* * Since setting the RXON may have been deferred while * performing the scan, fire one off if needed */ if (memcmp(&il->staging, &il->active, sizeof(il->staging))) - il3945_commit_rxon(il, ctx); + il3945_commit_rxon(il); } static void @@ -2680,7 +2676,8 @@ il3945_bg_restart(struct work_struct *data) if (test_and_clear_bit(S_FW_ERROR, &il->status)) { mutex_lock(&il->mutex); - il->ctx.vif = NULL; + /* FIXME: vif can be dereferenced */ + il->vif = NULL; il->is_open = 0; mutex_unlock(&il->mutex); il3945_down(il); @@ -2718,12 +2715,11 @@ il3945_post_associate(struct il_priv *il) { int rc = 0; struct ieee80211_conf *conf = NULL; - struct il_rxon_context *ctx = &il->ctx; - if (!ctx->vif || !il->is_open) + if (!il->vif || !il->is_open) return; - D_ASSOC("Associated as %d to: %pM\n", ctx->vif->bss_conf.aid, + D_ASSOC("Associated as %d to: %pM\n", il->vif->bss_conf.aid, il->active.bssid_addr); if (test_bit(S_EXIT_PENDING, &il->status)) @@ -2734,34 +2730,34 @@ il3945_post_associate(struct il_priv *il) conf = &il->hw->conf; il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - il3945_commit_rxon(il, ctx); + il3945_commit_rxon(il); - rc = il_send_rxon_timing(il, ctx); + rc = il_send_rxon_timing(il); if (rc) IL_WARN("C_RXON_TIMING failed - " "Attempting to continue.\n"); il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - il->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid); + il->staging.assoc_id = cpu_to_le16(il->vif->bss_conf.aid); - D_ASSOC("assoc id %d beacon interval %d\n", ctx->vif->bss_conf.aid, - ctx->vif->bss_conf.beacon_int); + D_ASSOC("assoc id %d beacon interval %d\n", il->vif->bss_conf.aid, + il->vif->bss_conf.beacon_int); - if (ctx->vif->bss_conf.use_short_preamble) + if (il->vif->bss_conf.use_short_preamble) il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; if (il->staging.flags & RXON_FLG_BAND_24G_MSK) { - if (ctx->vif->bss_conf.use_short_slot) + if (il->vif->bss_conf.use_short_slot) il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; else il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } - il3945_commit_rxon(il, ctx); + il3945_commit_rxon(il); - switch (ctx->vif->type) { + switch (il->vif->type) { case NL80211_IFTYPE_STATION: il3945_rate_scale_init(il->hw, IL_AP_ID); break; @@ -2770,7 +2766,7 @@ il3945_post_associate(struct il_priv *il) break; default: IL_ERR("%s Should not be called in %d mode\n", __func__, - ctx->vif->type); + il->vif->type); break; } } @@ -2887,8 +2883,7 @@ il3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) void il3945_config_ap(struct il_priv *il) { - struct il_rxon_context *ctx = &il->ctx; - struct ieee80211_vif *vif = ctx->vif; + struct ieee80211_vif *vif = il->vif; int rc = 0; if (test_bit(S_EXIT_PENDING, &il->status)) @@ -2899,10 +2894,10 @@ il3945_config_ap(struct il_priv *il) /* RXON - unassoc (to set timing command) */ il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - il3945_commit_rxon(il, ctx); + il3945_commit_rxon(il); /* RXON Timing */ - rc = il_send_rxon_timing(il, ctx); + rc = il_send_rxon_timing(il); if (rc) IL_WARN("C_RXON_TIMING failed - " "Attempting to continue.\n"); @@ -2922,7 +2917,7 @@ il3945_config_ap(struct il_priv *il) } /* restore RXON assoc */ il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - il3945_commit_rxon(il, ctx); + il3945_commit_rxon(il); } il3945_send_beacon_cmd(il); } @@ -2955,7 +2950,7 @@ il3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static_key = !il_is_associated(il); if (!static_key) { - sta_id = il_sta_id_or_broadcast(il, &il->ctx, sta); + sta_id = il_sta_id_or_broadcast(il, sta); if (sta_id == IL_INVALID_STATION) return -EINVAL; } @@ -3003,8 +2998,7 @@ il3945_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, D_INFO("proceeding to add station %pM\n", sta->addr); sta_priv->common.sta_id = IL_INVALID_STATION; - ret = - il_add_station_common(il, &il->ctx, sta->addr, is_ap, sta, &sta_id); + ret = il_add_station_common(il, sta->addr, is_ap, sta, &sta_id); if (ret) { IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret); /* Should we return success if return code is EEXIST ? */ @@ -3184,7 +3178,7 @@ il3945_store_flags(struct device *d, struct device_attribute *attr, else { D_INFO("Committing rxon.flags = 0x%04X\n", flags); il->staging.flags = cpu_to_le32(flags); - il3945_commit_rxon(il, &il->ctx); + il3945_commit_rxon(il); } } mutex_unlock(&il->mutex); @@ -3220,7 +3214,7 @@ il3945_store_filter_flags(struct device *d, struct device_attribute *attr, D_INFO("Committing rxon.filter_flags = " "0x%04X\n", filter_flags); il->staging.filter_flags = cpu_to_le32(filter_flags); - il3945_commit_rxon(il, &il->ctx); + il3945_commit_rxon(il); } } mutex_unlock(&il->mutex); @@ -3750,8 +3744,7 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_release_irq; } - il_set_rxon_channel(il, &il->bands[IEEE80211_BAND_2GHZ].channels[5], - &il->ctx); + il_set_rxon_channel(il, &il->bands[IEEE80211_BAND_2GHZ].channels[5]); il3945_setup_deferred_work(il); il3945_setup_handlers(il); il_power_initialize(il); diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c index 6a782b5c0c5..70bee1a4d87 100644 --- a/drivers/net/wireless/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/iwlegacy/3945-rs.c @@ -927,8 +927,7 @@ il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) rcu_read_lock(); - sta = - ieee80211_find_sta(il->ctx.vif, il->stations[sta_id].sta.sta.addr); + sta = ieee80211_find_sta(il->vif, il->stations[sta_id].sta.sta.addr); if (!sta) { D_RATE("Unable to find station to initialize rate scaling.\n"); rcu_read_unlock(); diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index 3024645a6be..1e617c9fc3c 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -1662,7 +1662,7 @@ il3945_hw_reg_set_txpower(struct il_priv *il, s8 power) } static int -il3945_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) +il3945_send_rxon_assoc(struct il_priv *il) { int rc = 0; struct il_rx_pkt *pkt; @@ -1714,7 +1714,7 @@ il3945_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) * a HW tune is required based on the RXON structure changes. */ int -il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) +il3945_commit_rxon(struct il_priv *il) { /* cast away the const for active_rxon in this function */ struct il3945_rxon_cmd *active_rxon = (void *)&il->active; @@ -1735,7 +1735,7 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) staging_rxon->flags &= ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); staging_rxon->flags |= il3945_get_antenna_flags(il); - rc = il_check_rxon_cmd(il, ctx); + rc = il_check_rxon_cmd(il); if (rc) { IL_ERR("Invalid RXON configuration. Not committing.\n"); return -EINVAL; @@ -1744,8 +1744,8 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) /* If we don't need to send a full RXON, we can use * il3945_rxon_assoc_cmd which is used to reconfigure filter * and other flags for the current radio configuration. */ - if (!il_full_rxon_required(il, &il->ctx)) { - rc = il_send_rxon_assoc(il, &il->ctx); + if (!il_full_rxon_required(il)) { + rc = il_send_rxon_assoc(il); if (rc) { IL_ERR("Error setting RXON_ASSOC " "configuration (%d).\n", rc); @@ -1786,8 +1786,8 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) "configuration (%d).\n", rc); return rc; } - il_clear_ucode_stations(il, &il->ctx); - il_restore_stations(il, &il->ctx); + il_clear_ucode_stations(il); + il_restore_stations(il); } D_INFO("Sending RXON\n" "* with%s RXON_FILTER_ASSOC_MSK\n" @@ -1801,7 +1801,7 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) staging_rxon->reserved4 = 0; staging_rxon->reserved5 = 0; - il_set_rxon_hwcrypto(il, ctx, !il3945_mod_params.sw_crypto); + il_set_rxon_hwcrypto(il, !il3945_mod_params.sw_crypto); /* Apply the new configuration */ rc = il_send_cmd_pdu(il, C_RXON, sizeof(struct il3945_rxon_cmd), @@ -1814,8 +1814,8 @@ il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); if (!new_assoc) { - il_clear_ucode_stations(il, &il->ctx); - il_restore_stations(il, &il->ctx); + il_clear_ucode_stations(il); + il_restore_stations(il); } /* If we issue a new RXON command which required a tune then we must @@ -2258,7 +2258,6 @@ il3945_build_addsta_hcmd(const struct il_addsta_cmd *cmd, u8 * data) static int il3945_add_bssid_station(struct il_priv *il, const u8 * addr, u8 * sta_id_r) { - struct il_rxon_context *ctx = &il->ctx; int ret; u8 sta_id; unsigned long flags; @@ -2266,7 +2265,7 @@ il3945_add_bssid_station(struct il_priv *il, const u8 * addr, u8 * sta_id_r) if (sta_id_r) *sta_id_r = IL_INVALID_STATION; - ret = il_add_station_common(il, ctx, addr, 0, NULL, &sta_id); + ret = il_add_station_common(il, addr, 0, NULL, &sta_id); if (ret) { IL_ERR("Unable to add station %pM\n", addr); return ret; diff --git a/drivers/net/wireless/iwlegacy/3945.h b/drivers/net/wireless/iwlegacy/3945.h index 9f42f79f877..8bee127d413 100644 --- a/drivers/net/wireless/iwlegacy/3945.h +++ b/drivers/net/wireless/iwlegacy/3945.h @@ -249,7 +249,7 @@ extern int il4965_get_temperature(const struct il_priv *il); extern void il3945_post_associate(struct il_priv *il); extern void il3945_config_ap(struct il_priv *il); -extern int il3945_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx); +extern int il3945_commit_rxon(struct il_priv *il); /** * il3945_hw_find_station - Find station id for a given BSSID diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 1a54c1a812d..4be53cc9198 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -843,7 +843,6 @@ il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif) .flags = CMD_SIZE_HUGE, }; struct il_scan_cmd *scan; - struct il_rxon_context *ctx = &il->ctx; u32 rate_flags = 0; u16 cmd_len; u16 rx_chain = 0; @@ -859,8 +858,6 @@ il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif) lockdep_assert_held(&il->mutex); - ctx = il_rxon_ctx_from_vif(vif); - if (!il->scan_cmd) { il->scan_cmd = kmalloc(sizeof(struct il_scan_cmd) + IL_MAX_SCAN_SIZE, @@ -1033,8 +1030,7 @@ il4965_manage_ibss_station(struct il_priv *il, struct ieee80211_vif *vif, struct il_vif_priv *vif_priv = (void *)vif->drv_priv; if (add) - return il4965_add_bssid_station(il, vif_priv->ctx, - vif->bss_conf.bssid, + return il4965_add_bssid_station(il, vif->bss_conf.bssid, &vif_priv->ibss_bssid_sta_id); return il_remove_station(il, vif_priv->ibss_bssid_sta_id, vif->bss_conf.bssid); @@ -1127,7 +1123,7 @@ il4965_count_chain_bitmap(u32 chain_bitmap) * This should not be used for scan command ... it puts data in wrong place. */ void -il4965_set_rxon_chain(struct il_priv *il, struct il_rxon_context *ctx) +il4965_set_rxon_chain(struct il_priv *il) { bool is_single = il4965_is_single_rx_stream(il); bool is_cam = !test_bit(S_POWER_PMI, &il->status); @@ -1456,7 +1452,7 @@ il4965_get_ac_from_tid(u16 tid) } static inline int -il4965_get_fifo_from_tid(struct il_rxon_context *ctx, u16 tid) +il4965_get_fifo_from_tid(u16 tid) { const u8 ac_to_fifo[] = { IL_TX_FIFO_VO, @@ -1645,7 +1641,6 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) struct il_device_cmd *out_cmd; struct il_cmd_meta *out_meta; struct il_tx_cmd *tx_cmd; - struct il_rxon_context *ctx = &il->ctx; int txq_id; dma_addr_t phys_addr; dma_addr_t txcmd_phys; @@ -1661,9 +1656,6 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) unsigned long flags; bool is_agg = false; - if (info->control.vif) - ctx = il_rxon_ctx_from_vif(info->control.vif); - spin_lock_irqsave(&il->lock, flags); if (il_is_rfkill(il)) { D_DROP("Dropping - RF KILL\n"); @@ -1688,7 +1680,7 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) sta_id = il->hw_params.bcast_id; else { /* Find idx into station table for destination station */ - sta_id = il_sta_id_or_broadcast(il, ctx, info->control.sta); + sta_id = il_sta_id_or_broadcast(il, info->control.sta); if (sta_id == IL_INVALID_STATION) { D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1); @@ -1764,7 +1756,6 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) /* Set up driver data for this TFD */ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct il_tx_info)); txq->txb[q->write_ptr].skb = skb; - txq->txb[q->write_ptr].ctx = ctx; /* Set up first empty entry in queue's array of Tx/cmd buffers */ out_cmd = txq->cmd[q->write_ptr]; @@ -2228,7 +2219,8 @@ il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif, unsigned long flags; struct il_tid_data *tid_data; - tx_fifo = il4965_get_fifo_from_tid(il_rxon_ctx_from_vif(vif), tid); + /* FIXME: warning if tx fifo not found ? */ + tx_fifo = il4965_get_fifo_from_tid(tid); if (unlikely(tx_fifo < 0)) return tx_fifo; @@ -2321,7 +2313,8 @@ il4965_tx_agg_stop(struct il_priv *il, struct ieee80211_vif *vif, int write_ptr, read_ptr; unsigned long flags; - tx_fifo_id = il4965_get_fifo_from_tid(il_rxon_ctx_from_vif(vif), tid); + /* FIXME: warning if tx_fifo_id not found ? */ + tx_fifo_id = il4965_get_fifo_from_tid(tid); if (unlikely(tx_fifo_id < 0)) return tx_fifo_id; @@ -2395,9 +2388,6 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id) struct il_queue *q = &il->txq[txq_id].q; u8 *addr = il->stations[sta_id].sta.sta.addr; struct il_tid_data *tid_data = &il->stations[sta_id].tid[tid]; - struct il_rxon_context *ctx; - - ctx = &il->ctx; lockdep_assert_held(&il->sta_lock); @@ -2408,11 +2398,11 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id) if (txq_id == tid_data->agg.txq_id && q->read_ptr == q->write_ptr) { u16 ssn = SEQ_TO_SN(tid_data->seq_number); - int tx_fifo = il4965_get_fifo_from_tid(ctx, tid); + int tx_fifo = il4965_get_fifo_from_tid(tid); D_HT("HW queue empty: continue DELBA flow\n"); il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo); tid_data->agg.state = IL_AGG_OFF; - ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); + ieee80211_stop_tx_ba_cb_irqsafe(il->vif, addr, tid); } break; case IL_EMPTYING_HW_QUEUE_ADDBA: @@ -2420,7 +2410,7 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id) if (tid_data->tfds_in_queue == 0) { D_HT("HW queue empty: continue ADDBA flow\n"); tid_data->agg.state = IL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid); + ieee80211_start_tx_ba_cb_irqsafe(il->vif, addr, tid); } break; } @@ -2429,14 +2419,13 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id) } static void -il4965_non_agg_tx_status(struct il_priv *il, struct il_rxon_context *ctx, - const u8 *addr1) +il4965_non_agg_tx_status(struct il_priv *il, const u8 *addr1) { struct ieee80211_sta *sta; struct il_station_priv *sta_priv; rcu_read_lock(); - sta = ieee80211_find_sta(ctx->vif, addr1); + sta = ieee80211_find_sta(il->vif, addr1); if (sta) { sta_priv = (void *)sta->drv_priv; /* avoid atomic ops if this isn't a client */ @@ -2453,7 +2442,7 @@ il4965_tx_status(struct il_priv *il, struct il_tx_info *tx_info, bool is_agg) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; if (!is_agg) - il4965_non_agg_tx_status(il, tx_info->ctx, hdr->addr1); + il4965_non_agg_tx_status(il, hdr->addr1); ieee80211_tx_status_irqsafe(il->hw, tx_info->skb); } @@ -2769,8 +2758,7 @@ il4965_sta_alloc_lq(struct il_priv *il, u8 sta_id) * Function sleeps. */ int -il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx, - const u8 *addr, u8 *sta_id_r) +il4965_add_bssid_station(struct il_priv *il, const u8 *addr, u8 *sta_id_r) { int ret; u8 sta_id; @@ -2780,7 +2768,7 @@ il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx, if (sta_id_r) *sta_id_r = IL_INVALID_STATION; - ret = il_add_station_common(il, ctx, addr, 0, NULL, &sta_id); + ret = il_add_station_common(il, addr, 0, NULL, &sta_id); if (ret) { IL_ERR("Unable to add station %pM\n", addr); return ret; @@ -2801,7 +2789,7 @@ il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx, return -ENOMEM; } - ret = il_send_lq_cmd(il, ctx, link_cmd, CMD_SYNC, true); + ret = il_send_lq_cmd(il, link_cmd, CMD_SYNC, true); if (ret) IL_ERR("Link quality command failed (%d)\n", ret); @@ -2813,8 +2801,7 @@ il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx, } static int -il4965_static_wepkey_cmd(struct il_priv *il, struct il_rxon_context *ctx, - bool send_if_empty) +il4965_static_wepkey_cmd(struct il_priv *il, bool send_if_empty) { int i; u8 buff[sizeof(struct il_wep_cmd) + @@ -2860,15 +2847,15 @@ il4965_static_wepkey_cmd(struct il_priv *il, struct il_rxon_context *ctx, } int -il4965_restore_default_wep_keys(struct il_priv *il, struct il_rxon_context *ctx) +il4965_restore_default_wep_keys(struct il_priv *il) { lockdep_assert_held(&il->mutex); - return il4965_static_wepkey_cmd(il, ctx, false); + return il4965_static_wepkey_cmd(il, false); } int -il4965_remove_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, +il4965_remove_default_wep_key(struct il_priv *il, struct ieee80211_key_conf *keyconf) { int ret; @@ -2884,14 +2871,14 @@ il4965_remove_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, /* but keys in device are clear anyway so return success */ return 0; } - ret = il4965_static_wepkey_cmd(il, ctx, 1); + ret = il4965_static_wepkey_cmd(il, 1); D_WEP("Remove default WEP key: idx=%d ret=%d\n", idx, ret); return ret; } int -il4965_set_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, +il4965_set_default_wep_key(struct il_priv *il, struct ieee80211_key_conf *keyconf) { int ret; @@ -2912,14 +2899,14 @@ il4965_set_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, il->_4965.wep_keys[idx].key_size = len; memcpy(&il->_4965.wep_keys[idx].key, &keyconf->key, len); - ret = il4965_static_wepkey_cmd(il, ctx, false); + ret = il4965_static_wepkey_cmd(il, false); D_WEP("Set default WEP key: len=%d idx=%d ret=%d\n", len, idx, ret); return ret; } static int -il4965_set_wep_dynamic_key_info(struct il_priv *il, struct il_rxon_context *ctx, +il4965_set_wep_dynamic_key_info(struct il_priv *il, struct ieee80211_key_conf *keyconf, u8 sta_id) { unsigned long flags; @@ -2974,7 +2961,6 @@ il4965_set_wep_dynamic_key_info(struct il_priv *il, struct il_rxon_context *ctx, static int il4965_set_ccmp_dynamic_key_info(struct il_priv *il, - struct il_rxon_context *ctx, struct ieee80211_key_conf *keyconf, u8 sta_id) { unsigned long flags; @@ -3023,7 +3009,6 @@ il4965_set_ccmp_dynamic_key_info(struct il_priv *il, static int il4965_set_tkip_dynamic_key_info(struct il_priv *il, - struct il_rxon_context *ctx, struct ieee80211_key_conf *keyconf, u8 sta_id) { unsigned long flags; @@ -3068,9 +3053,8 @@ il4965_set_tkip_dynamic_key_info(struct il_priv *il, } void -il4965_update_tkip_key(struct il_priv *il, struct il_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, u32 iv32, u16 * phase1key) +il4965_update_tkip_key(struct il_priv *il, struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) { u8 sta_id; unsigned long flags; @@ -3082,7 +3066,7 @@ il4965_update_tkip_key(struct il_priv *il, struct il_rxon_context *ctx, return; } - sta_id = il_sta_id_or_broadcast(il, ctx, sta); + sta_id = il_sta_id_or_broadcast(il, sta); if (sta_id == IL_INVALID_STATION) return; @@ -3100,11 +3084,10 @@ il4965_update_tkip_key(struct il_priv *il, struct il_rxon_context *ctx, il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC); spin_unlock_irqrestore(&il->sta_lock, flags); - } int -il4965_remove_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, +il4965_remove_dynamic_key(struct il_priv *il, struct ieee80211_key_conf *keyconf, u8 sta_id) { unsigned long flags; @@ -3165,8 +3148,8 @@ il4965_remove_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, } int -il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, u8 sta_id) +il4965_set_dynamic_key(struct il_priv *il, struct ieee80211_key_conf *keyconf, + u8 sta_id) { int ret; @@ -3178,15 +3161,15 @@ il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, switch (keyconf->cipher) { case WLAN_CIPHER_SUITE_CCMP: ret = - il4965_set_ccmp_dynamic_key_info(il, ctx, keyconf, sta_id); + il4965_set_ccmp_dynamic_key_info(il, keyconf, sta_id); break; case WLAN_CIPHER_SUITE_TKIP: ret = - il4965_set_tkip_dynamic_key_info(il, ctx, keyconf, sta_id); + il4965_set_tkip_dynamic_key_info(il, keyconf, sta_id); break; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: - ret = il4965_set_wep_dynamic_key_info(il, ctx, keyconf, sta_id); + ret = il4965_set_wep_dynamic_key_info(il, keyconf, sta_id); break; default: IL_ERR("Unknown alg: %s cipher = %x\n", __func__, @@ -3208,14 +3191,14 @@ il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, * device at the next best time. */ int -il4965_alloc_bcast_station(struct il_priv *il, struct il_rxon_context *ctx) +il4965_alloc_bcast_station(struct il_priv *il) { struct il_link_quality_cmd *link_cmd; unsigned long flags; u8 sta_id; spin_lock_irqsave(&il->sta_lock, flags); - sta_id = il_prep_station(il, ctx, il_bcast_addr, false, NULL); + sta_id = il_prep_station(il, il_bcast_addr, false, NULL); if (sta_id == IL_INVALID_STATION) { IL_ERR("Unable to prepare broadcast station\n"); spin_unlock_irqrestore(&il->sta_lock, flags); @@ -3248,7 +3231,7 @@ il4965_alloc_bcast_station(struct il_priv *il, struct il_rxon_context *ctx) * code together. */ static int -il4965_update_bcast_station(struct il_priv *il, struct il_rxon_context *ctx) +il4965_update_bcast_station(struct il_priv *il) { unsigned long flags; struct il_link_quality_cmd *link_cmd; @@ -3274,7 +3257,7 @@ il4965_update_bcast_station(struct il_priv *il, struct il_rxon_context *ctx) int il4965_update_bcast_stations(struct il_priv *il) { - return il4965_update_bcast_station(il, &il->ctx); + return il4965_update_bcast_station(il); } /** @@ -3375,9 +3358,9 @@ void il4965_update_chain_flags(struct il_priv *il) { if (il->cfg->ops->hcmd->set_rxon_chain) { - il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx); + il->cfg->ops->hcmd->set_rxon_chain(il); if (il->active.rx_chain != il->staging.rx_chain) - il_commit_rxon(il, &il->ctx); + il_commit_rxon(il); } } @@ -3489,8 +3472,8 @@ il4965_hw_get_beacon_cmd(struct il_priv *il, struct il_frame *frame) lockdep_assert_held(&il->mutex); - if (!il->beacon_ctx) { - IL_ERR("trying to build beacon w/o beacon context!\n"); + if (!il->beacon_enabled) { + IL_ERR("Trying to build beacon without beaconing enabled\n"); return 0; } @@ -3520,7 +3503,7 @@ il4965_hw_get_beacon_cmd(struct il_priv *il, struct il_frame *frame) frame_size); /* Set up packet rate and flags */ - rate = il_get_lowest_plcp(il, il->beacon_ctx); + rate = il_get_lowest_plcp(il); il4965_toggle_tx_ant(il, &il->mgmt_tx_ant, il->hw_params.valid_tx_ant); rate_flags = BIT(il->mgmt_tx_ant) << RATE_MCS_ANT_POS; if ((rate >= IL_FIRST_CCK_RATE) && (rate <= IL_LAST_CCK_RATE)) @@ -4977,7 +4960,6 @@ static void il4965_alive_start(struct il_priv *il) { int ret = 0; - struct il_rxon_context *ctx = &il->ctx; D_INFO("Runtime Alive received.\n"); @@ -5025,10 +5007,10 @@ il4965_alive_start(struct il_priv *il) active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { /* Initialize our rx_config data */ - il_connection_init_rx_config(il, &il->ctx); + il_connection_init_rx_config(il); if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il, ctx); + il->cfg->ops->hcmd->set_rxon_chain(il); } /* Configure bluetooth coexistence if enabled */ @@ -5039,7 +5021,7 @@ il4965_alive_start(struct il_priv *il) set_bit(S_READY, &il->status); /* Configure the adapter for unassociated operation */ - il_commit_rxon(il, ctx); + il_commit_rxon(il); /* At this point, the NIC is initialized and operational */ il4965_rf_kill_ct_config(il); @@ -5074,7 +5056,7 @@ __il4965_down(struct il_priv *il) * to prevent rearm timer */ del_timer_sync(&il->watchdog); - il_clear_ucode_stations(il, NULL); + il_clear_ucode_stations(il); /* FIXME: race conditions ? */ spin_lock_irq(&il->sta_lock); @@ -5239,7 +5221,7 @@ __il4965_up(struct il_priv *il) return -EIO; } - ret = il4965_alloc_bcast_station(il, &il->ctx); + ret = il4965_alloc_bcast_station(il); if (ret) { il_dealloc_bcast_stations(il); return ret; @@ -5393,7 +5375,8 @@ il4965_bg_restart(struct work_struct *data) if (test_and_clear_bit(S_FW_ERROR, &il->status)) { mutex_lock(&il->mutex); - il->ctx.vif = NULL; + /* FIXME: do we dereference vif without mutex locked ? */ + il->vif = NULL; il->is_open = 0; __il4965_down(il); @@ -5590,12 +5573,10 @@ il4965_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u32 iv32, u16 * phase1key) { struct il_priv *il = hw->priv; - struct il_vif_priv *vif_priv = (void *)vif->drv_priv; D_MAC80211("enter\n"); - il4965_update_tkip_key(il, vif_priv->ctx, keyconf, sta, iv32, - phase1key); + il4965_update_tkip_key(il, keyconf, sta, iv32, phase1key); D_MAC80211("leave\n"); } @@ -5606,8 +5587,6 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct il_priv *il = hw->priv; - struct il_vif_priv *vif_priv = (void *)vif->drv_priv; - struct il_rxon_context *ctx = vif_priv->ctx; int ret; u8 sta_id; bool is_default_wep_key = false; @@ -5619,7 +5598,7 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - sta_id = il_sta_id_or_broadcast(il, vif_priv->ctx, sta); + sta_id = il_sta_id_or_broadcast(il, sta); if (sta_id == IL_INVALID_STATION) return -EINVAL; @@ -5644,20 +5623,17 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch (cmd) { case SET_KEY: if (is_default_wep_key) - ret = - il4965_set_default_wep_key(il, vif_priv->ctx, key); + ret = il4965_set_default_wep_key(il, key); else - ret = - il4965_set_dynamic_key(il, vif_priv->ctx, key, - sta_id); + ret = il4965_set_dynamic_key(il, key, sta_id); D_MAC80211("enable hwcrypto key\n"); break; case DISABLE_KEY: if (is_default_wep_key) - ret = il4965_remove_default_wep_key(il, ctx, key); + ret = il4965_remove_default_wep_key(il, key); else - ret = il4965_remove_dynamic_key(il, ctx, key, sta_id); + ret = il4965_remove_dynamic_key(il, key, sta_id); D_MAC80211("disable hwcrypto key\n"); break; @@ -5723,7 +5699,6 @@ il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct il_priv *il = hw->priv; struct il_station_priv *sta_priv = (void *)sta->drv_priv; - struct il_vif_priv *vif_priv = (void *)vif->drv_priv; bool is_ap = vif->type == NL80211_IFTYPE_STATION; int ret; u8 sta_id; @@ -5736,8 +5711,7 @@ il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, atomic_set(&sta_priv->pending_frames, 0); ret = - il_add_station_common(il, vif_priv->ctx, sta->addr, is_ap, sta, - &sta_id); + il_add_station_common(il, sta->addr, is_ap, sta, &sta_id); if (ret) { IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret); /* Should we return success if return code is EEXIST ? */ @@ -5764,8 +5738,6 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_conf *conf = &hw->conf; struct ieee80211_channel *channel = ch_switch->channel; struct il_ht_config *ht_conf = &il->current_ht_config; - - struct il_rxon_context *ctx = &il->ctx; u16 ch; D_MAC80211("enter\n"); @@ -5822,9 +5794,9 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, if ((le16_to_cpu(il->staging.channel) != ch)) il->staging.flags = 0; - il_set_rxon_channel(il, channel, ctx); + il_set_rxon_channel(il, channel); il_set_rxon_ht(il, ht_conf); - il_set_flags_for_band(il, ctx, channel->band, ctx->vif); + il_set_flags_for_band(il, channel->band, il->vif); spin_unlock_irq(&il->lock); @@ -5838,7 +5810,7 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, if (il->cfg->ops->lib->set_channel_switch(il, ch_switch)) { clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status); il->switch_channel = 0; - ieee80211_chswitch_done(ctx->vif, false); + ieee80211_chswitch_done(il->vif, false); } out: @@ -6049,7 +6021,7 @@ il4965_init_drv(struct il_priv *il) /* Choose which receivers/antennas to use */ if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx); + il->cfg->ops->hcmd->set_rxon_chain(il); il_init_scan_params(il); diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c index ad186d9a598..d7e2856e41d 100644 --- a/drivers/net/wireless/iwlegacy/4965-rs.c +++ b/drivers/net/wireless/iwlegacy/4965-rs.c @@ -820,8 +820,6 @@ il4965_rs_tx_status(void *il_r, struct ieee80211_supported_band *sband, u32 tx_rate; struct il_scale_tbl_info tbl_type; struct il_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; - struct il_station_priv *sta_priv = (void *)sta->drv_priv; - struct il_rxon_context *ctx = sta_priv->common.ctx; D_RATE("get frame ack response, update rate scale win\n"); @@ -889,7 +887,7 @@ il4965_rs_tx_status(void *il_r, struct ieee80211_supported_band *sband, lq_sta->missed_rate_counter++; if (lq_sta->missed_rate_counter > IL_MISSED_RATE_MAX) { lq_sta->missed_rate_counter = 0; - il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_ASYNC, false); + il_send_lq_cmd(il, &lq_sta->lq, CMD_ASYNC, false); } /* Regardless, ignore this status info for outdated rate */ return; @@ -1181,8 +1179,6 @@ il4965_rs_switch_to_mimo2(struct il_priv *il, struct il_lq_sta *lq_sta, u16 rate_mask; s32 rate; s8 is_green = lq_sta->is_green; - struct il_station_priv *sta_priv = (void *)sta->drv_priv; - struct il_rxon_context *ctx = sta_priv->common.ctx; if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) return -1; @@ -1203,7 +1199,7 @@ il4965_rs_switch_to_mimo2(struct il_priv *il, struct il_lq_sta *lq_sta, tbl->max_search = IL_MAX_SEARCH; rate_mask = lq_sta->active_mimo2_rate; - if (il_is_ht40_tx_allowed(il, ctx, &sta->ht_cap)) + if (il_is_ht40_tx_allowed(il, &sta->ht_cap)) tbl->is_ht40 = 1; else tbl->is_ht40 = 0; @@ -1237,8 +1233,6 @@ il4965_rs_switch_to_siso(struct il_priv *il, struct il_lq_sta *lq_sta, u16 rate_mask; u8 is_green = lq_sta->is_green; s32 rate; - struct il_station_priv *sta_priv = (void *)sta->drv_priv; - struct il_rxon_context *ctx = sta_priv->common.ctx; if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) return -1; @@ -1251,7 +1245,7 @@ il4965_rs_switch_to_siso(struct il_priv *il, struct il_lq_sta *lq_sta, tbl->max_search = IL_MAX_SEARCH; rate_mask = lq_sta->active_siso_rate; - if (il_is_ht40_tx_allowed(il, ctx, &sta->ht_cap)) + if (il_is_ht40_tx_allowed(il, &sta->ht_cap)) tbl->is_ht40 = 1; else tbl->is_ht40 = 0; @@ -1730,8 +1724,7 @@ il4965_rs_stay_in_table(struct il_lq_sta *lq_sta, bool force_search) * setup rate table in uCode */ static void -il4965_rs_update_rate_tbl(struct il_priv *il, struct il_rxon_context *ctx, - struct il_lq_sta *lq_sta, +il4965_rs_update_rate_tbl(struct il_priv *il, struct il_lq_sta *lq_sta, struct il_scale_tbl_info *tbl, int idx, u8 is_green) { u32 rate; @@ -1739,7 +1732,7 @@ il4965_rs_update_rate_tbl(struct il_priv *il, struct il_rxon_context *ctx, /* Update uCode's rate table. */ rate = il4965_rate_n_flags_from_tbl(il, tbl, idx, is_green); il4965_rs_fill_link_cmd(il, lq_sta, rate); - il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_ASYNC, false); + il_send_lq_cmd(il, &lq_sta->lq, CMD_ASYNC, false); } /* @@ -1775,8 +1768,6 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb, s32 sr; u8 tid = MAX_TID_COUNT; struct il_tid_data *tid_data; - struct il_station_priv *sta_priv = (void *)sta->drv_priv; - struct il_rxon_context *ctx = sta_priv->common.ctx; D_RATE("rate scale calculate new rate for skb\n"); @@ -1851,7 +1842,7 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb, tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); /* get "active" rate info */ idx = il4965_hwrate_to_plcp_idx(tbl->current_rate); - il4965_rs_update_rate_tbl(il, ctx, lq_sta, tbl, idx, + il4965_rs_update_rate_tbl(il, lq_sta, tbl, idx, is_green); } return; @@ -2054,8 +2045,7 @@ il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb, lq_update: /* Replace uCode's rate table for the destination station. */ if (update_lq) - il4965_rs_update_rate_tbl(il, ctx, lq_sta, tbl, idx, - is_green); + il4965_rs_update_rate_tbl(il, lq_sta, tbl, idx, is_green); /* Should we stay with this modulation mode, * or search for a new one? */ @@ -2095,7 +2085,7 @@ lq_update: D_RATE("Switch current mcs: %X idx: %d\n", tbl->current_rate, idx); il4965_rs_fill_link_cmd(il, lq_sta, tbl->current_rate); - il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_ASYNC, false); + il_send_lq_cmd(il, &lq_sta->lq, CMD_ASYNC, false); } else done_search = 1; } @@ -2167,13 +2157,11 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf, u8 active_tbl = 0; u8 valid_tx_ant; struct il_station_priv *sta_priv; - struct il_rxon_context *ctx; if (!sta || !lq_sta) return; sta_priv = (void *)sta->drv_priv; - ctx = sta_priv->common.ctx; i = lq_sta->last_txrate_idx; @@ -2205,7 +2193,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf, il4965_rs_set_expected_tpt_table(lq_sta, tbl); il4965_rs_fill_link_cmd(NULL, lq_sta, rate); il->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; - il_send_lq_cmd(il, ctx, &lq_sta->lq, CMD_SYNC, true); + il_send_lq_cmd(il, &lq_sta->lq, CMD_SYNC, true); } static void @@ -2576,9 +2564,6 @@ il4965_rs_sta_dbgfs_scale_table_write(struct file *file, char buf[64]; size_t buf_size; u32 parsed_rate; - struct il_station_priv *sta_priv = - container_of(lq_sta, struct il_station_priv, lq_sta); - struct il_rxon_context *ctx = sta_priv->common.ctx; il = lq_sta->drv; memset(buf, 0, sizeof(buf)); @@ -2600,7 +2585,7 @@ il4965_rs_sta_dbgfs_scale_table_write(struct file *file, if (lq_sta->dbg_fixed_rate) { il4965_rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); - il_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC, false); + il_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); } return count; diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index 7b0192aff83..9d9197f7fa3 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c @@ -1370,7 +1370,7 @@ out: } static int -il4965_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) +il4965_send_rxon_assoc(struct il_priv *il) { int ret = 0; struct il4965_rxon_assoc_cmd rxon_assoc; @@ -1409,7 +1409,7 @@ il4965_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) } static int -il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) +il4965_commit_rxon(struct il_priv *il) { /* cast away the const for active_rxon in this function */ struct il_rxon_cmd *active_rxon = (void *)&il->active; @@ -1422,7 +1422,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) /* always get timestamp with Rx frame */ il->staging.flags |= RXON_FLG_TSF2HOST_MSK; - ret = il_check_rxon_cmd(il, ctx); + ret = il_check_rxon_cmd(il); if (ret) { IL_ERR("Invalid RXON configuration. Not committing.\n"); return -EINVAL; @@ -1442,15 +1442,15 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) /* If we don't need to send a full RXON, we can use * il_rxon_assoc_cmd which is used to reconfigure filter * and other flags for the current radio configuration. */ - if (!il_full_rxon_required(il, ctx)) { - ret = il_send_rxon_assoc(il, ctx); + if (!il_full_rxon_required(il)) { + ret = il_send_rxon_assoc(il); if (ret) { IL_ERR("Error setting RXON_ASSOC (%d)\n", ret); return ret; } memcpy(active_rxon, &il->staging, sizeof(*active_rxon)); - il_print_rx_config_cmd(il, ctx); + il_print_rx_config_cmd(il); /* * We do not commit tx power settings while channel changing, * do it now if tx power changed. @@ -1478,9 +1478,9 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) IL_ERR("Error clearing ASSOC_MSK (%d)\n", ret); return ret; } - il_clear_ucode_stations(il, ctx); - il_restore_stations(il, ctx); - ret = il4965_restore_default_wep_keys(il, ctx); + il_clear_ucode_stations(il); + il_restore_stations(il); + ret = il4965_restore_default_wep_keys(il); if (ret) { IL_ERR("Failed to restore WEP keys (%d)\n", ret); return ret; @@ -1491,7 +1491,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) "* channel = %d\n" "* bssid = %pM\n", (new_assoc ? "" : "out"), le16_to_cpu(il->staging.channel), il->staging.bssid_addr); - il_set_rxon_hwcrypto(il, ctx, !il->cfg->mod_params->sw_crypto); + il_set_rxon_hwcrypto(il, !il->cfg->mod_params->sw_crypto); /* Apply the new configuration * RXON unassoc clears the station table in uCode so restoration of @@ -1507,9 +1507,9 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) } D_INFO("Return from !new_assoc RXON.\n"); memcpy(active_rxon, &il->staging, sizeof(*active_rxon)); - il_clear_ucode_stations(il, ctx); - il_restore_stations(il, ctx); - ret = il4965_restore_default_wep_keys(il, ctx); + il_clear_ucode_stations(il); + il_restore_stations(il); + ret = il4965_restore_default_wep_keys(il); if (ret) { IL_ERR("Failed to restore WEP keys (%d)\n", ret); return ret; @@ -1529,7 +1529,7 @@ il4965_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) } memcpy(active_rxon, &il->staging, sizeof(*active_rxon)); } - il_print_rx_config_cmd(il, ctx); + il_print_rx_config_cmd(il); il4965_init_sensitivity(il); @@ -1548,7 +1548,6 @@ static int il4965_hw_channel_switch(struct il_priv *il, struct ieee80211_channel_switch *ch_switch) { - struct il_rxon_context *ctx = &il->ctx; int rc; u8 band = 0; bool is_ht40 = false; @@ -1560,8 +1559,11 @@ il4965_hw_channel_switch(struct il_priv *il, u32 tsf_low; u8 switch_count; u16 beacon_interval = le16_to_cpu(il->timing.beacon_interval); - struct ieee80211_vif *vif = ctx->vif; - band = il->band == IEEE80211_BAND_2GHZ; + struct ieee80211_vif *vif = il->vif; + band = (il->band == IEEE80211_BAND_2GHZ); + + if (WARN_ON_ONCE(vif == NULL)) + return -EIO; is_ht40 = iw4965_is_ht40_channel(il->staging.flags); @@ -2128,21 +2130,18 @@ static struct il_hcmd_ops il4965_hcmd = { static void il4965_post_scan(struct il_priv *il) { - struct il_rxon_context *ctx = &il->ctx; - /* * Since setting the RXON may have been deferred while * performing the scan, fire one off if needed */ if (memcmp(&il->staging, &il->active, sizeof(il->staging))) - il_commit_rxon(il, ctx); + il_commit_rxon(il); } static void il4965_post_associate(struct il_priv *il) { - struct il_rxon_context *ctx = &il->ctx; - struct ieee80211_vif *vif = ctx->vif; + struct ieee80211_vif *vif = il->vif; struct ieee80211_conf *conf = NULL; int ret = 0; @@ -2157,9 +2156,9 @@ il4965_post_associate(struct il_priv *il) conf = &il->hw->conf; il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - il_commit_rxon(il, ctx); + il_commit_rxon(il); - ret = il_send_rxon_timing(il, ctx); + ret = il_send_rxon_timing(il); if (ret) IL_WARN("RXON timing - " "Attempting to continue.\n"); @@ -2168,7 +2167,7 @@ il4965_post_associate(struct il_priv *il) il_set_rxon_ht(il, &il->current_ht_config); if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il, ctx); + il->cfg->ops->hcmd->set_rxon_chain(il); il->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); @@ -2187,7 +2186,7 @@ il4965_post_associate(struct il_priv *il) il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } - il_commit_rxon(il, ctx); + il_commit_rxon(il); D_ASSOC("Associated as %d to: %pM\n", vif->bss_conf.aid, il->active.bssid_addr); @@ -2218,8 +2217,7 @@ il4965_post_associate(struct il_priv *il) static void il4965_config_ap(struct il_priv *il) { - struct il_rxon_context *ctx = &il->ctx; - struct ieee80211_vif *vif = ctx->vif; + struct ieee80211_vif *vif = il->vif; int ret = 0; lockdep_assert_held(&il->mutex); @@ -2232,10 +2230,10 @@ il4965_config_ap(struct il_priv *il) /* RXON - unassoc (to set timing command) */ il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - il_commit_rxon(il, ctx); + il_commit_rxon(il); /* RXON Timing */ - ret = il_send_rxon_timing(il, ctx); + ret = il_send_rxon_timing(il); if (ret) IL_WARN("RXON timing failed - " "Attempting to continue.\n"); @@ -2244,7 +2242,7 @@ il4965_config_ap(struct il_priv *il) il->chain_noise_data.active_chains = il->hw_params.valid_rx_ant; il_set_rxon_ht(il, &il->current_ht_config); if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il, ctx); + il->cfg->ops->hcmd->set_rxon_chain(il); il->staging.assoc_id = 0; @@ -2263,7 +2261,7 @@ il4965_config_ap(struct il_priv *il) il4965_send_beacon_cmd(il); /* restore RXON assoc */ il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - il_commit_rxon(il, ctx); + il_commit_rxon(il); } il4965_send_beacon_cmd(il); } diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index f280e0161b1..67899602ee5 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h @@ -48,7 +48,7 @@ void il4965_free_tfds_in_queue(struct il_priv *il, int sta_id, int tid, int freed); /* RXON */ -void il4965_set_rxon_chain(struct il_priv *il, struct il_rxon_context *ctx); +void il4965_set_rxon_chain(struct il_priv *il); /* uCode */ int il4965_verify_ucode(struct il_priv *il); @@ -134,21 +134,18 @@ il4965_get_tx_fail_reason(u32 status) #endif /* station management */ -int il4965_alloc_bcast_station(struct il_priv *il, struct il_rxon_context *ctx); -int il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx, - const u8 *addr, u8 *sta_id_r); +int il4965_alloc_bcast_station(struct il_priv *il); +int il4965_add_bssid_station(struct il_priv *il, const u8 *addr, u8 *sta_id_r); int il4965_remove_default_wep_key(struct il_priv *il, - struct il_rxon_context *ctx, struct ieee80211_key_conf *key); -int il4965_set_default_wep_key(struct il_priv *il, struct il_rxon_context *ctx, +int il4965_set_default_wep_key(struct il_priv *il, struct ieee80211_key_conf *key); -int il4965_restore_default_wep_keys(struct il_priv *il, - struct il_rxon_context *ctx); -int il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, +int il4965_restore_default_wep_keys(struct il_priv *il); +int il4965_set_dynamic_key(struct il_priv *il, struct ieee80211_key_conf *key, u8 sta_id); -int il4965_remove_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx, +int il4965_remove_dynamic_key(struct il_priv *il, struct ieee80211_key_conf *key, u8 sta_id); -void il4965_update_tkip_key(struct il_priv *il, struct il_rxon_context *ctx, +void il4965_update_tkip_key(struct il_priv *il, struct ieee80211_key_conf *keyconf, struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index ea2fa97fa36..bee11a3aeac 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -1442,7 +1442,6 @@ u16 il_get_passive_dwell_time(struct il_priv *il, enum ieee80211_band band, struct ieee80211_vif *vif) { - struct il_rxon_context *ctx = &il->ctx; u16 value; u16 passive = @@ -1457,7 +1456,7 @@ il_get_passive_dwell_time(struct il_priv *il, enum ieee80211_band band, * dwell time to be 98% of the smallest beacon interval * (minus 2 * channel tune time) */ - value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0; + value = il->vif ? il->vif->bss_conf.beacon_int : 0; if (value > IL_PASSIVE_DWELL_BASE || !value) value = IL_PASSIVE_DWELL_BASE; value = (value * 98) / 100 - IL_CHANNEL_TUNE_TIME * 2; @@ -1832,8 +1831,7 @@ il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags) EXPORT_SYMBOL(il_send_add_sta); static void -il_set_ht_add_station(struct il_priv *il, u8 idx, struct ieee80211_sta *sta, - struct il_rxon_context *ctx) +il_set_ht_add_station(struct il_priv *il, u8 idx, struct ieee80211_sta *sta) { struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap; __le32 sta_flags; @@ -1874,7 +1872,7 @@ il_set_ht_add_station(struct il_priv *il, u8 idx, struct ieee80211_sta *sta, cpu_to_le32((u32) sta_ht_inf-> ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); - if (il_is_ht40_tx_allowed(il, ctx, &sta->ht_cap)) + if (il_is_ht40_tx_allowed(il, &sta->ht_cap)) sta_flags |= STA_FLG_HT40_EN_MSK; else sta_flags &= ~STA_FLG_HT40_EN_MSK; @@ -1890,8 +1888,8 @@ done: * should be called with sta_lock held */ u8 -il_prep_station(struct il_priv *il, struct il_rxon_context *ctx, - const u8 *addr, bool is_ap, struct ieee80211_sta *sta) +il_prep_station(struct il_priv *il, const u8 *addr, bool is_ap, + struct ieee80211_sta *sta) { struct il_station_entry *station; int i; @@ -1952,19 +1950,12 @@ il_prep_station(struct il_priv *il, struct il_rxon_context *ctx, station->sta.sta.sta_id = sta_id; station->sta.station_flags = 0; - if (sta) { - struct il_station_priv_common *sta_priv; - - sta_priv = (void *)sta->drv_priv; - sta_priv->ctx = ctx; - } - /* * OK to call unconditionally, since local stations (IBSS BSSID * STA and broadcast STA) pass in a NULL sta, and mac80211 * doesn't allow HT IBSS. */ - il_set_ht_add_station(il, sta_id, sta, ctx); + il_set_ht_add_station(il, sta_id, sta); /* 3945 only */ rate = (il->band == IEEE80211_BAND_5GHZ) ? RATE_6M_PLCP : RATE_1M_PLCP; @@ -1982,9 +1973,8 @@ EXPORT_SYMBOL_GPL(il_prep_station); * il_add_station_common - */ int -il_add_station_common(struct il_priv *il, struct il_rxon_context *ctx, - const u8 *addr, bool is_ap, struct ieee80211_sta *sta, - u8 *sta_id_r) +il_add_station_common(struct il_priv *il, const u8 *addr, bool is_ap, + struct ieee80211_sta *sta, u8 *sta_id_r) { unsigned long flags_spin; int ret = 0; @@ -1993,7 +1983,7 @@ il_add_station_common(struct il_priv *il, struct il_rxon_context *ctx, *sta_id_r = 0; spin_lock_irqsave(&il->sta_lock, flags_spin); - sta_id = il_prep_station(il, ctx, addr, is_ap, sta); + sta_id = il_prep_station(il, addr, is_ap, sta); if (sta_id == IL_INVALID_STATION) { IL_ERR("Unable to prepare station %pM for addition\n", addr); spin_unlock_irqrestore(&il->sta_lock, flags_spin); @@ -2180,7 +2170,7 @@ EXPORT_SYMBOL_GPL(il_remove_station); * the ucode, e.g. unassociated RXON. */ void -il_clear_ucode_stations(struct il_priv *il, struct il_rxon_context *ctx) +il_clear_ucode_stations(struct il_priv *il) { int i; unsigned long flags_spin; @@ -2212,7 +2202,7 @@ EXPORT_SYMBOL(il_clear_ucode_stations); * Function sleeps. */ void -il_restore_stations(struct il_priv *il, struct il_rxon_context *ctx) +il_restore_stations(struct il_priv *il) { struct il_addsta_cmd sta_cmd; struct il_link_quality_cmd lq; @@ -2267,7 +2257,7 @@ il_restore_stations(struct il_priv *il, struct il_rxon_context *ctx) * current LQ command */ if (send_lq) - il_send_lq_cmd(il, ctx, &lq, CMD_SYNC, true); + il_send_lq_cmd(il, &lq, CMD_SYNC, true); spin_lock_irqsave(&il->sta_lock, flags_spin); il->stations[i].used &= ~IL_STA_UCODE_INPROGRESS; } @@ -2347,8 +2337,7 @@ il_dump_lq_cmd(struct il_priv *il, struct il_link_quality_cmd *lq) * RXON flags are updated and when LQ command is updated. */ static bool -il_is_lq_table_valid(struct il_priv *il, struct il_rxon_context *ctx, - struct il_link_quality_cmd *lq) +il_is_lq_table_valid(struct il_priv *il, struct il_link_quality_cmd *lq) { int i; @@ -2376,8 +2365,8 @@ il_is_lq_table_valid(struct il_priv *il, struct il_rxon_context *ctx, * progress. */ int -il_send_lq_cmd(struct il_priv *il, struct il_rxon_context *ctx, - struct il_link_quality_cmd *lq, u8 flags, bool init) +il_send_lq_cmd(struct il_priv *il, struct il_link_quality_cmd *lq, + u8 flags, bool init) { int ret = 0; unsigned long flags_spin; @@ -2402,7 +2391,7 @@ il_send_lq_cmd(struct il_priv *il, struct il_rxon_context *ctx, il_dump_lq_cmd(il, lq); BUG_ON(init && (cmd.flags & CMD_ASYNC)); - if (il_is_lq_table_valid(il, ctx, lq)) + if (il_is_lq_table_valid(il, lq)) ret = il_send_cmd(il, &cmd); else ret = -EINVAL; @@ -3556,8 +3545,7 @@ il_is_channel_extension(struct il_priv *il, enum ieee80211_band band, } bool -il_is_ht40_tx_allowed(struct il_priv *il, struct il_rxon_context *ctx, - struct ieee80211_sta_ht_cap *ht_cap) +il_is_ht40_tx_allowed(struct il_priv *il, struct ieee80211_sta_ht_cap *ht_cap) { if (!il->ht.enabled || !il->ht.is_40mhz) return false; @@ -3615,13 +3603,13 @@ il_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) } int -il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx) +il_send_rxon_timing(struct il_priv *il) { u64 tsf; s32 interval_tm, rem; struct ieee80211_conf *conf = NULL; u16 beacon_int; - struct ieee80211_vif *vif = ctx->vif; + struct ieee80211_vif *vif = il->vif; conf = &il->hw->conf; @@ -3664,8 +3652,7 @@ il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx) EXPORT_SYMBOL(il_send_rxon_timing); void -il_set_rxon_hwcrypto(struct il_priv *il, struct il_rxon_context *ctx, - int hw_decrypt) +il_set_rxon_hwcrypto(struct il_priv *il, int hw_decrypt) { struct il_rxon_cmd *rxon = &il->staging; @@ -3679,7 +3666,7 @@ EXPORT_SYMBOL(il_set_rxon_hwcrypto); /* validate RXON structure is valid */ int -il_check_rxon_cmd(struct il_priv *il, struct il_rxon_context *ctx) +il_check_rxon_cmd(struct il_priv *il) { struct il_rxon_cmd *rxon = &il->staging; bool error = false; @@ -3759,7 +3746,7 @@ EXPORT_SYMBOL(il_check_rxon_cmd); * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. */ int -il_full_rxon_required(struct il_priv *il, struct il_rxon_context *ctx) +il_full_rxon_required(struct il_priv *il) { const struct il_rxon_cmd *staging = &il->staging; const struct il_rxon_cmd *active = &il->active; @@ -3813,7 +3800,7 @@ il_full_rxon_required(struct il_priv *il, struct il_rxon_context *ctx) EXPORT_SYMBOL(il_full_rxon_required); u8 -il_get_lowest_plcp(struct il_priv *il, struct il_rxon_context *ctx) +il_get_lowest_plcp(struct il_priv *il) { /* * Assign the lowest rate -- should really get this from @@ -3827,8 +3814,7 @@ il_get_lowest_plcp(struct il_priv *il, struct il_rxon_context *ctx) EXPORT_SYMBOL(il_get_lowest_plcp); static void -_il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, - struct il_rxon_context *ctx) +_il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf) { struct il_rxon_cmd *rxon = &il->staging; @@ -3848,7 +3834,7 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, /* clear the HT channel mode before set the mode */ rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); - if (il_is_ht40_tx_allowed(il, ctx, NULL)) { + if (il_is_ht40_tx_allowed(il, NULL)) { /* pure ht40 */ if (il->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; @@ -3886,7 +3872,7 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, } if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il, ctx); + il->cfg->ops->hcmd->set_rxon_chain(il); D_ASSOC("rxon flags 0x%X operation mode :0x%X " "extension channel offset 0x%x\n", le32_to_cpu(rxon->flags), @@ -3896,7 +3882,7 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf, void il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf) { - _il_set_rxon_ht(il, ht_conf, &il->ctx); + _il_set_rxon_ht(il, ht_conf); } EXPORT_SYMBOL(il_set_rxon_ht); @@ -3939,8 +3925,7 @@ EXPORT_SYMBOL(il_get_single_channel_number); * in the staging RXON flag structure based on the ch->band */ int -il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch, - struct il_rxon_context *ctx) +il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch) { enum ieee80211_band band = ch->band; u16 channel = ch->hw_value; @@ -3963,8 +3948,8 @@ il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch, EXPORT_SYMBOL(il_set_rxon_channel); void -il_set_flags_for_band(struct il_priv *il, struct il_rxon_context *ctx, - enum ieee80211_band band, struct ieee80211_vif *vif) +il_set_flags_for_band(struct il_priv *il, enum ieee80211_band band, + struct ieee80211_vif *vif) { if (band == IEEE80211_BAND_5GHZ) { il->staging.flags &= @@ -3989,35 +3974,26 @@ EXPORT_SYMBOL(il_set_flags_for_band); * initialize rxon structure with default values from eeprom */ void -il_connection_init_rx_config(struct il_priv *il, struct il_rxon_context *ctx) +il_connection_init_rx_config(struct il_priv *il) { const struct il_channel_info *ch_info; memset(&il->staging, 0, sizeof(il->staging)); - if (!ctx->vif) { + if (!il->vif) { il->staging.dev_type = RXON_DEV_TYPE_ESS; - } else - switch (ctx->vif->type) { - - case NL80211_IFTYPE_STATION: - il->staging.dev_type = RXON_DEV_TYPE_ESS; - il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; - break; - - case NL80211_IFTYPE_ADHOC: - il->staging.dev_type = RXON_DEV_TYPE_IBSS; - il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; - il->staging.filter_flags = - RXON_FILTER_BCON_AWARE_MSK | - RXON_FILTER_ACCEPT_GRP_MSK; - break; - - default: - IL_ERR("Unsupported interface type %d\n", - ctx->vif->type); - break; - } + } else if (il->vif->type == NL80211_IFTYPE_STATION) { + il->staging.dev_type = RXON_DEV_TYPE_ESS; + il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; + } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { + il->staging.dev_type = RXON_DEV_TYPE_IBSS; + il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; + il->staging.filter_flags = + RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; + } else { + IL_ERR("Unsupported interface type %d\n", il->vif->type); + return; + } #if 0 /* TODO: Figure out when short_preamble would be set and cache from @@ -4037,7 +4013,7 @@ il_connection_init_rx_config(struct il_priv *il, struct il_rxon_context *ctx) il->staging.channel = cpu_to_le16(ch_info->channel); il->band = ch_info->band; - il_set_flags_for_band(il, ctx, il->band, ctx->vif); + il_set_flags_for_band(il, il->band, il->vif); il->staging.ofdm_basic_rates = (IL_OFDM_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF; @@ -4047,8 +4023,8 @@ il_connection_init_rx_config(struct il_priv *il, struct il_rxon_context *ctx) /* clear both MIX and PURE40 mode flag */ il->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | RXON_FLG_CHANNEL_MODE_PURE_40); - if (ctx->vif) - memcpy(il->staging.node_addr, ctx->vif->addr, ETH_ALEN); + if (il->vif) + memcpy(il->staging.node_addr, il->vif->addr, ETH_ALEN); il->staging.ofdm_ht_single_stream_basic_rates = 0xff; il->staging.ofdm_ht_dual_stream_basic_rates = 0xff; @@ -4089,13 +4065,11 @@ EXPORT_SYMBOL(il_set_rate); void il_chswitch_done(struct il_priv *il, bool is_success) { - struct il_rxon_context *ctx = &il->ctx; - if (test_bit(S_EXIT_PENDING, &il->status)) return; if (test_and_clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status)) - ieee80211_chswitch_done(ctx->vif, is_success); + ieee80211_chswitch_done(il->vif, is_success); } EXPORT_SYMBOL(il_chswitch_done); @@ -4124,7 +4098,7 @@ EXPORT_SYMBOL(il_hdl_csa); #ifdef CONFIG_IWLEGACY_DEBUG void -il_print_rx_config_cmd(struct il_priv *il, struct il_rxon_context *ctx) +il_print_rx_config_cmd(struct il_priv *il) { struct il_rxon_cmd *rxon = &il->staging; @@ -4161,7 +4135,7 @@ il_irq_handle_error(struct il_priv *il) il->cfg->ops->lib->dump_fh(il, NULL, false); #ifdef CONFIG_IWLEGACY_DEBUG if (il_get_debug_level(il) & IL_DL_FW_ERRORS) - il_print_rx_config_cmd(il, &il->ctx); + il_print_rx_config_cmd(il); #endif wake_up(&il->wait_command_queue); @@ -4523,21 +4497,20 @@ il_mac_tx_last_beacon(struct ieee80211_hw *hw) EXPORT_SYMBOL_GPL(il_mac_tx_last_beacon); static int -il_set_mode(struct il_priv *il, struct il_rxon_context *ctx) +il_set_mode(struct il_priv *il) { - il_connection_init_rx_config(il, ctx); + il_connection_init_rx_config(il); if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il, ctx); + il->cfg->ops->hcmd->set_rxon_chain(il); - return il_commit_rxon(il, ctx); + return il_commit_rxon(il); } int il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct il_priv *il = hw->priv; - struct il_vif_priv *vif_priv = (void *)vif->drv_priv; int err; D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); @@ -4550,18 +4523,17 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) goto out; } - if (il->ctx.vif) { + if (il->vif) { err = -EOPNOTSUPP; goto out; } - vif_priv->ctx = &il->ctx; - il->ctx.vif = vif; + il->vif = vif; il->iw_mode = vif->type; - err = il_set_mode(il, &il->ctx); + err = il_set_mode(il); if (err) { - il->ctx.vif = NULL; + il->vif = NULL; il->iw_mode = NL80211_IFTYPE_STATION; } @@ -4577,8 +4549,6 @@ static void il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, bool mode_change) { - struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); - lockdep_assert_held(&il->mutex); if (il->scan_vif == vif) { @@ -4587,7 +4557,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, } if (!mode_change) - il_set_mode(il, ctx); + il_set_mode(il); } @@ -4595,14 +4565,13 @@ void il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct il_priv *il = hw->priv; - struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); D_MAC80211("enter\n"); mutex_lock(&il->mutex); - WARN_ON(ctx->vif != vif); - ctx->vif = NULL; + WARN_ON(il->vif != vif); + il->vif = NULL; il_teardown_interface(il, vif, false); @@ -4941,7 +4910,6 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum nl80211_iftype newtype, bool newp2p) { struct il_priv *il = hw->priv; - struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); int err; if (newp2p) @@ -4949,7 +4917,7 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mutex_lock(&il->mutex); - if (!ctx->vif || !il_is_ready_rf(il)) { + if (!il->vif || !il_is_ready_rf(il)) { /* * Huh? But wait ... this can maybe happen when * we're in the middle of a firmware restart! @@ -4962,7 +4930,7 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, il_teardown_interface(il, vif, true); vif->type = newtype; vif->p2p = false; - err = il_set_mode(il, ctx); + err = il_set_mode(il); WARN_ON(err); /* * We've switched internally, but submitting to the @@ -5194,7 +5162,7 @@ EXPORT_SYMBOL(il_pm_ops); #endif /* CONFIG_PM */ static void -il_update_qos(struct il_priv *il, struct il_rxon_context *ctx) +il_update_qos(struct il_priv *il) { if (test_bit(S_EXIT_PENDING, &il->status)) return; @@ -5226,7 +5194,6 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) struct ieee80211_conf *conf = &hw->conf; struct ieee80211_channel *channel = conf->channel; struct il_ht_config *ht_conf = &il->current_ht_config; - struct il_rxon_context *ctx = &il->ctx; unsigned long flags = 0; int ret = 0; u16 ch; @@ -5259,7 +5226,7 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) * configured. */ if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx); + il->cfg->ops->hcmd->set_rxon_chain(il); } /* during scanning mac80211 will delay channel setting until @@ -5321,10 +5288,10 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) if ((le16_to_cpu(il->staging.channel) != ch)) il->staging.flags = 0; - il_set_rxon_channel(il, channel, ctx); + il_set_rxon_channel(il, channel); il_set_rxon_ht(il, ht_conf); - il_set_flags_for_band(il, ctx, channel->band, ctx->vif); + il_set_flags_for_band(il, channel->band, il->vif); spin_unlock_irqrestore(&il->lock, flags); @@ -5360,11 +5327,11 @@ set_ch_out: goto out; if (memcmp(&il->active, &il->staging, sizeof(il->staging))) - il_commit_rxon(il, ctx); + il_commit_rxon(il); else D_INFO("Not re-sending same RXON configuration.\n"); if (ht_changed) - il_update_qos(il, ctx); + il_update_qos(il); out: D_MAC80211("leave\n"); @@ -5378,7 +5345,6 @@ il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct il_priv *il = hw->priv; unsigned long flags; - struct il_rxon_context *ctx = &il->ctx; if (WARN_ON(!il->cfg->ops->legacy)) return; @@ -5413,7 +5379,7 @@ il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) * clear RXON_FILTER_ASSOC_MSK bit */ il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - il_commit_rxon(il, ctx); + il_commit_rxon(il); il_set_rate(il); @@ -5486,8 +5452,6 @@ il_ht_conf(struct il_priv *il, struct ieee80211_vif *vif) static inline void il_set_no_assoc(struct il_priv *il, struct ieee80211_vif *vif) { - struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); - /* * inform the ucode that there is no longer an * association and that no more packets should be @@ -5495,7 +5459,7 @@ il_set_no_assoc(struct il_priv *il, struct ieee80211_vif *vif) */ il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; il->staging.assoc_id = 0; - il_commit_rxon(il, ctx); + il_commit_rxon(il); } static void @@ -5513,8 +5477,8 @@ il_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) lockdep_assert_held(&il->mutex); - if (!il->beacon_ctx) { - IL_ERR("update beacon but no beacon context!\n"); + if (!il->beacon_enabled) { + IL_ERR("update beacon with no beaconing enabled\n"); dev_kfree_skb(skb); return; } @@ -5545,7 +5509,6 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes) { struct il_priv *il = hw->priv; - struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); int ret; if (WARN_ON(!il->cfg->ops->legacy)) @@ -5565,20 +5528,16 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, spin_lock_irqsave(&il->lock, flags); il->qos_data.qos_active = bss_conf->qos; - il_update_qos(il, ctx); + il_update_qos(il); spin_unlock_irqrestore(&il->lock, flags); } if (changes & BSS_CHANGED_BEACON_ENABLED) { - /* - * the add_interface code must make sure we only ever - * have a single interface that could be beaconing at - * any time. - */ + /* FIXME: can we remove beacon_enabled ? */ if (vif->bss_conf.enable_beacon) - il->beacon_ctx = ctx; + il->beacon_enabled = true; else - il->beacon_ctx = NULL; + il->beacon_enabled = false; } if (changes & BSS_CHANGED_BSSID) { @@ -5658,7 +5617,7 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, il_ht_conf(il, vif); if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il, ctx); + il->cfg->ops->hcmd->set_rxon_chain(il); } if (changes & BSS_CHANGED_ASSOC) { @@ -5674,7 +5633,7 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (changes && il_is_associated(il) && bss_conf->aid) { D_MAC80211("Changes (%#x) while associated\n", changes); - ret = il_send_rxon_assoc(il, ctx); + ret = il_send_rxon_assoc(il); if (!ret) { /* Sync active_rxon with latest change. */ memcpy((void *)&il->active, &il->staging, diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 51c1eecf751..746eec08886 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -146,7 +146,6 @@ struct il_queue { /* One for each TFD */ struct il_tx_info { struct sk_buff *skb; - struct il_rxon_context *ctx; }; /** @@ -741,7 +740,6 @@ struct il_station_entry { }; struct il_station_priv_common { - struct il_rxon_context *ctx; u8 sta_id; }; @@ -752,7 +750,6 @@ struct il_station_priv_common { * space for us to put data into. */ struct il_vif_priv { - struct il_rxon_context *ctx; u8 ibss_bssid_sta_id; }; @@ -1257,7 +1254,7 @@ struct il_priv { u8 ucode_write_complete; /* the image write is complete */ char firmware_name[25]; - struct il_rxon_context ctx; + struct ieee80211_vif *vif; struct il_qos_info qos_data; @@ -1426,7 +1423,7 @@ struct il_priv { struct work_struct rx_replenish; struct work_struct abort_scan; - struct il_rxon_context *beacon_ctx; + bool beacon_enabled; struct sk_buff *beacon_skb; struct work_struct tx_flush; @@ -1493,17 +1490,6 @@ il_tx_queue_get_hdr(struct il_priv *il, int txq_id, int idx) return NULL; } -static inline struct il_rxon_context * -il_rxon_ctx_from_vif(struct ieee80211_vif *vif) -{ - struct il_vif_priv *vif_priv = (void *)vif->drv_priv; - - return vif_priv->ctx; -} - -#define for_each_context(il, _ctx) \ - for (_ctx = &il->ctx; _ctx == &il->ctx; _ctx++) - static inline int il_is_associated(struct il_priv *il) { @@ -1585,10 +1571,9 @@ il_free_pages(struct il_priv *il, unsigned long page) #define IL_RX_BUF_SIZE_8K (8 * 1024) struct il_hcmd_ops { - int (*rxon_assoc) (struct il_priv *il, struct il_rxon_context *ctx); - int (*commit_rxon) (struct il_priv *il, struct il_rxon_context *ctx); - void (*set_rxon_chain) (struct il_priv *il, - struct il_rxon_context *ctx); + int (*rxon_assoc) (struct il_priv *il); + int (*commit_rxon) (struct il_priv *il); + void (*set_rxon_chain) (struct il_priv *il); }; struct il_hcmd_utils_ops { @@ -1811,20 +1796,17 @@ int il_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params); int il_mac_tx_last_beacon(struct ieee80211_hw *hw); -void il_set_rxon_hwcrypto(struct il_priv *il, struct il_rxon_context *ctx, - int hw_decrypt); -int il_check_rxon_cmd(struct il_priv *il, struct il_rxon_context *ctx); -int il_full_rxon_required(struct il_priv *il, struct il_rxon_context *ctx); -int il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch, - struct il_rxon_context *ctx); -void il_set_flags_for_band(struct il_priv *il, struct il_rxon_context *ctx, - enum ieee80211_band band, struct ieee80211_vif *vif); +void il_set_rxon_hwcrypto(struct il_priv *il, int hw_decrypt); +int il_check_rxon_cmd(struct il_priv *il); +int il_full_rxon_required(struct il_priv *il); +int il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch); +void il_set_flags_for_band(struct il_priv *il, enum ieee80211_band band, + struct ieee80211_vif *vif); u8 il_get_single_channel_number(struct il_priv *il, enum ieee80211_band band); void il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf); -bool il_is_ht40_tx_allowed(struct il_priv *il, struct il_rxon_context *ctx, +bool il_is_ht40_tx_allowed(struct il_priv *il, struct ieee80211_sta_ht_cap *ht_cap); -void il_connection_init_rx_config(struct il_priv *il, - struct il_rxon_context *ctx); +void il_connection_init_rx_config(struct il_priv *il); void il_set_rate(struct il_priv *il); int il_set_decrypted_flag(struct il_priv *il, struct ieee80211_hdr *hdr, u32 decrypt_res, struct ieee80211_rx_status *stats); @@ -1927,7 +1909,7 @@ int il_set_tx_power(struct il_priv *il, s8 tx_power, bool force); * Rate ******************************************************************************/ -u8 il_get_lowest_plcp(struct il_priv *il, struct il_rxon_context *ctx); +u8 il_get_lowest_plcp(struct il_priv *il); /******************************************************************************* * Scanning @@ -2014,10 +1996,10 @@ extern const struct dev_pm_ops il_pm_ops; ******************************************************/ void il4965_dump_nic_error_log(struct il_priv *il); #ifdef CONFIG_IWLEGACY_DEBUG -void il_print_rx_config_cmd(struct il_priv *il, struct il_rxon_context *ctx); +void il_print_rx_config_cmd(struct il_priv *il); #else static inline void -il_print_rx_config_cmd(struct il_priv *il, struct il_rxon_context *ctx) +il_print_rx_config_cmd(struct il_priv *il) { } #endif @@ -2106,17 +2088,18 @@ extern int il_send_stats_request(struct il_priv *il, u8 flags, bool clear); void il_apm_stop(struct il_priv *il); int il_apm_init(struct il_priv *il); -int il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx); +int il_send_rxon_timing(struct il_priv *il); + static inline int -il_send_rxon_assoc(struct il_priv *il, struct il_rxon_context *ctx) +il_send_rxon_assoc(struct il_priv *il) { - return il->cfg->ops->hcmd->rxon_assoc(il, ctx); + return il->cfg->ops->hcmd->rxon_assoc(il); } static inline int -il_commit_rxon(struct il_priv *il, struct il_rxon_context *ctx) +il_commit_rxon(struct il_priv *il) { - return il->cfg->ops->hcmd->commit_rxon(il, ctx); + return il->cfg->ops->hcmd->commit_rxon(il); } static inline const struct ieee80211_supported_band * @@ -2274,23 +2257,22 @@ il_clear_bits_prph(struct il_priv *il, u32 reg, u32 mask) (this is for the IBSS BSSID stations) */ #define IL_STA_BCAST BIT(4) /* this station is the special bcast station */ -void il_restore_stations(struct il_priv *il, struct il_rxon_context *ctx); -void il_clear_ucode_stations(struct il_priv *il, struct il_rxon_context *ctx); +void il_restore_stations(struct il_priv *il); +void il_clear_ucode_stations(struct il_priv *il); void il_dealloc_bcast_stations(struct il_priv *il); int il_get_free_ucode_key_idx(struct il_priv *il); int il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags); -int il_add_station_common(struct il_priv *il, struct il_rxon_context *ctx, - const u8 *addr, bool is_ap, +int il_add_station_common(struct il_priv *il, const u8 *addr, bool is_ap, struct ieee80211_sta *sta, u8 *sta_id_r); int il_remove_station(struct il_priv *il, const u8 sta_id, const u8 * addr); int il_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -u8 il_prep_station(struct il_priv *il, struct il_rxon_context *ctx, - const u8 *addr, bool is_ap, struct ieee80211_sta *sta); +u8 il_prep_station(struct il_priv *il, const u8 *addr, bool is_ap, + struct ieee80211_sta *sta); -int il_send_lq_cmd(struct il_priv *il, struct il_rxon_context *ctx, - struct il_link_quality_cmd *lq, u8 flags, bool init); +int il_send_lq_cmd(struct il_priv *il, struct il_link_quality_cmd *lq, + u8 flags, bool init); /** * il_clear_driver_stations - clear knowledge of all stations from driver @@ -2334,8 +2316,7 @@ il_sta_id(struct ieee80211_sta *sta) * inline wraps that pattern. */ static inline int -il_sta_id_or_broadcast(struct il_priv *il, struct il_rxon_context *context, - struct ieee80211_sta *sta) +il_sta_id_or_broadcast(struct il_priv *il, struct ieee80211_sta *sta) { int sta_id; -- cgit v1.2.3 From c39ae9fd505ae314a7a4a159a41e3e022cfa317f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:58 +0100 Subject: iwlegacy: move ops out of config Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 22 +++--- drivers/net/wireless/iwlegacy/3945.c | 13 ++-- drivers/net/wireless/iwlegacy/3945.h | 4 +- drivers/net/wireless/iwlegacy/4965-calib.c | 4 +- drivers/net/wireless/iwlegacy/4965-mac.c | 78 +++++++++++-------- drivers/net/wireless/iwlegacy/4965.c | 34 ++------- drivers/net/wireless/iwlegacy/4965.h | 3 +- drivers/net/wireless/iwlegacy/common.c | 115 +++++++++++------------------ drivers/net/wireless/iwlegacy/common.h | 8 +- drivers/net/wireless/iwlegacy/debug.c | 13 ++-- 10 files changed, 127 insertions(+), 167 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index b2e04c591c6..40ce692b2c9 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -618,8 +618,7 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ - il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, - 0); + il->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0); /* Set up TFD's 2nd entry to point directly to remainder of skb, * if any (802.11 null frames have no payload). */ @@ -628,8 +627,8 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) phys_addr = pci_map_single(il->pci_dev, skb->data + hdr_len, len, PCI_DMA_TODEVICE); - il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, - len, 0, U32_PAD(len)); + il->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0, + U32_PAD(len)); } /* Tell device the write idx *just past* this latest filled TFD */ @@ -2416,7 +2415,7 @@ __il3945_up(struct il_priv *il) /* load bootstrap state machine, * load bootstrap program into processor's memory, * prepare to load the "initialize" uCode */ - rc = il->cfg->ops->lib->load_ucode(il); + rc = il->ops->lib->load_ucode(il); if (rc) { IL_ERR("Unable to set up bootstrap uCode: %d\n", rc); @@ -3458,7 +3457,7 @@ static struct attribute_group il3945_attribute_group = { .attrs = il3945_sysfs_entries, }; -struct ieee80211_ops il3945_hw_ops = { +struct ieee80211_ops il3945_mac_ops = { .tx = il3945_mac_tx, .start = il3945_mac_start, .stop = il3945_mac_stop, @@ -3599,15 +3598,13 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * 1. Allocating HW data * ********************/ - /* mac80211 allocates memory for this device instance, including - * space for this driver's ilate structure */ - hw = il_alloc_all(cfg); - if (hw == NULL) { - pr_err("Can not allocate network device\n"); + hw = ieee80211_alloc_hw(sizeof(struct il_priv), &il3945_mac_ops); + if (!hw) { err = -ENOMEM; goto out; } il = hw->priv; + il->hw = hw; SET_IEEE80211_DEV(hw, &pdev->dev); il->cmd_queue = IL39_CMD_QUEUE_NUM; @@ -3618,11 +3615,12 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ if (il3945_mod_params.disable_hw_scan) { D_INFO("Disabling hw_scan\n"); - il3945_hw_ops.hw_scan = NULL; + il3945_mac_ops.hw_scan = NULL; } D_INFO("*** LOAD DRIVER ***\n"); il->cfg = cfg; + il->ops = &il3945_ops; il->pci_dev = pdev; il->inta_mask = CSR_INI_SET_MASK; diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index 1e617c9fc3c..918cbefd657 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -303,7 +303,7 @@ il3945_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx) tx_info = &txq->txb[txq->q.read_ptr]; ieee80211_tx_status_irqsafe(il->hw, tx_info->skb); tx_info->skb = NULL; - il->cfg->ops->lib->txq_free_tfd(il, txq); + il->ops->lib->txq_free_tfd(il, txq); } if (il_queue_space(q) > q->low_mark && txq_id >= 0 && @@ -960,12 +960,12 @@ il3945_hw_nic_init(struct il_priv *il) struct il_rx_queue *rxq = &il->rxq; spin_lock_irqsave(&il->lock, flags); - il->cfg->ops->lib->apm_ops.init(il); + il->ops->lib->apm_ops.init(il); spin_unlock_irqrestore(&il->lock, flags); il3945_set_pwr_vmain(il); - il->cfg->ops->lib->apm_ops.config(il); + il->ops->lib->apm_ops.config(il); /* Allocate the RX queue, or reset if it is already allocated */ if (!rxq->bd) { @@ -1615,7 +1615,7 @@ il3945_hw_reg_comp_txpower_temp(struct il_priv *il) } /* send Txpower command for current channel to ucode */ - return il->cfg->ops->lib->send_tx_power(il); + return il->ops->lib->send_tx_power(il); } int @@ -2685,13 +2685,12 @@ static struct il_hcmd_utils_ops il3945_hcmd_utils = { .post_scan = il3945_post_scan, }; -static const struct il_ops il3945_ops = { +const struct il_ops il3945_ops = { .lib = &il3945_lib, .hcmd = &il3945_hcmd, .utils = &il3945_hcmd_utils, .led = &il3945_led_ops, .legacy = &il3945_legacy_ops, - .ieee80211_ops = &il3945_hw_ops, }; static struct il_base_params il3945_base_params = { @@ -2711,7 +2710,6 @@ static struct il_cfg il3945_bg_cfg = { .ucode_api_min = IL3945_UCODE_API_MIN, .sku = IL_SKU_G, .eeprom_ver = EEPROM_3945_EEPROM_VERSION, - .ops = &il3945_ops, .mod_params = &il3945_mod_params, .base_params = &il3945_base_params, .led_mode = IL_LED_BLINK, @@ -2724,7 +2722,6 @@ static struct il_cfg il3945_abg_cfg = { .ucode_api_min = IL3945_UCODE_API_MIN, .sku = IL_SKU_A | IL_SKU_G, .eeprom_ver = EEPROM_3945_EEPROM_VERSION, - .ops = &il3945_ops, .mod_params = &il3945_mod_params, .base_params = &il3945_base_params, .led_mode = IL_LED_BLINK, diff --git a/drivers/net/wireless/iwlegacy/3945.h b/drivers/net/wireless/iwlegacy/3945.h index 8bee127d413..c00a8d30b6f 100644 --- a/drivers/net/wireless/iwlegacy/3945.h +++ b/drivers/net/wireless/iwlegacy/3945.h @@ -36,6 +36,8 @@ extern const struct pci_device_id il3945_hw_card_ids[]; #include "common.h" +extern const struct il_ops il3945_ops; + /* Highest firmware API version supported */ #define IL3945_UCODE_API_MAX 2 @@ -261,8 +263,6 @@ extern int il3945_commit_rxon(struct il_priv *il); */ extern u8 il3945_hw_find_station(struct il_priv *il, const u8 * bssid); -extern struct ieee80211_ops il3945_hw_ops; - extern __le32 il3945_get_antenna_flags(const struct il_priv *il); extern int il3945_init_hw_rate_table(struct il_priv *il); extern void il3945_reg_txpower_periodic(struct il_priv *il); diff --git a/drivers/net/wireless/iwlegacy/4965-calib.c b/drivers/net/wireless/iwlegacy/4965-calib.c index f302a6ac628..bfb361dbba5 100644 --- a/drivers/net/wireless/iwlegacy/4965-calib.c +++ b/drivers/net/wireless/iwlegacy/4965-calib.c @@ -923,8 +923,8 @@ il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp) /* Some power changes may have been made during the calibration. * Update and commit the RXON */ - if (il->cfg->ops->lib->update_chain_flags) - il->cfg->ops->lib->update_chain_flags(il); + if (il->ops->lib->update_chain_flags) + il->ops->lib->update_chain_flags(il); data->state = IL_CHAIN_NOISE_DONE; il_power_update_mode(il, false); diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 4be53cc9198..2bf743fc782 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -201,7 +201,7 @@ il4965_hw_nic_init(struct il_priv *il) /* nic_init */ spin_lock_irqsave(&il->lock, flags); - il->cfg->ops->lib->apm_ops.init(il); + il->ops->lib->apm_ops.init(il); /* Set interrupt coalescing calibration timer to default (512 usecs) */ il_write8(il, CSR_INT_COALESCING, IL_HOST_INT_CALIB_TIMEOUT_DEF); @@ -210,7 +210,7 @@ il4965_hw_nic_init(struct il_priv *il) il4965_set_pwr_vmain(il); - il->cfg->ops->lib->apm_ops.config(il); + il->ops->lib->apm_ops.config(il); /* Allocate the RX queue, or reset if it is already allocated */ if (!rxq->bd) { @@ -1381,8 +1381,8 @@ il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb) il4965_rx_calc_noise(il); queue_work(il->workqueue, &il->run_time_calib_work); } - if (il->cfg->ops->lib->temp_ops.temperature && change) - il->cfg->ops->lib->temp_ops.temperature(il); + if (il->ops->lib->temp_ops.temperature && change) + il->ops->lib->temp_ops.temperature(il); } void @@ -1817,8 +1817,7 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) dma_unmap_len_set(out_meta, len, firstlen); /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ - il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, - 1, 0); + il->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0); if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; @@ -1834,8 +1833,8 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) phys_addr = pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen, PCI_DMA_TODEVICE); - il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, - secondlen, 0, 0); + il->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, + secondlen, 0, 0); } scratch_phys = @@ -1855,9 +1854,8 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) /* Set up entry for this TFD in Tx byte-count array */ if (info->flags & IEEE80211_TX_CTL_AMPDU) - il->cfg->ops->lib->txq_update_byte_cnt_tbl(il, txq, - le16_to_cpu(tx_cmd-> - len)); + il->ops->lib->txq_update_byte_cnt_tbl(il, txq, + le16_to_cpu(tx_cmd->len)); pci_dma_sync_single_for_device(il->pci_dev, txcmd_phys, firstlen, PCI_DMA_BIDIRECTIONAL); @@ -2479,7 +2477,7 @@ il4965_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx) txq_id >= IL4965_FIRST_AMPDU_QUEUE); tx_info->skb = NULL; - il->cfg->ops->lib->txq_free_tfd(il, txq); + il->ops->lib->txq_free_tfd(il, txq); } return nfreed; } @@ -3357,8 +3355,8 @@ il4965_sta_modify_sleep_tx_count(struct il_priv *il, int sta_id, int cnt) void il4965_update_chain_flags(struct il_priv *il) { - if (il->cfg->ops->hcmd->set_rxon_chain) { - il->cfg->ops->hcmd->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) { + il->ops->hcmd->set_rxon_chain(il); if (il->active.rx_chain != il->staging.rx_chain) il_commit_rxon(il); } @@ -3878,7 +3876,7 @@ il4965_setup_handlers(struct il_priv *il) /* block ack */ il->handlers[N_COMPRESSED_BA] = il4965_hdl_compressed_ba; /* Set up hardware specific Rx handlers */ - il->cfg->ops->lib->handler_setup(il); + il->ops->lib->handler_setup(il); } /** @@ -4780,7 +4778,7 @@ il4965_dump_nic_error_log(struct il_priv *il) else base = le32_to_cpu(il->card_alive.error_event_table_ptr); - if (!il->cfg->ops->lib->is_valid_rtc_data_addr(base)) { + if (!il->ops->lib->is_valid_rtc_data_addr(base)) { IL_ERR("Not valid error log pointer 0x%08X for %s uCode\n", base, (il->ucode_type == UCODE_INIT) ? "Init" : "RT"); return; @@ -5009,8 +5007,8 @@ il4965_alive_start(struct il_priv *il) /* Initialize our rx_config data */ il_connection_init_rx_config(il); - if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); } /* Configure bluetooth coexistence if enabled */ @@ -5282,7 +5280,7 @@ __il4965_up(struct il_priv *il) /* load bootstrap state machine, * load bootstrap program into processor's memory, * prepare to load the "initialize" uCode */ - ret = il->cfg->ops->lib->load_ucode(il); + ret = il->ops->lib->load_ucode(il); if (ret) { IL_ERR("Unable to set up bootstrap uCode: %d\n", ret); @@ -5323,7 +5321,7 @@ il4965_bg_init_alive_start(struct work_struct *data) if (test_bit(S_EXIT_PENDING, &il->status)) goto out; - il->cfg->ops->lib->init_alive_start(il); + il->ops->lib->init_alive_start(il); out: mutex_unlock(&il->mutex); } @@ -5755,7 +5753,7 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, if (!il_is_associated(il)) goto out; - if (!il->cfg->ops->lib->set_channel_switch) + if (!il->ops->lib->set_channel_switch) goto out; ch = channel->hw_value; @@ -5807,7 +5805,7 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, */ set_bit(S_CHANNEL_SWITCH_PENDING, &il->status); il->switch_channel = cpu_to_le16(ch); - if (il->cfg->ops->lib->set_channel_switch(il, ch_switch)) { + if (il->ops->lib->set_channel_switch(il, ch_switch)) { clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status); il->switch_channel = 0; ieee80211_chswitch_done(il->vif, false); @@ -5890,7 +5888,7 @@ il4965_bg_txpower_work(struct work_struct *work) /* Regardless of if we are associated, we must reconfigure the * TX power since frames can be sent on non-radar channels while * not associated */ - il->cfg->ops->lib->send_tx_power(il); + il->ops->lib->send_tx_power(il); /* Update last_temperature to keep is_calib_needed from running * when it isn't needed... */ @@ -5996,6 +5994,28 @@ il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq, scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); } +const struct ieee80211_ops il4965_mac_ops = { + .tx = il4965_mac_tx, + .start = il4965_mac_start, + .stop = il4965_mac_stop, + .add_interface = il_mac_add_interface, + .remove_interface = il_mac_remove_interface, + .change_interface = il_mac_change_interface, + .config = il_mac_config, + .configure_filter = il4965_configure_filter, + .set_key = il4965_mac_set_key, + .update_tkip_key = il4965_mac_update_tkip_key, + .conf_tx = il_mac_conf_tx, + .reset_tsf = il_mac_reset_tsf, + .bss_info_changed = il_mac_bss_info_changed, + .ampdu_action = il4965_mac_ampdu_action, + .hw_scan = il_mac_hw_scan, + .sta_add = il4965_mac_sta_add, + .sta_remove = il_mac_sta_remove, + .channel_switch = il4965_mac_channel_switch, + .tx_last_beacon = il_mac_tx_last_beacon, +}; + static int il4965_init_drv(struct il_priv *il) { @@ -6020,8 +6040,8 @@ il4965_init_drv(struct il_priv *il) il->force_reset.reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD; /* Choose which receivers/antennas to use */ - if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); il_init_scan_params(il); @@ -6081,7 +6101,7 @@ il4965_set_hw_params(struct il_priv *il) il->cfg->sku &= ~IL_SKU_N; /* Device-specific setup */ - return il->cfg->ops->lib->set_hw_params(il); + return il->ops->lib->set_hw_params(il); } static int @@ -6098,18 +6118,18 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * 1. Allocating HW data ************************/ - hw = il_alloc_all(cfg); + hw = ieee80211_alloc_hw(sizeof(struct il_priv), &il4965_mac_ops); if (!hw) { err = -ENOMEM; goto out; } il = hw->priv; - /* At this point both hw and il are allocated. */ - + il->hw = hw; SET_IEEE80211_DEV(hw, &pdev->dev); D_INFO("*** LOAD DRIVER ***\n"); il->cfg = cfg; + il->ops = &il4965_ops; il->pci_dev = pdev; il->inta_mask = CSR_INI_SET_MASK; diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index 9d9197f7fa3..27feb533d02 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c @@ -2166,8 +2166,8 @@ il4965_post_associate(struct il_priv *il) il_set_rxon_ht(il, &il->current_ht_config); - if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); il->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); @@ -2241,8 +2241,8 @@ il4965_config_ap(struct il_priv *il) /* AP has all antennas */ il->chain_noise_data.active_chains = il->hw_params.valid_rx_ant; il_set_rxon_ht(il, &il->current_ht_config); - if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); il->staging.assoc_id = 0; @@ -2323,35 +2323,12 @@ static const struct il_legacy_ops il4965_legacy_ops = { .update_bcast_stations = il4965_update_bcast_stations, }; -struct ieee80211_ops il4965_hw_ops = { - .tx = il4965_mac_tx, - .start = il4965_mac_start, - .stop = il4965_mac_stop, - .add_interface = il_mac_add_interface, - .remove_interface = il_mac_remove_interface, - .change_interface = il_mac_change_interface, - .config = il_mac_config, - .configure_filter = il4965_configure_filter, - .set_key = il4965_mac_set_key, - .update_tkip_key = il4965_mac_update_tkip_key, - .conf_tx = il_mac_conf_tx, - .reset_tsf = il_mac_reset_tsf, - .bss_info_changed = il_mac_bss_info_changed, - .ampdu_action = il4965_mac_ampdu_action, - .hw_scan = il_mac_hw_scan, - .sta_add = il4965_mac_sta_add, - .sta_remove = il_mac_sta_remove, - .channel_switch = il4965_mac_channel_switch, - .tx_last_beacon = il_mac_tx_last_beacon, -}; - -static const struct il_ops il4965_ops = { +const struct il_ops il4965_ops = { .lib = &il4965_lib, .hcmd = &il4965_hcmd, .utils = &il4965_hcmd_utils, .led = &il4965_led_ops, .legacy = &il4965_legacy_ops, - .ieee80211_ops = &il4965_hw_ops, }; static struct il_base_params il4965_base_params = { @@ -2380,7 +2357,6 @@ struct il_cfg il4965_cfg = { .valid_rx_ant = ANT_ABC, .eeprom_ver = EEPROM_4965_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, - .ops = &il4965_ops, .mod_params = &il4965_mod_params, .base_params = &il4965_base_params, .led_mode = IL_LED_BLINK, diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index 67899602ee5..83ab6049638 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h @@ -38,11 +38,10 @@ struct il_rxon_context; /* configuration for the _4965 devices */ extern struct il_cfg il4965_cfg; +extern const struct il_ops il4965_ops; extern struct il_mod_params il4965_mod_params; -extern struct ieee80211_ops il4965_hw_ops; - /* tx queue */ void il4965_free_tfds_in_queue(struct il_priv *il, int sta_id, int tid, int freed); diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index bee11a3aeac..3bd18333656 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -520,7 +520,7 @@ il_led_cmd(struct il_priv *il, unsigned long on, unsigned long off) il_blink_compensation(il, off, il->cfg->base_params->led_compensation); - ret = il->cfg->ops->led->cmd(il, &led_cmd); + ret = il->ops->led->cmd(il, &led_cmd); if (!ret) { il->blink_on = on; il->blink_off = off; @@ -731,7 +731,7 @@ il_eeprom_init(struct il_priv *il) } e = (__le16 *) il->eeprom; - il->cfg->ops->lib->apm_ops.init(il); + il->ops->lib->apm_ops.init(il); ret = il_eeprom_verify_signature(il); if (ret < 0) { @@ -741,7 +741,7 @@ il_eeprom_init(struct il_priv *il) } /* Make sure driver (instead of uCode) is allowed to read EEPROM */ - ret = il->cfg->ops->lib->eeprom_ops.acquire_semaphore(il); + ret = il->ops->lib->eeprom_ops.acquire_semaphore(il); if (ret < 0) { IL_ERR("Failed to acquire EEPROM semaphore.\n"); ret = -ENOENT; @@ -773,7 +773,7 @@ il_eeprom_init(struct il_priv *il) ret = 0; done: - il->cfg->ops->lib->eeprom_ops.release_semaphore(il); + il->ops->lib->eeprom_ops.release_semaphore(il); err: if (ret) @@ -800,7 +800,7 @@ il_init_band_reference(const struct il_priv *il, int eep_band, const u8 **eeprom_ch_idx) { u32 offset = - il->cfg->ops->lib->eeprom_ops.regulatory_bands[eep_band - 1]; + il->ops->lib->eeprom_ops.regulatory_bands[eep_band - 1]; switch (eep_band) { case 1: /* 2.4GHz band */ *eeprom_ch_count = ARRAY_SIZE(il_eeprom_band_1); @@ -1001,9 +1001,9 @@ il_init_channel_map(struct il_priv *il) } /* Check if we do have HT40 channels */ - if (il->cfg->ops->lib->eeprom_ops.regulatory_bands[5] == + if (il->ops->lib->eeprom_ops.regulatory_bands[5] == EEPROM_REGULATORY_BAND_NO_HT40 && - il->cfg->ops->lib->eeprom_ops.regulatory_bands[6] == + il->ops->lib->eeprom_ops.regulatory_bands[6] == EEPROM_REGULATORY_BAND_NO_HT40) return 0; @@ -1158,9 +1158,9 @@ il_power_set_mode(struct il_priv *il, struct il_powertable_cmd *cmd, bool force) if (!(cmd->flags & IL_POWER_DRIVER_ALLOW_SLEEP_MSK)) clear_bit(S_POWER_PMI, &il->status); - if (il->cfg->ops->lib->update_chain_flags && update_chains) - il->cfg->ops->lib->update_chain_flags(il); - else if (il->cfg->ops->lib->update_chain_flags) + if (il->ops->lib->update_chain_flags && update_chains) + il->ops->lib->update_chain_flags(il); + else if (il->ops->lib->update_chain_flags) D_POWER("Cannot update the power, chain noise " "calibration running: %d\n", il->chain_noise_data.state); @@ -1485,7 +1485,7 @@ il_scan_initiate(struct il_priv *il, struct ieee80211_vif *vif) lockdep_assert_held(&il->mutex); - if (WARN_ON(!il->cfg->ops->utils->request_scan)) + if (WARN_ON(!il->ops->utils->request_scan)) return -EOPNOTSUPP; cancel_delayed_work(&il->scan_check); @@ -1510,7 +1510,7 @@ il_scan_initiate(struct il_priv *il, struct ieee80211_vif *vif) set_bit(S_SCANNING, &il->status); il->scan_start = jiffies; - ret = il->cfg->ops->utils->request_scan(il, vif); + ret = il->ops->utils->request_scan(il, vif); if (ret) { clear_bit(S_SCANNING, &il->status); return ret; @@ -1672,7 +1672,7 @@ out_settings: il_power_set_mode(il, &il->power_data.sleep_cmd_next, false); il_set_tx_power(il, il->tx_power_next, false); - il->cfg->ops->utils->post_scan(il); + il->ops->utils->post_scan(il); out: mutex_unlock(&il->mutex); @@ -1814,7 +1814,7 @@ il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags) might_sleep(); } - cmd.len = il->cfg->ops->utils->build_addsta_hcmd(sta, data); + cmd.len = il->ops->utils->build_addsta_hcmd(sta, data); ret = il_send_cmd(il, &cmd); if (ret || (flags & CMD_ASYNC)) @@ -2722,7 +2722,7 @@ il_tx_queue_unmap(struct il_priv *il, int txq_id) return; while (q->write_ptr != q->read_ptr) { - il->cfg->ops->lib->txq_free_tfd(il, txq); + il->ops->lib->txq_free_tfd(il, txq); q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd); } } @@ -3024,7 +3024,7 @@ il_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq, int slots_num, il_queue_init(il, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); /* Tell device where to find queue */ - il->cfg->ops->lib->txq_init(il, txq); + il->ops->lib->txq_init(il, txq); return 0; err: @@ -3055,7 +3055,7 @@ il_tx_queue_reset(struct il_priv *il, struct il_tx_queue *txq, int slots_num, il_queue_init(il, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); /* Tell device where to find queue */ - il->cfg->ops->lib->txq_init(il, txq); + il->ops->lib->txq_init(il, txq); } EXPORT_SYMBOL(il_tx_queue_reset); @@ -3083,7 +3083,7 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) u32 idx; u16 fix_size; - cmd->len = il->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); + cmd->len = il->ops->utils->get_hcmd_size(cmd->id, cmd->len); fix_size = (u16) (cmd->len + sizeof(out_cmd->hdr)); /* If any of the command structures end up being larger than @@ -3162,9 +3162,9 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) #endif txq->need_update = 1; - if (il->cfg->ops->lib->txq_update_byte_cnt_tbl) + if (il->ops->lib->txq_update_byte_cnt_tbl) /* Set up entry in queue's byte count circular buffer */ - il->cfg->ops->lib->txq_update_byte_cnt_tbl(il, txq, 0); + il->ops->lib->txq_update_byte_cnt_tbl(il, txq, 0); phys_addr = pci_map_single(il->pci_dev, &out_cmd->hdr, fix_size, @@ -3172,8 +3172,8 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) dma_unmap_addr_set(out_meta, mapping, phys_addr); dma_unmap_len_set(out_meta, len, fix_size); - il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, fix_size, - 1, U32_PAD(cmd->len)); + il->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, fix_size, 1, + U32_PAD(cmd->len)); /* Increment and update queue's write idx */ q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd); @@ -3315,30 +3315,6 @@ EXPORT_SYMBOL(il_debug_level); const u8 il_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; EXPORT_SYMBOL(il_bcast_addr); -/* This function both allocates and initializes hw and il. */ -struct ieee80211_hw * -il_alloc_all(struct il_cfg *cfg) -{ - struct il_priv *il; - /* mac80211 allocates memory for this device instance, including - * space for this driver's ilate structure */ - struct ieee80211_hw *hw; - - hw = ieee80211_alloc_hw(sizeof(struct il_priv), - cfg->ops->ieee80211_ops); - if (hw == NULL) { - pr_err("%s: Can not allocate network device\n", cfg->name); - goto out; - } - - il = hw->priv; - il->hw = hw; - -out: - return hw; -} -EXPORT_SYMBOL(il_alloc_all); - #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ static void @@ -3871,8 +3847,8 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf) rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY; } - if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); D_ASSOC("rxon flags 0x%X operation mode :0x%X " "extension channel offset 0x%x\n", le32_to_cpu(rxon->flags), @@ -4130,9 +4106,9 @@ il_irq_handle_error(struct il_priv *il) IL_ERR("Loaded firmware version: %s\n", il->hw->wiphy->fw_version); - il->cfg->ops->lib->dump_nic_error_log(il); - if (il->cfg->ops->lib->dump_fh) - il->cfg->ops->lib->dump_fh(il, NULL, false); + il->ops->lib->dump_nic_error_log(il); + if (il->ops->lib->dump_fh) + il->ops->lib->dump_fh(il, NULL, false); #ifdef CONFIG_IWLEGACY_DEBUG if (il_get_debug_level(il) & IL_DL_FW_ERRORS) il_print_rx_config_cmd(il); @@ -4319,7 +4295,7 @@ il_set_tx_power(struct il_priv *il, s8 tx_power, bool force) if (il->tx_power_user_lmt == tx_power && !force) return 0; - if (!il->cfg->ops->lib->send_tx_power) + if (!il->ops->lib->send_tx_power) return -EOPNOTSUPP; /* 0 dBm mean 1 milliwatt */ @@ -4352,7 +4328,7 @@ il_set_tx_power(struct il_priv *il, s8 tx_power, bool force) prev_tx_power = il->tx_power_user_lmt; il->tx_power_user_lmt = tx_power; - ret = il->cfg->ops->lib->send_tx_power(il); + ret = il->ops->lib->send_tx_power(il); /* if fail to set tx_power, restore the orig. tx power */ if (ret) { @@ -4501,8 +4477,8 @@ il_set_mode(struct il_priv *il) { il_connection_init_rx_config(il); - if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); return il_commit_rxon(il); } @@ -5200,7 +5176,7 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) int scan_active = 0; bool ht_changed = false; - if (WARN_ON(!il->cfg->ops->legacy)) + if (WARN_ON(!il->ops->legacy)) return -EOPNOTSUPP; mutex_lock(&il->mutex); @@ -5225,8 +5201,8 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) * set up the SM PS mode to OFF if an HT channel is * configured. */ - if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); } /* during scanning mac80211 will delay channel setting until @@ -5295,8 +5271,8 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) spin_unlock_irqrestore(&il->lock, flags); - if (il->cfg->ops->legacy->update_bcast_stations) - ret = il->cfg->ops->legacy->update_bcast_stations(il); + if (il->ops->legacy->update_bcast_stations) + ret = il->ops->legacy->update_bcast_stations(il); set_ch_out: /* The list of supported rates and rate mask can be different @@ -5346,7 +5322,7 @@ il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct il_priv *il = hw->priv; unsigned long flags; - if (WARN_ON(!il->cfg->ops->legacy)) + if (WARN_ON(!il->ops->legacy)) return; mutex_lock(&il->mutex); @@ -5501,7 +5477,7 @@ il_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return; } - il->cfg->ops->legacy->post_associate(il); + il->ops->legacy->post_associate(il); } void @@ -5511,7 +5487,7 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct il_priv *il = hw->priv; int ret; - if (WARN_ON(!il->cfg->ops->legacy)) + if (WARN_ON(!il->ops->legacy)) return; D_MAC80211("changes = 0x%X\n", changes); @@ -5616,8 +5592,8 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (changes & BSS_CHANGED_HT) { il_ht_conf(il, vif); - if (il->cfg->ops->hcmd->set_rxon_chain) - il->cfg->ops->hcmd->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); } if (changes & BSS_CHANGED_ASSOC) { @@ -5626,7 +5602,7 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, il->timestamp = bss_conf->timestamp; if (!il_is_rfkill(il)) - il->cfg->ops->legacy->post_associate(il); + il->ops->legacy->post_associate(il); } else il_set_no_assoc(il, vif); } @@ -5646,16 +5622,15 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, memcpy(il->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); - il->cfg->ops->legacy->config_ap(il); + il->ops->legacy->config_ap(il); } else il_set_no_assoc(il, vif); } if (changes & BSS_CHANGED_IBSS) { ret = - il->cfg->ops->legacy->manage_ibss_station(il, vif, - bss_conf-> - ibss_joined); + il->ops->legacy->manage_ibss_station(il, vif, + bss_conf->ibss_joined); if (ret) IL_ERR("failed to %s IBSS station %pM\n", bss_conf->ibss_joined ? "add" : "remove", diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 746eec08886..2af861062de 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1167,6 +1167,7 @@ struct il_priv { struct ieee80211_channel *ieee_channels; struct ieee80211_rate *ieee_rates; struct il_cfg *cfg; + const struct il_ops *ops; /* temporary frame storage list */ struct list_head free_frames; @@ -1668,7 +1669,6 @@ struct il_ops { const struct il_led_ops *led; const struct il_nic_ops *nic; const struct il_legacy_ops *legacy; - const struct ieee80211_ops *ieee80211_ops; }; struct il_mod_params { @@ -1777,7 +1777,6 @@ struct il_cfg { unsigned int sku; u16 eeprom_ver; u16 eeprom_calib_ver; - const struct il_ops *ops; /* module based parameters which can be set from modprobe cmd */ const struct il_mod_params *mod_params; /* params not likely to change within a device family */ @@ -1791,7 +1790,6 @@ struct il_cfg { * L i b * ***************************/ -struct ieee80211_hw *il_alloc_all(struct il_cfg *cfg); int il_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params); int il_mac_tx_last_beacon(struct ieee80211_hw *hw); @@ -2093,13 +2091,13 @@ int il_send_rxon_timing(struct il_priv *il); static inline int il_send_rxon_assoc(struct il_priv *il) { - return il->cfg->ops->hcmd->rxon_assoc(il); + return il->ops->hcmd->rxon_assoc(il); } static inline int il_commit_rxon(struct il_priv *il) { - return il->cfg->ops->hcmd->commit_rxon(il); + return il->ops->hcmd->commit_rxon(il); } static inline const struct ieee80211_supported_band * diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c index 3a9609a8874..4fb769caef5 100644 --- a/drivers/net/wireless/iwlegacy/debug.c +++ b/drivers/net/wireless/iwlegacy/debug.c @@ -901,8 +901,7 @@ il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct il_priv *il = file->private_data; - return il->cfg->ops->lib->debugfs_ops.rx_stats_read(file, user_buf, - count, ppos); + return il->ops->lib->debugfs_ops.rx_stats_read(file, user_buf, count, ppos); } static ssize_t @@ -910,8 +909,7 @@ il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct il_priv *il = file->private_data; - return il->cfg->ops->lib->debugfs_ops.tx_stats_read(file, user_buf, - count, ppos); + return il->ops->lib->debugfs_ops.tx_stats_read(file, user_buf, count, ppos); } static ssize_t @@ -919,8 +917,7 @@ il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct il_priv *il = file->private_data; - return il->cfg->ops->lib->debugfs_ops.general_stats_read(file, user_buf, - count, ppos); + return il->ops->lib->debugfs_ops.general_stats_read(file, user_buf, count, ppos); } static ssize_t @@ -1178,8 +1175,8 @@ il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count, int pos = 0; ssize_t ret = -EFAULT; - if (il->cfg->ops->lib->dump_fh) { - ret = pos = il->cfg->ops->lib->dump_fh(il, &buf, true); + if (il->ops->lib->dump_fh) { + ret = pos = il->ops->lib->dump_fh(il, &buf, true); if (buf) { ret = simple_read_from_buffer(user_buf, count, ppos, buf, -- cgit v1.2.3 From 89ef1ed2d241d3dfe884055d8446a5dd94919e54 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:31:59 +0100 Subject: iwlegacy: merge il_base_params into il_cfg Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945.c | 30 +++++++++++++----------- drivers/net/wireless/iwlegacy/4965-calib.c | 14 +++++------ drivers/net/wireless/iwlegacy/4965-mac.c | 8 +++---- drivers/net/wireless/iwlegacy/4965.c | 37 ++++++++++++++---------------- drivers/net/wireless/iwlegacy/common.c | 28 +++++++++++----------- drivers/net/wireless/iwlegacy/common.h | 31 +++++++++++++------------ drivers/net/wireless/iwlegacy/debug.c | 16 ++++++------- 7 files changed, 83 insertions(+), 81 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index 918cbefd657..7c21a57d1bb 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -2398,7 +2398,7 @@ il3945_hw_set_hw_params(struct il_priv *il) il->hw_params.bcast_id = IL3945_BROADCAST_ID; /* Assign number of Usable TX queues */ - il->hw_params.max_txq_num = il->cfg->base_params->num_of_queues; + il->hw_params.max_txq_num = il->cfg->num_of_queues; il->hw_params.tfd_size = sizeof(struct il3945_tfd); il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_3K); @@ -2693,16 +2693,6 @@ const struct il_ops il3945_ops = { .legacy = &il3945_legacy_ops, }; -static struct il_base_params il3945_base_params = { - .eeprom_size = IL3945_EEPROM_IMG_SIZE, - .num_of_queues = IL39_NUM_QUEUES, - .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, - .set_l0s = false, - .use_bsm = true, - .led_compensation = 64, - .wd_timeout = IL_DEF_WD_TIMEOUT, -}; - static struct il_cfg il3945_bg_cfg = { .name = "3945BG", .fw_name_pre = IL3945_FW_PRE, @@ -2711,8 +2701,15 @@ static struct il_cfg il3945_bg_cfg = { .sku = IL_SKU_G, .eeprom_ver = EEPROM_3945_EEPROM_VERSION, .mod_params = &il3945_mod_params, - .base_params = &il3945_base_params, .led_mode = IL_LED_BLINK, + + .eeprom_size = IL3945_EEPROM_IMG_SIZE, + .num_of_queues = IL39_NUM_QUEUES, + .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, + .set_l0s = false, + .use_bsm = true, + .led_compensation = 64, + .wd_timeout = IL_DEF_WD_TIMEOUT }; static struct il_cfg il3945_abg_cfg = { @@ -2723,8 +2720,15 @@ static struct il_cfg il3945_abg_cfg = { .sku = IL_SKU_A | IL_SKU_G, .eeprom_ver = EEPROM_3945_EEPROM_VERSION, .mod_params = &il3945_mod_params, - .base_params = &il3945_base_params, .led_mode = IL_LED_BLINK, + + .eeprom_size = IL3945_EEPROM_IMG_SIZE, + .num_of_queues = IL39_NUM_QUEUES, + .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, + .set_l0s = false, + .use_bsm = true, + .led_compensation = 64, + .wd_timeout = IL_DEF_WD_TIMEOUT }; DEFINE_PCI_DEVICE_TABLE(il3945_hw_card_ids) = { diff --git a/drivers/net/wireless/iwlegacy/4965-calib.c b/drivers/net/wireless/iwlegacy/4965-calib.c index bfb361dbba5..fe9171506a9 100644 --- a/drivers/net/wireless/iwlegacy/4965-calib.c +++ b/drivers/net/wireless/iwlegacy/4965-calib.c @@ -627,13 +627,13 @@ il4965_find_disconn_antenna(struct il_priv *il, u32 * average_sig, average_sig[0] = data->chain_signal_a / - il->cfg->base_params->chain_noise_num_beacons; + il->cfg->chain_noise_num_beacons; average_sig[1] = data->chain_signal_b / - il->cfg->base_params->chain_noise_num_beacons; + il->cfg->chain_noise_num_beacons; average_sig[2] = data->chain_signal_c / - il->cfg->base_params->chain_noise_num_beacons; + il->cfg->chain_noise_num_beacons; if (average_sig[0] >= average_sig[1]) { max_average_sig = average_sig[0]; @@ -886,7 +886,7 @@ il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp) /* If this is the "chain_noise_num_beacons", determine: * 1) Disconnected antennas (using signal strengths) * 2) Differential gain (using silence noise) to balance receivers */ - if (data->beacon_count != il->cfg->base_params->chain_noise_num_beacons) + if (data->beacon_count != il->cfg->chain_noise_num_beacons) return; /* Analyze signal for disconnected antenna */ @@ -894,11 +894,11 @@ il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp) /* Analyze noise for rx balance */ average_noise[0] = - data->chain_noise_a / il->cfg->base_params->chain_noise_num_beacons; + data->chain_noise_a / il->cfg->chain_noise_num_beacons; average_noise[1] = - data->chain_noise_b / il->cfg->base_params->chain_noise_num_beacons; + data->chain_noise_b / il->cfg->chain_noise_num_beacons; average_noise[2] = - data->chain_noise_c / il->cfg->base_params->chain_noise_num_beacons; + data->chain_noise_c / il->cfg->chain_noise_num_beacons; for (i = 0; i < NUM_RX_CHAINS; i++) { if (!data->disconn_array[i] && diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 2bf743fc782..49dd1e0e9a5 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -2150,11 +2150,11 @@ il4965_txq_agg_enable(struct il_priv *il, int txq_id, int tx_fifo, int sta_id, if ((IL49_FIRST_AMPDU_QUEUE > txq_id) || (IL49_FIRST_AMPDU_QUEUE + - il->cfg->base_params->num_of_ampdu_queues <= txq_id)) { + il->cfg->num_of_ampdu_queues <= txq_id)) { IL_WARN("queue number out of range: %d, must be %d to %d\n", txq_id, IL49_FIRST_AMPDU_QUEUE, IL49_FIRST_AMPDU_QUEUE + - il->cfg->base_params->num_of_ampdu_queues - 1); + il->cfg->num_of_ampdu_queues - 1); return -EINVAL; } @@ -2278,11 +2278,11 @@ il4965_txq_agg_disable(struct il_priv *il, u16 txq_id, u16 ssn_idx, u8 tx_fifo) { if ((IL49_FIRST_AMPDU_QUEUE > txq_id) || (IL49_FIRST_AMPDU_QUEUE + - il->cfg->base_params->num_of_ampdu_queues <= txq_id)) { + il->cfg->num_of_ampdu_queues <= txq_id)) { IL_WARN("queue number out of range: %d, must be %d to %d\n", txq_id, IL49_FIRST_AMPDU_QUEUE, IL49_FIRST_AMPDU_QUEUE + - il->cfg->base_params->num_of_ampdu_queues - 1); + il->cfg->num_of_ampdu_queues - 1); return -EINVAL; } diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index 27feb533d02..cf1d0164a9a 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c @@ -614,13 +614,13 @@ il4965_hw_set_hw_params(struct il_priv *il) { if (il->cfg->mod_params->num_of_queues >= IL_MIN_NUM_QUEUES && il->cfg->mod_params->num_of_queues <= IL49_NUM_QUEUES) - il->cfg->base_params->num_of_queues = + il->cfg->num_of_queues = il->cfg->mod_params->num_of_queues; - il->hw_params.max_txq_num = il->cfg->base_params->num_of_queues; + il->hw_params.max_txq_num = il->cfg->num_of_queues; il->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; il->hw_params.scd_bc_tbls_size = - il->cfg->base_params->num_of_queues * + il->cfg->num_of_queues * sizeof(struct il4965_scd_bc_tbl); il->hw_params.tfd_size = sizeof(struct il_tfd); il->hw_params.max_stations = IL4965_STATION_COUNT; @@ -2331,22 +2331,6 @@ const struct il_ops il4965_ops = { .legacy = &il4965_legacy_ops, }; -static struct il_base_params il4965_base_params = { - .eeprom_size = IL4965_EEPROM_IMG_SIZE, - .num_of_queues = IL49_NUM_QUEUES, - .num_of_ampdu_queues = IL49_NUM_AMPDU_QUEUES, - .pll_cfg_val = 0, - .set_l0s = true, - .use_bsm = true, - .led_compensation = 61, - .chain_noise_num_beacons = IL4965_CAL_NUM_BEACONS, - .wd_timeout = IL_DEF_WD_TIMEOUT, - .temperature_kelvin = true, - .ucode_tracing = true, - .sensitivity_calib_by_driver = true, - .chain_noise_calib_by_driver = true, -}; - struct il_cfg il4965_cfg = { .name = "Intel(R) Wireless WiFi Link 4965AGN", .fw_name_pre = IL4965_FW_PRE, @@ -2358,13 +2342,26 @@ struct il_cfg il4965_cfg = { .eeprom_ver = EEPROM_4965_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, .mod_params = &il4965_mod_params, - .base_params = &il4965_base_params, .led_mode = IL_LED_BLINK, /* * Force use of chains B and C for scan RX on 5 GHz band * because the device has off-channel reception on chain A. */ .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, + + .eeprom_size = IL4965_EEPROM_IMG_SIZE, + .num_of_queues = IL49_NUM_QUEUES, + .num_of_ampdu_queues = IL49_NUM_AMPDU_QUEUES, + .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = true, + .led_compensation = 61, + .chain_noise_num_beacons = IL4965_CAL_NUM_BEACONS, + .wd_timeout = IL_DEF_WD_TIMEOUT, + .temperature_kelvin = true, + .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 3bd18333656..1173521f21f 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -512,13 +512,13 @@ il_led_cmd(struct il_priv *il, unsigned long on, unsigned long off) } D_LED("Led blink time compensation=%u\n", - il->cfg->base_params->led_compensation); + il->cfg->led_compensation); led_cmd.on = il_blink_compensation(il, on, - il->cfg->base_params->led_compensation); + il->cfg->led_compensation); led_cmd.off = il_blink_compensation(il, off, - il->cfg->base_params->led_compensation); + il->cfg->led_compensation); ret = il->ops->led->cmd(il, &led_cmd); if (!ret) { @@ -691,7 +691,7 @@ il_eeprom_verify_signature(struct il_priv *il) const u8 * il_eeprom_query_addr(const struct il_priv *il, size_t offset) { - BUG_ON(offset >= il->cfg->base_params->eeprom_size); + BUG_ON(offset >= il->cfg->eeprom_size); return &il->eeprom[offset]; } EXPORT_SYMBOL(il_eeprom_query_addr); @@ -722,7 +722,7 @@ il_eeprom_init(struct il_priv *il) u16 addr; /* allocate eeprom */ - sz = il->cfg->base_params->eeprom_size; + sz = il->cfg->eeprom_size; D_EEPROM("NVM size = %d\n", sz); il->eeprom = kzalloc(sz, GFP_KERNEL); if (!il->eeprom) { @@ -4218,7 +4218,7 @@ il_apm_init(struct il_priv *il) * If not (unlikely), enable L0S, so there is at least some * power savings, even without L1. */ - if (il->cfg->base_params->set_l0s) { + if (il->cfg->set_l0s) { lctl = il_pcie_link_ctl(il); if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) { @@ -4235,9 +4235,9 @@ il_apm_init(struct il_priv *il) } /* Configure analog phase-lock-loop before activating to D0A */ - if (il->cfg->base_params->pll_cfg_val) + if (il->cfg->pll_cfg_val) il_set_bit(il, CSR_ANA_PLL_CFG, - il->cfg->base_params->pll_cfg_val); + il->cfg->pll_cfg_val); /* * Set "initialization complete" bit to move adapter from @@ -4267,7 +4267,7 @@ il_apm_init(struct il_priv *il) * do not disable clocks. This preserves any hardware bits already * set by default in "CLK_CTRL_REG" after reset. */ - if (il->cfg->base_params->use_bsm) + if (il->cfg->use_bsm) il_wr_prph(il, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); else @@ -4565,7 +4565,7 @@ il_alloc_txq_mem(struct il_priv *il) if (!il->txq) il->txq = kzalloc(sizeof(struct il_tx_queue) * - il->cfg->base_params->num_of_queues, GFP_KERNEL); + il->cfg->num_of_queues, GFP_KERNEL); if (!il->txq) { IL_ERR("Not enough memory for txq\n"); return -ENOMEM; @@ -4942,11 +4942,11 @@ il_check_stuck_queue(struct il_priv *il, int cnt) timeout = txq->time_stamp + - msecs_to_jiffies(il->cfg->base_params->wd_timeout); + msecs_to_jiffies(il->cfg->wd_timeout); if (time_after(jiffies, timeout)) { IL_ERR("Queue %d stuck for %u ms.\n", q->id, - il->cfg->base_params->wd_timeout); + il->cfg->wd_timeout); ret = il_force_reset(il, false); return (ret == -EAGAIN) ? 0 : 1; } @@ -4974,7 +4974,7 @@ il_bg_watchdog(unsigned long data) if (test_bit(S_EXIT_PENDING, &il->status)) return; - timeout = il->cfg->base_params->wd_timeout; + timeout = il->cfg->wd_timeout; if (timeout == 0) return; @@ -5001,7 +5001,7 @@ EXPORT_SYMBOL(il_bg_watchdog); void il_setup_watchdog(struct il_priv *il) { - unsigned int timeout = il->cfg->base_params->wd_timeout; + unsigned int timeout = il->cfg->wd_timeout; if (timeout) mod_timer(&il->watchdog, diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 2af861062de..21ed70a7f68 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1695,21 +1695,6 @@ struct il_mod_params { * chain noise calibration operation */ struct il_base_params { - int eeprom_size; - int num_of_queues; /* def: HW dependent */ - int num_of_ampdu_queues; /* def: HW dependent */ - /* for il_apm_init() */ - u32 pll_cfg_val; - bool set_l0s; - bool use_bsm; - - u16 led_compensation; - int chain_noise_num_beacons; - unsigned int wd_timeout; - bool temperature_kelvin; - const bool ucode_tracing; - const bool sensitivity_calib_by_driver; - const bool chain_noise_calib_by_driver; }; #define IL_LED_SOLID 11 @@ -1784,6 +1769,22 @@ struct il_cfg { /* params likely to change within a device family */ u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; enum il_led_mode led_mode; + + int eeprom_size; + int num_of_queues; /* def: HW dependent */ + int num_of_ampdu_queues; /* def: HW dependent */ + /* for il_apm_init() */ + u32 pll_cfg_val; + bool set_l0s; + bool use_bsm; + + u16 led_compensation; + int chain_noise_num_beacons; + unsigned int wd_timeout; + bool temperature_kelvin; + const bool ucode_tracing; + const bool sensitivity_calib_by_driver; + const bool chain_noise_calib_by_driver; }; /*************************** diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c index 4fb769caef5..bb7c95607a6 100644 --- a/drivers/net/wireless/iwlegacy/debug.c +++ b/drivers/net/wireless/iwlegacy/debug.c @@ -361,7 +361,7 @@ il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count, const u8 *ptr; char *buf; u16 eeprom_ver; - size_t eeprom_len = il->cfg->base_params->eeprom_size; + size_t eeprom_len = il->cfg->eeprom_size; buf_size = 4 * eeprom_len + 256; if (eeprom_len % 16) { @@ -727,7 +727,7 @@ il_dbgfs_traffic_log_read(struct file *file, char __user *user_buf, char *buf; int bufsz = ((IL_TRAFFIC_ENTRIES * IL_TRAFFIC_ENTRY_SIZE * 64) * 2) + - (il->cfg->base_params->num_of_queues * 32 * 8) + 400; + (il->cfg->num_of_queues * 32 * 8) + 400; const u8 *ptr; ssize_t ret; @@ -833,7 +833,7 @@ il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count, int cnt; int ret; const size_t bufsz = - sizeof(char) * 64 * il->cfg->base_params->num_of_queues; + sizeof(char) * 64 * il->cfg->num_of_queues; if (!il->txq) { IL_ERR("txq not ready\n"); @@ -1293,7 +1293,7 @@ il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf, if (timeout < 0 || timeout > IL_MAX_WD_TIMEOUT) timeout = IL_DEF_WD_TIMEOUT; - il->cfg->base_params->wd_timeout = timeout; + il->cfg->wd_timeout = timeout; il_setup_watchdog(il); return count; } @@ -1367,17 +1367,17 @@ il_dbgfs_register(struct il_priv *il, const char *name) DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); - if (il->cfg->base_params->sensitivity_calib_by_driver) + if (il->cfg->sensitivity_calib_by_driver) DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); - if (il->cfg->base_params->chain_noise_calib_by_driver) + if (il->cfg->chain_noise_calib_by_driver) DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); - if (il->cfg->base_params->sensitivity_calib_by_driver) + if (il->cfg->sensitivity_calib_by_driver) DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &il->disable_sens_cal); - if (il->cfg->base_params->chain_noise_calib_by_driver) + if (il->cfg->chain_noise_calib_by_driver) DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, &il->disable_chain_noise_cal); DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal); -- cgit v1.2.3 From 00ea99e1d86b05e7ba90d66673b536b731af87cd Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:32:00 +0100 Subject: iwlegacy: remove struct il_tx_info It's just wrapper to sk_buff pointers ... Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 4 +--- drivers/net/wireless/iwlegacy/3945.c | 18 ++++++++--------- drivers/net/wireless/iwlegacy/4965-mac.c | 33 ++++++++++++++------------------ drivers/net/wireless/iwlegacy/4965.c | 18 +++++++++-------- drivers/net/wireless/iwlegacy/common.c | 24 +++++++++++------------ drivers/net/wireless/iwlegacy/common.h | 18 ++--------------- 6 files changed, 46 insertions(+), 69 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 40ce692b2c9..aa8f5c0bd64 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -538,9 +538,7 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) idx = il_get_cmd_idx(q, q->write_ptr, 0); - /* Set up driver data for this TFD */ - memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct il_tx_info)); - txq->txb[q->write_ptr].skb = skb; + txq->skbs[q->write_ptr] = skb; /* Init first empty entry in queue's array of Tx/cmd buffers */ out_cmd = txq->cmd[idx]; diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index 7c21a57d1bb..6c1ae5fab89 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -293,16 +293,16 @@ il3945_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx) { struct il_tx_queue *txq = &il->txq[txq_id]; struct il_queue *q = &txq->q; - struct il_tx_info *tx_info; + struct sk_buff *skb; BUG_ON(txq_id == IL39_CMD_QUEUE_NUM); for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) { - tx_info = &txq->txb[txq->q.read_ptr]; - ieee80211_tx_status_irqsafe(il->hw, tx_info->skb); - tx_info->skb = NULL; + skb = txq->skbs[txq->q.read_ptr]; + ieee80211_tx_status_irqsafe(il->hw, skb); + txq->skbs[txq->q.read_ptr] = NULL; il->ops->lib->txq_free_tfd(il, txq); } @@ -336,7 +336,7 @@ il3945_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) } txq->time_stamp = jiffies; - info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); + info = IEEE80211_SKB_CB(txq->skbs[txq->q.read_ptr]); ieee80211_tx_info_clear_status(info); /* Fill the MRR chain with some info about on-chip retransmissions */ @@ -660,15 +660,13 @@ il3945_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq) PCI_DMA_TODEVICE); /* free SKB */ - if (txq->txb) { - struct sk_buff *skb; - - skb = txq->txb[txq->q.read_ptr].skb; + if (txq->skbs) { + struct sk_buff *skb = txq->skbs[txq->q.read_ptr]; /* can be called from irqs-disabled context */ if (skb) { dev_kfree_skb_any(skb); - txq->txb[txq->q.read_ptr].skb = NULL; + txq->skbs[txq->q.read_ptr] = NULL; } } } diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 49dd1e0e9a5..2a52e7b7325 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -1753,9 +1753,7 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) spin_unlock(&il->sta_lock); - /* Set up driver data for this TFD */ - memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct il_tx_info)); - txq->txb[q->write_ptr].skb = skb; + txq->skbs[q->write_ptr] = skb; /* Set up first empty entry in queue's array of Tx/cmd buffers */ out_cmd = txq->cmd[q->write_ptr]; @@ -2435,14 +2433,14 @@ il4965_non_agg_tx_status(struct il_priv *il, const u8 *addr1) } static void -il4965_tx_status(struct il_priv *il, struct il_tx_info *tx_info, bool is_agg) +il4965_tx_status(struct il_priv *il, struct sk_buff *skb, bool is_agg) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; if (!is_agg) il4965_non_agg_tx_status(il, hdr->addr1); - ieee80211_tx_status_irqsafe(il->hw, tx_info->skb); + ieee80211_tx_status_irqsafe(il->hw, skb); } int @@ -2450,9 +2448,9 @@ il4965_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx) { struct il_tx_queue *txq = &il->txq[txq_id]; struct il_queue *q = &txq->q; - struct il_tx_info *tx_info; int nfreed = 0; struct ieee80211_hdr *hdr; + struct sk_buff *skb; if (idx >= q->n_bd || il_queue_used(q, idx) == 0) { IL_ERR("Read idx for DMA queue txq id (%d), idx %d, " @@ -2464,19 +2462,18 @@ il4965_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx) for (idx = il_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd)) { - tx_info = &txq->txb[txq->q.read_ptr]; + skb = txq->skbs[txq->q.read_ptr]; - if (WARN_ON_ONCE(tx_info->skb == NULL)) + if (WARN_ON_ONCE(skb == NULL)) continue; - hdr = (struct ieee80211_hdr *)tx_info->skb->data; + hdr = (struct ieee80211_hdr *) skb->data; if (ieee80211_is_data_qos(hdr->frame_control)) nfreed++; - il4965_tx_status(il, tx_info, - txq_id >= IL4965_FIRST_AMPDU_QUEUE); - tx_info->skb = NULL; + il4965_tx_status(il, skb, txq_id >= IL4965_FIRST_AMPDU_QUEUE); + txq->skbs[txq->q.read_ptr] = NULL; il->ops->lib->txq_free_tfd(il, txq); } return nfreed; @@ -2540,7 +2537,7 @@ il4965_tx_status_reply_compressed_ba(struct il_priv *il, struct il_ht_agg *agg, D_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap); - info = IEEE80211_SKB_CB(il->txq[scd_flow].txb[agg->start_idx].skb); + info = IEEE80211_SKB_CB(il->txq[scd_flow].skbs[agg->start_idx]); memset(&info->status, 0, sizeof(info->status)); info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_AMPDU; @@ -3624,15 +3621,13 @@ il4965_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq) PCI_DMA_TODEVICE); /* free SKB */ - if (txq->txb) { - struct sk_buff *skb; - - skb = txq->txb[txq->q.read_ptr].skb; + if (txq->skbs) { + struct sk_buff *skb = txq->skbs[txq->q.read_ptr]; /* can be called from irqs-disabled context */ if (skb) { dev_kfree_skb_any(skb); - txq->txb[txq->q.read_ptr].skb = NULL; + txq->skbs[txq->q.read_ptr] = NULL; } } } diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index cf1d0164a9a..17a6922e890 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c @@ -1873,7 +1873,7 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg, D_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", agg->frame_count, agg->start_idx, idx); - info = IEEE80211_SKB_CB(il->txq[txq_id].txb[idx].skb); + info = IEEE80211_SKB_CB(il->txq[txq_id].skbs[idx]); info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= il4965_tx_status_to_mac80211(status); @@ -1888,6 +1888,7 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg, /* Two or more frames were attempted; expect block-ack */ u64 bitmap = 0; int start = agg->start_idx; + struct sk_buff *skb; /* Construct bit-map of pending frames within Tx win */ for (i = 0; i < agg->frame_count; i++) { @@ -1905,12 +1906,10 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg, D_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n", agg->frame_count, txq_id, idx); - hdr = il_tx_queue_get_hdr(il, txq_id, idx); - if (!hdr) { - IL_ERR("BUG_ON idx doesn't point to valid skb" - " idx=%d, txq_id=%d\n", idx, txq_id); + skb = il->txq[txq_id].skbs[idx]; + if (WARN_ON_ONCE(skb == NULL)) return -1; - } + hdr = (struct ieee80211_hdr *) skb->data; sc = le16_to_cpu(hdr->seq_ctrl); if (idx != (SEQ_TO_SN(sc) & 0xff)) { @@ -2018,6 +2017,7 @@ il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) int txq_id = SEQ_TO_QUEUE(sequence); int idx = SEQ_TO_IDX(sequence); struct il_tx_queue *txq = &il->txq[txq_id]; + struct sk_buff *skb; struct ieee80211_hdr *hdr; struct ieee80211_tx_info *info; struct il4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; @@ -2036,10 +2036,12 @@ il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) } txq->time_stamp = jiffies; - info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb); + + skb = txq->skbs[txq->q.read_ptr]; + info = IEEE80211_SKB_CB(skb); memset(&info->status, 0, sizeof(info->status)); - hdr = il_tx_queue_get_hdr(il, txq_id, idx); + hdr = (struct ieee80211_hdr *) skb->data; if (ieee80211_is_data_qos(hdr->frame_control)) { qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & 0xf; diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 1173521f21f..04ec38e5eaa 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -2755,8 +2755,8 @@ il_tx_queue_free(struct il_priv *il, int txq_id) txq->tfds, txq->q.dma_addr); /* De-alloc array of per-TFD driver data */ - kfree(txq->txb); - txq->txb = NULL; + kfree(txq->skbs); + txq->skbs = NULL; /* deallocate arrays */ kfree(txq->cmd); @@ -2930,23 +2930,21 @@ il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id) /* Driver ilate data, only for Tx (not command) queues, * not shared with device. */ if (id != il->cmd_queue) { - txq->txb = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->txb[0]), - GFP_KERNEL); - if (!txq->txb) { - IL_ERR("kmalloc for auxiliary BD " - "structures failed\n"); + txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(struct skb *), + GFP_KERNEL); + if (!txq->skbs) { + IL_ERR("Fail to alloc skbs\n"); goto error; } - } else { - txq->txb = NULL; - } + } else + txq->skbs = NULL; /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, GFP_KERNEL); if (!txq->tfds) { - IL_ERR("pci_alloc_consistent(%zd) failed\n", tfd_sz); + IL_ERR("Fail to alloc TFDs\n"); goto error; } txq->q.id = id; @@ -2954,8 +2952,8 @@ il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id) return 0; error: - kfree(txq->txb); - txq->txb = NULL; + kfree(txq->skbs); + txq->skbs = NULL; return -ENOMEM; } diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 21ed70a7f68..527a1b9f99e 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -143,11 +143,6 @@ struct il_queue { * space less than this */ }; -/* One for each TFD */ -struct il_tx_info { - struct sk_buff *skb; -}; - /** * struct il_tx_queue - Tx Queue for DMA * @q: generic Rx/Tx queue descriptor @@ -155,7 +150,7 @@ struct il_tx_info { * @cmd: array of command/TX buffer pointers * @meta: array of meta data for each command/tx buffer * @dma_addr_cmd: physical address of cmd/tx buffer array - * @txb: array of per-TFD driver data + * @skbs: array of per-TFD socket buffer pointers * @time_stamp: time (in jiffies) of last read_ptr change * @need_update: indicates need to update read/write idx * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled @@ -171,7 +166,7 @@ struct il_tx_queue { void *tfds; struct il_device_cmd **cmd; struct il_cmd_meta *meta; - struct il_tx_info *txb; + struct sk_buff **skbs; unsigned long time_stamp; u8 need_update; u8 sched_retry; @@ -1482,15 +1477,6 @@ il_txq_ctx_deactivate(struct il_priv *il, int txq_id) clear_bit(txq_id, &il->txq_ctx_active_msk); } -static inline struct ieee80211_hdr * -il_tx_queue_get_hdr(struct il_priv *il, int txq_id, int idx) -{ - if (il->txq[txq_id].txb[idx].skb) - return (struct ieee80211_hdr *)il->txq[txq_id].txb[idx].skb-> - data; - return NULL; -} - static inline int il_is_associated(struct il_priv *il) { -- cgit v1.2.3 From 1023f3bc7b3f56da1f79f605cbe459318c4792ae Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 3 Feb 2012 17:32:01 +0100 Subject: iwlegacy: remove set_hw_params callback We do not need that callback, settings parameters can be done locally. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/4965-mac.c | 66 ++++++++++++++++++++++++--- drivers/net/wireless/iwlegacy/4965.c | 76 -------------------------------- drivers/net/wireless/iwlegacy/common.h | 2 - 3 files changed, 59 insertions(+), 85 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 2a52e7b7325..235812ac6a0 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -6079,7 +6079,34 @@ il4965_hw_detect(struct il_priv *il) D_INFO("HW Revision ID = 0x%X\n", il->rev_id); } -static int +static struct il_sensitivity_ranges il4965_sensitivity = { + .min_nrg_cck = 97, + .max_nrg_cck = 0, /* not used, set to 0 */ + + .auto_corr_min_ofdm = 85, + .auto_corr_min_ofdm_mrc = 170, + .auto_corr_min_ofdm_x1 = 105, + .auto_corr_min_ofdm_mrc_x1 = 220, + + .auto_corr_max_ofdm = 120, + .auto_corr_max_ofdm_mrc = 210, + .auto_corr_max_ofdm_x1 = 140, + .auto_corr_max_ofdm_mrc_x1 = 270, + + .auto_corr_min_cck = 125, + .auto_corr_max_cck = 200, + .auto_corr_min_cck_mrc = 200, + .auto_corr_max_cck_mrc = 400, + + .nrg_th_cck = 100, + .nrg_th_ofdm = 100, + + .barker_corr_th_min = 190, + .barker_corr_th_min_mrc = 390, + .nrg_th_cca = 62, +}; + +static void il4965_set_hw_params(struct il_priv *il) { il->hw_params.bcast_id = IL4965_BROADCAST_ID; @@ -6095,8 +6122,36 @@ il4965_set_hw_params(struct il_priv *il) if (il->cfg->mod_params->disable_11n) il->cfg->sku &= ~IL_SKU_N; - /* Device-specific setup */ - return il->ops->lib->set_hw_params(il); + if (il->cfg->mod_params->num_of_queues >= IL_MIN_NUM_QUEUES && + il->cfg->mod_params->num_of_queues <= IL49_NUM_QUEUES) + il->cfg->num_of_queues = + il->cfg->mod_params->num_of_queues; + + il->hw_params.max_txq_num = il->cfg->num_of_queues; + il->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; + il->hw_params.scd_bc_tbls_size = + il->cfg->num_of_queues * + sizeof(struct il4965_scd_bc_tbl); + + il->hw_params.tfd_size = sizeof(struct il_tfd); + il->hw_params.max_stations = IL4965_STATION_COUNT; + il->hw_params.max_data_size = IL49_RTC_DATA_SIZE; + il->hw_params.max_inst_size = IL49_RTC_INST_SIZE; + il->hw_params.max_bsm_size = BSM_SRAM_SIZE; + il->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ); + + il->hw_params.rx_wrt_ptr_reg = FH49_RSCSR_CHNL0_WPTR; + + il->hw_params.tx_chains_num = il4965_num_of_ant(il->cfg->valid_tx_ant); + il->hw_params.rx_chains_num = il4965_num_of_ant(il->cfg->valid_rx_ant); + il->hw_params.valid_tx_ant = il->cfg->valid_tx_ant; + il->hw_params.valid_rx_ant = il->cfg->valid_rx_ant; + + il->hw_params.ct_kill_threshold = + CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY); + + il->hw_params.sens = &il4965_sensitivity; + il->hw_params.beacon_time_tsf_bits = IL4965_EXT_BEACON_TIME_POS; } static int @@ -6230,10 +6285,7 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /************************ * 5. Setup HW constants ************************/ - if (il4965_set_hw_params(il)) { - IL_ERR("failed to set hw parameters\n"); - goto out_free_eeprom; - } + il4965_set_hw_params(il); /******************* * 6. Setup il diff --git a/drivers/net/wireless/iwlegacy/4965.c b/drivers/net/wireless/iwlegacy/4965.c index 17a6922e890..79e4e797133 100644 --- a/drivers/net/wireless/iwlegacy/4965.c +++ b/drivers/net/wireless/iwlegacy/4965.c @@ -569,81 +569,6 @@ il4965_chain_noise_reset(struct il_priv *il) } } -static struct il_sensitivity_ranges il4965_sensitivity = { - .min_nrg_cck = 97, - .max_nrg_cck = 0, /* not used, set to 0 */ - - .auto_corr_min_ofdm = 85, - .auto_corr_min_ofdm_mrc = 170, - .auto_corr_min_ofdm_x1 = 105, - .auto_corr_min_ofdm_mrc_x1 = 220, - - .auto_corr_max_ofdm = 120, - .auto_corr_max_ofdm_mrc = 210, - .auto_corr_max_ofdm_x1 = 140, - .auto_corr_max_ofdm_mrc_x1 = 270, - - .auto_corr_min_cck = 125, - .auto_corr_max_cck = 200, - .auto_corr_min_cck_mrc = 200, - .auto_corr_max_cck_mrc = 400, - - .nrg_th_cck = 100, - .nrg_th_ofdm = 100, - - .barker_corr_th_min = 190, - .barker_corr_th_min_mrc = 390, - .nrg_th_cca = 62, -}; - -static void -il4965_set_ct_threshold(struct il_priv *il) -{ - /* want Kelvin */ - il->hw_params.ct_kill_threshold = - CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY); -} - -/** - * il4965_hw_set_hw_params - * - * Called when initializing driver - */ -static int -il4965_hw_set_hw_params(struct il_priv *il) -{ - if (il->cfg->mod_params->num_of_queues >= IL_MIN_NUM_QUEUES && - il->cfg->mod_params->num_of_queues <= IL49_NUM_QUEUES) - il->cfg->num_of_queues = - il->cfg->mod_params->num_of_queues; - - il->hw_params.max_txq_num = il->cfg->num_of_queues; - il->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; - il->hw_params.scd_bc_tbls_size = - il->cfg->num_of_queues * - sizeof(struct il4965_scd_bc_tbl); - il->hw_params.tfd_size = sizeof(struct il_tfd); - il->hw_params.max_stations = IL4965_STATION_COUNT; - il->hw_params.max_data_size = IL49_RTC_DATA_SIZE; - il->hw_params.max_inst_size = IL49_RTC_INST_SIZE; - il->hw_params.max_bsm_size = BSM_SRAM_SIZE; - il->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ); - - il->hw_params.rx_wrt_ptr_reg = FH49_RSCSR_CHNL0_WPTR; - - il->hw_params.tx_chains_num = il4965_num_of_ant(il->cfg->valid_tx_ant); - il->hw_params.rx_chains_num = il4965_num_of_ant(il->cfg->valid_rx_ant); - il->hw_params.valid_tx_ant = il->cfg->valid_tx_ant; - il->hw_params.valid_rx_ant = il->cfg->valid_rx_ant; - - il4965_set_ct_threshold(il); - - il->hw_params.sens = &il4965_sensitivity; - il->hw_params.beacon_time_tsf_bits = IL4965_EXT_BEACON_TIME_POS; - - return 0; -} - static s32 il4965_math_div_round(s32 num, s32 denom, s32 * res) { @@ -2276,7 +2201,6 @@ static struct il_hcmd_utils_ops il4965_hcmd_utils = { }; static struct il_lib_ops il4965_lib = { - .set_hw_params = il4965_hw_set_hw_params, .txq_update_byte_cnt_tbl = il4965_txq_update_byte_cnt_tbl, .txq_attach_buf_to_tfd = il4965_hw_txq_attach_buf_to_tfd, .txq_free_tfd = il4965_hw_txq_free_tfd, diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 527a1b9f99e..708095644f1 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1592,8 +1592,6 @@ struct il_temp_ops { }; struct il_lib_ops { - /* set hw dependent parameters */ - int (*set_hw_params) (struct il_priv *il); /* Handling TX */ void (*txq_update_byte_cnt_tbl) (struct il_priv *il, struct il_tx_queue *txq, -- cgit v1.2.3 From e1936e9407138b483e6d1332dd944afec8131f30 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:23 +0100 Subject: mac80211: call rate control only after init There are situations where we don't have the necessary rate control information yet for station entries, e.g. when associating. This currently doesn't really happen due to the dummy station handling; explicitly disabling rate control when it's not initialised will allow us to remove dummy stations. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs_sta.c | 4 ++-- net/mac80211/rate.c | 2 +- net/mac80211/rate.h | 1 + net/mac80211/sta_info.h | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index c8383712fde..6d45804d09b 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -63,7 +63,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" int res = scnprintf(buf, sizeof(buf), - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", TEST(AUTH), TEST(ASSOC), TEST(PS_STA), TEST(PS_DRIVER), TEST(AUTHORIZED), TEST(SHORT_PREAMBLE), @@ -71,7 +71,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), - TEST(INSERTED)); + TEST(INSERTED), TEST(RATE_CONTROL)); #undef TEST return simple_read_from_buffer(userbuf, count, ppos, buf, res); } diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 22fc28e9026..111fba38be8 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -439,7 +439,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, u32 mask; u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; - if (sta) { + if (sta && test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) { ista = &sta->sta; priv_sta = sta->rate_ctrl_priv; } diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 8268457bd14..5fc3135a6b4 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -58,6 +58,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; ref->ops->rate_init(ref->priv, sband, ista, priv_sta); + set_sta_flag(sta, WLAN_STA_RATE_CONTROL); } static inline void rate_control_rate_update(struct ieee80211_local *local, diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 03f249bc276..23a97c9dc04 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -53,6 +53,7 @@ * reply to other uAPSD trigger frames or PS-Poll. * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. * @WLAN_STA_INSERTED: This station is inserted into the hash table. + * @WLAN_STA_RATE_CONTROL: rate control was initialized for this station. */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH, @@ -73,6 +74,7 @@ enum ieee80211_sta_info_flags { WLAN_STA_SP, WLAN_STA_4ADDR_EVENT, WLAN_STA_INSERTED, + WLAN_STA_RATE_CONTROL, }; #define STA_TID_NUM 16 -- cgit v1.2.3 From 234f6e5c05277c0198797553434e2ed5acac18cc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 6 Feb 2012 14:07:24 +1100 Subject: orinoco: Remove old mailing lists from MAINTAINERS The two orinoco mailing lists on sourceforge were set up many years ago and are now more or less moribund. I'd like to shut them down, so I don't have to keep filtering the spam from them (which is most of what comes through now). In preparation, this patch removes the reference to them from the MAINTAINERS file. Any remaining discussion of this approaching obsolete driver can go to the linux-wireless list. Signed-off-by: David Gibson Acked-by: Pavel Roskin Signed-off-by: John W. Linville --- MAINTAINERS | 2 -- 1 file changed, 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 1adb206dfca..bcb668c0af7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4894,8 +4894,6 @@ F: fs/ocfs2/ ORINOCO DRIVER L: linux-wireless@vger.kernel.org -L: orinoco-users@lists.sourceforge.net -L: orinoco-devel@lists.sourceforge.net W: http://linuxwireless.org/en/users/Drivers/orinoco W: http://www.nongnu.org/orinoco/ S: Orphan -- cgit v1.2.3 From 1ebbc48520a0853cd4d812d8342f9886b2b07b92 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 6 Feb 2012 23:45:06 +0100 Subject: rt2x00: Introduce concept of driver data in struct rt2x00_dev. We are getting more and more fields in struct rt2x00_dev that are specific to one or two of the low-level drivers. Instead of putting these fields inside the main structure and thus clobbering all low-level drivers with these fields, introduce the concept of driver data inside struct rt2x00_dev, whose size is indicated by the low-level driver and which can be populated by the low-level driver. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 6 ++++++ drivers/net/wireless/rt2x00/rt2x00dev.c | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index b03b22c47b1..b4260bfb6cb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -647,6 +647,7 @@ struct rt2x00lib_ops { */ struct rt2x00_ops { const char *name; + const unsigned int drv_data_size; const unsigned int max_sta_intf; const unsigned int max_ap_intf; const unsigned int eeprom_size; @@ -741,6 +742,11 @@ struct rt2x00_dev { */ const struct rt2x00_ops *ops; + /* + * Driver data. + */ + void *drv_data; + /* * IEEE80211 control structure. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index c3e1aa7c1a8..bae5b01299e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1121,6 +1121,18 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) { int retval = -ENOMEM; + /* + * Allocate the driver data memory, if necessary. + */ + if (rt2x00dev->ops->drv_data_size > 0) { + rt2x00dev->drv_data = kzalloc(rt2x00dev->ops->drv_data_size, + GFP_KERNEL); + if (!rt2x00dev->drv_data) { + retval = -ENOMEM; + goto exit; + } + } + spin_lock_init(&rt2x00dev->irqmask_lock); mutex_init(&rt2x00dev->csr_mutex); @@ -1261,6 +1273,12 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) * Free queue structures. */ rt2x00queue_free(rt2x00dev); + + /* + * Free the driver data. + */ + if (rt2x00dev->drv_data) + kfree(rt2x00dev->drv_data); } EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); -- cgit v1.2.3 From 3a1c01288e5596fb70ca48ec9d9d8b561121c544 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 6 Feb 2012 23:45:07 +0100 Subject: rt2x00: Use struct rt2x00_dev driver data in rt2800{pci,usb}. Start using the struct rt2x00_dev driver data in rt2800 for the calibration data. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 8 ++++++++ drivers/net/wireless/rt2x00/rt2800lib.c | 31 +++++++++++++++++++++---------- drivers/net/wireless/rt2x00/rt2800pci.c | 1 + drivers/net/wireless/rt2x00/rt2800usb.c | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 7 ------- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index fac9ece22b2..7c05dee5787 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2438,4 +2438,12 @@ struct mac_iveiv_entry { */ #define EIRP_MAX_TX_POWER_LIMIT 0x50 +/* + * RT2800 driver data structure + */ +struct rt2800_drv_data { + u8 calibration_bw20; + u8 calibration_bw40; +}; + #endif /* RT2800_H */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index c326e7b1c37..131139ed4b1 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1645,6 +1645,7 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, struct rf_channel *rf, struct channel_info *info) { + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; u8 rfcsr, calib_tx, calib_rx; rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); @@ -1714,8 +1715,13 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, calib_tx = conf_is_ht40(conf) ? 0x68 : 0x4f; calib_rx = conf_is_ht40(conf) ? 0x6f : 0x4f; } else { - calib_tx = rt2x00dev->calibration[conf_is_ht40(conf)]; - calib_rx = rt2x00dev->calibration[conf_is_ht40(conf)]; + if (conf_is_ht40(conf)) { + calib_tx = drv_data->calibration_bw40; + calib_rx = drv_data->calibration_bw40; + } else { + calib_tx = drv_data->calibration_bw20; + calib_rx = drv_data->calibration_bw20; + } } rt2800_rfcsr_read(rt2x00dev, 24, &rfcsr); @@ -1743,6 +1749,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, struct rf_channel *rf, struct channel_info *info) { + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; u8 rfcsr; u32 reg; @@ -1836,10 +1843,13 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); - rt2800_rfcsr_write(rt2x00dev, 24, - rt2x00dev->calibration[conf_is_ht40(conf)]); - rt2800_rfcsr_write(rt2x00dev, 31, - rt2x00dev->calibration[conf_is_ht40(conf)]); + if (conf_is_ht40(conf)) { + rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw40); + rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw40); + } else { + rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw20); + rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw20); + } if (rf->channel <= 14) { rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); @@ -3310,6 +3320,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) { + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; u8 rfcsr; u8 bbp; u32 reg; @@ -3598,17 +3609,17 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) * Set RX Filter calibration for 20MHz and 40MHz */ if (rt2x00_rt(rt2x00dev, RT3070)) { - rt2x00dev->calibration[0] = + drv_data->calibration_bw20 = rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); - rt2x00dev->calibration[1] = + 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, RT3390) || rt2x00_rt(rt2x00dev, RT3572)) { - rt2x00dev->calibration[0] = + drv_data->calibration_bw20 = rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13); - rt2x00dev->calibration[1] = + drv_data->calibration_bw40 = rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15); } diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 4e985026985..6ad692914ee 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1093,6 +1093,7 @@ static const struct data_queue_desc rt2800pci_queue_bcn = { static const struct rt2x00_ops rt2800pci_ops = { .name = KBUILD_MODNAME, + .drv_data_size = sizeof(struct rt2800_drv_data), .max_sta_intf = 1, .max_ap_intf = 8, .eeprom_size = EEPROM_SIZE, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index f0074bcee7c..d009b6b794b 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -827,6 +827,7 @@ static const struct data_queue_desc rt2800usb_queue_bcn = { static const struct rt2x00_ops rt2800usb_ops = { .name = KBUILD_MODNAME, + .drv_data_size = sizeof(struct rt2800_drv_data), .max_sta_intf = 1, .max_ap_intf = 8, .eeprom_size = EEPROM_SIZE, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index b4260bfb6cb..5bd2f225ce4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -896,13 +896,6 @@ struct rt2x00_dev { */ u8 freq_offset; - /* - * Calibration information (for rt2800usb & rt2800pci). - * [0] -> BW20 - * [1] -> BW40 - */ - u8 calibration[2]; - /* * Association id. */ -- cgit v1.2.3 From bef453dc9cf1999348e568068f256b1c439d1152 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 6 Feb 2012 23:45:08 +0100 Subject: rt2x00: Update comment on freq_offset field in struct rt2x00_dev. The comment states that the field is only used for rt61pci and rt73usb. However, it is now used by rt2800pci and rt2800usb as well, so the comment is not correct anymore. Update the comment to not state any low-level drivers anymore. Signed-off-by: Gertjan van Wingerde Acked-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 5bd2f225ce4..ed2ae6efcaa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -892,7 +892,7 @@ struct rt2x00_dev { u8 rssi_offset; /* - * Frequency offset (for rt61pci & rt73usb). + * Frequency offset. */ u8 freq_offset; -- cgit v1.2.3 From 5d137dff36dce1eda0617a00eb87b57e48300045 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 6 Feb 2012 23:45:09 +0100 Subject: rt2x00: Use saved BBP 25 and 26 values when configuring channel on RT3572. This brings the rt2800 channel switching code for RT3572 closer to the v2.5.0.0 Ralink RT3572 driver. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 2 ++ drivers/net/wireless/rt2x00/rt2800lib.c | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 7c05dee5787..8aabd0dc02c 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2444,6 +2444,8 @@ struct mac_iveiv_entry { struct rt2800_drv_data { u8 calibration_bw20; u8 calibration_bw40; + u8 bbp25; + u8 bbp26; }; #endif /* RT2800_H */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 131139ed4b1..3873a155587 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1754,8 +1754,8 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, u32 reg; if (rf->channel <= 14) { - rt2800_bbp_write(rt2x00dev, 25, 0x15); - rt2800_bbp_write(rt2x00dev, 26, 0x85); + rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25); + rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26); } else { rt2800_bbp_write(rt2x00dev, 25, 0x09); rt2800_bbp_write(rt2x00dev, 26, 0xff); @@ -3623,6 +3623,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) 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)) { /* * Set back to initial state -- cgit v1.2.3 From 569ffa56344e7e2a1d635a9c620215196f5c7298 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 6 Feb 2012 23:45:10 +0100 Subject: rt2x00: Fix RFCSR 12 & 13 programming on RT3572 channel switching. Align with v2.5.0.0 Ralink RT3572 driver for 2.4GHz band channel switch. Signed-off-by: Gertjan van Wingerde Acked-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 3873a155587..80a2087fcf8 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1783,8 +1783,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, if (rf->channel <= 14) { rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3); rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, - (info->default_power1 & 0x3) | - ((info->default_power1 & 0xC) << 1)); + info->default_power1); } else { rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7); rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, @@ -1797,8 +1796,7 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, if (rf->channel <= 14) { rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3); rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, - (info->default_power2 & 0x3) | - ((info->default_power2 & 0xC) << 1)); + info->default_power2); } else { rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7); rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, -- cgit v1.2.3 From 0cd461efcc1df6763b86b29ef4d6ee1cb923aa47 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 6 Feb 2012 23:45:11 +0100 Subject: rt2x00: Align RT3572 channel switch RFCSR 1 programming with Ralink driver. Align with the v2.5.0.0 Ralink RT3572 driver. Signed-off-by: Gertjan van Wingerde Acked-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 80a2087fcf8..135e8a40edd 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1806,11 +1806,12 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); 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, 0); rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { if (rf->channel <= 14) { rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); -- cgit v1.2.3 From 58b8ae14d58319bff63a30a9e1c0ebb9c07f2243 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 6 Feb 2012 23:45:12 +0100 Subject: rt2x00: Fix RT3572 channel switch RFCSR 7 programming. Align with the v2.5.0.0 Ralink RT3572 driver. Signed-off-by: Gertjan van Wingerde Acked-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 10 ++++++---- drivers/net/wireless/rt2x00/rt2800lib.c | 7 ++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 8aabd0dc02c..c6648b02bf8 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1819,10 +1819,12 @@ struct mac_iveiv_entry { * RFCSR 7: */ #define RFCSR7_RF_TUNING FIELD8(0x01) -#define RFCSR7_R02 FIELD8(0x07) -#define RFCSR7_R3 FIELD8(0x08) -#define RFCSR7_R45 FIELD8(0x30) -#define RFCSR7_R67 FIELD8(0xc0) +#define RFCSR7_BIT1 FIELD8(0x02) +#define RFCSR7_BIT2 FIELD8(0x04) +#define RFCSR7_BIT3 FIELD8(0x08) +#define RFCSR7_BIT4 FIELD8(0x10) +#define RFCSR7_BIT5 FIELD8(0x20) +#define RFCSR7_BITS67 FIELD8(0xc0) /* * RFCSR 11: diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 135e8a40edd..395453c41e2 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1865,7 +1865,12 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 27, 0x00); rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); } else { - rt2800_rfcsr_write(rt2x00dev, 7, 0x14); + rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR7_BIT2, 1); + rt2x00_set_field8(&rfcsr, RFCSR7_BIT3, 0); + rt2x00_set_field8(&rfcsr, RFCSR7_BIT4, 1); + rt2x00_set_field8(&rfcsr, RFCSR7_BITS67, 0); + rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); rt2800_rfcsr_write(rt2x00dev, 11, 0x00); -- cgit v1.2.3 From 77c06c2cb44fe68295efdd33939153c7d56de004 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Mon, 6 Feb 2012 23:45:13 +0100 Subject: rt2x00: Correctly set txmixer_gain in RT3572 channel switching. Align with the v2.5.0.0 Ralink RT3572 driver. Save the EEPROM txmixer_gain values inside the rt2800 driver data structure and use it throughout the code. Signed-off-by: Gertjan van Wingerde Acked-by: Stanislaw Gruszka Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 13 +++++++++++++ drivers/net/wireless/rt2x00/rt2800lib.c | 34 ++++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index c6648b02bf8..06acabd0298 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1848,6 +1848,11 @@ struct mac_iveiv_entry { */ #define RFCSR15_TX_LO2_EN FIELD8(0x08) +/* + * RFCSR 16: + */ +#define RFCSR16_TXMIXER_GAIN FIELD8(0x07) + /* * RFCSR 17: */ @@ -2110,6 +2115,12 @@ struct mac_iveiv_entry { #define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff) #define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) +/* + * EEPROM TXMIXER GAIN A offset (note overlaps with EEPROM RSSI A2). + */ +#define EEPROM_TXMIXER_GAIN_A 0x0026 +#define EEPROM_TXMIXER_GAIN_A_VAL FIELD16(0x0007) + /* * EEPROM EIRP Maximum TX power values(unit: dbm) */ @@ -2448,6 +2459,8 @@ struct rt2800_drv_data { u8 calibration_bw40; u8 bbp25; u8 bbp26; + u8 txmixer_gain_24g; + u8 txmixer_gain_5g; }; #endif /* RT2800_H */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 395453c41e2..52728be6527 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1856,7 +1856,10 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); rt2800_rfcsr_write(rt2x00dev, 15, 0x53); - rt2800_rfcsr_write(rt2x00dev, 16, 0x4c); + rfcsr = 0x4c; + rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN, + drv_data->txmixer_gain_24g); + rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); rt2800_rfcsr_write(rt2x00dev, 17, 0x23); rt2800_rfcsr_write(rt2x00dev, 19, 0x93); rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); @@ -1875,7 +1878,10 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); rt2800_rfcsr_write(rt2x00dev, 11, 0x00); rt2800_rfcsr_write(rt2x00dev, 15, 0x43); - rt2800_rfcsr_write(rt2x00dev, 16, 0x7a); + rfcsr = 0x7a; + rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN, + drv_data->txmixer_gain_5g); + rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); rt2800_rfcsr_write(rt2x00dev, 17, 0x23); if (rf->channel <= 64) { rt2800_rfcsr_write(rt2x00dev, 19, 0xb7); @@ -3672,11 +3678,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) &rt2x00dev->cap_flags)) rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); } - rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1) - rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN, - rt2x00_get_field16(eeprom, - EEPROM_TXMIXER_GAIN_BG_VAL)); + rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN, + drv_data->txmixer_gain_24g); rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); } @@ -3884,6 +3887,7 @@ EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse); int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) { + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; u16 word; u8 *mac; u8 default_lna_gain; @@ -3967,6 +3971,14 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); + rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); + if ((word & 0x00ff) != 0x00ff) { + drv_data->txmixer_gain_24g = + rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL); + } else { + drv_data->txmixer_gain_24g = 0; + } + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); @@ -3976,6 +3988,14 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) default_lna_gain); rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); + rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); + if ((word & 0x00ff) != 0x00ff) { + drv_data->txmixer_gain_5g = + rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL); + } else { + drv_data->txmixer_gain_5g = 0; + } + rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0); -- cgit v1.2.3 From 79027596ff710f9662ccae5f5e85de43961420ed Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 7 Feb 2012 12:45:44 +0100 Subject: mac80211: add #ifdef CONFIG_MAC80211_VERBOSE_DEBUG for a debug printk When not debugging mac80211 code, station state transitions do not need to show up in the kernel log. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/sta_info.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 31cd6d92531..4034ee61602 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1379,8 +1379,10 @@ int sta_info_move_state(struct sta_info *sta, return -EINVAL; } +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: moving STA %pM to state %d\n", sta->sdata->name, sta->sta.addr, new_state); +#endif /* * notify the driver before the actual changes so it can -- cgit v1.2.3 From 7f66c2f93e5779625c10d262c84537427a2673ca Mon Sep 17 00:00:00 2001 From: Simon Graham Date: Tue, 7 Feb 2012 18:07:38 -0600 Subject: rtlwifi: Handle previous allocation failures when freeing device memory Handle previous allocation failures when freeing device memory Signed-off-by: Simon Graham Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index c5f6a322feb..c503bd3b809 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1148,10 +1148,12 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw, ring->idx = (ring->idx + 1) % ring->entries; } - pci_free_consistent(rtlpci->pdev, - sizeof(*ring->desc) * ring->entries, - ring->desc, ring->dma); - ring->desc = NULL; + if (ring->desc) { + pci_free_consistent(rtlpci->pdev, + sizeof(*ring->desc) * ring->entries, + ring->desc, ring->dma); + ring->desc = NULL; + } } static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci) @@ -1175,12 +1177,14 @@ static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci) kfree_skb(skb); } - pci_free_consistent(rtlpci->pdev, + if (rtlpci->rx_ring[rx_queue_idx].desc) { + pci_free_consistent(rtlpci->pdev, sizeof(*rtlpci->rx_ring[rx_queue_idx]. desc) * rtlpci->rxringcount, rtlpci->rx_ring[rx_queue_idx].desc, rtlpci->rx_ring[rx_queue_idx].dma); - rtlpci->rx_ring[rx_queue_idx].desc = NULL; + rtlpci->rx_ring[rx_queue_idx].desc = NULL; + } } } -- cgit v1.2.3 From 5ad20dd1480dc557afcec19ac7fae5581264dd59 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 7 Feb 2012 21:09:25 -0800 Subject: mac80211: rename mesh static path_lookup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If you want to use mesh support from mac80211 on a recent kernel on 2.6.24 you'll run into a name clash when compiling against include/linux/namei.h, so rename this routine. /home/mcgrof/tmp/compat-wireless-3.2.5-1/net/mac80211/mesh_pathtbl.c: At top level: /home/mcgrof/tmp/compat-wireless-3.2.5-1/net/mac80211/mesh_pathtbl.c:342:26: error: conflicting types for ‘path_lookup’ include/linux/namei.h:71:12: note: previous declaration of ‘path_lookup’ was here Although this could sit as a separate patch in compat-wireless it seems best to just merge upstream. Cc: Javier Cardona Signed-off-by: Luis R. Rodriguez Acked-by: Javier Cardona Signed-off-by: John W. Linville --- net/mac80211/mesh_pathtbl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index edf167e3b8f..dc51669e67d 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -336,7 +336,7 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, } -static struct mesh_path *path_lookup(struct mesh_table *tbl, u8 *dst, +static struct mesh_path *mpath_lookup(struct mesh_table *tbl, u8 *dst, struct ieee80211_sub_if_data *sdata) { struct mesh_path *mpath; @@ -371,12 +371,12 @@ static struct mesh_path *path_lookup(struct mesh_table *tbl, u8 *dst, */ struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) { - return path_lookup(rcu_dereference(mesh_paths), dst, sdata); + return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata); } struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) { - return path_lookup(rcu_dereference(mpp_paths), dst, sdata); + return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata); } -- cgit v1.2.3 From 42bc0c9716c456a9686fcd4ee5cf115b992b9952 Mon Sep 17 00:00:00 2001 From: Simon Graham Date: Wed, 8 Feb 2012 12:34:23 -0500 Subject: rtlwifi: Return correct failure code on error Callers of rtl_pci_init expect zero to be returned on error. Returning the error code leads to, amongst other things, divide by zero panics attempting to use the ring size that is set to zero. Signed-off-by: Simon Graham Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index c503bd3b809..8a941b588a4 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1492,7 +1492,7 @@ static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "tx ring initialization failed\n"); - return err; + return 0; } return 1; -- cgit v1.2.3 From 2cfc6fc584a65db87935ca4e4d5e1ad89d5192ee Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 8 Feb 2012 19:17:11 +0100 Subject: mac80211: do not call rate control .tx_status before .rate_init Most rate control implementations assume .get_rate and .tx_status are only called once the per-station data has been fully initialized. minstrel_ht crashes if this assumption is violated. Signed-off-by: Felix Fietkau Tested-by: Arend van Spriel Signed-off-by: John W. Linville --- net/mac80211/rate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 5fc3135a6b4..fbb1efdc4d0 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -37,7 +37,7 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, struct ieee80211_sta *ista = &sta->sta; void *priv_sta = sta->rate_ctrl_priv; - if (!ref) + if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) return; ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); -- cgit v1.2.3 From 12325280dfeba18164f9c47e226a40ab34e23ee7 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 9 Feb 2012 14:48:25 -0500 Subject: rtlwifi: Modify rtl_pci_init to return 0 on success Fixes problem where caller would think routine succeeded when it failed leading to divide by zero panic. (This also reverts an earlier attempt, commit 42bc0c97 "rtlwifi: Return correct failure code on error". -- JWL) Signed-off-by: Simon Graham Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 8a941b588a4..07dd38efe62 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -1492,10 +1492,10 @@ static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "tx ring initialization failed\n"); - return 0; + return err; } - return 1; + return 0; } static int rtl_pci_start(struct ieee80211_hw *hw) @@ -1866,7 +1866,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, } /* Init PCI sw */ - err = !rtl_pci_init(hw, pdev); + err = rtl_pci_init(hw, pdev); if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Failed to init PCI\n"); goto fail3; -- cgit v1.2.3 From 18daf1644e634bae951a6e3d4d19d89170209762 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 13 Jan 2012 15:11:30 +0100 Subject: Bluetooth: Fix l2cap conn failures for ssp devices Commit 330605423c fixed l2cap conn establishment for non-ssp remote devices by not setting HCI_CONN_ENCRYPT_PEND every time conn security is tested (which was always returning failure on any subsequent security checks). However, this broke l2cap conn establishment for ssp remote devices when an ACL link was already established at SDP-level security. This fix ensures that encryption must be pending whenever authentication is also pending. Signed-off-by: Peter Hurley Tested-by: Daniel Wagner Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3db432473ad..07bc69ed949 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -635,6 +635,10 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { struct hci_cp_auth_requested cp; + + /* encrypt must be pending if auth is also pending */ + set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); + cp.handle = cpu_to_le16(conn->handle); hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); -- cgit v1.2.3 From 19ad9e94f6e2b4b3e1feccfb2466eb6e3e5b8c2a Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 3 Jan 2012 11:53:53 +0100 Subject: Bluetooth: Don't mark non xfer isoc endpoint URBs with URB_ISO_ASAP [ 2096.384084] btusb_send_frame:684: hci0 [ 2096.384087] usb 3-1: BOGUS urb flags, 2 --> 0 [ 2096.384091] Bluetooth: hci0 urb ffff8801b61d3a80 submission failed (22) According the documentation in usb_submit_urb() URB_ISO_ASAP flag is only allowed for endpoints of type USB_ENDPOINT_XFER_ISOC. This reverts commit b8aabfc92249b239c425da7e4ca85b7e4855e984. Signed-off-by: Daniel Wagner Acked-by: Luiz Augusto von Dentz Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index f00f596c102..b7c4f4e2e39 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -726,9 +726,6 @@ static int btusb_send_frame(struct sk_buff *skb) usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len, btusb_tx_complete, skb); - if (skb->priority >= HCI_PRIO_MAX - 1) - urb->transfer_flags = URB_ISO_ASAP; - hdev->stat.acl_tx++; break; -- cgit v1.2.3 From 4aa832c27edf902130f8bace1d42cf22468823fa Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 8 Jan 2012 22:51:16 +0200 Subject: Bluetooth: Remove bogus inline declaration from l2cap_chan_connect As reported by Dan Carpenter this function causes a Sparse warning and shouldn't be declared inline: include/net/bluetooth/l2cap.h:837:30 error: marked inline, but without a definition" Reported-by: Dan Carpenter Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann --- include/net/bluetooth/l2cap.h | 2 +- net/bluetooth/l2cap_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 68f58915069..124f7cf45bd 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -834,7 +834,7 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); struct l2cap_chan *l2cap_chan_create(struct sock *sk); void l2cap_chan_close(struct l2cap_chan *chan, int reason); void l2cap_chan_destroy(struct l2cap_chan *chan); -inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, +int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst); int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u32 priority); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index faf0b11ac1d..980abdb3067 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1120,7 +1120,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr return c1; } -inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst) +int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst) { struct sock *sk = chan->sk; bdaddr_t *src = &bt_sk(sk)->src; -- cgit v1.2.3 From a63752552b95624a9f1dfa3d763870f72f964ad0 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 4 Jan 2012 12:10:41 +0100 Subject: Bluetooth: Fix sk_sndtimeo initialization for L2CAP socket sk_sndtime value should be specified in jiffies thus initial value needs to be converted from miliseconds. Otherwise this timeout is unreliable when CONFIG_HZ is not set to 1000. Signed-off-by: Andrzej Kaczmarek Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index c61d967012b..c57027f7606 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1002,7 +1002,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p INIT_LIST_HEAD(&bt_sk(sk)->accept_q); sk->sk_destruct = l2cap_sock_destruct; - sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT; + sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT); sock_reset_flag(sk, SOCK_ZAPPED); -- cgit v1.2.3 From 6e1da683f79a22fafaada62d547138daaa9e3456 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 4 Jan 2012 12:10:42 +0100 Subject: Bluetooth: l2cap_set_timer needs jiffies as timeout value After moving L2CAP timers to workqueues l2cap_set_timer expects timeout value to be specified in jiffies but constants defined in miliseconds are used. This makes timeouts unreliable when CONFIG_HZ is not set to 1000. __set_chan_timer macro still uses jiffies as input to avoid multiple conversions from/to jiffies for sk_sndtimeo value which is already specified in jiffies. Signed-off-by: Andrzej Kaczmarek Ackec-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/l2cap.h | 6 +++--- net/bluetooth/l2cap_core.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 124f7cf45bd..26486e182f5 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -626,13 +626,13 @@ static inline void l2cap_clear_timer(struct l2cap_chan *chan, #define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t)) #define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer) #define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \ - L2CAP_DEFAULT_RETRANS_TO); + msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); #define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer) #define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \ - L2CAP_DEFAULT_MONITOR_TO); + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO)); #define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer) #define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \ - L2CAP_DEFAULT_ACK_TO); + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); #define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer) static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 980abdb3067..dcccae04ae0 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2970,7 +2970,8 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr default: sk->sk_err = ECONNRESET; - __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT); + __set_chan_timer(chan, + msecs_to_jiffies(L2CAP_DISC_REJ_TIMEOUT)); l2cap_send_disconn_req(conn, chan, ECONNRESET); goto done; } @@ -4478,7 +4479,8 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) if (encrypt == 0x00) { if (chan->sec_level == BT_SECURITY_MEDIUM) { __clear_chan_timer(chan); - __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); + __set_chan_timer(chan, + msecs_to_jiffies(L2CAP_ENC_TIMEOUT)); } else if (chan->sec_level == BT_SECURITY_HIGH) l2cap_chan_close(chan, ECONNREFUSED); } else { @@ -4546,7 +4548,8 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) L2CAP_CONN_REQ, sizeof(req), &req); } else { __clear_chan_timer(chan); - __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); + __set_chan_timer(chan, + msecs_to_jiffies(L2CAP_DISC_TIMEOUT)); } } else if (chan->state == BT_CONNECT2) { struct l2cap_conn_rsp rsp; @@ -4566,7 +4569,8 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) } } else { l2cap_state_change(chan, BT_DISCONN); - __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); + __set_chan_timer(chan, + msecs_to_jiffies(L2CAP_DISC_TIMEOUT)); res = L2CAP_CR_SEC_BLOCK; stat = L2CAP_CS_NO_INFO; } -- cgit v1.2.3 From 331660637b4e5136602a98200a84f6b65ed8d5be Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Wed, 4 Jan 2012 11:57:17 -0300 Subject: Bluetooth: Fix using an absolute timeout on hci_conn_put() queue_delayed_work() expects a relative time for when that work should be scheduled. Signed-off-by: Vinicius Costa Gomes Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ea9231f4935..92b8fea553d 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -561,7 +561,7 @@ static inline void hci_conn_put(struct hci_conn *conn) } cancel_delayed_work_sync(&conn->disc_work); queue_delayed_work(conn->hdev->workqueue, - &conn->disc_work, jiffies + timeo); + &conn->disc_work, timeo); } } -- cgit v1.2.3 From b5a30dda6598af216c070165ece6068f9f00f33a Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sun, 22 Jan 2012 00:28:34 +0200 Subject: Bluetooth: silence lockdep warning Since bluetooth uses multiple protocols types, to avoid lockdep warnings, we need to use different lockdep classes (one for each protocol type). This is already done in bt_sock_create but it misses a couple of cases when new connections are created. This patch corrects that to fix the following warning: <4>[ 1864.732366] ======================================================= <4>[ 1864.733030] [ INFO: possible circular locking dependency detected ] <4>[ 1864.733544] 3.0.16-mid3-00007-gc9a0f62 #3 <4>[ 1864.733883] ------------------------------------------------------- <4>[ 1864.734408] t.android.btclc/4204 is trying to acquire lock: <4>[ 1864.734869] (rfcomm_mutex){+.+.+.}, at: [] rfcomm_dlc_close+0x15/0x30 <4>[ 1864.735541] <4>[ 1864.735549] but task is already holding lock: <4>[ 1864.736045] (sk_lock-AF_BLUETOOTH){+.+.+.}, at: [] lock_sock+0xa/0xc <4>[ 1864.736732] <4>[ 1864.736740] which lock already depends on the new lock. <4>[ 1864.736750] <4>[ 1864.737428] <4>[ 1864.737437] the existing dependency chain (in reverse order) is: <4>[ 1864.738016] <4>[ 1864.738023] -> #1 (sk_lock-AF_BLUETOOTH){+.+.+.}: <4>[ 1864.738549] [] lock_acquire+0x104/0x140 <4>[ 1864.738977] [] lock_sock_nested+0x58/0x68 <4>[ 1864.739411] [] l2cap_sock_sendmsg+0x3e/0x76 <4>[ 1864.739858] [] __sock_sendmsg+0x50/0x59 <4>[ 1864.740279] [] sock_sendmsg+0x94/0xa8 <4>[ 1864.740687] [] kernel_sendmsg+0x28/0x37 <4>[ 1864.741106] [] rfcomm_send_frame+0x30/0x38 <4>[ 1864.741542] [] rfcomm_send_ua+0x58/0x5a <4>[ 1864.741959] [] rfcomm_run+0x441/0xb52 <4>[ 1864.742365] [] kthread+0x63/0x68 <4>[ 1864.742742] [] kernel_thread_helper+0x6/0xd <4>[ 1864.743187] <4>[ 1864.743193] -> #0 (rfcomm_mutex){+.+.+.}: <4>[ 1864.743667] [] __lock_acquire+0x988/0xc00 <4>[ 1864.744100] [] lock_acquire+0x104/0x140 <4>[ 1864.744519] [] __mutex_lock_common+0x3b/0x33f <4>[ 1864.744975] [] mutex_lock_nested+0x2d/0x36 <4>[ 1864.745412] [] rfcomm_dlc_close+0x15/0x30 <4>[ 1864.745842] [] __rfcomm_sock_close+0x5f/0x6b <4>[ 1864.746288] [] rfcomm_sock_shutdown+0x2f/0x62 <4>[ 1864.746737] [] sys_socketcall+0x1db/0x422 <4>[ 1864.747165] [] syscall_call+0x7/0xb Signed-off-by: Octavian Purdila Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/bluetooth.h | 2 ++ net/bluetooth/af_bluetooth.c | 12 +++++------- net/bluetooth/l2cap_sock.c | 2 ++ net/bluetooth/rfcomm/sock.c | 2 ++ 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index abaad6ed9b8..4a82ca0bb0b 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -256,4 +256,6 @@ void l2cap_exit(void); int sco_init(void); void sco_exit(void); +void bt_sock_reclassify_lock(struct sock *sk, int proto); + #endif /* __BLUETOOTH_H */ diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index ef92864ac62..72eb187a5f6 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -71,19 +71,16 @@ static const char *const bt_slock_key_strings[BT_MAX_PROTO] = { "slock-AF_BLUETOOTH-BTPROTO_AVDTP", }; -static inline void bt_sock_reclassify_lock(struct socket *sock, int proto) +void bt_sock_reclassify_lock(struct sock *sk, int proto) { - struct sock *sk = sock->sk; - - if (!sk) - return; - + BUG_ON(!sk); BUG_ON(sock_owned_by_user(sk)); sock_lock_init_class_and_name(sk, bt_slock_key_strings[proto], &bt_slock_key[proto], bt_key_strings[proto], &bt_lock_key[proto]); } +EXPORT_SYMBOL(bt_sock_reclassify_lock); int bt_sock_register(int proto, const struct net_proto_family *ops) { @@ -145,7 +142,8 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto, if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { err = bt_proto[proto]->create(net, sock, proto, kern); - bt_sock_reclassify_lock(sock, proto); + if (!err) + bt_sock_reclassify_lock(sock->sk, proto); module_put(bt_proto[proto]->owner); } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index c57027f7606..401d9428ae4 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -849,6 +849,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data) if (!sk) return NULL; + bt_sock_reclassify_lock(sk, BTPROTO_L2CAP); + l2cap_sock_init(sk, parent); return l2cap_pi(sk)->chan; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index f066678faee..22169c3f148 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -956,6 +956,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * if (!sk) goto done; + bt_sock_reclassify_lock(sk, BTPROTO_RFCOMM); + rfcomm_sock_init(sk, parent); bacpy(&bt_sk(sk)->src, &src); bacpy(&bt_sk(sk)->dst, &dst); -- cgit v1.2.3 From a51cd2be864a3cc0272359b1995e213341dfc7e7 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 27 Jan 2012 19:42:02 -0300 Subject: Bluetooth: Fix potential deadlock We don't need to use the _sync variant in hci_conn_hold and hci_conn_put to cancel conn->disc_work delayed work. This way we avoid potential deadlocks like this one reported by lockdep. ====================================================== [ INFO: possible circular locking dependency detected ] 3.2.0+ #1 Not tainted ------------------------------------------------------- kworker/u:1/17 is trying to acquire lock: (&hdev->lock){+.+.+.}, at: [] hci_conn_timeout+0x62/0x158 [bluetooth] but task is already holding lock: ((&(&conn->disc_work)->work)){+.+...}, at: [] process_one_work+0x11a/0x2bf which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 ((&(&conn->disc_work)->work)){+.+...}: [] lock_acquire+0x8a/0xa7 [] wait_on_work+0x3d/0xaa [] __cancel_work_timer+0xac/0xef [] cancel_delayed_work_sync+0xd/0xf [] smp_chan_create+0xde/0xe6 [bluetooth] [] smp_conn_security+0xa3/0x12d [bluetooth] [] l2cap_connect_cfm+0x237/0x2e8 [bluetooth] [] hci_proto_connect_cfm+0x2d/0x6f [bluetooth] [] hci_event_packet+0x29d1/0x2d60 [bluetooth] [] hci_rx_work+0xd0/0x2e1 [bluetooth] [] process_one_work+0x178/0x2bf [] worker_thread+0xce/0x152 [] kthread+0x95/0x9d [] kernel_thread_helper+0x4/0x10 -> #1 (slock-AF_BLUETOOTH-BTPROTO_L2CAP){+.+...}: [] lock_acquire+0x8a/0xa7 [] _raw_spin_lock_bh+0x36/0x6a [] lock_sock_nested+0x24/0x7f [] lock_sock+0xb/0xd [bluetooth] [] l2cap_chan_connect+0xa9/0x26f [bluetooth] [] l2cap_sock_connect+0xb3/0xff [bluetooth] [] sys_connect+0x69/0x8a [] system_call_fastpath+0x16/0x1b -> #0 (&hdev->lock){+.+.+.}: [] __lock_acquire+0xa80/0xd74 [] lock_acquire+0x8a/0xa7 [] __mutex_lock_common+0x48/0x38e [] mutex_lock_nested+0x2a/0x31 [] hci_conn_timeout+0x62/0x158 [bluetooth] [] process_one_work+0x178/0x2bf [] worker_thread+0xce/0x152 [] kthread+0x95/0x9d [] kernel_thread_helper+0x4/0x10 other info that might help us debug this: Chain exists of: &hdev->lock --> slock-AF_BLUETOOTH-BTPROTO_L2CAP --> (&(&conn->disc_work)->work) Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock((&(&conn->disc_work)->work)); lock(slock-AF_BLUETOOTH-BTPROTO_L2CAP); lock((&(&conn->disc_work)->work)); lock(&hdev->lock); *** DEADLOCK *** 2 locks held by kworker/u:1/17: #0: (hdev->name){.+.+.+}, at: [] process_one_work+0x11a/0x2bf #1: ((&(&conn->disc_work)->work)){+.+...}, at: [] process_one_work+0x11a/0x2bf stack backtrace: Pid: 17, comm: kworker/u:1 Not tainted 3.2.0+ #1 Call Trace: [] print_circular_bug+0x1f8/0x209 [] __lock_acquire+0xa80/0xd74 [] ? arch_local_irq_restore+0x6/0xd [] ? vprintk+0x3f9/0x41e [] lock_acquire+0x8a/0xa7 [] ? hci_conn_timeout+0x62/0x158 [bluetooth] [] __mutex_lock_common+0x48/0x38e [] ? hci_conn_timeout+0x62/0x158 [bluetooth] [] ? __dynamic_pr_debug+0x6d/0x6f [] ? hci_conn_timeout+0x62/0x158 [bluetooth] [] ? trace_hardirqs_off+0xd/0xf [] mutex_lock_nested+0x2a/0x31 [] hci_conn_timeout+0x62/0x158 [bluetooth] [] process_one_work+0x178/0x2bf [] ? process_one_work+0x11a/0x2bf [] ? lock_acquired+0x1d0/0x1df [] ? hci_acl_disconn+0x65/0x65 [bluetooth] [] worker_thread+0xce/0x152 [] ? finish_task_switch+0x45/0xc5 [] ? manage_workers.isra.25+0x16a/0x16a [] kthread+0x95/0x9d [] kernel_thread_helper+0x4/0x10 [] ? retint_restore_args+0x13/0x13 [] ? __init_kthread_worker+0x55/0x55 [] ? gs_change+0x13/0x13 Signed-off-by: Andre Guedes Signed-off-by: Vinicius Costa Gomes Reviewed-by: Ulisses Furquim Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 92b8fea553d..453893b3120 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -540,7 +540,7 @@ void hci_conn_put_device(struct hci_conn *conn); static inline void hci_conn_hold(struct hci_conn *conn) { atomic_inc(&conn->refcnt); - cancel_delayed_work_sync(&conn->disc_work); + cancel_delayed_work(&conn->disc_work); } static inline void hci_conn_put(struct hci_conn *conn) @@ -559,7 +559,7 @@ static inline void hci_conn_put(struct hci_conn *conn) } else { timeo = msecs_to_jiffies(10); } - cancel_delayed_work_sync(&conn->disc_work); + cancel_delayed_work(&conn->disc_work); queue_delayed_work(conn->hdev->workqueue, &conn->disc_work, timeo); } -- cgit v1.2.3 From cf33e77b76d7439f21a23a94eab4ab3b405a6a7d Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Fri, 27 Jan 2012 19:32:39 +0200 Subject: Bluetooth: Fix RFCOMM session reference counting issue There is an imbalance in the rfcomm_session_hold / rfcomm_session_put operations which causes the following crash: [ 685.010159] BUG: unable to handle kernel paging request at 6b6b6b6b [ 685.010169] IP: [] rfcomm_process_dlcs+0x1b/0x15e [ 685.010181] *pdpt = 000000002d665001 *pde = 0000000000000000 [ 685.010191] Oops: 0000 [#1] PREEMPT SMP [ 685.010247] [ 685.010255] Pid: 947, comm: krfcommd Tainted: G C 3.0.16-mid8-dirty #44 [ 685.010266] EIP: 0060:[] EFLAGS: 00010246 CPU: 1 [ 685.010274] EIP is at rfcomm_process_dlcs+0x1b/0x15e [ 685.010281] EAX: e79f551c EBX: 6b6b6b6b ECX: 00000007 EDX: e79f40b4 [ 685.010288] ESI: e79f4060 EDI: ed4e1f70 EBP: ed4e1f68 ESP: ed4e1f50 [ 685.010295] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 685.010303] Process krfcommd (pid: 947, ti=ed4e0000 task=ed43e5e0 task.ti=ed4e0000) [ 685.010308] Stack: [ 685.010312] ed4e1f68 c149eb53 e5925150 e79f4060 ed500000 ed4e1f70 ed4e1f80 c149ec10 [ 685.010331] 00000000 ed43e5e0 00000000 ed4e1f90 ed4e1f9c c149ec87 0000bf54 00000000 [ 685.010348] 00000000 ee03bf54 c149ec37 ed4e1fe4 c104fe01 00000000 00000000 00000000 [ 685.010367] Call Trace: [ 685.010376] [] ? rfcomm_process_rx+0x6e/0x74 [ 685.010387] [] rfcomm_process_sessions+0xb7/0xde [ 685.010398] [] rfcomm_run+0x50/0x6d [ 685.010409] [] ? rfcomm_process_sessions+0xde/0xde [ 685.010419] [] kthread+0x63/0x68 [ 685.010431] [] ? __init_kthread_worker+0x42/0x42 [ 685.010442] [] kernel_thread_helper+0x6/0xd This issue has been brought up earlier here: https://lkml.org/lkml/2011/5/21/127 The issue appears to be the rfcomm_session_put in rfcomm_recv_ua. This operation doesn't seem be to required as for the non-initiator case we have the rfcomm_process_rx doing an explicit put and in the initiator case the last dlc_unlink will drive the reference counter to 0. There have been several attempts to fix these issue: 6c2718d Bluetooth: Do not call rfcomm_session_put() for RFCOMM UA on closed socket 683d949 Bluetooth: Never deallocate a session when some DLC points to it but AFAICS they do not fix the issue just make it harder to reproduce. Signed-off-by: Octavian Purdila Signed-off-by: Gopala Krishna Murala Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/rfcomm/core.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 501649bf559..8a602388f1e 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1164,12 +1164,18 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) break; case BT_DISCONN: - /* When socket is closed and we are not RFCOMM - * initiator rfcomm_process_rx already calls - * rfcomm_session_put() */ - if (s->sock->sk->sk_state != BT_CLOSED) - if (list_empty(&s->dlcs)) - rfcomm_session_put(s); + /* rfcomm_session_put is called later so don't do + * anything here otherwise we will mess up the session + * reference counter: + * + * (a) when we are the initiator dlc_unlink will drive + * the reference counter to 0 (there is no initial put + * after session_add) + * + * (b) when we are not the initiator rfcomm_rx_process + * will explicitly call put to balance the initial hold + * done after session add. + */ break; } } -- cgit v1.2.3 From ca0d6c7ece0e78268cd7c5c378d6b1b610625085 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 3 Feb 2012 21:29:40 +0200 Subject: Bluetooth: Add missing QUIRK_NO_RESET test to hci_dev_do_close We should only perform a reset in hci_dev_do_close if the HCI_QUIRK_NO_RESET flag is set (since in such a case a reset will not be performed when initializing the device). Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann --- net/bluetooth/hci_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 9de93714213..5aeb6249119 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -640,7 +640,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) /* Reset device */ skb_queue_purge(&hdev->cmd_q); atomic_set(&hdev->cmd_cnt, 1); - if (!test_bit(HCI_RAW, &hdev->flags)) { + if (!test_bit(HCI_RAW, &hdev->flags) && + test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) { set_bit(HCI_INIT, &hdev->flags); __hci_request(hdev, hci_reset_req, 0, msecs_to_jiffies(250)); -- cgit v1.2.3 From 403f048a57050add364827fb3e2650af86463168 Mon Sep 17 00:00:00 2001 From: Manoj Iyer Date: Thu, 2 Feb 2012 09:32:36 -0600 Subject: Bluetooth: btusb: Add vendor specific ID (0a5c 21f3) for BCM20702A0 T: Bus=01 Lev=02 Prnt=02 Port=03 Cnt=03 Dev#= 5 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0a5c ProdID=21f3 Rev=01.12 S: Manufacturer=Broadcom Corp S: Product=BCM20702A0 S: SerialNumber=74DE2B344A7B C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) Signed-off-by: Manoj Iyer Tested-by: Dennis Chua Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index b7c4f4e2e39..789c9b579ae 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -102,6 +102,7 @@ static struct usb_device_id btusb_table[] = { /* Broadcom BCM20702A0 */ { USB_DEVICE(0x0a5c, 0x21e3) }, + { USB_DEVICE(0x0a5c, 0x21f3) }, { USB_DEVICE(0x413c, 0x8197) }, { } /* Terminating entry */ -- cgit v1.2.3 From 6de32750822d00bfa92c341166132b0714c5b559 Mon Sep 17 00:00:00 2001 From: Ulisses Furquim Date: Mon, 30 Jan 2012 18:26:28 -0200 Subject: Bluetooth: Remove usage of __cancel_delayed_work() __cancel_delayed_work() is being used in some paths where we cannot sleep waiting for the delayed work to finish. However, that function might return while the timer is running and the work will be queued again. Replace the calls with safer cancel_delayed_work() version which spins until the timer handler finishes on other CPUs and cancels the delayed work. Signed-off-by: Ulisses Furquim Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/l2cap.h | 4 ++-- net/bluetooth/l2cap_core.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 26486e182f5..b1664ed884e 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -611,7 +611,7 @@ static inline void l2cap_set_timer(struct l2cap_chan *chan, { BT_DBG("chan %p state %d timeout %ld", chan, chan->state, timeout); - if (!__cancel_delayed_work(work)) + if (!cancel_delayed_work(work)) l2cap_chan_hold(chan); schedule_delayed_work(work, timeout); } @@ -619,7 +619,7 @@ static inline void l2cap_set_timer(struct l2cap_chan *chan, static inline void l2cap_clear_timer(struct l2cap_chan *chan, struct delayed_work *work) { - if (__cancel_delayed_work(work)) + if (cancel_delayed_work(work)) l2cap_chan_put(chan); } diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index dcccae04ae0..ec10c698b89 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2574,7 +2574,7 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && cmd->ident == conn->info_ident) { - __cancel_delayed_work(&conn->info_timer); + cancel_delayed_work(&conn->info_timer); conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; conn->info_ident = 0; @@ -3121,7 +3121,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) return 0; - __cancel_delayed_work(&conn->info_timer); + cancel_delayed_work(&conn->info_timer); if (result != L2CAP_IR_SUCCESS) { conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; @@ -4501,7 +4501,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) if (hcon->type == LE_LINK) { smp_distribute_keys(conn, 0); - __cancel_delayed_work(&conn->security_timer); + cancel_delayed_work(&conn->security_timer); } rcu_read_lock(); -- cgit v1.2.3 From 24d2b8c0ac5c8ec41c26ed432238b0e027184882 Mon Sep 17 00:00:00 2001 From: Ulisses Furquim Date: Mon, 30 Jan 2012 18:26:29 -0200 Subject: Bluetooth: Fix possible use after free in delete path We need to use the _sync() version for cancelling the info and security timer in the L2CAP connection delete path. Otherwise the delayed work handler might run after the connection object is freed. Signed-off-by: Ulisses Furquim Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index ec10c698b89..32d338c30e6 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1018,10 +1018,10 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) hci_chan_del(conn->hchan); if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) - __cancel_delayed_work(&conn->info_timer); + cancel_delayed_work_sync(&conn->info_timer); if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) { - __cancel_delayed_work(&conn->security_timer); + cancel_delayed_work_sync(&conn->security_timer); smp_chan_destroy(conn); } -- cgit v1.2.3 From 4b5a433ae5348c23caa0b5f0a2fca7c342acb200 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 20 Jan 2012 13:55:23 +0100 Subject: mac80211: call rate control only after init There are situations where we don't have the necessary rate control information yet for station entries, e.g. when associating. This currently doesn't really happen due to the dummy station handling; explicitly disabling rate control when it's not initialised will allow us to remove dummy stations. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs_sta.c | 4 ++-- net/mac80211/rate.c | 2 +- net/mac80211/rate.h | 1 + net/mac80211/sta_info.h | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 2406b3e7393..d86217d56bd 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -63,14 +63,14 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" int res = scnprintf(buf, sizeof(buf), - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", TEST(AUTH), TEST(ASSOC), TEST(PS_STA), TEST(PS_DRIVER), TEST(AUTHORIZED), TEST(SHORT_PREAMBLE), TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT), TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), - TEST(TDLS_PEER_AUTH)); + TEST(TDLS_PEER_AUTH), TEST(RATE_CONTROL)); #undef TEST return simple_read_from_buffer(userbuf, count, ppos, buf, res); } diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 5a5a7767d54..ad64f4d5271 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -336,7 +336,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, int i; u32 mask; - if (sta) { + if (sta && test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) { ista = &sta->sta; priv_sta = sta->rate_ctrl_priv; } diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 168427b0ffd..2b83f32144f 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -62,6 +62,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; ref->ops->rate_init(ref->priv, sband, ista, priv_sta); + set_sta_flag(sta, WLAN_STA_RATE_CONTROL); } static inline void rate_control_rate_update(struct ieee80211_local *local, diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 6f77f12dc3f..bfed851d0d3 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -52,6 +52,7 @@ * @WLAN_STA_SP: Station is in a service period, so don't try to * reply to other uAPSD trigger frames or PS-Poll. * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. + * @WLAN_STA_RATE_CONTROL: rate control was initialized for this station. */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH, @@ -71,6 +72,7 @@ enum ieee80211_sta_info_flags { WLAN_STA_UAPSD, WLAN_STA_SP, WLAN_STA_4ADDR_EVENT, + WLAN_STA_RATE_CONTROL, }; enum ieee80211_sta_state { -- cgit v1.2.3 From 216c57b214bd621335ff698b475f6db2802502dc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 8 Feb 2012 19:17:11 +0100 Subject: mac80211: do not call rate control .tx_status before .rate_init Most rate control implementations assume .get_rate and .tx_status are only called once the per-station data has been fully initialized. minstrel_ht crashes if this assumption is violated. Signed-off-by: Felix Fietkau Tested-by: Arend van Spriel Signed-off-by: John W. Linville --- net/mac80211/rate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 2b83f32144f..80cfc006dd7 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -41,7 +41,7 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, struct ieee80211_sta *ista = &sta->sta; void *priv_sta = sta->rate_ctrl_priv; - if (!ref) + if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) return; ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); -- cgit v1.2.3 From 6670f15b1f6858a43b292d8ab64464e9f085a6aa Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 9 Feb 2012 18:32:22 -0800 Subject: mwifiex: clear previous security setting during association Driver maintains different flags for WEP, WPA, WPA2 security modes. Appropriate flag is set using security information provided in connect request. mwifiex_is_network_compatible() routine uses them to check if driver's setting is compatible with AP. Association is aborted if the routine fails. For some corner cases, it is observed that association is failed even for valid security information based on association history. This patch fixes the problem by clearing previous security setting during each association. We should set WEP key provided in connect request as default tx key. This missing change is also added here. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index c3b6c4652cd..5b2972b43b0 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -841,7 +841,12 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, ret = mwifiex_set_rf_channel(priv, channel, priv->adapter->channel_type); - ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); /* Disable keys */ + /* As this is new association, clear locally stored + * keys and security related flags */ + priv->sec_info.wpa_enabled = false; + priv->sec_info.wpa2_enabled = false; + priv->wep_key_curr_index = 0; + ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); if (mode == NL80211_IFTYPE_ADHOC) { /* "privacy" is set only for ad-hoc mode */ @@ -886,6 +891,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, dev_dbg(priv->adapter->dev, "info: setting wep encryption" " with key len %d\n", sme->key_len); + priv->wep_key_curr_index = sme->key_idx; ret = mwifiex_set_encode(priv, sme->key, sme->key_len, sme->key_idx, 0); } -- cgit v1.2.3 From 2504a6423b9ab4c36df78227055995644de19edb Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Sat, 11 Feb 2012 10:01:53 -0500 Subject: ath9k: stop on rates with idx -1 in ath9k rate control's .tx_status Rate control algorithms are supposed to stop processing when they encounter a rate with the index -1. Checking for rate->count not being zero is not enough. Allowing a rate with negative index leads to memory corruption in ath_debug_stat_rc(). One consequence of the bug is discussed at https://bugzilla.redhat.com/show_bug.cgi?id=768639 Signed-off-by: Pavel Roskin Cc: stable@vger.kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 635b592ad96..a427a16bb73 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1346,7 +1346,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, fc = hdr->frame_control; for (i = 0; i < sc->hw->max_rates; i++) { struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; - if (!rate->count) + if (rate->idx < 0 || !rate->count) break; final_ts_idx = i; -- cgit v1.2.3