From 784f694d0f3ca927361aa0c26de1aa340eb5b275 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:39 +0200 Subject: [PATCH 01/97] wl12xx: replace wl->mac_addr with vif->addr The mac address of the interface already exists in vif->addr. Use it instead of wl->mac_addr. It seems that due to some fw bug, we still need to set nvs->mac to the actual mac addresss, otherwise the fw doesn't function well (e.g. can't get dhcp address). Thus, use wl->mac_addr for this purpose, and don't delete it yet. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 9 ++++---- drivers/net/wireless/wl12xx/cmd.h | 5 +++-- drivers/net/wireless/wl12xx/event.c | 2 +- drivers/net/wireless/wl12xx/init.c | 29 ++++++++++++++----------- drivers/net/wireless/wl12xx/init.h | 4 ++-- drivers/net/wireless/wl12xx/main.c | 19 +++++++++++------ drivers/net/wireless/wl12xx/scan.c | 32 ++++++++++++++++------------ drivers/net/wireless/wl12xx/scan.h | 5 +++-- drivers/net/wireless/wl12xx/wl12xx.h | 1 + 9 files changed, 62 insertions(+), 44 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index a52299e548fa..bee44c7d67fd 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -358,7 +358,8 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) return 0; } -int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id) +int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, + u8 *role_id) { struct wl12xx_cmd_role_enable *cmd; int ret; @@ -381,7 +382,7 @@ int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id) goto out_free; } - memcpy(cmd->mac_address, wl->mac_addr, ETH_ALEN); + memcpy(cmd->mac_address, addr, ETH_ALEN); cmd->role_type = role_type; ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0); @@ -1200,14 +1201,14 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr) return ret; } -int wl1271_build_qos_null_data(struct wl1271 *wl) +int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif) { struct ieee80211_qos_hdr template; memset(&template, 0, sizeof(template)); memcpy(template.addr1, wl->bssid, ETH_ALEN); - memcpy(template.addr2, wl->mac_addr, ETH_ALEN); + memcpy(template.addr2, vif->addr, ETH_ALEN); memcpy(template.addr3, wl->bssid, ETH_ALEN); template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index b7bd42769aa7..1ae949f00c14 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -36,7 +36,8 @@ int wl128x_cmd_general_parms(struct wl1271 *wl); int wl1271_cmd_radio_parms(struct wl1271 *wl); int wl128x_cmd_radio_parms(struct wl1271 *wl); int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); -int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id); +int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, + u8 *role_id); int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); int wl12xx_cmd_role_start_dev(struct wl1271 *wl); int wl12xx_cmd_role_stop_dev(struct wl1271 *wl); @@ -62,7 +63,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, struct sk_buff *skb); int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); -int wl1271_build_qos_null_data(struct wl1271 *wl); +int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif); int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid); int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 674ad2a9e409..7e3ff808feef 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -234,7 +234,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl1271_debug(DEBUG_EVENT, "status: 0x%x", mbox->scheduled_scan_status); - wl1271_scan_stm(wl); + wl1271_scan_stm(wl, wl->scan_vif); } if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 04db64c94e9a..4692a91ca737 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -123,7 +123,8 @@ out: return ret; } -static int wl1271_ap_init_null_template(struct wl1271 *wl) +static int wl1271_ap_init_null_template(struct wl1271 *wl, + struct ieee80211_vif *vif) { struct ieee80211_hdr_3addr *nullfunc; int ret; @@ -141,8 +142,8 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl) /* nullfunc->addr1 is filled by FW */ - memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN); - memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN); + memcpy(nullfunc->addr2, vif->addr, ETH_ALEN); + memcpy(nullfunc->addr3, vif->addr, ETH_ALEN); rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc, @@ -153,7 +154,8 @@ out: return ret; } -static int wl1271_ap_init_qos_null_template(struct wl1271 *wl) +static int wl1271_ap_init_qos_null_template(struct wl1271 *wl, + struct ieee80211_vif *vif) { struct ieee80211_qos_hdr *qosnull; int ret; @@ -171,8 +173,8 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl) /* qosnull->addr1 is filled by FW */ - memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN); - memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN); + memcpy(qosnull->addr2, vif->addr, ETH_ALEN); + memcpy(qosnull->addr3, vif->addr, ETH_ALEN); rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull, @@ -449,7 +451,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) return 0; } -int wl1271_ap_init_templates(struct wl1271 *wl) +int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif) { int ret; @@ -457,11 +459,11 @@ int wl1271_ap_init_templates(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_ap_init_null_template(wl); + ret = wl1271_ap_init_null_template(wl, vif); if (ret < 0) return ret; - ret = wl1271_ap_init_qos_null_template(wl); + ret = wl1271_ap_init_qos_null_template(wl, vif); if (ret < 0) return ret; @@ -476,9 +478,10 @@ int wl1271_ap_init_templates(struct wl1271 *wl) return 0; } -static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) +static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl, + struct ieee80211_vif *vif) { - return wl1271_ap_init_templates(wl); + return wl1271_ap_init_templates(wl, vif); } int wl1271_init_ap_rates(struct wl1271 *wl) @@ -576,7 +579,7 @@ out: } -int wl1271_hw_init(struct wl1271 *wl) +int wl1271_hw_init(struct wl1271 *wl, struct ieee80211_vif *vif) { struct conf_tx_ac_category *conf_ac; struct conf_tx_tid *conf_tid; @@ -694,7 +697,7 @@ int wl1271_hw_init(struct wl1271 *wl) /* Mode specific init - post mem init */ if (is_ap) - ret = wl1271_ap_hw_init_post_mem(wl); + ret = wl1271_ap_hw_init_post_mem(wl, vif); else ret = wl1271_sta_hw_init_post_mem(wl); diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h index 3a3c230fd292..b1f97bcc47c0 100644 --- a/drivers/net/wireless/wl12xx/init.h +++ b/drivers/net/wireless/wl12xx/init.h @@ -32,8 +32,8 @@ int wl1271_init_phy_config(struct wl1271 *wl); int wl1271_init_pta(struct wl1271 *wl); int wl1271_init_energy_detection(struct wl1271 *wl); int wl1271_chip_specific_init(struct wl1271 *wl); -int wl1271_hw_init(struct wl1271 *wl); +int wl1271_hw_init(struct wl1271 *wl, struct ieee80211_vif *vif); int wl1271_init_ap_rates(struct wl1271 *wl); -int wl1271_ap_init_templates(struct wl1271 *wl); +int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif); #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 884f82b63219..652471e8c61b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1896,6 +1896,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, ret = -EINVAL; goto out; } + /* + * we still need this in order to configure the fw + * while uploading the nvs + */ memcpy(wl->mac_addr, vif->addr, ETH_ALEN); if (wl->state != WL1271_STATE_OFF) { @@ -1923,18 +1927,19 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, * the STA role can get packets only from * its associated bssid) */ - ret = wl12xx_cmd_role_enable(wl, + ret = wl12xx_cmd_role_enable(wl, vif->addr, WL1271_ROLE_DEVICE, &wl->dev_role_id); if (ret < 0) goto irq_disable; } - ret = wl12xx_cmd_role_enable(wl, role_type, &wl->role_id); + ret = wl12xx_cmd_role_enable(wl, vif->addr, + role_type, &wl->role_id); if (ret < 0) goto irq_disable; - ret = wl1271_hw_init(wl); + ret = wl1271_hw_init(wl, vif); if (ret < 0) goto irq_disable; @@ -2019,6 +2024,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); + wl->scan_vif = NULL; wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, true); } @@ -2885,7 +2891,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, wl12xx_cmd_role_stop_dev(wl); } - ret = wl1271_scan(hw->priv, ssid, len, req); + ret = wl1271_scan(hw->priv, vif, ssid, len, req); out_sleep: wl1271_ps_elp_sleep(wl); out: @@ -2921,6 +2927,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, } wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); + wl->scan_vif = NULL; wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, true); @@ -3295,7 +3302,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, goto out; } - ret = wl1271_ap_init_templates(wl); + ret = wl1271_ap_init_templates(wl, vif); if (ret < 0) goto out; } @@ -3428,7 +3435,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (ret < 0) goto out; - ret = wl1271_build_qos_null_data(wl); + ret = wl1271_build_qos_null_data(wl, vif); if (ret < 0) goto out; diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 128ccb79318c..a8576181ab7f 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -53,6 +53,7 @@ void wl1271_scan_complete_work(struct work_struct *work) wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan.req = NULL; + wl->scan_vif = NULL; ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) @@ -155,8 +156,9 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, #define WL1271_NOTHING_TO_SCAN 1 -static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, - bool passive, u32 basic_rate) +static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, + enum ieee80211_band band, + bool passive, u32 basic_rate) { struct wl1271_cmd_scan *cmd; struct wl1271_cmd_trigger_scan_to *trigger; @@ -208,7 +210,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len); } - memcpy(cmd->addr, wl->mac_addr, ETH_ALEN); + memcpy(cmd->addr, vif->addr, ETH_ALEN); ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len, wl->scan.req->ie, wl->scan.req->ie_len, @@ -241,7 +243,7 @@ out: return ret; } -void wl1271_scan_stm(struct wl1271 *wl) +void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) { int ret = 0; enum ieee80211_band band; @@ -254,10 +256,10 @@ void wl1271_scan_stm(struct wl1271 *wl) case WL1271_SCAN_STATE_2GHZ_ACTIVE: band = IEEE80211_BAND_2GHZ; rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); - ret = wl1271_scan_send(wl, band, false, rate); + ret = wl1271_scan_send(wl, vif, band, false, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; - wl1271_scan_stm(wl); + wl1271_scan_stm(wl, vif); } break; @@ -265,13 +267,13 @@ void wl1271_scan_stm(struct wl1271 *wl) case WL1271_SCAN_STATE_2GHZ_PASSIVE: band = IEEE80211_BAND_2GHZ; rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); - ret = wl1271_scan_send(wl, band, true, rate); + ret = wl1271_scan_send(wl, vif, band, true, rate); if (ret == WL1271_NOTHING_TO_SCAN) { if (wl->enable_11a) wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; else wl->scan.state = WL1271_SCAN_STATE_DONE; - wl1271_scan_stm(wl); + wl1271_scan_stm(wl, vif); } break; @@ -279,10 +281,10 @@ void wl1271_scan_stm(struct wl1271 *wl) case WL1271_SCAN_STATE_5GHZ_ACTIVE: band = IEEE80211_BAND_5GHZ; rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); - ret = wl1271_scan_send(wl, band, false, rate); + ret = wl1271_scan_send(wl, vif, band, false, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; - wl1271_scan_stm(wl); + wl1271_scan_stm(wl, vif); } break; @@ -290,10 +292,10 @@ void wl1271_scan_stm(struct wl1271 *wl) case WL1271_SCAN_STATE_5GHZ_PASSIVE: band = IEEE80211_BAND_5GHZ; rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); - ret = wl1271_scan_send(wl, band, true, rate); + ret = wl1271_scan_send(wl, vif, band, true, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_DONE; - wl1271_scan_stm(wl); + wl1271_scan_stm(wl, vif); } break; @@ -317,7 +319,8 @@ void wl1271_scan_stm(struct wl1271 *wl) } } -int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, +int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, + const u8 *ssid, size_t ssid_len, struct cfg80211_scan_request *req) { /* @@ -338,6 +341,7 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, wl->scan.ssid_len = 0; } + wl->scan_vif = vif; wl->scan.req = req; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); @@ -346,7 +350,7 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, msecs_to_jiffies(WL1271_SCAN_TIMEOUT)); - wl1271_scan_stm(wl); + wl1271_scan_stm(wl, vif); return 0; } diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h index 92115156522f..15177bdfb542 100644 --- a/drivers/net/wireless/wl12xx/scan.h +++ b/drivers/net/wireless/wl12xx/scan.h @@ -26,13 +26,14 @@ #include "wl12xx.h" -int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, +int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, + const u8 *ssid, size_t ssid_len, struct cfg80211_scan_request *req); int wl1271_scan_stop(struct wl1271 *wl); int wl1271_scan_build_probe_req(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 band); -void wl1271_scan_stm(struct wl1271 *wl); +void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif); void wl1271_scan_complete_work(struct work_struct *work); int wl1271_scan_sched_scan_config(struct wl1271 *wl, struct cfg80211_sched_scan_request *req, diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 1ec90fc7505e..b8de2f5e052b 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -507,6 +507,7 @@ struct wl1271 { u32 mbox_ptr[2]; /* Are we currently scanning */ + struct ieee80211_vif *scan_vif; struct wl1271_scan scan; struct delayed_work scan_complete_work; From 92c77c734f958474ac73af670834bc32cb833e54 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:40 +0200 Subject: [PATCH 02/97] wl12xx: start reworking the init sequence Split the init sequence into common commands (non role-specific) and role-specific commands. We still need to call the common commands only on add_interface() (rather than on start()) as the fw must get the mac address when uploading the nvs. Future patches will refactor the init sequence further more. Signed-off-by: Eliad Peller [fixed a couple of sparse warnings] Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/init.c | 310 +++++++++++++++-------------- drivers/net/wireless/wl12xx/init.h | 5 +- drivers/net/wireless/wl12xx/main.c | 8 +- 3 files changed, 173 insertions(+), 150 deletions(-) diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 4692a91ca737..145601dddab0 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -33,7 +33,7 @@ #include "tx.h" #include "io.h" -int wl1271_sta_init_templates_config(struct wl1271 *wl) +int wl1271_init_templates_config(struct wl1271 *wl) { int ret, i; @@ -88,6 +88,29 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl) if (ret < 0) return ret; + /* + * Put very large empty placeholders for all templates. These + * reserve memory for later. + */ + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL, + WL1271_CMD_TEMPL_MAX_SIZE, + 0, WL1271_RATE_AUTOMATIC); + if (ret < 0) + return ret; + + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL, + WL1271_CMD_TEMPL_MAX_SIZE, + 0, WL1271_RATE_AUTOMATIC); + if (ret < 0) + return ret; + + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL, + sizeof + (struct wl12xx_disconn_template), + 0, WL1271_RATE_AUTOMATIC); + if (ret < 0) + return ret; + for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, WL1271_CMD_TEMPL_DFLT_SIZE, i, @@ -185,49 +208,6 @@ out: return ret; } -static int wl1271_ap_init_templates_config(struct wl1271 *wl) -{ - int ret; - - /* - * Put very large empty placeholders for all templates. These - * reserve memory for later. - */ - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, - 0, WL1271_RATE_AUTOMATIC); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, - 0, WL1271_RATE_AUTOMATIC); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL, - sizeof - (struct wl12xx_disconn_template), - 0, WL1271_RATE_AUTOMATIC); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, - sizeof(struct wl12xx_null_data_template), - 0, WL1271_RATE_AUTOMATIC); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, - sizeof - (struct wl12xx_qos_null_data_template), - 0, WL1271_RATE_AUTOMATIC); - if (ret < 0) - return ret; - - return 0; -} - static int wl12xx_init_rx_config(struct wl1271 *wl) { int ret; @@ -247,6 +227,13 @@ int wl1271_init_phy_config(struct wl1271 *wl) if (ret < 0) return ret; + return 0; +} + +static int wl12xx_init_phy_vif_config(struct wl1271 *wl) +{ + int ret; + ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME); if (ret < 0) return ret; @@ -329,6 +316,7 @@ static int wl12xx_init_fwlog(struct wl1271 *wl) return 0; } +/* generic sta initialization (non vif-specific) */ static int wl1271_sta_hw_init(struct wl1271 *wl) { int ret; @@ -344,57 +332,20 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_sta_init_templates_config(wl); - if (ret < 0) - return ret; - - ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0); - if (ret < 0) - return ret; - - /* Initialize connection monitoring thresholds */ - ret = wl1271_acx_conn_monit_params(wl, false); - if (ret < 0) - return ret; - - /* Beacon filtering */ - ret = wl1271_init_beacon_filter(wl); - if (ret < 0) - return ret; - /* FM WLAN coexistence */ ret = wl1271_acx_fm_coex(wl); if (ret < 0) return ret; - /* Beacons and broadcast settings */ - ret = wl1271_init_beacon_broadcast(wl); - if (ret < 0) - return ret; - /* Configure for ELP power saving */ ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); if (ret < 0) return ret; - /* Configure rssi/snr averaging weights */ - ret = wl1271_acx_rssi_snr_avg_weights(wl); - if (ret < 0) - return ret; - ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) return ret; - ret = wl12xx_acx_mem_cfg(wl); - if (ret < 0) - return ret; - - /* Configure the FW logger */ - ret = wl12xx_init_fwlog(wl); - if (ret < 0) - return ret; - return 0; } @@ -418,14 +369,11 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl) return 0; } +/* generic ap initialization (non vif-specific) */ static int wl1271_ap_hw_init(struct wl1271 *wl) { int ret; - ret = wl1271_ap_init_templates_config(wl); - if (ret < 0) - return ret; - /* Configure for power always on */ ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); if (ret < 0) @@ -435,19 +383,6 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_acx_ap_max_tx_retry(wl); - if (ret < 0) - return ret; - - ret = wl12xx_acx_mem_cfg(wl); - if (ret < 0) - return ret; - - /* initialize Tx power */ - ret = wl1271_acx_tx_power(wl, wl->power_level); - if (ret < 0) - return ret; - return 0; } @@ -578,14 +513,133 @@ out: return ret; } +/* vif-specifc initialization */ +static int wl12xx_init_sta_role(struct wl1271 *wl, struct ieee80211_vif *vif) +{ + int ret; -int wl1271_hw_init(struct wl1271 *wl, struct ieee80211_vif *vif) + ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0); + if (ret < 0) + return ret; + + /* Initialize connection monitoring thresholds */ + ret = wl1271_acx_conn_monit_params(wl, false); + if (ret < 0) + return ret; + + /* Beacon filtering */ + ret = wl1271_init_beacon_filter(wl); + if (ret < 0) + return ret; + + /* Beacons and broadcast settings */ + ret = wl1271_init_beacon_broadcast(wl); + if (ret < 0) + return ret; + + /* Configure rssi/snr averaging weights */ + ret = wl1271_acx_rssi_snr_avg_weights(wl); + if (ret < 0) + return ret; + + return 0; +} + +/* vif-specific intialization */ +static int wl12xx_init_ap_role(struct wl1271 *wl, struct ieee80211_vif *vif) +{ + int ret; + + ret = wl1271_acx_ap_max_tx_retry(wl); + if (ret < 0) + return ret; + + /* initialize Tx power */ + ret = wl1271_acx_tx_power(wl, wl->power_level); + if (ret < 0) + return ret; + + return 0; +} + +int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) { struct conf_tx_ac_category *conf_ac; struct conf_tx_tid *conf_tid; - int ret, i; bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + int ret, i; + + /* Mode specific init */ + if (is_ap) { + ret = wl1271_ap_hw_init(wl); + if (ret < 0) + return ret; + + ret = wl12xx_init_ap_role(wl, vif); + if (ret < 0) + return ret; + } else { + ret = wl1271_sta_hw_init(wl); + if (ret < 0) + return ret; + + ret = wl12xx_init_sta_role(wl, vif); + if (ret < 0) + return ret; + } + + wl12xx_init_phy_vif_config(wl); + + /* Default TID/AC configuration */ + BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); + for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { + conf_ac = &wl->conf.tx.ac_conf[i]; + ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, + conf_ac->cw_max, conf_ac->aifsn, + conf_ac->tx_op_limit); + if (ret < 0) + return ret; + + conf_tid = &wl->conf.tx.tid_conf[i]; + ret = wl1271_acx_tid_cfg(wl, + conf_tid->queue_id, + conf_tid->channel_type, + conf_tid->tsid, + conf_tid->ps_scheme, + conf_tid->ack_policy, + conf_tid->apsd_conf[0], + conf_tid->apsd_conf[1]); + if (ret < 0) + return ret; + } + + /* Configure HW encryption */ + ret = wl1271_acx_feature_cfg(wl); + if (ret < 0) + return ret; + + /* Mode specific init - post mem init */ + if (is_ap) + ret = wl1271_ap_hw_init_post_mem(wl, vif); + else + ret = wl1271_sta_hw_init_post_mem(wl); + + if (ret < 0) + return ret; + + /* Configure initiator BA sessions policies */ + ret = wl1271_set_ba_policies(wl); + if (ret < 0) + return ret; + + return 0; +} + +int wl1271_hw_init(struct wl1271 *wl) +{ + int ret; + if (wl->chip.id == CHIP_ID_1283_PG20) ret = wl128x_cmd_general_parms(wl); else @@ -605,12 +659,17 @@ int wl1271_hw_init(struct wl1271 *wl, struct ieee80211_vif *vif) if (ret < 0) return ret; - /* Mode specific init */ - if (is_ap) - ret = wl1271_ap_hw_init(wl); - else - ret = wl1271_sta_hw_init(wl); + /* Init templates */ + ret = wl1271_init_templates_config(wl); + if (ret < 0) + return ret; + ret = wl12xx_acx_mem_cfg(wl); + if (ret < 0) + return ret; + + /* Configure the FW logger */ + ret = wl12xx_init_fwlog(wl); if (ret < 0) return ret; @@ -658,61 +717,20 @@ int wl1271_hw_init(struct wl1271 *wl, struct ieee80211_vif *vif) if (ret < 0) goto out_free_memmap; - /* Default TID/AC configuration */ - BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); - for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { - conf_ac = &wl->conf.tx.ac_conf[i]; - ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, - conf_ac->cw_max, conf_ac->aifsn, - conf_ac->tx_op_limit); - if (ret < 0) - goto out_free_memmap; - - conf_tid = &wl->conf.tx.tid_conf[i]; - ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, - conf_tid->channel_type, - conf_tid->tsid, - conf_tid->ps_scheme, - conf_tid->ack_policy, - conf_tid->apsd_conf[0], - conf_tid->apsd_conf[1]); - if (ret < 0) - goto out_free_memmap; - } - /* Enable data path */ ret = wl1271_cmd_data_path(wl, 1); if (ret < 0) goto out_free_memmap; - /* Configure HW encryption */ - ret = wl1271_acx_feature_cfg(wl); - if (ret < 0) - goto out_free_memmap; - /* configure PM */ ret = wl1271_acx_pm_config(wl); if (ret < 0) goto out_free_memmap; - /* Mode specific init - post mem init */ - if (is_ap) - ret = wl1271_ap_hw_init_post_mem(wl, vif); - else - ret = wl1271_sta_hw_init_post_mem(wl); - - if (ret < 0) - goto out_free_memmap; - ret = wl12xx_acx_set_rate_mgmt_params(wl); if (ret < 0) goto out_free_memmap; - /* Configure initiator BA sessions policies */ - ret = wl1271_set_ba_policies(wl); - if (ret < 0) - goto out_free_memmap; - /* configure hangover */ ret = wl12xx_acx_config_hangover(wl); if (ret < 0) diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h index b1f97bcc47c0..64320c0224ca 100644 --- a/drivers/net/wireless/wl12xx/init.h +++ b/drivers/net/wireless/wl12xx/init.h @@ -27,12 +27,13 @@ #include "wl12xx.h" int wl1271_hw_init_power_auth(struct wl1271 *wl); -int wl1271_sta_init_templates_config(struct wl1271 *wl); +int wl1271_init_templates_config(struct wl1271 *wl); int wl1271_init_phy_config(struct wl1271 *wl); int wl1271_init_pta(struct wl1271 *wl); int wl1271_init_energy_detection(struct wl1271 *wl); int wl1271_chip_specific_init(struct wl1271 *wl); -int wl1271_hw_init(struct wl1271 *wl, struct ieee80211_vif *vif); +int wl1271_hw_init(struct wl1271 *wl); +int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif); int wl1271_init_ap_rates(struct wl1271 *wl); int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 652471e8c61b..901e43a8334b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -676,7 +676,7 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_sta_init_templates_config(wl); + ret = wl1271_init_templates_config(wl); if (ret < 0) return ret; @@ -1919,6 +1919,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (ret < 0) goto power_off; + ret = wl1271_hw_init(wl); + if (ret < 0) + goto irq_disable; + if (wl->bss_type == BSS_TYPE_STA_BSS || wl->bss_type == BSS_TYPE_IBSS) { /* @@ -1939,7 +1943,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (ret < 0) goto irq_disable; - ret = wl1271_hw_init(wl, vif); + ret = wl1271_init_vif_specific(wl, vif); if (ret < 0) goto irq_disable; From 87fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0ca Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:41 +0200 Subject: [PATCH 03/97] wl12xx: define wl12xx_vif Define a per-vif data struct. This struct holds all the vif-specifc data, which is currently being hold by the global wl struct. Start by moving the basic_rate_set field into it. NOTE: in order to make the patches a bit smaller, start by using wl->vif in some functions, instead of changing all the function prototypes at once. finally, wl->vif will be removed altogether. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 21 ++++---- drivers/net/wireless/wl12xx/cmd.h | 9 ++-- drivers/net/wireless/wl12xx/debugfs.c | 1 - drivers/net/wireless/wl12xx/init.c | 34 +++++++------ drivers/net/wireless/wl12xx/init.h | 2 +- drivers/net/wireless/wl12xx/main.c | 70 +++++++++++++++++---------- drivers/net/wireless/wl12xx/wl12xx.h | 16 +++++- 7 files changed, 96 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index bee44c7d67fd..c99fc61113d1 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -555,7 +555,7 @@ out: return ret; } -int wl12xx_cmd_role_start_sta(struct wl1271 *wl) +int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_start *cmd; int ret; @@ -572,7 +572,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl) if (wl->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; - cmd->sta.basic_rate_set = cpu_to_le32(wl->basic_rate_set); + cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int); cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; cmd->sta.ssid_len = wl->ssid_len; @@ -592,7 +592,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl) wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " "basic_rate_set: 0x%x, remote_rates: 0x%x", wl->role_id, cmd->sta.hlid, cmd->sta.session, - wl->basic_rate_set, wl->rate_set); + wlvif->basic_rate_set, wl->rate_set); ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); if (ret < 0) { @@ -649,7 +649,7 @@ out: return ret; } -int wl12xx_cmd_role_start_ap(struct wl1271 *wl) +int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_start *cmd; struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; @@ -683,7 +683,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl) cmd->ap.bss_index = WL1271_AP_BSS_INDEX; cmd->ap.global_hlid = wl->ap_global_hlid; cmd->ap.broadcast_hlid = wl->ap_bcast_hlid; - cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set); + cmd->ap.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int); cmd->ap.dtim_interval = bss_conf->dtim_period; cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; @@ -767,7 +767,7 @@ out: return ret; } -int wl12xx_cmd_role_start_ibss(struct wl1271 *wl) +int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_start *cmd; struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; @@ -785,7 +785,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl) if (wl->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; - cmd->ibss.basic_rate_set = cpu_to_le32(wl->basic_rate_set); + cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int); cmd->ibss.dtim_interval = bss_conf->dtim_period; cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY; @@ -805,7 +805,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl) wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " "basic_rate_set: 0x%x, remote_rates: 0x%x", wl->role_id, cmd->sta.hlid, cmd->sta.session, - wl->basic_rate_set, wl->rate_set); + wlvif->basic_rate_set, wl->rate_set); wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid); @@ -1085,7 +1085,8 @@ out: } -int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) +int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u16 aid) { struct sk_buff *skb; int ret = 0; @@ -1095,7 +1096,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) goto out; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, - skb->len, 0, wl->basic_rate_set); + skb->len, 0, wlvif->basic_rate_set); out: dev_kfree_skb(skb); diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 1ae949f00c14..234a8dc90559 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -41,11 +41,11 @@ int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); int wl12xx_cmd_role_start_dev(struct wl1271 *wl); int wl12xx_cmd_role_stop_dev(struct wl1271 *wl); -int wl12xx_cmd_role_start_sta(struct wl1271 *wl); +int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_stop_sta(struct wl1271 *wl); -int wl12xx_cmd_role_start_ap(struct wl1271 *wl); +int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_stop_ap(struct wl1271 *wl); -int wl12xx_cmd_role_start_ibss(struct wl1271 *wl); +int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); @@ -56,7 +56,8 @@ int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, void *buf, size_t buf_len, int index, u32 rates); int wl1271_cmd_build_null_data(struct wl1271 *wl); -int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); +int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u16 aid); int wl1271_cmd_build_probe_req(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 band); diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 3999fd528302..0419aafe5c57 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -353,7 +353,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(bss_type); DRIVER_STATE_PRINT_INT(channel); DRIVER_STATE_PRINT_HEX(rate_set); - DRIVER_STATE_PRINT_HEX(basic_rate_set); DRIVER_STATE_PRINT_HEX(basic_rate); DRIVER_STATE_PRINT_INT(band); DRIVER_STATE_PRINT_INT(beacon_int); diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 145601dddab0..c00bdf8a3584 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -122,7 +122,8 @@ int wl1271_init_templates_config(struct wl1271 *wl) return 0; } -static int wl1271_ap_init_deauth_template(struct wl1271 *wl) +static int wl1271_ap_init_deauth_template(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { struct wl12xx_disconn_template *tmpl; int ret; @@ -137,7 +138,7 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl) tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); - rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, tmpl, sizeof(*tmpl), 0, rate); @@ -149,6 +150,7 @@ out: static int wl1271_ap_init_null_template(struct wl1271 *wl, struct ieee80211_vif *vif) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct ieee80211_hdr_3addr *nullfunc; int ret; u32 rate; @@ -168,7 +170,7 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl, memcpy(nullfunc->addr2, vif->addr, ETH_ALEN); memcpy(nullfunc->addr3, vif->addr, ETH_ALEN); - rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc, sizeof(*nullfunc), 0, rate); @@ -180,6 +182,7 @@ out: static int wl1271_ap_init_qos_null_template(struct wl1271 *wl, struct ieee80211_vif *vif) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct ieee80211_qos_hdr *qosnull; int ret; u32 rate; @@ -199,7 +202,7 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl, memcpy(qosnull->addr2, vif->addr, ETH_ALEN); memcpy(qosnull->addr3, vif->addr, ETH_ALEN); - rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull, sizeof(*qosnull), 0, rate); @@ -370,7 +373,7 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl) } /* generic ap initialization (non vif-specific) */ -static int wl1271_ap_hw_init(struct wl1271 *wl) +static int wl1271_ap_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret; @@ -379,7 +382,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_init_ap_rates(wl); + ret = wl1271_init_ap_rates(wl, wlvif); if (ret < 0) return ret; @@ -388,9 +391,10 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; - ret = wl1271_ap_init_deauth_template(wl); + ret = wl1271_ap_init_deauth_template(wl, wlvif); if (ret < 0) return ret; @@ -419,18 +423,19 @@ static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl, return wl1271_ap_init_templates(wl, vif); } -int wl1271_init_ap_rates(struct wl1271 *wl) +int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int i, ret; struct conf_tx_rate_class rc; u32 supported_rates; - wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x", wl->basic_rate_set); + wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x", + wlvif->basic_rate_set); - if (wl->basic_rate_set == 0) + if (wlvif->basic_rate_set == 0) return -EINVAL; - rc.enabled_rates = wl->basic_rate_set; + rc.enabled_rates = wlvif->basic_rate_set; rc.long_retry_limit = 10; rc.short_retry_limit = 10; rc.aflags = 0; @@ -439,7 +444,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl) return ret; /* use the min basic rate for AP broadcast/multicast */ - rc.enabled_rates = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + rc.enabled_rates = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); rc.short_retry_limit = 10; rc.long_retry_limit = 10; rc.aflags = 0; @@ -451,7 +456,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl) * If the basic rates contain OFDM rates, use OFDM only * rates for unicast TX as well. Else use all supported rates. */ - if ((wl->basic_rate_set & CONF_TX_OFDM_RATES)) + if ((wlvif->basic_rate_set & CONF_TX_OFDM_RATES)) supported_rates = CONF_TX_OFDM_RATES; else supported_rates = CONF_TX_AP_ENABLED_RATES; @@ -564,6 +569,7 @@ static int wl12xx_init_ap_role(struct wl1271 *wl, struct ieee80211_vif *vif) int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct conf_tx_ac_category *conf_ac; struct conf_tx_tid *conf_tid; bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); @@ -572,7 +578,7 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) /* Mode specific init */ if (is_ap) { - ret = wl1271_ap_hw_init(wl); + ret = wl1271_ap_hw_init(wl, wlvif); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h index 64320c0224ca..81140b81f654 100644 --- a/drivers/net/wireless/wl12xx/init.h +++ b/drivers/net/wireless/wl12xx/init.h @@ -34,7 +34,7 @@ int wl1271_init_energy_detection(struct wl1271 *wl); int wl1271_chip_specific_init(struct wl1271 *wl); int wl1271_hw_init(struct wl1271 *wl); int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif); -int wl1271_init_ap_rates(struct wl1271 *wl); +int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif); #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 901e43a8334b..0c43cf55f9bf 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1837,6 +1837,11 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl) return WL12XX_INVALID_ROLE_TYPE; } +static void wl12xx_init_vif_data(struct wl12xx_vif *wlvif) +{ + wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; +} + static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -1857,6 +1862,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, ret = -EBUSY; goto out; } + wl12xx_init_vif_data(wl12xx_vif_to_data(vif)); /* * in some very corner case HW recovery scenarios its possible to @@ -2163,7 +2169,8 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, cancel_work_sync(&wl->recovery_work); } -static int wl1271_join(struct wl1271 *wl, bool set_assoc) +static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool set_assoc) { int ret; bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); @@ -2184,9 +2191,9 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc) set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); if (is_ibss) - ret = wl12xx_cmd_role_start_ibss(wl); + ret = wl12xx_cmd_role_start_ibss(wl, wlvif); else - ret = wl12xx_cmd_role_start_sta(wl); + ret = wl12xx_cmd_role_start_sta(wl, wlvif); if (ret < 0) goto out; @@ -2244,10 +2251,10 @@ out: return ret; } -static void wl1271_set_band_rate(struct wl1271 *wl) +static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif) { - wl->basic_rate_set = wl->bitrate_masks[wl->band]; - wl->rate_set = wl->basic_rate_set; + wlvif->basic_rate_set = wl->bitrate_masks[wl->band]; + wl->rate_set = wlvif->basic_rate_set; } static bool wl12xx_is_roc(struct wl1271 *wl) @@ -2261,7 +2268,8 @@ static bool wl12xx_is_roc(struct wl1271 *wl) return true; } -static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) +static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool idle) { int ret; @@ -2276,7 +2284,8 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) if (ret < 0) goto out; } - wl->rate_set = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + wl->rate_set = wl1271_tx_min_rate_get(wl, + wlvif->basic_rate_set); ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) goto out; @@ -2310,6 +2319,8 @@ out: static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) { struct wl1271 *wl = hw->priv; + struct ieee80211_vif *vif = wl->vif; /* TODO: reconfig all vifs */ + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct ieee80211_conf *conf = &hw->conf; int channel, ret = 0; bool is_ap; @@ -2371,10 +2382,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) * association frames and other control messages. */ if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) - wl1271_set_band_rate(wl); + wl1271_set_band_rate(wl, wlvif); wl->basic_rate = - wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + wl1271_tx_min_rate_get(wl, + wlvif->basic_rate_set); ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) wl1271_warning("rate policy for channel " @@ -2387,7 +2399,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (ret < 0) goto out_sleep; } - ret = wl1271_join(wl, false); + ret = wl1271_join(wl, wlvif, false); if (ret < 0) wl1271_warning("cmd join on channel " "failed %d", ret); @@ -2413,7 +2425,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_IDLE && !is_ap) { - ret = wl1271_sta_handle_idle(wl, + ret = wl1271_sta_handle_idle(wl, wlvif, conf->flags & IEEE80211_CONF_IDLE); if (ret < 0) wl1271_warning("idle mode change failed %d", ret); @@ -3207,6 +3219,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, struct ieee80211_bss_conf *bss_conf, u32 changed) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); int ret = 0; @@ -3235,7 +3248,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, dev_kfree_skb(beacon); goto out; } - min_rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : CMD_TEMPL_BEACON; ret = wl1271_cmd_template_set(wl, tmpl_id, @@ -3290,17 +3303,18 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, struct ieee80211_bss_conf *bss_conf, u32 changed) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret = 0; if ((changed & BSS_CHANGED_BASIC_RATES)) { u32 rates = bss_conf->basic_rates; - wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, + wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, wl->band); wl->basic_rate = wl1271_tx_min_rate_get(wl, - wl->basic_rate_set); + wlvif->basic_rate_set); - ret = wl1271_init_ap_rates(wl); + ret = wl1271_init_ap_rates(wl, wlvif); if (ret < 0) { wl1271_error("AP rate policy change failed %d", ret); goto out; @@ -3318,7 +3332,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, if ((changed & BSS_CHANGED_BEACON_ENABLED)) { if (bss_conf->enable_beacon) { if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { - ret = wl12xx_cmd_role_start_ap(wl); + ret = wl12xx_cmd_role_start_ap(wl, wlvif); if (ret < 0) goto out; @@ -3366,6 +3380,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, struct ieee80211_bss_conf *bss_conf, u32 changed) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); bool do_join = false, set_assoc = false; bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); bool ibss_joined = false; @@ -3480,11 +3495,12 @@ sta_not_found: * to use with control frames. */ rates = bss_conf->basic_rates; - wl->basic_rate_set = + wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, wl->band); wl->basic_rate = - wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + wl1271_tx_min_rate_get(wl, + wlvif->basic_rate_set); if (sta_rate_set) wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rate_set, @@ -3499,7 +3515,7 @@ sta_not_found: * updates it by itself when the first beacon is * received after a join. */ - ret = wl1271_cmd_build_ps_poll(wl, wl->aid); + ret = wl1271_cmd_build_ps_poll(wl, wlvif, wl->aid); if (ret < 0) goto out; @@ -3534,9 +3550,10 @@ sta_not_found: ieee80211_enable_dyn_ps(wl->vif); /* revert back to minimum rates for the current band */ - wl1271_set_band_rate(wl); + wl1271_set_band_rate(wl, wlvif); wl->basic_rate = - wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + wl1271_tx_min_rate_get(wl, + wlvif->basic_rate_set); ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) goto out; @@ -3587,11 +3604,12 @@ sta_not_found: if (bss_conf->ibss_joined) { u32 rates = bss_conf->basic_rates; - wl->basic_rate_set = + wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, wl->band); wl->basic_rate = - wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + wl1271_tx_min_rate_get(wl, + wlvif->basic_rate_set); /* by default, use 11b + OFDM rates */ wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; @@ -3634,7 +3652,7 @@ sta_not_found: } if (do_join) { - ret = wl1271_join(wl, set_assoc); + ret = wl1271_join(wl, wlvif, set_assoc); if (ret < 0) { wl1271_warning("cmd join failed %d", ret); goto out; @@ -4750,6 +4768,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); wl->hw->sta_data_size = sizeof(struct wl1271_station); + wl->hw->vif_data_size = sizeof(struct wl12xx_vif); wl->hw->max_rx_aggregation_subframes = 8; @@ -4824,7 +4843,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->rx_counter = 0; wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; - wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wl->basic_rate = CONF_TX_RATE_MASK_BASIC; wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->band = IEEE80211_BAND_2GHZ; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index b8de2f5e052b..7e30dd53cb88 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -525,7 +525,6 @@ struct wl1271 { * bits 16-23 - 802.11n MCS index mask * support only 1 stream, thus only 8 bits for the MCS rates (0-7). */ - u32 basic_rate_set; u32 basic_rate; u32 rate_set; u32 bitrate_masks[IEEE80211_NUM_BANDS]; @@ -639,6 +638,21 @@ struct wl1271_station { u8 hlid; }; +struct wl12xx_vif { + u32 basic_rate_set; +}; + +static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) +{ + return (struct wl12xx_vif *)vif->drv_priv; +} + +static inline +struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif) +{ + return container_of((void *)wlvif, struct ieee80211_vif, drv_priv); +} + int wl1271_plt_start(struct wl1271 *wl); int wl1271_plt_stop(struct wl1271 *wl); int wl1271_recalc_rx_streaming(struct wl1271 *wl); From 30d0c8fd5b87d1c5486705d6420545a21533e115 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:42 +0200 Subject: [PATCH 04/97] wl12xx: move rate_set into wlvif move rate_set into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 6 +++--- drivers/net/wireless/wl12xx/acx.h | 2 +- drivers/net/wireless/wl12xx/cmd.c | 12 ++++++------ drivers/net/wireless/wl12xx/debugfs.c | 1 - drivers/net/wireless/wl12xx/init.c | 6 +++--- drivers/net/wireless/wl12xx/main.c | 24 ++++++++++++------------ drivers/net/wireless/wl12xx/wl12xx.h | 9 ++++++++- 7 files changed, 33 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index ca044a743191..1ef9b0b48635 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -739,7 +739,7 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) return 0; } -int wl1271_acx_sta_rate_policies(struct wl1271 *wl) +int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct acx_rate_policy *acx; struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf; @@ -755,7 +755,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl) } wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x", - wl->basic_rate, wl->rate_set); + wl->basic_rate, wlvif->rate_set); /* configure one basic rate class */ acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE); @@ -772,7 +772,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl) /* configure one AP supported rate class */ acx->rate_policy_idx = cpu_to_le32(ACX_TX_AP_FULL_RATE); - acx->rate_policy.enabled_rates = cpu_to_le32(wl->rate_set); + acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->rate_set); acx->rate_policy.short_retry_limit = c->short_retry_limit; acx->rate_policy.long_retry_limit = c->long_retry_limit; acx->rate_policy.aflags = c->aflags; diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index e3f93b4b3429..81779f45ab41 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -1261,7 +1261,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); int wl1271_acx_cts_protect(struct wl1271 *wl, enum acx_ctsprotect_type ctsprotect); int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); -int wl1271_acx_sta_rate_policies(struct wl1271 *wl); +int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, u8 idx); int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index c99fc61113d1..6a2f758eb1d3 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -578,7 +578,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->sta.ssid_len = wl->ssid_len; memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len); memcpy(cmd->sta.bssid, wl->bssid, ETH_ALEN); - cmd->sta.local_rates = cpu_to_le32(wl->rate_set); + cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { ret = wl12xx_allocate_link(wl, &wl->sta_hlid); @@ -587,12 +587,12 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) } cmd->sta.hlid = wl->sta_hlid; cmd->sta.session = wl12xx_get_new_session_id(wl); - cmd->sta.remote_rates = cpu_to_le32(wl->rate_set); + cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set); wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " "basic_rate_set: 0x%x, remote_rates: 0x%x", wl->role_id, cmd->sta.hlid, cmd->sta.session, - wlvif->basic_rate_set, wl->rate_set); + wlvif->basic_rate_set, wlvif->rate_set); ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); if (ret < 0) { @@ -792,7 +792,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->ibss.ssid_len = wl->ssid_len; memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len); memcpy(cmd->ibss.bssid, wl->bssid, ETH_ALEN); - cmd->sta.local_rates = cpu_to_le32(wl->rate_set); + cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { ret = wl12xx_allocate_link(wl, &wl->sta_hlid); @@ -800,12 +800,12 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; } cmd->ibss.hlid = wl->sta_hlid; - cmd->ibss.remote_rates = cpu_to_le32(wl->rate_set); + cmd->ibss.remote_rates = cpu_to_le32(wlvif->rate_set); wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " "basic_rate_set: 0x%x, remote_rates: 0x%x", wl->role_id, cmd->sta.hlid, cmd->sta.session, - wlvif->basic_rate_set, wl->rate_set); + wlvif->basic_rate_set, wlvif->rate_set); wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid); diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 0419aafe5c57..e63fea4b120d 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -352,7 +352,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(state); DRIVER_STATE_PRINT_INT(bss_type); DRIVER_STATE_PRINT_INT(channel); - DRIVER_STATE_PRINT_HEX(rate_set); DRIVER_STATE_PRINT_HEX(basic_rate); DRIVER_STATE_PRINT_INT(band); DRIVER_STATE_PRINT_INT(beacon_int); diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index c00bdf8a3584..37955dad1f93 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -320,7 +320,7 @@ static int wl12xx_init_fwlog(struct wl1271 *wl) } /* generic sta initialization (non vif-specific) */ -static int wl1271_sta_hw_init(struct wl1271 *wl) +static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret; @@ -345,7 +345,7 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_acx_sta_rate_policies(wl); + ret = wl1271_acx_sta_rate_policies(wl, wlvif); if (ret < 0) return ret; @@ -586,7 +586,7 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) if (ret < 0) return ret; } else { - ret = wl1271_sta_hw_init(wl); + ret = wl1271_sta_hw_init(wl, wlvif); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0c43cf55f9bf..195dcbdf1fc7 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1840,6 +1840,7 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl) static void wl12xx_init_vif_data(struct wl12xx_vif *wlvif) { wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; + wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; } static int wl1271_op_add_interface(struct ieee80211_hw *hw, @@ -2106,7 +2107,6 @@ deinit: wl->tx_packets_count = 0; wl->time_offset = 0; wl->session_counter = 0; - wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; wl->vif = NULL; @@ -2254,7 +2254,7 @@ out: static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif) { wlvif->basic_rate_set = wl->bitrate_masks[wl->band]; - wl->rate_set = wlvif->basic_rate_set; + wlvif->rate_set = wlvif->basic_rate_set; } static bool wl12xx_is_roc(struct wl1271 *wl) @@ -2284,9 +2284,9 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (ret < 0) goto out; } - wl->rate_set = wl1271_tx_min_rate_get(wl, - wlvif->basic_rate_set); - ret = wl1271_acx_sta_rate_policies(wl); + wlvif->rate_set = + wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); + ret = wl1271_acx_sta_rate_policies(wl, wlvif); if (ret < 0) goto out; ret = wl1271_acx_keep_alive_config( @@ -2387,7 +2387,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl->basic_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - ret = wl1271_acx_sta_rate_policies(wl); + ret = wl1271_acx_sta_rate_policies(wl, wlvif); if (ret < 0) wl1271_warning("rate policy for channel " "failed %d", ret); @@ -3502,10 +3502,11 @@ sta_not_found: wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); if (sta_rate_set) - wl->rate_set = wl1271_tx_enabled_rates_get(wl, + wlvif->rate_set = + wl1271_tx_enabled_rates_get(wl, sta_rate_set, wl->band); - ret = wl1271_acx_sta_rate_policies(wl); + ret = wl1271_acx_sta_rate_policies(wl, wlvif); if (ret < 0) goto out; @@ -3554,7 +3555,7 @@ sta_not_found: wl->basic_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - ret = wl1271_acx_sta_rate_policies(wl); + ret = wl1271_acx_sta_rate_policies(wl, wlvif); if (ret < 0) goto out; @@ -3612,8 +3613,8 @@ sta_not_found: wlvif->basic_rate_set); /* by default, use 11b + OFDM rates */ - wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; - ret = wl1271_acx_sta_rate_policies(wl); + wlvif->rate_set = CONF_TX_IBSS_DEFAULT_RATES; + ret = wl1271_acx_sta_rate_policies(wl, wlvif); if (ret < 0) goto out; } @@ -4844,7 +4845,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->basic_rate = CONF_TX_RATE_MASK_BASIC; - wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; wl->flags = 0; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 7e30dd53cb88..6f3efbae740e 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -526,7 +526,6 @@ struct wl1271 { * support only 1 stream, thus only 8 bits for the MCS rates (0-7). */ u32 basic_rate; - u32 rate_set; u32 bitrate_masks[IEEE80211_NUM_BANDS]; /* The current band */ @@ -640,6 +639,14 @@ struct wl1271_station { struct wl12xx_vif { u32 basic_rate_set; + + /* + * currently configured rate set: + * bits 0-15 - 802.11abg rates + * bits 16-23 - 802.11n MCS index mask + * support only 1 stream, thus only 8 bits for the MCS rates (0-7). + */ + u32 rate_set; }; static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) From d2d66c56cf6c8727662aa321991f791604c22094 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:43 +0200 Subject: [PATCH 05/97] wl12xx: move basic_rate into wlvif move basic_rate into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 8 ++--- drivers/net/wireless/wl12xx/acx.h | 2 +- drivers/net/wireless/wl12xx/cmd.c | 23 ++++++++----- drivers/net/wireless/wl12xx/cmd.h | 8 +++-- drivers/net/wireless/wl12xx/debugfs.c | 1 - drivers/net/wireless/wl12xx/event.c | 21 ++++++++---- drivers/net/wireless/wl12xx/init.c | 2 +- drivers/net/wireless/wl12xx/main.c | 47 +++++++++++++++------------ drivers/net/wireless/wl12xx/wl12xx.h | 8 +---- 9 files changed, 68 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 1ef9b0b48635..015938f94805 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -755,11 +755,11 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) } wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x", - wl->basic_rate, wlvif->rate_set); + wlvif->basic_rate, wlvif->rate_set); /* configure one basic rate class */ acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE); - acx->rate_policy.enabled_rates = cpu_to_le32(wl->basic_rate); + acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->basic_rate); acx->rate_policy.short_retry_limit = c->short_retry_limit; acx->rate_policy.long_retry_limit = c->long_retry_limit; acx->rate_policy.aflags = c->aflags; @@ -1567,7 +1567,7 @@ out: return ret; } -int wl1271_acx_config_ps(struct wl1271 *wl) +int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl1271_acx_config_ps *config_ps; int ret; @@ -1582,7 +1582,7 @@ int wl1271_acx_config_ps(struct wl1271 *wl) config_ps->exit_retries = wl->conf.conn.psm_exit_retries; config_ps->enter_retries = wl->conf.conn.psm_entry_retries; - config_ps->null_data_rate = cpu_to_le32(wl->basic_rate); + config_ps->null_data_rate = cpu_to_le32(wlvif->basic_rate); ret = wl1271_cmd_configure(wl, ACX_CONFIG_PS, config_ps, sizeof(*config_ps)); diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 81779f45ab41..2678e1d505f9 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -1295,7 +1295,7 @@ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); -int wl1271_acx_config_ps(struct wl1271 *wl); +int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); int wl1271_acx_fm_coex(struct wl1271 *wl); int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 6a2f758eb1d3..ce734157980a 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1031,7 +1031,7 @@ out: return ret; } -int wl1271_cmd_build_null_data(struct wl1271 *wl) +int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct sk_buff *skb = NULL; int size; @@ -1043,7 +1043,8 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl) size = sizeof(struct wl12xx_null_data_template); ptr = NULL; } else { - skb = ieee80211_nullfunc_get(wl->hw, wl->vif); + skb = ieee80211_nullfunc_get(wl->hw, + wl12xx_wlvif_to_vif(wlvif)); if (!skb) goto out; size = skb->len; @@ -1051,7 +1052,7 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl) } ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, - wl->basic_rate); + wlvif->basic_rate); out: dev_kfree_skb(skb); @@ -1062,19 +1063,21 @@ out: } -int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) +int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct sk_buff *skb = NULL; int ret = -ENOMEM; - skb = ieee80211_nullfunc_get(wl->hw, wl->vif); + skb = ieee80211_nullfunc_get(wl->hw, vif); if (!skb) goto out; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, skb->data, skb->len, CMD_TEMPL_KLV_IDX_NULL_DATA, - wl->basic_rate); + wlvif->basic_rate); out: dev_kfree_skb(skb); @@ -1161,7 +1164,8 @@ out: return skb; } -int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr) +int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, + __be32 ip_addr) { int ret; struct wl12xx_arp_rsp_template tmpl; @@ -1197,13 +1201,14 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, &tmpl, sizeof(tmpl), 0, - wl->basic_rate); + wlvif->basic_rate); return ret; } int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct ieee80211_qos_hdr template; memset(&template, 0, sizeof(template)); @@ -1221,7 +1226,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif) return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, sizeof(template), 0, - wl->basic_rate); + wlvif->basic_rate); } int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid) diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 234a8dc90559..d5749f5b3bf1 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -55,7 +55,7 @@ int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, size_t len); int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, void *buf, size_t buf_len, int index, u32 rates); -int wl1271_cmd_build_null_data(struct wl1271 *wl); +int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 aid); int wl1271_cmd_build_probe_req(struct wl1271 *wl, @@ -63,9 +63,11 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, const u8 *ie, size_t ie_len, u8 band); struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, struct sk_buff *skb); -int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); +int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, + __be32 ip_addr); int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif); -int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); +int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, + struct wl12xx_vif *wlvif); int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid); int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index e63fea4b120d..620acbfd9ec3 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -352,7 +352,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(state); DRIVER_STATE_PRINT_INT(bss_type); DRIVER_STATE_PRINT_INT(channel); - DRIVER_STATE_PRINT_HEX(basic_rate); DRIVER_STATE_PRINT_INT(band); DRIVER_STATE_PRINT_INT(beacon_int); DRIVER_STATE_PRINT_INT(psm_entry_retry); diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 7e3ff808feef..af4cef366a3e 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -31,12 +31,16 @@ void wl1271_pspoll_work(struct work_struct *work) { + struct ieee80211_vif *vif; + struct wl12xx_vif *wlvif; struct delayed_work *dwork; struct wl1271 *wl; int ret; dwork = container_of(work, struct delayed_work, work); wl = container_of(dwork, struct wl1271, pspoll_work); + vif = wl->vif; /* TODO: move work into vif struct */ + wlvif = wl12xx_vif_to_data(vif); wl1271_debug(DEBUG_EVENT, "pspoll work"); @@ -60,14 +64,16 @@ void wl1271_pspoll_work(struct work_struct *work) if (ret < 0) goto out; - wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); + wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wlvif->basic_rate, + true); wl1271_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); }; -static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) +static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { int delay = wl->conf.conn.ps_poll_recovery_period; int ret; @@ -80,7 +86,7 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) /* force active mode receive data from the AP */ if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, - wl->basic_rate, true); + wlvif->basic_rate, true); if (ret < 0) return; set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); @@ -97,6 +103,7 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) } static int wl1271_event_ps_report(struct wl1271 *wl, + struct wl12xx_vif *wlvif, struct event_mailbox *mbox, bool *beacon_loss) { @@ -118,7 +125,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, if (wl->psm_entry_retry < total_retries) { wl->psm_entry_retry++; ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, - wl->basic_rate, true); + wlvif->basic_rate, true); } else { wl1271_info("No ack to nullfunc from AP."); wl->psm_entry_retry = 0; @@ -217,6 +224,8 @@ static void wl1271_event_mbox_dump(struct event_mailbox *mbox) static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) { + struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; u32 vector; bool beacon_loss = false; @@ -276,13 +285,13 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) if ((vector & PS_REPORT_EVENT_ID) && !is_ap) { wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); - ret = wl1271_event_ps_report(wl, mbox, &beacon_loss); + ret = wl1271_event_ps_report(wl, wlvif, mbox, &beacon_loss); if (ret < 0) return ret; } if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap) - wl1271_event_pspoll_delivery_fail(wl); + wl1271_event_pspoll_delivery_fail(wl, wlvif); if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 37955dad1f93..ed27c5f06bb2 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -331,7 +331,7 @@ static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) } /* PS config */ - ret = wl1271_acx_config_ps(wl); + ret = wl12xx_acx_config_ps(wl, wlvif); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 195dcbdf1fc7..8863ea542ea6 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1609,7 +1609,8 @@ static struct notifier_block wl1271_dev_notifier = { }; #ifdef CONFIG_PM -static int wl1271_configure_suspend_sta(struct wl1271 *wl) +static int wl1271_configure_suspend_sta(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { int ret = 0; @@ -1628,7 +1629,7 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl) wl->ps_compl = &compl; ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, - wl->basic_rate, true); + wlvif->basic_rate, true); if (ret < 0) goto out_sleep; @@ -1682,16 +1683,18 @@ out_unlock: } -static int wl1271_configure_suspend(struct wl1271 *wl) +static int wl1271_configure_suspend(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { if (wl->bss_type == BSS_TYPE_STA_BSS) - return wl1271_configure_suspend_sta(wl); + return wl1271_configure_suspend_sta(wl, wlvif); if (wl->bss_type == BSS_TYPE_AP_BSS) return wl1271_configure_suspend_ap(wl); return 0; } -static void wl1271_configure_resume(struct wl1271 *wl) +static void wl1271_configure_resume(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { int ret; bool is_sta = wl->bss_type == BSS_TYPE_STA_BSS; @@ -1709,7 +1712,7 @@ static void wl1271_configure_resume(struct wl1271 *wl) /* exit psm if it wasn't configured */ if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, - wl->basic_rate, true); + wlvif->basic_rate, true); } else if (is_ap) { wl1271_acx_beacon_filter_opt(wl, false); } @@ -1723,13 +1726,15 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) { struct wl1271 *wl = hw->priv; + struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); WARN_ON(!wow || !wow->any); wl->wow_enabled = true; - ret = wl1271_configure_suspend(wl); + ret = wl1271_configure_suspend(wl, wlvif); if (ret < 0) { wl1271_warning("couldn't prepare device to suspend"); return ret; @@ -1760,6 +1765,8 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, static int wl1271_op_resume(struct ieee80211_hw *hw) { struct wl1271 *wl = hw->priv; + struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); unsigned long flags; bool run_irq_work = false; @@ -1783,7 +1790,7 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) wl1271_irq(0, wl); wl1271_enable_interrupts(wl); } - wl1271_configure_resume(wl); + wl1271_configure_resume(wl, wlvif); wl->wow_enabled = false; return 0; @@ -1840,6 +1847,7 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl) static void wl12xx_init_vif_data(struct wl12xx_vif *wlvif) { wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; + wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; } @@ -2214,7 +2222,7 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (ret < 0) goto out; - ret = wl1271_cmd_build_klv_null_data(wl); + ret = wl12xx_cmd_build_klv_null_data(wl, wlvif); if (ret < 0) goto out; @@ -2384,7 +2392,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) wl1271_set_band_rate(wl, wlvif); - wl->basic_rate = + wlvif->basic_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); ret = wl1271_acx_sta_rate_policies(wl, wlvif); @@ -2450,7 +2458,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { wl1271_debug(DEBUG_PSM, "psm enabled"); ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, - wl->basic_rate, true); + wlvif->basic_rate, true); } } else if (!(conf->flags & IEEE80211_CONF_PS) && test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { @@ -2460,7 +2468,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (test_bit(WL1271_FLAG_PSM, &wl->flags)) ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, - wl->basic_rate, true); + wlvif->basic_rate, true); } if (conf->power_level != wl->power_level) { @@ -3311,7 +3319,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, wl->band); - wl->basic_rate = wl1271_tx_min_rate_get(wl, + wlvif->basic_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); ret = wl1271_init_ap_rates(wl, wlvif); @@ -3450,7 +3458,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); if (!is_zero_ether_addr(wl->bssid)) { - ret = wl1271_cmd_build_null_data(wl); + ret = wl12xx_cmd_build_null_data(wl, wlvif); if (ret < 0) goto out; @@ -3498,7 +3506,7 @@ sta_not_found: wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, wl->band); - wl->basic_rate = + wlvif->basic_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); if (sta_rate_set) @@ -3552,7 +3560,7 @@ sta_not_found: /* revert back to minimum rates for the current band */ wl1271_set_band_rate(wl, wlvif); - wl->basic_rate = + wlvif->basic_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); ret = wl1271_acx_sta_rate_policies(wl, wlvif); @@ -3608,7 +3616,7 @@ sta_not_found: wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, wl->band); - wl->basic_rate = + wlvif->basic_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); @@ -3636,7 +3644,7 @@ sta_not_found: * isn't being set (when sending), so we have to * reconfigure the template upon every ip change. */ - ret = wl1271_cmd_build_arp_rsp(wl, addr); + ret = wl1271_cmd_build_arp_rsp(wl, wlvif, addr); if (ret < 0) { wl1271_warning("build arp rsp failed: %d", ret); goto out; @@ -3689,7 +3697,7 @@ sta_not_found: mode = STATION_POWER_SAVE_MODE; ret = wl1271_ps_set_mode(wl, mode, - wl->basic_rate, + wlvif->basic_rate, true); if (ret < 0) goto out; @@ -4844,7 +4852,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->rx_counter = 0; wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; - wl->basic_rate = CONF_TX_RATE_MASK_BASIC; wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; wl->flags = 0; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 6f3efbae740e..d355c737044b 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -519,13 +519,6 @@ struct wl1271 { /* Our association ID */ u16 aid; - /* - * currently configured rate set: - * bits 0-15 - 802.11abg rates - * bits 16-23 - 802.11n MCS index mask - * support only 1 stream, thus only 8 bits for the MCS rates (0-7). - */ - u32 basic_rate; u32 bitrate_masks[IEEE80211_NUM_BANDS]; /* The current band */ @@ -646,6 +639,7 @@ struct wl12xx_vif { * bits 16-23 - 802.11n MCS index mask * support only 1 stream, thus only 8 bits for the MCS rates (0-7). */ + u32 basic_rate; u32 rate_set; }; From cdf09495588fda7e9c15c25bc20cb828e07be314 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:44 +0200 Subject: [PATCH 06/97] wl12xx: replace wl->bssid with vif->bss_conf.bssid Use the per-interface vif->bss_conf instead of the global wl->bssid. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 13 ++++++++----- drivers/net/wireless/wl12xx/event.c | 2 +- drivers/net/wireless/wl12xx/main.c | 15 ++------------- drivers/net/wireless/wl12xx/wl12xx.h | 1 - 4 files changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index ce734157980a..b9bb76b22f58 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -557,6 +557,7 @@ out: int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct wl12xx_cmd_role_start *cmd; int ret; @@ -577,7 +578,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; cmd->sta.ssid_len = wl->ssid_len; memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len); - memcpy(cmd->sta.bssid, wl->bssid, ETH_ALEN); + memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN); cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { @@ -769,6 +770,7 @@ out: int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct wl12xx_cmd_role_start *cmd; struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; int ret; @@ -791,7 +793,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY; cmd->ibss.ssid_len = wl->ssid_len; memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len); - memcpy(cmd->ibss.bssid, wl->bssid, ETH_ALEN); + memcpy(cmd->ibss.bssid, vif->bss_conf.bssid, ETH_ALEN); cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { @@ -807,7 +809,8 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) wl->role_id, cmd->sta.hlid, cmd->sta.session, wlvif->basic_rate_set, wlvif->rate_set); - wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid); + wl1271_debug(DEBUG_CMD, "vif->bss_conf.bssid = %pM", + vif->bss_conf.bssid); ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); if (ret < 0) { @@ -1213,9 +1216,9 @@ int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif) memset(&template, 0, sizeof(template)); - memcpy(template.addr1, wl->bssid, ETH_ALEN); + memcpy(template.addr1, vif->bss_conf.bssid, ETH_ALEN); memcpy(template.addr2, vif->addr, ETH_ALEN); - memcpy(template.addr3, wl->bssid, ETH_ALEN); + memcpy(template.addr3, vif->bss_conf.bssid, ETH_ALEN); template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC | diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index af4cef366a3e..30d05fd24672 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -184,7 +184,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl) if (!wl->ba_rx_bitmap) return; ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, - wl->bssid); + wl->vif->bss_conf.bssid); } else { int i; struct wl1271_link *lnk; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8863ea542ea6..d19c3fe34860 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2098,7 +2098,6 @@ deinit: wl1271_tx_reset(wl, reset_tx_queues); wl1271_power_off(wl); - memset(wl->bssid, 0, ETH_ALEN); memset(wl->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); wl->ssid_len = 0; wl->bss_type = MAX_BSS_TYPE; @@ -2249,8 +2248,6 @@ static int wl1271_unjoin(struct wl1271 *wl) if (ret < 0) goto out; - memset(wl->bssid, 0, ETH_ALEN); - /* reset TX security counters on a clean disconnect */ wl->tx_security_last_seq_lsb = 0; wl->tx_security_seq = 0; @@ -3449,15 +3446,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, wl->rssi_thold = bss_conf->cqm_rssi_thold; } - if ((changed & BSS_CHANGED_BSSID) && - /* - * Now we know the correct bssid, so we send a new join command - * and enable the BSSID filter - */ - memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { - memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); - - if (!is_zero_ether_addr(wl->bssid)) { + if (changed & BSS_CHANGED_BSSID) + if (!is_zero_ether_addr(bss_conf->bssid)) { ret = wl12xx_cmd_build_null_data(wl, wlvif); if (ret < 0) goto out; @@ -3469,7 +3459,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, /* Need to update the BSSID (for filtering etc) */ do_join = true; } - } if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { rcu_read_lock(); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index d355c737044b..44a5daeff07e 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -399,7 +399,6 @@ struct wl1271 { s8 hw_pg_ver; - u8 bssid[ETH_ALEN]; u8 mac_addr[ETH_ALEN]; u8 bss_type; u8 set_bss_type; From 536129c8ad35de87ff2f864f205a54ac32bfebcc Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:45 +0200 Subject: [PATCH 07/97] wl12xx: move bss_type into wlvif move bss_type into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 2 +- drivers/net/wireless/wl12xx/debugfs.c | 1 - drivers/net/wireless/wl12xx/event.c | 10 +-- drivers/net/wireless/wl12xx/init.c | 10 +-- drivers/net/wireless/wl12xx/main.c | 109 ++++++++++++++------------ drivers/net/wireless/wl12xx/rx.c | 4 +- drivers/net/wireless/wl12xx/scan.c | 12 ++- drivers/net/wireless/wl12xx/scan.h | 3 +- drivers/net/wireless/wl12xx/tx.c | 86 ++++++++++++-------- drivers/net/wireless/wl12xx/tx.h | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 3 +- 11 files changed, 141 insertions(+), 101 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index b9bb76b22f58..096a713a8c94 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1042,7 +1042,7 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif) int ret = -ENOMEM; - if (wl->bss_type == BSS_TYPE_IBSS) { + if (wlvif->bss_type == BSS_TYPE_IBSS) { size = sizeof(struct wl12xx_null_data_template); ptr = NULL; } else { diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 620acbfd9ec3..8f88ad6496f9 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -350,7 +350,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(rx_counter); DRIVER_STATE_PRINT_INT(session_counter); DRIVER_STATE_PRINT_INT(state); - DRIVER_STATE_PRINT_INT(bss_type); DRIVER_STATE_PRINT_INT(channel); DRIVER_STATE_PRINT_INT(band); DRIVER_STATE_PRINT_INT(beacon_int); diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 30d05fd24672..072addc0bffc 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -178,9 +178,9 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl, wl->last_rssi_event = event; } -static void wl1271_stop_ba_event(struct wl1271 *wl) +static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) { - if (wl->bss_type != BSS_TYPE_AP_BSS) { + if (wlvif->bss_type != BSS_TYPE_AP_BSS) { if (!wl->ba_rx_bitmap) return; ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, @@ -229,7 +229,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) int ret; u32 vector; bool beacon_loss = false; - bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); bool disconnect_sta = false; unsigned long sta_bitmap = 0; @@ -263,7 +263,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) } if (vector & SOFT_GEMINI_SENSE_EVENT_ID && - wl->bss_type == BSS_TYPE_STA_BSS) + wlvif->bss_type == BSS_TYPE_STA_BSS) wl12xx_event_soft_gemini_sense(wl, mbox->soft_gemini_sense_info); @@ -306,7 +306,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl->ba_allowed = !!mbox->rx_ba_allowed; if (wl->vif && !wl->ba_allowed) - wl1271_stop_ba_event(wl); + wl1271_stop_ba_event(wl, wlvif); } if ((vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) && !is_ap) { diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index ed27c5f06bb2..e54cc693ff69 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -478,7 +478,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) return 0; } -static int wl1271_set_ba_policies(struct wl1271 *wl) +static int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) { /* Reset the BA RX indicators */ wl->ba_rx_bitmap = 0; @@ -486,8 +486,8 @@ static int wl1271_set_ba_policies(struct wl1271 *wl) wl->ba_rx_session_count = 0; /* BA is supported in STA/AP modes */ - if (wl->bss_type != BSS_TYPE_AP_BSS && - wl->bss_type != BSS_TYPE_STA_BSS) { + if (wlvif->bss_type != BSS_TYPE_AP_BSS && + wlvif->bss_type != BSS_TYPE_STA_BSS) { wl->ba_support = false; return 0; } @@ -572,7 +572,7 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct conf_tx_ac_category *conf_ac; struct conf_tx_tid *conf_tid; - bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); int ret, i; @@ -635,7 +635,7 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) return ret; /* Configure initiator BA sessions policies */ - ret = wl1271_set_ba_policies(wl); + ret = wl1271_set_ba_policies(wl, wlvif); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index d19c3fe34860..5b13af0f8e8e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -377,6 +377,7 @@ static char *fwlog_param; static bool bug_on_recovery; static void __wl1271_op_remove_interface(struct wl1271 *wl, + struct ieee80211_vif *vif, bool reset_tx_queues); static void wl1271_free_ap_keys(struct wl1271 *wl); @@ -844,6 +845,8 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, static void wl12xx_fw_status(struct wl1271 *wl, struct wl12xx_fw_status *status) { + struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct timespec ts; u32 old_tx_blk_count = wl->tx_blocks_available; int avail, freed_blocks; @@ -898,7 +901,7 @@ static void wl12xx_fw_status(struct wl1271 *wl, clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); /* for AP update num of allocated TX blocks per link and ps status */ - if (wl->bss_type == BSS_TYPE_AP_BSS) + if (wlvif->bss_type == BSS_TYPE_AP_BSS) wl12xx_irq_update_links_status(wl, status); /* update the host-chipset time offset */ @@ -1004,7 +1007,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie) * In order to avoid starvation of the TX path, * call the work function directly. */ - wl1271_tx_work_locked(wl); + wl1271_tx_work_locked(wl, wl->vif); } else { spin_unlock_irqrestore(&wl->wl_lock, flags); } @@ -1251,7 +1254,7 @@ static void wl1271_recovery_work(struct work_struct *work) } /* reboot the chipset */ - __wl1271_op_remove_interface(wl, false); + __wl1271_op_remove_interface(wl, wl->vif, false); clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); @@ -1389,8 +1392,6 @@ int wl1271_plt_start(struct wl1271 *wl) goto out; } - wl->bss_type = BSS_TYPE_STA_BSS; - while (retries) { retries--; ret = wl1271_chip_wakeup(wl); @@ -1482,6 +1483,8 @@ int wl1271_plt_stop(struct wl1271 *wl) static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct wl1271 *wl = hw->priv; + struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb); + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(control->control.vif); unsigned long flags; int q, mapping; u8 hlid = 0; @@ -1489,13 +1492,13 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) mapping = skb_get_queue_mapping(skb); q = wl1271_tx_get_queue(mapping); - if (wl->bss_type == BSS_TYPE_AP_BSS) + if (wlvif->bss_type == BSS_TYPE_AP_BSS) hlid = wl12xx_tx_get_hlid_ap(wl, skb); spin_lock_irqsave(&wl->wl_lock, flags); /* queue the packet */ - if (wl->bss_type == BSS_TYPE_AP_BSS) { + if (wlvif->bss_type == BSS_TYPE_AP_BSS) { if (!wl1271_is_active_sta(wl, hlid)) { wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); @@ -1552,7 +1555,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl) /* The FW is low on RX memory blocks, so send the dummy packet asap */ if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) - wl1271_tx_work_locked(wl); + wl1271_tx_work_locked(wl, wl->vif); /* * If the FW TX is busy, TX work will be scheduled by the threaded @@ -1686,9 +1689,9 @@ out_unlock: static int wl1271_configure_suspend(struct wl1271 *wl, struct wl12xx_vif *wlvif) { - if (wl->bss_type == BSS_TYPE_STA_BSS) + if (wlvif->bss_type == BSS_TYPE_STA_BSS) return wl1271_configure_suspend_sta(wl, wlvif); - if (wl->bss_type == BSS_TYPE_AP_BSS) + if (wlvif->bss_type == BSS_TYPE_AP_BSS) return wl1271_configure_suspend_ap(wl); return 0; } @@ -1697,8 +1700,8 @@ static void wl1271_configure_resume(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret; - bool is_sta = wl->bss_type == BSS_TYPE_STA_BSS; - bool is_ap = wl->bss_type == BSS_TYPE_AP_BSS; + bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; + bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; if (!is_sta && !is_ap) return; @@ -1820,9 +1823,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); } -static u8 wl12xx_get_role_type(struct wl1271 *wl) +static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) { - switch (wl->bss_type) { + switch (wlvif->bss_type) { case BSS_TYPE_AP_BSS: if (wl->p2p) return WL1271_ROLE_P2P_GO; @@ -1839,13 +1842,14 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl) return WL1271_ROLE_IBSS; default: - wl1271_error("invalid bss_type: %d", wl->bss_type); + wl1271_error("invalid bss_type: %d", wlvif->bss_type); } return WL12XX_INVALID_ROLE_TYPE; } static void wl12xx_init_vif_data(struct wl12xx_vif *wlvif) { + wlvif->bss_type = MAX_BSS_TYPE; wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; @@ -1856,6 +1860,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, { struct wl1271 *wl = hw->priv; struct wiphy *wiphy = hw->wiphy; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int retries = WL1271_BOOT_RETRIES; int ret = 0; u8 role_type; @@ -1871,7 +1876,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, ret = -EBUSY; goto out; } - wl12xx_init_vif_data(wl12xx_vif_to_data(vif)); + wl12xx_init_vif_data(wlvif); /* * in some very corner case HW recovery scenarios its possible to @@ -1888,25 +1893,25 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, wl->p2p = 1; /* fall-through */ case NL80211_IFTYPE_STATION: - wl->bss_type = BSS_TYPE_STA_BSS; + wlvif->bss_type = BSS_TYPE_STA_BSS; wl->set_bss_type = BSS_TYPE_STA_BSS; break; case NL80211_IFTYPE_ADHOC: - wl->bss_type = BSS_TYPE_IBSS; + wlvif->bss_type = BSS_TYPE_IBSS; wl->set_bss_type = BSS_TYPE_STA_BSS; break; case NL80211_IFTYPE_P2P_GO: wl->p2p = 1; /* fall-through */ case NL80211_IFTYPE_AP: - wl->bss_type = BSS_TYPE_AP_BSS; + wlvif->bss_type = BSS_TYPE_AP_BSS; break; default: ret = -EOPNOTSUPP; goto out; } - role_type = wl12xx_get_role_type(wl); + role_type = wl12xx_get_role_type(wl, wlvif); if (role_type == WL12XX_INVALID_ROLE_TYPE) { ret = -EINVAL; goto out; @@ -1938,8 +1943,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (ret < 0) goto irq_disable; - if (wl->bss_type == BSS_TYPE_STA_BSS || - wl->bss_type == BSS_TYPE_IBSS) { + if (wlvif->bss_type == BSS_TYPE_STA_BSS || + wlvif->bss_type == BSS_TYPE_IBSS) { /* * The device role is a special role used for * rx and tx frames prior to association (as @@ -2020,8 +2025,10 @@ out: } static void __wl1271_op_remove_interface(struct wl1271 *wl, + struct ieee80211_vif *vif, bool reset_tx_queues) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret, i; wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); @@ -2037,7 +2044,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, mutex_unlock(&wl_list_mutex); /* enable dyn ps just in case (if left on due to fw crash etc) */ - if (wl->bss_type == BSS_TYPE_STA_BSS) + if (wlvif->bss_type == BSS_TYPE_STA_BSS) ieee80211_enable_dyn_ps(wl->vif); if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { @@ -2054,7 +2061,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, if (ret < 0) goto deinit; - if (wl->bss_type == BSS_TYPE_STA_BSS) { + if (wlvif->bss_type == BSS_TYPE_STA_BSS) { ret = wl12xx_cmd_role_disable(wl, &wl->dev_role_id); if (ret < 0) goto deinit; @@ -2100,7 +2107,6 @@ deinit: memset(wl->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); wl->ssid_len = 0; - wl->bss_type = MAX_BSS_TYPE; wl->set_bss_type = MAX_BSS_TYPE; wl->p2p = 0; wl->band = IEEE80211_BAND_2GHZ; @@ -2169,7 +2175,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, */ if (wl->vif) { WARN_ON(wl->vif != vif); - __wl1271_op_remove_interface(wl, true); + __wl1271_op_remove_interface(wl, vif, true); } mutex_unlock(&wl->mutex); @@ -2180,7 +2186,7 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, bool set_assoc) { int ret; - bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); + bool is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); /* * One of the side effects of the JOIN command is that is clears @@ -2364,7 +2370,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) goto out; } - is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) @@ -2375,7 +2381,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) ((wl->band != conf->channel->band) || (wl->channel != channel))) { /* send all pending packets */ - wl1271_tx_work_locked(wl); + wl1271_tx_work_locked(wl, vif); wl->band = conf->channel->band; wl->channel = channel; @@ -2536,6 +2542,9 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, { struct wl1271_filter_params *fp = (void *)(unsigned long)multicast; struct wl1271 *wl = hw->priv; + struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter changed %x" @@ -2553,7 +2562,7 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, if (ret < 0) goto out; - if (wl->bss_type != BSS_TYPE_AP_BSS) { + if (wlvif->bss_type != BSS_TYPE_AP_BSS) { if (*total & FIF_ALLMULTI) ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); else if (fp) @@ -2673,12 +2682,13 @@ out: return ret; } -static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, +static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u32 tx_seq_32, u16 tx_seq_16, struct ieee80211_sta *sta) { int ret; - bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); if (is_ap) { struct wl1271_station *wl_sta; @@ -2774,6 +2784,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key_conf) { struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; u32 tx_seq_32 = 0; u16 tx_seq_16 = 0; @@ -2833,7 +2844,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch (cmd) { case SET_KEY: - ret = wl1271_set_key(wl, KEY_ADD_OR_REPLACE, + ret = wl1271_set_key(wl, wlvif, KEY_ADD_OR_REPLACE, key_conf->keyidx, key_type, key_conf->keylen, key_conf->key, tx_seq_32, tx_seq_16, sta); @@ -2844,7 +2855,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; case DISABLE_KEY: - ret = wl1271_set_key(wl, KEY_REMOVE, + ret = wl1271_set_key(wl, wlvif, KEY_REMOVE, key_conf->keyidx, key_type, key_conf->keylen, key_conf->key, 0, 0, sta); @@ -2966,6 +2977,7 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, struct ieee80211_sched_scan_ies *ies) { struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_start"); @@ -2976,11 +2988,11 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, if (ret < 0) goto out; - ret = wl1271_scan_sched_scan_config(wl, req, ies); + ret = wl1271_scan_sched_scan_config(wl, wlvif, req, ies); if (ret < 0) goto out_sleep; - ret = wl1271_scan_sched_scan_start(wl); + ret = wl1271_scan_sched_scan_start(wl, wlvif); if (ret < 0) goto out_sleep; @@ -3225,7 +3237,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, u32 changed) { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); int ret = 0; if ((changed & BSS_CHANGED_BEACON_INT)) { @@ -3387,7 +3399,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); bool do_join = false, set_assoc = false; - bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); + bool is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); bool ibss_joined = false; u32 sta_rate_set = 0; int ret; @@ -3623,7 +3635,7 @@ sta_not_found: if (changed & BSS_CHANGED_ARP_FILTER) { __be32 addr = bss_conf->arp_addr_list[0]; - WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); + WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS); if (bss_conf->arp_addr_cnt == 1 && bss_conf->arp_filter_enabled) { @@ -3742,7 +3754,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, u32 changed) { struct wl1271 *wl = hw->priv; - bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x", @@ -3933,6 +3946,7 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret = 0; u8 hlid; @@ -3941,7 +3955,7 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; - if (wl->bss_type != BSS_TYPE_AP_BSS) + if (wlvif->bss_type != BSS_TYPE_AP_BSS) goto out; wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); @@ -3983,6 +3997,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271_station *wl_sta; int ret = 0, id; @@ -3991,7 +4006,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; - if (wl->bss_type != BSS_TYPE_AP_BSS) + if (wlvif->bss_type != BSS_TYPE_AP_BSS) goto out; wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid); @@ -4026,6 +4041,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, u8 buf_size) { struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; u8 hlid, *ba_bitmap; @@ -4043,10 +4059,10 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, goto out; } - if (wl->bss_type == BSS_TYPE_STA_BSS) { + if (wlvif->bss_type == BSS_TYPE_STA_BSS) { hlid = wl->sta_hlid; ba_bitmap = &wl->ba_rx_bitmap; - } else if (wl->bss_type == BSS_TYPE_AP_BSS) { + } else if (wlvif->bss_type == BSS_TYPE_AP_BSS) { struct wl1271_station *wl_sta; wl_sta = (struct wl1271_station *)sta->drv_priv; @@ -4197,10 +4213,6 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) /* packets are considered pending if in the TX queue or the FW */ ret = (wl1271_tx_total_queue_count(wl) > 0) || (wl->tx_frames_cnt > 0); - - /* the above is appropriate for STA mode for PS purposes */ - WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); - out: mutex_unlock(&wl->mutex); @@ -4846,7 +4858,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->flags = 0; wl->sg_enabled = true; wl->hw_pg_ver = -1; - wl->bss_type = MAX_BSS_TYPE; wl->set_bss_type = MAX_BSS_TYPE; wl->last_tx_hlid = 0; wl->ap_ps_map = 0; diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index dee4cfe9ccc1..9cfa0b25a6f8 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -185,6 +185,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) { struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; + struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); u32 buf_size; u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; @@ -192,7 +194,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) u32 mem_block; u32 pkt_length; u32 pkt_offset; - bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); bool had_data = false; bool unaligned = false; diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index a8576181ab7f..197d2c2b1e74 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -34,6 +34,7 @@ void wl1271_scan_complete_work(struct work_struct *work) { struct delayed_work *dwork; struct wl1271 *wl; + struct wl12xx_vif *wlvif; int ret; bool is_sta, is_ibss; @@ -50,6 +51,8 @@ void wl1271_scan_complete_work(struct work_struct *work) if (wl->scan.state == WL1271_SCAN_STATE_IDLE) goto out; + wlvif = wl12xx_vif_to_data(wl->scan_vif); + wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan.req = NULL; @@ -65,8 +68,8 @@ void wl1271_scan_complete_work(struct work_struct *work) } /* return to ROC if needed */ - is_sta = (wl->bss_type == BSS_TYPE_STA_BSS); - is_ibss = (wl->bss_type == BSS_TYPE_IBSS); + is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS); + is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) || (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) && !test_bit(wl->dev_role_id, wl->roc_map)) { @@ -589,6 +592,7 @@ out: } int wl1271_scan_sched_scan_config(struct wl1271 *wl, + struct wl12xx_vif *wlvif, struct cfg80211_sched_scan_request *req, struct ieee80211_sched_scan_ies *ies) { @@ -671,14 +675,14 @@ out: return ret; } -int wl1271_scan_sched_scan_start(struct wl1271 *wl) +int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl1271_cmd_sched_scan_start *start; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); - if (wl->bss_type != BSS_TYPE_STA_BSS) + if (wlvif->bss_type != BSS_TYPE_STA_BSS) return -EOPNOTSUPP; if (!test_bit(WL1271_FLAG_IDLE, &wl->flags)) diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h index 15177bdfb542..a7ed43dc08c9 100644 --- a/drivers/net/wireless/wl12xx/scan.h +++ b/drivers/net/wireless/wl12xx/scan.h @@ -36,9 +36,10 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl, void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif); void wl1271_scan_complete_work(struct work_struct *work); int wl1271_scan_sched_scan_config(struct wl1271 *wl, + struct wl12xx_vif *wlvif, struct cfg80211_sched_scan_request *req, struct ieee80211_sched_scan_ies *ies); -int wl1271_scan_sched_scan_start(struct wl1271 *wl); +int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif); void wl1271_scan_sched_scan_stop(struct wl1271 *wl); void wl1271_scan_sched_scan_results(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index bad9e29d49b0..5561ec2d4b4f 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -32,10 +32,11 @@ #include "tx.h" #include "event.h" -static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id) +static int wl1271_set_default_wep_key(struct wl1271 *wl, + struct wl12xx_vif *wlvif, u8 id) { int ret; - bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); if (is_ap) ret = wl12xx_cmd_set_default_wep_key(wl, id, @@ -178,14 +179,17 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb) } } -static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb) +static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct ieee80211_vif *vif, + struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + if (wl12xx_is_dummy_packet(wl, skb)) return wl->system_hlid; - if (wl->bss_type == BSS_TYPE_AP_BSS) + if (wlvif->bss_type == BSS_TYPE_AP_BSS) return wl12xx_tx_get_hlid_ap(wl, skb); wl1271_tx_update_filters(wl, skb); @@ -208,9 +212,11 @@ static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, return ALIGN(packet_length, WL1271_TX_ALIGN_TO); } -static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, - u32 buf_offset, u8 hlid) +static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif, + struct sk_buff *skb, u32 extra, u32 buf_offset, + u8 hlid) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271_tx_hw_descr *desc; u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; u32 len; @@ -257,7 +263,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); wl->tx_allocated_pkts[ac]++; - if (wl->bss_type == BSS_TYPE_AP_BSS && + if (wlvif->bss_type == BSS_TYPE_AP_BSS && hlid >= WL1271_AP_STA_HLID_START) wl->links[hlid].allocated_pkts++; @@ -273,10 +279,11 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, return ret; } -static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, - u32 extra, struct ieee80211_tx_info *control, - u8 hlid) +static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif, + struct sk_buff *skb, u32 extra, + struct ieee80211_tx_info *control, u8 hlid) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct timespec ts; struct wl1271_tx_hw_descr *desc; int aligned_len, ac, rate_idx; @@ -298,7 +305,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, hosttime = (timespec_to_ns(&ts) >> 10); desc->start_time = cpu_to_le32(hosttime - wl->time_offset); - if (wl->bss_type != BSS_TYPE_AP_BSS) + if (wlvif->bss_type != BSS_TYPE_AP_BSS) desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); else desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU); @@ -324,8 +331,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, } desc->hlid = hlid; - - if (wl->bss_type != BSS_TYPE_AP_BSS) { + if (wlvif->bss_type != BSS_TYPE_AP_BSS) { /* if the packets are destined for AP (have a STA entry) send them with AP rate policies, otherwise use default basic rates */ @@ -383,16 +389,27 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, u32 buf_offset) { struct ieee80211_tx_info *info; + struct ieee80211_vif *vif; + struct wl12xx_vif *wlvif; u32 extra = 0; int ret = 0; u32 total_len; u8 hlid; + bool is_dummy; if (!skb) return -EINVAL; info = IEEE80211_SKB_CB(skb); + /* TODO: handle dummy packets on multi-vifs */ + is_dummy = wl12xx_is_dummy_packet(wl, skb); + if (is_dummy) + info->control.vif = wl->vif; + + vif = info->control.vif; + wlvif = wl12xx_vif_to_data(vif); + if (info->control.hw_key && info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) extra = WL1271_TKIP_IV_SPACE; @@ -406,26 +423,25 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, (cipher == WLAN_CIPHER_SUITE_WEP104); if (unlikely(is_wep && wl->default_key != idx)) { - ret = wl1271_set_default_wep_key(wl, idx); + ret = wl1271_set_default_wep_key(wl, wlvif, idx); if (ret < 0) return ret; wl->default_key = idx; } } - - hlid = wl1271_tx_get_hlid(wl, skb); + hlid = wl1271_tx_get_hlid(wl, vif, skb); if (hlid == WL12XX_INVALID_LINK_ID) { wl1271_error("invalid hlid. dropping skb 0x%p", skb); return -EINVAL; } - ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid); + ret = wl1271_tx_allocate(wl, vif, skb, extra, buf_offset, hlid); if (ret < 0) return ret; - wl1271_tx_fill_hdr(wl, skb, extra, info, hlid); + wl1271_tx_fill_hdr(wl, vif, skb, extra, info, hlid); - if (wl->bss_type == BSS_TYPE_AP_BSS) { + if (wlvif->bss_type == BSS_TYPE_AP_BSS && !is_dummy) { wl1271_tx_ap_update_inconnection_sta(wl, skb); wl1271_tx_regulate_link(wl, hlid); } @@ -444,7 +460,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len); /* Revert side effects in the dummy packet skb, so it can be reused */ - if (wl12xx_is_dummy_packet(wl, skb)) + if (is_dummy) skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); return total_len; @@ -586,12 +602,13 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) return skb; } -static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) +static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { unsigned long flags; struct sk_buff *skb = NULL; - if (wl->bss_type == BSS_TYPE_AP_BSS) + if (wlvif->bss_type == BSS_TYPE_AP_BSS) skb = wl1271_ap_skb_dequeue(wl); else skb = wl1271_sta_skb_dequeue(wl); @@ -610,15 +627,17 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) return skb; } -static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) +static void wl1271_skb_queue_head(struct wl1271 *wl, struct ieee80211_vif *vif, + struct sk_buff *skb) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); unsigned long flags; int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); if (wl12xx_is_dummy_packet(wl, skb)) { set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); - } else if (wl->bss_type == BSS_TYPE_AP_BSS) { - u8 hlid = wl1271_tx_get_hlid(wl, skb); + } else if (wlvif->bss_type == BSS_TYPE_AP_BSS) { + u8 hlid = wl1271_tx_get_hlid(wl, vif, skb); skb_queue_head(&wl->links[hlid].tx_queue[q], skb); /* make sure we dequeue the same packet next time */ @@ -639,19 +658,20 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb) return ieee80211_is_data_present(hdr->frame_control); } -void wl1271_tx_work_locked(struct wl1271 *wl) +void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct sk_buff *skb; u32 buf_offset = 0; bool sent_packets = false; bool had_data = false; - bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); int ret; if (unlikely(wl->state == WL1271_STATE_OFF)) return; - while ((skb = wl1271_skb_dequeue(wl))) { + while ((skb = wl1271_skb_dequeue(wl, wlvif))) { if (wl1271_tx_is_data_present(skb)) had_data = true; @@ -661,7 +681,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) * Aggregation buffer is full. * Flush buffer and try again. */ - wl1271_skb_queue_head(wl, skb); + wl1271_skb_queue_head(wl, vif, skb); wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, buf_offset, true); sent_packets = true; @@ -672,7 +692,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) * Firmware buffer is full. * Queue back last skb, and stop aggregating. */ - wl1271_skb_queue_head(wl, skb); + wl1271_skb_queue_head(wl, vif, skb); /* No work left, avoid scheduling redundant tx work */ set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); goto out_ack; @@ -726,7 +746,7 @@ void wl1271_tx_work(struct work_struct *work) if (ret < 0) goto out; - wl1271_tx_work_locked(wl); + wl1271_tx_work_locked(wl, wl->vif); wl1271_ps_elp_sleep(wl); out: @@ -888,12 +908,14 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) /* caller must hold wl->mutex and TX must be stopped */ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) { + struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int i; struct sk_buff *skb; struct ieee80211_tx_info *info; /* TX failure */ - if (wl->bss_type == BSS_TYPE_AP_BSS) { + if (wlvif->bss_type == BSS_TYPE_AP_BSS) { for (i = 0; i < AP_MAX_LINKS; i++) { wl1271_free_sta(wl, i); wl1271_tx_reset_link_queues(wl, i); diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index dc4f09adf088..ba9403a45404 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -204,7 +204,7 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) } void wl1271_tx_work(struct work_struct *work); -void wl1271_tx_work_locked(struct wl1271 *wl); +void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif); void wl1271_tx_complete(struct wl1271 *wl); void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues); void wl1271_tx_flush(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 44a5daeff07e..97ed19c67695 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -400,7 +400,6 @@ struct wl1271 { s8 hw_pg_ver; u8 mac_addr[ETH_ALEN]; - u8 bss_type; u8 set_bss_type; u8 p2p; /* we are using p2p role */ u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; @@ -630,6 +629,8 @@ struct wl1271_station { }; struct wl12xx_vif { + u8 bss_type; + u32 basic_rate_set; /* From 10bcf745ae737cfbca1796386d76b0636b086770 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:46 +0200 Subject: [PATCH 08/97] wl12xx: remove set_bss_type field set_bss_type is no longer evaluated, so delete it. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 8 -------- drivers/net/wireless/wl12xx/wl12xx.h | 1 - 2 files changed, 9 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 5b13af0f8e8e..50ee9d40e641 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1894,11 +1894,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, /* fall-through */ case NL80211_IFTYPE_STATION: wlvif->bss_type = BSS_TYPE_STA_BSS; - wl->set_bss_type = BSS_TYPE_STA_BSS; break; case NL80211_IFTYPE_ADHOC: wlvif->bss_type = BSS_TYPE_IBSS; - wl->set_bss_type = BSS_TYPE_STA_BSS; break; case NL80211_IFTYPE_P2P_GO: wl->p2p = 1; @@ -2107,7 +2105,6 @@ deinit: memset(wl->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); wl->ssid_len = 0; - wl->set_bss_type = MAX_BSS_TYPE; wl->p2p = 0; wl->band = IEEE80211_BAND_2GHZ; @@ -3439,10 +3436,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", bss_conf->enable_beacon ? "enabled" : "disabled"); - if (bss_conf->enable_beacon) - wl->set_bss_type = BSS_TYPE_IBSS; - else - wl->set_bss_type = BSS_TYPE_STA_BSS; do_join = true; } @@ -4858,7 +4851,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->flags = 0; wl->sg_enabled = true; wl->hw_pg_ver = -1; - wl->set_bss_type = MAX_BSS_TYPE; wl->last_tx_hlid = 0; wl->ap_ps_map = 0; wl->ap_fw_ps_map = 0; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 97ed19c67695..0578d750528b 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -400,7 +400,6 @@ struct wl1271 { s8 hw_pg_ver; u8 mac_addr[ETH_ALEN]; - u8 set_bss_type; u8 p2p; /* we are using p2p role */ u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 ssid_len; From fb0e707c838ac7d8aae7ab90ea448e5ac1e29697 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:47 +0200 Subject: [PATCH 09/97] wl12xx: move p2p into wlvif move p2p field into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 9 ++++----- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 50ee9d40e641..111a465ec541 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1827,13 +1827,13 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) { switch (wlvif->bss_type) { case BSS_TYPE_AP_BSS: - if (wl->p2p) + if (wlvif->p2p) return WL1271_ROLE_P2P_GO; else return WL1271_ROLE_AP; case BSS_TYPE_STA_BSS: - if (wl->p2p) + if (wlvif->p2p) return WL1271_ROLE_P2P_CL; else return WL1271_ROLE_STA; @@ -1890,7 +1890,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, switch (ieee80211_vif_type_p2p(vif)) { case NL80211_IFTYPE_P2P_CLIENT: - wl->p2p = 1; + wlvif->p2p = 1; /* fall-through */ case NL80211_IFTYPE_STATION: wlvif->bss_type = BSS_TYPE_STA_BSS; @@ -1899,7 +1899,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, wlvif->bss_type = BSS_TYPE_IBSS; break; case NL80211_IFTYPE_P2P_GO: - wl->p2p = 1; + wlvif->p2p = 1; /* fall-through */ case NL80211_IFTYPE_AP: wlvif->bss_type = BSS_TYPE_AP_BSS; @@ -2105,7 +2105,6 @@ deinit: memset(wl->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); wl->ssid_len = 0; - wl->p2p = 0; wl->band = IEEE80211_BAND_2GHZ; wl->rx_counter = 0; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 0578d750528b..d84c0deee36a 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -400,7 +400,6 @@ struct wl1271 { s8 hw_pg_ver; u8 mac_addr[ETH_ALEN]; - u8 p2p; /* we are using p2p role */ u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 ssid_len; int channel; @@ -629,6 +628,7 @@ struct wl1271_station { struct wl12xx_vif { u8 bss_type; + u8 p2p; /* we are using p2p role */ u32 basic_rate_set; From 1fe9f1616ee0852e9422d1f676630e9a4531ace3 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:48 +0200 Subject: [PATCH 10/97] wl12xx: move ssid and ssid_len into wlvif move ssid and ssid_len into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 14 +++++++------- drivers/net/wireless/wl12xx/main.c | 21 +++++++++++---------- drivers/net/wireless/wl12xx/wl12xx.h | 5 +++-- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 096a713a8c94..1f29eab82146 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -576,8 +576,8 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int); cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; - cmd->sta.ssid_len = wl->ssid_len; - memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len); + cmd->sta.ssid_len = wlvif->ssid_len; + memcpy(cmd->sta.ssid, wlvif->ssid, wlvif->ssid_len); memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN); cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); @@ -659,7 +659,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id); /* trying to use hidden SSID with an old hostapd version */ - if (wl->ssid_len == 0 && !bss_conf->hidden_ssid) { + if (wlvif->ssid_len == 0 && !bss_conf->hidden_ssid) { wl1271_error("got a null SSID from beacon/bss"); ret = -EINVAL; goto out; @@ -693,8 +693,8 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (!bss_conf->hidden_ssid) { /* take the SSID from the beacon for backward compatibility */ cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; - cmd->ap.ssid_len = wl->ssid_len; - memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len); + cmd->ap.ssid_len = wlvif->ssid_len; + memcpy(cmd->ap.ssid, wlvif->ssid, wlvif->ssid_len); } else { cmd->ap.ssid_type = WL12XX_SSID_TYPE_HIDDEN; cmd->ap.ssid_len = bss_conf->ssid_len; @@ -791,8 +791,8 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int); cmd->ibss.dtim_interval = bss_conf->dtim_period; cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY; - cmd->ibss.ssid_len = wl->ssid_len; - memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len); + cmd->ibss.ssid_len = wlvif->ssid_len; + memcpy(cmd->ibss.ssid, wlvif->ssid, wlvif->ssid_len); memcpy(cmd->ibss.bssid, vif->bss_conf.bssid, ETH_ALEN); cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 111a465ec541..0da9ddc8b6cf 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2103,8 +2103,6 @@ deinit: wl1271_tx_reset(wl, reset_tx_queues); wl1271_power_off(wl); - memset(wl->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); - wl->ssid_len = 0; wl->band = IEEE80211_BAND_2GHZ; wl->rx_counter = 0; @@ -3078,9 +3076,10 @@ out: return ret; } -static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, +static int wl1271_ssid_set(struct ieee80211_vif *vif, struct sk_buff *skb, int offset) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); u8 ssid_len; const u8 *ptr = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, skb->len - offset); @@ -3096,8 +3095,8 @@ static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, return -EINVAL; } - wl->ssid_len = ssid_len; - memcpy(wl->ssid, ptr+2, ssid_len); + wlvif->ssid_len = ssid_len; + memcpy(wlvif->ssid, ptr+2, ssid_len); return 0; } @@ -3133,17 +3132,19 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb, } static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, + struct ieee80211_vif *vif, u8 *probe_rsp_data, size_t probe_rsp_len, u32 rates) { - struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; u8 probe_rsp_templ[WL1271_CMD_TEMPL_MAX_SIZE]; int ssid_ie_offset, ie_offset, templ_len; const u8 *ptr; /* no need to change probe response if the SSID is set correctly */ - if (wl->ssid_len > 0) + if (wlvif->ssid_len > 0) return wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, probe_rsp_data, @@ -3256,7 +3257,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, wl1271_debug(DEBUG_MASTER, "beacon updated"); - ret = wl1271_ssid_set(wl, beacon, ieoffset); + ret = wl1271_ssid_set(vif, beacon, ieoffset); if (ret < 0) { dev_kfree_skb(beacon); goto out; @@ -3291,7 +3292,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); if (is_ap) - ret = wl1271_ap_set_probe_resp_tmpl(wl, + ret = wl1271_ap_set_probe_resp_tmpl(wl, vif, beacon->data, beacon->len, min_rate); @@ -3528,7 +3529,7 @@ sta_not_found: wl->probereq = wl1271_cmd_build_ap_probe_req(wl, NULL); ieoffset = offsetof(struct ieee80211_mgmt, u.probe_req.variable); - wl1271_ssid_set(wl, wl->probereq, ieoffset); + wl1271_ssid_set(vif, wl->probereq, ieoffset); /* enable the connection monitoring feature */ ret = wl1271_acx_conn_monit_params(wl, true); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index d84c0deee36a..539cf40be535 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -400,8 +400,6 @@ struct wl1271 { s8 hw_pg_ver; u8 mac_addr[ETH_ALEN]; - u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; - u8 ssid_len; int channel; u8 role_id; u8 dev_role_id; @@ -630,6 +628,9 @@ struct wl12xx_vif { u8 bss_type; u8 p2p; /* we are using p2p role */ + u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; + u8 ssid_len; + u32 basic_rate_set; /* From bddb29b83a9874fda21c34abe7627cbf14fec10e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:49 +0200 Subject: [PATCH 11/97] wl12xx: move probereq into wlvif move probereq into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 11 ++++++----- drivers/net/wireless/wl12xx/scan.c | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0da9ddc8b6cf..006e17458130 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3525,11 +3525,12 @@ sta_not_found: /* * Get a template for hardware connection maintenance */ - dev_kfree_skb(wl->probereq); - wl->probereq = wl1271_cmd_build_ap_probe_req(wl, NULL); + dev_kfree_skb(wlvif->probereq); + wlvif->probereq = wl1271_cmd_build_ap_probe_req(wl, + NULL); ieoffset = offsetof(struct ieee80211_mgmt, u.probe_req.variable); - wl1271_ssid_set(vif, wl->probereq, ieoffset); + wl1271_ssid_set(vif, wlvif->probereq, ieoffset); /* enable the connection monitoring feature */ ret = wl1271_acx_conn_monit_params(wl, true); @@ -3546,8 +3547,8 @@ sta_not_found: wl->aid = 0; /* free probe-request template */ - dev_kfree_skb(wl->probereq); - wl->probereq = NULL; + dev_kfree_skb(wlvif->probereq); + wlvif->probereq = NULL; /* re-enable dynamic ps - just in case */ ieee80211_enable_dyn_ps(wl->vif); diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 197d2c2b1e74..e3b863b895f3 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -64,7 +64,7 @@ void wl1271_scan_complete_work(struct work_struct *work) if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { /* restore hardware connection monitoring template */ - wl1271_cmd_build_ap_probe_req(wl, wl->probereq); + wl1271_cmd_build_ap_probe_req(wl, wlvif->probereq); } /* return to ROC if needed */ diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 539cf40be535..8d100561522c 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -507,9 +507,6 @@ struct wl1271 { bool sched_scanning; - /* probe-req template for the current AP */ - struct sk_buff *probereq; - /* Our association ID */ u16 aid; @@ -641,6 +638,9 @@ struct wl12xx_vif { */ u32 basic_rate; u32 rate_set; + + /* probe-req template for the current AP */ + struct sk_buff *probereq; }; static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) From 6840e37aec6fd9ffa5b4cf62674af55afdb565ed Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:50 +0200 Subject: [PATCH 12/97] wl12xx: move aid into wlvif move aid into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 8 ++++---- drivers/net/wireless/wl12xx/wl12xx.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 006e17458130..e0a557fc3a31 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2217,7 +2217,7 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (ret < 0) goto out; - ret = wl1271_acx_aid(wl, wl->aid); + ret = wl1271_acx_aid(wl, wlvif->aid); if (ret < 0) goto out; @@ -3487,7 +3487,7 @@ sta_not_found: if (bss_conf->assoc) { u32 rates; int ieoffset; - wl->aid = bss_conf->aid; + wlvif->aid = bss_conf->aid; set_assoc = true; wl->ps_poll_failures = 0; @@ -3518,7 +3518,7 @@ sta_not_found: * updates it by itself when the first beacon is * received after a join. */ - ret = wl1271_cmd_build_ps_poll(wl, wlvif, wl->aid); + ret = wl1271_cmd_build_ps_poll(wl, wlvif, wlvif->aid); if (ret < 0) goto out; @@ -3544,7 +3544,7 @@ sta_not_found: bool was_ifup = !!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); - wl->aid = 0; + wlvif->aid = 0; /* free probe-request template */ dev_kfree_skb(wlvif->probereq); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 8d100561522c..e6d3c214acf9 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -507,9 +507,6 @@ struct wl1271 { bool sched_scanning; - /* Our association ID */ - u16 aid; - u32 bitrate_masks[IEEE80211_NUM_BANDS]; /* The current band */ @@ -641,6 +638,9 @@ struct wl12xx_vif { /* probe-req template for the current AP */ struct sk_buff *probereq; + + /* Our association ID */ + u16 aid; }; static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) From 0603d891c5b5153f667a79357d4652824c22b54e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:51 +0200 Subject: [PATCH 13/97] wl12xx: move role_id into wlvif move role_id into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 124 +++++++++++++++----------- drivers/net/wireless/wl12xx/acx.h | 71 +++++++++------ drivers/net/wireless/wl12xx/cmd.c | 33 +++---- drivers/net/wireless/wl12xx/cmd.h | 7 +- drivers/net/wireless/wl12xx/debugfs.c | 10 ++- drivers/net/wireless/wl12xx/event.c | 13 +-- drivers/net/wireless/wl12xx/init.c | 69 +++++++------- drivers/net/wireless/wl12xx/main.c | 118 +++++++++++++----------- drivers/net/wireless/wl12xx/ps.c | 14 +-- drivers/net/wireless/wl12xx/ps.h | 4 +- drivers/net/wireless/wl12xx/scan.c | 5 +- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 12 files changed, 270 insertions(+), 200 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 015938f94805..9b4eef61bd01 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -33,7 +33,7 @@ #include "reg.h" #include "ps.h" -int wl1271_acx_wake_up_conditions(struct wl1271 *wl) +int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct acx_wake_up_condition *wake_up; int ret; @@ -46,7 +46,7 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl) goto out; } - wake_up->role_id = wl->role_id; + wake_up->role_id = wlvif->role_id; wake_up->wake_up_event = wl->conf.conn.wake_up_event; wake_up->listen_interval = wl->conf.conn.listen_interval; @@ -84,7 +84,8 @@ out: return ret; } -int wl1271_acx_tx_power(struct wl1271 *wl, int power) +int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, + int power) { struct acx_current_tx_power *acx; int ret; @@ -100,7 +101,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) goto out; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->current_tx_power = power * 10; ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); @@ -114,7 +115,7 @@ out: return ret; } -int wl1271_acx_feature_cfg(struct wl1271 *wl) +int wl1271_acx_feature_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct acx_feature_config *feature; int ret; @@ -128,7 +129,7 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl) } /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ - feature->role_id = wl->role_id; + feature->role_id = wlvif->role_id; feature->data_flow_options = 0; feature->options = 0; @@ -210,7 +211,8 @@ out: return ret; } -int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) +int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif, + enum acx_slot_type slot_time) { struct acx_slot *slot; int ret; @@ -223,7 +225,7 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) goto out; } - slot->role_id = wl->role_id; + slot->role_id = wlvif->role_id; slot->wone_index = STATION_WONE_INDEX; slot->slot_time = slot_time; @@ -238,8 +240,8 @@ out: return ret; } -int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, - void *mc_list, u32 mc_list_len) +int wl1271_acx_group_address_tbl(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable, void *mc_list, u32 mc_list_len) { struct acx_dot11_grp_addr_tbl *acx; int ret; @@ -253,7 +255,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, } /* MAC filtering */ - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->enabled = enable; acx->num_groups = mc_list_len; memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN); @@ -270,7 +272,8 @@ out: return ret; } -int wl1271_acx_service_period_timeout(struct wl1271 *wl) +int wl1271_acx_service_period_timeout(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { struct acx_rx_timeout *rx_timeout; int ret; @@ -283,7 +286,7 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl) wl1271_debug(DEBUG_ACX, "acx service period timeout"); - rx_timeout->role_id = wl->role_id; + rx_timeout->role_id = wlvif->role_id; rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout); rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout); @@ -300,7 +303,8 @@ out: return ret; } -int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold) +int wl1271_acx_rts_threshold(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u32 rts_threshold) { struct acx_rts_threshold *rts; int ret; @@ -320,7 +324,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold) goto out; } - rts->role_id = wl->role_id; + rts->role_id = wlvif->role_id; rts->threshold = cpu_to_le16((u16)rts_threshold); ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); @@ -363,7 +367,8 @@ out: return ret; } -int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) +int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable_filter) { struct acx_beacon_filter_option *beacon_filter = NULL; int ret = 0; @@ -380,7 +385,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) goto out; } - beacon_filter->role_id = wl->role_id; + beacon_filter->role_id = wlvif->role_id; beacon_filter->enable = enable_filter; /* @@ -401,7 +406,8 @@ out: return ret; } -int wl1271_acx_beacon_filter_table(struct wl1271 *wl) +int wl1271_acx_beacon_filter_table(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { struct acx_beacon_filter_ie_table *ie_table; int i, idx = 0; @@ -417,7 +423,7 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl) } /* configure default beacon pass-through rules */ - ie_table->role_id = wl->role_id; + ie_table->role_id = wlvif->role_id; ie_table->num_ie = 0; for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) { struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]); @@ -458,7 +464,8 @@ out: #define ACX_CONN_MONIT_DISABLE_VALUE 0xffffffff -int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) +int wl1271_acx_conn_monit_params(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable) { struct acx_conn_monit_params *acx; u32 threshold = ACX_CONN_MONIT_DISABLE_VALUE; @@ -479,7 +486,7 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) timeout = wl->conf.conn.bss_lose_timeout; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->synch_fail_thold = cpu_to_le32(threshold); acx->bss_lose_timeout = cpu_to_le32(timeout); @@ -582,7 +589,7 @@ out: return ret; } -int wl1271_acx_bcn_dtim_options(struct wl1271 *wl) +int wl1271_acx_bcn_dtim_options(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct acx_beacon_broadcast *bb; int ret; @@ -595,7 +602,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl) goto out; } - bb->role_id = wl->role_id; + bb->role_id = wlvif->role_id; bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout); bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout); bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps; @@ -612,7 +619,7 @@ out: return ret; } -int wl1271_acx_aid(struct wl1271 *wl, u16 aid) +int wl1271_acx_aid(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 aid) { struct acx_aid *acx_aid; int ret; @@ -625,7 +632,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid) goto out; } - acx_aid->role_id = wl->role_id; + acx_aid->role_id = wlvif->role_id; acx_aid->aid = cpu_to_le16(aid); ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); @@ -668,7 +675,8 @@ out: return ret; } -int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble) +int wl1271_acx_set_preamble(struct wl1271 *wl, struct wl12xx_vif *wlvif, + enum acx_preamble_type preamble) { struct acx_preamble *acx; int ret; @@ -681,7 +689,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble) goto out; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->preamble = preamble; ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx)); @@ -695,7 +703,7 @@ out: return ret; } -int wl1271_acx_cts_protect(struct wl1271 *wl, +int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif, enum acx_ctsprotect_type ctsprotect) { struct acx_ctsprotect *acx; @@ -709,7 +717,7 @@ int wl1271_acx_cts_protect(struct wl1271 *wl, goto out; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->ctsprotect = ctsprotect; ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx)); @@ -839,8 +847,8 @@ out: return ret; } -int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, - u8 aifsn, u16 txop) +int wl1271_acx_ac_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 ac, u8 cw_min, u16 cw_max, u8 aifsn, u16 txop) { struct acx_ac_cfg *acx; int ret = 0; @@ -855,7 +863,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, goto out; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->ac = ac; acx->cw_min = cw_min; acx->cw_max = cpu_to_le16(cw_max); @@ -873,7 +881,8 @@ out: return ret; } -int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, +int wl1271_acx_tid_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 queue_id, u8 channel_type, u8 tsid, u8 ps_scheme, u8 ack_policy, u32 apsd_conf0, u32 apsd_conf1) { @@ -889,7 +898,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, goto out; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->queue_id = queue_id; acx->channel_type = channel_type; acx->tsid = tsid; @@ -1098,7 +1107,8 @@ out: return ret; } -int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) +int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable) { struct wl1271_acx_bet_enable *acx = NULL; int ret = 0; @@ -1114,7 +1124,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) goto out; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE; acx->max_consecutive = wl->conf.conn.bet_max_consecutive; @@ -1129,7 +1139,8 @@ out: return ret; } -int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address) +int wl1271_acx_arp_ip_filter(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 enable, __be32 address) { struct wl1271_acx_arp_filter *acx; int ret; @@ -1142,7 +1153,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address) goto out; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->version = ACX_IPV4_VERSION; acx->enable = enable; @@ -1189,7 +1200,8 @@ out: return ret; } -int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) +int wl1271_acx_keep_alive_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable) { struct wl1271_acx_keep_alive_mode *acx = NULL; int ret = 0; @@ -1202,7 +1214,7 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) goto out; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->enabled = enable; ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); @@ -1216,7 +1228,8 @@ out: return ret; } -int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) +int wl1271_acx_keep_alive_config(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 index, u8 tpl_valid) { struct wl1271_acx_keep_alive_config *acx = NULL; int ret = 0; @@ -1229,7 +1242,7 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) goto out; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); acx->index = index; acx->tpl_validation = tpl_valid; @@ -1247,8 +1260,8 @@ out: return ret; } -int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, - s16 thold, u8 hyst) +int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable, s16 thold, u8 hyst) { struct wl1271_acx_rssi_snr_trigger *acx = NULL; int ret = 0; @@ -1263,7 +1276,7 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, wl->last_rssi_event = -1; - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing); acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON; acx->type = WL1271_ACX_TRIG_TYPE_EDGE; @@ -1288,7 +1301,8 @@ out: return ret; } -int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) +int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { struct wl1271_acx_rssi_snr_avg_weights *acx = NULL; struct conf_roam_trigger_settings *c = &wl->conf.roam_trigger; @@ -1302,7 +1316,7 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) goto out; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->rssi_beacon = c->avg_weight_rssi_beacon; acx->rssi_data = c->avg_weight_rssi_data; acx->snr_beacon = c->avg_weight_snr_beacon; @@ -1367,6 +1381,7 @@ out: } int wl1271_acx_set_ht_information(struct wl1271 *wl, + struct wl12xx_vif *wlvif, u16 ht_operation_mode) { struct wl1271_acx_ht_information *acx; @@ -1380,7 +1395,7 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl, goto out; } - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->ht_protection = (u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION); acx->rifs_mode = 0; @@ -1402,7 +1417,8 @@ out: } /* Configure BA session initiator/receiver parameters setting in the FW. */ -int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl) +int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { struct wl1271_acx_ba_initiator_policy *acx; int ret; @@ -1416,7 +1432,7 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl) } /* set for the current role */ - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->tid_bitmap = wl->conf.ht.tx_ba_tid_bitmap; acx->win_size = wl->conf.ht.tx_ba_win_size; acx->inactivity_timeout = wl->conf.ht.inactivity_timeout; @@ -1496,6 +1512,8 @@ out: int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable) { + struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271_acx_ps_rx_streaming *rx_streaming; u32 conf_queues, enable_queues; int i, ret = 0; @@ -1523,7 +1541,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable) if (!(conf_queues & BIT(i))) continue; - rx_streaming->role_id = wl->role_id; + rx_streaming->role_id = wlvif->role_id; rx_streaming->tid = i; rx_streaming->enable = enable_queues & BIT(i); rx_streaming->period = wl->conf.rx_streaming.interval; @@ -1542,7 +1560,7 @@ out: return ret; } -int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) +int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl1271_acx_ap_max_tx_retry *acx = NULL; int ret; @@ -1553,7 +1571,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) if (!acx) return -ENOMEM; - acx->role_id = wl->role_id; + acx->role_id = wlvif->role_id; acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 2678e1d505f9..7fccfcc55ca0 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -1234,39 +1234,49 @@ enum { }; -int wl1271_acx_wake_up_conditions(struct wl1271 *wl); +int wl1271_acx_wake_up_conditions(struct wl1271 *wl, + struct wl12xx_vif *wlvif); int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); -int wl1271_acx_tx_power(struct wl1271 *wl, int power); -int wl1271_acx_feature_cfg(struct wl1271 *wl); +int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, + int power); +int wl1271_acx_feature_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map, size_t len); int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl); int wl1271_acx_pd_threshold(struct wl1271 *wl); -int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); -int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, - void *mc_list, u32 mc_list_len); -int wl1271_acx_service_period_timeout(struct wl1271 *wl); -int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold); +int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif, + enum acx_slot_type slot_time); +int wl1271_acx_group_address_tbl(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable, void *mc_list, u32 mc_list_len); +int wl1271_acx_service_period_timeout(struct wl1271 *wl, + struct wl12xx_vif *wlvif); +int wl1271_acx_rts_threshold(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u32 rts_threshold); int wl1271_acx_dco_itrim_params(struct wl1271 *wl); -int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); -int wl1271_acx_beacon_filter_table(struct wl1271 *wl); -int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); +int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable_filter); +int wl1271_acx_beacon_filter_table(struct wl1271 *wl, + struct wl12xx_vif *wlvif); +int wl1271_acx_conn_monit_params(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable); int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); int wl12xx_acx_sg_cfg(struct wl1271 *wl); int wl1271_acx_cca_threshold(struct wl1271 *wl); -int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); -int wl1271_acx_aid(struct wl1271 *wl, u16 aid); +int wl1271_acx_bcn_dtim_options(struct wl1271 *wl, struct wl12xx_vif *wlvif); +int wl1271_acx_aid(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 aid); int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask); -int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); -int wl1271_acx_cts_protect(struct wl1271 *wl, +int wl1271_acx_set_preamble(struct wl1271 *wl, struct wl12xx_vif *wlvif, + enum acx_preamble_type preamble); +int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif, enum acx_ctsprotect_type ctsprotect); int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, u8 idx); -int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, - u8 aifsn, u16 txop); -int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, +int wl1271_acx_ac_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 ac, u8 cw_min, u16 cw_max, u8 aifsn, u16 txop); +int wl1271_acx_tid_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 queue_id, u8 channel_type, u8 tsid, u8 ps_scheme, u8 ack_policy, u32 apsd_conf0, u32 apsd_conf1); int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold); @@ -1276,25 +1286,32 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl); int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); int wl1271_acx_smart_reflex(struct wl1271 *wl); -int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); -int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address); +int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable); +int wl1271_acx_arp_ip_filter(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 enable, __be32 address); int wl1271_acx_pm_config(struct wl1271 *wl); -int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); -int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); -int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, - s16 thold, u8 hyst); -int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); +int wl1271_acx_keep_alive_mode(struct wl1271 *wl, struct wl12xx_vif *vif, + bool enable); +int wl1271_acx_keep_alive_config(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 index, u8 tpl_valid); +int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable, s16 thold, u8 hyst); +int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl, + struct wl12xx_vif *wlvif); int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, struct ieee80211_sta_ht_cap *ht_cap, bool allow_ht_operation, u8 hlid); int wl1271_acx_set_ht_information(struct wl1271 *wl, + struct wl12xx_vif *wlvif, u16 ht_operation_mode); -int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl); +int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, + struct wl12xx_vif *wlvif); int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, bool enable, u8 peer_hlid); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); -int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); +int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); int wl1271_acx_fm_coex(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 1f29eab82146..918faca517cf 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -567,9 +567,9 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; } - wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wl->role_id); + wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wlvif->role_id); - cmd->role_id = wl->role_id; + cmd->role_id = wlvif->role_id; if (wl->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; @@ -592,7 +592,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " "basic_rate_set: 0x%x, remote_rates: 0x%x", - wl->role_id, cmd->sta.hlid, cmd->sta.session, + wlvif->role_id, cmd->sta.hlid, cmd->sta.session, wlvif->basic_rate_set, wlvif->rate_set); ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); @@ -615,7 +615,7 @@ out: } /* use this function to stop ibss as well */ -int wl12xx_cmd_role_stop_sta(struct wl1271 *wl) +int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_stop *cmd; int ret; @@ -629,9 +629,9 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl) goto out; } - wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wl->role_id); + wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wlvif->role_id); - cmd->role_id = wl->role_id; + cmd->role_id = wlvif->role_id; cmd->disc_type = DISCONNECT_IMMEDIATE; cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); @@ -656,7 +656,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; int ret; - wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id); + wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wlvif->role_id); /* trying to use hidden SSID with an old hostapd version */ if (wlvif->ssid_len == 0 && !bss_conf->hidden_ssid) { @@ -679,7 +679,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (ret < 0) goto out_free_global; - cmd->role_id = wl->role_id; + cmd->role_id = wlvif->role_id; cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); cmd->ap.bss_index = WL1271_AP_BSS_INDEX; cmd->ap.global_hlid = wl->ap_global_hlid; @@ -737,7 +737,7 @@ out: return ret; } -int wl12xx_cmd_role_stop_ap(struct wl1271 *wl) +int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_stop *cmd; int ret; @@ -748,9 +748,9 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl) goto out; } - wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wl->role_id); + wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wlvif->role_id); - cmd->role_id = wl->role_id; + cmd->role_id = wlvif->role_id; ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); if (ret < 0) { @@ -781,9 +781,9 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; } - wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wl->role_id); + wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wlvif->role_id); - cmd->role_id = wl->role_id; + cmd->role_id = wlvif->role_id; if (wl->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; @@ -806,7 +806,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " "basic_rate_set: 0x%x, remote_rates: 0x%x", - wl->role_id, cmd->sta.hlid, cmd->sta.session, + wlvif->role_id, cmd->sta.hlid, cmd->sta.session, wlvif->basic_rate_set, wlvif->rate_set); wl1271_debug(DEBUG_CMD, "vif->bss_conf.bssid = %pM", @@ -966,7 +966,8 @@ out: return ret; } -int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) +int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 ps_mode) { struct wl1271_cmd_ps_params *ps_params = NULL; int ret = 0; @@ -979,7 +980,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) goto out; } - ps_params->role_id = wl->role_id; + ps_params->role_id = wlvif->role_id; ps_params->ps_mode = ps_mode; ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index d5749f5b3bf1..bf2c45b8b911 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -42,15 +42,16 @@ int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); int wl12xx_cmd_role_start_dev(struct wl1271 *wl); int wl12xx_cmd_role_stop_dev(struct wl1271 *wl); int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl12xx_cmd_role_stop_sta(struct wl1271 *wl); +int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl12xx_cmd_role_stop_ap(struct wl1271 *wl); +int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); -int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); +int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 ps_mode); int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, size_t len); int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 8f88ad6496f9..3309fea2e90e 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -620,11 +620,19 @@ static ssize_t beacon_filtering_write(struct file *file, size_t count, loff_t *ppos) { struct wl1271 *wl = file->private_data; + struct ieee80211_vif *vif; + struct wl12xx_vif *wlvif; char buf[10]; size_t len; unsigned long value; int ret; + if (!wl->vif) + return -EINVAL; + + vif = wl->vif; + wlvif = wl12xx_vif_to_data(vif); + len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; @@ -642,7 +650,7 @@ static ssize_t beacon_filtering_write(struct file *file, if (ret < 0) goto out; - ret = wl1271_acx_beacon_filter_opt(wl, !!value); + ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value); wl1271_ps_elp_sleep(wl); out: diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 072addc0bffc..28a4396fb8e4 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -64,8 +64,8 @@ void wl1271_pspoll_work(struct work_struct *work) if (ret < 0) goto out; - wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wlvif->basic_rate, - true); + wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, + wlvif->basic_rate, true); wl1271_ps_elp_sleep(wl); out: @@ -85,7 +85,7 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl, /* force active mode receive data from the AP */ if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { - ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, + ret = wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, wlvif->basic_rate, true); if (ret < 0) return; @@ -124,7 +124,8 @@ static int wl1271_event_ps_report(struct wl1271 *wl, if (wl->psm_entry_retry < total_retries) { wl->psm_entry_retry++; - ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, + ret = wl1271_ps_set_mode(wl, wlvif, + STATION_POWER_SAVE_MODE, wlvif->basic_rate, true); } else { wl1271_info("No ack to nullfunc from AP."); @@ -136,7 +137,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, wl->psm_entry_retry = 0; /* enable beacon filtering */ - ret = wl1271_acx_beacon_filter_opt(wl, true); + ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); if (ret < 0) break; @@ -146,7 +147,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, */ if (wl->band == IEEE80211_BAND_2GHZ) /* enable beacon early termination */ - ret = wl1271_acx_bet_enable(wl, true); + ret = wl1271_acx_bet_enable(wl, wlvif, true); if (wl->ps_compl) { complete(wl->ps_compl); diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index e54cc693ff69..1eaa0a3d9273 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -233,35 +233,37 @@ int wl1271_init_phy_config(struct wl1271 *wl) return 0; } -static int wl12xx_init_phy_vif_config(struct wl1271 *wl) +static int wl12xx_init_phy_vif_config(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { int ret; - ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME); + ret = wl1271_acx_slot(wl, wlvif, DEFAULT_SLOT_TIME); if (ret < 0) return ret; - ret = wl1271_acx_service_period_timeout(wl); + ret = wl1271_acx_service_period_timeout(wl, wlvif); if (ret < 0) return ret; - ret = wl1271_acx_rts_threshold(wl, wl->hw->wiphy->rts_threshold); + ret = wl1271_acx_rts_threshold(wl, wlvif, wl->hw->wiphy->rts_threshold); if (ret < 0) return ret; return 0; } -static int wl1271_init_beacon_filter(struct wl1271 *wl) +static int wl1271_init_beacon_filter(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { int ret; /* disable beacon filtering at this stage */ - ret = wl1271_acx_beacon_filter_opt(wl, false); + ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); if (ret < 0) return ret; - ret = wl1271_acx_beacon_filter_table(wl); + ret = wl1271_acx_beacon_filter_table(wl, wlvif); if (ret < 0) return ret; @@ -294,11 +296,12 @@ int wl1271_init_energy_detection(struct wl1271 *wl) return 0; } -static int wl1271_init_beacon_broadcast(struct wl1271 *wl) +static int wl1271_init_beacon_broadcast(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { int ret; - ret = wl1271_acx_bcn_dtim_options(wl); + ret = wl1271_acx_bcn_dtim_options(wl, wlvif); if (ret < 0) return ret; @@ -352,20 +355,22 @@ static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) return 0; } -static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl) +static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl, + struct ieee80211_vif *vif) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret, i; /* disable all keep-alive templates */ for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { - ret = wl1271_acx_keep_alive_config(wl, i, + ret = wl1271_acx_keep_alive_config(wl, wlvif, i, ACX_KEEP_ALIVE_TPL_INVALID); if (ret < 0) return ret; } /* disable the keep-alive feature */ - ret = wl1271_acx_keep_alive_mode(wl, false); + ret = wl1271_acx_keep_alive_mode(wl, wlvif, false); if (ret < 0) return ret; @@ -410,7 +415,7 @@ int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif) * when operating as AP we want to receive external beacons for * configuring ERP protection. */ - ret = wl1271_acx_beacon_filter_opt(wl, false); + ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); if (ret < 0) return ret; @@ -495,7 +500,7 @@ static int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) wl->ba_support = true; /* 802.11n initiator BA session setting */ - return wl12xx_acx_set_ba_initiator_policy(wl); + return wl12xx_acx_set_ba_initiator_policy(wl, wlvif); } int wl1271_chip_specific_init(struct wl1271 *wl) @@ -519,31 +524,31 @@ out: } /* vif-specifc initialization */ -static int wl12xx_init_sta_role(struct wl1271 *wl, struct ieee80211_vif *vif) +static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret; - ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0); + ret = wl1271_acx_group_address_tbl(wl, wlvif, true, NULL, 0); if (ret < 0) return ret; /* Initialize connection monitoring thresholds */ - ret = wl1271_acx_conn_monit_params(wl, false); + ret = wl1271_acx_conn_monit_params(wl, wlvif, false); if (ret < 0) return ret; /* Beacon filtering */ - ret = wl1271_init_beacon_filter(wl); + ret = wl1271_init_beacon_filter(wl, wlvif); if (ret < 0) return ret; /* Beacons and broadcast settings */ - ret = wl1271_init_beacon_broadcast(wl); + ret = wl1271_init_beacon_broadcast(wl, wlvif); if (ret < 0) return ret; /* Configure rssi/snr averaging weights */ - ret = wl1271_acx_rssi_snr_avg_weights(wl); + ret = wl1271_acx_rssi_snr_avg_weights(wl, wlvif); if (ret < 0) return ret; @@ -551,16 +556,16 @@ static int wl12xx_init_sta_role(struct wl1271 *wl, struct ieee80211_vif *vif) } /* vif-specific intialization */ -static int wl12xx_init_ap_role(struct wl1271 *wl, struct ieee80211_vif *vif) +static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret; - ret = wl1271_acx_ap_max_tx_retry(wl); + ret = wl1271_acx_ap_max_tx_retry(wl, wlvif); if (ret < 0) return ret; /* initialize Tx power */ - ret = wl1271_acx_tx_power(wl, wl->power_level); + ret = wl1271_acx_tx_power(wl, wlvif, wl->power_level); if (ret < 0) return ret; @@ -582,7 +587,7 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) if (ret < 0) return ret; - ret = wl12xx_init_ap_role(wl, vif); + ret = wl12xx_init_ap_role(wl, wlvif); if (ret < 0) return ret; } else { @@ -590,25 +595,25 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) if (ret < 0) return ret; - ret = wl12xx_init_sta_role(wl, vif); + ret = wl12xx_init_sta_role(wl, wlvif); if (ret < 0) return ret; } - wl12xx_init_phy_vif_config(wl); + wl12xx_init_phy_vif_config(wl, wlvif); /* Default TID/AC configuration */ BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { conf_ac = &wl->conf.tx.ac_conf[i]; - ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, - conf_ac->cw_max, conf_ac->aifsn, - conf_ac->tx_op_limit); + ret = wl1271_acx_ac_cfg(wl, wlvif, conf_ac->ac, + conf_ac->cw_min, conf_ac->cw_max, + conf_ac->aifsn, conf_ac->tx_op_limit); if (ret < 0) return ret; conf_tid = &wl->conf.tx.tid_conf[i]; - ret = wl1271_acx_tid_cfg(wl, + ret = wl1271_acx_tid_cfg(wl, wlvif, conf_tid->queue_id, conf_tid->channel_type, conf_tid->tsid, @@ -621,7 +626,7 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) } /* Configure HW encryption */ - ret = wl1271_acx_feature_cfg(wl); + ret = wl1271_acx_feature_cfg(wl, wlvif); if (ret < 0) return ret; @@ -629,7 +634,7 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) if (is_ap) ret = wl1271_ap_hw_init_post_mem(wl, vif); else - ret = wl1271_sta_hw_init_post_mem(wl); + ret = wl1271_sta_hw_init_post_mem(wl, vif); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index e0a557fc3a31..b3d4ef5b900d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -402,7 +402,10 @@ static LIST_HEAD(wl_list); static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate) { + struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; + if (operstate != IF_OPER_UP) return 0; @@ -413,7 +416,7 @@ static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate) if (ret < 0) return ret; - wl12xx_croc(wl, wl->role_id); + wl12xx_croc(wl, wlvif->role_id); wl1271_info("Association completed."); return 0; @@ -695,7 +698,7 @@ static int wl1271_plt_init(struct wl1271 *wl) goto out_free_memmap; /* Initialize connection monitoring thresholds */ - ret = wl1271_acx_conn_monit_params(wl, false); + ret = wl1271_acx_conn_monit_params(wl, NULL, false); /* TODO: fix */ if (ret < 0) goto out_free_memmap; @@ -727,14 +730,16 @@ static int wl1271_plt_init(struct wl1271 *wl) BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { conf_ac = &wl->conf.tx.ac_conf[i]; - ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, + /* TODO: fix */ + ret = wl1271_acx_ac_cfg(wl, NULL, conf_ac->ac, conf_ac->cw_min, conf_ac->cw_max, conf_ac->aifsn, conf_ac->tx_op_limit); if (ret < 0) goto out_free_memmap; conf_tid = &wl->conf.tx.tid_conf[i]; - ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, + /* TODO: fix */ + ret = wl1271_acx_tid_cfg(wl, NULL, conf_tid->queue_id, conf_tid->channel_type, conf_tid->tsid, conf_tid->ps_scheme, @@ -1631,7 +1636,7 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, DECLARE_COMPLETION_ONSTACK(compl); wl->ps_compl = &compl; - ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, + ret = wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, wlvif->basic_rate, true); if (ret < 0) goto out_sleep; @@ -1664,7 +1669,8 @@ out: } -static int wl1271_configure_suspend_ap(struct wl1271 *wl) +static int wl1271_configure_suspend_ap(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { int ret = 0; @@ -1677,7 +1683,7 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl) if (ret < 0) goto out_unlock; - ret = wl1271_acx_beacon_filter_opt(wl, true); + ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); wl1271_ps_elp_sleep(wl); out_unlock: @@ -1692,7 +1698,7 @@ static int wl1271_configure_suspend(struct wl1271 *wl, if (wlvif->bss_type == BSS_TYPE_STA_BSS) return wl1271_configure_suspend_sta(wl, wlvif); if (wlvif->bss_type == BSS_TYPE_AP_BSS) - return wl1271_configure_suspend_ap(wl); + return wl1271_configure_suspend_ap(wl, wlvif); return 0; } @@ -1714,10 +1720,10 @@ static void wl1271_configure_resume(struct wl1271 *wl, if (is_sta) { /* exit psm if it wasn't configured */ if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) - wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, + wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, wlvif->basic_rate, true); } else if (is_ap) { - wl1271_acx_beacon_filter_opt(wl, false); + wl1271_acx_beacon_filter_opt(wl, wlvif, false); } wl1271_ps_elp_sleep(wl); @@ -1850,6 +1856,7 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) static void wl12xx_init_vif_data(struct wl12xx_vif *wlvif) { wlvif->bss_type = MAX_BSS_TYPE; + wlvif->role_id = WL12XX_INVALID_ROLE_ID; wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; @@ -1957,7 +1964,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, } ret = wl12xx_cmd_role_enable(wl, vif->addr, - role_type, &wl->role_id); + role_type, &wlvif->role_id); if (ret < 0) goto irq_disable; @@ -2065,7 +2072,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, goto deinit; } - ret = wl12xx_cmd_role_disable(wl, &wl->role_id); + ret = wl12xx_cmd_role_disable(wl, &wlvif->role_id); if (ret < 0) goto deinit; @@ -2123,7 +2130,7 @@ deinit: wl->ap_fw_ps_map = 0; wl->ap_ps_map = 0; wl->sched_scanning = false; - wl->role_id = WL12XX_INVALID_ROLE_ID; + wlvif->role_id = WL12XX_INVALID_ROLE_ID; wl->dev_role_id = WL12XX_INVALID_ROLE_ID; memset(wl->roles_map, 0, sizeof(wl->roles_map)); memset(wl->links_map, 0, sizeof(wl->links_map)); @@ -2213,11 +2220,11 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, * the join. The acx_aid starts the keep-alive process, and the order * of the commands below is relevant. */ - ret = wl1271_acx_keep_alive_mode(wl, true); + ret = wl1271_acx_keep_alive_mode(wl, wlvif, true); if (ret < 0) goto out; - ret = wl1271_acx_aid(wl, wlvif->aid); + ret = wl1271_acx_aid(wl, wlvif, wlvif->aid); if (ret < 0) goto out; @@ -2225,7 +2232,8 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (ret < 0) goto out; - ret = wl1271_acx_keep_alive_config(wl, CMD_TEMPL_KLV_IDX_NULL_DATA, + ret = wl1271_acx_keep_alive_config(wl, wlvif, + CMD_TEMPL_KLV_IDX_NULL_DATA, ACX_KEEP_ALIVE_TPL_VALID); if (ret < 0) goto out; @@ -2234,7 +2242,7 @@ out: return ret; } -static int wl1271_unjoin(struct wl1271 *wl) +static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret; @@ -2244,7 +2252,7 @@ static int wl1271_unjoin(struct wl1271 *wl) } /* to stop listening to a channel, we disconnect */ - ret = wl12xx_cmd_role_stop_sta(wl); + ret = wl12xx_cmd_role_stop_sta(wl, wlvif); if (ret < 0) goto out; @@ -2295,7 +2303,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (ret < 0) goto out; ret = wl1271_acx_keep_alive_config( - wl, CMD_TEMPL_KLV_IDX_NULL_DATA, + wl, wlvif, CMD_TEMPL_KLV_IDX_NULL_DATA, ACX_KEEP_ALIVE_TPL_INVALID); if (ret < 0) goto out; @@ -2454,7 +2462,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) */ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { wl1271_debug(DEBUG_PSM, "psm enabled"); - ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, + ret = wl1271_ps_set_mode(wl, wlvif, + STATION_POWER_SAVE_MODE, wlvif->basic_rate, true); } } else if (!(conf->flags & IEEE80211_CONF_PS) && @@ -2464,12 +2473,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); if (test_bit(WL1271_FLAG_PSM, &wl->flags)) - ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, + ret = wl1271_ps_set_mode(wl, wlvif, + STATION_ACTIVE_MODE, wlvif->basic_rate, true); } if (conf->power_level != wl->power_level) { - ret = wl1271_acx_tx_power(wl, conf->power_level); + ret = wl1271_acx_tx_power(wl, wlvif, conf->power_level); if (ret < 0) goto out_sleep; @@ -2558,9 +2568,11 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, if (wlvif->bss_type != BSS_TYPE_AP_BSS) { if (*total & FIF_ALLMULTI) - ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); + ret = wl1271_acx_group_address_tbl(wl, wlvif, false, + NULL, 0); else if (fp) - ret = wl1271_acx_group_address_tbl(wl, fp->enabled, + ret = wl1271_acx_group_address_tbl(wl, wlvif, + fp->enabled, fp->mc_list, fp->mc_list_length); if (ret < 0) @@ -3051,6 +3063,8 @@ out: static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { struct wl1271 *wl = hw->priv; + struct ieee80211_vif *vif = wl->vif; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret = 0; mutex_lock(&wl->mutex); @@ -3064,7 +3078,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) if (ret < 0) goto out; - ret = wl1271_acx_rts_threshold(wl, value); + ret = wl1271_acx_rts_threshold(wl, wlvif, value); if (ret < 0) wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); @@ -3190,16 +3204,18 @@ static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, } static int wl1271_bss_erp_info_changed(struct wl1271 *wl, + struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changed) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret = 0; if (changed & BSS_CHANGED_ERP_SLOT) { if (bss_conf->use_short_slot) - ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT); + ret = wl1271_acx_slot(wl, wlvif, SLOT_TIME_SHORT); else - ret = wl1271_acx_slot(wl, SLOT_TIME_LONG); + ret = wl1271_acx_slot(wl, wlvif, SLOT_TIME_LONG); if (ret < 0) { wl1271_warning("Set slot time failed %d", ret); goto out; @@ -3208,16 +3224,18 @@ static int wl1271_bss_erp_info_changed(struct wl1271 *wl, if (changed & BSS_CHANGED_ERP_PREAMBLE) { if (bss_conf->use_short_preamble) - wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); + wl1271_acx_set_preamble(wl, wlvif, ACX_PREAMBLE_SHORT); else - wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG); + wl1271_acx_set_preamble(wl, wlvif, ACX_PREAMBLE_LONG); } if (changed & BSS_CHANGED_ERP_CTS_PROT) { if (bss_conf->use_cts_prot) - ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE); + ret = wl1271_acx_cts_protect(wl, wlvif, + CTSPROTECT_ENABLE); else - ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE); + ret = wl1271_acx_cts_protect(wl, wlvif, + CTSPROTECT_DISABLE); if (ret < 0) { wl1271_warning("Set ctsprotect failed %d", ret); goto out; @@ -3359,7 +3377,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, } } else { if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { - ret = wl12xx_cmd_role_stop_ap(wl); + ret = wl12xx_cmd_role_stop_ap(wl, wlvif); if (ret < 0) goto out; @@ -3369,14 +3387,14 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, } } - ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); + ret = wl1271_bss_erp_info_changed(wl, vif, bss_conf, changed); if (ret < 0) goto out; /* Handle HT information change */ if ((changed & BSS_CHANGED_HT) && (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { - ret = wl1271_acx_set_ht_information(wl, + ret = wl1271_acx_set_ht_information(wl, wlvif, bss_conf->ht_operation_mode); if (ret < 0) { wl1271_warning("Set ht information failed %d", ret); @@ -3418,7 +3436,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, } else { if (test_and_clear_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) { - wl1271_unjoin(wl); + wl1271_unjoin(wl, wlvif); wl12xx_cmd_role_start_dev(wl); wl12xx_roc(wl, wl->dev_role_id); } @@ -3443,7 +3461,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, bool enable = false; if (bss_conf->cqm_rssi_thold) enable = true; - ret = wl1271_acx_rssi_snr_trigger(wl, enable, + ret = wl1271_acx_rssi_snr_trigger(wl, wlvif, enable, bss_conf->cqm_rssi_thold, bss_conf->cqm_rssi_hyst); if (ret < 0) @@ -3533,7 +3551,7 @@ sta_not_found: wl1271_ssid_set(vif, wlvif->probereq, ieoffset); /* enable the connection monitoring feature */ - ret = wl1271_acx_conn_monit_params(wl, true); + ret = wl1271_acx_conn_monit_params(wl, wlvif, true); if (ret < 0) goto out; } else { @@ -3563,10 +3581,10 @@ sta_not_found: goto out; /* disable connection monitor features */ - ret = wl1271_acx_conn_monit_params(wl, false); + ret = wl1271_acx_conn_monit_params(wl, wlvif, false); /* Disable the keep-alive feature */ - ret = wl1271_acx_keep_alive_mode(wl, false); + ret = wl1271_acx_keep_alive_mode(wl, wlvif, false); if (ret < 0) goto out; @@ -3578,7 +3596,7 @@ sta_not_found: * no IF_OPER_UP notification. */ if (!was_ifup) { - ret = wl12xx_croc(wl, wl->role_id); + ret = wl12xx_croc(wl, wlvif->role_id); if (ret < 0) goto out; } @@ -3593,7 +3611,7 @@ sta_not_found: goto out; } - wl1271_unjoin(wl); + wl1271_unjoin(wl, wlvif); if (!(conf_flags & IEEE80211_CONF_IDLE)) { wl12xx_cmd_role_start_dev(wl); wl12xx_roc(wl, wl->dev_role_id); @@ -3623,7 +3641,7 @@ sta_not_found: } } - ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); + ret = wl1271_bss_erp_info_changed(wl, vif, bss_conf, changed); if (ret < 0) goto out; @@ -3645,11 +3663,11 @@ sta_not_found: goto out; } - ret = wl1271_acx_arp_ip_filter(wl, + ret = wl1271_acx_arp_ip_filter(wl, wlvif, ACX_ARP_FILTER_ARP_FILTERING, addr); } else - ret = wl1271_acx_arp_ip_filter(wl, 0, addr); + ret = wl1271_acx_arp_ip_filter(wl, wlvif, 0, addr); if (ret < 0) goto out; @@ -3664,7 +3682,7 @@ sta_not_found: /* ROC until connected (after EAPOL exchange) */ if (!is_ibss) { - ret = wl12xx_roc(wl, wl->role_id); + ret = wl12xx_roc(wl, wlvif->role_id); if (ret < 0) goto out; @@ -3691,7 +3709,7 @@ sta_not_found: enum wl1271_cmd_ps_mode mode; mode = STATION_POWER_SAVE_MODE; - ret = wl1271_ps_set_mode(wl, mode, + ret = wl1271_ps_set_mode(wl, wlvif, mode, wlvif->basic_rate, true); if (ret < 0) @@ -3730,7 +3748,7 @@ sta_not_found: /* Handle HT information change. Done after join. */ if ((changed & BSS_CHANGED_HT) && (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { - ret = wl1271_acx_set_ht_information(wl, + ret = wl1271_acx_set_ht_information(wl, wlvif, bss_conf->ht_operation_mode); if (ret < 0) { wl1271_warning("Set ht information failed %d", ret); @@ -3780,6 +3798,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, const struct ieee80211_tx_queue_params *params) { struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); u8 ps_scheme; int ret = 0; @@ -3826,13 +3845,13 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, * the txop is confed in units of 32us by the mac80211, * we need us */ - ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), + ret = wl1271_acx_ac_cfg(wl, wlvif, wl1271_tx_get_queue(queue), params->cw_min, params->cw_max, params->aifs, params->txop << 5); if (ret < 0) goto out_sleep; - ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), + ret = wl1271_acx_tid_cfg(wl, wlvif, wl1271_tx_get_queue(queue), CONF_CHANNEL_TYPE_EDCF, wl1271_tx_get_queue(queue), ps_scheme, CONF_ACK_POLICY_LEGACY, @@ -4861,7 +4880,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->tx_security_seq = 0; wl->tx_security_last_seq_lsb = 0; wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; - wl->role_id = WL12XX_INVALID_ROLE_ID; wl->system_hlid = WL12XX_SYSTEM_HLID; wl->sta_hlid = WL12XX_INVALID_LINK_ID; wl->dev_role_id = WL12XX_INVALID_ROLE_ID; diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index c15ebf2efd40..ac3f20716f5b 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -143,8 +143,8 @@ out: return 0; } -int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, - u32 rates, bool send) +int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, + enum wl1271_cmd_ps_mode mode, u32 rates, bool send) { int ret; @@ -152,13 +152,13 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, case STATION_POWER_SAVE_MODE: wl1271_debug(DEBUG_PSM, "entering psm"); - ret = wl1271_acx_wake_up_conditions(wl); + ret = wl1271_acx_wake_up_conditions(wl, wlvif); if (ret < 0) { wl1271_error("couldn't set wake up conditions"); return ret; } - ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); + ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_POWER_SAVE_MODE); if (ret < 0) return ret; @@ -170,17 +170,17 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, /* disable beacon early termination */ if (wl->band == IEEE80211_BAND_2GHZ) { - ret = wl1271_acx_bet_enable(wl, false); + ret = wl1271_acx_bet_enable(wl, wlvif, false); if (ret < 0) return ret; } /* disable beacon filtering */ - ret = wl1271_acx_beacon_filter_opt(wl, false); + ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); if (ret < 0) return ret; - ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE); + ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_ACTIVE_MODE); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/ps.h index 25eb9bc9b628..6ad0a0bd29bd 100644 --- a/drivers/net/wireless/wl12xx/ps.h +++ b/drivers/net/wireless/wl12xx/ps.h @@ -27,8 +27,8 @@ #include "wl12xx.h" #include "acx.h" -int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, - u32 rates, bool send); +int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, + enum wl1271_cmd_ps_mode mode, u32 rates, bool send); void wl1271_ps_elp_sleep(struct wl1271 *wl); int wl1271_ps_elp_wakeup(struct wl1271 *wl); void wl1271_elp_work(struct work_struct *work); diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index e3b863b895f3..9d0dfb516e26 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -163,6 +163,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, enum ieee80211_band band, bool passive, u32 basic_rate) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271_cmd_scan *cmd; struct wl1271_cmd_trigger_scan_to *trigger; int ret; @@ -182,11 +183,11 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, if (passive) scan_options |= WL1271_SCAN_OPT_PASSIVE; - if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) { + if (WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID)) { ret = -EINVAL; goto out; } - cmd->params.role_id = wl->role_id; + cmd->params.role_id = wlvif->role_id; cmd->params.scan_options = cpu_to_le16(scan_options); cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index e6d3c214acf9..e249b459f62b 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -401,7 +401,6 @@ struct wl1271 { u8 mac_addr[ETH_ALEN]; int channel; - u8 role_id; u8 dev_role_id; u8 system_hlid; u8 sta_hlid; @@ -621,6 +620,7 @@ struct wl1271_station { struct wl12xx_vif { u8 bss_type; u8 p2p; /* we are using p2p role */ + u8 role_id; u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 ssid_len; From 7edebf56ca424484b9e0e51a6188c93c7fdd3a41 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:52 +0200 Subject: [PATCH 14/97] wl12xx: move dev_role_id into wlvif move dev_role_id into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 10 +++--- drivers/net/wireless/wl12xx/cmd.h | 4 +-- drivers/net/wireless/wl12xx/main.c | 50 ++++++++++++++++------------ drivers/net/wireless/wl12xx/scan.c | 10 +++--- drivers/net/wireless/wl12xx/tx.c | 9 ++--- drivers/net/wireless/wl12xx/wl12xx.h | 4 ++- 6 files changed, 49 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 918faca517cf..36544ff6a79b 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -464,7 +464,7 @@ static int wl12xx_get_new_session_id(struct wl1271 *wl) return wl->session_counter; } -int wl12xx_cmd_role_start_dev(struct wl1271 *wl) +int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_start *cmd; int ret; @@ -475,9 +475,9 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl) goto out; } - wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wl->dev_role_id); + wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wlvif->dev_role_id); - cmd->role_id = wl->dev_role_id; + cmd->role_id = wlvif->dev_role_id; if (wl->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; @@ -514,7 +514,7 @@ out: return ret; } -int wl12xx_cmd_role_stop_dev(struct wl1271 *wl) +int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_stop *cmd; int ret; @@ -530,7 +530,7 @@ int wl12xx_cmd_role_stop_dev(struct wl1271 *wl) wl1271_debug(DEBUG_CMD, "cmd role stop dev"); - cmd->role_id = wl->dev_role_id; + cmd->role_id = wlvif->dev_role_id; cmd->disc_type = DISCONNECT_IMMEDIATE; cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index bf2c45b8b911..fb40556a8ad1 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -39,8 +39,8 @@ int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, u8 *role_id); int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); -int wl12xx_cmd_role_start_dev(struct wl1271 *wl); -int wl12xx_cmd_role_stop_dev(struct wl1271 *wl); +int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); +int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index b3d4ef5b900d..f4d3df15719b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1857,6 +1857,7 @@ static void wl12xx_init_vif_data(struct wl12xx_vif *wlvif) { wlvif->bss_type = MAX_BSS_TYPE; wlvif->role_id = WL12XX_INVALID_ROLE_ID; + wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; @@ -1958,7 +1959,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, */ ret = wl12xx_cmd_role_enable(wl, vif->addr, WL1271_ROLE_DEVICE, - &wl->dev_role_id); + &wlvif->dev_role_id); if (ret < 0) goto irq_disable; } @@ -2067,7 +2068,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, goto deinit; if (wlvif->bss_type == BSS_TYPE_STA_BSS) { - ret = wl12xx_cmd_role_disable(wl, &wl->dev_role_id); + ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); if (ret < 0) goto deinit; } @@ -2131,7 +2132,7 @@ deinit: wl->ap_ps_map = 0; wl->sched_scanning = false; wlvif->role_id = WL12XX_INVALID_ROLE_ID; - wl->dev_role_id = WL12XX_INVALID_ROLE_ID; + wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; memset(wl->roles_map, 0, sizeof(wl->roles_map)); memset(wl->links_map, 0, sizeof(wl->links_map)); memset(wl->roc_map, 0, sizeof(wl->roc_map)); @@ -2289,11 +2290,11 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (idle) { /* no need to croc if we weren't busy (e.g. during boot) */ if (wl12xx_is_roc(wl)) { - ret = wl12xx_croc(wl, wl->dev_role_id); + ret = wl12xx_croc(wl, wlvif->dev_role_id); if (ret < 0) goto out; - ret = wl12xx_cmd_role_stop_dev(wl); + ret = wl12xx_cmd_role_stop_dev(wl, wlvif); if (ret < 0) goto out; } @@ -2315,11 +2316,11 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, ieee80211_sched_scan_stopped(wl->hw); } - ret = wl12xx_cmd_role_start_dev(wl); + ret = wl12xx_cmd_role_start_dev(wl, wlvif); if (ret < 0) goto out; - ret = wl12xx_roc(wl, wl->dev_role_id); + ret = wl12xx_roc(wl, wlvif->dev_role_id); if (ret < 0) goto out; clear_bit(WL1271_FLAG_IDLE, &wl->flags); @@ -2408,7 +2409,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { if (wl12xx_is_roc(wl)) { /* roaming */ - ret = wl12xx_croc(wl, wl->dev_role_id); + ret = wl12xx_croc(wl, + wlvif->dev_role_id); if (ret < 0) goto out_sleep; } @@ -2424,11 +2426,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) */ if (wl12xx_is_roc(wl) && !(conf->flags & IEEE80211_CONF_IDLE)) { - ret = wl12xx_croc(wl, wl->dev_role_id); + ret = wl12xx_croc(wl, + wlvif->dev_role_id); if (ret < 0) goto out_sleep; - ret = wl12xx_roc(wl, wl->dev_role_id); + ret = wl12xx_roc(wl, + wlvif->dev_role_id); if (ret < 0) wl1271_warning("roc failed %d", ret); @@ -2891,6 +2895,8 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req) { struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + int ret; u8 *ssid = NULL; size_t len = 0; @@ -2925,8 +2931,8 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, ret = -EBUSY; goto out_sleep; } - wl12xx_croc(wl, wl->dev_role_id); - wl12xx_cmd_role_stop_dev(wl); + wl12xx_croc(wl, wlvif->dev_role_id); + wl12xx_cmd_role_stop_dev(wl, wlvif); } ret = wl1271_scan(hw->priv, vif, ssid, len, req); @@ -3437,8 +3443,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (test_and_clear_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) { wl1271_unjoin(wl, wlvif); - wl12xx_cmd_role_start_dev(wl); - wl12xx_roc(wl, wl->dev_role_id); + wl12xx_cmd_role_start_dev(wl, wlvif); + wl12xx_roc(wl, wlvif->dev_role_id); } } } @@ -3605,16 +3611,17 @@ sta_not_found: * roaming on the same channel. until we will * have a better flow...) */ - if (test_bit(wl->dev_role_id, wl->roc_map)) { - ret = wl12xx_croc(wl, wl->dev_role_id); + if (test_bit(wlvif->dev_role_id, wl->roc_map)) { + ret = wl12xx_croc(wl, + wlvif->dev_role_id); if (ret < 0) goto out; } wl1271_unjoin(wl, wlvif); if (!(conf_flags & IEEE80211_CONF_IDLE)) { - wl12xx_cmd_role_start_dev(wl); - wl12xx_roc(wl, wl->dev_role_id); + wl12xx_cmd_role_start_dev(wl, wlvif); + wl12xx_roc(wl, wlvif->dev_role_id); } } } @@ -3693,12 +3700,12 @@ sta_not_found: * stop device role if started (we might already be in * STA role). TODO: make it better. */ - if (wl->dev_role_id != WL12XX_INVALID_ROLE_ID) { - ret = wl12xx_croc(wl, wl->dev_role_id); + if (wlvif->dev_role_id != WL12XX_INVALID_ROLE_ID) { + ret = wl12xx_croc(wl, wlvif->dev_role_id); if (ret < 0) goto out; - ret = wl12xx_cmd_role_stop_dev(wl); + ret = wl12xx_cmd_role_stop_dev(wl, wlvif); if (ret < 0) goto out; } @@ -4882,7 +4889,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl->system_hlid = WL12XX_SYSTEM_HLID; wl->sta_hlid = WL12XX_INVALID_LINK_ID; - wl->dev_role_id = WL12XX_INVALID_ROLE_ID; wl->dev_hlid = WL12XX_INVALID_LINK_ID; wl->session_counter = 0; wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 9d0dfb516e26..9372136b27e4 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -34,6 +34,7 @@ void wl1271_scan_complete_work(struct work_struct *work) { struct delayed_work *dwork; struct wl1271 *wl; + struct ieee80211_vif *vif; struct wl12xx_vif *wlvif; int ret; bool is_sta, is_ibss; @@ -51,7 +52,8 @@ void wl1271_scan_complete_work(struct work_struct *work) if (wl->scan.state == WL1271_SCAN_STATE_IDLE) goto out; - wlvif = wl12xx_vif_to_data(wl->scan_vif); + vif = wl->scan_vif; + wlvif = wl12xx_vif_to_data(vif); wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); @@ -72,10 +74,10 @@ void wl1271_scan_complete_work(struct work_struct *work) is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) || (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) && - !test_bit(wl->dev_role_id, wl->roc_map)) { + !test_bit(wlvif->dev_role_id, wl->roc_map)) { /* restore remain on channel */ - wl12xx_cmd_role_start_dev(wl); - wl12xx_roc(wl, wl->dev_role_id); + wl12xx_cmd_role_start_dev(wl, wlvif); + wl12xx_roc(wl, wlvif->dev_role_id); } wl1271_ps_elp_sleep(wl); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 5561ec2d4b4f..538d8613b324 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -77,7 +77,8 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id) } static int wl1271_tx_update_filters(struct wl1271 *wl, - struct sk_buff *skb) + struct wl12xx_vif *wlvif, + struct sk_buff *skb) { struct ieee80211_hdr *hdr; int ret; @@ -97,11 +98,11 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, goto out; wl1271_debug(DEBUG_CMD, "starting device role for roaming"); - ret = wl12xx_cmd_role_start_dev(wl); + ret = wl12xx_cmd_role_start_dev(wl, wlvif); if (ret < 0) goto out; - ret = wl12xx_roc(wl, wl->dev_role_id); + ret = wl12xx_roc(wl, wlvif->dev_role_id); if (ret < 0) goto out; out: @@ -192,7 +193,7 @@ static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct ieee80211_vif *vif, if (wlvif->bss_type == BSS_TYPE_AP_BSS) return wl12xx_tx_get_hlid_ap(wl, skb); - wl1271_tx_update_filters(wl, skb); + wl1271_tx_update_filters(wl, wlvif, skb); if ((test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) && diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index e249b459f62b..4c69ae1635fe 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -401,7 +401,6 @@ struct wl1271 { u8 mac_addr[ETH_ALEN]; int channel; - u8 dev_role_id; u8 system_hlid; u8 sta_hlid; u8 dev_hlid; @@ -622,6 +621,9 @@ struct wl12xx_vif { u8 p2p; /* we are using p2p role */ u8 role_id; + /* sta/ibss specific */ + u8 dev_role_id; + u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 ssid_len; From 154da67c7da14ffd8da292394f8cbc81cc5ea4e3 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:53 +0200 Subject: [PATCH 15/97] wl12xx: move sta_hlid into wlvif move sta_hlid into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 28 +++++++++++++++------------- drivers/net/wireless/wl12xx/cmd.h | 3 ++- drivers/net/wireless/wl12xx/main.c | 18 +++++++++--------- drivers/net/wireless/wl12xx/tx.c | 4 ++-- drivers/net/wireless/wl12xx/wl12xx.h | 7 ++++++- 5 files changed, 34 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 36544ff6a79b..2a9a4b2032e5 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -581,12 +581,12 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN); cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); - if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, &wl->sta_hlid); + if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, &wlvif->sta.hlid); if (ret) goto out_free; } - cmd->sta.hlid = wl->sta_hlid; + cmd->sta.hlid = wlvif->sta.hlid; cmd->sta.session = wl12xx_get_new_session_id(wl); cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set); @@ -605,7 +605,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) err_hlid: /* clear links on error. */ - wl12xx_free_link(wl, &wl->sta_hlid); + wl12xx_free_link(wl, &wlvif->sta.hlid); out_free: kfree(cmd); @@ -620,7 +620,7 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) struct wl12xx_cmd_role_stop *cmd; int ret; - if (WARN_ON(wl->sta_hlid == WL12XX_INVALID_LINK_ID)) + if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID)) return -EINVAL; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -641,7 +641,7 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; } - wl12xx_free_link(wl, &wl->sta_hlid); + wl12xx_free_link(wl, &wlvif->sta.hlid); out_free: kfree(cmd); @@ -796,12 +796,12 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) memcpy(cmd->ibss.bssid, vif->bss_conf.bssid, ETH_ALEN); cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); - if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, &wl->sta_hlid); + if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, &wlvif->sta.hlid); if (ret) goto out_free; } - cmd->ibss.hlid = wl->sta_hlid; + cmd->ibss.hlid = wlvif->sta.hlid; cmd->ibss.remote_rates = cpu_to_le32(wlvif->rate_set); wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " @@ -822,7 +822,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) err_hlid: /* clear links on error. */ - wl12xx_free_link(wl, &wl->sta_hlid); + wl12xx_free_link(wl, &wlvif->sta.hlid); out_free: kfree(cmd); @@ -1264,15 +1264,17 @@ out: return ret; } -int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, +int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct ieee80211_vif *vif, + u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, u32 tx_seq_32, u16 tx_seq_16) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271_cmd_set_keys *cmd; int ret = 0; /* hlid might have already been deleted */ - if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) + if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) return 0; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -1281,7 +1283,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, goto out; } - cmd->hlid = wl->sta_hlid; + cmd->hlid = wlvif->sta.hlid; if (key_type == KEY_WEP) cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index fb40556a8ad1..25ab400f2ebd 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -70,7 +70,8 @@ int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif); int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid); -int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, +int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct ieee80211_vif *vif, + u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, u32 tx_seq_32, u16 tx_seq_16); int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index f4d3df15719b..3358cfe5b019 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -412,7 +412,7 @@ static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate) if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) return 0; - ret = wl12xx_cmd_set_peer_state(wl, wl->sta_hlid); + ret = wl12xx_cmd_set_peer_state(wl, wlvif->sta.hlid); if (ret < 0) return ret; @@ -1858,6 +1858,7 @@ static void wl12xx_init_vif_data(struct wl12xx_vif *wlvif) wlvif->bss_type = MAX_BSS_TYPE; wlvif->role_id = WL12XX_INVALID_ROLE_ID; wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; + wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; @@ -2081,7 +2082,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, } deinit: /* clear all hlids (except system_hlid) */ - wl->sta_hlid = WL12XX_INVALID_LINK_ID; + wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; wl->dev_hlid = WL12XX_INVALID_LINK_ID; wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; @@ -2765,10 +2766,10 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, /* don't remove key if hlid was already deleted */ if (action == KEY_REMOVE && - wl->sta_hlid == WL12XX_INVALID_LINK_ID) + wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) return 0; - ret = wl1271_cmd_set_sta_key(wl, action, + ret = wl1271_cmd_set_sta_key(wl, vif, action, id, key_type, key_size, key, addr, tx_seq_32, tx_seq_16); @@ -2779,7 +2780,7 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (key_type == KEY_WEP) { ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key, - wl->sta_hlid); + wlvif->sta.hlid); if (ret < 0) return ret; } @@ -3731,7 +3732,7 @@ sta_not_found: ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, true, - wl->sta_hlid); + wlvif->sta.hlid); if (ret < 0) { wl1271_warning("Set ht cap true failed %d", ret); @@ -3743,7 +3744,7 @@ sta_not_found: ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, false, - wl->sta_hlid); + wlvif->sta.hlid); if (ret < 0) { wl1271_warning("Set ht cap false failed %d", ret); @@ -4080,7 +4081,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, } if (wlvif->bss_type == BSS_TYPE_STA_BSS) { - hlid = wl->sta_hlid; + hlid = wlvif->sta.hlid; ba_bitmap = &wl->ba_rx_bitmap; } else if (wlvif->bss_type == BSS_TYPE_AP_BSS) { struct wl1271_station *wl_sta; @@ -4888,7 +4889,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->tx_security_last_seq_lsb = 0; wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl->system_hlid = WL12XX_SYSTEM_HLID; - wl->sta_hlid = WL12XX_INVALID_LINK_ID; wl->dev_hlid = WL12XX_INVALID_LINK_ID; wl->session_counter = 0; wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 538d8613b324..db55767d7d54 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -42,7 +42,7 @@ static int wl1271_set_default_wep_key(struct wl1271 *wl, ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->ap_bcast_hlid); else - ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->sta_hlid); + ret = wl12xx_cmd_set_default_wep_key(wl, id, wlvif->sta.hlid); if (ret < 0) return ret; @@ -199,7 +199,7 @@ static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct ieee80211_vif *vif, test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) && !ieee80211_is_auth(hdr->frame_control) && !ieee80211_is_assoc_req(hdr->frame_control)) - return wl->sta_hlid; + return wlvif->sta.hlid; else return wl->dev_hlid; } diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 4c69ae1635fe..a1084d1466bb 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -402,7 +402,6 @@ struct wl1271 { u8 mac_addr[ETH_ALEN]; int channel; u8 system_hlid; - u8 sta_hlid; u8 dev_hlid; u8 ap_global_hlid; u8 ap_bcast_hlid; @@ -624,6 +623,12 @@ struct wl12xx_vif { /* sta/ibss specific */ u8 dev_role_id; + union { + struct { + u8 hlid; + } sta; + }; + u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 ssid_len; From a8ab39a4b588e8523be2fa75671bdc9612d3467a Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:54 +0200 Subject: [PATCH 16/97] wl12xx: move ap_global_hlid and ap_bcast_hlid into wlvif move ap_global_hlid and ap_bcast_hlid into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 28 +++++++++++------------ drivers/net/wireless/wl12xx/cmd.h | 5 ++-- drivers/net/wireless/wl12xx/main.c | 34 ++++++++++++++++------------ drivers/net/wireless/wl12xx/tx.c | 15 ++++++------ drivers/net/wireless/wl12xx/tx.h | 3 ++- drivers/net/wireless/wl12xx/wl12xx.h | 6 +++-- 6 files changed, 50 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 2a9a4b2032e5..d0124e63dad1 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -671,19 +671,19 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; } - ret = wl12xx_allocate_link(wl, &wl->ap_global_hlid); + ret = wl12xx_allocate_link(wl, &wlvif->ap.global_hlid); if (ret < 0) goto out_free; - ret = wl12xx_allocate_link(wl, &wl->ap_bcast_hlid); + ret = wl12xx_allocate_link(wl, &wlvif->ap.bcast_hlid); if (ret < 0) goto out_free_global; cmd->role_id = wlvif->role_id; cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); cmd->ap.bss_index = WL1271_AP_BSS_INDEX; - cmd->ap.global_hlid = wl->ap_global_hlid; - cmd->ap.broadcast_hlid = wl->ap_bcast_hlid; + cmd->ap.global_hlid = wlvif->ap.global_hlid; + cmd->ap.broadcast_hlid = wlvif->ap.bcast_hlid; cmd->ap.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int); cmd->ap.dtim_interval = bss_conf->dtim_period; @@ -725,10 +725,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; out_free_bcast: - wl12xx_free_link(wl, &wl->ap_bcast_hlid); + wl12xx_free_link(wl, &wlvif->ap.bcast_hlid); out_free_global: - wl12xx_free_link(wl, &wl->ap_global_hlid); + wl12xx_free_link(wl, &wlvif->ap.global_hlid); out_free: kfree(cmd); @@ -758,8 +758,8 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; } - wl12xx_free_link(wl, &wl->ap_bcast_hlid); - wl12xx_free_link(wl, &wl->ap_global_hlid); + wl12xx_free_link(wl, &wlvif->ap.bcast_hlid); + wl12xx_free_link(wl, &wlvif->ap.global_hlid); out_free: kfree(cmd); @@ -1264,12 +1264,11 @@ out: return ret; } -int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct ieee80211_vif *vif, +int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, u32 tx_seq_32, u16 tx_seq_16) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271_cmd_set_keys *cmd; int ret = 0; @@ -1334,9 +1333,10 @@ out: * TODO: merge with sta/ibss into 1 set_key function. * note there are slight diffs */ -int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, - u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, - u16 tx_seq_16) +int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u16 action, u8 id, u8 key_type, + u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, + u16 tx_seq_16) { struct wl1271_cmd_set_keys *cmd; int ret = 0; @@ -1346,7 +1346,7 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, if (!cmd) return -ENOMEM; - if (hlid == wl->ap_bcast_hlid) { + if (hlid == wlvif->ap.bcast_hlid) { if (key_type == KEY_WEP) lid_type = WEP_DEFAULT_LID_TYPE; else diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 25ab400f2ebd..9624828b76e8 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -70,11 +70,12 @@ int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif); int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid); -int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct ieee80211_vif *vif, +int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, u32 tx_seq_32, u16 tx_seq_16); -int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, +int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u16 tx_seq_16); int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 3358cfe5b019..731e34bc275a 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1488,8 +1488,9 @@ int wl1271_plt_stop(struct wl1271 *wl) static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct wl1271 *wl = hw->priv; - struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb); - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(control->control.vif); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); unsigned long flags; int q, mapping; u8 hlid = 0; @@ -1498,7 +1499,7 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) q = wl1271_tx_get_queue(mapping); if (wlvif->bss_type == BSS_TYPE_AP_BSS) - hlid = wl12xx_tx_get_hlid_ap(wl, skb); + hlid = wl12xx_tx_get_hlid_ap(wl, wlvif, skb); spin_lock_irqsave(&wl->wl_lock, flags); @@ -1858,7 +1859,12 @@ static void wl12xx_init_vif_data(struct wl12xx_vif *wlvif) wlvif->bss_type = MAX_BSS_TYPE; wlvif->role_id = WL12XX_INVALID_ROLE_ID; wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; + + /* TODO: init union by type */ wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; + wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; + wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; + wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; @@ -2084,8 +2090,8 @@ deinit: /* clear all hlids (except system_hlid) */ wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; wl->dev_hlid = WL12XX_INVALID_LINK_ID; - wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; - wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; + wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; + wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; /* * this must be before the cancel_work calls below, so that the work @@ -2653,7 +2659,7 @@ static void wl1271_free_ap_keys(struct wl1271 *wl) } } -static int wl1271_ap_init_hwenc(struct wl1271 *wl) +static int wl1271_ap_init_hwenc(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int i, ret = 0; struct wl1271_ap_key *key; @@ -2667,9 +2673,9 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl) key = wl->recorded_ap_keys[i]; hlid = key->hlid; if (hlid == WL12XX_INVALID_LINK_ID) - hlid = wl->ap_bcast_hlid; + hlid = wlvif->ap.bcast_hlid; - ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE, + ret = wl1271_cmd_set_ap_key(wl, wlvif, KEY_ADD_OR_REPLACE, key->id, key->key_type, key->key_size, key->key, hlid, key->tx_seq_32, @@ -2683,7 +2689,7 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl) if (wep_key_added) { ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key, - wl->ap_bcast_hlid); + wlvif->ap.bcast_hlid); if (ret < 0) goto out; } @@ -2709,7 +2715,7 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl_sta = (struct wl1271_station *)sta->drv_priv; hlid = wl_sta->hlid; } else { - hlid = wl->ap_bcast_hlid; + hlid = wlvif->ap.bcast_hlid; } if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { @@ -2725,7 +2731,7 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, key, hlid, tx_seq_32, tx_seq_16); } else { - ret = wl1271_cmd_set_ap_key(wl, action, + ret = wl1271_cmd_set_ap_key(wl, wlvif, action, id, key_type, key_size, key, hlid, tx_seq_32, tx_seq_16); @@ -2769,7 +2775,7 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) return 0; - ret = wl1271_cmd_set_sta_key(wl, vif, action, + ret = wl1271_cmd_set_sta_key(wl, wlvif, action, id, key_type, key_size, key, addr, tx_seq_32, tx_seq_16); @@ -3375,7 +3381,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, if (ret < 0) goto out; - ret = wl1271_ap_init_hwenc(wl); + ret = wl1271_ap_init_hwenc(wl, wlvif); if (ret < 0) goto out; @@ -4891,8 +4897,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->system_hlid = WL12XX_SYSTEM_HLID; wl->dev_hlid = WL12XX_INVALID_LINK_ID; wl->session_counter = 0; - wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; - wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; wl->active_sta_count = 0; setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, (unsigned long) wl); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index db55767d7d54..53c6451a8fde 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -40,7 +40,7 @@ static int wl1271_set_default_wep_key(struct wl1271 *wl, if (is_ap) ret = wl12xx_cmd_set_default_wep_key(wl, id, - wl->ap_bcast_hlid); + wlvif->ap.bcast_hlid); else ret = wl12xx_cmd_set_default_wep_key(wl, id, wlvif->sta.hlid); @@ -156,7 +156,8 @@ bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) return wl->dummy_packet == skb; } -u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb) +u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, + struct sk_buff *skb) { struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb); @@ -174,9 +175,9 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb) hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_mgmt(hdr->frame_control)) - return wl->ap_global_hlid; + return wlvif->ap.global_hlid; else - return wl->ap_bcast_hlid; + return wlvif->ap.bcast_hlid; } } @@ -191,7 +192,7 @@ static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct ieee80211_vif *vif, return wl->system_hlid; if (wlvif->bss_type == BSS_TYPE_AP_BSS) - return wl12xx_tx_get_hlid_ap(wl, skb); + return wl12xx_tx_get_hlid_ap(wl, wlvif, skb); wl1271_tx_update_filters(wl, wlvif, skb); @@ -341,9 +342,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif, else rate_idx = ACX_TX_BASIC_RATE; } else { - if (hlid == wl->ap_global_hlid) + if (hlid == wlvif->ap.global_hlid) rate_idx = ACX_TX_AP_MODE_MGMT_RATE; - else if (hlid == wl->ap_bcast_hlid) + else if (hlid == wlvif->ap.bcast_hlid) rate_idx = ACX_TX_AP_MODE_BCST_RATE; else rate_idx = ac; diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index ba9403a45404..0964c9335316 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -212,7 +212,8 @@ u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, enum ieee80211_band rate_band); u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set); -u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb); +u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, + struct sk_buff *skb); void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); void wl1271_handle_tx_low_watermark(struct wl1271 *wl); bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index a1084d1466bb..aa84899466a8 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -403,8 +403,6 @@ struct wl1271 { int channel; u8 system_hlid; u8 dev_hlid; - u8 ap_global_hlid; - u8 ap_bcast_hlid; unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; @@ -627,6 +625,10 @@ struct wl12xx_vif { struct { u8 hlid; } sta; + struct { + u8 global_hlid; + u8 bcast_hlid; + } ap; }; u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; From 98b8625301e55bd3e4340f704edc378e4707e577 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:55 +0200 Subject: [PATCH 17/97] wl12xx: move session_counter into wlvif move session_counter into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 15 ++++++++------- drivers/net/wireless/wl12xx/debugfs.c | 1 - drivers/net/wireless/wl12xx/main.c | 2 -- drivers/net/wireless/wl12xx/tx.c | 6 +++--- drivers/net/wireless/wl12xx/wl12xx.h | 9 +++++---- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index d0124e63dad1..89d263e7b569 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -454,14 +454,15 @@ static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid) *hlid = WL12XX_INVALID_LINK_ID; } -static int wl12xx_get_new_session_id(struct wl1271 *wl) +static int wl12xx_get_new_session_id(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { - if (wl->session_counter >= SESSION_COUNTER_MAX) - wl->session_counter = 0; + if (wlvif->session_counter >= SESSION_COUNTER_MAX) + wlvif->session_counter = 0; - wl->session_counter++; + wlvif->session_counter++; - return wl->session_counter; + return wlvif->session_counter; } int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) @@ -488,7 +489,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; } cmd->device.hlid = wl->dev_hlid; - cmd->device.session = wl->session_counter; + cmd->device.session = wlvif->session_counter; wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d", cmd->role_id, cmd->device.hlid, cmd->device.session); @@ -587,7 +588,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; } cmd->sta.hlid = wlvif->sta.hlid; - cmd->sta.session = wl12xx_get_new_session_id(wl); + cmd->sta.session = wl12xx_get_new_session_id(wl, wlvif); cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set); wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 3309fea2e90e..d8d856823651 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -348,7 +348,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(tx_blocks_freed); DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb); DRIVER_STATE_PRINT_INT(rx_counter); - DRIVER_STATE_PRINT_INT(session_counter); DRIVER_STATE_PRINT_INT(state); DRIVER_STATE_PRINT_INT(channel); DRIVER_STATE_PRINT_INT(band); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 731e34bc275a..63871b46c0c1 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2128,7 +2128,6 @@ deinit: wl->tx_results_count = 0; wl->tx_packets_count = 0; wl->time_offset = 0; - wl->session_counter = 0; wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; wl->vif = NULL; @@ -4896,7 +4895,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl->system_hlid = WL12XX_SYSTEM_HLID; wl->dev_hlid = WL12XX_INVALID_LINK_ID; - wl->session_counter = 0; wl->active_sta_count = 0; setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, (unsigned long) wl); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 53c6451a8fde..da8427f5d7a8 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -321,15 +321,15 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif, * FW expects the dummy packet to have an invalid session id - * any session id that is different than the one set in the join */ - tx_attr = ((~wl->session_counter) << + tx_attr = (SESSION_COUNTER_INVALID << TX_HW_ATTR_OFST_SESSION_COUNTER) & TX_HW_ATTR_SESSION_COUNTER; tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ; } else { /* configure the tx attributes */ - tx_attr = - wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; + tx_attr = wlvif->session_counter << + TX_HW_ATTR_OFST_SESSION_COUNTER; } desc->hlid = hlid; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index aa84899466a8..9fcaa03cd737 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -429,9 +429,6 @@ struct wl1271 { /* Time-offset between host and chipset clocks */ s64 time_offset; - /* Session counter for the chipset */ - int session_counter; - /* Frames scheduled for transmission, not handled yet */ struct sk_buff_head tx_queue[NUM_TX_QUEUES]; int tx_queue_count[NUM_TX_QUEUES]; @@ -650,6 +647,9 @@ struct wl12xx_vif { /* Our association ID */ u16 aid; + + /* Session counter for the chipset */ + int session_counter; }; static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) @@ -671,7 +671,8 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); #define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ -#define SESSION_COUNTER_MAX 7 /* maximum value for the session counter */ +#define SESSION_COUNTER_MAX 6 /* maximum value for the session counter */ +#define SESSION_COUNTER_INVALID 7 /* used with dummy_packet */ #define WL1271_DEFAULT_POWER_LEVEL 0 From e936bbe0dc235458408c060deaa43f5b8b0bd705 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:56 +0200 Subject: [PATCH 18/97] wl12xx: move some logic into wl12xx_init_vif_data Initialize the vif data according to the vif type Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 66 ++++++++++++++++++------------ 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 63871b46c0c1..effba53eb3f4 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1854,20 +1854,52 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) return WL12XX_INVALID_ROLE_TYPE; } -static void wl12xx_init_vif_data(struct wl12xx_vif *wlvif) +static int wl12xx_init_vif_data(struct ieee80211_vif *vif) { - wlvif->bss_type = MAX_BSS_TYPE; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + + /* make sure wlvif is zeroed */ + memset(wlvif, 0, sizeof(*wlvif)); + + switch (ieee80211_vif_type_p2p(vif)) { + case NL80211_IFTYPE_P2P_CLIENT: + wlvif->p2p = 1; + /* fall-through */ + case NL80211_IFTYPE_STATION: + wlvif->bss_type = BSS_TYPE_STA_BSS; + break; + case NL80211_IFTYPE_ADHOC: + wlvif->bss_type = BSS_TYPE_IBSS; + break; + case NL80211_IFTYPE_P2P_GO: + wlvif->p2p = 1; + /* fall-through */ + case NL80211_IFTYPE_AP: + wlvif->bss_type = BSS_TYPE_AP_BSS; + break; + default: + wlvif->bss_type = MAX_BSS_TYPE; + return -EOPNOTSUPP; + } + wlvif->role_id = WL12XX_INVALID_ROLE_ID; wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; - /* TODO: init union by type */ - wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; - wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; - wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; + if (wlvif->bss_type == BSS_TYPE_STA_BSS || + wlvif->bss_type == BSS_TYPE_IBSS) { + /* init sta/ibss data */ + wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; + + } else { + /* init ap data */ + wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; + wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; + } wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; + return 0; } static int wl1271_op_add_interface(struct ieee80211_hw *hw, @@ -1891,7 +1923,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, ret = -EBUSY; goto out; } - wl12xx_init_vif_data(wlvif); /* * in some very corner case HW recovery scenarios its possible to @@ -1903,26 +1934,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } - switch (ieee80211_vif_type_p2p(vif)) { - case NL80211_IFTYPE_P2P_CLIENT: - wlvif->p2p = 1; - /* fall-through */ - case NL80211_IFTYPE_STATION: - wlvif->bss_type = BSS_TYPE_STA_BSS; - break; - case NL80211_IFTYPE_ADHOC: - wlvif->bss_type = BSS_TYPE_IBSS; - break; - case NL80211_IFTYPE_P2P_GO: - wlvif->p2p = 1; - /* fall-through */ - case NL80211_IFTYPE_AP: - wlvif->bss_type = BSS_TYPE_AP_BSS; - break; - default: - ret = -EOPNOTSUPP; + ret = wl12xx_init_vif_data(vif); + if (ret < 0) goto out; - } role_type = wl12xx_get_role_type(wl, wlvif); if (role_type == WL12XX_INVALID_ROLE_TYPE) { From afaf8bdb2b08bbf493b03757243821df72b26c53 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:57 +0200 Subject: [PATCH 19/97] wl12xx: move dev_hlid into wlvif move dev_hlid into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 14 ++++++-------- drivers/net/wireless/wl12xx/main.c | 4 ++-- drivers/net/wireless/wl12xx/tx.c | 4 ++-- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 89d263e7b569..166d984cb5af 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -483,12 +483,12 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; - if (wl->dev_hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, &wl->dev_hlid); + if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, &wlvif->dev_hlid); if (ret) goto out_free; } - cmd->device.hlid = wl->dev_hlid; + cmd->device.hlid = wlvif->dev_hlid; cmd->device.session = wlvif->session_counter; wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d", @@ -504,9 +504,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) err_hlid: /* clear links on error */ - __clear_bit(wl->dev_hlid, wl->links_map); - wl->dev_hlid = WL12XX_INVALID_LINK_ID; - + wl12xx_free_link(wl, &wlvif->dev_hlid); out_free: kfree(cmd); @@ -520,7 +518,7 @@ int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) struct wl12xx_cmd_role_stop *cmd; int ret; - if (WARN_ON(wl->dev_hlid == WL12XX_INVALID_LINK_ID)) + if (WARN_ON(wlvif->dev_hlid == WL12XX_INVALID_LINK_ID)) return -EINVAL; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -547,7 +545,7 @@ int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; } - wl12xx_free_link(wl, &wl->dev_hlid); + wl12xx_free_link(wl, &wlvif->dev_hlid); out_free: kfree(cmd); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index effba53eb3f4..e8d73d70cedf 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1884,6 +1884,7 @@ static int wl12xx_init_vif_data(struct ieee80211_vif *vif) wlvif->role_id = WL12XX_INVALID_ROLE_ID; wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; + wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; if (wlvif->bss_type == BSS_TYPE_STA_BSS || wlvif->bss_type == BSS_TYPE_IBSS) { @@ -2103,7 +2104,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, deinit: /* clear all hlids (except system_hlid) */ wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; - wl->dev_hlid = WL12XX_INVALID_LINK_ID; + wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; @@ -4908,7 +4909,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->tx_security_last_seq_lsb = 0; wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl->system_hlid = WL12XX_SYSTEM_HLID; - wl->dev_hlid = WL12XX_INVALID_LINK_ID; wl->active_sta_count = 0; setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, (unsigned long) wl); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index da8427f5d7a8..8db68c649437 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -94,7 +94,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, if (!ieee80211_is_auth(hdr->frame_control)) return 0; - if (wl->dev_hlid != WL12XX_INVALID_LINK_ID) + if (wlvif->dev_hlid != WL12XX_INVALID_LINK_ID) goto out; wl1271_debug(DEBUG_CMD, "starting device role for roaming"); @@ -202,7 +202,7 @@ static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct ieee80211_vif *vif, !ieee80211_is_assoc_req(hdr->frame_control)) return wlvif->sta.hlid; else - return wl->dev_hlid; + return wlvif->dev_hlid; } static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 9fcaa03cd737..752b6b99210c 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -402,7 +402,6 @@ struct wl1271 { u8 mac_addr[ETH_ALEN]; int channel; u8 system_hlid; - u8 dev_hlid; unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; @@ -617,6 +616,7 @@ struct wl12xx_vif { /* sta/ibss specific */ u8 dev_role_id; + u8 dev_hlid; union { struct { From 6a8997964366f51c39d8efcfdc0e6319b2bd01fa Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:58 +0200 Subject: [PATCH 20/97] wl12xx: move beacon_int into wlvif move beacon_int into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 6 +++--- drivers/net/wireless/wl12xx/debugfs.c | 1 - drivers/net/wireless/wl12xx/main.c | 5 +++-- drivers/net/wireless/wl12xx/wl12xx.h | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 166d984cb5af..68375ffb4123 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -573,7 +573,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); - cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int); + cmd->sta.beacon_interval = cpu_to_le16(wlvif->beacon_int); cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; cmd->sta.ssid_len = wlvif->ssid_len; memcpy(cmd->sta.ssid, wlvif->ssid, wlvif->ssid_len); @@ -684,7 +684,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->ap.global_hlid = wlvif->ap.global_hlid; cmd->ap.broadcast_hlid = wlvif->ap.bcast_hlid; cmd->ap.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); - cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int); + cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int); cmd->ap.dtim_interval = bss_conf->dtim_period; cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; cmd->channel = wl->channel; @@ -787,7 +787,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); - cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int); + cmd->ibss.beacon_interval = cpu_to_le16(wlvif->beacon_int); cmd->ibss.dtim_interval = bss_conf->dtim_period; cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY; cmd->ibss.ssid_len = wlvif->ssid_len; diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index d8d856823651..439db1f8d277 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -351,7 +351,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(state); DRIVER_STATE_PRINT_INT(channel); DRIVER_STATE_PRINT_INT(band); - DRIVER_STATE_PRINT_INT(beacon_int); DRIVER_STATE_PRINT_INT(psm_entry_retry); DRIVER_STATE_PRINT_INT(ps_poll_failures); DRIVER_STATE_PRINT_INT(power_level); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index e8d73d70cedf..577266defe9e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1900,6 +1900,8 @@ static int wl12xx_init_vif_data(struct ieee80211_vif *vif) wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; + wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; + return 0; } @@ -3286,7 +3288,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, wl1271_debug(DEBUG_MASTER, "beacon interval updated: %d", bss_conf->beacon_int); - wl->beacon_int = bss_conf->beacon_int; + wlvif->beacon_int = bss_conf->beacon_int; } if ((changed & BSS_CHANGED_BEACON)) { @@ -4889,7 +4891,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) } wl->channel = WL1271_DEFAULT_CHANNEL; - wl->beacon_int = WL1271_DEFAULT_BEACON_INT; wl->default_key = 0; wl->rx_counter = 0; wl->psm_entry_retry = 0; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 752b6b99210c..9d4b72e96c24 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -503,9 +503,6 @@ struct wl1271 { /* The current band */ enum ieee80211_band band; - /* Beaconing interval (needed for ad-hoc) */ - u32 beacon_int; - /* Default key (for WEP) */ u32 default_key; @@ -645,6 +642,9 @@ struct wl12xx_vif { /* probe-req template for the current AP */ struct sk_buff *probereq; + /* Beaconing interval (needed for ad-hoc) */ + u32 beacon_int; + /* Our association ID */ u16 aid; From f75c753f3c77b758fa5ace90c15b2ea3b7a3d46d Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:59 +0200 Subject: [PATCH 21/97] wl12xx: move default_key into wlvif move default_key into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 7 +++---- drivers/net/wireless/wl12xx/tx.c | 4 ++-- drivers/net/wireless/wl12xx/wl12xx.h | 6 +++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 577266defe9e..09983dee4105 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2704,7 +2704,7 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl, struct wl12xx_vif *wlvif) } if (wep_key_added) { - ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key, + ret = wl12xx_cmd_set_default_wep_key(wl, wlvif->default_key, wlvif->ap.bcast_hlid); if (ret < 0) goto out; @@ -2801,8 +2801,8 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, /* the default WEP key needs to be configured at least once */ if (key_type == KEY_WEP) { ret = wl12xx_cmd_set_default_wep_key(wl, - wl->default_key, - wlvif->sta.hlid); + wlvif->default_key, + wlvif->sta.hlid); if (ret < 0) return ret; } @@ -4891,7 +4891,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) } wl->channel = WL1271_DEFAULT_CHANNEL; - wl->default_key = 0; wl->rx_counter = 0; wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 8db68c649437..509ae10f0e03 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -424,11 +424,11 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) || (cipher == WLAN_CIPHER_SUITE_WEP104); - if (unlikely(is_wep && wl->default_key != idx)) { + if (unlikely(is_wep && wlvif->default_key != idx)) { ret = wl1271_set_default_wep_key(wl, wlvif, idx); if (ret < 0) return ret; - wl->default_key = idx; + wlvif->default_key = idx; } } hlid = wl1271_tx_get_hlid(wl, vif, skb); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 9d4b72e96c24..91e6cd36bf8b 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -503,9 +503,6 @@ struct wl1271 { /* The current band */ enum ieee80211_band band; - /* Default key (for WEP) */ - u32 default_key; - /* Rx Streaming */ struct work_struct rx_streaming_enable_work; struct work_struct rx_streaming_disable_work; @@ -645,6 +642,9 @@ struct wl12xx_vif { /* Beaconing interval (needed for ad-hoc) */ u32 beacon_int; + /* Default key (for WEP) */ + u32 default_key; + /* Our association ID */ u16 aid; From 252efa4f978a2901039fffc934060fb8ccf82ac7 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:00 +0200 Subject: [PATCH 22/97] wl12xx: move pspoll_work into wlvif move pspoll_work into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 8 ++++---- drivers/net/wireless/wl12xx/main.c | 8 +++++--- drivers/net/wireless/wl12xx/wl12xx.h | 4 +++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 28a4396fb8e4..4e3474c11e05 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -38,9 +38,9 @@ void wl1271_pspoll_work(struct work_struct *work) int ret; dwork = container_of(work, struct delayed_work, work); - wl = container_of(dwork, struct wl1271, pspoll_work); - vif = wl->vif; /* TODO: move work into vif struct */ - wlvif = wl12xx_vif_to_data(vif); + wlvif = container_of(dwork, struct wl12xx_vif, pspoll_work); + vif = container_of((void *)wlvif, struct ieee80211_vif, drv_priv); + wl = wlvif->wl; wl1271_debug(DEBUG_EVENT, "pspoll work"); @@ -90,7 +90,7 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl, if (ret < 0) return; set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); - ieee80211_queue_delayed_work(wl->hw, &wl->pspoll_work, + ieee80211_queue_delayed_work(wl->hw, &wlvif->pspoll_work, msecs_to_jiffies(delay)); } diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 09983dee4105..76f466380667 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1766,7 +1766,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, wl1271_enable_interrupts(wl); flush_work(&wl->tx_work); - flush_delayed_work(&wl->pspoll_work); + flush_delayed_work(&wlvif->pspoll_work); flush_delayed_work(&wl->elp_work); return 0; @@ -1902,6 +1902,8 @@ static int wl12xx_init_vif_data(struct ieee80211_vif *vif) wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; + INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work); + return 0; } @@ -1941,6 +1943,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (ret < 0) goto out; + wlvif->wl = wl; role_type = wl12xx_get_role_type(wl, wlvif); if (role_type == WL12XX_INVALID_ROLE_TYPE) { ret = -EINVAL; @@ -2126,7 +2129,7 @@ deinit: del_timer_sync(&wl->rx_streaming_timer); cancel_work_sync(&wl->rx_streaming_enable_work); cancel_work_sync(&wl->rx_streaming_disable_work); - cancel_delayed_work_sync(&wl->pspoll_work); + cancel_delayed_work_sync(&wlvif->pspoll_work); cancel_delayed_work_sync(&wl->elp_work); mutex_lock(&wl->mutex); @@ -4874,7 +4877,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) skb_queue_head_init(&wl->deferred_tx_queue); INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); - INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); INIT_WORK(&wl->netstack_work, wl1271_netstack_work); INIT_WORK(&wl->tx_work, wl1271_tx_work); INIT_WORK(&wl->recovery_work, wl1271_recovery_work); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 91e6cd36bf8b..d6d5a7bff315 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -511,7 +511,6 @@ struct wl1271 { struct completion *elp_compl; struct completion *ps_compl; struct delayed_work elp_work; - struct delayed_work pspoll_work; /* counter for ps-poll delivery failures */ int ps_poll_failures; @@ -604,6 +603,7 @@ struct wl1271_station { }; struct wl12xx_vif { + struct wl1271 *wl; u8 bss_type; u8 p2p; /* we are using p2p role */ u8 role_id; @@ -650,6 +650,8 @@ struct wl12xx_vif { /* Session counter for the chipset */ int session_counter; + + struct delayed_work pspoll_work; }; static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) From 6ec45dc282f6983d5685758c5e8993bc2c818d3c Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:01 +0200 Subject: [PATCH 23/97] wl12xx: move ps_compl into wlvif move ps_compl into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 6 +++--- drivers/net/wireless/wl12xx/main.c | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 4e3474c11e05..7a9913a3f71c 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -149,9 +149,9 @@ static int wl1271_event_ps_report(struct wl1271 *wl, /* enable beacon early termination */ ret = wl1271_acx_bet_enable(wl, wlvif, true); - if (wl->ps_compl) { - complete(wl->ps_compl); - wl->ps_compl = NULL; + if (wlvif->ps_compl) { + complete(wlvif->ps_compl); + wlvif->ps_compl = NULL; } break; default: diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 76f466380667..cb2355354bf0 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1636,7 +1636,7 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { DECLARE_COMPLETION_ONSTACK(compl); - wl->ps_compl = &compl; + wlvif->ps_compl = &compl; ret = wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, wlvif->basic_rate, true); if (ret < 0) diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index d6d5a7bff315..7166a79e00e4 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -509,7 +509,6 @@ struct wl1271 { struct timer_list rx_streaming_timer; struct completion *elp_compl; - struct completion *ps_compl; struct delayed_work elp_work; /* counter for ps-poll delivery failures */ @@ -651,6 +650,7 @@ struct wl12xx_vif { /* Session counter for the chipset */ int session_counter; + struct completion *ps_compl; struct delayed_work pspoll_work; }; From 74ec839557878007c3f97d1bc89e09fde5d0f3fa Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:02 +0200 Subject: [PATCH 24/97] wl12xx: move ps_poll_failures and psm_entry_retry into wlvif move ps_poll_failures and psm_entry_retries into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 2 -- drivers/net/wireless/wl12xx/event.c | 14 +++++++------- drivers/net/wireless/wl12xx/main.c | 4 +--- drivers/net/wireless/wl12xx/wl12xx.h | 12 ++++++------ 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 439db1f8d277..cd390e0da51d 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -351,8 +351,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(state); DRIVER_STATE_PRINT_INT(channel); DRIVER_STATE_PRINT_INT(band); - DRIVER_STATE_PRINT_INT(psm_entry_retry); - DRIVER_STATE_PRINT_INT(ps_poll_failures); DRIVER_STATE_PRINT_INT(power_level); DRIVER_STATE_PRINT_INT(rssi_thold); DRIVER_STATE_PRINT_INT(last_rssi_event); diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 7a9913a3f71c..6c48b8c3f5bb 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -78,8 +78,8 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl, int delay = wl->conf.conn.ps_poll_recovery_period; int ret; - wl->ps_poll_failures++; - if (wl->ps_poll_failures == 1) + wlvif->ps_poll_failures++; + if (wlvif->ps_poll_failures == 1) wl1271_info("AP with dysfunctional ps-poll, " "trying to work around it."); @@ -118,23 +118,23 @@ static int wl1271_event_ps_report(struct wl1271 *wl, if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { /* remain in active mode */ - wl->psm_entry_retry = 0; + wlvif->psm_entry_retry = 0; break; } - if (wl->psm_entry_retry < total_retries) { - wl->psm_entry_retry++; + if (wlvif->psm_entry_retry < total_retries) { + wlvif->psm_entry_retry++; ret = wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, wlvif->basic_rate, true); } else { wl1271_info("No ack to nullfunc from AP."); - wl->psm_entry_retry = 0; + wlvif->psm_entry_retry = 0; *beacon_loss = true; } break; case EVENT_ENTER_POWER_SAVE_SUCCESS: - wl->psm_entry_retry = 0; + wlvif->psm_entry_retry = 0; /* enable beacon filtering */ ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index cb2355354bf0..fd2b9f21acff 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2141,7 +2141,6 @@ deinit: wl->band = IEEE80211_BAND_2GHZ; wl->rx_counter = 0; - wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; wl->tx_allocated_blocks = 0; @@ -3540,7 +3539,7 @@ sta_not_found: wlvif->aid = bss_conf->aid; set_assoc = true; - wl->ps_poll_failures = 0; + wlvif->ps_poll_failures = 0; /* * use basic rates from AP, and determine lowest rate @@ -4894,7 +4893,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->channel = WL1271_DEFAULT_CHANNEL; wl->rx_counter = 0; - wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 7166a79e00e4..9d9d3fbd14e5 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -511,12 +511,6 @@ struct wl1271 { struct completion *elp_compl; struct delayed_work elp_work; - /* counter for ps-poll delivery failures */ - int ps_poll_failures; - - /* retry counter for PSM entries */ - u8 psm_entry_retry; - /* in dBm */ int power_level; @@ -652,6 +646,12 @@ struct wl12xx_vif { struct completion *ps_compl; struct delayed_work pspoll_work; + + /* counter for ps-poll delivery failures */ + int ps_poll_failures; + + /* retry counter for PSM entries */ + u8 psm_entry_retry; }; static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) From 04324d99818d16da4f64e266b45cad2e5803b961 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:03 +0200 Subject: [PATCH 25/97] wl12xx: move rssi_thold and last_rssi_event into wlvif move rssi_thold and last_rssi_event into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 2 +- drivers/net/wireless/wl12xx/debugfs.c | 2 -- drivers/net/wireless/wl12xx/event.c | 12 +++++++----- drivers/net/wireless/wl12xx/main.c | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 9b4eef61bd01..5b70cc19e1d4 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1274,7 +1274,7 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - wl->last_rssi_event = -1; + wlvif->last_rssi_event = -1; acx->role_id = wlvif->role_id; acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing); diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index cd390e0da51d..e53f96830c2f 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -352,8 +352,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(channel); DRIVER_STATE_PRINT_INT(band); DRIVER_STATE_PRINT_INT(power_level); - DRIVER_STATE_PRINT_INT(rssi_thold); - DRIVER_STATE_PRINT_INT(last_rssi_event); DRIVER_STATE_PRINT_INT(sg_enabled); DRIVER_STATE_PRINT_INT(enable_11a); DRIVER_STATE_PRINT_INT(noise); diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 6c48b8c3f5bb..775ad952ac8f 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -162,21 +162,23 @@ static int wl1271_event_ps_report(struct wl1271 *wl, } static void wl1271_event_rssi_trigger(struct wl1271 *wl, + struct ieee80211_vif *vif, struct event_mailbox *mbox) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); enum nl80211_cqm_rssi_threshold_event event; s8 metric = mbox->rssi_snr_trigger_metric[0]; wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric); - if (metric <= wl->rssi_thold) + if (metric <= wlvif->rssi_thold) event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; else event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; - if (event != wl->last_rssi_event) - ieee80211_cqm_rssi_notify(wl->vif, event, GFP_KERNEL); - wl->last_rssi_event = event; + if (event != wlvif->last_rssi_event) + ieee80211_cqm_rssi_notify(vif, event, GFP_KERNEL); + wlvif->last_rssi_event = event; } static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) @@ -297,7 +299,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); if (wl->vif) - wl1271_event_rssi_trigger(wl, mbox); + wl1271_event_rssi_trigger(wl, vif, mbox); } if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) { diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index fd2b9f21acff..72ab25657dab 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3497,7 +3497,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, bss_conf->cqm_rssi_hyst); if (ret < 0) goto out; - wl->rssi_thold = bss_conf->cqm_rssi_thold; + wlvif->rssi_thold = bss_conf->cqm_rssi_thold; } if (changed & BSS_CHANGED_BSSID) diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 9d9d3fbd14e5..5a82450d8c70 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -514,9 +514,6 @@ struct wl1271 { /* in dBm */ int power_level; - int rssi_thold; - int last_rssi_event; - struct wl1271_stats stats; __le32 buffer_32; @@ -652,6 +649,9 @@ struct wl12xx_vif { /* retry counter for PSM entries */ u8 psm_entry_retry; + + int rssi_thold; + int last_rssi_event; }; static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) From d0802abdf9c60b1dadb097e806022f3449b0cc6b Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:04 +0200 Subject: [PATCH 26/97] wl12xx: move ba fields into wlvif move ba_fields into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 2 -- drivers/net/wireless/wl12xx/event.c | 8 ++++---- drivers/net/wireless/wl12xx/init.c | 7 +++---- drivers/net/wireless/wl12xx/main.c | 4 ++-- drivers/net/wireless/wl12xx/tx.c | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 10 +++++----- 6 files changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index e53f96830c2f..ee42a43d6a66 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -357,8 +357,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(noise); DRIVER_STATE_PRINT_LHEX(ap_hlid_map[0]); DRIVER_STATE_PRINT_INT(last_tx_hlid); - DRIVER_STATE_PRINT_INT(ba_support); - DRIVER_STATE_PRINT_HEX(ba_rx_bitmap); DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); DRIVER_STATE_PRINT_LHEX(ap_ps_map); DRIVER_STATE_PRINT_HEX(quirks); diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 775ad952ac8f..8c31274228ea 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -184,9 +184,9 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl, static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) { if (wlvif->bss_type != BSS_TYPE_AP_BSS) { - if (!wl->ba_rx_bitmap) + if (!wlvif->sta.ba_rx_bitmap) return; - ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, + ieee80211_stop_rx_ba_session(wl->vif, wlvif->sta.ba_rx_bitmap, wl->vif->bss_conf.bssid); } else { int i; @@ -306,9 +306,9 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " "ba_allowed = 0x%x", mbox->rx_ba_allowed); - wl->ba_allowed = !!mbox->rx_ba_allowed; + wlvif->ba_allowed = !!mbox->rx_ba_allowed; - if (wl->vif && !wl->ba_allowed) + if (wl->vif && !wlvif->ba_allowed) wl1271_stop_ba_event(wl, wlvif); } diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 1eaa0a3d9273..80e89e319879 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -486,18 +486,17 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) static int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) { /* Reset the BA RX indicators */ - wl->ba_rx_bitmap = 0; - wl->ba_allowed = true; + wlvif->ba_allowed = true; wl->ba_rx_session_count = 0; /* BA is supported in STA/AP modes */ if (wlvif->bss_type != BSS_TYPE_AP_BSS && wlvif->bss_type != BSS_TYPE_STA_BSS) { - wl->ba_support = false; + wlvif->ba_support = false; return 0; } - wl->ba_support = true; + wlvif->ba_support = true; /* 802.11n initiator BA session setting */ return wl12xx_acx_set_ba_initiator_policy(wl, wlvif); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 72ab25657dab..984dae881a8d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -4106,7 +4106,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, if (wlvif->bss_type == BSS_TYPE_STA_BSS) { hlid = wlvif->sta.hlid; - ba_bitmap = &wl->ba_rx_bitmap; + ba_bitmap = &wlvif->sta.ba_rx_bitmap; } else if (wlvif->bss_type == BSS_TYPE_AP_BSS) { struct wl1271_station *wl_sta; @@ -4127,7 +4127,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: - if (!wl->ba_support || !wl->ba_allowed) { + if (!wlvif->ba_support || !wlvif->ba_allowed) { ret = -ENOTSUPP; break; } diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 509ae10f0e03..6ce61635f3bd 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -941,7 +941,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) } } - wl->ba_rx_bitmap = 0; + wlvif->sta.ba_rx_bitmap = 0; } for (i = 0; i < NUM_TX_QUEUES; i++) diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 5a82450d8c70..fcc779147c1c 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -546,11 +546,6 @@ struct wl1271 { /* bands supported by this instance of wl12xx */ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; - /* RX BA constraint value */ - bool ba_support; - u8 ba_rx_bitmap; - bool ba_allowed; - int tcxo_clock; /* @@ -605,6 +600,7 @@ struct wl12xx_vif { union { struct { u8 hlid; + u8 ba_rx_bitmap; } sta; struct { u8 global_hlid; @@ -652,6 +648,10 @@ struct wl12xx_vif { int rssi_thold; int last_rssi_event; + + /* RX BA constraint value */ + bool ba_support; + bool ba_allowed; }; static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) From c7ffb902cca655e4d6bdda4156407008573bb214 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:05 +0200 Subject: [PATCH 27/97] wl12xx: move ap_hlid_map into wlvif.ap Add wlvif->links_map bitmap to represent all the links allocated for this vif. AP vif also has a sta_hlid_map bitmap, which represents the links stations connected to it (sta_hlid_bitmap is a subset of wlvif->links_map, which itself is a subset of the global wl->links_map) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 34 +++++----- drivers/net/wireless/wl12xx/cmd.h | 3 + drivers/net/wireless/wl12xx/debugfs.c | 1 - drivers/net/wireless/wl12xx/event.c | 15 ++--- drivers/net/wireless/wl12xx/event.h | 3 - drivers/net/wireless/wl12xx/main.c | 92 ++++++++++++--------------- drivers/net/wireless/wl12xx/tx.c | 35 +++++----- drivers/net/wireless/wl12xx/tx.h | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 24 ++----- 9 files changed, 92 insertions(+), 117 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 68375ffb4123..102a8a5371e4 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -434,23 +434,25 @@ out: return ret; } -static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid) +int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) { u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS); if (link >= WL12XX_MAX_LINKS) return -EBUSY; __set_bit(link, wl->links_map); + __set_bit(link, wlvif->links_map); *hlid = link; return 0; } -static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid) +void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) { if (*hlid == WL12XX_INVALID_LINK_ID) return; __clear_bit(*hlid, wl->links_map); + __clear_bit(*hlid, wlvif->links_map); *hlid = WL12XX_INVALID_LINK_ID; } @@ -484,7 +486,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->channel = wl->channel; if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, &wlvif->dev_hlid); + ret = wl12xx_allocate_link(wl, wlvif, &wlvif->dev_hlid); if (ret) goto out_free; } @@ -504,7 +506,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) err_hlid: /* clear links on error */ - wl12xx_free_link(wl, &wlvif->dev_hlid); + wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid); out_free: kfree(cmd); @@ -545,7 +547,7 @@ int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; } - wl12xx_free_link(wl, &wlvif->dev_hlid); + wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid); out_free: kfree(cmd); @@ -581,7 +583,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, &wlvif->sta.hlid); + ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid); if (ret) goto out_free; } @@ -604,7 +606,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) err_hlid: /* clear links on error. */ - wl12xx_free_link(wl, &wlvif->sta.hlid); + wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); out_free: kfree(cmd); @@ -640,7 +642,7 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; } - wl12xx_free_link(wl, &wlvif->sta.hlid); + wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); out_free: kfree(cmd); @@ -670,11 +672,11 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; } - ret = wl12xx_allocate_link(wl, &wlvif->ap.global_hlid); + ret = wl12xx_allocate_link(wl, wlvif, &wlvif->ap.global_hlid); if (ret < 0) goto out_free; - ret = wl12xx_allocate_link(wl, &wlvif->ap.bcast_hlid); + ret = wl12xx_allocate_link(wl, wlvif, &wlvif->ap.bcast_hlid); if (ret < 0) goto out_free_global; @@ -724,10 +726,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; out_free_bcast: - wl12xx_free_link(wl, &wlvif->ap.bcast_hlid); + wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid); out_free_global: - wl12xx_free_link(wl, &wlvif->ap.global_hlid); + wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid); out_free: kfree(cmd); @@ -757,8 +759,8 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; } - wl12xx_free_link(wl, &wlvif->ap.bcast_hlid); - wl12xx_free_link(wl, &wlvif->ap.global_hlid); + wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid); + wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid); out_free: kfree(cmd); @@ -796,7 +798,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, &wlvif->sta.hlid); + ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid); if (ret) goto out_free; } @@ -821,7 +823,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) err_hlid: /* clear links on error. */ - wl12xx_free_link(wl, &wlvif->sta.hlid); + wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); out_free: kfree(cmd); diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 9624828b76e8..d2670d379b75 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -89,6 +89,9 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); int wl12xx_cmd_channel_switch(struct wl1271 *wl, struct ieee80211_channel_switch *ch_switch); int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl); +int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 *hlid); +void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid); enum wl1271_commands { CMD_INTERROGATE = 1, /*use this to read information elements*/ diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index ee42a43d6a66..f0398d037d4d 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -355,7 +355,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(sg_enabled); DRIVER_STATE_PRINT_INT(enable_11a); DRIVER_STATE_PRINT_INT(noise); - DRIVER_STATE_PRINT_LHEX(ap_hlid_map[0]); DRIVER_STATE_PRINT_INT(last_tx_hlid); DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); DRIVER_STATE_PRINT_LHEX(ap_ps_map); diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 8c31274228ea..486c8ee0101a 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -189,11 +189,12 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) ieee80211_stop_rx_ba_session(wl->vif, wlvif->sta.ba_rx_bitmap, wl->vif->bss_conf.bssid); } else { - int i; + u8 hlid; struct wl1271_link *lnk; - for (i = WL1271_AP_STA_HLID_START; i < AP_MAX_LINKS; i++) { - lnk = &wl->links[i]; - if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap) + for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, + WL12XX_MAX_LINKS) { + lnk = &wl->links[hlid]; + if (!lnk->ba_bitmap) continue; ieee80211_stop_rx_ba_session(wl->vif, @@ -355,10 +356,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) const u8 *addr; int h; - for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); - h < AP_MAX_LINKS; - h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { - if (!wl1271_is_active_sta(wl, h)) + for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) { + if (!test_bit(h, wlvif->ap.sta_hlid_map)) continue; addr = wl->links[h].addr; diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h index 49c1a0ede5b1..1d878ba47bf4 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/wl12xx/event.h @@ -132,7 +132,4 @@ void wl1271_event_mbox_config(struct wl1271 *wl); int wl1271_event_handle(struct wl1271 *wl, u8 mbox); void wl1271_pspoll_work(struct work_struct *work); -/* Functions from main.c */ -bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid); - #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 984dae881a8d..f712f0fb50be 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -778,10 +778,6 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) { bool fw_ps, single_sta; - /* only regulate station links */ - if (hlid < WL1271_AP_STA_HLID_START) - return; - fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); single_sta = (wl->active_sta_count == 1); @@ -801,21 +797,11 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) wl1271_ps_link_start(wl, hlid, true); } -bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) -{ - int id; - - /* global/broadcast "stations" are always active */ - if (hlid < WL1271_AP_STA_HLID_START) - return true; - - id = hlid - WL1271_AP_STA_HLID_START; - return test_bit(id, wl->ap_hlid_map); -} - static void wl12xx_irq_update_links_status(struct wl1271 *wl, + struct wl12xx_vif *wlvif, struct wl12xx_fw_status *status) { + struct wl1271_link *lnk; u32 cur_fw_ps_map; u8 hlid, cnt; @@ -831,19 +817,14 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, wl->ap_fw_ps_map = cur_fw_ps_map; } - for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) { - if (!wl1271_is_active_sta(wl, hlid)) - continue; + for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) { + lnk = &wl->links[hlid]; + cnt = status->tx_lnk_free_pkts[hlid] - lnk->prev_freed_pkts; - cnt = status->tx_lnk_free_pkts[hlid] - - wl->links[hlid].prev_freed_pkts; + lnk->prev_freed_pkts = status->tx_lnk_free_pkts[hlid]; + lnk->allocated_pkts -= cnt; - wl->links[hlid].prev_freed_pkts = - status->tx_lnk_free_pkts[hlid]; - wl->links[hlid].allocated_pkts -= cnt; - - wl12xx_irq_ps_regulate_link(wl, hlid, - wl->links[hlid].allocated_pkts); + wl12xx_irq_ps_regulate_link(wl, hlid, lnk->allocated_pkts); } } @@ -907,7 +888,7 @@ static void wl12xx_fw_status(struct wl1271 *wl, /* for AP update num of allocated TX blocks per link and ps status */ if (wlvif->bss_type == BSS_TYPE_AP_BSS) - wl12xx_irq_update_links_status(wl, status); + wl12xx_irq_update_links_status(wl, wlvif, status); /* update the host-chipset time offset */ getnstimeofday(&ts); @@ -1505,7 +1486,7 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) /* queue the packet */ if (wlvif->bss_type == BSS_TYPE_AP_BSS) { - if (!wl1271_is_active_sta(wl, hlid)) { + if (!test_bit(hlid, wlvif->links_map)) { wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); dev_kfree_skb(skb); @@ -2152,7 +2133,7 @@ deinit: wl->vif = NULL; wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl1271_free_ap_keys(wl); - memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); + memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map)); wl->ap_fw_ps_map = 0; wl->ap_ps_map = 0; wl->sched_scanning = false; @@ -3946,43 +3927,44 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, } static int wl1271_allocate_sta(struct wl1271 *wl, - struct ieee80211_sta *sta, - u8 *hlid) + struct wl12xx_vif *wlvif, + struct ieee80211_sta *sta) { struct wl1271_station *wl_sta; - int id; + int ret; - id = find_first_zero_bit(wl->ap_hlid_map, AP_MAX_STATIONS); - if (id >= AP_MAX_STATIONS) { + + if (wl->active_sta_count >= AP_MAX_STATIONS) { wl1271_warning("could not allocate HLID - too much stations"); return -EBUSY; } wl_sta = (struct wl1271_station *)sta->drv_priv; - set_bit(id, wl->ap_hlid_map); - wl_sta->hlid = WL1271_AP_STA_HLID_START + id; - *hlid = wl_sta->hlid; + ret = wl12xx_allocate_link(wl, wlvif, &wl_sta->hlid); + if (ret < 0) { + wl1271_warning("could not allocate HLID - too many links"); + return -EBUSY; + } + + set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map); memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); wl->active_sta_count++; return 0; } -void wl1271_free_sta(struct wl1271 *wl, u8 hlid) +/* TODO: change wl1271_tx_reset(), so we can get sta as param */ +void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) { - int id = hlid - WL1271_AP_STA_HLID_START; - - if (hlid < WL1271_AP_STA_HLID_START) + if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) return; - if (!test_bit(id, wl->ap_hlid_map)) - return; - - clear_bit(id, wl->ap_hlid_map); + clear_bit(hlid, wlvif->ap.sta_hlid_map); memset(wl->links[hlid].addr, 0, ETH_ALEN); wl->links[hlid].ba_bitmap = 0; wl1271_tx_reset_link_queues(wl, hlid); __clear_bit(hlid, &wl->ap_ps_map); __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); + wl12xx_free_link(wl, wlvif, &hlid); wl->active_sta_count--; } @@ -3992,6 +3974,7 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, { struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct wl1271_station *wl_sta; int ret = 0; u8 hlid; @@ -4005,10 +3988,13 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); - ret = wl1271_allocate_sta(wl, sta, &hlid); + ret = wl1271_allocate_sta(wl, wlvif, sta); if (ret < 0) goto out; + wl_sta = (struct wl1271_station *)sta->drv_priv; + hlid = wl_sta->hlid; + ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out_free_sta; @@ -4030,7 +4016,7 @@ out_sleep: out_free_sta: if (ret < 0) - wl1271_free_sta(wl, hlid); + wl1271_free_sta(wl, wlvif, hlid); out: mutex_unlock(&wl->mutex); @@ -4057,8 +4043,8 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid); wl_sta = (struct wl1271_station *)sta->drv_priv; - id = wl_sta->hlid - WL1271_AP_STA_HLID_START; - if (WARN_ON(!test_bit(id, wl->ap_hlid_map))) + id = wl_sta->hlid; + if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map))) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -4069,7 +4055,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; - wl1271_free_sta(wl, wl_sta->hlid); + wl1271_free_sta(wl, wlvif, wl_sta->hlid); out_sleep: wl1271_ps_elp_sleep(wl); @@ -4841,7 +4827,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) int i, j, ret; unsigned int order; - BUILD_BUG_ON(AP_MAX_LINKS > WL12XX_MAX_LINKS); + BUILD_BUG_ON(AP_MAX_STATIONS > WL12XX_MAX_LINKS); hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); if (!hw) { @@ -4869,7 +4855,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) skb_queue_head_init(&wl->tx_queue[i]); for (i = 0; i < NUM_TX_QUEUES; i++) - for (j = 0; j < AP_MAX_LINKS; j++) + for (j = 0; j < WL12XX_MAX_LINKS; j++) skb_queue_head_init(&wl->links[j].tx_queue[i]); skb_queue_head_init(&wl->deferred_rx_queue); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 6ce61635f3bd..1b3d8e3f35a8 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -125,18 +125,16 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, wl1271_acx_set_inconnection_sta(wl, hdr->addr1); } -static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid) +static void wl1271_tx_regulate_link(struct wl1271 *wl, + struct wl12xx_vif *wlvif, + u8 hlid) { bool fw_ps, single_sta; u8 tx_pkts; - /* only regulate station links */ - if (hlid < WL1271_AP_STA_HLID_START) + if (WARN_ON(!test_bit(hlid, wlvif->links_map))) return; - if (WARN_ON(!wl1271_is_active_sta(wl, hlid))) - return; - fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); tx_pkts = wl->links[hlid].allocated_pkts; single_sta = (wl->active_sta_count == 1); @@ -266,7 +264,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif, wl->tx_allocated_pkts[ac]++; if (wlvif->bss_type == BSS_TYPE_AP_BSS && - hlid >= WL1271_AP_STA_HLID_START) + test_bit(hlid, wlvif->ap.sta_hlid_map)) wl->links[hlid].allocated_pkts++; ret = 0; @@ -445,7 +443,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, if (wlvif->bss_type == BSS_TYPE_AP_BSS && !is_dummy) { wl1271_tx_ap_update_inconnection_sta(wl, skb); - wl1271_tx_regulate_link(wl, hlid); + wl1271_tx_regulate_link(wl, wlvif, hlid); } /* @@ -563,7 +561,8 @@ out: return skb; } -static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) +static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { struct sk_buff *skb = NULL; unsigned long flags; @@ -571,15 +570,14 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) struct sk_buff_head *queue; /* start from the link after the last one */ - start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS; + start_hlid = (wl->last_tx_hlid + 1) % WL12XX_MAX_LINKS; /* dequeue according to AC, round robin on each link */ - for (i = 0; i < AP_MAX_LINKS; i++) { - h = (start_hlid + i) % AP_MAX_LINKS; + for (i = 0; i < WL12XX_MAX_LINKS; i++) { + h = (start_hlid + i) % WL12XX_MAX_LINKS; /* only consider connected stations */ - if (h >= WL1271_AP_STA_HLID_START && - !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map)) + if (!test_bit(h, wlvif->links_map)) continue; queue = wl1271_select_queue(wl, wl->links[h].tx_queue); @@ -611,7 +609,7 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl, struct sk_buff *skb = NULL; if (wlvif->bss_type == BSS_TYPE_AP_BSS) - skb = wl1271_ap_skb_dequeue(wl); + skb = wl1271_ap_skb_dequeue(wl, wlvif); else skb = wl1271_sta_skb_dequeue(wl); @@ -643,7 +641,8 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct ieee80211_vif *vif, skb_queue_head(&wl->links[hlid].tx_queue[q], skb); /* make sure we dequeue the same packet next time */ - wl->last_tx_hlid = (hlid + AP_MAX_LINKS - 1) % AP_MAX_LINKS; + wl->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) % + WL12XX_MAX_LINKS; } else { skb_queue_head(&wl->tx_queue[q], skb); } @@ -918,8 +917,8 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) /* TX failure */ if (wlvif->bss_type == BSS_TYPE_AP_BSS) { - for (i = 0; i < AP_MAX_LINKS; i++) { - wl1271_free_sta(wl, i); + for (i = 0; i < WL12XX_MAX_LINKS; i++) { + wl1271_free_sta(wl, wlvif, i); wl1271_tx_reset_link_queues(wl, i); wl->links[i].allocated_pkts = 0; wl->links[i].prev_freed_pkts = 0; diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 0964c9335316..add4402d7931 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -219,6 +219,6 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl); bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); /* from main.c */ -void wl1271_free_sta(struct wl1271 *wl, u8 hlid); +void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); #endif diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index fcc779147c1c..5fd3c262bc5f 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -145,12 +145,6 @@ extern u32 wl12xx_debug_level; /* Defined by FW as 0. Will not be freed or allocated. */ #define WL12XX_SYSTEM_HLID 0 -/* - * TODO: we currently don't support multirole. remove - * this constant from the code when we do. - */ -#define WL1271_AP_STA_HLID_START 3 - /* * When in AP-mode, we allow (at least) this number of packets * to be transmitted to FW for a STA in PS-mode. Only when packets are @@ -236,13 +230,6 @@ struct wl1271_stats { #define AP_MAX_STATIONS 8 -/* Broadcast and Global links + system link + links to stations */ -/* - * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all - * the places that use this. - */ -#define AP_MAX_LINKS (AP_MAX_STATIONS + WL1271_AP_STA_HLID_START) - /* FW status registers */ struct wl12xx_fw_status { __le32 intr; @@ -537,9 +524,6 @@ struct wl1271 { /* Most recently reported noise in dBm */ s8 noise; - /* map for HLIDs of associated stations - when operating in AP mode */ - unsigned long ap_hlid_map[BITS_TO_LONGS(AP_MAX_STATIONS)]; - /* recoreded keys for AP-mode - set here before AP startup */ struct wl1271_ap_key *recorded_ap_keys[MAX_NUM_KEYS]; @@ -559,7 +543,7 @@ struct wl1271 { * AP-mode - links indexed by HLID. The global and broadcast links * are always active. */ - struct wl1271_link links[AP_MAX_LINKS]; + struct wl1271_link links[WL12XX_MAX_LINKS]; /* the hlid of the link where the last transmitted skb came from */ int last_tx_hlid; @@ -605,9 +589,15 @@ struct wl12xx_vif { struct { u8 global_hlid; u8 bcast_hlid; + + /* HLIDs bitmap of associated stations */ + unsigned long sta_hlid_map[BITS_TO_LONGS( + WL12XX_MAX_LINKS)]; } ap; }; + unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; + u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 ssid_len; From 170d0e6732c5fb1d4103ded3da95a5630c24e5dd Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:06 +0200 Subject: [PATCH 28/97] wl12xx: move recorded_ap_keys into wlvif move recorded_ap_keys into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 31 ++++++++++++++-------------- drivers/net/wireless/wl12xx/wl12xx.h | 6 +++--- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index f712f0fb50be..194d7cc366de 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -379,7 +379,7 @@ static bool bug_on_recovery; static void __wl1271_op_remove_interface(struct wl1271 *wl, struct ieee80211_vif *vif, bool reset_tx_queues); -static void wl1271_free_ap_keys(struct wl1271 *wl); +static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif); static void wl1271_device_release(struct device *dev) @@ -2132,7 +2132,7 @@ deinit: wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; wl->vif = NULL; wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; - wl1271_free_ap_keys(wl); + wl1271_free_ap_keys(wl, wlvif); memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map)); wl->ap_fw_ps_map = 0; wl->ap_ps_map = 0; @@ -2603,9 +2603,10 @@ out: kfree(fp); } -static int wl1271_record_ap_key(struct wl1271 *wl, u8 id, u8 key_type, - u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, - u16 tx_seq_16) +static int wl1271_record_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 id, u8 key_type, u8 key_size, + const u8 *key, u8 hlid, u32 tx_seq_32, + u16 tx_seq_16) { struct wl1271_ap_key *ap_key; int i; @@ -2620,10 +2621,10 @@ static int wl1271_record_ap_key(struct wl1271 *wl, u8 id, u8 key_type, * an existing key. */ for (i = 0; i < MAX_NUM_KEYS; i++) { - if (wl->recorded_ap_keys[i] == NULL) + if (wlvif->ap.recorded_keys[i] == NULL) break; - if (wl->recorded_ap_keys[i]->id == id) { + if (wlvif->ap.recorded_keys[i]->id == id) { wl1271_warning("trying to record key replacement"); return -EINVAL; } @@ -2644,17 +2645,17 @@ static int wl1271_record_ap_key(struct wl1271 *wl, u8 id, u8 key_type, ap_key->tx_seq_32 = tx_seq_32; ap_key->tx_seq_16 = tx_seq_16; - wl->recorded_ap_keys[i] = ap_key; + wlvif->ap.recorded_keys[i] = ap_key; return 0; } -static void wl1271_free_ap_keys(struct wl1271 *wl) +static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int i; for (i = 0; i < MAX_NUM_KEYS; i++) { - kfree(wl->recorded_ap_keys[i]); - wl->recorded_ap_keys[i] = NULL; + kfree(wlvif->ap.recorded_keys[i]); + wlvif->ap.recorded_keys[i] = NULL; } } @@ -2666,10 +2667,10 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl, struct wl12xx_vif *wlvif) for (i = 0; i < MAX_NUM_KEYS; i++) { u8 hlid; - if (wl->recorded_ap_keys[i] == NULL) + if (wlvif->ap.recorded_keys[i] == NULL) break; - key = wl->recorded_ap_keys[i]; + key = wlvif->ap.recorded_keys[i]; hlid = key->hlid; if (hlid == WL12XX_INVALID_LINK_ID) hlid = wlvif->ap.bcast_hlid; @@ -2694,7 +2695,7 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl, struct wl12xx_vif *wlvif) } out: - wl1271_free_ap_keys(wl); + wl1271_free_ap_keys(wl, wlvif); return ret; } @@ -2725,7 +2726,7 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (action != KEY_ADD_OR_REPLACE) return 0; - ret = wl1271_record_ap_key(wl, id, + ret = wl1271_record_ap_key(wl, wlvif, id, key_type, key_size, key, hlid, tx_seq_32, tx_seq_16); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 5fd3c262bc5f..074de4e1fb33 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -524,9 +524,6 @@ struct wl1271 { /* Most recently reported noise in dBm */ s8 noise; - /* recoreded keys for AP-mode - set here before AP startup */ - struct wl1271_ap_key *recorded_ap_keys[MAX_NUM_KEYS]; - /* bands supported by this instance of wl12xx */ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; @@ -593,6 +590,9 @@ struct wl12xx_vif { /* HLIDs bitmap of associated stations */ unsigned long sta_hlid_map[BITS_TO_LONGS( WL12XX_MAX_LINKS)]; + + /* recoreded keys - set here before AP startup */ + struct wl1271_ap_key *recorded_keys[MAX_NUM_KEYS]; } ap; }; From 1d095475f58680af17e4a0e8dd84269b3f08ce54 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:49 +0200 Subject: [PATCH 29/97] wl12xx: refactor fw init into a new function The fw boot and initialization currently happens inside the add_interface() callback. This is wrong, as add_interface is called for each new vif. However, we due to some fw limitation (we have to know the actual mac address on boot), we can't completely move it into the start() callback. Until the fw will be fixed, refactor the fw init into a new function, and call it from add_interface() Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 187 ++++++++++++++++------------- 1 file changed, 101 insertions(+), 86 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 194d7cc366de..3667acf0a031 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1888,13 +1888,80 @@ static int wl12xx_init_vif_data(struct ieee80211_vif *vif) return 0; } +static bool wl12xx_init_fw(struct wl1271 *wl) +{ + int retries = WL1271_BOOT_RETRIES; + bool booted = false; + struct wiphy *wiphy = wl->hw->wiphy; + int ret; + + while (retries) { + retries--; + ret = wl1271_chip_wakeup(wl); + if (ret < 0) + goto power_off; + + ret = wl1271_boot(wl); + if (ret < 0) + goto power_off; + + ret = wl1271_hw_init(wl); + if (ret < 0) + goto irq_disable; + + booted = true; + break; + +irq_disable: + mutex_unlock(&wl->mutex); + /* Unlocking the mutex in the middle of handling is + inherently unsafe. In this case we deem it safe to do, + because we need to let any possibly pending IRQ out of + the system (and while we are WL1271_STATE_OFF the IRQ + work function will not do anything.) Also, any other + possible concurrent operations will fail due to the + current state, hence the wl1271 struct should be safe. */ + wl1271_disable_interrupts(wl); + wl1271_flush_deferred_work(wl); + cancel_work_sync(&wl->netstack_work); + mutex_lock(&wl->mutex); +power_off: + wl1271_power_off(wl); + } + + if (!booted) { + wl1271_error("firmware boot failed despite %d retries", + WL1271_BOOT_RETRIES); + goto out; + } + + wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); + + /* update hw/fw version info in wiphy struct */ + wiphy->hw_version = wl->chip.id; + strncpy(wiphy->fw_version, wl->chip.fw_ver_str, + sizeof(wiphy->fw_version)); + + /* + * Now we know if 11a is supported (info from the NVS), so disable + * 11a channels if not supported + */ + if (!wl->enable_11a) + wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels = 0; + + wl1271_debug(DEBUG_MAC80211, "11a is %ssupported", + wl->enable_11a ? "" : "not "); + + wl->state = WL1271_STATE_ON; +out: + return booted; +} + static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; - struct wiphy *wiphy = hw->wiphy; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - int retries = WL1271_BOOT_RETRIES; int ret = 0; u8 role_type; bool booted = false; @@ -1930,103 +1997,51 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, ret = -EINVAL; goto out; } + /* - * we still need this in order to configure the fw - * while uploading the nvs + * TODO: after the nvs issue will be solved, move this block + * to start(), and make sure here the driver is ON. */ - memcpy(wl->mac_addr, vif->addr, ETH_ALEN); + if (wl->state == WL1271_STATE_OFF) { + /* + * we still need this in order to configure the fw + * while uploading the nvs + */ + memcpy(wl->mac_addr, vif->addr, ETH_ALEN); - if (wl->state != WL1271_STATE_OFF) { - wl1271_error("cannot start because not in off state: %d", - wl->state); - ret = -EBUSY; - goto out; - } - - while (retries) { - retries--; - ret = wl1271_chip_wakeup(wl); - if (ret < 0) - goto power_off; - - ret = wl1271_boot(wl); - if (ret < 0) - goto power_off; - - ret = wl1271_hw_init(wl); - if (ret < 0) - goto irq_disable; - - if (wlvif->bss_type == BSS_TYPE_STA_BSS || - wlvif->bss_type == BSS_TYPE_IBSS) { - /* - * The device role is a special role used for - * rx and tx frames prior to association (as - * the STA role can get packets only from - * its associated bssid) - */ - ret = wl12xx_cmd_role_enable(wl, vif->addr, - WL1271_ROLE_DEVICE, - &wlvif->dev_role_id); - if (ret < 0) - goto irq_disable; + booted = wl12xx_init_fw(wl); + if (!booted) { + ret = -EINVAL; + goto out; } + } + if (wlvif->bss_type == BSS_TYPE_STA_BSS || + wlvif->bss_type == BSS_TYPE_IBSS) { + /* + * The device role is a special role used for + * rx and tx frames prior to association (as + * the STA role can get packets only from + * its associated bssid) + */ ret = wl12xx_cmd_role_enable(wl, vif->addr, - role_type, &wlvif->role_id); + WL1271_ROLE_DEVICE, + &wlvif->dev_role_id); if (ret < 0) - goto irq_disable; - - ret = wl1271_init_vif_specific(wl, vif); - if (ret < 0) - goto irq_disable; - - booted = true; - break; - -irq_disable: - mutex_unlock(&wl->mutex); - /* Unlocking the mutex in the middle of handling is - inherently unsafe. In this case we deem it safe to do, - because we need to let any possibly pending IRQ out of - the system (and while we are WL1271_STATE_OFF the IRQ - work function will not do anything.) Also, any other - possible concurrent operations will fail due to the - current state, hence the wl1271 struct should be safe. */ - wl1271_disable_interrupts(wl); - wl1271_flush_deferred_work(wl); - cancel_work_sync(&wl->netstack_work); - mutex_lock(&wl->mutex); -power_off: - wl1271_power_off(wl); + goto out; } - if (!booted) { - wl1271_error("firmware boot failed despite %d retries", - WL1271_BOOT_RETRIES); + ret = wl12xx_cmd_role_enable(wl, vif->addr, + role_type, &wlvif->role_id); + if (ret < 0) + goto out; + + ret = wl1271_init_vif_specific(wl, vif); + if (ret < 0) goto out; - } wl->vif = vif; - wl->state = WL1271_STATE_ON; set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); - wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); - - /* update hw/fw version info in wiphy struct */ - wiphy->hw_version = wl->chip.id; - strncpy(wiphy->fw_version, wl->chip.fw_ver_str, - sizeof(wiphy->fw_version)); - - /* - * Now we know if 11a is supported (info from the NVS), so disable - * 11a channels if not supported - */ - if (!wl->enable_11a) - wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels = 0; - - wl1271_debug(DEBUG_MAC80211, "11a is %ssupported", - wl->enable_11a ? "" : "not "); - out: mutex_unlock(&wl->mutex); From 4438aca9e16901d8d32a025ca27ad8284a117e09 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:50 +0200 Subject: [PATCH 30/97] wl12xx: move last_tx_hlid into wlvif move last_tx_hlid into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 1 - drivers/net/wireless/wl12xx/main.c | 1 - drivers/net/wireless/wl12xx/tx.c | 10 +++++----- drivers/net/wireless/wl12xx/wl12xx.h | 6 +++--- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index f0398d037d4d..bbc8004edf40 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -355,7 +355,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(sg_enabled); DRIVER_STATE_PRINT_INT(enable_11a); DRIVER_STATE_PRINT_INT(noise); - DRIVER_STATE_PRINT_INT(last_tx_hlid); DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); DRIVER_STATE_PRINT_LHEX(ap_ps_map); DRIVER_STATE_PRINT_HEX(quirks); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 3667acf0a031..0606b0d8aabd 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -4901,7 +4901,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->flags = 0; wl->sg_enabled = true; wl->hw_pg_ver = -1; - wl->last_tx_hlid = 0; wl->ap_ps_map = 0; wl->ap_fw_ps_map = 0; wl->quirks = 0; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 1b3d8e3f35a8..951ff03b7f42 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -570,7 +570,7 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl, struct sk_buff_head *queue; /* start from the link after the last one */ - start_hlid = (wl->last_tx_hlid + 1) % WL12XX_MAX_LINKS; + start_hlid = (wlvif->last_tx_hlid + 1) % WL12XX_MAX_LINKS; /* dequeue according to AC, round robin on each link */ for (i = 0; i < WL12XX_MAX_LINKS; i++) { @@ -591,12 +591,12 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl, if (skb) { int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); - wl->last_tx_hlid = h; + wlvif->last_tx_hlid = h; spin_lock_irqsave(&wl->wl_lock, flags); wl->tx_queue_count[q]--; spin_unlock_irqrestore(&wl->wl_lock, flags); } else { - wl->last_tx_hlid = 0; + wlvif->last_tx_hlid = 0; } return skb; @@ -641,7 +641,7 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct ieee80211_vif *vif, skb_queue_head(&wl->links[hlid].tx_queue[q], skb); /* make sure we dequeue the same packet next time */ - wl->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) % + wlvif->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) % WL12XX_MAX_LINKS; } else { skb_queue_head(&wl->tx_queue[q], skb); @@ -924,7 +924,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) wl->links[i].prev_freed_pkts = 0; } - wl->last_tx_hlid = 0; + wlvif->last_tx_hlid = 0; } else { for (i = 0; i < NUM_TX_QUEUES; i++) { while ((skb = skb_dequeue(&wl->tx_queue[i]))) { diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 074de4e1fb33..b350f0bdd38d 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -542,9 +542,6 @@ struct wl1271 { */ struct wl1271_link links[WL12XX_MAX_LINKS]; - /* the hlid of the link where the last transmitted skb came from */ - int last_tx_hlid; - /* AP-mode - a bitmap of links currently in PS mode according to FW */ u32 ap_fw_ps_map; @@ -596,6 +593,9 @@ struct wl12xx_vif { } ap; }; + /* the hlid of the last transmitted skb */ + int last_tx_hlid; + unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; From d6a3cc2ef962ad4392a2401cae513a18a6d35099 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:51 +0200 Subject: [PATCH 31/97] wl12xx: unify STA and AP tx_queue mechanism Make sta use the global wl->links[hlid].tx_queue (by considering its links map) instead of wl->tx_queue, and then unify the tx and tx_reset flows for the various vifs. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 32 +++----- drivers/net/wireless/wl12xx/tx.c | 115 ++++++++++----------------- drivers/net/wireless/wl12xx/tx.h | 5 +- drivers/net/wireless/wl12xx/wl12xx.h | 1 - 4 files changed, 58 insertions(+), 95 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0606b0d8aabd..abe5ef8807ba 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1474,31 +1474,26 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); unsigned long flags; int q, mapping; - u8 hlid = 0; + u8 hlid; mapping = skb_get_queue_mapping(skb); q = wl1271_tx_get_queue(mapping); - if (wlvif->bss_type == BSS_TYPE_AP_BSS) - hlid = wl12xx_tx_get_hlid_ap(wl, wlvif, skb); + hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); spin_lock_irqsave(&wl->wl_lock, flags); /* queue the packet */ - if (wlvif->bss_type == BSS_TYPE_AP_BSS) { - if (!test_bit(hlid, wlvif->links_map)) { - wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", - hlid, q); - dev_kfree_skb(skb); - goto out; - } - - wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q); - skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); - } else { - skb_queue_tail(&wl->tx_queue[q], skb); + if (hlid == WL12XX_INVALID_LINK_ID || + !test_bit(hlid, wlvif->links_map)) { + wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); + dev_kfree_skb(skb); + goto out; } + wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q); + skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); + wl->tx_queue_count[q]++; /* @@ -2131,7 +2126,8 @@ deinit: mutex_lock(&wl->mutex); /* let's notify MAC80211 about the remaining pending TX frames */ - wl1271_tx_reset(wl, reset_tx_queues); + wl12xx_tx_reset_wlvif(wl, wlvif); + wl12xx_tx_reset(wl, reset_tx_queues); wl1271_power_off(wl); wl->band = IEEE80211_BAND_2GHZ; @@ -3968,7 +3964,6 @@ static int wl1271_allocate_sta(struct wl1271 *wl, return 0; } -/* TODO: change wl1271_tx_reset(), so we can get sta as param */ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) { if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) @@ -4867,9 +4862,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->hw = hw; wl->plat_dev = plat_dev; - for (i = 0; i < NUM_TX_QUEUES; i++) - skb_queue_head_init(&wl->tx_queue[i]); - for (i = 0; i < NUM_TX_QUEUES; i++) for (j = 0; j < WL12XX_MAX_LINKS; j++) skb_queue_head_init(&wl->links[j].tx_queue[i]); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 951ff03b7f42..6c0135b27820 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -179,12 +179,10 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, } } -static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct ieee80211_vif *vif, - struct sk_buff *skb) +u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, + struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - if (wl12xx_is_dummy_packet(wl, skb)) return wl->system_hlid; @@ -429,7 +427,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, wlvif->default_key = idx; } } - hlid = wl1271_tx_get_hlid(wl, vif, skb); + hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); if (hlid == WL12XX_INVALID_LINK_ID) { wl1271_error("invalid hlid. dropping skb 0x%p", skb); return -EINVAL; @@ -538,19 +536,18 @@ static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, return &queues[q]; } -static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl) +static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl, + struct wl1271_link *lnk) { - struct sk_buff *skb = NULL; + struct sk_buff *skb; unsigned long flags; struct sk_buff_head *queue; - queue = wl1271_select_queue(wl, wl->tx_queue); + queue = wl1271_select_queue(wl, lnk->tx_queue); if (!queue) - goto out; + return NULL; skb = skb_dequeue(queue); - -out: if (skb) { int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); spin_lock_irqsave(&wl->wl_lock, flags); @@ -561,13 +558,11 @@ out: return skb; } -static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { struct sk_buff *skb = NULL; - unsigned long flags; int i, h, start_hlid; - struct sk_buff_head *queue; /* start from the link after the last one */ start_hlid = (wlvif->last_tx_hlid + 1) % WL12XX_MAX_LINKS; @@ -580,24 +575,16 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl, if (!test_bit(h, wlvif->links_map)) continue; - queue = wl1271_select_queue(wl, wl->links[h].tx_queue); - if (!queue) + skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[h]); + if (!skb) continue; - skb = skb_dequeue(queue); - if (skb) - break; + wlvif->last_tx_hlid = h; + break; } - if (skb) { - int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); - wlvif->last_tx_hlid = h; - spin_lock_irqsave(&wl->wl_lock, flags); - wl->tx_queue_count[q]--; - spin_unlock_irqrestore(&wl->wl_lock, flags); - } else { + if (!skb) wlvif->last_tx_hlid = 0; - } return skb; } @@ -608,11 +595,7 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl, unsigned long flags; struct sk_buff *skb = NULL; - if (wlvif->bss_type == BSS_TYPE_AP_BSS) - skb = wl1271_ap_skb_dequeue(wl, wlvif); - else - skb = wl1271_sta_skb_dequeue(wl); - + skb = wl12xx_vif_skb_dequeue(wl, wlvif); if (!skb && test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { int q; @@ -627,24 +610,21 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl, return skb; } -static void wl1271_skb_queue_head(struct wl1271 *wl, struct ieee80211_vif *vif, +static void wl1271_skb_queue_head(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct sk_buff *skb) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); unsigned long flags; int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); if (wl12xx_is_dummy_packet(wl, skb)) { set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); - } else if (wlvif->bss_type == BSS_TYPE_AP_BSS) { - u8 hlid = wl1271_tx_get_hlid(wl, vif, skb); + } else { + u8 hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); skb_queue_head(&wl->links[hlid].tx_queue[q], skb); /* make sure we dequeue the same packet next time */ wlvif->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) % - WL12XX_MAX_LINKS; - } else { - skb_queue_head(&wl->tx_queue[q], skb); + WL12XX_MAX_LINKS; } spin_lock_irqsave(&wl->wl_lock, flags); @@ -682,7 +662,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif) * Aggregation buffer is full. * Flush buffer and try again. */ - wl1271_skb_queue_head(wl, vif, skb); + wl1271_skb_queue_head(wl, wlvif, skb); wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, buf_offset, true); sent_packets = true; @@ -693,7 +673,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif) * Firmware buffer is full. * Queue back last skb, and stop aggregating. */ - wl1271_skb_queue_head(wl, vif, skb); + wl1271_skb_queue_head(wl, wlvif, skb); /* No work left, avoid scheduling redundant tx work */ set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); goto out_ack; @@ -907,42 +887,31 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) } /* caller must hold wl->mutex and TX must be stopped */ -void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) +void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + int i; + + /* TX failure */ + for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) { + if (wlvif->bss_type == BSS_TYPE_AP_BSS) + wl1271_free_sta(wl, wlvif, i); + else + wlvif->sta.ba_rx_bitmap = 0; + + wl1271_tx_reset_link_queues(wl, i); + wl->links[i].allocated_pkts = 0; + wl->links[i].prev_freed_pkts = 0; + } + wlvif->last_tx_hlid = 0; + +} +/* caller must hold wl->mutex and TX must be stopped */ +void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues) { - struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int i; struct sk_buff *skb; struct ieee80211_tx_info *info; - /* TX failure */ - if (wlvif->bss_type == BSS_TYPE_AP_BSS) { - for (i = 0; i < WL12XX_MAX_LINKS; i++) { - wl1271_free_sta(wl, wlvif, i); - wl1271_tx_reset_link_queues(wl, i); - wl->links[i].allocated_pkts = 0; - wl->links[i].prev_freed_pkts = 0; - } - - wlvif->last_tx_hlid = 0; - } else { - for (i = 0; i < NUM_TX_QUEUES; i++) { - while ((skb = skb_dequeue(&wl->tx_queue[i]))) { - wl1271_debug(DEBUG_TX, "freeing skb 0x%p", - skb); - - if (!wl12xx_is_dummy_packet(wl, skb)) { - info = IEEE80211_SKB_CB(skb); - info->status.rates[0].idx = -1; - info->status.rates[0].count = 0; - ieee80211_tx_status_ni(wl->hw, skb); - } - } - } - - wlvif->sta.ba_rx_bitmap = 0; - } - for (i = 0; i < NUM_TX_QUEUES; i++) wl->tx_queue_count[i] = 0; diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index add4402d7931..050a04792600 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -206,7 +206,8 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) void wl1271_tx_work(struct work_struct *work); void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif); void wl1271_tx_complete(struct wl1271 *wl); -void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues); +void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); +void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues); void wl1271_tx_flush(struct wl1271 *wl); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, @@ -214,6 +215,8 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set); u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct sk_buff *skb); +u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, + struct sk_buff *skb); void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); void wl1271_handle_tx_low_watermark(struct wl1271 *wl); bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index b350f0bdd38d..4802f685de63 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -416,7 +416,6 @@ struct wl1271 { s64 time_offset; /* Frames scheduled for transmission, not handled yet */ - struct sk_buff_head tx_queue[NUM_TX_QUEUES]; int tx_queue_count[NUM_TX_QUEUES]; long stopped_queues_map; From baf6277ae964b1d3830aa74b13e87ff9ba29145c Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:52 +0200 Subject: [PATCH 32/97] wl12xx: move some functions from remove_interface() to stop() Leave only vif-specific deinit stuff in remove_interface(). Move the global deinit (including power_off) to stop(). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 157 +++++++++++++++-------------- 1 file changed, 83 insertions(+), 74 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index abe5ef8807ba..e53829aab92e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1803,7 +1803,83 @@ static int wl1271_op_start(struct ieee80211_hw *hw) static void wl1271_op_stop(struct ieee80211_hw *hw) { + struct wl1271 *wl = hw->priv; + int i; + wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); + + mutex_lock(&wl_list_mutex); + list_del(&wl->list); + + /* + * this must be before the cancel_work calls below, so that the work + * functions don't perform further work. + */ + wl->state = WL1271_STATE_OFF; + mutex_unlock(&wl_list_mutex); + + wl1271_disable_interrupts(wl); + wl1271_flush_deferred_work(wl); + cancel_delayed_work_sync(&wl->scan_complete_work); + cancel_work_sync(&wl->netstack_work); + cancel_work_sync(&wl->tx_work); + del_timer_sync(&wl->rx_streaming_timer); + cancel_work_sync(&wl->rx_streaming_enable_work); + cancel_work_sync(&wl->rx_streaming_disable_work); + cancel_delayed_work_sync(&wl->elp_work); + + /* let's notify MAC80211 about the remaining pending TX frames */ + wl12xx_tx_reset(wl, true); + mutex_lock(&wl->mutex); + + wl1271_power_off(wl); + + wl->band = IEEE80211_BAND_2GHZ; + + wl->rx_counter = 0; + wl->power_level = WL1271_DEFAULT_POWER_LEVEL; + wl->tx_blocks_available = 0; + wl->tx_allocated_blocks = 0; + wl->tx_results_count = 0; + wl->tx_packets_count = 0; + wl->time_offset = 0; + wl->vif = NULL; + wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; + wl->ap_fw_ps_map = 0; + wl->ap_ps_map = 0; + wl->sched_scanning = false; + memset(wl->roles_map, 0, sizeof(wl->roles_map)); + memset(wl->links_map, 0, sizeof(wl->links_map)); + memset(wl->roc_map, 0, sizeof(wl->roc_map)); + wl->active_sta_count = 0; + + /* The system link is always allocated */ + __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); + + /* + * this is performed after the cancel_work calls and the associated + * mutex_lock, so that wl1271_op_add_interface does not accidentally + * get executed before all these vars have been reset. + */ + wl->flags = 0; + + wl->tx_blocks_freed = 0; + + for (i = 0; i < NUM_TX_QUEUES; i++) { + wl->tx_pkts_freed[i] = 0; + wl->tx_allocated_pkts[i] = 0; + } + + wl1271_debugfs_reset(wl); + + kfree(wl->fw_status); + wl->fw_status = NULL; + kfree(wl->tx_res_if); + wl->tx_res_if = NULL; + kfree(wl->target_mem_map); + wl->target_mem_map = NULL; + + mutex_unlock(&wl->mutex); } static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) @@ -2053,7 +2129,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, bool reset_tx_queues) { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - int ret, i; + int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); @@ -2063,15 +2139,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl1271_info("down"); - mutex_lock(&wl_list_mutex); - list_del(&wl->list); - mutex_unlock(&wl_list_mutex); - /* enable dyn ps just in case (if left on due to fw crash etc) */ if (wlvif->bss_type == BSS_TYPE_STA_BSS) - ieee80211_enable_dyn_ps(wl->vif); + ieee80211_enable_dyn_ps(vif); - if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { + if (wl->scan.state != WL1271_SCAN_STATE_IDLE && + wl->scan_vif == vif) { wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan_vif = NULL; @@ -2104,82 +2177,18 @@ deinit: wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; - /* - * this must be before the cancel_work calls below, so that the work - * functions don't perform further work. - */ - wl->state = WL1271_STATE_OFF; - - mutex_unlock(&wl->mutex); - - wl1271_disable_interrupts(wl); - wl1271_flush_deferred_work(wl); - cancel_delayed_work_sync(&wl->scan_complete_work); - cancel_work_sync(&wl->netstack_work); - cancel_work_sync(&wl->tx_work); - del_timer_sync(&wl->rx_streaming_timer); - cancel_work_sync(&wl->rx_streaming_enable_work); - cancel_work_sync(&wl->rx_streaming_disable_work); - cancel_delayed_work_sync(&wlvif->pspoll_work); - cancel_delayed_work_sync(&wl->elp_work); - - mutex_lock(&wl->mutex); - - /* let's notify MAC80211 about the remaining pending TX frames */ wl12xx_tx_reset_wlvif(wl, wlvif); - wl12xx_tx_reset(wl, reset_tx_queues); - wl1271_power_off(wl); - - wl->band = IEEE80211_BAND_2GHZ; - - wl->rx_counter = 0; - wl->power_level = WL1271_DEFAULT_POWER_LEVEL; - wl->tx_blocks_available = 0; - wl->tx_allocated_blocks = 0; - wl->tx_results_count = 0; - wl->tx_packets_count = 0; - wl->time_offset = 0; wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; - wl->vif = NULL; - wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl1271_free_ap_keys(wl, wlvif); memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map)); - wl->ap_fw_ps_map = 0; - wl->ap_ps_map = 0; - wl->sched_scanning = false; wlvif->role_id = WL12XX_INVALID_ROLE_ID; wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; - memset(wl->roles_map, 0, sizeof(wl->roles_map)); - memset(wl->links_map, 0, sizeof(wl->links_map)); - memset(wl->roc_map, 0, sizeof(wl->roc_map)); - wl->active_sta_count = 0; - /* The system link is always allocated */ - __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); + mutex_unlock(&wl->mutex); + cancel_delayed_work_sync(&wlvif->pspoll_work); - /* - * this is performed after the cancel_work calls and the associated - * mutex_lock, so that wl1271_op_add_interface does not accidentally - * get executed before all these vars have been reset. - */ - wl->flags = 0; - - wl->tx_blocks_freed = 0; - - for (i = 0; i < NUM_TX_QUEUES; i++) { - wl->tx_pkts_freed[i] = 0; - wl->tx_allocated_pkts[i] = 0; - } - - wl1271_debugfs_reset(wl); - - kfree(wl->fw_status); - wl->fw_status = NULL; - kfree(wl->tx_res_if); - wl->tx_res_if = NULL; - kfree(wl->target_mem_map); - wl->target_mem_map = NULL; + mutex_lock(&wl->mutex); } static void wl1271_op_remove_interface(struct ieee80211_hw *hw, From 83587505a2b63bb434f76b26a22f48283b86a467 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:53 +0200 Subject: [PATCH 33/97] wl12xx: move bitrate_masks into wlvif move bitrate_masks into the per-interface data, rather than being global. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 13 ++++++++----- drivers/net/wireless/wl12xx/cmd.h | 3 ++- drivers/net/wireless/wl12xx/main.c | 16 ++++++++-------- drivers/net/wireless/wl12xx/scan.c | 21 +++++++++++---------- drivers/net/wireless/wl12xx/wl12xx.h | 3 +-- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 102a8a5371e4..ff653e8832a8 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1111,15 +1111,16 @@ out: return ret; } -int wl1271_cmd_build_probe_req(struct wl1271 *wl, +int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 band) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct sk_buff *skb; int ret; u32 rate; - skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, + skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, ie, ie_len); if (!skb) { ret = -ENOMEM; @@ -1128,7 +1129,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); + rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); if (band == IEEE80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, skb->data, skb->len, 0, rate); @@ -1142,19 +1143,21 @@ out: } struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, + struct wl12xx_vif *wlvif, struct sk_buff *skb) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); int ret; u32 rate; if (!skb) - skb = ieee80211_ap_probereq_get(wl->hw, wl->vif); + skb = ieee80211_ap_probereq_get(wl->hw, vif); if (!skb) goto out; wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[wl->band]); + rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wl->band]); if (wl->band == IEEE80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, skb->data, skb->len, 0, rate); diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index d2670d379b75..8182cf1b4861 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -59,10 +59,11 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 aid); -int wl1271_cmd_build_probe_req(struct wl1271 *wl, +int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 band); struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, + struct wl12xx_vif *wlvif, struct sk_buff *skb); int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, __be32 ip_addr); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index e53829aab92e..acfc49743d22 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1906,7 +1906,7 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) return WL12XX_INVALID_ROLE_TYPE; } -static int wl12xx_init_vif_data(struct ieee80211_vif *vif) +static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); @@ -1949,6 +1949,8 @@ static int wl12xx_init_vif_data(struct ieee80211_vif *vif) wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; } + wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; + wlvif->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; @@ -2058,7 +2060,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } - ret = wl12xx_init_vif_data(vif); + ret = wl12xx_init_vif_data(wl, vif); if (ret < 0) goto out; @@ -2178,8 +2180,6 @@ deinit: wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; wl12xx_tx_reset_wlvif(wl, wlvif); - wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; - wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; wl1271_free_ap_keys(wl, wlvif); memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map)); wlvif->role_id = WL12XX_INVALID_ROLE_ID; @@ -2293,7 +2293,7 @@ out: static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif) { - wlvif->basic_rate_set = wl->bitrate_masks[wl->band]; + wlvif->basic_rate_set = wlvif->bitrate_masks[wl->band]; wlvif->rate_set = wlvif->basic_rate_set; } @@ -3578,6 +3578,7 @@ sta_not_found: */ dev_kfree_skb(wlvif->probereq); wlvif->probereq = wl1271_cmd_build_ap_probe_req(wl, + wlvif, NULL); ieoffset = offsetof(struct ieee80211_mgmt, u.probe_req.variable); @@ -4202,6 +4203,7 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271 *wl = hw->priv; int i; @@ -4212,7 +4214,7 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); for (i = 0; i < IEEE80211_NUM_BANDS; i++) - wl->bitrate_masks[i] = + wlvif->bitrate_masks[i] = wl1271_tx_enabled_rates_get(wl, mask->control[i].legacy, i); @@ -4931,8 +4933,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) /* Apply default driver configuration. */ wl1271_conf_init(wl); - wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; - wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; order = get_order(WL1271_AGGR_BUFFER_SIZE); wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 9372136b27e4..e1a8ce092e39 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -66,7 +66,7 @@ void wl1271_scan_complete_work(struct work_struct *work) if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { /* restore hardware connection monitoring template */ - wl1271_cmd_build_ap_probe_req(wl, wlvif->probereq); + wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq); } /* return to ROC if needed */ @@ -218,9 +218,9 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, memcpy(cmd->addr, vif->addr, ETH_ALEN); - ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len, - wl->scan.req->ie, wl->scan.req->ie_len, - band); + ret = wl1271_cmd_build_probe_req(wl, wlvif, wl->scan.ssid, + wl->scan.ssid_len, wl->scan.req->ie, + wl->scan.req->ie_len, band); if (ret < 0) { wl1271_error("PROBE request template failed"); goto out; @@ -251,6 +251,7 @@ out: void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) { + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret = 0; enum ieee80211_band band; u32 rate; @@ -261,7 +262,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) case WL1271_SCAN_STATE_2GHZ_ACTIVE: band = IEEE80211_BAND_2GHZ; - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); + rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); ret = wl1271_scan_send(wl, vif, band, false, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; @@ -272,7 +273,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) case WL1271_SCAN_STATE_2GHZ_PASSIVE: band = IEEE80211_BAND_2GHZ; - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); + rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); ret = wl1271_scan_send(wl, vif, band, true, rate); if (ret == WL1271_NOTHING_TO_SCAN) { if (wl->enable_11a) @@ -286,7 +287,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) case WL1271_SCAN_STATE_5GHZ_ACTIVE: band = IEEE80211_BAND_5GHZ; - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); + rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); ret = wl1271_scan_send(wl, vif, band, false, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; @@ -297,7 +298,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) case WL1271_SCAN_STATE_5GHZ_PASSIVE: band = IEEE80211_BAND_5GHZ; - rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); + rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); ret = wl1271_scan_send(wl, vif, band, true, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_DONE; @@ -642,7 +643,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, } if (!force_passive && cfg->active[0]) { - ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, + ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid, req->ssids[0].ssid_len, ies->ie[IEEE80211_BAND_2GHZ], ies->len[IEEE80211_BAND_2GHZ], @@ -654,7 +655,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, } if (!force_passive && cfg->active[1]) { - ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, + ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid, req->ssids[0].ssid_len, ies->ie[IEEE80211_BAND_5GHZ], ies->len[IEEE80211_BAND_5GHZ], diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 4802f685de63..33ccdf84c432 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -484,8 +484,6 @@ struct wl1271 { bool sched_scanning; - u32 bitrate_masks[IEEE80211_NUM_BANDS]; - /* The current band */ enum ieee80211_band band; @@ -600,6 +598,7 @@ struct wl12xx_vif { u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 ssid_len; + u32 bitrate_masks[IEEE80211_NUM_BANDS]; u32 basic_rate_set; /* From 87627214738fcfd44803e90193f9f2f4583ce68b Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:54 +0200 Subject: [PATCH 34/97] wl12xx: add vifs list keep a list of all the vifs associated with our hw. it will be later used in order to iterate through vifs. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 4 ++++ drivers/net/wireless/wl12xx/wl12xx.h | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index acfc49743d22..56d592398677 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1957,6 +1957,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work); + INIT_LIST_HEAD(&wlvif->list); return 0; } @@ -2114,6 +2115,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; wl->vif = vif; + list_add(&wlvif->list, &wl->wlvif_list); set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); out: mutex_unlock(&wl->mutex); @@ -2181,6 +2183,7 @@ deinit: wl12xx_tx_reset_wlvif(wl, wlvif); wl1271_free_ap_keys(wl, wlvif); + list_del(&wlvif->list); memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map)); wlvif->role_id = WL12XX_INVALID_ROLE_ID; wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; @@ -4869,6 +4872,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) memset(wl, 0, sizeof(*wl)); INIT_LIST_HEAD(&wl->list); + INIT_LIST_HEAD(&wl->wlvif_list); wl->hw = hw; wl->plat_dev = plat_dev; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 33ccdf84c432..55561c597ad9 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -394,6 +394,8 @@ struct wl1271 { unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; + struct list_head wlvif_list; + struct wl1271_acx_mem_map *target_mem_map; /* Accounting for allocated / available TX blocks on HW */ @@ -564,6 +566,7 @@ struct wl1271_station { struct wl12xx_vif { struct wl1271 *wl; + struct list_head list; u8 bss_type; u8 p2p; /* we are using p2p role */ u8 role_id; @@ -653,6 +656,9 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif) return container_of((void *)wlvif, struct ieee80211_vif, drv_priv); } +#define wl12xx_for_each_wlvif(wl, wlvif) \ + list_for_each_entry(wlvif, &wl->wlvif_list, list) + int wl1271_plt_start(struct wl1271 *wl); int wl1271_plt_stop(struct wl1271 *wl); int wl1271_recalc_rx_streaming(struct wl1271 *wl); From a32d0cdfcb7e5d41f210e13cbc78dc86a5a85a08 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:55 +0200 Subject: [PATCH 35/97] wl12xx: support multiple vifs in the tx path Pass the wlvif associated with each skb as param. Note that dummy packet doesn't belong to any particular vif, so we pass NULL in this case. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 6 +-- drivers/net/wireless/wl12xx/tx.c | 79 ++++++++++++++++++------------ drivers/net/wireless/wl12xx/tx.h | 2 +- 3 files changed, 52 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 56d592398677..0623f5dc02ca 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -993,7 +993,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie) * In order to avoid starvation of the TX path, * call the work function directly. */ - wl1271_tx_work_locked(wl, wl->vif); + wl1271_tx_work_locked(wl); } else { spin_unlock_irqrestore(&wl->wl_lock, flags); } @@ -1537,7 +1537,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl) /* The FW is low on RX memory blocks, so send the dummy packet asap */ if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) - wl1271_tx_work_locked(wl, wl->vif); + wl1271_tx_work_locked(wl); /* * If the FW TX is busy, TX work will be scheduled by the threaded @@ -2413,7 +2413,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) ((wl->band != conf->channel->band) || (wl->channel != channel))) { /* send all pending packets */ - wl1271_tx_work_locked(wl, vif); + wl1271_tx_work_locked(wl); wl->band = conf->channel->band; wl->channel = channel; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 6c0135b27820..c7be15186c4a 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -210,17 +210,17 @@ static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, return ALIGN(packet_length, WL1271_TX_ALIGN_TO); } -static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif, +static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct sk_buff *skb, u32 extra, u32 buf_offset, u8 hlid) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271_tx_hw_descr *desc; u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; u32 len; u32 total_blocks; int id, ret = -EBUSY, ac; u32 spare_blocks = wl->tx_spare_blocks; + bool is_dummy = false; if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) return -EAGAIN; @@ -235,8 +235,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif, len = wl12xx_calc_packet_alignment(wl, total_len); /* in case of a dummy packet, use default amount of spare mem blocks */ - if (unlikely(wl12xx_is_dummy_packet(wl, skb))) + if (unlikely(wl12xx_is_dummy_packet(wl, skb))) { + is_dummy = true; spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; + } total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE + spare_blocks; @@ -261,7 +263,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif, ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); wl->tx_allocated_pkts[ac]++; - if (wlvif->bss_type == BSS_TYPE_AP_BSS && + if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS && test_bit(hlid, wlvif->ap.sta_hlid_map)) wl->links[hlid].allocated_pkts++; @@ -277,16 +279,16 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif, return ret; } -static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif, +static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct sk_buff *skb, u32 extra, struct ieee80211_tx_info *control, u8 hlid) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct timespec ts; struct wl1271_tx_hw_descr *desc; int aligned_len, ac, rate_idx; s64 hosttime; u16 tx_attr; + bool is_dummy; desc = (struct wl1271_tx_hw_descr *) skb->data; @@ -303,7 +305,8 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif, hosttime = (timespec_to_ns(&ts) >> 10); desc->start_time = cpu_to_le32(hosttime - wl->time_offset); - if (wlvif->bss_type != BSS_TYPE_AP_BSS) + is_dummy = wl12xx_is_dummy_packet(wl, skb); + if (is_dummy || wlvif->bss_type != BSS_TYPE_AP_BSS) desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); else desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU); @@ -312,7 +315,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif, ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); desc->tid = skb->priority; - if (wl12xx_is_dummy_packet(wl, skb)) { + if (is_dummy) { /* * FW expects the dummy packet to have an invalid session id - * any session id that is different than the one set in the join @@ -329,7 +332,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif, } desc->hlid = hlid; - if (wlvif->bss_type != BSS_TYPE_AP_BSS) { + if (is_dummy) + rate_idx = 0; + else if (wlvif->bss_type != BSS_TYPE_AP_BSS) { /* if the packets are destined for AP (have a STA entry) send them with AP rate policies, otherwise use default basic rates */ @@ -383,12 +388,10 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct ieee80211_vif *vif, } /* caller must hold wl->mutex */ -static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, - u32 buf_offset) +static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, + struct sk_buff *skb, u32 buf_offset) { struct ieee80211_tx_info *info; - struct ieee80211_vif *vif; - struct wl12xx_vif *wlvif; u32 extra = 0; int ret = 0; u32 total_len; @@ -402,11 +405,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, /* TODO: handle dummy packets on multi-vifs */ is_dummy = wl12xx_is_dummy_packet(wl, skb); - if (is_dummy) - info->control.vif = wl->vif; - - vif = info->control.vif; - wlvif = wl12xx_vif_to_data(vif); if (info->control.hw_key && info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) @@ -433,13 +431,13 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, return -EINVAL; } - ret = wl1271_tx_allocate(wl, vif, skb, extra, buf_offset, hlid); + ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid); if (ret < 0) return ret; - wl1271_tx_fill_hdr(wl, vif, skb, extra, info, hlid); + wl1271_tx_fill_hdr(wl, wlvif, skb, extra, info, hlid); - if (wlvif->bss_type == BSS_TYPE_AP_BSS && !is_dummy) { + if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS) { wl1271_tx_ap_update_inconnection_sta(wl, skb); wl1271_tx_regulate_link(wl, wlvif, hlid); } @@ -589,13 +587,19 @@ static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl, return skb; } -static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) { unsigned long flags; + struct wl12xx_vif *wlvif; struct sk_buff *skb = NULL; - skb = wl12xx_vif_skb_dequeue(wl, wlvif); + /* TODO: rememeber last vif and consider it */ + wl12xx_for_each_wlvif(wl, wlvif) { + skb = wl12xx_vif_skb_dequeue(wl, wlvif); + if (skb) + break; + } + if (!skb && test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { int q; @@ -639,24 +643,35 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb) return ieee80211_is_data_present(hdr->frame_control); } -void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif) +void wl1271_tx_work_locked(struct wl1271 *wl) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct wl12xx_vif *wlvif; struct sk_buff *skb; u32 buf_offset = 0; bool sent_packets = false; bool had_data = false; - bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); + /* TODO: save bitmap of relevant stations */ + bool is_sta = false; int ret; if (unlikely(wl->state == WL1271_STATE_OFF)) return; - while ((skb = wl1271_skb_dequeue(wl, wlvif))) { + while ((skb = wl1271_skb_dequeue(wl))) { + wlvif = NULL; + if (!wl12xx_is_dummy_packet(wl, skb)) { + struct ieee80211_tx_info *info; + struct ieee80211_vif *vif; + + info = IEEE80211_SKB_CB(skb); + vif = info->control.vif; + wlvif = wl12xx_vif_to_data(vif); + } + if (wl1271_tx_is_data_present(skb)) had_data = true; - ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); + ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset); if (ret == -EAGAIN) { /* * Aggregation buffer is full. @@ -683,6 +698,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif) } buf_offset += ret; wl->tx_packets_count++; + if (wlvif && wlvif->bss_type == BSS_TYPE_STA_BSS) + is_sta = true; } out_ack: @@ -702,7 +719,7 @@ out_ack: wl1271_handle_tx_low_watermark(wl); } - if (!is_ap && wl->conf.rx_streaming.interval && had_data && + if (is_sta && wl->conf.rx_streaming.interval && had_data && (wl->conf.rx_streaming.always || test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { u32 timeout = wl->conf.rx_streaming.duration; @@ -727,7 +744,7 @@ void wl1271_tx_work(struct work_struct *work) if (ret < 0) goto out; - wl1271_tx_work_locked(wl, wl->vif); + wl1271_tx_work_locked(wl); wl1271_ps_elp_sleep(wl); out: diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 050a04792600..fe29ff524e9a 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -204,7 +204,7 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) } void wl1271_tx_work(struct work_struct *work); -void wl1271_tx_work_locked(struct wl1271 *wl, struct ieee80211_vif *vif); +void wl1271_tx_work_locked(struct wl1271 *wl); void wl1271_tx_complete(struct wl1271 *wl); void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues); From a4e4130dcea01f3e0dfcbfeaf0d815b971e6e515 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 11 Oct 2011 11:49:15 +0200 Subject: [PATCH 36/97] wl12xx: configure sleep_policy according to active roles If there is an active AP role, stay always on. Otherwise, allow chip to enter elp. (Note that this is a global configuration, so if the device is already configured according to our policy, we don't have to configure it again) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/init.c | 29 +++++++++++++++++----------- drivers/net/wireless/wl12xx/main.c | 10 ++++++++++ drivers/net/wireless/wl12xx/wl12xx.h | 2 ++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 80e89e319879..4af7e2fb52fd 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -343,11 +343,6 @@ static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (ret < 0) return ret; - /* Configure for ELP power saving */ - ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); - if (ret < 0) - return ret; - ret = wl1271_acx_sta_rate_policies(wl, wlvif); if (ret < 0) return ret; @@ -382,11 +377,6 @@ static int wl1271_ap_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret; - /* Configure for power always on */ - ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); - if (ret < 0) - return ret; - ret = wl1271_init_ap_rates(wl, wlvif); if (ret < 0) return ret; @@ -577,9 +567,26 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) struct conf_tx_ac_category *conf_ac; struct conf_tx_tid *conf_tid; bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); - int ret, i; + /* + * consider all existing roles before configuring psm. + * TODO: reconfigure on interface removal. + */ + if (!wl->ap_count) { + if (is_ap) { + /* Configure for power always on */ + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); + if (ret < 0) + return ret; + } else if (!wl->sta_count) { + /* Configure for ELP power saving */ + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); + if (ret < 0) + return ret; + } + } + /* Mode specific init */ if (is_ap) { ret = wl1271_ap_hw_init(wl, wlvif); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0623f5dc02ca..b52deac368f4 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2117,6 +2117,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, wl->vif = vif; list_add(&wlvif->list, &wl->wlvif_list); set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); + + if (wlvif->bss_type == BSS_TYPE_AP_BSS) + wl->ap_count++; + else + wl->sta_count++; out: mutex_unlock(&wl->mutex); @@ -2188,6 +2193,11 @@ deinit: wlvif->role_id = WL12XX_INVALID_ROLE_ID; wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; + if (wlvif->bss_type == BSS_TYPE_AP_BSS) + wl->ap_count--; + else + wl->sta_count--; + mutex_unlock(&wl->mutex); cancel_delayed_work_sync(&wlvif->pspoll_work); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 55561c597ad9..fd78f8c1ebcc 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -395,6 +395,8 @@ struct wl1271 { unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; struct list_head wlvif_list; + u8 sta_count; + u8 ap_count; struct wl1271_acx_mem_map *target_mem_map; From 4b730b6a814fe52425d90ff3db3d8deefb22fb24 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:57 +0200 Subject: [PATCH 37/97] wl12xx: make event handling support multirole Some events don't indicate the role they are intended for. In these cases, iterate through all the relevant vifs, and pass the event to each one of them. This is only a workaround. future fw releases should indicate the relevant role_id for such events. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 121 ++++++++++++++++++--------- drivers/net/wireless/wl12xx/wl12xx.h | 10 +++ 2 files changed, 91 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 486c8ee0101a..dbc40bb49bcd 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -162,10 +162,10 @@ static int wl1271_event_ps_report(struct wl1271 *wl, } static void wl1271_event_rssi_trigger(struct wl1271 *wl, - struct ieee80211_vif *vif, + struct wl12xx_vif *wlvif, struct event_mailbox *mbox) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); enum nl80211_cqm_rssi_threshold_event event; s8 metric = mbox->rssi_snr_trigger_metric[0]; @@ -183,11 +183,13 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl, static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + if (wlvif->bss_type != BSS_TYPE_AP_BSS) { if (!wlvif->sta.ba_rx_bitmap) return; - ieee80211_stop_rx_ba_session(wl->vif, wlvif->sta.ba_rx_bitmap, - wl->vif->bss_conf.bssid); + ieee80211_stop_rx_ba_session(vif, wlvif->sta.ba_rx_bitmap, + vif->bss_conf.bssid); } else { u8 hlid; struct wl1271_link *lnk; @@ -197,7 +199,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (!lnk->ba_bitmap) continue; - ieee80211_stop_rx_ba_session(wl->vif, + ieee80211_stop_rx_ba_session(vif, lnk->ba_bitmap, lnk->addr); } @@ -207,12 +209,21 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, u8 enable) { + struct ieee80211_vif *vif; + struct wl12xx_vif *wlvif; + if (enable) { /* disable dynamic PS when requested by the firmware */ - ieee80211_disable_dyn_ps(wl->vif); + wl12xx_for_each_wlvif_sta(wl, wlvif) { + vif = wl12xx_wlvif_to_vif(wlvif); + ieee80211_disable_dyn_ps(vif); + } set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); } else { - ieee80211_enable_dyn_ps(wl->vif); + wl12xx_for_each_wlvif_sta(wl, wlvif) { + vif = wl12xx_wlvif_to_vif(wlvif); + ieee80211_enable_dyn_ps(vif); + } clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); wl1271_recalc_rx_streaming(wl); } @@ -228,12 +239,11 @@ static void wl1271_event_mbox_dump(struct event_mailbox *mbox) static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) { - struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct ieee80211_vif *vif; + struct wl12xx_vif *wlvif; int ret; u32 vector; bool beacon_loss = false; - bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); bool disconnect_sta = false; unsigned long sta_bitmap = 0; @@ -266,8 +276,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) } } - if (vector & SOFT_GEMINI_SENSE_EVENT_ID && - wlvif->bss_type == BSS_TYPE_STA_BSS) + if (vector & SOFT_GEMINI_SENSE_EVENT_ID) wl12xx_event_soft_gemini_sense(wl, mbox->soft_gemini_sense_info); @@ -280,40 +289,54 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. * */ - if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) { + if (vector & BSS_LOSE_EVENT_ID) { + /* TODO: check for multi-role */ wl1271_info("Beacon loss detected."); /* indicate to the stack, that beacons have been lost */ beacon_loss = true; } - if ((vector & PS_REPORT_EVENT_ID) && !is_ap) { + if (vector & PS_REPORT_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); - ret = wl1271_event_ps_report(wl, wlvif, mbox, &beacon_loss); - if (ret < 0) - return ret; + wl12xx_for_each_wlvif_sta(wl, wlvif) { + ret = wl1271_event_ps_report(wl, wlvif, + mbox, &beacon_loss); + if (ret < 0) + return ret; + } } - if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap) - wl1271_event_pspoll_delivery_fail(wl, wlvif); + if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) + wl12xx_for_each_wlvif_sta(wl, wlvif) { + wl1271_event_pspoll_delivery_fail(wl, wlvif); + } if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { + /* TODO: check actual multi-role support */ wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); - if (wl->vif) - wl1271_event_rssi_trigger(wl, vif, mbox); + wl12xx_for_each_wlvif_sta(wl, wlvif) { + wl1271_event_rssi_trigger(wl, wlvif, mbox); + } } - if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) { + if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) { + u8 role_id = mbox->role_id; wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " - "ba_allowed = 0x%x", mbox->rx_ba_allowed); + "ba_allowed = 0x%x, role_id=%d", + mbox->rx_ba_allowed, role_id); - wlvif->ba_allowed = !!mbox->rx_ba_allowed; + wl12xx_for_each_wlvif(wl, wlvif) { + if (role_id != 0xff && role_id != wlvif->role_id) + continue; - if (wl->vif && !wlvif->ba_allowed) - wl1271_stop_ba_event(wl, wlvif); + wlvif->ba_allowed = !!mbox->rx_ba_allowed; + if (!wlvif->ba_allowed) + wl1271_stop_ba_event(wl, wlvif); + } } - if ((vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) && !is_ap) { + if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. " "status = 0x%x", mbox->channel_switch_status); @@ -322,48 +345,63 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) * 1) channel switch complete with status=0 * 2) channel switch failed status=1 */ - if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags) && - (wl->vif)) - ieee80211_chswitch_done(wl->vif, - mbox->channel_switch_status ? false : true); + if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) { + /* TODO: configure only the relevant vif */ + wl12xx_for_each_wlvif_sta(wl, wlvif) { + struct ieee80211_vif *vif = + wl12xx_wlvif_to_vif(wlvif); + bool success = mbox->channel_switch_status ? + false : true; + + ieee80211_chswitch_done(vif, success); + } + } } if ((vector & DUMMY_PACKET_EVENT_ID)) { wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); - if (wl->vif) - wl1271_tx_dummy_packet(wl); + wl1271_tx_dummy_packet(wl); } /* * "TX retries exceeded" has a different meaning according to mode. * In AP mode the offending station is disconnected. */ - if ((vector & MAX_TX_RETRY_EVENT_ID) && is_ap) { + if (vector & MAX_TX_RETRY_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); disconnect_sta = true; } - if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { + if (vector & INACTIVE_STA_EVENT_ID) { wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); disconnect_sta = true; } - if (is_ap && disconnect_sta) { + if (disconnect_sta) { u32 num_packets = wl->conf.tx.max_tx_retries; struct ieee80211_sta *sta; const u8 *addr; int h; for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) { - if (!test_bit(h, wlvif->ap.sta_hlid_map)) + bool found = false; + /* find the ap vif connected to this sta */ + wl12xx_for_each_wlvif_ap(wl, wlvif) { + if (!test_bit(h, wlvif->ap.sta_hlid_map)) + continue; + found = true; + break; + } + if (!found) continue; + vif = wl12xx_wlvif_to_vif(wlvif); addr = wl->links[h].addr; rcu_read_lock(); - sta = ieee80211_find_sta(wl->vif, addr); + sta = ieee80211_find_sta(vif, addr); if (sta) { wl1271_debug(DEBUG_EVENT, "remove sta %d", h); ieee80211_report_low_ack(sta, num_packets); @@ -372,8 +410,11 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) } } - if (wl->vif && beacon_loss) - ieee80211_connection_loss(wl->vif); + if (beacon_loss) + wl12xx_for_each_wlvif_sta(wl, wlvif) { + vif = wl12xx_wlvif_to_vif(wlvif); + ieee80211_connection_loss(vif); + } return 0; } diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index fd78f8c1ebcc..de9a2b639403 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -661,6 +661,16 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif) #define wl12xx_for_each_wlvif(wl, wlvif) \ list_for_each_entry(wlvif, &wl->wlvif_list, list) +#define wl12xx_for_each_wlvif_bss_type(wl, wlvif, _bss_type) \ + wl12xx_for_each_wlvif(wl, wlvif) \ + if (wlvif->bss_type == _bss_type) + +#define wl12xx_for_each_wlvif_sta(wl, wlvif) \ + wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_STA_BSS) + +#define wl12xx_for_each_wlvif_ap(wl, wlvif) \ + wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_AP_BSS) + int wl1271_plt_start(struct wl1271 *wl); int wl1271_plt_stop(struct wl1271 *wl); int wl1271_recalc_rx_streaming(struct wl1271 *wl); From 48e93e402ad19f570bae323b07911bdf6562af8e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:58 +0200 Subject: [PATCH 38/97] wl12xx: move tx_security_seq into wlvif The last security seq num has to be saved across reconfigs. Add a new "persistent" struct into wlvif, which won't get deleted on wl12xx_init_vif_data() Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 1 - drivers/net/wireless/wl12xx/main.c | 32 ++++++++++++++------------- drivers/net/wireless/wl12xx/tx.c | 12 +++++++--- drivers/net/wireless/wl12xx/wl12xx.h | 30 ++++++++++++++++--------- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index bbc8004edf40..669b081848e8 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -346,7 +346,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(tx_results_count); DRIVER_STATE_PRINT_LHEX(flags); DRIVER_STATE_PRINT_INT(tx_blocks_freed); - DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb); DRIVER_STATE_PRINT_INT(rx_counter); DRIVER_STATE_PRINT_INT(state); DRIVER_STATE_PRINT_INT(channel); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index b52deac368f4..8d87df53bbec 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1206,6 +1206,7 @@ static void wl1271_recovery_work(struct work_struct *work) { struct wl1271 *wl = container_of(work, struct wl1271, recovery_work); + struct wl12xx_vif *wlvif; mutex_lock(&wl->mutex); @@ -1227,9 +1228,12 @@ static void wl1271_recovery_work(struct work_struct *work) * in the firmware during recovery. This doens't hurt if the network is * not encrypted. */ - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || - test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) - wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING; + wl12xx_for_each_wlvif(wl, wlvif) { + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || + test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) + wlvif->tx_security_seq += + WL1271_TX_SQN_POST_RECOVERY_PADDING; + } /* Prevent spurious TX during FW restart */ ieee80211_stop_queues(wl->hw); @@ -1910,8 +1914,8 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - /* make sure wlvif is zeroed */ - memset(wlvif, 0, sizeof(*wlvif)); + /* clear everything but the persistent data */ + memset(wlvif, 0, offsetof(struct wl12xx_vif, persistent)); switch (ieee80211_vif_type_p2p(vif)) { case NL80211_IFTYPE_P2P_CLIENT: @@ -2297,8 +2301,8 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; /* reset TX security counters on a clean disconnect */ - wl->tx_security_last_seq_lsb = 0; - wl->tx_security_seq = 0; + wlvif->tx_security_last_seq_lsb = 0; + wlvif->tx_security_seq = 0; out: return ret; @@ -2870,20 +2874,20 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, key_type = KEY_TKIP; key_conf->hw_key_idx = key_conf->keyidx; - tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); - tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); + tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); + tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); break; case WLAN_CIPHER_SUITE_CCMP: key_type = KEY_AES; key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); - tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); + tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); + tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); break; case WL1271_CIPHER_SUITE_GEM: key_type = KEY_GEM; - tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); - tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); + tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); + tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); break; default: wl1271_error("Unknown key algo 0x%x", key_conf->cipher); @@ -4923,8 +4927,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->quirks = 0; wl->platform_quirks = 0; wl->sched_scanning = false; - wl->tx_security_seq = 0; - wl->tx_security_last_seq_lsb = 0; wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl->system_hlid = WL12XX_SYSTEM_HLID; wl->active_sta_count = 0; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index c7be15186c4a..8c35d37ba600 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -755,6 +755,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, struct wl1271_tx_hw_res_descr *result) { struct ieee80211_tx_info *info; + struct ieee80211_vif *vif; + struct wl12xx_vif *wlvif; struct sk_buff *skb; int id = result->id; int rate = -1; @@ -774,6 +776,10 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, return; } + /* info->control is valid as long as we don't update info->status */ + vif = info->control.vif; + wlvif = wl12xx_vif_to_data(vif); + /* update the TX status info */ if (result->status == TX_SUCCESS) { if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) @@ -801,14 +807,14 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP || info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) { u8 fw_lsb = result->tx_security_sequence_number_lsb; - u8 cur_lsb = wl->tx_security_last_seq_lsb; + u8 cur_lsb = wlvif->tx_security_last_seq_lsb; /* * update security sequence number, taking care of potential * wrap-around */ - wl->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256; - wl->tx_security_last_seq_lsb = fw_lsb; + wlvif->tx_security_seq += (fw_lsb - cur_lsb) & 0xff; + wlvif->tx_security_last_seq_lsb = fw_lsb; } /* remove private header from packet */ diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index de9a2b639403..d58488598d11 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -437,17 +437,6 @@ struct wl1271 { struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; int tx_frames_cnt; - /* - * Security sequence number - * bits 0-15: lower 16 bits part of sequence number - * bits 16-47: higher 32 bits part of sequence number - * bits 48-63: not in use - */ - u64 tx_security_seq; - - /* 8 bits of the last sequence number in use */ - u8 tx_security_last_seq_lsb; - /* FW Rx counter */ u32 rx_counter; @@ -645,6 +634,25 @@ struct wl12xx_vif { /* RX BA constraint value */ bool ba_support; bool ba_allowed; + + /* + * This struct must be last! + * data that has to be saved acrossed reconfigs (e.g. recovery) + * should be declared in this struct. + */ + struct { + u8 persistent[0]; + /* + * Security sequence number + * bits 0-15: lower 16 bits part of sequence number + * bits 16-47: higher 32 bits part of sequence number + * bits 48-63: not in use + */ + u64 tx_security_seq; + + /* 8 bits of the last sequence number in use */ + u8 tx_security_last_seq_lsb; + }; }; static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) From 9eb599e9c62dcfd4efece1936c385381b366b684 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:59 +0200 Subject: [PATCH 39/97] wl12xx: rearm rx streaming per vif Currently, the rx streaming doesn't support multi-vif (the actual wlvif is taken from wl->vif, and the management is global). Make the rx streaming timers/works per-vif, and pass the the actual vif as param. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 5 +- drivers/net/wireless/wl12xx/acx.h | 3 +- drivers/net/wireless/wl12xx/debugfs.c | 10 +++- drivers/net/wireless/wl12xx/event.c | 4 +- drivers/net/wireless/wl12xx/main.c | 53 +++++++++++---------- drivers/net/wireless/wl12xx/rx.c | 35 ++++++-------- drivers/net/wireless/wl12xx/tx.c | 67 ++++++++++++++++++--------- drivers/net/wireless/wl12xx/tx.h | 1 + drivers/net/wireless/wl12xx/wl12xx.h | 12 ++--- 9 files changed, 109 insertions(+), 81 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 5b70cc19e1d4..21e74ca4ddb2 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -1510,10 +1510,9 @@ out: return ret; } -int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable) +int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable) { - struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271_acx_ps_rx_streaming *rx_streaming; u32 conf_queues, enable_queues; int i, ret = 0; diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 7fccfcc55ca0..c06119b053e3 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -1310,7 +1310,8 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, bool enable, u8 peer_hlid); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); -int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); +int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable); int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 669b081848e8..4abff8274ac3 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -505,6 +505,7 @@ static ssize_t rx_streaming_interval_write(struct file *file, size_t count, loff_t *ppos) { struct wl1271 *wl = file->private_data; + struct wl12xx_vif *wlvif; unsigned long value; int ret; @@ -528,7 +529,9 @@ static ssize_t rx_streaming_interval_write(struct file *file, if (ret < 0) goto out; - wl1271_recalc_rx_streaming(wl); + wl12xx_for_each_wlvif_sta(wl, wlvif) { + wl1271_recalc_rx_streaming(wl, wlvif); + } wl1271_ps_elp_sleep(wl); out: @@ -557,6 +560,7 @@ static ssize_t rx_streaming_always_write(struct file *file, size_t count, loff_t *ppos) { struct wl1271 *wl = file->private_data; + struct wl12xx_vif *wlvif; unsigned long value; int ret; @@ -580,7 +584,9 @@ static ssize_t rx_streaming_always_write(struct file *file, if (ret < 0) goto out; - wl1271_recalc_rx_streaming(wl); + wl12xx_for_each_wlvif_sta(wl, wlvif) { + wl1271_recalc_rx_streaming(wl, wlvif); + } wl1271_ps_elp_sleep(wl); out: diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index dbc40bb49bcd..be9e1121c8f8 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -220,12 +220,12 @@ static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, } set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); } else { + clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); wl12xx_for_each_wlvif_sta(wl, wlvif) { vif = wl12xx_wlvif_to_vif(wlvif); ieee80211_enable_dyn_ps(vif); + wl1271_recalc_rx_streaming(wl, wlvif); } - clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); - wl1271_recalc_rx_streaming(wl); } } diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8d87df53bbec..5ce01f1379a4 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -502,12 +502,13 @@ static int wl1271_reg_notify(struct wiphy *wiphy, return 0; } -static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable) +static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, + bool enable) { int ret = 0; /* we should hold wl->mutex */ - ret = wl1271_acx_ps_rx_streaming(wl, enable); + ret = wl1271_acx_ps_rx_streaming(wl, wlvif, enable); if (ret < 0) goto out; @@ -523,7 +524,7 @@ out: * this function is being called when the rx_streaming interval * has beed changed or rx_streaming should be disabled */ -int wl1271_recalc_rx_streaming(struct wl1271 *wl) +int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret = 0; int period = wl->conf.rx_streaming.interval; @@ -537,11 +538,11 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl) test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) && (wl->conf.rx_streaming.always || test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) - ret = wl1271_set_rx_streaming(wl, true); + ret = wl1271_set_rx_streaming(wl, wlvif, true); else { - ret = wl1271_set_rx_streaming(wl, false); + ret = wl1271_set_rx_streaming(wl, wlvif, false); /* don't cancel_work_sync since we might deadlock */ - del_timer_sync(&wl->rx_streaming_timer); + del_timer_sync(&wlvif->rx_streaming_timer); } out: return ret; @@ -550,8 +551,9 @@ out: static void wl1271_rx_streaming_enable_work(struct work_struct *work) { int ret; - struct wl1271 *wl = - container_of(work, struct wl1271, rx_streaming_enable_work); + struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif, + rx_streaming_enable_work); + struct wl1271 *wl = wlvif->wl; mutex_lock(&wl->mutex); @@ -568,12 +570,12 @@ static void wl1271_rx_streaming_enable_work(struct work_struct *work) if (ret < 0) goto out; - ret = wl1271_set_rx_streaming(wl, true); + ret = wl1271_set_rx_streaming(wl, wlvif, true); if (ret < 0) goto out_sleep; /* stop it after some time of inactivity */ - mod_timer(&wl->rx_streaming_timer, + mod_timer(&wlvif->rx_streaming_timer, jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration)); out_sleep: @@ -585,8 +587,9 @@ out: static void wl1271_rx_streaming_disable_work(struct work_struct *work) { int ret; - struct wl1271 *wl = - container_of(work, struct wl1271, rx_streaming_disable_work); + struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif, + rx_streaming_disable_work); + struct wl1271 *wl = wlvif->wl; mutex_lock(&wl->mutex); @@ -597,7 +600,7 @@ static void wl1271_rx_streaming_disable_work(struct work_struct *work) if (ret < 0) goto out; - ret = wl1271_set_rx_streaming(wl, false); + ret = wl1271_set_rx_streaming(wl, wlvif, false); if (ret) goto out_sleep; @@ -609,8 +612,9 @@ out: static void wl1271_rx_streaming_timer(unsigned long data) { - struct wl1271 *wl = (struct wl1271 *)data; - ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work); + struct wl12xx_vif *wlvif = (struct wl12xx_vif *)data; + struct wl1271 *wl = wlvif->wl; + ieee80211_queue_work(wl->hw, &wlvif->rx_streaming_disable_work); } static void wl1271_conf_init(struct wl1271 *wl) @@ -1827,9 +1831,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) cancel_delayed_work_sync(&wl->scan_complete_work); cancel_work_sync(&wl->netstack_work); cancel_work_sync(&wl->tx_work); - del_timer_sync(&wl->rx_streaming_timer); - cancel_work_sync(&wl->rx_streaming_enable_work); - cancel_work_sync(&wl->rx_streaming_disable_work); cancel_delayed_work_sync(&wl->elp_work); /* let's notify MAC80211 about the remaining pending TX frames */ @@ -1960,9 +1961,16 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; + INIT_WORK(&wlvif->rx_streaming_enable_work, + wl1271_rx_streaming_enable_work); + INIT_WORK(&wlvif->rx_streaming_disable_work, + wl1271_rx_streaming_disable_work); INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work); INIT_LIST_HEAD(&wlvif->list); + setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, + (unsigned long) wlvif); + return 0; } @@ -2203,6 +2211,9 @@ deinit: wl->sta_count--; mutex_unlock(&wl->mutex); + del_timer_sync(&wlvif->rx_streaming_timer); + cancel_work_sync(&wlvif->rx_streaming_enable_work); + cancel_work_sync(&wlvif->rx_streaming_disable_work); cancel_delayed_work_sync(&wlvif->pspoll_work); mutex_lock(&wl->mutex); @@ -4903,10 +4914,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) INIT_WORK(&wl->tx_work, wl1271_tx_work); INIT_WORK(&wl->recovery_work, wl1271_recovery_work); INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); - INIT_WORK(&wl->rx_streaming_enable_work, - wl1271_rx_streaming_enable_work); - INIT_WORK(&wl->rx_streaming_disable_work, - wl1271_rx_streaming_disable_work); wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); if (!wl->freezable_wq) { @@ -4930,8 +4937,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl->system_hlid = WL12XX_SYSTEM_HLID; wl->active_sta_count = 0; - setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, - (unsigned long) wl); wl->fwlog_size = 0; init_waitqueue_head(&wl->fwlog_waitq); diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 9cfa0b25a6f8..dd2f8b714a7f 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -28,6 +28,7 @@ #include "acx.h" #include "reg.h" #include "rx.h" +#include "tx.h" #include "io.h" static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status, @@ -96,7 +97,7 @@ static void wl1271_rx_status(struct wl1271 *wl, } static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, - bool unaligned) + bool unaligned, u8 *hlid) { struct wl1271_rx_descriptor *desc; struct sk_buff *skb; @@ -159,6 +160,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, * payload aligned to 4 bytes. */ memcpy(buf, data + sizeof(*desc), length - sizeof(*desc)); + *hlid = desc->hlid; hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_beacon(hdr->frame_control)) @@ -169,10 +171,10 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d", skb, + wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d hlid %d", skb, skb->len - desc->pad_len, beacon ? "beacon" : "", - seq_num); + seq_num, *hlid); skb_trim(skb, skb->len - desc->pad_len); @@ -185,8 +187,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) { struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; - struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; u32 buf_size; u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; @@ -194,8 +195,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) u32 mem_block; u32 pkt_length; u32 pkt_offset; - bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); - bool had_data = false; + u8 hlid; bool unaligned = false; while (drv_rx_counter != fw_rx_counter) { @@ -255,8 +255,11 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) */ if (wl1271_rx_handle_data(wl, wl->aggr_buf + pkt_offset, - pkt_length, unaligned) == 1) - had_data = true; + pkt_length, unaligned, + &hlid) == 1) { + WARN_ON(hlid >= WL12XX_MAX_LINKS); + __set_bit(hlid, active_hlids); + } wl->rx_counter++; drv_rx_counter++; @@ -272,17 +275,5 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); - if (!is_ap && wl->conf.rx_streaming.interval && had_data && - (wl->conf.rx_streaming.always || - test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { - u32 timeout = wl->conf.rx_streaming.duration; - - /* restart rx streaming */ - if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) - ieee80211_queue_work(wl->hw, - &wl->rx_streaming_enable_work); - - mod_timer(&wl->rx_streaming_timer, - jiffies + msecs_to_jiffies(timeout)); - } + wl12xx_rearm_rx_streaming(wl, active_hlids); } diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 8c35d37ba600..a06aa4e8df7b 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -643,21 +643,58 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb) return ieee80211_is_data_present(hdr->frame_control); } +void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids) +{ + struct wl12xx_vif *wlvif; + u32 timeout; + u8 hlid; + + if (!wl->conf.rx_streaming.interval) + return; + + if (!wl->conf.rx_streaming.always && + !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)) + return; + + timeout = wl->conf.rx_streaming.duration; + wl12xx_for_each_wlvif_sta(wl, wlvif) { + bool found = false; + for_each_set_bit(hlid, active_hlids, WL12XX_MAX_LINKS) { + if (test_bit(hlid, wlvif->links_map)) { + found = true; + break; + } + } + + if (!found) + continue; + + /* enable rx streaming */ + if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) + ieee80211_queue_work(wl->hw, + &wlvif->rx_streaming_enable_work); + + mod_timer(&wlvif->rx_streaming_timer, + jiffies + msecs_to_jiffies(timeout)); + } +} + void wl1271_tx_work_locked(struct wl1271 *wl) { struct wl12xx_vif *wlvif; struct sk_buff *skb; + struct wl1271_tx_hw_descr *desc; u32 buf_offset = 0; bool sent_packets = false; - bool had_data = false; - /* TODO: save bitmap of relevant stations */ - bool is_sta = false; + unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; int ret; if (unlikely(wl->state == WL1271_STATE_OFF)) return; while ((skb = wl1271_skb_dequeue(wl))) { + bool has_data = false; + wlvif = NULL; if (!wl12xx_is_dummy_packet(wl, skb)) { struct ieee80211_tx_info *info; @@ -667,9 +704,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) vif = info->control.vif; wlvif = wl12xx_vif_to_data(vif); } - - if (wl1271_tx_is_data_present(skb)) - had_data = true; + has_data = wlvif && wl1271_tx_is_data_present(skb); ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset); if (ret == -EAGAIN) { @@ -698,8 +733,10 @@ void wl1271_tx_work_locked(struct wl1271 *wl) } buf_offset += ret; wl->tx_packets_count++; - if (wlvif && wlvif->bss_type == BSS_TYPE_STA_BSS) - is_sta = true; + if (has_data) { + desc = (struct wl1271_tx_hw_descr *) skb->data; + __set_bit(desc->hlid, active_hlids); + } } out_ack: @@ -719,19 +756,7 @@ out_ack: wl1271_handle_tx_low_watermark(wl); } - if (is_sta && wl->conf.rx_streaming.interval && had_data && - (wl->conf.rx_streaming.always || - test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { - u32 timeout = wl->conf.rx_streaming.duration; - - /* enable rx streaming */ - if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) - ieee80211_queue_work(wl->hw, - &wl->rx_streaming_enable_work); - - mod_timer(&wl->rx_streaming_timer, - jiffies + msecs_to_jiffies(timeout)); - } + wl12xx_rearm_rx_streaming(wl, active_hlids); } void wl1271_tx_work(struct work_struct *work) diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index fe29ff524e9a..2dbb24e6d541 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -220,6 +220,7 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); void wl1271_handle_tx_low_watermark(struct wl1271 *wl); bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); +void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids); /* from main.c */ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index d58488598d11..52d1cd0ddb6f 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -480,11 +480,6 @@ struct wl1271 { /* The current band */ enum ieee80211_band band; - /* Rx Streaming */ - struct work_struct rx_streaming_enable_work; - struct work_struct rx_streaming_disable_work; - struct timer_list rx_streaming_timer; - struct completion *elp_compl; struct delayed_work elp_work; @@ -635,6 +630,11 @@ struct wl12xx_vif { bool ba_support; bool ba_allowed; + /* Rx Streaming */ + struct work_struct rx_streaming_enable_work; + struct work_struct rx_streaming_disable_work; + struct timer_list rx_streaming_timer; + /* * This struct must be last! * data that has to be saved acrossed reconfigs (e.g. recovery) @@ -681,7 +681,7 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif) int wl1271_plt_start(struct wl1271 *wl); int wl1271_plt_stop(struct wl1271 *wl); -int wl1271_recalc_rx_streaming(struct wl1271 *wl); +int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif); void wl12xx_queue_recovery_work(struct wl1271 *wl); size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); From ba8447f64159927baf673d827e404605471d8f68 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:00 +0200 Subject: [PATCH 40/97] wl12xx: make WL1271_FLAG_STA_ASSOCIATED flag per-vif This flag should be set per-vif, rather than globally. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 2 +- drivers/net/wireless/wl12xx/main.c | 52 +++++++++++++++------------- drivers/net/wireless/wl12xx/scan.c | 4 +-- drivers/net/wireless/wl12xx/tx.c | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 6 +++- 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index be9e1121c8f8..cfb2835c118c 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -52,7 +52,7 @@ void wl1271_pspoll_work(struct work_struct *work) if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags)) goto out; - if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) goto out; /* diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 5ce01f1379a4..d91e8bcccaaa 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -400,10 +400,9 @@ static struct platform_device wl1271_device = { static DEFINE_MUTEX(wl_list_mutex); static LIST_HEAD(wl_list); -static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate) +static int wl1271_check_operstate(struct wl1271 *wl, struct wl12xx_vif *wlvif, + unsigned char operstate) { - struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; if (operstate != IF_OPER_UP) @@ -430,6 +429,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, struct ieee80211_hw *hw; struct wl1271 *wl; struct wl1271 *wl_temp; + struct wl12xx_vif *wlvif; int ret = 0; /* Check that this notification is for us. */ @@ -463,17 +463,18 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, if (wl->state == WL1271_STATE_OFF) goto out; - if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) - goto out; + wl12xx_for_each_wlvif_sta(wl, wlvif) { + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + continue; - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; - wl1271_check_operstate(wl, dev->operstate); - - wl1271_ps_elp_sleep(wl); + wl1271_check_operstate(wl, wlvif, dev->operstate); + wl1271_ps_elp_sleep(wl); + } out: mutex_unlock(&wl->mutex); @@ -535,7 +536,7 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif) /* reconfigure/disable according to new streaming_period */ if (period && - test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) && + test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) && (wl->conf.rx_streaming.always || test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) ret = wl1271_set_rx_streaming(wl, wlvif, true); @@ -558,7 +559,7 @@ static void wl1271_rx_streaming_enable_work(struct work_struct *work) mutex_lock(&wl->mutex); if (test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags) || - !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || + !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || (!wl->conf.rx_streaming.always && !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) goto out; @@ -1233,7 +1234,7 @@ static void wl1271_recovery_work(struct work_struct *work) * not encrypted. */ wl12xx_for_each_wlvif(wl, wlvif) { - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || + if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) wlvif->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING; @@ -1609,7 +1610,7 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, mutex_lock(&wl->mutex); - if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) goto out_unlock; ret = wl1271_ps_elp_wakeup(wl); @@ -2253,11 +2254,11 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, * Keep the below message for now, unless it starts bothering * users who really like to roam a lot :) */ - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) wl1271_info("JOIN while associated."); if (set_assoc) - set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); + set_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags); if (is_ibss) ret = wl12xx_cmd_role_start_ibss(wl, wlvif); @@ -2266,7 +2267,7 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (ret < 0) goto out; - if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) goto out; /* @@ -2449,7 +2450,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) * possible rate for the band as a fixed rate for * association frames and other control messages. */ - if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) wl1271_set_band_rate(wl, wlvif); wlvif->basic_rate = @@ -2460,7 +2461,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl1271_warning("rate policy for channel " "failed %d", ret); - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { + if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, + &wlvif->flags)) { if (wl12xx_is_roc(wl)) { /* roaming */ ret = wl12xx_croc(wl, @@ -2518,7 +2520,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) * If we're not, we'll enter it when joining an SSID, * through the bss_info_changed() hook. */ - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { + if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { wl1271_debug(DEBUG_PSM, "psm enabled"); ret = wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, @@ -2981,7 +2983,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, /* cancel ROC before scanning */ if (wl12xx_is_roc(wl)) { - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { + if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { /* don't allow scanning right now */ ret = -EBUSY; goto out_sleep; @@ -3619,8 +3621,8 @@ sta_not_found: } else { /* use defaults when not associated */ bool was_assoc = - !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED, - &wl->flags); + !!test_and_clear_bit(WLVIF_FLAG_STA_ASSOCIATED, + &wlvif->flags); bool was_ifup = !!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); @@ -3749,7 +3751,7 @@ sta_not_found: if (ret < 0) goto out; - wl1271_check_operstate(wl, + wl1271_check_operstate(wl, wlvif, ieee80211_get_operstate(vif)); } /* diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index e1a8ce092e39..687f59b871ef 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -64,7 +64,7 @@ void wl1271_scan_complete_work(struct work_struct *work) if (ret < 0) goto out; - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { + if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { /* restore hardware connection monitoring template */ wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq); } @@ -72,7 +72,7 @@ void wl1271_scan_complete_work(struct work_struct *work) /* return to ROC if needed */ is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS); is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); - if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) || + if (((is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) || (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) && !test_bit(wlvif->dev_role_id, wl->roc_map)) { /* restore remain on channel */ diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index a06aa4e8df7b..bbb101b5de0c 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -192,7 +192,7 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_tx_update_filters(wl, wlvif, skb); - if ((test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || + if ((test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) && !ieee80211_is_auth(hdr->frame_control) && !ieee80211_is_assoc_req(hdr->frame_control)) diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 52d1cd0ddb6f..efb35a66fa5e 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -313,7 +313,6 @@ struct wl1271_ap_key { }; enum wl12xx_flags { - WL1271_FLAG_STA_ASSOCIATED, WL1271_FLAG_IBSS_JOINED, WL1271_FLAG_GPIO_POWER, WL1271_FLAG_TX_QUEUE_STOPPED, @@ -338,6 +337,10 @@ enum wl12xx_flags { WL1271_FLAG_CS_PROGRESS, }; +enum wl12xx_vif_flags { + WLVIF_FLAG_STA_ASSOCIATED, +}; + struct wl1271_link { /* AP-mode - TX queue per AC in link */ struct sk_buff_head tx_queue[NUM_TX_QUEUES]; @@ -553,6 +556,7 @@ struct wl1271_station { struct wl12xx_vif { struct wl1271 *wl; struct list_head list; + unsigned long flags; u8 bss_type; u8 p2p; /* we are using p2p role */ u8 role_id; From eee514e3d6cecc7abdf1b27734169004fefb0941 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:01 +0200 Subject: [PATCH 41/97] wl12xx: make WL1271_FLAG_IBSS_JOINED flag per-vif This flag should be set per-vif, rather than globally. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 6 +++--- drivers/net/wireless/wl12xx/scan.c | 2 +- drivers/net/wireless/wl12xx/tx.c | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index d91e8bcccaaa..ac5be7323405 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3494,11 +3494,11 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (changed & BSS_CHANGED_IBSS) { if (bss_conf->ibss_joined) { - set_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags); + set_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags); ibss_joined = true; } else { - if (test_and_clear_bit(WL1271_FLAG_IBSS_JOINED, - &wl->flags)) { + if (test_and_clear_bit(WLVIF_FLAG_IBSS_JOINED, + &wlvif->flags)) { wl1271_unjoin(wl, wlvif); wl12xx_cmd_role_start_dev(wl, wlvif); wl12xx_roc(wl, wlvif->dev_role_id); diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 687f59b871ef..765f08ba29af 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -73,7 +73,7 @@ void wl1271_scan_complete_work(struct work_struct *work) is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS); is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); if (((is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) || - (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) && + (is_ibss && !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags))) && !test_bit(wlvif->dev_role_id, wl->roc_map)) { /* restore remain on channel */ wl12xx_cmd_role_start_dev(wl, wlvif); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index bbb101b5de0c..8965fd1384dd 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -193,7 +193,7 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_tx_update_filters(wl, wlvif, skb); if ((test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || - test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) && + test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) && !ieee80211_is_auth(hdr->frame_control) && !ieee80211_is_assoc_req(hdr->frame_control)) return wlvif->sta.hlid; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index efb35a66fa5e..489c20555dff 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -313,7 +313,6 @@ struct wl1271_ap_key { }; enum wl12xx_flags { - WL1271_FLAG_IBSS_JOINED, WL1271_FLAG_GPIO_POWER, WL1271_FLAG_TX_QUEUE_STOPPED, WL1271_FLAG_TX_PENDING, @@ -339,6 +338,7 @@ enum wl12xx_flags { enum wl12xx_vif_flags { WLVIF_FLAG_STA_ASSOCIATED, + WLVIF_FLAG_IBSS_JOINED, }; struct wl1271_link { From 53d40d0b863e22b697f8d85e1f95cb6f9d2d95b1 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:02 +0200 Subject: [PATCH 42/97] wl12xx: make WL1271_FLAG_AP_STARTED flag per-vif This flag should be set per-vif, rather than globally. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 14 +++++++------- drivers/net/wireless/wl12xx/tx.c | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index ac5be7323405..41cc5fe27d87 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1235,7 +1235,7 @@ static void wl1271_recovery_work(struct work_struct *work) */ wl12xx_for_each_wlvif(wl, wlvif) { if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || - test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) + test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) wlvif->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING; } @@ -1662,7 +1662,7 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl, mutex_lock(&wl->mutex); - if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) + if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) goto out_unlock; ret = wl1271_ps_elp_wakeup(wl); @@ -2768,7 +2768,7 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, hlid = wlvif->ap.bcast_hlid; } - if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { + if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { /* * We do not support removing keys after AP shutdown. * Pretend we do to make mac80211 happy. @@ -3426,7 +3426,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, if ((changed & BSS_CHANGED_BEACON_ENABLED)) { if (bss_conf->enable_beacon) { - if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { + if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { ret = wl12xx_cmd_role_start_ap(wl, wlvif); if (ret < 0) goto out; @@ -3435,16 +3435,16 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, if (ret < 0) goto out; - set_bit(WL1271_FLAG_AP_STARTED, &wl->flags); + set_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags); wl1271_debug(DEBUG_AP, "started AP"); } } else { - if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { + if (test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { ret = wl12xx_cmd_role_stop_ap(wl, wlvif); if (ret < 0) goto out; - clear_bit(WL1271_FLAG_AP_STARTED, &wl->flags); + clear_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags); wl1271_debug(DEBUG_AP, "stopped AP"); } } diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 8965fd1384dd..a60d8feb69e4 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -168,7 +168,7 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, } else { struct ieee80211_hdr *hdr; - if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) + if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) return wl->system_hlid; hdr = (struct ieee80211_hdr *)skb->data; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 489c20555dff..9b28e478930e 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -325,7 +325,6 @@ enum wl12xx_flags { WL1271_FLAG_PSPOLL_FAILURE, WL1271_FLAG_STA_STATE_SENT, WL1271_FLAG_FW_TX_BUSY, - WL1271_FLAG_AP_STARTED, WL1271_FLAG_IF_INITIALIZED, WL1271_FLAG_DUMMY_PACKET_PENDING, WL1271_FLAG_SUSPENDED, @@ -339,6 +338,7 @@ enum wl12xx_flags { enum wl12xx_vif_flags { WLVIF_FLAG_STA_ASSOCIATED, WLVIF_FLAG_IBSS_JOINED, + WLVIF_FLAG_AP_STARTED, }; struct wl1271_link { From c29bb001e448ef57e077db9f1c5ae864e3f8abab Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:03 +0200 Subject: [PATCH 43/97] wl12xx: make WL1271_FLAG_PSM flag per-vif move WL1271_FLAG_PSM and WL1271_FLAG_PSM_REQUESTED into per-vif flags. These flags should be set per-vif, rather than globally. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 4 ++-- drivers/net/wireless/wl12xx/main.c | 18 +++++++++--------- drivers/net/wireless/wl12xx/ps.c | 25 +++++++++++++++++-------- drivers/net/wireless/wl12xx/wl12xx.h | 4 ++-- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index cfb2835c118c..d8b183bba52b 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -84,7 +84,7 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl, "trying to work around it."); /* force active mode receive data from the AP */ - if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { + if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { ret = wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, wlvif->basic_rate, true); if (ret < 0) @@ -116,7 +116,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, case EVENT_ENTER_POWER_SAVE_FAIL: wl1271_debug(DEBUG_PSM, "PSM entry failed"); - if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { + if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { /* remain in active mode */ wlvif->psm_entry_retry = 0; break; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 41cc5fe27d87..2fe0ee144a9d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1618,7 +1618,7 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, goto out_unlock; /* enter psm if needed*/ - if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { + if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { DECLARE_COMPLETION_ONSTACK(compl); wlvif->ps_compl = &compl; @@ -1705,7 +1705,7 @@ static void wl1271_configure_resume(struct wl1271 *wl, if (is_sta) { /* exit psm if it wasn't configured */ - if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) + if (!test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, wlvif->basic_rate, true); } else if (is_ap) { @@ -2512,8 +2512,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); if (conf->flags & IEEE80211_CONF_PS && - !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { - set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); + !test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) { + set_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags); /* * We enter PSM only if we're already associated. @@ -2527,12 +2527,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wlvif->basic_rate, true); } } else if (!(conf->flags & IEEE80211_CONF_PS) && - test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { + test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) { wl1271_debug(DEBUG_PSM, "psm disabled"); - clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); + clear_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags); - if (test_bit(WL1271_FLAG_PSM, &wl->flags)) + if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) ret = wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, wlvif->basic_rate, true); @@ -3769,8 +3769,8 @@ sta_not_found: } /* If we want to go in PSM but we're not there yet */ - if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && - !test_bit(WL1271_FLAG_PSM, &wl->flags)) { + if (test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags) && + !test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { enum wl1271_cmd_ps_mode mode; mode = STATION_POWER_SAVE_MODE; diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index ac3f20716f5b..8cd81cec2841 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -32,6 +32,7 @@ void wl1271_elp_work(struct work_struct *work) { struct delayed_work *dwork; struct wl1271 *wl; + struct wl12xx_vif *wlvif; dwork = container_of(work, struct delayed_work, work); wl = container_of(dwork, struct wl1271, elp_work); @@ -47,11 +48,15 @@ void wl1271_elp_work(struct work_struct *work) if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) goto out; - if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || - (!test_bit(WL1271_FLAG_PSM, &wl->flags) && - !test_bit(WL1271_FLAG_IDLE, &wl->flags))) + if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) goto out; + wl12xx_for_each_wlvif(wl, wlvif) { + if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && + !test_bit(WL1271_FLAG_IDLE, &wl->flags)) + goto out; + } + wl1271_debug(DEBUG_PSM, "chip to elp"); wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); set_bit(WL1271_FLAG_IN_ELP, &wl->flags); @@ -65,13 +70,17 @@ out: /* Routines to toggle sleep mode while in ELP */ void wl1271_ps_elp_sleep(struct wl1271 *wl) { + struct wl12xx_vif *wlvif; + /* we shouldn't get consecutive sleep requests */ if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) return; - if (!test_bit(WL1271_FLAG_PSM, &wl->flags) && - !test_bit(WL1271_FLAG_IDLE, &wl->flags)) - return; + wl12xx_for_each_wlvif(wl, wlvif) { + if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && + !test_bit(WL1271_FLAG_IDLE, &wl->flags)) + return; + } ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, msecs_to_jiffies(ELP_ENTRY_DELAY)); @@ -162,7 +171,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (ret < 0) return ret; - set_bit(WL1271_FLAG_PSM, &wl->flags); + set_bit(WLVIF_FLAG_PSM, &wlvif->flags); break; case STATION_ACTIVE_MODE: default: @@ -184,7 +193,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (ret < 0) return ret; - clear_bit(WL1271_FLAG_PSM, &wl->flags); + clear_bit(WLVIF_FLAG_PSM, &wlvif->flags); break; } diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 9b28e478930e..ea6b7293175a 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -318,8 +318,6 @@ enum wl12xx_flags { WL1271_FLAG_TX_PENDING, WL1271_FLAG_IN_ELP, WL1271_FLAG_ELP_REQUESTED, - WL1271_FLAG_PSM, - WL1271_FLAG_PSM_REQUESTED, WL1271_FLAG_IRQ_RUNNING, WL1271_FLAG_IDLE, WL1271_FLAG_PSPOLL_FAILURE, @@ -339,6 +337,8 @@ enum wl12xx_vif_flags { WLVIF_FLAG_STA_ASSOCIATED, WLVIF_FLAG_IBSS_JOINED, WLVIF_FLAG_AP_STARTED, + WLVIF_FLAG_PSM, + WLVIF_FLAG_PSM_REQUESTED, }; struct wl1271_link { From 8181aecce9ea3731ff5554c6f9cf16bf249a61fa Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:04 +0200 Subject: [PATCH 44/97] wl12xx: make WL1271_FLAG_STA_STATE_SENT flag per-vif This flag should be set per-vif, rather than globally. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 6 +++--- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 2fe0ee144a9d..63340ad8451d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -408,7 +408,7 @@ static int wl1271_check_operstate(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (operstate != IF_OPER_UP) return 0; - if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) + if (test_and_set_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags)) return 0; ret = wl12xx_cmd_set_peer_state(wl, wlvif->sta.hlid); @@ -3624,8 +3624,8 @@ sta_not_found: !!test_and_clear_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags); bool was_ifup = - !!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT, - &wl->flags); + !!test_and_clear_bit(WLVIF_FLAG_STA_STATE_SENT, + &wlvif->flags); wlvif->aid = 0; /* free probe-request template */ diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index ea6b7293175a..9de57dd71c34 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -321,7 +321,6 @@ enum wl12xx_flags { WL1271_FLAG_IRQ_RUNNING, WL1271_FLAG_IDLE, WL1271_FLAG_PSPOLL_FAILURE, - WL1271_FLAG_STA_STATE_SENT, WL1271_FLAG_FW_TX_BUSY, WL1271_FLAG_IF_INITIALIZED, WL1271_FLAG_DUMMY_PACKET_PENDING, @@ -339,6 +338,7 @@ enum wl12xx_vif_flags { WLVIF_FLAG_AP_STARTED, WLVIF_FLAG_PSM, WLVIF_FLAG_PSM_REQUESTED, + WLVIF_FLAG_STA_STATE_SENT, }; struct wl1271_link { From 0744bdb60b51dce54553d5af9a6133f1fe419032 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:05 +0200 Subject: [PATCH 45/97] wl12xx: make WL1271_FLAG_RX_STREAMING_STARTED flag per-vif This flag should be set per-vif, rather than globally. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 10 +++++----- drivers/net/wireless/wl12xx/tx.c | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 63340ad8451d..9042445e0d03 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -514,9 +514,9 @@ static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; if (enable) - set_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags); + set_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags); else - clear_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags); + clear_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags); out: return ret; } @@ -531,7 +531,7 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif) int period = wl->conf.rx_streaming.interval; /* don't reconfigure if rx_streaming is disabled */ - if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) + if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags)) goto out; /* reconfigure/disable according to new streaming_period */ @@ -558,7 +558,7 @@ static void wl1271_rx_streaming_enable_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags) || + if (test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags) || !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || (!wl->conf.rx_streaming.always && !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) @@ -594,7 +594,7 @@ static void wl1271_rx_streaming_disable_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) + if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags)) goto out; ret = wl1271_ps_elp_wakeup(wl); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index a60d8feb69e4..3cf7166dab63 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -670,7 +670,7 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids) continue; /* enable rx streaming */ - if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) + if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags)) ieee80211_queue_work(wl->hw, &wlvif->rx_streaming_enable_work); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 9de57dd71c34..5b5c93093347 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -327,7 +327,6 @@ enum wl12xx_flags { WL1271_FLAG_SUSPENDED, WL1271_FLAG_PENDING_WORK, WL1271_FLAG_SOFT_GEMINI, - WL1271_FLAG_RX_STREAMING_STARTED, WL1271_FLAG_RECOVERY_IN_PROGRESS, WL1271_FLAG_CS_PROGRESS, }; @@ -339,6 +338,7 @@ enum wl12xx_vif_flags { WLVIF_FLAG_PSM, WLVIF_FLAG_PSM_REQUESTED, WLVIF_FLAG_STA_STATE_SENT, + WLVIF_FLAG_RX_STREAMING_STARTED, }; struct wl1271_link { From 10c8cd01e329b2973eddddafe67ae499eef83b19 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:06 +0200 Subject: [PATCH 46/97] wl12xx: make WL1271_FLAG_IF_INITIALIZED per-vif Make the initialization flag per-vif, and add some checks for it. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 32 ++++++++++++++++++++++------ drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 9042445e0d03..fb5951cb69e1 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1817,14 +1817,20 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); - mutex_lock(&wl_list_mutex); - list_del(&wl->list); - + mutex_lock(&wl->mutex); + if (wl->state == WL1271_STATE_OFF) { + mutex_unlock(&wl->mutex); + return; + } /* * this must be before the cancel_work calls below, so that the work * functions don't perform further work. */ wl->state = WL1271_STATE_OFF; + mutex_unlock(&wl->mutex); + + mutex_lock(&wl_list_mutex); + list_del(&wl->list); mutex_unlock(&wl_list_mutex); wl1271_disable_interrupts(wl); @@ -1971,7 +1977,6 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, (unsigned long) wlvif); - return 0; } @@ -2069,7 +2074,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, * get here before __wl1271_op_remove_interface is complete, so * opt out if that is the case. */ - if (test_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags)) { + if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags) || + test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) { ret = -EBUSY; goto out; } @@ -2129,7 +2135,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, wl->vif = vif; list_add(&wlvif->list, &wl->wlvif_list); - set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); + set_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags); if (wlvif->bss_type == BSS_TYPE_AP_BSS) wl->ap_count++; @@ -2155,6 +2161,9 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); + if (!test_and_clear_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) + return; + /* because of hardware recovery, we may get here twice */ if (wl->state != WL1271_STATE_ON) return; @@ -2224,8 +2233,14 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); mutex_lock(&wl->mutex); + + if (wl->state == WL1271_STATE_OFF || + !test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) + goto out; + /* * wl->vif can be null here if someone shuts down the interface * just when hardware recovery has been started. @@ -2234,7 +2249,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, WARN_ON(wl->vif != vif); __wl1271_op_remove_interface(wl, vif, true); } - +out: mutex_unlock(&wl->mutex); cancel_work_sync(&wl->recovery_work); } @@ -3843,6 +3858,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; + if (unlikely(!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags))) + goto out; + ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 5b5c93093347..740a9b19cea1 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -322,7 +322,6 @@ enum wl12xx_flags { WL1271_FLAG_IDLE, WL1271_FLAG_PSPOLL_FAILURE, WL1271_FLAG_FW_TX_BUSY, - WL1271_FLAG_IF_INITIALIZED, WL1271_FLAG_DUMMY_PACKET_PENDING, WL1271_FLAG_SUSPENDED, WL1271_FLAG_PENDING_WORK, @@ -332,6 +331,7 @@ enum wl12xx_flags { }; enum wl12xx_vif_flags { + WLVIF_FLAG_INITIALIZED, WLVIF_FLAG_STA_ASSOCIATED, WLVIF_FLAG_IBSS_JOINED, WLVIF_FLAG_AP_STARTED, From 836d6600ea0e785fcf8159a3c4b7350276bcd49a Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:07 +0200 Subject: [PATCH 47/97] wl12xx: make WL1271_FLAG_PSPOLL_FAILURE flag per-vif This flag should be set per-vif, rather than globally. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 4 ++-- drivers/net/wireless/wl12xx/main.c | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index d8b183bba52b..1f60a1f6335e 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -49,7 +49,7 @@ void wl1271_pspoll_work(struct work_struct *work) if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; - if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags)) + if (!test_and_clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags)) goto out; if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) @@ -89,7 +89,7 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl, wlvif->basic_rate, true); if (ret < 0) return; - set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); + set_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags); ieee80211_queue_delayed_work(wl->hw, &wlvif->pspoll_work, msecs_to_jiffies(delay)); } diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index fb5951cb69e1..73973b4fc57f 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2524,7 +2524,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) * incorrectly changed after the pspoll failure active window. */ if (changed & IEEE80211_CONF_CHANGE_PS) - clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); + clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags); if (conf->flags & IEEE80211_CONF_PS && !test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) { diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 740a9b19cea1..bf410f8d01cb 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -320,7 +320,6 @@ enum wl12xx_flags { WL1271_FLAG_ELP_REQUESTED, WL1271_FLAG_IRQ_RUNNING, WL1271_FLAG_IDLE, - WL1271_FLAG_PSPOLL_FAILURE, WL1271_FLAG_FW_TX_BUSY, WL1271_FLAG_DUMMY_PACKET_PENDING, WL1271_FLAG_SUSPENDED, @@ -339,6 +338,7 @@ enum wl12xx_vif_flags { WLVIF_FLAG_PSM_REQUESTED, WLVIF_FLAG_STA_STATE_SENT, WLVIF_FLAG_RX_STREAMING_STARTED, + WLVIF_FLAG_PSPOLL_FAILURE, }; struct wl1271_link { From 52630c5d89840bf09826fe89cc15f868e92223ef Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:08 +0200 Subject: [PATCH 48/97] wl12xx: make WL1271_FLAG_CS_PROGRESS flag per-vif This flag should be set per-vif, rather than globally. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 20 +++++++++++--------- drivers/net/wireless/wl12xx/main.c | 12 ++++++++---- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 1f60a1f6335e..a47312db5a2a 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -345,16 +345,18 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) * 1) channel switch complete with status=0 * 2) channel switch failed status=1 */ - if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) { - /* TODO: configure only the relevant vif */ - wl12xx_for_each_wlvif_sta(wl, wlvif) { - struct ieee80211_vif *vif = - wl12xx_wlvif_to_vif(wlvif); - bool success = mbox->channel_switch_status ? - false : true; - ieee80211_chswitch_done(vif, success); - } + /* TODO: configure only the relevant vif */ + wl12xx_for_each_wlvif_sta(wl, wlvif) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + bool success; + + if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, + &wl->flags)) + continue; + + success = mbox->channel_switch_status ? false : true; + ieee80211_chswitch_done(vif, success); } } diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 73973b4fc57f..0647d460b698 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2317,7 +2317,7 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret; - if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) { + if (test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) { wl12xx_cmd_stop_channel_switch(wl); ieee80211_chswitch_done(wl->vif, false); } @@ -4275,6 +4275,7 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, struct ieee80211_channel_switch *ch_switch) { struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif; int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch"); @@ -4291,10 +4292,13 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, if (ret < 0) goto out; - ret = wl12xx_cmd_channel_switch(wl, ch_switch); + /* TODO: change mac80211 to pass vif as param */ + wl12xx_for_each_wlvif_sta(wl, wlvif) { + ret = wl12xx_cmd_channel_switch(wl, ch_switch); - if (!ret) - set_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags); + if (!ret) + set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags); + } wl1271_ps_elp_sleep(wl); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index bf410f8d01cb..fc8c9758fc0c 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -326,7 +326,6 @@ enum wl12xx_flags { WL1271_FLAG_PENDING_WORK, WL1271_FLAG_SOFT_GEMINI, WL1271_FLAG_RECOVERY_IN_PROGRESS, - WL1271_FLAG_CS_PROGRESS, }; enum wl12xx_vif_flags { @@ -339,6 +338,7 @@ enum wl12xx_vif_flags { WLVIF_FLAG_STA_STATE_SENT, WLVIF_FLAG_RX_STREAMING_STARTED, WLVIF_FLAG_PSPOLL_FAILURE, + WLVIF_FLAG_CS_PROGRESS, }; struct wl1271_link { From 1b92f15ee0e0f06222d4fd36dc36960d217243b3 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:09 +0200 Subject: [PATCH 49/97] wl12xx: add band field to wlvif add band field into the per-interface data. mac80211 configures some values (e.g. band, channel) globally, while we configure them per-interface. In order to make it easier to keep track of the configured value for each value while keeping sync with mac80211, save these values both globally and per-vif. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 32 +++++++++++++++------------- drivers/net/wireless/wl12xx/cmd.h | 5 +++-- drivers/net/wireless/wl12xx/event.c | 2 +- drivers/net/wireless/wl12xx/main.c | 32 +++++++++++++++++----------- drivers/net/wireless/wl12xx/ps.c | 2 +- drivers/net/wireless/wl12xx/scan.c | 2 +- drivers/net/wireless/wl12xx/tx.c | 5 +++-- drivers/net/wireless/wl12xx/wl12xx.h | 3 +++ 8 files changed, 49 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index ff653e8832a8..6cf8cdc72b59 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -481,7 +481,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wlvif->dev_role_id); cmd->role_id = wlvif->dev_role_id; - if (wl->band == IEEE80211_BAND_5GHZ) + if (wlvif->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; @@ -571,7 +571,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wlvif->role_id); cmd->role_id = wlvif->role_id; - if (wl->band == IEEE80211_BAND_5GHZ) + if (wlvif->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); @@ -704,7 +704,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->ap.local_rates = cpu_to_le32(0xffffffff); - switch (wl->band) { + switch (wlvif->band) { case IEEE80211_BAND_2GHZ: cmd->band = RADIO_BAND_2_4GHZ; break; @@ -712,7 +712,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->band = RADIO_BAND_5GHZ; break; default: - wl1271_warning("ap start - unknown band: %d", (int)wl->band); + wl1271_warning("ap start - unknown band: %d", (int)wlvif->band); cmd->band = RADIO_BAND_2_4GHZ; break; } @@ -785,7 +785,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wlvif->role_id); cmd->role_id = wlvif->role_id; - if (wl->band == IEEE80211_BAND_5GHZ) + if (wlvif->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); @@ -1157,8 +1157,8 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); - rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wl->band]); - if (wl->band == IEEE80211_BAND_2GHZ) + rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]); + if (wlvif->band == IEEE80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, skb->data, skb->len, 0, rate); else @@ -1428,7 +1428,8 @@ out: return ret; } -int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) +int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, + struct ieee80211_sta *sta, u8 hlid) { struct wl12xx_cmd_add_peer *cmd; int i, ret; @@ -1455,13 +1456,13 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) else cmd->psd_type[i] = WL1271_PSD_LEGACY; - sta_rates = sta->supp_rates[wl->band]; + sta_rates = sta->supp_rates[wlvif->band]; if (sta->ht_cap.ht_supported) sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates, - wl->band)); + wlvif->band)); wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x", cmd->supported_rates, sta->uapsd_queues); @@ -1601,7 +1602,8 @@ out: return ret; } -static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id) +static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 role_id) { struct wl12xx_cmd_roc *cmd; int ret = 0; @@ -1619,7 +1621,7 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id) cmd->role_id = role_id; cmd->channel = wl->channel; - switch (wl->band) { + switch (wlvif->band) { case IEEE80211_BAND_2GHZ: cmd->band = RADIO_BAND_2_4GHZ; break; @@ -1627,7 +1629,7 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id) cmd->band = RADIO_BAND_5GHZ; break; default: - wl1271_error("roc - unknown band: %d", (int)wl->band); + wl1271_error("roc - unknown band: %d", (int)wlvif->band); ret = -EINVAL; goto out_free; } @@ -1674,14 +1676,14 @@ out: return ret; } -int wl12xx_roc(struct wl1271 *wl, u8 role_id) +int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id) { int ret = 0; if (WARN_ON(test_bit(role_id, wl->roc_map))) return 0; - ret = wl12xx_cmd_roc(wl, role_id); + ret = wl12xx_cmd_roc(wl, wlvif, role_id); if (ret < 0) goto out; diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 8182cf1b4861..968d5bdc0b60 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -80,9 +80,10 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u16 tx_seq_16); int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid); -int wl12xx_roc(struct wl1271 *wl, u8 role_id); +int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id); int wl12xx_croc(struct wl1271 *wl, u8 role_id); -int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid); +int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, + struct ieee80211_sta *sta, u8 hlid); int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid); int wl12xx_cmd_config_fwlog(struct wl1271 *wl); int wl12xx_cmd_start_fwlog(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index a47312db5a2a..fd2e7b2d9389 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -145,7 +145,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, * BET has only a minor effect in 5GHz and masks * channel switch IEs, so we only enable BET on 2.4GHz */ - if (wl->band == IEEE80211_BAND_2GHZ) + if (wlvif->band == IEEE80211_BAND_2GHZ) /* enable beacon early termination */ ret = wl1271_acx_bet_enable(wl, wlvif, true); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0647d460b698..8e395f1f4b1a 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1968,6 +1968,12 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; + /* + * mac80211 configures some values globally, while we treat them + * per-interface. thus, on init, we have to copy them from wl + */ + wlvif->band = wl->band; + INIT_WORK(&wlvif->rx_streaming_enable_work, wl1271_rx_streaming_enable_work); INIT_WORK(&wlvif->rx_streaming_disable_work, @@ -2337,7 +2343,7 @@ out: static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif) { - wlvif->basic_rate_set = wlvif->bitrate_masks[wl->band]; + wlvif->basic_rate_set = wlvif->bitrate_masks[wlvif->band]; wlvif->rate_set = wlvif->basic_rate_set; } @@ -2390,7 +2396,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (ret < 0) goto out; - ret = wl12xx_roc(wl, wlvif->dev_role_id); + ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); if (ret < 0) goto out; clear_bit(WL1271_FLAG_IDLE, &wl->flags); @@ -2451,11 +2457,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) /* if the channel changes while joined, join again */ if (changed & IEEE80211_CONF_CHANGE_CHANNEL && - ((wl->band != conf->channel->band) || + ((wlvif->band != conf->channel->band) || (wl->channel != channel))) { /* send all pending packets */ wl1271_tx_work_locked(wl); wl->band = conf->channel->band; + wlvif->band = conf->channel->band; wl->channel = channel; if (!is_ap) { @@ -2502,7 +2509,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (ret < 0) goto out_sleep; - ret = wl12xx_roc(wl, + ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); if (ret < 0) wl1271_warning("roc failed %d", @@ -3420,7 +3427,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, u32 rates = bss_conf->basic_rates; wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, - wl->band); + wlvif->band); wlvif->basic_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); @@ -3516,7 +3523,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, &wlvif->flags)) { wl1271_unjoin(wl, wlvif); wl12xx_cmd_role_start_dev(wl, wlvif); - wl12xx_roc(wl, wlvif->dev_role_id); + wl12xx_roc(wl, wlvif, wlvif->dev_role_id); } } } @@ -3595,7 +3602,7 @@ sta_not_found: rates = bss_conf->basic_rates; wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, - wl->band); + wlvif->band); wlvif->basic_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); @@ -3603,7 +3610,7 @@ sta_not_found: wlvif->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rate_set, - wl->band); + wlvif->band); ret = wl1271_acx_sta_rate_policies(wl, wlvif); if (ret < 0) goto out; @@ -3694,7 +3701,8 @@ sta_not_found: wl1271_unjoin(wl, wlvif); if (!(conf_flags & IEEE80211_CONF_IDLE)) { wl12xx_cmd_role_start_dev(wl, wlvif); - wl12xx_roc(wl, wlvif->dev_role_id); + wl12xx_roc(wl, wlvif, + wlvif->dev_role_id); } } } @@ -3708,7 +3716,7 @@ sta_not_found: u32 rates = bss_conf->basic_rates; wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, - wl->band); + wlvif->band); wlvif->basic_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); @@ -3762,7 +3770,7 @@ sta_not_found: /* ROC until connected (after EAPOL exchange) */ if (!is_ibss) { - ret = wl12xx_roc(wl, wlvif->role_id); + ret = wl12xx_roc(wl, wlvif, wlvif->role_id); if (ret < 0) goto out; @@ -4068,7 +4076,7 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, if (ret < 0) goto out_free_sta; - ret = wl12xx_cmd_add_peer(wl, sta, hlid); + ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid); if (ret < 0) goto out_sleep; diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 8cd81cec2841..8153408233b5 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -178,7 +178,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_debug(DEBUG_PSM, "leaving psm"); /* disable beacon early termination */ - if (wl->band == IEEE80211_BAND_2GHZ) { + if (wlvif->band == IEEE80211_BAND_2GHZ) { ret = wl1271_acx_bet_enable(wl, wlvif, false); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 765f08ba29af..2711438fdde3 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -77,7 +77,7 @@ void wl1271_scan_complete_work(struct work_struct *work) !test_bit(wlvif->dev_role_id, wl->roc_map)) { /* restore remain on channel */ wl12xx_cmd_role_start_dev(wl, wlvif); - wl12xx_roc(wl, wlvif->dev_role_id); + wl12xx_roc(wl, wlvif, wlvif->dev_role_id); } wl1271_ps_elp_sleep(wl); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 3cf7166dab63..604913ff42bd 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -102,7 +102,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, if (ret < 0) goto out; - ret = wl12xx_roc(wl, wlvif->dev_role_id); + ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); if (ret < 0) goto out; out: @@ -809,7 +809,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, if (result->status == TX_SUCCESS) { if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_ACK; - rate = wl1271_rate_to_idx(result->rate_class_index, wl->band); + rate = wl1271_rate_to_idx(result->rate_class_index, + wlvif->band); retries = result->ack_failures; } else if (result->status == TX_RETRY_EXCEEDED) { wl->stats.excessive_retries++; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index fc8c9758fc0c..a689ad02a357 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -591,6 +591,9 @@ struct wl12xx_vif { u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 ssid_len; + /* The current band */ + enum ieee80211_band band; + u32 bitrate_masks[IEEE80211_NUM_BANDS]; u32 basic_rate_set; From 61f845f4f441a90e5328a78c6c4e0646d99fc2f0 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:10 +0200 Subject: [PATCH 50/97] wl12xx: add channel field to wlvif add channel into the per-interface data. mac80211 configures some values (e.g. band, channel) globally, while we configure them per-interface. In order to make it easier to keep track of the configured value for each value while keeping sync with mac80211, save these values both globally and per-vif. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 12 ++++++------ drivers/net/wireless/wl12xx/main.c | 6 ++++-- drivers/net/wireless/wl12xx/wl12xx.h | 1 + 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 6cf8cdc72b59..4c5c51810fda 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -483,7 +483,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->role_id = wlvif->dev_role_id; if (wlvif->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; - cmd->channel = wl->channel; + cmd->channel = wlvif->channel; if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { ret = wl12xx_allocate_link(wl, wlvif, &wlvif->dev_hlid); @@ -573,7 +573,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->role_id = wlvif->role_id; if (wlvif->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; - cmd->channel = wl->channel; + cmd->channel = wlvif->channel; cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); cmd->sta.beacon_interval = cpu_to_le16(wlvif->beacon_int); cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; @@ -689,7 +689,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int); cmd->ap.dtim_interval = bss_conf->dtim_period; cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; - cmd->channel = wl->channel; + cmd->channel = wlvif->channel; if (!bss_conf->hidden_ssid) { /* take the SSID from the beacon for backward compatibility */ @@ -787,7 +787,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->role_id = wlvif->role_id; if (wlvif->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; - cmd->channel = wl->channel; + cmd->channel = wlvif->channel; cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); cmd->ibss.beacon_interval = cpu_to_le16(wlvif->beacon_int); cmd->ibss.dtim_interval = bss_conf->dtim_period; @@ -1608,7 +1608,7 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct wl12xx_cmd_roc *cmd; int ret = 0; - wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wl->channel, role_id); + wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wlvif->channel, role_id); if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID)) return -EINVAL; @@ -1620,7 +1620,7 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, } cmd->role_id = role_id; - cmd->channel = wl->channel; + cmd->channel = wlvif->channel; switch (wlvif->band) { case IEEE80211_BAND_2GHZ: cmd->band = RADIO_BAND_2_4GHZ; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8e395f1f4b1a..5137275d3591 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1973,6 +1973,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) * per-interface. thus, on init, we have to copy them from wl */ wlvif->band = wl->band; + wlvif->channel = wl->channel; INIT_WORK(&wlvif->rx_streaming_enable_work, wl1271_rx_streaming_enable_work); @@ -2458,12 +2459,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) /* if the channel changes while joined, join again */ if (changed & IEEE80211_CONF_CHANGE_CHANNEL && ((wlvif->band != conf->channel->band) || - (wl->channel != channel))) { + (wlvif->channel != channel))) { /* send all pending packets */ wl1271_tx_work_locked(wl); wl->band = conf->channel->band; - wlvif->band = conf->channel->band; wl->channel = channel; + wlvif->band = conf->channel->band; + wlvif->channel = channel; if (!is_ap) { /* diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index a689ad02a357..02dedd191bd4 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -593,6 +593,7 @@ struct wl12xx_vif { /* The current band */ enum ieee80211_band band; + int channel; u32 bitrate_masks[IEEE80211_NUM_BANDS]; u32 basic_rate_set; From 6bd650299046f00df6d7374c7f61c5afe6df6696 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:11 +0200 Subject: [PATCH 51/97] wl12xx: add power_level field to wlvif move power_level into the per-interface data. mac80211 configures some values (e.g. band, channel) globally, while we configure them per-interface. In order to make it easier to keep track of the configured value for each value while keeping sync with mac80211, save these values both globally and per-vif. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/init.c | 2 +- drivers/net/wireless/wl12xx/main.c | 4 +++- drivers/net/wireless/wl12xx/wl12xx.h | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 4af7e2fb52fd..74f569099b53 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -554,7 +554,7 @@ static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif) return ret; /* initialize Tx power */ - ret = wl1271_acx_tx_power(wl, wlvif, wl->power_level); + ret = wl1271_acx_tx_power(wl, wlvif, wlvif->power_level); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 5137275d3591..cffb40be7b5b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1974,6 +1974,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) */ wlvif->band = wl->band; wlvif->channel = wl->channel; + wlvif->power_level = wl->power_level; INIT_WORK(&wlvif->rx_streaming_enable_work, wl1271_rx_streaming_enable_work); @@ -2562,12 +2563,13 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wlvif->basic_rate, true); } - if (conf->power_level != wl->power_level) { + if (conf->power_level != wlvif->power_level) { ret = wl1271_acx_tx_power(wl, wlvif, conf->power_level); if (ret < 0) goto out_sleep; wl->power_level = conf->power_level; + wlvif->power_level = conf->power_level; } out_sleep: diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 02dedd191bd4..2689522ba4ed 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -631,6 +631,9 @@ struct wl12xx_vif { /* retry counter for PSM entries */ u8 psm_entry_retry; + /* in dBm */ + int power_level; + int rssi_thold; int last_rssi_event; From 9f259c4e5e42d5f0c25675dc1088cd96dc81a9f1 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:12 +0200 Subject: [PATCH 52/97] wl12xx: make op_config configure all vifs When mac80211 changes a global (hw) config, iterate through all the relevant vifs and update them. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 112 ++++++++++++++++------------- 1 file changed, 61 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index cffb40be7b5b..b2640edcc3a8 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2408,63 +2408,20 @@ out: return ret; } -static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) +static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, + struct ieee80211_conf *conf, u32 changed) { - struct wl1271 *wl = hw->priv; - struct ieee80211_vif *vif = wl->vif; /* TODO: reconfig all vifs */ - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - struct ieee80211_conf *conf = &hw->conf; - int channel, ret = 0; - bool is_ap; + bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); + int channel, ret; channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s" - " changed 0x%x", - channel, - conf->flags & IEEE80211_CONF_PS ? "on" : "off", - conf->power_level, - conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use", - changed); - - /* - * mac80211 will go to idle nearly immediately after transmitting some - * frames, such as the deauth. To make sure those frames reach the air, - * wait here until the TX queue is fully flushed. - */ - if ((changed & IEEE80211_CONF_CHANGE_IDLE) && - (conf->flags & IEEE80211_CONF_IDLE)) - wl1271_tx_flush(wl); - - mutex_lock(&wl->mutex); - - if (unlikely(wl->state == WL1271_STATE_OFF)) { - /* we support configuring the channel and band while off */ - if ((changed & IEEE80211_CONF_CHANGE_CHANNEL)) { - wl->band = conf->channel->band; - wl->channel = channel; - } - - if ((changed & IEEE80211_CONF_CHANGE_POWER)) - wl->power_level = conf->power_level; - - goto out; - } - - is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - /* if the channel changes while joined, join again */ if (changed & IEEE80211_CONF_CHANGE_CHANNEL && ((wlvif->band != conf->channel->band) || (wlvif->channel != channel))) { /* send all pending packets */ wl1271_tx_work_locked(wl); - wl->band = conf->channel->band; - wl->channel = channel; wlvif->band = conf->channel->band; wlvif->channel = channel; @@ -2493,7 +2450,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) ret = wl12xx_croc(wl, wlvif->dev_role_id); if (ret < 0) - goto out_sleep; + return ret; } ret = wl1271_join(wl, wlvif, false); if (ret < 0) @@ -2510,7 +2467,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) ret = wl12xx_croc(wl, wlvif->dev_role_id); if (ret < 0) - goto out_sleep; + return ret; ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); @@ -2566,12 +2523,65 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (conf->power_level != wlvif->power_level) { ret = wl1271_acx_tx_power(wl, wlvif, conf->power_level); if (ret < 0) - goto out_sleep; + return ret; - wl->power_level = conf->power_level; wlvif->power_level = conf->power_level; } + return 0; +} + +static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) +{ + struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif; + struct ieee80211_conf *conf = &hw->conf; + int channel, ret = 0; + + channel = ieee80211_frequency_to_channel(conf->channel->center_freq); + + wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s" + " changed 0x%x", + channel, + conf->flags & IEEE80211_CONF_PS ? "on" : "off", + conf->power_level, + conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use", + changed); + + /* + * mac80211 will go to idle nearly immediately after transmitting some + * frames, such as the deauth. To make sure those frames reach the air, + * wait here until the TX queue is fully flushed. + */ + if ((changed & IEEE80211_CONF_CHANGE_IDLE) && + (conf->flags & IEEE80211_CONF_IDLE)) + wl1271_tx_flush(wl); + + mutex_lock(&wl->mutex); + + /* we support configuring the channel and band even while off */ + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + wl->band = conf->channel->band; + wl->channel = channel; + } + + if (changed & IEEE80211_CONF_CHANGE_POWER) + wl->power_level = conf->power_level; + + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + + /* configure each interface */ + wl12xx_for_each_wlvif(wl, wlvif) { + ret = wl12xx_config_vif(wl, wlvif, conf, changed); + if (ret < 0) + goto out_sleep; + } + out_sleep: wl1271_ps_elp_sleep(wl); From 6e8cd3310491b10db20d0f7eaf5713b05fa7b753 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:13 +0200 Subject: [PATCH 53/97] wl12xx: replace all remaining wl->vif references wl->vif is appropriate only when a single vif is being used. Instead, pass wlvif as parameter or iterate through all the vifs (e.g. when a global configuration was changed) Leave wl->vif only to determine whether a vif was already added (this check will be removed as well after both the driver and fw will support multiple vifs) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 15 ++-- drivers/net/wireless/wl12xx/debugfs.c | 11 +-- drivers/net/wireless/wl12xx/main.c | 112 ++++++++++++++++---------- drivers/net/wireless/wl12xx/ps.c | 11 ++- drivers/net/wireless/wl12xx/ps.h | 5 +- drivers/net/wireless/wl12xx/tx.c | 2 +- 6 files changed, 91 insertions(+), 65 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 4c5c51810fda..65bf9526576d 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -654,7 +654,8 @@ out: int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_start *cmd; - struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; int ret; wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wlvif->role_id); @@ -773,7 +774,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct wl12xx_cmd_role_start *cmd; - struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; int ret; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -1096,10 +1097,11 @@ out: int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 aid) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct sk_buff *skb; int ret = 0; - skb = ieee80211_pspoll_get(wl->hw, wl->vif); + skb = ieee80211_pspoll_get(wl->hw, vif); if (!skb) goto out; @@ -1176,6 +1178,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, __be32 ip_addr) { int ret; + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct wl12xx_arp_rsp_template tmpl; struct ieee80211_hdr_3addr *hdr; struct arphdr *arp_hdr; @@ -1187,8 +1190,8 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | IEEE80211_FCTL_TODS); - memcpy(hdr->addr1, wl->vif->bss_conf.bssid, ETH_ALEN); - memcpy(hdr->addr2, wl->vif->addr, ETH_ALEN); + memcpy(hdr->addr1, vif->bss_conf.bssid, ETH_ALEN); + memcpy(hdr->addr2, vif->addr, ETH_ALEN); memset(hdr->addr3, 0xff, ETH_ALEN); /* llc layer */ @@ -1204,7 +1207,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY); /* arp payload */ - memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN); + memcpy(tmpl.sender_hw, vif->addr, ETH_ALEN); tmpl.sender_ip = ip_addr; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 4abff8274ac3..d6c2d0c1b6cd 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -615,19 +615,12 @@ static ssize_t beacon_filtering_write(struct file *file, size_t count, loff_t *ppos) { struct wl1271 *wl = file->private_data; - struct ieee80211_vif *vif; struct wl12xx_vif *wlvif; char buf[10]; size_t len; unsigned long value; int ret; - if (!wl->vif) - return -EINVAL; - - vif = wl->vif; - wlvif = wl12xx_vif_to_data(vif); - len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; @@ -645,7 +638,9 @@ static ssize_t beacon_filtering_write(struct file *file, if (ret < 0) goto out; - ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value); + wl12xx_for_each_wlvif(wl, wlvif) { + ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value); + } wl1271_ps_elp_sleep(wl); out: diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index b2640edcc3a8..08fc9d464288 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -779,7 +779,9 @@ static int wl1271_plt_init(struct wl1271 *wl) return ret; } -static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) +static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, + struct wl12xx_vif *wlvif, + u8 hlid, u8 tx_pkts) { bool fw_ps, single_sta; @@ -791,7 +793,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) * packets in FW or if the STA is awake. */ if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS) - wl1271_ps_link_end(wl, hlid); + wl12xx_ps_link_end(wl, wlvif, hlid); /* * Start high-level PS if the STA is asleep with enough blocks in FW. @@ -799,7 +801,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) * case FW-memory congestion is not a problem. */ else if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) - wl1271_ps_link_start(wl, hlid, true); + wl12xx_ps_link_start(wl, wlvif, hlid, true); } static void wl12xx_irq_update_links_status(struct wl1271 *wl, @@ -829,15 +831,15 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, lnk->prev_freed_pkts = status->tx_lnk_free_pkts[hlid]; lnk->allocated_pkts -= cnt; - wl12xx_irq_ps_regulate_link(wl, hlid, lnk->allocated_pkts); + wl12xx_irq_ps_regulate_link(wl, wlvif, hlid, + lnk->allocated_pkts); } } static void wl12xx_fw_status(struct wl1271 *wl, struct wl12xx_fw_status *status) { - struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct wl12xx_vif *wlvif; struct timespec ts; u32 old_tx_blk_count = wl->tx_blocks_available; int avail, freed_blocks; @@ -892,8 +894,9 @@ static void wl12xx_fw_status(struct wl1271 *wl, clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); /* for AP update num of allocated TX blocks per link and ps status */ - if (wlvif->bss_type == BSS_TYPE_AP_BSS) + wl12xx_for_each_wlvif_ap(wl, wlvif) { wl12xx_irq_update_links_status(wl, wlvif, status); + } /* update the host-chipset time offset */ getnstimeofday(&ts); @@ -1212,6 +1215,7 @@ static void wl1271_recovery_work(struct work_struct *work) struct wl1271 *wl = container_of(work, struct wl1271, recovery_work); struct wl12xx_vif *wlvif; + struct ieee80211_vif *vif; mutex_lock(&wl->mutex); @@ -1249,7 +1253,12 @@ static void wl1271_recovery_work(struct work_struct *work) } /* reboot the chipset */ - __wl1271_op_remove_interface(wl, wl->vif, false); + while (!list_empty(&wl->wlvif_list)) { + wlvif = list_first_entry(&wl->wlvif_list, + struct wl12xx_vif, list); + vif = wl12xx_wlvif_to_vif(wlvif); + __wl1271_op_remove_interface(wl, vif, false); + } clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); @@ -1721,18 +1730,19 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) { struct wl1271 *wl = hw->priv; - struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct wl12xx_vif *wlvif; int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); WARN_ON(!wow || !wow->any); wl->wow_enabled = true; - ret = wl1271_configure_suspend(wl, wlvif); - if (ret < 0) { - wl1271_warning("couldn't prepare device to suspend"); - return ret; + wl12xx_for_each_wlvif(wl, wlvif) { + ret = wl1271_configure_suspend(wl, wlvif); + if (ret < 0) { + wl1271_warning("couldn't prepare device to suspend"); + return ret; + } } /* flush any remaining work */ wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); @@ -1751,7 +1761,9 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, wl1271_enable_interrupts(wl); flush_work(&wl->tx_work); - flush_delayed_work(&wlvif->pspoll_work); + wl12xx_for_each_wlvif(wl, wlvif) { + flush_delayed_work(&wlvif->pspoll_work); + } flush_delayed_work(&wl->elp_work); return 0; @@ -1760,8 +1772,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, static int wl1271_op_resume(struct ieee80211_hw *hw) { struct wl1271 *wl = hw->priv; - struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct wl12xx_vif *wlvif; unsigned long flags; bool run_irq_work = false; @@ -1785,7 +1796,9 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) wl1271_irq(0, wl); wl1271_enable_interrupts(wl); } - wl1271_configure_resume(wl, wlvif); + wl12xx_for_each_wlvif(wl, wlvif) { + wl1271_configure_resume(wl, wlvif); + } wl->wow_enabled = false; return 0; @@ -2242,6 +2255,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, { struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct wl12xx_vif *iter; mutex_lock(&wl->mutex); @@ -2253,10 +2267,14 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, * wl->vif can be null here if someone shuts down the interface * just when hardware recovery has been started. */ - if (wl->vif) { - WARN_ON(wl->vif != vif); + wl12xx_for_each_wlvif(wl, iter) { + if (iter != wlvif) + continue; + __wl1271_op_remove_interface(wl, vif, true); + break; } + WARN_ON(iter != wlvif); out: mutex_unlock(&wl->mutex); cancel_work_sync(&wl->recovery_work); @@ -2326,8 +2344,10 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) int ret; if (test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + wl12xx_cmd_stop_channel_switch(wl); - ieee80211_chswitch_done(wl->vif, false); + ieee80211_chswitch_done(vif, false); } /* to stop listening to a channel, we disconnect */ @@ -2642,8 +2662,7 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, { struct wl1271_filter_params *fp = (void *)(unsigned long)multicast; struct wl1271 *wl = hw->priv; - struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct wl12xx_vif *wlvif; int ret; @@ -2662,17 +2681,20 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, if (ret < 0) goto out; - if (wlvif->bss_type != BSS_TYPE_AP_BSS) { - if (*total & FIF_ALLMULTI) - ret = wl1271_acx_group_address_tbl(wl, wlvif, false, - NULL, 0); - else if (fp) - ret = wl1271_acx_group_address_tbl(wl, wlvif, - fp->enabled, - fp->mc_list, - fp->mc_list_length); - if (ret < 0) - goto out_sleep; + wl12xx_for_each_wlvif(wl, wlvif) { + if (wlvif->bss_type != BSS_TYPE_AP_BSS) { + if (*total & FIF_ALLMULTI) + ret = wl1271_acx_group_address_tbl(wl, wlvif, + false, + NULL, 0); + else if (fp) + ret = wl1271_acx_group_address_tbl(wl, wlvif, + fp->enabled, + fp->mc_list, + fp->mc_list_length); + if (ret < 0) + goto out_sleep; + } } /* @@ -3162,8 +3184,7 @@ out: static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { struct wl1271 *wl = hw->priv; - struct ieee80211_vif *vif = wl->vif; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct wl12xx_vif *wlvif; int ret = 0; mutex_lock(&wl->mutex); @@ -3177,10 +3198,11 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) if (ret < 0) goto out; - ret = wl1271_acx_rts_threshold(wl, wlvif, value); - if (ret < 0) - wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); - + wl12xx_for_each_wlvif(wl, wlvif) { + ret = wl1271_acx_rts_threshold(wl, wlvif, value); + if (ret < 0) + wl1271_warning("set rts threshold failed: %d", ret); + } wl1271_ps_elp_sleep(wl); out: @@ -3669,7 +3691,7 @@ sta_not_found: wlvif->probereq = NULL; /* re-enable dynamic ps - just in case */ - ieee80211_enable_dyn_ps(wl->vif); + ieee80211_enable_dyn_ps(vif); /* revert back to minimum rates for the current band */ wl1271_set_band_rate(wl, wlvif); @@ -4305,9 +4327,11 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); if (unlikely(wl->state == WL1271_STATE_OFF)) { - mutex_unlock(&wl->mutex); - ieee80211_chswitch_done(wl->vif, false); - return; + wl12xx_for_each_wlvif_sta(wl, wlvif) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + ieee80211_chswitch_done(vif, false); + } + goto out; } ret = wl1271_ps_elp_wakeup(wl); diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 8153408233b5..84a1afac6f53 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -232,9 +232,11 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid) wl1271_handle_tx_low_watermark(wl); } -void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues) +void wl12xx_ps_link_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 hlid, bool clean_queues) { struct ieee80211_sta *sta; + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); if (test_bit(hlid, &wl->ap_ps_map)) return; @@ -244,7 +246,7 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues) clean_queues); rcu_read_lock(); - sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr); + sta = ieee80211_find_sta(vif, wl->links[hlid].addr); if (!sta) { wl1271_error("could not find sta %pM for starting ps", wl->links[hlid].addr); @@ -262,9 +264,10 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues) __set_bit(hlid, &wl->ap_ps_map); } -void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid) +void wl12xx_ps_link_end(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) { struct ieee80211_sta *sta; + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); if (!test_bit(hlid, &wl->ap_ps_map)) return; @@ -274,7 +277,7 @@ void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid) __clear_bit(hlid, &wl->ap_ps_map); rcu_read_lock(); - sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr); + sta = ieee80211_find_sta(vif, wl->links[hlid].addr); if (!sta) { wl1271_error("could not find sta %pM for ending ps", wl->links[hlid].addr); diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/ps.h index 6ad0a0bd29bd..a12052f02026 100644 --- a/drivers/net/wireless/wl12xx/ps.h +++ b/drivers/net/wireless/wl12xx/ps.h @@ -32,8 +32,9 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, void wl1271_ps_elp_sleep(struct wl1271 *wl); int wl1271_ps_elp_wakeup(struct wl1271 *wl); void wl1271_elp_work(struct work_struct *work); -void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); -void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); +void wl12xx_ps_link_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 hlid, bool clean_queues); +void wl12xx_ps_link_end(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); #define WL1271_PS_COMPLETE_TIMEOUT 500 diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 604913ff42bd..185a65d971ff 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -146,7 +146,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, * case FW-memory congestion is not a problem. */ if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) - wl1271_ps_link_start(wl, hlid, true); + wl12xx_ps_link_start(wl, wlvif, hlid, true); } bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) From f02774343030c2794bb58b6150420dfefc31c39f Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:14 +0200 Subject: [PATCH 54/97] wl12xx: call stop() on recovery The recovery work should call stop() after it removed all the existing interfaces. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 08fc9d464288..433a06fae40b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -379,6 +379,7 @@ static bool bug_on_recovery; static void __wl1271_op_remove_interface(struct wl1271 *wl, struct ieee80211_vif *vif, bool reset_tx_queues); +static void wl1271_op_stop(struct ieee80211_hw *hw); static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif); @@ -1220,7 +1221,7 @@ static void wl1271_recovery_work(struct work_struct *work) mutex_lock(&wl->mutex); if (wl->state != WL1271_STATE_ON) - goto out; + goto out_unlock; /* Avoid a recursive recovery */ set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); @@ -1259,6 +1260,8 @@ static void wl1271_recovery_work(struct work_struct *work) vif = wl12xx_wlvif_to_vif(wlvif); __wl1271_op_remove_interface(wl, vif, false); } + mutex_unlock(&wl->mutex); + wl1271_op_stop(wl->hw); clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); @@ -1269,8 +1272,8 @@ static void wl1271_recovery_work(struct work_struct *work) * to restart the HW. */ ieee80211_wake_queues(wl->hw); - -out: + return; +out_unlock: mutex_unlock(&wl->mutex); } From e5a359f873f50cc123d5ca97637caa30fa095bb9 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:15 +0200 Subject: [PATCH 55/97] wl12xx: use dynamic rate policies allocate the rate policies dynamically, instead of using hardcoded indexes. this is needed for proper multi-role configuration. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 6 ++-- drivers/net/wireless/wl12xx/acx.h | 5 --- drivers/net/wireless/wl12xx/init.c | 7 ++-- drivers/net/wireless/wl12xx/main.c | 52 +++++++++++++++++++++++++--- drivers/net/wireless/wl12xx/tx.c | 10 +++--- drivers/net/wireless/wl12xx/wl12xx.h | 13 +++++++ 6 files changed, 72 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 21e74ca4ddb2..e2e46705059d 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -766,7 +766,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) wlvif->basic_rate, wlvif->rate_set); /* configure one basic rate class */ - acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE); + acx->rate_policy_idx = cpu_to_le32(wlvif->sta.basic_rate_idx); acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->basic_rate); acx->rate_policy.short_retry_limit = c->short_retry_limit; acx->rate_policy.long_retry_limit = c->long_retry_limit; @@ -779,7 +779,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) } /* configure one AP supported rate class */ - acx->rate_policy_idx = cpu_to_le32(ACX_TX_AP_FULL_RATE); + acx->rate_policy_idx = cpu_to_le32(wlvif->sta.ap_rate_idx); acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->rate_set); acx->rate_policy.short_retry_limit = c->short_retry_limit; acx->rate_policy.long_retry_limit = c->long_retry_limit; @@ -796,7 +796,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) * (p2p packets should always go out with OFDM rates, even * if we are currently connected to 11b AP) */ - acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE_P2P); + acx->rate_policy_idx = cpu_to_le32(wlvif->sta.p2p_rate_idx); acx->rate_policy.enabled_rates = cpu_to_le32(CONF_TX_RATE_MASK_BASIC_P2P); acx->rate_policy.short_retry_limit = c->short_retry_limit; diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index c06119b053e3..b2d85bea6378 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -654,11 +654,6 @@ struct acx_rate_class { u8 reserved; }; -#define ACX_TX_BASIC_RATE 0 -#define ACX_TX_AP_FULL_RATE 1 -#define ACX_TX_BASIC_RATE_P2P 2 -#define ACX_TX_AP_MODE_MGMT_RATE 4 -#define ACX_TX_AP_MODE_BCST_RATE 5 struct acx_rate_policy { struct acx_header header; diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 74f569099b53..ba286d0a74a8 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -434,7 +434,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) rc.long_retry_limit = 10; rc.short_retry_limit = 10; rc.aflags = 0; - ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_MGMT_RATE); + ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.mgmt_rate_idx); if (ret < 0) return ret; @@ -443,7 +443,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) rc.short_retry_limit = 10; rc.long_retry_limit = 10; rc.aflags = 0; - ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_BCST_RATE); + ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.bcast_rate_idx); if (ret < 0) return ret; @@ -465,7 +465,8 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) rc.short_retry_limit = 10; rc.long_retry_limit = 10; rc.aflags = 0; - ret = wl1271_acx_ap_rate_policy(wl, &rc, i); + ret = wl1271_acx_ap_rate_policy(wl, &rc, + wlvif->ap.ucast_rate_idx[i]); if (ret < 0) return ret; } diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 433a06fae40b..cd2722562e60 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1910,6 +1910,27 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) mutex_unlock(&wl->mutex); } +static int wl12xx_allocate_rate_policy(struct wl1271 *wl, u8 *idx) +{ + u8 policy = find_first_zero_bit(wl->rate_policies_map, + WL12XX_MAX_RATE_POLICIES); + if (policy >= WL12XX_MAX_RATE_POLICIES) + return -EBUSY; + + __set_bit(policy, wl->rate_policies_map); + *idx = policy; + return 0; +} + +static void wl12xx_free_rate_policy(struct wl1271 *wl, u8 *idx) +{ + if (WARN_ON(*idx >= WL12XX_MAX_RATE_POLICIES)) + return; + + __clear_bit(*idx, wl->rate_policies_map); + *idx = WL12XX_MAX_RATE_POLICIES; +} + static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) { switch (wlvif->bss_type) { @@ -1937,6 +1958,7 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + int i; /* clear everything but the persistent data */ memset(wlvif, 0, offsetof(struct wl12xx_vif, persistent)); @@ -1970,11 +1992,18 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) wlvif->bss_type == BSS_TYPE_IBSS) { /* init sta/ibss data */ wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; - + wl12xx_allocate_rate_policy(wl, &wlvif->sta.basic_rate_idx); + wl12xx_allocate_rate_policy(wl, &wlvif->sta.ap_rate_idx); + wl12xx_allocate_rate_policy(wl, &wlvif->sta.p2p_rate_idx); } else { /* init ap data */ wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; + wl12xx_allocate_rate_policy(wl, &wlvif->ap.mgmt_rate_idx); + wl12xx_allocate_rate_policy(wl, &wlvif->ap.bcast_rate_idx); + for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) + wl12xx_allocate_rate_policy(wl, + &wlvif->ap.ucast_rate_idx[i]); } wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; @@ -2181,7 +2210,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, bool reset_tx_queues) { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - int ret; + int i, ret; wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); @@ -2227,10 +2256,23 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, } deinit: /* clear all hlids (except system_hlid) */ - wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; - wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; - wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; + + if (wlvif->bss_type == BSS_TYPE_STA_BSS || + wlvif->bss_type == BSS_TYPE_IBSS) { + wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; + wl12xx_free_rate_policy(wl, &wlvif->sta.basic_rate_idx); + wl12xx_free_rate_policy(wl, &wlvif->sta.ap_rate_idx); + wl12xx_free_rate_policy(wl, &wlvif->sta.p2p_rate_idx); + } else { + wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; + wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; + wl12xx_free_rate_policy(wl, &wlvif->ap.mgmt_rate_idx); + wl12xx_free_rate_policy(wl, &wlvif->ap.bcast_rate_idx); + for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) + wl12xx_free_rate_policy(wl, + &wlvif->ap.ucast_rate_idx[i]); + } wl12xx_tx_reset_wlvif(wl, wlvif); wl1271_free_ap_keys(wl, wlvif); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 185a65d971ff..69ac03f5d54b 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -339,16 +339,16 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, send them with AP rate policies, otherwise use default basic rates */ if (control->control.sta) - rate_idx = ACX_TX_AP_FULL_RATE; + rate_idx = wlvif->sta.ap_rate_idx; else - rate_idx = ACX_TX_BASIC_RATE; + rate_idx = wlvif->sta.basic_rate_idx; } else { if (hlid == wlvif->ap.global_hlid) - rate_idx = ACX_TX_AP_MODE_MGMT_RATE; + rate_idx = wlvif->ap.mgmt_rate_idx; else if (hlid == wlvif->ap.bcast_hlid) - rate_idx = ACX_TX_AP_MODE_BCST_RATE; + rate_idx = wlvif->ap.bcast_rate_idx; else - rate_idx = ac; + rate_idx = wlvif->ap.ucast_rate_idx[ac]; } tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 2689522ba4ed..d169d52f6d1c 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -142,6 +142,8 @@ extern u32 wl12xx_debug_level; #define WL12XX_INVALID_ROLE_ID 0xff #define WL12XX_INVALID_LINK_ID 0xff +#define WL12XX_MAX_RATE_POLICIES 16 + /* Defined by FW as 0. Will not be freed or allocated. */ #define WL12XX_SYSTEM_HLID 0 @@ -396,8 +398,11 @@ struct wl1271 { unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; + unsigned long rate_policies_map[ + BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)]; struct list_head wlvif_list; + u8 sta_count; u8 ap_count; @@ -569,6 +574,10 @@ struct wl12xx_vif { struct { u8 hlid; u8 ba_rx_bitmap; + + u8 basic_rate_idx; + u8 ap_rate_idx; + u8 p2p_rate_idx; } sta; struct { u8 global_hlid; @@ -580,6 +589,10 @@ struct wl12xx_vif { /* recoreded keys - set here before AP startup */ struct wl1271_ap_key *recorded_keys[MAX_NUM_KEYS]; + + u8 mgmt_rate_idx; + u8 bcast_rate_idx; + u8 ucast_rate_idx[CONF_TX_MAX_AC_COUNT]; } ap; }; From f750c82045d8f5d0d6d59e517eb485ffbbe014b2 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:16 +0200 Subject: [PATCH 56/97] wl12xx: add elp wakeup/sleep calls to add_interface add_interface might be called while the chip is in elp. add elp_wakeup/sleep calls to handle it. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index cd2722562e60..6e6ac63fb8cd 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2115,6 +2115,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, ieee80211_vif_type_p2p(vif), vif->addr); mutex_lock(&wl->mutex); + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out_unlock; + if (wl->vif) { wl1271_debug(DEBUG_MAC80211, "multiple vifs are not supported yet"); @@ -2195,6 +2199,8 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, else wl->sta_count++; out: + wl1271_ps_elp_sleep(wl); +out_unlock: mutex_unlock(&wl->mutex); mutex_lock(&wl_list_mutex); From e4120df982c2051f3cfc02f6278798c5166a72f8 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:17 +0200 Subject: [PATCH 57/97] wl12xx: use round-robin policy for tx Currently, a single vif might starve all the other vifs. Save the last vif we dequeued a packet from, and continue with the following one using a round-robin policy. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 2 ++ drivers/net/wireless/wl12xx/tx.c | 26 ++++++++++++++++++++------ drivers/net/wireless/wl12xx/wl12xx.h | 6 ++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 6e6ac63fb8cd..f29d18daaa82 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2282,6 +2282,8 @@ deinit: wl12xx_tx_reset_wlvif(wl, wlvif); wl1271_free_ap_keys(wl, wlvif); + if (wl->last_wlvif == wlvif) + wl->last_wlvif = NULL; list_del(&wlvif->list); memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map)); wlvif->role_id = WL12XX_INVALID_ROLE_ID; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 69ac03f5d54b..5aeef95229eb 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -590,14 +590,28 @@ static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl, static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) { unsigned long flags; - struct wl12xx_vif *wlvif; + struct wl12xx_vif *wlvif = wl->last_wlvif; struct sk_buff *skb = NULL; - /* TODO: rememeber last vif and consider it */ - wl12xx_for_each_wlvif(wl, wlvif) { - skb = wl12xx_vif_skb_dequeue(wl, wlvif); - if (skb) - break; + if (wlvif) { + wl12xx_for_each_wlvif_continue(wl, wlvif) { + skb = wl12xx_vif_skb_dequeue(wl, wlvif); + if (skb) { + wl->last_wlvif = wlvif; + break; + } + } + } + + /* do another pass */ + if (!skb) { + wl12xx_for_each_wlvif(wl, wlvif) { + skb = wl12xx_vif_skb_dequeue(wl, wlvif); + if (skb) { + wl->last_wlvif = wlvif; + break; + } + } } if (!skb && diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index d169d52f6d1c..8815fd9a0f47 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -552,6 +552,9 @@ struct wl1271 { /* AP-mode - number of currently connected stations */ int active_sta_count; + + /* last wlvif we transmitted from */ + struct wl12xx_vif *last_wlvif; }; struct wl1271_station { @@ -693,6 +696,9 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif) #define wl12xx_for_each_wlvif(wl, wlvif) \ list_for_each_entry(wlvif, &wl->wlvif_list, list) +#define wl12xx_for_each_wlvif_continue(wl, wlvif) \ + list_for_each_entry_continue(wlvif, &wl->wlvif_list, list) + #define wl12xx_for_each_wlvif_bss_type(wl, wlvif, _bss_type) \ wl12xx_for_each_wlvif(wl, wlvif) \ if (wlvif->bss_type == _bss_type) From c7e7c227b63836933ef736fa2d7cc526174b1563 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 6 Oct 2011 22:59:37 +0300 Subject: [PATCH 58/97] wl12xx: remove sdio_test module This module has been causing more trouble than being useful. It only tests the SDIO speed by connecting to the wl12xx chip and does some throughput calculations. It is an ugly quick hack and, if we really want to have it as part of wl12xx we need to clean it up and implement it properly. A tarball of the code has been created and posted here, with some instructions: http://wireless.kernel.org/en/users/Drivers/wl12xx#SDIO_performance_test_module Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/Kconfig | 10 - drivers/net/wireless/wl12xx/Makefile | 3 - drivers/net/wireless/wl12xx/sdio_test.c | 543 ------------------------ 3 files changed, 556 deletions(-) delete mode 100644 drivers/net/wireless/wl12xx/sdio_test.c diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 3fe388b87c2e..af08c8609c63 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -42,16 +42,6 @@ config WL12XX_SDIO If you choose to build a module, it'll be called wl12xx_sdio. Say N if unsure. -config WL12XX_SDIO_TEST - tristate "TI wl12xx SDIO testing support" - depends on WL12XX && MMC && WL12XX_SDIO - default n - ---help--- - This module adds support for the SDIO bus testing with the - TI wl12xx chipsets. You probably don't want this unless you are - testing a new hardware platform. Select this if you want to test the - SDIO bus which is connected to the wl12xx chip. - config WL12XX_PLATFORM_DATA bool depends on WL12XX_SDIO != n || WL1251_SDIO != n diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 621b3483ca2c..fe67262ba19f 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile @@ -3,14 +3,11 @@ wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ wl12xx_spi-objs = spi.o wl12xx_sdio-objs = sdio.o -wl12xx_sdio_test-objs = sdio_test.o wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o obj-$(CONFIG_WL12XX) += wl12xx.o obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o -obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o - # small builtin driver bit obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c deleted file mode 100644 index f25d5d9212e7..000000000000 --- a/drivers/net/wireless/wl12xx/sdio_test.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * SDIO testing driver for wl12xx - * - * Copyright (C) 2010 Nokia Corporation - * - * Contact: Roger Quadros - * - * wl12xx read/write routines taken from the main module - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wl12xx.h" -#include "io.h" -#include "boot.h" - -#ifndef SDIO_VENDOR_ID_TI -#define SDIO_VENDOR_ID_TI 0x0097 -#endif - -#ifndef SDIO_DEVICE_ID_TI_WL1271 -#define SDIO_DEVICE_ID_TI_WL1271 0x4076 -#endif - -static bool rx, tx; - -module_param(rx, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(rx, "Perform rx test. Default (0). " - "This test continuously reads data from the SDIO device.\n"); - -module_param(tx, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(tx, "Perform tx test. Default (0). " - "This test continuously writes data to the SDIO device.\n"); - -struct wl1271_test { - struct wl1271 wl; - struct task_struct *test_task; -}; - -static const struct sdio_device_id wl1271_devices[] = { - { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, - {} -}; - -static inline struct sdio_func *wl_to_func(struct wl1271 *wl) -{ - return wl->if_priv; -} - -static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) -{ - return &(wl_to_func(wl)->dev); -} - -static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed) -{ - int ret = 0; - struct sdio_func *func = wl_to_func(wl); - - if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { - ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); - wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", - addr, ((u8 *)buf)[0]); - } else { - if (fixed) - ret = sdio_readsb(func, buf, addr, len); - else - ret = sdio_memcpy_fromio(func, buf, addr, len); - - wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes", - addr, len); - wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); - } - - if (ret) - wl1271_error("sdio read failed (%d)", ret); -} - -static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed) -{ - int ret = 0; - struct sdio_func *func = wl_to_func(wl); - - if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { - sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); - wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", - addr, ((u8 *)buf)[0]); - } else { - wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes", - addr, len); - wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); - - if (fixed) - ret = sdio_writesb(func, addr, buf, len); - else - ret = sdio_memcpy_toio(func, addr, buf, len); - } - if (ret) - wl1271_error("sdio write failed (%d)", ret); - -} - -static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) -{ - struct sdio_func *func = wl_to_func(wl); - int ret; - - /* Let the SDIO stack handle wlan_enable control, so we - * keep host claimed while wlan is in use to keep wl1271 - * alive. - */ - if (enable) { - /* Power up the card */ - ret = pm_runtime_get_sync(&func->dev); - if (ret < 0) - goto out; - - /* Runtime PM might be disabled, power up the card manually */ - ret = mmc_power_restore_host(func->card->host); - if (ret < 0) - goto out; - - sdio_claim_host(func); - sdio_enable_func(func); - } else { - sdio_disable_func(func); - sdio_release_host(func); - - /* Runtime PM might be disabled, power off the card manually */ - ret = mmc_power_save_host(func->card->host); - if (ret < 0) - goto out; - - /* Power down the card */ - ret = pm_runtime_put_sync(&func->dev); - } - -out: - return ret; -} - -static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) -{ -} - -static void wl1271_sdio_enable_interrupts(struct wl1271 *wl) -{ -} - - -static struct wl1271_if_operations sdio_ops = { - .read = wl1271_sdio_raw_read, - .write = wl1271_sdio_raw_write, - .power = wl1271_sdio_set_power, - .dev = wl1271_sdio_wl_to_dev, - .enable_irq = wl1271_sdio_enable_interrupts, - .disable_irq = wl1271_sdio_disable_interrupts, -}; - -static void wl1271_fw_wakeup(struct wl1271 *wl) -{ - u32 elp_reg; - - elp_reg = ELPCTRL_WAKE_UP; - wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); -} - -static int wl1271_fetch_firmware(struct wl1271 *wl) -{ - const struct firmware *fw; - int ret; - - if (wl->chip.id == CHIP_ID_1283_PG20) - ret = request_firmware(&fw, WL128X_FW_NAME, - wl1271_wl_to_dev(wl)); - else - ret = request_firmware(&fw, WL127X_FW_NAME, - wl1271_wl_to_dev(wl)); - - if (ret < 0) { - wl1271_error("could not get firmware: %d", ret); - return ret; - } - - if (fw->size % 4) { - wl1271_error("firmware size is not multiple of 32 bits: %zu", - fw->size); - ret = -EILSEQ; - goto out; - } - - wl->fw_len = fw->size; - wl->fw = vmalloc(wl->fw_len); - - if (!wl->fw) { - wl1271_error("could not allocate memory for the firmware"); - ret = -ENOMEM; - goto out; - } - - memcpy(wl->fw, fw->data, wl->fw_len); - - ret = 0; - -out: - release_firmware(fw); - - return ret; -} - -static int wl1271_fetch_nvs(struct wl1271 *wl) -{ - const struct firmware *fw; - int ret; - - ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); - - if (ret < 0) { - wl1271_error("could not get nvs file: %d", ret); - return ret; - } - - wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); - - if (!wl->nvs) { - wl1271_error("could not allocate memory for the nvs file"); - ret = -ENOMEM; - goto out; - } - - wl->nvs_len = fw->size; - -out: - release_firmware(fw); - - return ret; -} - -static int wl1271_chip_wakeup(struct wl1271 *wl) -{ - struct wl1271_partition_set partition; - int ret; - - msleep(WL1271_PRE_POWER_ON_SLEEP); - ret = wl1271_power_on(wl); - if (ret) - return ret; - - msleep(WL1271_POWER_ON_SLEEP); - - /* We don't need a real memory partition here, because we only want - * to use the registers at this point. */ - memset(&partition, 0, sizeof(partition)); - partition.reg.start = REGISTERS_BASE; - partition.reg.size = REGISTERS_DOWN_SIZE; - wl1271_set_partition(wl, &partition); - - /* ELP module wake up */ - wl1271_fw_wakeup(wl); - - /* whal_FwCtrl_BootSm() */ - - /* 0. read chip id from CHIP_ID */ - wl->chip.id = wl1271_read32(wl, CHIP_ID_B); - - /* 1. check if chip id is valid */ - - switch (wl->chip.id) { - case CHIP_ID_1271_PG10: - wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", - wl->chip.id); - break; - case CHIP_ID_1271_PG20: - wl1271_notice("chip id 0x%x (1271 PG20)", - wl->chip.id); - break; - case CHIP_ID_1283_PG20: - wl1271_notice("chip id 0x%x (1283 PG20)", - wl->chip.id); - break; - case CHIP_ID_1283_PG10: - default: - wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); - return -ENODEV; - } - - return ret; -} - -static struct wl1271_partition_set part_down = { - .mem = { - .start = 0x00000000, - .size = 0x000177c0 - }, - .reg = { - .start = REGISTERS_BASE, - .size = 0x00008800 - }, - .mem2 = { - .start = 0x00000000, - .size = 0x00000000 - }, - .mem3 = { - .start = 0x00000000, - .size = 0x00000000 - }, -}; - -static int tester(void *data) -{ - struct wl1271 *wl = data; - struct sdio_func *func = wl_to_func(wl); - struct device *pdev = &func->dev; - int ret = 0; - bool rx_started = 0; - bool tx_started = 0; - uint8_t *tx_buf, *rx_buf; - int test_size = PAGE_SIZE; - u32 addr = 0; - struct wl1271_partition_set partition; - - /* We assume chip is powered up and firmware fetched */ - - memcpy(&partition, &part_down, sizeof(partition)); - partition.mem.start = addr; - wl1271_set_partition(wl, &partition); - - tx_buf = kmalloc(test_size, GFP_KERNEL); - rx_buf = kmalloc(test_size, GFP_KERNEL); - if (!tx_buf || !rx_buf) { - dev_err(pdev, - "Could not allocate memory. Test will not run.\n"); - ret = -ENOMEM; - goto free; - } - - memset(tx_buf, 0x5a, test_size); - - /* write something in data area so we can read it back */ - wl1271_write(wl, addr, tx_buf, test_size, false); - - while (!kthread_should_stop()) { - if (rx && !rx_started) { - dev_info(pdev, "starting rx test\n"); - rx_started = 1; - } else if (!rx && rx_started) { - dev_info(pdev, "stopping rx test\n"); - rx_started = 0; - } - - if (tx && !tx_started) { - dev_info(pdev, "starting tx test\n"); - tx_started = 1; - } else if (!tx && tx_started) { - dev_info(pdev, "stopping tx test\n"); - tx_started = 0; - } - - if (rx_started) - wl1271_read(wl, addr, rx_buf, test_size, false); - - if (tx_started) - wl1271_write(wl, addr, tx_buf, test_size, false); - - if (!rx_started && !tx_started) - msleep(100); - } - -free: - kfree(tx_buf); - kfree(rx_buf); - return ret; -} - -static int __devinit wl1271_probe(struct sdio_func *func, - const struct sdio_device_id *id) -{ - const struct wl12xx_platform_data *wlan_data; - struct wl1271 *wl; - struct wl1271_test *wl_test; - int ret = 0; - - /* wl1271 has 2 sdio functions we handle just the wlan part */ - if (func->num != 0x02) - return -ENODEV; - - wl_test = kzalloc(sizeof(struct wl1271_test), GFP_KERNEL); - if (!wl_test) { - dev_err(&func->dev, "Could not allocate memory\n"); - return -ENOMEM; - } - - wl = &wl_test->wl; - - wl->if_priv = func; - wl->if_ops = &sdio_ops; - - /* Grab access to FN0 for ELP reg. */ - func->card->quirks |= MMC_QUIRK_LENIENT_FN0; - - /* Use block mode for transferring over one block size of data */ - func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; - - wlan_data = wl12xx_get_platform_data(); - if (IS_ERR(wlan_data)) { - ret = PTR_ERR(wlan_data); - dev_err(&func->dev, "missing wlan platform data: %d\n", ret); - goto out_free; - } - - wl->irq = wlan_data->irq; - wl->ref_clock = wlan_data->board_ref_clock; - wl->tcxo_clock = wlan_data->board_tcxo_clock; - - sdio_set_drvdata(func, wl_test); - - /* power up the device */ - ret = wl1271_chip_wakeup(wl); - if (ret) { - dev_err(&func->dev, "could not wake up chip\n"); - goto out_free; - } - - if (wl->fw == NULL) { - ret = wl1271_fetch_firmware(wl); - if (ret < 0) { - dev_err(&func->dev, "firmware fetch error\n"); - goto out_off; - } - } - - /* fetch NVS */ - if (wl->nvs == NULL) { - ret = wl1271_fetch_nvs(wl); - if (ret < 0) { - dev_err(&func->dev, "NVS fetch error\n"); - goto out_off; - } - } - - ret = wl1271_load_firmware(wl); - if (ret < 0) { - dev_err(&func->dev, "firmware load error: %d\n", ret); - goto out_free; - } - - dev_info(&func->dev, "initialized\n"); - - /* I/O testing will be done in the tester thread */ - - wl_test->test_task = kthread_run(tester, wl, "sdio_tester"); - if (IS_ERR(wl_test->test_task)) { - dev_err(&func->dev, "unable to create kernel thread\n"); - ret = PTR_ERR(wl_test->test_task); - goto out_free; - } - - return 0; - -out_off: - /* power off the chip */ - wl1271_power_off(wl); - -out_free: - kfree(wl_test); - return ret; -} - -static void __devexit wl1271_remove(struct sdio_func *func) -{ - struct wl1271_test *wl_test = sdio_get_drvdata(func); - - /* stop the I/O test thread */ - kthread_stop(wl_test->test_task); - - /* power off the chip */ - wl1271_power_off(&wl_test->wl); - - vfree(wl_test->wl.fw); - wl_test->wl.fw = NULL; - kfree(wl_test->wl.nvs); - wl_test->wl.nvs = NULL; - - kfree(wl_test); -} - -static struct sdio_driver wl1271_sdio_driver = { - .name = "wl12xx_sdio_test", - .id_table = wl1271_devices, - .probe = wl1271_probe, - .remove = __devexit_p(wl1271_remove), -}; - -static int __init wl1271_init(void) -{ - int ret; - - ret = sdio_register_driver(&wl1271_sdio_driver); - if (ret < 0) - pr_err("failed to register sdio driver: %d\n", ret); - - return ret; -} -module_init(wl1271_init); - -static void __exit wl1271_exit(void) -{ - sdio_unregister_driver(&wl1271_sdio_driver); -} -module_exit(wl1271_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Roger Quadros "); - From fbe936bcb59d8e6e054c325a441082b55538bf8f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 4 Oct 2011 23:10:28 +0300 Subject: [PATCH 59/97] wl12xx: add an sdio glue struct to keep wl and device side-by-side In order to fully abstract the bus, we need to save the device structure *beside* wl1271, instead of inside it. This will help re-structuring the driver so that we avoid the duplicated code in the bus modules. Signed-off-by: Felipe Balbi [forward-ported and cleaned up and rephrased commit message] Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/sdio.c | 59 ++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 516a8980723c..5a4268012da4 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -44,6 +44,11 @@ #define SDIO_DEVICE_ID_TI_WL1271 0x4076 #endif +struct wl12xx_sdio_glue { + struct device *dev; + struct wl1271 *wl; +}; + static const struct sdio_device_id wl1271_devices[] __devinitconst = { { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, {} @@ -57,14 +62,14 @@ static void wl1271_sdio_set_block_size(struct wl1271 *wl, unsigned int blksz) sdio_release_host(wl->if_priv); } -static inline struct sdio_func *wl_to_func(struct wl1271 *wl) +static inline struct wl12xx_sdio_glue *wl_to_glue(struct wl1271 *wl) { return wl->if_priv; } static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) { - return &(wl_to_func(wl)->dev); + return wl_to_glue(wl)->dev; } static irqreturn_t wl1271_hardirq(int irq, void *cookie) @@ -110,7 +115,8 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { int ret; - struct sdio_func *func = wl_to_func(wl); + struct wl12xx_sdio_glue *glue = wl_to_glue(wl); + struct sdio_func *func = dev_to_sdio_func(glue->dev); if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); @@ -135,7 +141,8 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { int ret; - struct sdio_func *func = wl_to_func(wl); + struct wl12xx_sdio_glue *glue = wl_to_glue(wl); + struct sdio_func *func = dev_to_sdio_func(glue->dev); if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); @@ -158,8 +165,9 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, static int wl1271_sdio_power_on(struct wl1271 *wl) { - struct sdio_func *func = wl_to_func(wl); int ret; + struct wl12xx_sdio_glue *glue = wl_to_glue(wl); + struct sdio_func *func = dev_to_sdio_func(glue->dev); /* If enabled, tell runtime PM not to power off the card */ if (pm_runtime_enabled(&func->dev)) { @@ -182,8 +190,9 @@ out: static int wl1271_sdio_power_off(struct wl1271 *wl) { - struct sdio_func *func = wl_to_func(wl); int ret; + struct wl12xx_sdio_glue *glue = wl_to_glue(wl); + struct sdio_func *func = dev_to_sdio_func(glue->dev); sdio_disable_func(func); sdio_release_host(func); @@ -224,21 +233,34 @@ static int __devinit wl1271_probe(struct sdio_func *func, struct ieee80211_hw *hw; const struct wl12xx_platform_data *wlan_data; struct wl1271 *wl; + struct wl12xx_sdio_glue *glue; unsigned long irqflags; mmc_pm_flag_t mmcflags; - int ret; + int ret = -ENOMEM; /* We are only able to handle the wlan function */ if (func->num != 0x02) return -ENODEV; + glue = kzalloc(sizeof(*glue), GFP_KERNEL); + if (!glue) { + wl1271_error("can't allocate glue"); + goto out; + } + hw = wl1271_alloc_hw(); - if (IS_ERR(hw)) - return PTR_ERR(hw); + if (IS_ERR(hw)) { + wl1271_error("can't allocate hw"); + ret = PTR_ERR(hw); + goto out_free_glue; + } wl = hw->priv; - wl->if_priv = func; + glue->dev = &func->dev; + glue->wl = wl; + + wl->if_priv = glue; wl->if_ops = &sdio_ops; /* Grab access to FN0 for ELP reg. */ @@ -251,7 +273,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, if (IS_ERR(wlan_data)) { ret = PTR_ERR(wlan_data); wl1271_error("missing wlan platform data: %d", ret); - goto out_free; + goto out_free_hw; } wl->irq = wlan_data->irq; @@ -269,7 +291,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); - goto out_free; + goto out_free_hw; } ret = enable_irq_wake(wl->irq); @@ -294,25 +316,29 @@ static int __devinit wl1271_probe(struct sdio_func *func, if (ret) goto out_irq; - sdio_set_drvdata(func, wl); + sdio_set_drvdata(func, glue); /* Tell PM core that we don't need the card to be powered now */ pm_runtime_put_noidle(&func->dev); return 0; - out_irq: +out_irq: free_irq(wl->irq, wl); - out_free: +out_free_hw: wl1271_free_hw(wl); +out_free_glue: + kfree(glue); +out: return ret; } static void __devexit wl1271_remove(struct sdio_func *func) { - struct wl1271 *wl = sdio_get_drvdata(func); + struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); + struct wl1271 *wl = glue->wl; /* Undo decrement done above in wl1271_probe */ pm_runtime_get_noresume(&func->dev); @@ -324,6 +350,7 @@ static void __devexit wl1271_remove(struct sdio_func *func) } free_irq(wl->irq, wl); wl1271_free_hw(wl); + kfree(glue); } #ifdef CONFIG_PM From b65019f661733ece3be0680be307d238d4dec68e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 4 Oct 2011 23:36:47 +0300 Subject: [PATCH 60/97] wl12xx: add an spi glue struct to keep wl and device side-by-side In order to fully abstract the bus, we need to save the device structure *beside* wl1271, instead of inside it. This will help re-structuring the driver so that we avoid the duplicated code in the bus modules. Signed-off-by: Felipe Balbi [forward-ported and cleaned up and rephrased commit message] Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/spi.c | 67 ++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 0f9718677860..16f0c71f6d4c 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -69,14 +69,19 @@ #define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) -static inline struct spi_device *wl_to_spi(struct wl1271 *wl) +struct wl12xx_spi_glue { + struct device *dev; + struct wl1271 *wl; +}; + +static inline struct wl12xx_spi_glue *wl_to_glue(struct wl1271 *wl) { return wl->if_priv; } static struct device *wl1271_spi_wl_to_dev(struct wl1271 *wl) { - return &(wl_to_spi(wl)->dev); + return wl_to_glue(wl)->dev; } static void wl1271_spi_disable_interrupts(struct wl1271 *wl) @@ -91,6 +96,7 @@ static void wl1271_spi_enable_interrupts(struct wl1271 *wl) static void wl1271_spi_reset(struct wl1271 *wl) { + struct wl12xx_spi_glue *glue = wl_to_glue(wl); u8 *cmd; struct spi_transfer t; struct spi_message m; @@ -110,7 +116,7 @@ static void wl1271_spi_reset(struct wl1271 *wl) t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); - spi_sync(wl_to_spi(wl), &m); + spi_sync(to_spi_device(glue->dev), &m); wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); kfree(cmd); @@ -118,6 +124,7 @@ static void wl1271_spi_reset(struct wl1271 *wl) static void wl1271_spi_init(struct wl1271 *wl) { + struct wl12xx_spi_glue *glue = wl_to_glue(wl); u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; struct spi_transfer t; struct spi_message m; @@ -165,7 +172,7 @@ static void wl1271_spi_init(struct wl1271 *wl) t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); - spi_sync(wl_to_spi(wl), &m); + spi_sync(to_spi_device(glue->dev), &m); wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); kfree(cmd); } @@ -174,6 +181,7 @@ static void wl1271_spi_init(struct wl1271 *wl) static int wl1271_spi_read_busy(struct wl1271 *wl) { + struct wl12xx_spi_glue *glue = wl_to_glue(wl); struct spi_transfer t[1]; struct spi_message m; u32 *busy_buf; @@ -194,7 +202,7 @@ static int wl1271_spi_read_busy(struct wl1271 *wl) t[0].len = sizeof(u32); t[0].cs_change = true; spi_message_add_tail(&t[0], &m); - spi_sync(wl_to_spi(wl), &m); + spi_sync(to_spi_device(glue->dev), &m); if (*busy_buf & 0x1) return 0; @@ -208,6 +216,7 @@ static int wl1271_spi_read_busy(struct wl1271 *wl) static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { + struct wl12xx_spi_glue *glue = wl_to_glue(wl); struct spi_transfer t[2]; struct spi_message m; u32 *busy_buf; @@ -243,7 +252,7 @@ static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, t[1].cs_change = true; spi_message_add_tail(&t[1], &m); - spi_sync(wl_to_spi(wl), &m); + spi_sync(to_spi_device(glue->dev), &m); if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && wl1271_spi_read_busy(wl)) { @@ -259,7 +268,7 @@ static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, t[0].cs_change = true; spi_message_add_tail(&t[0], &m); - spi_sync(wl_to_spi(wl), &m); + spi_sync(to_spi_device(glue->dev), &m); wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, chunk_len); @@ -274,6 +283,7 @@ static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { + struct wl12xx_spi_glue *glue = wl_to_glue(wl); struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; struct spi_message m; u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; @@ -318,7 +328,7 @@ static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, cmd++; } - spi_sync(wl_to_spi(wl), &m); + spi_sync(to_spi_device(glue->dev), &m); } static irqreturn_t wl1271_hardirq(int irq, void *cookie) @@ -362,11 +372,12 @@ static struct wl1271_if_operations spi_ops = { static int __devinit wl1271_probe(struct spi_device *spi) { + struct wl12xx_spi_glue *glue; struct wl12xx_platform_data *pdata; struct ieee80211_hw *hw; struct wl1271 *wl; unsigned long irqflags; - int ret; + int ret = -ENOMEM; pdata = spi->dev.platform_data; if (!pdata) { @@ -374,14 +385,25 @@ static int __devinit wl1271_probe(struct spi_device *spi) return -ENODEV; } + glue = kzalloc(sizeof(*glue), GFP_KERNEL); + if (!glue) { + wl1271_error("can't allocate glue"); + goto out; + } + hw = wl1271_alloc_hw(); - if (IS_ERR(hw)) - return PTR_ERR(hw); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto out_free_glue; + } wl = hw->priv; - dev_set_drvdata(&spi->dev, wl); - wl->if_priv = spi; + glue->dev = &spi->dev; + glue->wl = wl; + + spi_set_drvdata(spi, glue); + wl->if_priv = glue; wl->if_ops = &spi_ops; @@ -392,14 +414,14 @@ static int __devinit wl1271_probe(struct spi_device *spi) ret = spi_setup(spi); if (ret < 0) { wl1271_error("spi_setup failed"); - goto out_free; + goto out_free_hw; } wl->set_power = pdata->set_power; if (!wl->set_power) { wl1271_error("set power function missing in platform data"); ret = -ENODEV; - goto out_free; + goto out_free_hw; } wl->ref_clock = pdata->board_ref_clock; @@ -415,7 +437,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) if (wl->irq < 0) { wl1271_error("irq missing in platform data"); ret = -ENODEV; - goto out_free; + goto out_free_hw; } ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, @@ -423,7 +445,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) DRIVER_NAME, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); - goto out_free; + goto out_free_hw; } disable_irq(wl->irq); @@ -438,22 +460,27 @@ static int __devinit wl1271_probe(struct spi_device *spi) return 0; - out_irq: +out_irq: free_irq(wl->irq, wl); - out_free: +out_free_hw: wl1271_free_hw(wl); +out_free_glue: + kfree(glue); +out: return ret; } static int __devexit wl1271_remove(struct spi_device *spi) { - struct wl1271 *wl = dev_get_drvdata(&spi->dev); + struct wl12xx_spi_glue *glue = spi_get_drvdata(spi); + struct wl1271 *wl = glue->wl; wl1271_unregister_hw(wl); free_irq(wl->irq, wl); wl1271_free_hw(wl); + kfree(glue); return 0; } From 025aef8fcfbdf680376c4f7aa31b9ac85cebc700 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 5 Oct 2011 09:00:12 +0300 Subject: [PATCH 61/97] wl12xx: add a platform device to the sdio module The platform device will be used to match the platform driver that will be implemented by the core module. Signed-off-by: Felipe Balbi [forward-ported, cleaned-up and rephrased commit message] [call platform_device_add() instead of platform_device_register()] [store alloc'ed device platform directly in glue->core] [fixed the length of memset(res...)] Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/sdio.c | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 5a4268012da4..e7ee5d155d34 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ struct wl12xx_sdio_glue { struct device *dev; struct wl1271 *wl; + struct platform_device *core; }; static const struct sdio_device_id wl1271_devices[] __devinitconst = { @@ -234,6 +236,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, const struct wl12xx_platform_data *wlan_data; struct wl1271 *wl; struct wl12xx_sdio_glue *glue; + struct resource res[1]; unsigned long irqflags; mmc_pm_flag_t mmcflags; int ret = -ENOMEM; @@ -321,8 +324,47 @@ static int __devinit wl1271_probe(struct sdio_func *func, /* Tell PM core that we don't need the card to be powered now */ pm_runtime_put_noidle(&func->dev); + glue->core = platform_device_alloc("wl12xx-sdio", -1); + if (!glue->core) { + wl1271_error("can't allocate platform_device"); + ret = -ENOMEM; + goto out_unreg_hw; + } + + glue->core->dev.parent = &func->dev; + + memset(res, 0x00, sizeof(res)); + + res[0].start = wlan_data->irq; + res[0].flags = IORESOURCE_IRQ; + res[0].name = "irq"; + + ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); + if (ret) { + wl1271_error("can't add resources"); + goto out_dev_put; + } + + ret = platform_device_add_data(glue->core, wlan_data, + sizeof(*wlan_data)); + if (ret) { + wl1271_error("can't add platform data"); + goto out_dev_put; + } + + ret = platform_device_add(glue->core); + if (ret) { + wl1271_error("can't add platform device"); + goto out_dev_put; + } return 0; +out_dev_put: + platform_device_put(glue->core); + +out_unreg_hw: + wl1271_unregister_hw(wl); + out_irq: free_irq(wl->irq, wl); @@ -350,6 +392,8 @@ static void __devexit wl1271_remove(struct sdio_func *func) } free_irq(wl->irq, wl); wl1271_free_hw(wl); + platform_device_del(glue->core); + platform_device_put(glue->core); kfree(glue); } From 0969d6793f4899a4c5f56443d50f272068b97142 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 5 Oct 2011 09:29:13 +0300 Subject: [PATCH 62/97] wl12xx: add a platform device to the spi module The platform device will be used to match the platform driver that will be implemented by the core module. Signed-off-by: Felipe Balbi [forward-ported, cleaned-up and rephrased commit message] [call platform_device_add() instead of platform_device_register()] [store alloc'ed device platform directly in glue->core] [fixed the length of memset(res...)] Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/spi.c | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 16f0c71f6d4c..2dd659886a04 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "wl12xx.h" @@ -72,6 +73,7 @@ struct wl12xx_spi_glue { struct device *dev; struct wl1271 *wl; + struct platform_device *core; }; static inline struct wl12xx_spi_glue *wl_to_glue(struct wl1271 *wl) @@ -376,6 +378,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) struct wl12xx_platform_data *pdata; struct ieee80211_hw *hw; struct wl1271 *wl; + struct resource res[1]; unsigned long irqflags; int ret = -ENOMEM; @@ -458,8 +461,47 @@ static int __devinit wl1271_probe(struct spi_device *spi) if (ret) goto out_irq; + glue->core = platform_device_alloc("wl12xx-spi", -1); + if (!glue->core) { + wl1271_error("can't allocate platform_device"); + ret = -ENOMEM; + goto out_unreg_hw; + } + + glue->core->dev.parent = &spi->dev; + + memset(res, 0x00, sizeof(res)); + + res[0].start = spi->irq; + res[0].flags = IORESOURCE_IRQ; + res[0].name = "irq"; + + ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); + if (ret) { + wl1271_error("can't add resources"); + goto out_dev_put; + } + + ret = platform_device_add_data(glue->core, pdata, sizeof(*pdata)); + if (ret) { + wl1271_error("can't add platform data"); + goto out_dev_put; + } + + ret = platform_device_add(glue->core); + if (ret) { + wl1271_error("can't register platform device"); + goto out_dev_put; + } + return 0; +out_dev_put: + platform_device_put(glue->core); + +out_unreg_hw: + wl1271_unregister_hw(wl); + out_irq: free_irq(wl->irq, wl); @@ -480,6 +522,8 @@ static int __devexit wl1271_remove(struct spi_device *spi) wl1271_unregister_hw(wl); free_irq(wl->irq, wl); wl1271_free_hw(wl); + platform_device_del(glue->core); + platform_device_put(glue->core); kfree(glue); return 0; From ce2a217c8268906640ebf7291d7a06210a35dd2f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 5 Oct 2011 14:12:55 +0300 Subject: [PATCH 63/97] wl12xx: add platform driver to the core module Nnow that we have a platform_device on both glue layers, add a platform_driver to the core driver. It's currently an empty platform_driver but more functionality will be added on later patches. Signed-off-by: Felipe Balbi [forward-ported, cleaned-up and rephrased commit message] [added platform_driver.driver initialization] Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index f29d18daaa82..3262e8a6c475 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -5200,6 +5200,45 @@ int wl1271_free_hw(struct wl1271 *wl) } EXPORT_SYMBOL_GPL(wl1271_free_hw); +static int __devinit wl12xx_probe(struct platform_device *pdev) +{ + return 0; +} + +static int __devexit wl12xx_remove(struct platform_device *pdev) +{ + return 0; +} + +static const struct platform_device_id wl12xx_id_table[] __devinitconst = { + { "wl12xx-sdio", 0 }, + { "wl12xx-spi", 0 }, + { } /* Terminating Entry */ +}; +MODULE_DEVICE_TABLE(platform, wl12xx_id_table); + +static struct platform_driver wl12xx_driver = { + .probe = wl12xx_probe, + .remove = __devexit_p(wl12xx_remove), + .id_table = wl12xx_id_table, + .driver = { + .name = "wl12xx", + .owner = THIS_MODULE, + } +}; + +static int __init wl12xx_init(void) +{ + return platform_driver_register(&wl12xx_driver); +} +module_init(wl12xx_init); + +static void __exit wl12xx_exit(void) +{ + platform_driver_unregister(&wl12xx_driver); +} +module_exit(wl12xx_exit); + u32 wl12xx_debug_level = DEBUG_NONE; EXPORT_SYMBOL_GPL(wl12xx_debug_level); module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR); From a390e85cfe91c346ff4745bcd45ad0a7e7101aa2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Oct 2011 10:07:44 +0300 Subject: [PATCH 64/97] wl12xx: move common init code from bus modules to main Move all common parts from sdio.c and spi.c to main.c, since they now can be handled as part of the platform driver. Signed-off-by: Felipe Balbi [forward-ported, cleaned-up and rephrased commit message] [added a bunch of fixes and a new pdata element] [moved some new code into main.c as well] Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/io.c | 11 +- drivers/net/wireless/wl12xx/io.h | 14 +- drivers/net/wireless/wl12xx/main.c | 110 ++++++++++- drivers/net/wireless/wl12xx/sdio.c | 176 ++++-------------- drivers/net/wireless/wl12xx/spi.c | 161 +++------------- drivers/net/wireless/wl12xx/wl12xx.h | 17 +- .../wireless/wl12xx/wl12xx_platform_data.c | 4 +- include/linux/wl12xx.h | 5 +- 8 files changed, 185 insertions(+), 313 deletions(-) diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c index c2da66f45046..1a7df8a7ed2d 100644 --- a/drivers/net/wireless/wl12xx/io.c +++ b/drivers/net/wireless/wl12xx/io.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "wl12xx.h" #include "wl12xx_80211.h" @@ -46,7 +47,7 @@ bool wl1271_set_block_size(struct wl1271 *wl) { if (wl->if_ops->set_block_size) { - wl->if_ops->set_block_size(wl, WL12XX_BUS_BLOCK_SIZE); + wl->if_ops->set_block_size(wl->dev, WL12XX_BUS_BLOCK_SIZE); return true; } @@ -55,12 +56,12 @@ bool wl1271_set_block_size(struct wl1271 *wl) void wl1271_disable_interrupts(struct wl1271 *wl) { - wl->if_ops->disable_irq(wl); + disable_irq(wl->irq); } void wl1271_enable_interrupts(struct wl1271 *wl) { - wl->if_ops->enable_irq(wl); + enable_irq(wl->irq); } /* Set the SPI partitions to access the chip addresses @@ -128,13 +129,13 @@ EXPORT_SYMBOL_GPL(wl1271_set_partition); void wl1271_io_reset(struct wl1271 *wl) { if (wl->if_ops->reset) - wl->if_ops->reset(wl); + wl->if_ops->reset(wl->dev); } void wl1271_io_init(struct wl1271 *wl) { if (wl->if_ops->init) - wl->if_ops->init(wl); + wl->if_ops->init(wl->dev); } void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h index e839341dfafe..e82dad19aa30 100644 --- a/drivers/net/wireless/wl12xx/io.h +++ b/drivers/net/wireless/wl12xx/io.h @@ -51,23 +51,17 @@ void wl1271_enable_interrupts(struct wl1271 *wl); void wl1271_io_reset(struct wl1271 *wl); void wl1271_io_init(struct wl1271 *wl); -static inline struct device *wl1271_wl_to_dev(struct wl1271 *wl) -{ - return wl->if_ops->dev(wl); -} - - /* Raw target IO, address is not translated */ static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { - wl->if_ops->write(wl, addr, buf, len, fixed); + wl->if_ops->write(wl->dev, addr, buf, len, fixed); } static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { - wl->if_ops->read(wl, addr, buf, len, fixed); + wl->if_ops->read(wl->dev, addr, buf, len, fixed); } static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) @@ -155,13 +149,13 @@ static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) static inline void wl1271_power_off(struct wl1271 *wl) { - wl->if_ops->power(wl, false); + wl->if_ops->power(wl->dev, false); clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); } static inline int wl1271_power_on(struct wl1271 *wl) { - int ret = wl->if_ops->power(wl, true); + int ret = wl->if_ops->power(wl->dev, true); if (ret == 0) set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 3262e8a6c475..1cf987785053 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "wl12xx.h" #include "wl12xx_80211.h" @@ -1067,7 +1068,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); - ret = request_firmware(&fw, fw_name, wl1271_wl_to_dev(wl)); + ret = request_firmware(&fw, fw_name, wl->dev); if (ret < 0) { wl1271_error("could not get firmware: %d", ret); @@ -1105,7 +1106,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) const struct firmware *fw; int ret; - ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); + ret = request_firmware(&fw, WL12XX_NVS_NAME, wl->dev); if (ret < 0) { wl1271_error("could not get nvs file: %d", ret); @@ -4979,7 +4980,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->wiphy->reg_notifier = wl1271_reg_notify; - SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); + SET_IEEE80211_DEV(wl->hw, wl->dev); wl->hw->sta_data_size = sizeof(struct wl1271_station); wl->hw->vif_data_size = sizeof(struct wl12xx_vif); @@ -5200,13 +5201,116 @@ int wl1271_free_hw(struct wl1271 *wl) } EXPORT_SYMBOL_GPL(wl1271_free_hw); +static irqreturn_t wl12xx_hardirq(int irq, void *cookie) +{ + struct wl1271 *wl = cookie; + unsigned long flags; + + wl1271_debug(DEBUG_IRQ, "IRQ"); + + /* complete the ELP completion */ + spin_lock_irqsave(&wl->wl_lock, flags); + set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); + if (wl->elp_compl) { + complete(wl->elp_compl); + wl->elp_compl = NULL; + } + + if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { + /* don't enqueue a work right now. mark it as pending */ + set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); + wl1271_debug(DEBUG_IRQ, "should not enqueue work"); + disable_irq_nosync(wl->irq); + pm_wakeup_event(wl->dev, 0); + spin_unlock_irqrestore(&wl->wl_lock, flags); + return IRQ_HANDLED; + } + spin_unlock_irqrestore(&wl->wl_lock, flags); + + return IRQ_WAKE_THREAD; +} + static int __devinit wl12xx_probe(struct platform_device *pdev) { + struct wl12xx_platform_data *pdata = pdev->dev.platform_data; + struct ieee80211_hw *hw; + struct wl1271 *wl; + unsigned long irqflags; + int ret = -ENODEV; + + hw = wl1271_alloc_hw(); + if (IS_ERR(hw)) { + wl1271_error("can't allocate hw"); + ret = PTR_ERR(hw); + goto out; + } + + wl = hw->priv; + wl->irq = platform_get_irq(pdev, 0); + wl->ref_clock = pdata->board_ref_clock; + wl->tcxo_clock = pdata->board_tcxo_clock; + wl->platform_quirks = pdata->platform_quirks; + wl->set_power = pdata->set_power; + wl->dev = &pdev->dev; + wl->if_ops = pdata->ops; + + platform_set_drvdata(pdev, wl); + + if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) + irqflags = IRQF_TRIGGER_RISING; + else + irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; + + ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wl1271_irq, + irqflags, + pdev->name, wl); + if (ret < 0) { + wl1271_error("request_irq() failed: %d", ret); + goto out_free_hw; + } + + ret = enable_irq_wake(wl->irq); + if (!ret) { + wl->irq_wake_enabled = true; + device_init_wakeup(wl->dev, 1); + if (pdata->pwr_in_suspend) + hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; + + } + disable_irq(wl->irq); + + ret = wl1271_init_ieee80211(wl); + if (ret) + goto out_irq; + + ret = wl1271_register_hw(wl); + if (ret) + goto out_irq; + return 0; + +out_irq: + free_irq(wl->irq, wl); + +out_free_hw: + wl1271_free_hw(wl); + +out: + return ret; } static int __devexit wl12xx_remove(struct platform_device *pdev) { + struct wl1271 *wl = platform_get_drvdata(pdev); + + if (wl->irq_wake_enabled) { + device_init_wakeup(wl->dev, 0); + disable_irq_wake(wl->irq); + } + wl1271_unregister_hw(wl); + free_irq(wl->irq, wl); + wl1271_free_hw(wl); + return 0; } diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index e7ee5d155d34..78e5352c4037 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -47,7 +47,6 @@ struct wl12xx_sdio_glue { struct device *dev; - struct wl1271 *wl; struct platform_device *core; }; @@ -57,67 +56,22 @@ static const struct sdio_device_id wl1271_devices[] __devinitconst = { }; MODULE_DEVICE_TABLE(sdio, wl1271_devices); -static void wl1271_sdio_set_block_size(struct wl1271 *wl, unsigned int blksz) +static void wl1271_sdio_set_block_size(struct device *child, + unsigned int blksz) { - sdio_claim_host(wl->if_priv); - sdio_set_block_size(wl->if_priv, blksz); - sdio_release_host(wl->if_priv); + struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); + struct sdio_func *func = dev_to_sdio_func(glue->dev); + + sdio_claim_host(func); + sdio_set_block_size(func, blksz); + sdio_release_host(func); } -static inline struct wl12xx_sdio_glue *wl_to_glue(struct wl1271 *wl) -{ - return wl->if_priv; -} - -static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) -{ - return wl_to_glue(wl)->dev; -} - -static irqreturn_t wl1271_hardirq(int irq, void *cookie) -{ - struct wl1271 *wl = cookie; - unsigned long flags; - - wl1271_debug(DEBUG_IRQ, "IRQ"); - - /* complete the ELP completion */ - spin_lock_irqsave(&wl->wl_lock, flags); - set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); - if (wl->elp_compl) { - complete(wl->elp_compl); - wl->elp_compl = NULL; - } - - if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { - /* don't enqueue a work right now. mark it as pending */ - set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); - wl1271_debug(DEBUG_IRQ, "should not enqueue work"); - disable_irq_nosync(wl->irq); - pm_wakeup_event(wl1271_sdio_wl_to_dev(wl), 0); - spin_unlock_irqrestore(&wl->wl_lock, flags); - return IRQ_HANDLED; - } - spin_unlock_irqrestore(&wl->wl_lock, flags); - - return IRQ_WAKE_THREAD; -} - -static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) -{ - disable_irq(wl->irq); -} - -static void wl1271_sdio_enable_interrupts(struct wl1271 *wl) -{ - enable_irq(wl->irq); -} - -static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, +static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, size_t len, bool fixed) { int ret; - struct wl12xx_sdio_glue *glue = wl_to_glue(wl); + struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); struct sdio_func *func = dev_to_sdio_func(glue->dev); if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { @@ -139,11 +93,11 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, wl1271_error("sdio read failed (%d)", ret); } -static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, +static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, size_t len, bool fixed) { int ret; - struct wl12xx_sdio_glue *glue = wl_to_glue(wl); + struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); struct sdio_func *func = dev_to_sdio_func(glue->dev); if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { @@ -165,10 +119,9 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, wl1271_error("sdio write failed (%d)", ret); } -static int wl1271_sdio_power_on(struct wl1271 *wl) +static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) { int ret; - struct wl12xx_sdio_glue *glue = wl_to_glue(wl); struct sdio_func *func = dev_to_sdio_func(glue->dev); /* If enabled, tell runtime PM not to power off the card */ @@ -190,10 +143,9 @@ out: return ret; } -static int wl1271_sdio_power_off(struct wl1271 *wl) +static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue) { int ret; - struct wl12xx_sdio_glue *glue = wl_to_glue(wl); struct sdio_func *func = dev_to_sdio_func(glue->dev); sdio_disable_func(func); @@ -211,33 +163,29 @@ static int wl1271_sdio_power_off(struct wl1271 *wl) return ret; } -static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) +static int wl12xx_sdio_set_power(struct device *child, bool enable) { + struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); + if (enable) - return wl1271_sdio_power_on(wl); + return wl12xx_sdio_power_on(glue); else - return wl1271_sdio_power_off(wl); + return wl12xx_sdio_power_off(glue); } static struct wl1271_if_operations sdio_ops = { - .read = wl1271_sdio_raw_read, - .write = wl1271_sdio_raw_write, - .power = wl1271_sdio_set_power, - .dev = wl1271_sdio_wl_to_dev, - .enable_irq = wl1271_sdio_enable_interrupts, - .disable_irq = wl1271_sdio_disable_interrupts, + .read = wl12xx_sdio_raw_read, + .write = wl12xx_sdio_raw_write, + .power = wl12xx_sdio_set_power, .set_block_size = wl1271_sdio_set_block_size, }; static int __devinit wl1271_probe(struct sdio_func *func, const struct sdio_device_id *id) { - struct ieee80211_hw *hw; - const struct wl12xx_platform_data *wlan_data; - struct wl1271 *wl; + struct wl12xx_platform_data *wlan_data; struct wl12xx_sdio_glue *glue; struct resource res[1]; - unsigned long irqflags; mmc_pm_flag_t mmcflags; int ret = -ENOMEM; @@ -251,20 +199,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, goto out; } - hw = wl1271_alloc_hw(); - if (IS_ERR(hw)) { - wl1271_error("can't allocate hw"); - ret = PTR_ERR(hw); - goto out_free_glue; - } - - wl = hw->priv; - glue->dev = &func->dev; - glue->wl = wl; - - wl->if_priv = glue; - wl->if_ops = &sdio_ops; /* Grab access to FN0 for ELP reg. */ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; @@ -276,48 +211,17 @@ static int __devinit wl1271_probe(struct sdio_func *func, if (IS_ERR(wlan_data)) { ret = PTR_ERR(wlan_data); wl1271_error("missing wlan platform data: %d", ret); - goto out_free_hw; + goto out_free_glue; } - wl->irq = wlan_data->irq; - wl->ref_clock = wlan_data->board_ref_clock; - wl->tcxo_clock = wlan_data->board_tcxo_clock; - wl->platform_quirks = wlan_data->platform_quirks; + /* if sdio can keep power while host is suspended, enable wow */ + mmcflags = sdio_get_host_pm_caps(func); + wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags); - if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) - irqflags = IRQF_TRIGGER_RISING; - else - irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; + if (mmcflags & MMC_PM_KEEP_POWER) + wlan_data->pwr_in_suspend = true; - ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, - irqflags, - DRIVER_NAME, wl); - if (ret < 0) { - wl1271_error("request_irq() failed: %d", ret); - goto out_free_hw; - } - - ret = enable_irq_wake(wl->irq); - if (!ret) { - wl->irq_wake_enabled = true; - device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1); - - /* if sdio can keep power while host is suspended, enable wow */ - mmcflags = sdio_get_host_pm_caps(func); - wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags); - - if (mmcflags & MMC_PM_KEEP_POWER) - hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; - } - disable_irq(wl->irq); - - ret = wl1271_init_ieee80211(wl); - if (ret) - goto out_irq; - - ret = wl1271_register_hw(wl); - if (ret) - goto out_irq; + wlan_data->ops = &sdio_ops; sdio_set_drvdata(func, glue); @@ -328,7 +232,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, if (!glue->core) { wl1271_error("can't allocate platform_device"); ret = -ENOMEM; - goto out_unreg_hw; + goto out_free_glue; } glue->core->dev.parent = &func->dev; @@ -362,17 +266,9 @@ static int __devinit wl1271_probe(struct sdio_func *func, out_dev_put: platform_device_put(glue->core); -out_unreg_hw: - wl1271_unregister_hw(wl); - -out_irq: - free_irq(wl->irq, wl); - -out_free_hw: - wl1271_free_hw(wl); - out_free_glue: kfree(glue); + out: return ret; } @@ -380,18 +276,10 @@ out: static void __devexit wl1271_remove(struct sdio_func *func) { struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); - struct wl1271 *wl = glue->wl; /* Undo decrement done above in wl1271_probe */ pm_runtime_get_noresume(&func->dev); - wl1271_unregister_hw(wl); - if (wl->irq_wake_enabled) { - device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0); - disable_irq_wake(wl->irq); - } - free_irq(wl->irq, wl); - wl1271_free_hw(wl); platform_device_del(glue->core); platform_device_put(glue->core); kfree(glue); diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 2dd659886a04..22c1337ba883 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -72,33 +72,12 @@ struct wl12xx_spi_glue { struct device *dev; - struct wl1271 *wl; struct platform_device *core; }; -static inline struct wl12xx_spi_glue *wl_to_glue(struct wl1271 *wl) +static void wl12xx_spi_reset(struct device *child) { - return wl->if_priv; -} - -static struct device *wl1271_spi_wl_to_dev(struct wl1271 *wl) -{ - return wl_to_glue(wl)->dev; -} - -static void wl1271_spi_disable_interrupts(struct wl1271 *wl) -{ - disable_irq(wl->irq); -} - -static void wl1271_spi_enable_interrupts(struct wl1271 *wl) -{ - enable_irq(wl->irq); -} - -static void wl1271_spi_reset(struct wl1271 *wl) -{ - struct wl12xx_spi_glue *glue = wl_to_glue(wl); + struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); u8 *cmd; struct spi_transfer t; struct spi_message m; @@ -124,9 +103,9 @@ static void wl1271_spi_reset(struct wl1271 *wl) kfree(cmd); } -static void wl1271_spi_init(struct wl1271 *wl) +static void wl12xx_spi_init(struct device *child) { - struct wl12xx_spi_glue *glue = wl_to_glue(wl); + struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; struct spi_transfer t; struct spi_message m; @@ -181,9 +160,10 @@ static void wl1271_spi_init(struct wl1271 *wl) #define WL1271_BUSY_WORD_TIMEOUT 1000 -static int wl1271_spi_read_busy(struct wl1271 *wl) +static int wl12xx_spi_read_busy(struct device *child) { - struct wl12xx_spi_glue *glue = wl_to_glue(wl); + struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); + struct wl1271 *wl = dev_get_drvdata(child); struct spi_transfer t[1]; struct spi_message m; u32 *busy_buf; @@ -215,10 +195,11 @@ static int wl1271_spi_read_busy(struct wl1271 *wl) return -ETIMEDOUT; } -static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, +static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, size_t len, bool fixed) { - struct wl12xx_spi_glue *glue = wl_to_glue(wl); + struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); + struct wl1271 *wl = dev_get_drvdata(child); struct spi_transfer t[2]; struct spi_message m; u32 *busy_buf; @@ -257,7 +238,7 @@ static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, spi_sync(to_spi_device(glue->dev), &m); if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && - wl1271_spi_read_busy(wl)) { + wl12xx_spi_read_busy(child)) { memset(buf, 0, chunk_len); return; } @@ -282,10 +263,10 @@ static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, } } -static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed) +static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf, + size_t len, bool fixed) { - struct wl12xx_spi_glue *glue = wl_to_glue(wl); + struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; struct spi_message m; u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; @@ -333,42 +314,11 @@ static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, spi_sync(to_spi_device(glue->dev), &m); } -static irqreturn_t wl1271_hardirq(int irq, void *cookie) -{ - struct wl1271 *wl = cookie; - unsigned long flags; - - wl1271_debug(DEBUG_IRQ, "IRQ"); - - /* complete the ELP completion */ - spin_lock_irqsave(&wl->wl_lock, flags); - set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); - if (wl->elp_compl) { - complete(wl->elp_compl); - wl->elp_compl = NULL; - } - spin_unlock_irqrestore(&wl->wl_lock, flags); - - return IRQ_WAKE_THREAD; -} - -static int wl1271_spi_set_power(struct wl1271 *wl, bool enable) -{ - if (wl->set_power) - wl->set_power(enable); - - return 0; -} - static struct wl1271_if_operations spi_ops = { - .read = wl1271_spi_raw_read, - .write = wl1271_spi_raw_write, - .reset = wl1271_spi_reset, - .init = wl1271_spi_init, - .power = wl1271_spi_set_power, - .dev = wl1271_spi_wl_to_dev, - .enable_irq = wl1271_spi_enable_interrupts, - .disable_irq = wl1271_spi_disable_interrupts, + .read = wl12xx_spi_raw_read, + .write = wl12xx_spi_raw_write, + .reset = wl12xx_spi_reset, + .init = wl12xx_spi_init, .set_block_size = NULL, }; @@ -376,10 +326,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) { struct wl12xx_spi_glue *glue; struct wl12xx_platform_data *pdata; - struct ieee80211_hw *hw; - struct wl1271 *wl; struct resource res[1]; - unsigned long irqflags; int ret = -ENOMEM; pdata = spi->dev.platform_data; @@ -388,27 +335,17 @@ static int __devinit wl1271_probe(struct spi_device *spi) return -ENODEV; } + pdata->ops = &spi_ops; + glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { wl1271_error("can't allocate glue"); goto out; } - hw = wl1271_alloc_hw(); - if (IS_ERR(hw)) { - ret = PTR_ERR(hw); - goto out_free_glue; - } - - wl = hw->priv; - glue->dev = &spi->dev; - glue->wl = wl; spi_set_drvdata(spi, glue); - wl->if_priv = glue; - - wl->if_ops = &spi_ops; /* This is the only SPI value that we need to set here, the rest * comes from the board-peripherals file */ @@ -417,55 +354,14 @@ static int __devinit wl1271_probe(struct spi_device *spi) ret = spi_setup(spi); if (ret < 0) { wl1271_error("spi_setup failed"); - goto out_free_hw; + goto out_free_glue; } - wl->set_power = pdata->set_power; - if (!wl->set_power) { - wl1271_error("set power function missing in platform data"); - ret = -ENODEV; - goto out_free_hw; - } - - wl->ref_clock = pdata->board_ref_clock; - wl->tcxo_clock = pdata->board_tcxo_clock; - wl->platform_quirks = pdata->platform_quirks; - - if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) - irqflags = IRQF_TRIGGER_RISING; - else - irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; - - wl->irq = spi->irq; - if (wl->irq < 0) { - wl1271_error("irq missing in platform data"); - ret = -ENODEV; - goto out_free_hw; - } - - ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, - irqflags, - DRIVER_NAME, wl); - if (ret < 0) { - wl1271_error("request_irq() failed: %d", ret); - goto out_free_hw; - } - - disable_irq(wl->irq); - - ret = wl1271_init_ieee80211(wl); - if (ret) - goto out_irq; - - ret = wl1271_register_hw(wl); - if (ret) - goto out_irq; - glue->core = platform_device_alloc("wl12xx-spi", -1); if (!glue->core) { wl1271_error("can't allocate platform_device"); ret = -ENOMEM; - goto out_unreg_hw; + goto out_free_glue; } glue->core->dev.parent = &spi->dev; @@ -499,15 +395,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) out_dev_put: platform_device_put(glue->core); -out_unreg_hw: - wl1271_unregister_hw(wl); - -out_irq: - free_irq(wl->irq, wl); - -out_free_hw: - wl1271_free_hw(wl); - out_free_glue: kfree(glue); out: @@ -517,11 +404,7 @@ out: static int __devexit wl1271_remove(struct spi_device *spi) { struct wl12xx_spi_glue *glue = spi_get_drvdata(spi); - struct wl1271 *wl = glue->wl; - wl1271_unregister_hw(wl); - free_irq(wl->irq, wl); - wl1271_free_hw(wl); platform_device_del(glue->core); platform_device_put(glue->core); kfree(glue); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 8815fd9a0f47..d2028939eee5 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -288,17 +288,14 @@ struct wl1271_scan { }; struct wl1271_if_operations { - void (*read)(struct wl1271 *wl, int addr, void *buf, size_t len, + void (*read)(struct device *child, int addr, void *buf, size_t len, bool fixed); - void (*write)(struct wl1271 *wl, int addr, void *buf, size_t len, + void (*write)(struct device *child, int addr, void *buf, size_t len, bool fixed); - void (*reset)(struct wl1271 *wl); - void (*init)(struct wl1271 *wl); - int (*power)(struct wl1271 *wl, bool enable); - struct device* (*dev)(struct wl1271 *wl); - void (*enable_irq)(struct wl1271 *wl); - void (*disable_irq)(struct wl1271 *wl); - void (*set_block_size) (struct wl1271 *wl, unsigned int blksz); + void (*reset)(struct device *child); + void (*init)(struct device *child); + int (*power)(struct device *child, bool enable); + void (*set_block_size) (struct device *child, unsigned int blksz); }; #define MAX_NUM_KEYS 14 @@ -362,6 +359,8 @@ struct wl1271 { struct ieee80211_hw *hw; bool mac80211_registered; + struct device *dev; + void *if_priv; struct wl1271_if_operations *if_ops; diff --git a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c index 973b11060a8f..3c96b332184e 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_platform_data.c +++ b/drivers/net/wireless/wl12xx/wl12xx_platform_data.c @@ -2,7 +2,7 @@ #include #include -static const struct wl12xx_platform_data *platform_data; +static struct wl12xx_platform_data *platform_data; int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data) { @@ -18,7 +18,7 @@ int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data) return 0; } -const struct wl12xx_platform_data *wl12xx_get_platform_data(void) +struct wl12xx_platform_data *wl12xx_get_platform_data(void) { if (!platform_data) return ERR_PTR(-ENODEV); diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h index 4b697395326e..0d6373195d32 100644 --- a/include/linux/wl12xx.h +++ b/include/linux/wl12xx.h @@ -54,6 +54,9 @@ struct wl12xx_platform_data { int board_ref_clock; int board_tcxo_clock; unsigned long platform_quirks; + bool pwr_in_suspend; + + struct wl1271_if_operations *ops; }; /* Platform does not support level trigger interrupts */ @@ -73,6 +76,6 @@ int wl12xx_set_platform_data(const struct wl12xx_platform_data *data) #endif -const struct wl12xx_platform_data *wl12xx_get_platform_data(void); +struct wl12xx_platform_data *wl12xx_get_platform_data(void); #endif From 4b32a2c9a636eaab69c797d9ebc7e086a6bd2fb7 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Oct 2011 10:46:20 +0300 Subject: [PATCH 65/97] wl12xx: mark some symbols static after re-factoring a bunch of symbols are only used inside main.c which allows us to mark them as static. Signed-off-by: Felipe Balbi [forward-ported] Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/io.h | 9 ++------- drivers/net/wireless/wl12xx/main.c | 18 ++++++------------ 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h index e82dad19aa30..d398cbcea986 100644 --- a/drivers/net/wireless/wl12xx/io.h +++ b/drivers/net/wireless/wl12xx/io.h @@ -170,15 +170,10 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); int wl1271_set_partition(struct wl1271 *wl, struct wl1271_partition_set *p); +bool wl1271_set_block_size(struct wl1271 *wl); + /* Functions from wl1271_main.c */ -int wl1271_register_hw(struct wl1271 *wl); -void wl1271_unregister_hw(struct wl1271 *wl); -int wl1271_init_ieee80211(struct wl1271 *wl); -struct ieee80211_hw *wl1271_alloc_hw(void); -int wl1271_free_hw(struct wl1271 *wl); -irqreturn_t wl1271_irq(int irq, void *data); -bool wl1271_set_block_size(struct wl1271 *wl); int wl1271_tx_dummy_packet(struct wl1271 *wl); #endif diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 1cf987785053..56927051f665 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -931,7 +931,7 @@ static void wl1271_netstack_work(struct work_struct *work) #define WL1271_IRQ_MAX_LOOPS 256 -irqreturn_t wl1271_irq(int irq, void *cookie) +static irqreturn_t wl1271_irq(int irq, void *cookie) { int ret; u32 intr; @@ -1053,7 +1053,6 @@ out: return IRQ_HANDLED; } -EXPORT_SYMBOL_GPL(wl1271_irq); static int wl1271_fetch_firmware(struct wl1271 *wl) { @@ -4848,7 +4847,7 @@ static struct bin_attribute fwlog_attr = { .read = wl1271_sysfs_read_fwlog, }; -int wl1271_register_hw(struct wl1271 *wl) +static int wl1271_register_hw(struct wl1271 *wl) { int ret; @@ -4889,9 +4888,8 @@ int wl1271_register_hw(struct wl1271 *wl) return 0; } -EXPORT_SYMBOL_GPL(wl1271_register_hw); -void wl1271_unregister_hw(struct wl1271 *wl) +static void wl1271_unregister_hw(struct wl1271 *wl) { if (wl->state == WL1271_STATE_PLT) __wl1271_plt_stop(wl); @@ -4901,9 +4899,8 @@ void wl1271_unregister_hw(struct wl1271 *wl) wl->mac80211_registered = false; } -EXPORT_SYMBOL_GPL(wl1271_unregister_hw); -int wl1271_init_ieee80211(struct wl1271 *wl) +static int wl1271_init_ieee80211(struct wl1271 *wl) { static const u32 cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, @@ -4989,11 +4986,10 @@ int wl1271_init_ieee80211(struct wl1271 *wl) return 0; } -EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); #define WL1271_DEFAULT_CHANNEL 0 -struct ieee80211_hw *wl1271_alloc_hw(void) +static struct ieee80211_hw *wl1271_alloc_hw(void) { struct ieee80211_hw *hw; struct platform_device *plat_dev = NULL; @@ -5162,9 +5158,8 @@ err_hw_alloc: return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(wl1271_alloc_hw); -int wl1271_free_hw(struct wl1271 *wl) +static int wl1271_free_hw(struct wl1271 *wl) { /* Unblock any fwlog readers */ mutex_lock(&wl->mutex); @@ -5199,7 +5194,6 @@ int wl1271_free_hw(struct wl1271 *wl) return 0; } -EXPORT_SYMBOL_GPL(wl1271_free_hw); static irqreturn_t wl12xx_hardirq(int irq, void *cookie) { From f79f890c9ccd8d10f7e5e2f7c590b0c2e854bfb6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Oct 2011 13:05:25 +0300 Subject: [PATCH 66/97] wl12xx: drop unneeded plat_dev now that useless plat_dev is unnecessary, we can remove it. Signed-off-by: Felipe Balbi [forward ported and fixed sysfs file creation] Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 104 ++++++++------------------- drivers/net/wireless/wl12xx/wl12xx.h | 1 - 2 files changed, 30 insertions(+), 75 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 56927051f665..c72f7497db09 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -383,22 +383,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, static void wl1271_op_stop(struct ieee80211_hw *hw); static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif); - -static void wl1271_device_release(struct device *dev) -{ - -} - -static struct platform_device wl1271_device = { - .name = "wl1271", - .id = -1, - - /* device model insists to have a release function */ - .dev = { - .release = wl1271_device_release, - }, -}; - static DEFINE_MUTEX(wl_list_mutex); static LIST_HEAD(wl_list); @@ -4992,7 +4976,6 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) static struct ieee80211_hw *wl1271_alloc_hw(void) { struct ieee80211_hw *hw; - struct platform_device *plat_dev = NULL; struct wl1271 *wl; int i, j, ret; unsigned int order; @@ -5006,13 +4989,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) goto err_hw_alloc; } - plat_dev = kmemdup(&wl1271_device, sizeof(wl1271_device), GFP_KERNEL); - if (!plat_dev) { - wl1271_error("could not allocate platform_device"); - ret = -ENOMEM; - goto err_plat_alloc; - } - wl = hw->priv; memset(wl, 0, sizeof(*wl)); @@ -5020,7 +4996,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) INIT_LIST_HEAD(&wl->wlvif_list); wl->hw = hw; - wl->plat_dev = plat_dev; for (i = 0; i < NUM_TX_QUEUES; i++) for (j = 0; j < WL12XX_MAX_LINKS; j++) @@ -5095,49 +5070,8 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) goto err_dummy_packet; } - /* Register platform device */ - ret = platform_device_register(wl->plat_dev); - if (ret) { - wl1271_error("couldn't register platform device"); - goto err_fwlog; - } - dev_set_drvdata(&wl->plat_dev->dev, wl); - - /* Create sysfs file to control bt coex state */ - ret = device_create_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); - if (ret < 0) { - wl1271_error("failed to create sysfs file bt_coex_state"); - goto err_platform; - } - - /* Create sysfs file to get HW PG version */ - ret = device_create_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); - if (ret < 0) { - wl1271_error("failed to create sysfs file hw_pg_ver"); - goto err_bt_coex_state; - } - - /* Create sysfs file for the FW log */ - ret = device_create_bin_file(&wl->plat_dev->dev, &fwlog_attr); - if (ret < 0) { - wl1271_error("failed to create sysfs file fwlog"); - goto err_hw_pg_ver; - } - return hw; -err_hw_pg_ver: - device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); - -err_bt_coex_state: - device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); - -err_platform: - platform_device_unregister(wl->plat_dev); - -err_fwlog: - free_page((unsigned long)wl->fwlog); - err_dummy_packet: dev_kfree_skb(wl->dummy_packet); @@ -5149,9 +5083,6 @@ err_wq: err_hw: wl1271_debugfs_exit(wl); - kfree(plat_dev); - -err_plat_alloc: ieee80211_free_hw(hw); err_hw_alloc: @@ -5167,17 +5098,15 @@ static int wl1271_free_hw(struct wl1271 *wl) wake_up_interruptible_all(&wl->fwlog_waitq); mutex_unlock(&wl->mutex); - device_remove_bin_file(&wl->plat_dev->dev, &fwlog_attr); + device_remove_bin_file(wl->dev, &fwlog_attr); - device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); + device_remove_file(wl->dev, &dev_attr_hw_pg_ver); - device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); - platform_device_unregister(wl->plat_dev); + device_remove_file(wl->dev, &dev_attr_bt_coex_state); free_page((unsigned long)wl->fwlog); dev_kfree_skb(wl->dummy_packet); free_pages((unsigned long)wl->aggr_buf, get_order(WL1271_AGGR_BUFFER_SIZE)); - kfree(wl->plat_dev); wl1271_debugfs_exit(wl); @@ -5281,8 +5210,35 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) if (ret) goto out_irq; + /* Create sysfs file to control bt coex state */ + ret = device_create_file(wl->dev, &dev_attr_bt_coex_state); + if (ret < 0) { + wl1271_error("failed to create sysfs file bt_coex_state"); + goto out_irq; + } + + /* Create sysfs file to get HW PG version */ + ret = device_create_file(wl->dev, &dev_attr_hw_pg_ver); + if (ret < 0) { + wl1271_error("failed to create sysfs file hw_pg_ver"); + goto out_bt_coex_state; + } + + /* Create sysfs file for the FW log */ + ret = device_create_bin_file(wl->dev, &fwlog_attr); + if (ret < 0) { + wl1271_error("failed to create sysfs file fwlog"); + goto out_hw_pg_ver; + } + return 0; +out_hw_pg_ver: + device_remove_file(wl->dev, &dev_attr_hw_pg_ver); + +out_bt_coex_state: + device_remove_file(wl->dev, &dev_attr_bt_coex_state); + out_irq: free_irq(wl->irq, wl); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index d2028939eee5..158714a1092f 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -355,7 +355,6 @@ struct wl1271_link { }; struct wl1271 { - struct platform_device *plat_dev; struct ieee80211_hw *hw; bool mac80211_registered; From 0f4e31222a2c0b93f25a87effd2033cb78c7a79c Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 7 Oct 2011 11:02:42 +0300 Subject: [PATCH 67/97] wl12xx: move debugging definitions to a separate file Separate the debugging macros and other definitions to a new debug.h file. This is be needed because the sdio and spi modules don't need to depend on the wl12xx module anymore, but still need to include wl12xx.h. Currently they do depend on it, because of the debugging global that wl12xx exports. A future patch will remove this dependency. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/acx.c | 1 + drivers/net/wireless/wl12xx/boot.c | 1 + drivers/net/wireless/wl12xx/cmd.c | 1 + drivers/net/wireless/wl12xx/debug.h | 101 +++++++++++++++++++++++++ drivers/net/wireless/wl12xx/debugfs.c | 1 + drivers/net/wireless/wl12xx/event.c | 1 + drivers/net/wireless/wl12xx/init.c | 1 + drivers/net/wireless/wl12xx/io.c | 1 + drivers/net/wireless/wl12xx/main.c | 1 + drivers/net/wireless/wl12xx/ps.c | 1 + drivers/net/wireless/wl12xx/rx.c | 1 + drivers/net/wireless/wl12xx/scan.c | 1 + drivers/net/wireless/wl12xx/sdio.c | 1 + drivers/net/wireless/wl12xx/spi.c | 1 + drivers/net/wireless/wl12xx/testmode.c | 1 + drivers/net/wireless/wl12xx/tx.c | 1 + drivers/net/wireless/wl12xx/wl12xx.h | 70 ----------------- 17 files changed, 116 insertions(+), 70 deletions(-) create mode 100644 drivers/net/wireless/wl12xx/debug.h diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index e2e46705059d..bde1d862bdd5 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -29,6 +29,7 @@ #include #include "wl12xx.h" +#include "debug.h" #include "wl12xx_80211.h" #include "reg.h" #include "ps.h" diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index d4e628db76b0..4ce634b925cb 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -24,6 +24,7 @@ #include #include +#include "debug.h" #include "acx.h" #include "reg.h" #include "boot.h" diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 65bf9526576d..2413c43d0894 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -29,6 +29,7 @@ #include #include "wl12xx.h" +#include "debug.h" #include "reg.h" #include "io.h" #include "acx.h" diff --git a/drivers/net/wireless/wl12xx/debug.h b/drivers/net/wireless/wl12xx/debug.h new file mode 100644 index 000000000000..b85fd8c41e8f --- /dev/null +++ b/drivers/net/wireless/wl12xx/debug.h @@ -0,0 +1,101 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2011 Texas Instruments. All rights reserved. + * Copyright (C) 2008-2009 Nokia Corporation + * + * Contact: Luciano Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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 St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include +#include + +#define DRIVER_NAME "wl12xx" +#define DRIVER_PREFIX DRIVER_NAME ": " + +enum { + DEBUG_NONE = 0, + DEBUG_IRQ = BIT(0), + DEBUG_SPI = BIT(1), + DEBUG_BOOT = BIT(2), + DEBUG_MAILBOX = BIT(3), + DEBUG_TESTMODE = BIT(4), + DEBUG_EVENT = BIT(5), + DEBUG_TX = BIT(6), + DEBUG_RX = BIT(7), + DEBUG_SCAN = BIT(8), + DEBUG_CRYPT = BIT(9), + DEBUG_PSM = BIT(10), + DEBUG_MAC80211 = BIT(11), + DEBUG_CMD = BIT(12), + DEBUG_ACX = BIT(13), + DEBUG_SDIO = BIT(14), + DEBUG_FILTERS = BIT(15), + DEBUG_ADHOC = BIT(16), + DEBUG_AP = BIT(17), + DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP), + DEBUG_ALL = ~0, +}; + +extern u32 wl12xx_debug_level; + +#define DEBUG_DUMP_LIMIT 1024 + +#define wl1271_error(fmt, arg...) \ + pr_err(DRIVER_PREFIX "ERROR " fmt "\n", ##arg) + +#define wl1271_warning(fmt, arg...) \ + pr_warning(DRIVER_PREFIX "WARNING " fmt "\n", ##arg) + +#define wl1271_notice(fmt, arg...) \ + pr_info(DRIVER_PREFIX fmt "\n", ##arg) + +#define wl1271_info(fmt, arg...) \ + pr_info(DRIVER_PREFIX fmt "\n", ##arg) + +#define wl1271_debug(level, fmt, arg...) \ + do { \ + if (level & wl12xx_debug_level) \ + pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \ + } while (0) + +/* TODO: use pr_debug_hex_dump when it becomes available */ +#define wl1271_dump(level, prefix, buf, len) \ + do { \ + if (level & wl12xx_debug_level) \ + print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ + DUMP_PREFIX_OFFSET, 16, 1, \ + buf, \ + min_t(size_t, len, DEBUG_DUMP_LIMIT), \ + 0); \ + } while (0) + +#define wl1271_dump_ascii(level, prefix, buf, len) \ + do { \ + if (level & wl12xx_debug_level) \ + print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ + DUMP_PREFIX_OFFSET, 16, 1, \ + buf, \ + min_t(size_t, len, DEBUG_DUMP_LIMIT), \ + true); \ + } while (0) + +#endif /* __DEBUG_H__ */ diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index d6c2d0c1b6cd..a9e0b7383bb5 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -27,6 +27,7 @@ #include #include "wl12xx.h" +#include "debug.h" #include "acx.h" #include "ps.h" #include "io.h" diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index fd2e7b2d9389..e22df6ce139a 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -22,6 +22,7 @@ */ #include "wl12xx.h" +#include "debug.h" #include "reg.h" #include "io.h" #include "event.h" diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index ba286d0a74a8..c6084f8a9c43 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -25,6 +25,7 @@ #include #include +#include "debug.h" #include "init.h" #include "wl12xx_80211.h" #include "acx.h" diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c index 1a7df8a7ed2d..079ad380e8ff 100644 --- a/drivers/net/wireless/wl12xx/io.c +++ b/drivers/net/wireless/wl12xx/io.c @@ -27,6 +27,7 @@ #include #include "wl12xx.h" +#include "debug.h" #include "wl12xx_80211.h" #include "io.h" #include "tx.h" diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index c72f7497db09..44d52efedc74 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -35,6 +35,7 @@ #include #include "wl12xx.h" +#include "debug.h" #include "wl12xx_80211.h" #include "reg.h" #include "io.h" diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 84a1afac6f53..9f4e8c03cc8f 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -25,6 +25,7 @@ #include "ps.h" #include "io.h" #include "tx.h" +#include "debug.h" #define WL1271_WAKEUP_TIMEOUT 500 diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index dd2f8b714a7f..8c277c0cb372 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -25,6 +25,7 @@ #include #include "wl12xx.h" +#include "debug.h" #include "acx.h" #include "reg.h" #include "rx.h" diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 2711438fdde3..fb2c4319749d 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -24,6 +24,7 @@ #include #include "wl12xx.h" +#include "debug.h" #include "cmd.h" #include "scan.h" #include "acx.h" diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 78e5352c4037..55c63adb1d0f 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -34,6 +34,7 @@ #include #include "wl12xx.h" +#include "debug.h" #include "wl12xx_80211.h" #include "io.h" diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 22c1337ba883..bcc7d7c95a22 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -31,6 +31,7 @@ #include #include "wl12xx.h" +#include "debug.h" #include "wl12xx_80211.h" #include "io.h" diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 4ae8effaee22..61fff45686ad 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -26,6 +26,7 @@ #include #include "wl12xx.h" +#include "debug.h" #include "acx.h" #include "reg.h" diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 5aeef95229eb..5351f015feef 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -26,6 +26,7 @@ #include #include "wl12xx.h" +#include "debug.h" #include "io.h" #include "reg.h" #include "ps.h" diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 158714a1092f..b7036df5939d 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -35,9 +35,6 @@ #include "conf.h" #include "ini.h" -#define DRIVER_NAME "wl1271" -#define DRIVER_PREFIX DRIVER_NAME ": " - /* * FW versions support BA 11n * versions marks x.x.x.50-60.x @@ -45,73 +42,6 @@ #define WL12XX_BA_SUPPORT_FW_COST_VER2_START 50 #define WL12XX_BA_SUPPORT_FW_COST_VER2_END 60 -enum { - DEBUG_NONE = 0, - DEBUG_IRQ = BIT(0), - DEBUG_SPI = BIT(1), - DEBUG_BOOT = BIT(2), - DEBUG_MAILBOX = BIT(3), - DEBUG_TESTMODE = BIT(4), - DEBUG_EVENT = BIT(5), - DEBUG_TX = BIT(6), - DEBUG_RX = BIT(7), - DEBUG_SCAN = BIT(8), - DEBUG_CRYPT = BIT(9), - DEBUG_PSM = BIT(10), - DEBUG_MAC80211 = BIT(11), - DEBUG_CMD = BIT(12), - DEBUG_ACX = BIT(13), - DEBUG_SDIO = BIT(14), - DEBUG_FILTERS = BIT(15), - DEBUG_ADHOC = BIT(16), - DEBUG_AP = BIT(17), - DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP), - DEBUG_ALL = ~0, -}; - -extern u32 wl12xx_debug_level; - -#define DEBUG_DUMP_LIMIT 1024 - -#define wl1271_error(fmt, arg...) \ - pr_err(DRIVER_PREFIX "ERROR " fmt "\n", ##arg) - -#define wl1271_warning(fmt, arg...) \ - pr_warning(DRIVER_PREFIX "WARNING " fmt "\n", ##arg) - -#define wl1271_notice(fmt, arg...) \ - pr_info(DRIVER_PREFIX fmt "\n", ##arg) - -#define wl1271_info(fmt, arg...) \ - pr_info(DRIVER_PREFIX fmt "\n", ##arg) - -#define wl1271_debug(level, fmt, arg...) \ - do { \ - if (level & wl12xx_debug_level) \ - pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \ - } while (0) - -/* TODO: use pr_debug_hex_dump when it will be available */ -#define wl1271_dump(level, prefix, buf, len) \ - do { \ - if (level & wl12xx_debug_level) \ - print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ - DUMP_PREFIX_OFFSET, 16, 1, \ - buf, \ - min_t(size_t, len, DEBUG_DUMP_LIMIT), \ - 0); \ - } while (0) - -#define wl1271_dump_ascii(level, prefix, buf, len) \ - do { \ - if (level & wl12xx_debug_level) \ - print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ - DUMP_PREFIX_OFFSET, 16, 1, \ - buf, \ - min_t(size_t, len, DEBUG_DUMP_LIMIT), \ - true); \ - } while (0) - #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin" #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin" From 3c4d386868dcbfb9fa51427e314fde39ee70b0ff Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 7 Oct 2011 14:14:25 +0300 Subject: [PATCH 68/97] wl12xx: sdio: use dev_dbg instead of wl1271_debug To prevent a useless dependency between the sdio module and the wl12xx module, we need to replace the wl1271_debug macros (and friends) for dev_dbg and other equivalents. At the same time, remove the SDIO data hexdump, since this produces way too much data and is not particularly useful. There's not print_hex_dump() equivalent for dynamic debug, so it's hard to control when the dumps are printed out. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/sdio.c | 49 ++++++++++++++---------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 55c63adb1d0f..57e72b4b8d22 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -34,7 +34,6 @@ #include #include "wl12xx.h" -#include "debug.h" #include "wl12xx_80211.h" #include "io.h" @@ -77,21 +76,20 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); - wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", - addr, ((u8 *)buf)[0]); + dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", + addr, ((u8 *)buf)[0]); } else { if (fixed) ret = sdio_readsb(func, buf, addr, len); else ret = sdio_memcpy_fromio(func, buf, addr, len); - wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes", - addr, len); - wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); + dev_dbg(child->parent, "sdio read 53 addr 0x%x, %zu bytes\n", + addr, len); } if (ret) - wl1271_error("sdio read failed (%d)", ret); + dev_err(child->parent, "sdio read failed (%d)\n", ret); } static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, @@ -103,12 +101,11 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); - wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", - addr, ((u8 *)buf)[0]); + dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n", + addr, ((u8 *)buf)[0]); } else { - wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes", - addr, len); - wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); + dev_dbg(child->parent, "sdio write 53 addr 0x%x, %zu bytes\n", + addr, len); if (fixed) ret = sdio_writesb(func, addr, buf, len); @@ -117,7 +114,7 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, } if (ret) - wl1271_error("sdio write failed (%d)", ret); + dev_err(child->parent, "sdio write failed (%d)\n", ret); } static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) @@ -196,7 +193,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { - wl1271_error("can't allocate glue"); + dev_err(&func->dev, "can't allocate glue\n"); goto out; } @@ -211,13 +208,13 @@ static int __devinit wl1271_probe(struct sdio_func *func, wlan_data = wl12xx_get_platform_data(); if (IS_ERR(wlan_data)) { ret = PTR_ERR(wlan_data); - wl1271_error("missing wlan platform data: %d", ret); + dev_err(glue->dev, "missing wlan platform data: %d\n", ret); goto out_free_glue; } /* if sdio can keep power while host is suspended, enable wow */ mmcflags = sdio_get_host_pm_caps(func); - wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags); + dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags); if (mmcflags & MMC_PM_KEEP_POWER) wlan_data->pwr_in_suspend = true; @@ -231,7 +228,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, glue->core = platform_device_alloc("wl12xx-sdio", -1); if (!glue->core) { - wl1271_error("can't allocate platform_device"); + dev_err(glue->dev, "can't allocate platform_device"); ret = -ENOMEM; goto out_free_glue; } @@ -246,20 +243,20 @@ static int __devinit wl1271_probe(struct sdio_func *func, ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); if (ret) { - wl1271_error("can't add resources"); + dev_err(glue->dev, "can't add resources\n"); goto out_dev_put; } ret = platform_device_add_data(glue->core, wlan_data, sizeof(*wlan_data)); if (ret) { - wl1271_error("can't add platform data"); + dev_err(glue->dev, "can't add platform data\n"); goto out_dev_put; } ret = platform_device_add(glue->core); if (ret) { - wl1271_error("can't add platform device"); + dev_err(glue->dev, "can't add platform device\n"); goto out_dev_put; } return 0; @@ -296,16 +293,16 @@ static int wl1271_suspend(struct device *dev) mmc_pm_flag_t sdio_flags; int ret = 0; - wl1271_debug(DEBUG_MAC80211, "wl1271 suspend. wow_enabled: %d", - wl->wow_enabled); + dev_dbg(dev, "wl1271 suspend. wow_enabled: %d\n", + wl->wow_enabled); /* check whether sdio should keep power */ if (wl->wow_enabled) { sdio_flags = sdio_get_host_pm_caps(func); if (!(sdio_flags & MMC_PM_KEEP_POWER)) { - wl1271_error("can't keep power while host " - "is suspended"); + dev_err(dev, "can't keep power while host " + "is suspended\n"); ret = -EINVAL; goto out; } @@ -313,7 +310,7 @@ static int wl1271_suspend(struct device *dev) /* keep power while host suspended */ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); if (ret) { - wl1271_error("error while trying to keep power"); + dev_err(dev, "error while trying to keep power\n"); goto out; } @@ -329,7 +326,7 @@ static int wl1271_resume(struct device *dev) struct sdio_func *func = dev_to_sdio_func(dev); struct wl1271 *wl = sdio_get_drvdata(func); - wl1271_debug(DEBUG_MAC80211, "wl1271 resume"); + dev_dbg(dev, "wl1271 resume\n"); if (wl->wow_enabled) { /* claim back host */ sdio_claim_host(func); From e5d3625e8741d204e8c3f0a959f92c9e901519aa Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 7 Oct 2011 14:33:29 +0300 Subject: [PATCH 69/97] wl12xx: spi: use dev_err instead of wl1271_error To prevent a useless dependency between the spi module and the wl12xx module, we need to replace the wl1271_error macros with dev_err. At the same time, remove the SPI data hexdump, since this produces way too much data and is not particularly useful. There's no print_hex_dump() equivalent for dynamic debug, so it's hard to control when the dumps are printed out. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/spi.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index bcc7d7c95a22..976d3d556833 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -31,7 +31,6 @@ #include #include "wl12xx.h" -#include "debug.h" #include "wl12xx_80211.h" #include "io.h" @@ -85,7 +84,8 @@ static void wl12xx_spi_reset(struct device *child) cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); if (!cmd) { - wl1271_error("could not allocate cmd for spi reset"); + dev_err(child->parent, + "could not allocate cmd for spi reset\n"); return; } @@ -100,7 +100,6 @@ static void wl12xx_spi_reset(struct device *child) spi_sync(to_spi_device(glue->dev), &m); - wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); kfree(cmd); } @@ -113,7 +112,8 @@ static void wl12xx_spi_init(struct device *child) cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); if (!cmd) { - wl1271_error("could not allocate cmd for spi init"); + dev_err(child->parent, + "could not allocate cmd for spi init\n"); return; } @@ -155,7 +155,6 @@ static void wl12xx_spi_init(struct device *child) spi_message_add_tail(&t, &m); spi_sync(to_spi_device(glue->dev), &m); - wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); kfree(cmd); } @@ -192,7 +191,7 @@ static int wl12xx_spi_read_busy(struct device *child) } /* The SPI bus is unresponsive, the read failed. */ - wl1271_error("SPI read busy-word timeout!\n"); + dev_err(child->parent, "SPI read busy-word timeout!\n"); return -ETIMEDOUT; } @@ -254,9 +253,6 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, spi_sync(to_spi_device(glue->dev), &m); - wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); - wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, chunk_len); - if (!fixed) addr += chunk_len; buf += chunk_len; @@ -302,9 +298,6 @@ static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf, t[i].len = chunk_len; spi_message_add_tail(&t[i++], &m); - wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); - wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, chunk_len); - if (!fixed) addr += chunk_len; buf += chunk_len; @@ -332,7 +325,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) pdata = spi->dev.platform_data; if (!pdata) { - wl1271_error("no platform data"); + dev_err(&spi->dev, "no platform data\n"); return -ENODEV; } @@ -340,7 +333,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { - wl1271_error("can't allocate glue"); + dev_err(&spi->dev, "can't allocate glue\n"); goto out; } @@ -354,13 +347,13 @@ static int __devinit wl1271_probe(struct spi_device *spi) ret = spi_setup(spi); if (ret < 0) { - wl1271_error("spi_setup failed"); + dev_err(glue->dev, "spi_setup failed\n"); goto out_free_glue; } glue->core = platform_device_alloc("wl12xx-spi", -1); if (!glue->core) { - wl1271_error("can't allocate platform_device"); + dev_err(glue->dev, "can't allocate platform_device\n"); ret = -ENOMEM; goto out_free_glue; } @@ -375,19 +368,19 @@ static int __devinit wl1271_probe(struct spi_device *spi) ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); if (ret) { - wl1271_error("can't add resources"); + dev_err(glue->dev, "can't add resources\n"); goto out_dev_put; } ret = platform_device_add_data(glue->core, pdata, sizeof(*pdata)); if (ret) { - wl1271_error("can't add platform data"); + dev_err(glue->dev, "can't add platform data\n"); goto out_dev_put; } ret = platform_device_add(glue->core); if (ret) { - wl1271_error("can't register platform device"); + dev_err(glue->dev, "can't register platform device\n"); goto out_dev_put; } From 48309fd477ef867babb6819f67fe082c133a5fa9 Mon Sep 17 00:00:00 2001 From: Shahar Lev Date: Fri, 7 Oct 2011 18:17:25 +0200 Subject: [PATCH 70/97] wl12xx: remove warning message during IBSS Tx mac80211 sets the carrier on an IBSS interface even when no network is joined. Ignore garbage frames transmitted on a disconnected IBSS interface without printing warnings. Signed-off-by: Shahar Lev [merged with wlvif changes] Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/tx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 5351f015feef..27a45e1459c4 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -428,7 +428,15 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, } hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); if (hlid == WL12XX_INVALID_LINK_ID) { - wl1271_error("invalid hlid. dropping skb 0x%p", skb); + if (wlvif->bss_type == BSS_TYPE_IBSS && + !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) { + /* It's ok to drop packets when not joined to IBSS */ + wl1271_debug(DEBUG_TX, "dropping skb while IBSS not " + " joined"); + } else { + wl1271_error("invalid hlid. dropping skb 0x%p", skb); + } + return -EINVAL; } From ccb62000d5e92772b6d5c2acce2f56263886ed89 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 7 Oct 2011 15:54:15 +0300 Subject: [PATCH 71/97] wl12xx: use the same plat dev name for both SPI and SDIO There's no need to have the bus name included in the platform device name that we create. The core driver doesn't need to know about the type of bus it uses. Any differences between the buses that need to be handled differently in the core, can be passed in the platform data (as the pwr_in_suspend boolean does). Use "wl12xx" for the device name in both bus drivers. Rename the platform driver name to "wl12xx_driver", just to differentiate from the platform device names. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 5 ++--- drivers/net/wireless/wl12xx/sdio.c | 2 +- drivers/net/wireless/wl12xx/spi.c | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 44d52efedc74..a2d16933ccb0 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -5266,8 +5266,7 @@ static int __devexit wl12xx_remove(struct platform_device *pdev) } static const struct platform_device_id wl12xx_id_table[] __devinitconst = { - { "wl12xx-sdio", 0 }, - { "wl12xx-spi", 0 }, + { "wl12xx", 0 }, { } /* Terminating Entry */ }; MODULE_DEVICE_TABLE(platform, wl12xx_id_table); @@ -5277,7 +5276,7 @@ static struct platform_driver wl12xx_driver = { .remove = __devexit_p(wl12xx_remove), .id_table = wl12xx_id_table, .driver = { - .name = "wl12xx", + .name = "wl12xx_driver", .owner = THIS_MODULE, } }; diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 57e72b4b8d22..ed97f9cee3f0 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -226,7 +226,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, /* Tell PM core that we don't need the card to be powered now */ pm_runtime_put_noidle(&func->dev); - glue->core = platform_device_alloc("wl12xx-sdio", -1); + glue->core = platform_device_alloc("wl12xx", -1); if (!glue->core) { dev_err(glue->dev, "can't allocate platform_device"); ret = -ENOMEM; diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 976d3d556833..9e6f7fa0f9a3 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -351,7 +351,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) goto out_free_glue; } - glue->core = platform_device_alloc("wl12xx-spi", -1); + glue->core = platform_device_alloc("wl12xx", -1); if (!glue->core) { dev_err(glue->dev, "can't allocate platform_device\n"); ret = -ENOMEM; From 0f1680147ce2509383e053fa843020e0e9f3c6ce Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 11 Oct 2011 13:52:25 +0200 Subject: [PATCH 72/97] wl12xx: handle injected packets Injected packets are sent with no vif, causing the wl12xx to NULL-dereference in multiple places. Furthermore, injected packets are currently not sent at all, as system_hlid doesn't belong to any specific role, so wl1271_skb_dequeue() never return its packets. Handle both these problems. Reported-by: Luciano Coelho Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 7 +++++-- drivers/net/wireless/wl12xx/tx.c | 27 +++++++++++++-------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index a2d16933ccb0..f76be5ad8ab0 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1477,11 +1477,14 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct wl1271 *wl = hw->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct wl12xx_vif *wlvif = NULL; unsigned long flags; int q, mapping; u8 hlid; + if (vif) + wlvif = wl12xx_vif_to_data(vif); + mapping = skb_get_queue_mapping(skb); q = wl1271_tx_get_queue(mapping); @@ -1491,7 +1494,7 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) /* queue the packet */ if (hlid == WL12XX_INVALID_LINK_ID || - !test_bit(hlid, wlvif->links_map)) { + (wlvif && !test_bit(hlid, wlvif->links_map))) { wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); dev_kfree_skb(skb); goto out; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 27a45e1459c4..c7ad4f5976c5 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -185,7 +185,7 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - if (wl12xx_is_dummy_packet(wl, skb)) + if (!wlvif || wl12xx_is_dummy_packet(wl, skb)) return wl->system_hlid; if (wlvif->bss_type == BSS_TYPE_AP_BSS) @@ -264,7 +264,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); wl->tx_allocated_pkts[ac]++; - if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS && + if (!is_dummy && wlvif && + wlvif->bss_type == BSS_TYPE_AP_BSS && test_bit(hlid, wlvif->ap.sta_hlid_map)) wl->links[hlid].allocated_pkts++; @@ -307,7 +308,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, desc->start_time = cpu_to_le32(hosttime - wl->time_offset); is_dummy = wl12xx_is_dummy_packet(wl, skb); - if (is_dummy || wlvif->bss_type != BSS_TYPE_AP_BSS) + if (is_dummy || !wlvif || wlvif->bss_type != BSS_TYPE_AP_BSS) desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); else desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU); @@ -326,14 +327,14 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, TX_HW_ATTR_SESSION_COUNTER; tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ; - } else { + } else if (wlvif) { /* configure the tx attributes */ tx_attr = wlvif->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; } desc->hlid = hlid; - if (is_dummy) + if (is_dummy || !wlvif) rate_idx = 0; else if (wlvif->bss_type != BSS_TYPE_AP_BSS) { /* if the packets are destined for AP (have a STA entry) @@ -446,7 +447,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_tx_fill_hdr(wl, wlvif, skb, extra, info, hlid); - if (!is_dummy && wlvif->bss_type == BSS_TYPE_AP_BSS) { + if (!is_dummy && wlvif && wlvif->bss_type == BSS_TYPE_AP_BSS) { wl1271_tx_ap_update_inconnection_sta(wl, skb); wl1271_tx_regulate_link(wl, wlvif, hlid); } @@ -623,6 +624,9 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) } } + if (!skb) + skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[wl->system_hlid]); + if (!skb && test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { int q; @@ -716,19 +720,14 @@ void wl1271_tx_work_locked(struct wl1271 *wl) return; while ((skb = wl1271_skb_dequeue(wl))) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); bool has_data = false; wlvif = NULL; - if (!wl12xx_is_dummy_packet(wl, skb)) { - struct ieee80211_tx_info *info; - struct ieee80211_vif *vif; + if (!wl12xx_is_dummy_packet(wl, skb) && info->control.vif) + wlvif = wl12xx_vif_to_data(info->control.vif); - info = IEEE80211_SKB_CB(skb); - vif = info->control.vif; - wlvif = wl12xx_vif_to_data(vif); - } has_data = wlvif && wl1271_tx_is_data_present(skb); - ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset); if (ret == -EAGAIN) { /* From 679a673414473239d189b5b41ea4014b088be7b9 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 11 Oct 2011 11:55:44 +0200 Subject: [PATCH 73/97] wl12xx: couple role_start_dev with roc Device role is always started along with ROC. Couple them together by introducing new wl12xx_start_dev and wl12xx_stop_dev functions. By using these functions, we solve a bug that occured during channel switch - we started the dev role on one channel, and ROCed on a different one. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 53 ++++++++++++++++++++++++++++-- drivers/net/wireless/wl12xx/cmd.h | 4 +-- drivers/net/wireless/wl12xx/main.c | 40 ++++++---------------- drivers/net/wireless/wl12xx/scan.c | 3 +- drivers/net/wireless/wl12xx/tx.c | 6 +--- 5 files changed, 65 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 2413c43d0894..afd597387e7e 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -468,7 +468,8 @@ static int wl12xx_get_new_session_id(struct wl1271 *wl, return wlvif->session_counter; } -int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) +static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_start *cmd; int ret; @@ -516,7 +517,8 @@ out: return ret; } -int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) +static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_stop *cmd; int ret; @@ -1776,3 +1778,50 @@ out_free: out: return ret; } + +/* start dev role and roc on its channel */ +int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + int ret; + + if (WARN_ON(!(wlvif->bss_type == BSS_TYPE_STA_BSS || + wlvif->bss_type == BSS_TYPE_IBSS))) + return -EINVAL; + + ret = wl12xx_cmd_role_start_dev(wl, wlvif); + if (ret < 0) + goto out; + + ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); + if (ret < 0) + goto out_stop; + + return 0; + +out_stop: + wl12xx_cmd_role_stop_dev(wl, wlvif); +out: + return ret; +} + +/* croc dev hlid, and stop the role */ +int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + int ret; + + if (WARN_ON(!(wlvif->bss_type == BSS_TYPE_STA_BSS || + wlvif->bss_type == BSS_TYPE_IBSS))) + return -EINVAL; + + if (test_bit(wlvif->dev_role_id, wl->roc_map)) { + ret = wl12xx_croc(wl, wlvif->dev_role_id); + if (ret < 0) + goto out; + } + + ret = wl12xx_cmd_role_stop_dev(wl, wlvif); + if (ret < 0) + goto out; +out: + return ret; +} diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 968d5bdc0b60..3f7d0b93c24d 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -39,13 +39,13 @@ int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, u8 *role_id); int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); -int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif); +int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); +int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index f76be5ad8ab0..44070e66cfed 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2429,11 +2429,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (idle) { /* no need to croc if we weren't busy (e.g. during boot) */ if (wl12xx_is_roc(wl)) { - ret = wl12xx_croc(wl, wlvif->dev_role_id); - if (ret < 0) - goto out; - - ret = wl12xx_cmd_role_stop_dev(wl, wlvif); + ret = wl12xx_stop_dev(wl, wlvif); if (ret < 0) goto out; } @@ -2455,11 +2451,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, ieee80211_sched_scan_stopped(wl->hw); } - ret = wl12xx_cmd_role_start_dev(wl, wlvif); - if (ret < 0) - goto out; - - ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); + ret = wl12xx_start_dev(wl, wlvif); if (ret < 0) goto out; clear_bit(WL1271_FLAG_IDLE, &wl->flags); @@ -2525,16 +2517,13 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, */ if (wl12xx_is_roc(wl) && !(conf->flags & IEEE80211_CONF_IDLE)) { - ret = wl12xx_croc(wl, - wlvif->dev_role_id); + ret = wl12xx_stop_dev(wl, wlvif); if (ret < 0) return ret; - ret = wl12xx_roc(wl, wlvif, - wlvif->dev_role_id); + ret = wl12xx_start_dev(wl, wlvif); if (ret < 0) - wl1271_warning("roc failed %d", - ret); + return ret; } } } @@ -3087,8 +3076,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, ret = -EBUSY; goto out_sleep; } - wl12xx_croc(wl, wlvif->dev_role_id); - wl12xx_cmd_role_stop_dev(wl, wlvif); + wl12xx_stop_dev(wl, wlvif); } ret = wl1271_scan(hw->priv, vif, ssid, len, req); @@ -3599,8 +3587,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (test_and_clear_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) { wl1271_unjoin(wl, wlvif); - wl12xx_cmd_role_start_dev(wl, wlvif); - wl12xx_roc(wl, wlvif, wlvif->dev_role_id); + wl12xx_start_dev(wl, wlvif); } } } @@ -3776,11 +3763,8 @@ sta_not_found: } wl1271_unjoin(wl, wlvif); - if (!(conf_flags & IEEE80211_CONF_IDLE)) { - wl12xx_cmd_role_start_dev(wl, wlvif); - wl12xx_roc(wl, wlvif, - wlvif->dev_role_id); - } + if (!(conf_flags & IEEE80211_CONF_IDLE)) + wl12xx_start_dev(wl, wlvif); } } } @@ -3859,11 +3843,7 @@ sta_not_found: * STA role). TODO: make it better. */ if (wlvif->dev_role_id != WL12XX_INVALID_ROLE_ID) { - ret = wl12xx_croc(wl, wlvif->dev_role_id); - if (ret < 0) - goto out; - - ret = wl12xx_cmd_role_stop_dev(wl, wlvif); + ret = wl12xx_stop_dev(wl, wlvif); if (ret < 0) goto out; } diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index fb2c4319749d..898d03d5b527 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -77,8 +77,7 @@ void wl1271_scan_complete_work(struct work_struct *work) (is_ibss && !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags))) && !test_bit(wlvif->dev_role_id, wl->roc_map)) { /* restore remain on channel */ - wl12xx_cmd_role_start_dev(wl, wlvif); - wl12xx_roc(wl, wlvif, wlvif->dev_role_id); + wl12xx_start_dev(wl, wlvif); } wl1271_ps_elp_sleep(wl); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index c7ad4f5976c5..3a9d2a6b8a09 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -99,11 +99,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, goto out; wl1271_debug(DEBUG_CMD, "starting device role for roaming"); - ret = wl12xx_cmd_role_start_dev(wl, wlvif); - if (ret < 0) - goto out; - - ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); + ret = wl12xx_start_dev(wl, wlvif); if (ret < 0) goto out; out: From d6fa37c9ffa2a613943dd1c32f220a3e6e9eb77c Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 11 Oct 2011 11:57:39 +0200 Subject: [PATCH 74/97] wl12xx: reconfigure rate policies on set_bitrate_mask The rate policies are configured only after association, resulting in auth req being sent in wrong rates. Reconfigure rate policies on bitrate mask change. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 44070e66cfed..c05be03907e4 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -4318,7 +4318,7 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271 *wl = hw->priv; - int i; + int i, ret = 0; wl1271_debug(DEBUG_MAC80211, "mac80211 set_bitrate_mask 0x%x 0x%x", mask->control[NL80211_BAND_2GHZ].legacy, @@ -4331,9 +4331,28 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, wl1271_tx_enabled_rates_get(wl, mask->control[i].legacy, i); + + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + + if (wlvif->bss_type == BSS_TYPE_STA_BSS && + !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + + wl1271_set_band_rate(wl, wlvif); + wlvif->basic_rate = + wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); + ret = wl1271_acx_sta_rate_policies(wl, wlvif); + + wl1271_ps_elp_sleep(wl); + } +out: mutex_unlock(&wl->mutex); - return 0; + return ret; } static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, From a693534b1a46ee934606cec52b12baeaebba0342 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 24 Oct 2011 17:25:20 +0200 Subject: [PATCH 75/97] wl12xx: keep beacon-filtering enabled during STA operation Enable beacon filtering on STA init, and don't disable it when entering active mode. Otherwise dynamic-PS supports means we receive beacons from the current AP during any Tx/Rx performed by the driver. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/event.c | 5 ----- drivers/net/wireless/wl12xx/init.c | 12 ++++++------ drivers/net/wireless/wl12xx/ps.c | 5 ----- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index e22df6ce139a..00ce794eebae 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -137,11 +137,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl, case EVENT_ENTER_POWER_SAVE_SUCCESS: wlvif->psm_entry_retry = 0; - /* enable beacon filtering */ - ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); - if (ret < 0) - break; - /* * BET has only a minor effect in 5GHz and masks * channel switch IEs, so we only enable BET on 2.4GHz diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index c6084f8a9c43..14ff01efc0b1 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -254,17 +254,17 @@ static int wl12xx_init_phy_vif_config(struct wl1271 *wl, return 0; } -static int wl1271_init_beacon_filter(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static int wl1271_init_sta_beacon_filter(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { int ret; - /* disable beacon filtering at this stage */ - ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); + ret = wl1271_acx_beacon_filter_table(wl, wlvif); if (ret < 0) return ret; - ret = wl1271_acx_beacon_filter_table(wl, wlvif); + /* enable beacon filtering */ + ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); if (ret < 0) return ret; @@ -529,7 +529,7 @@ static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif) return ret; /* Beacon filtering */ - ret = wl1271_init_beacon_filter(wl, wlvif); + ret = wl1271_init_sta_beacon_filter(wl, wlvif); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 9f4e8c03cc8f..a7a11088dd31 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -185,11 +185,6 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } - /* disable beacon filtering */ - ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); - if (ret < 0) - return ret; - ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_ACTIVE_MODE); if (ret < 0) return ret; From fa5e13756ad5112842bd5e765d66b6c6074b74b7 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 31 Oct 2011 12:24:49 +0200 Subject: [PATCH 76/97] wl12xx: add vifs_state debugfs key Add debugfs key to dump information regarding the active vifs (similar to the driver_state debugfs key) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 110 ++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index a9e0b7383bb5..2e14b436101f 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -385,6 +385,115 @@ static const struct file_operations driver_state_ops = { .llseek = default_llseek, }; +static ssize_t vifs_state_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + struct wl12xx_vif *wlvif; + int ret, res = 0; + const int buf_size = 4096; + char *buf; + char tmp_buf[64]; + + buf = kzalloc(buf_size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + mutex_lock(&wl->mutex); + +#define VIF_STATE_PRINT(x, fmt) \ + (res += scnprintf(buf + res, buf_size - res, \ + #x " = " fmt "\n", wlvif->x)) + +#define VIF_STATE_PRINT_LONG(x) VIF_STATE_PRINT(x, "%ld") +#define VIF_STATE_PRINT_INT(x) VIF_STATE_PRINT(x, "%d") +#define VIF_STATE_PRINT_STR(x) VIF_STATE_PRINT(x, "%s") +#define VIF_STATE_PRINT_LHEX(x) VIF_STATE_PRINT(x, "0x%lx") +#define VIF_STATE_PRINT_LLHEX(x) VIF_STATE_PRINT(x, "0x%llx") +#define VIF_STATE_PRINT_HEX(x) VIF_STATE_PRINT(x, "0x%x") + +#define VIF_STATE_PRINT_NSTR(x, len) \ + do { \ + memset(tmp_buf, 0, sizeof(tmp_buf)); \ + memcpy(tmp_buf, wlvif->x, \ + min_t(u8, len, sizeof(tmp_buf) - 1)); \ + res += scnprintf(buf + res, buf_size - res, \ + #x " = %s\n", tmp_buf); \ + } while (0) + + wl12xx_for_each_wlvif(wl, wlvif) { + VIF_STATE_PRINT_INT(role_id); + VIF_STATE_PRINT_INT(bss_type); + VIF_STATE_PRINT_LHEX(flags); + VIF_STATE_PRINT_INT(p2p); + VIF_STATE_PRINT_INT(dev_role_id); + VIF_STATE_PRINT_INT(dev_hlid); + + if (wlvif->bss_type == BSS_TYPE_STA_BSS || + wlvif->bss_type == BSS_TYPE_IBSS) { + VIF_STATE_PRINT_INT(sta.hlid); + VIF_STATE_PRINT_INT(sta.ba_rx_bitmap); + VIF_STATE_PRINT_INT(sta.basic_rate_idx); + VIF_STATE_PRINT_INT(sta.ap_rate_idx); + VIF_STATE_PRINT_INT(sta.p2p_rate_idx); + } else { + VIF_STATE_PRINT_INT(ap.global_hlid); + VIF_STATE_PRINT_INT(ap.bcast_hlid); + VIF_STATE_PRINT_LHEX(ap.sta_hlid_map[0]); + VIF_STATE_PRINT_INT(ap.mgmt_rate_idx); + VIF_STATE_PRINT_INT(ap.bcast_rate_idx); + VIF_STATE_PRINT_INT(ap.ucast_rate_idx[0]); + VIF_STATE_PRINT_INT(ap.ucast_rate_idx[1]); + VIF_STATE_PRINT_INT(ap.ucast_rate_idx[2]); + VIF_STATE_PRINT_INT(ap.ucast_rate_idx[3]); + } + VIF_STATE_PRINT_INT(last_tx_hlid); + VIF_STATE_PRINT_LHEX(links_map[0]); + VIF_STATE_PRINT_NSTR(ssid, wlvif->ssid_len); + VIF_STATE_PRINT_INT(band); + VIF_STATE_PRINT_INT(channel); + VIF_STATE_PRINT_HEX(bitrate_masks[0]); + VIF_STATE_PRINT_HEX(bitrate_masks[1]); + VIF_STATE_PRINT_HEX(basic_rate_set); + VIF_STATE_PRINT_HEX(basic_rate); + VIF_STATE_PRINT_HEX(rate_set); + VIF_STATE_PRINT_INT(beacon_int); + VIF_STATE_PRINT_INT(default_key); + VIF_STATE_PRINT_INT(aid); + VIF_STATE_PRINT_INT(session_counter); + VIF_STATE_PRINT_INT(ps_poll_failures); + VIF_STATE_PRINT_INT(psm_entry_retry); + VIF_STATE_PRINT_INT(power_level); + VIF_STATE_PRINT_INT(rssi_thold); + VIF_STATE_PRINT_INT(last_rssi_event); + VIF_STATE_PRINT_INT(ba_support); + VIF_STATE_PRINT_INT(ba_allowed); + VIF_STATE_PRINT_LLHEX(tx_security_seq); + VIF_STATE_PRINT_INT(tx_security_last_seq_lsb); + } + +#undef VIF_STATE_PRINT_INT +#undef VIF_STATE_PRINT_LONG +#undef VIF_STATE_PRINT_HEX +#undef VIF_STATE_PRINT_LHEX +#undef VIF_STATE_PRINT_LLHEX +#undef VIF_STATE_PRINT_STR +#undef VIF_STATE_PRINT_NSTR +#undef VIF_STATE_PRINT + + mutex_unlock(&wl->mutex); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, res); + kfree(buf); + return ret; +} + +static const struct file_operations vifs_state_ops = { + .read = vifs_state_read, + .open = wl1271_open_file_generic, + .llseek = default_llseek, +}; + static ssize_t dtim_interval_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -765,6 +874,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, DEBUGFS_ADD(gpio_power, rootdir); DEBUGFS_ADD(start_recovery, rootdir); DEBUGFS_ADD(driver_state, rootdir); + DEBUGFS_ADD(vifs_state, rootdir); DEBUGFS_ADD(dtim_interval, rootdir); DEBUGFS_ADD(beacon_interval, rootdir); DEBUGFS_ADD(beacon_filtering, rootdir); From 2f8e81ad42cee6e1503462105f540214b1fb3e54 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 1 Nov 2011 15:12:50 +0200 Subject: [PATCH 77/97] wl12xx: clear wl->vif on remove_interface wl->vif should be cleared on remove_interface() (rather than on stop()) even when only a single vif is supported, because during vif mode change stop() might not get called (e.g. because of monitor interface existence) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index c05be03907e4..51d519f93d79 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1859,7 +1859,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->tx_results_count = 0; wl->tx_packets_count = 0; wl->time_offset = 0; - wl->vif = NULL; wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl->ap_fw_ps_map = 0; wl->ap_ps_map = 0; @@ -2211,6 +2210,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, if (!test_and_clear_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) return; + wl->vif = NULL; + /* because of hardware recovery, we may get here twice */ if (wl->state != WL1271_STATE_ON) return; From ce39defb5c6312a89a0c7be48797d6fb8fe9abad Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 3 Nov 2011 08:44:41 +0200 Subject: [PATCH 78/97] wl12xx: change blocksize alignment quirk to negative SDIO blocksize alignment support is now the rule, not the exception. To simplify the code in patches to come, invert the meaning of the quirk to be negative (ie. the quirk is set if the device does _not_ support blocksize alignment). Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/init.c | 2 +- drivers/net/wireless/wl12xx/main.c | 8 ++++++-- drivers/net/wireless/wl12xx/tx.c | 6 +++--- drivers/net/wireless/wl12xx/wl12xx.h | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 14ff01efc0b1..c413abd26d1c 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -501,7 +501,7 @@ int wl1271_chip_specific_init(struct wl1271 *wl) if (wl->chip.id == CHIP_ID_1283_PG20) { u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; - if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT) + if (!(wl->quirks & WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT)) /* Enable SDIO padding */ host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 51d519f93d79..b9a3fe497274 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1323,7 +1323,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ret = wl1271_setup(wl); if (ret < 0) goto out; + wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; break; + case CHIP_ID_1271_PG20: wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", wl->chip.id); @@ -1331,7 +1333,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ret = wl1271_setup(wl); if (ret < 0) goto out; + wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; break; + case CHIP_ID_1283_PG20: wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", wl->chip.id); @@ -1340,8 +1344,8 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) if (ret < 0) goto out; - if (wl1271_set_block_size(wl)) - wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT; + if (!wl1271_set_block_size(wl)) + wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; break; case CHIP_ID_1283_PG10: default: diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 3a9d2a6b8a09..a07ee8201d6d 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -201,10 +201,10 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, unsigned int packet_length) { - if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT) - return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); - else + if (wl->quirks & WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT) return ALIGN(packet_length, WL1271_TX_ALIGN_TO); + else + return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); } static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index b7036df5939d..e58e801f7aea 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -669,8 +669,8 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); /* Each RX/TX transaction requires an end-of-transaction transfer */ #define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) -/* WL128X requires aggregated packets to be aligned to the SDIO block size */ -#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2) +/* wl127x and SPI don't support SDIO block size alignment */ +#define WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT BIT(2) /* Older firmwares did not implement the FW logger over bus feature */ #define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4) From e62c9ce4a4c0e0ffd5718e962ba4606cd5d0d600 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 3 Nov 2011 08:44:42 +0200 Subject: [PATCH 79/97] wl12xx: use the same SDIO block size for all different chips The sdio driver uses a block size of 512 bytes by default. With our card, this doesn't work correctly because it sets the block size FBR in the chip too early (ie. before the chip is powered on). Thus, if we don't set it explicitly, block mode remains disabled in the chip. If we try to send more data than fits in one block, the sdio driver will split it into separate blocks before sending to the chip. This causes problems because the chip is not expecting multiple blocks. At the moment this is not a problem, because we use chunks of 512 bytes for firmware upload and the data is always sent in byte mode. In the next patch, we will change the chunk size to a bigger value, so this patch is a preparation for that. Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index b9a3fe497274..aa1c0f3ebeeb 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1313,7 +1313,16 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) /* 0. read chip id from CHIP_ID */ wl->chip.id = wl1271_read32(wl, CHIP_ID_B); - /* 1. check if chip id is valid */ + /* + * For wl127x based devices we could use the default block + * size (512 bytes), but due to a bug in the sdio driver, we + * need to set it explicitly after the chip is powered on. To + * simplify the code and since the performance impact is + * negligible, we use the same block size for all different + * chip types. + */ + if (!wl1271_set_block_size(wl)) + wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; switch (wl->chip.id) { case CHIP_ID_1271_PG10: @@ -1343,9 +1352,6 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ret = wl1271_setup(wl); if (ret < 0) goto out; - - if (!wl1271_set_block_size(wl)) - wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; break; case CHIP_ID_1283_PG10: default: From 3f3fd78e33213b1684ac1e4deacbcf7ed1828e3c Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 3 Nov 2011 08:44:43 +0200 Subject: [PATCH 80/97] wl12xx: increase firmware upload chunk size The chunk size used during firmware upload was set to 512, which is the size of a single SDIO block (or two). This is very inneficient because we send one or two blocks only per SDIO transaction and don't get the full benefits of sdio block transfers. This patch increases the chunk size to 16K. This more than doubles the transfer speed both in wl127x and wl128x chips, with greater impact on the latter: wl127x: 512 bytes chunk -> ~132ms 16384 bytes chunk -> ~57ms wl128x: 512 bytes chunk -> ~216ms 16384 bytes chunk -> ~37ms Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h index 3f570f397586..df34d5977b98 100644 --- a/drivers/net/wireless/wl12xx/reg.h +++ b/drivers/net/wireless/wl12xx/reg.h @@ -408,7 +408,7 @@ /* Firmware image load chunk size */ -#define CHUNK_SIZE 512 +#define CHUNK_SIZE 16384 /* Firmware image header size */ #define FW_HDR_SIZE 8 From bfafba8a4c61841ab850887d6dfe2741ad037ab6 Mon Sep 17 00:00:00 2001 From: Guy Eilam Date: Tue, 1 Nov 2011 09:23:51 +0200 Subject: [PATCH 81/97] wl12xx: set scan probe requests rate according to the no_cck flag Set the TX rate of probe requests during scanning according to the no_cck flag in the scan request struct. Signed-off-by: Guy Eilam Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/conf.h | 4 ++++ drivers/net/wireless/wl12xx/scan.c | 19 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 04bb8fbf93f9..1bcfb017058d 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -440,6 +440,10 @@ struct conf_rx_settings { CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ CONF_HW_BIT_RATE_54MBPS) +#define CONF_TX_CCK_RATES (CONF_HW_BIT_RATE_1MBPS | \ + CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ + CONF_HW_BIT_RATE_11MBPS) + #define CONF_TX_OFDM_RATES (CONF_HW_BIT_RATE_6MBPS | \ CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS | \ CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 898d03d5b527..a13c49e27a36 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -202,7 +202,6 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, cmd->params.tx_rate = cpu_to_le32(basic_rate); cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; - cmd->params.tx_rate = cpu_to_le32(basic_rate); cmd->params.tid_trigger = 0; cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; @@ -254,7 +253,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret = 0; enum ieee80211_band band; - u32 rate; + u32 rate, mask; switch (wl->scan.state) { case WL1271_SCAN_STATE_IDLE: @@ -262,7 +261,13 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) case WL1271_SCAN_STATE_2GHZ_ACTIVE: band = IEEE80211_BAND_2GHZ; - rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); + mask = wlvif->bitrate_masks[band]; + if (wl->scan.req->no_cck) { + mask &= ~CONF_TX_CCK_RATES; + if (!mask) + mask = CONF_TX_RATE_MASK_BASIC_P2P; + } + rate = wl1271_tx_min_rate_get(wl, mask); ret = wl1271_scan_send(wl, vif, band, false, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; @@ -273,7 +278,13 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) case WL1271_SCAN_STATE_2GHZ_PASSIVE: band = IEEE80211_BAND_2GHZ; - rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); + mask = wlvif->bitrate_masks[band]; + if (wl->scan.req->no_cck) { + mask &= ~CONF_TX_CCK_RATES; + if (!mask) + mask = CONF_TX_RATE_MASK_BASIC_P2P; + } + rate = wl1271_tx_min_rate_get(wl, mask); ret = wl1271_scan_send(wl, vif, band, true, rate); if (ret == WL1271_NOTHING_TO_SCAN) { if (wl->enable_11a) From 8a0f2ee37810aa4a4f46baf08b2ad587e138eb58 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 1 Nov 2011 09:23:52 +0200 Subject: [PATCH 82/97] wl12xx: use p2p rate index when the skb has the NO_CCK flag If the skb contains the NO_CCK flag, use the p2p rate index (which contains only the OFDM rates) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/tx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index a07ee8201d6d..fa518a5b7c8b 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -336,7 +336,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, /* if the packets are destined for AP (have a STA entry) send them with AP rate policies, otherwise use default basic rates */ - if (control->control.sta) + if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE) + rate_idx = wlvif->sta.p2p_rate_idx; + else if (control->control.sta) rate_idx = wlvif->sta.ap_rate_idx; else rate_idx = wlvif->sta.basic_rate_idx; From c31e494689128203ef04fb946f05a72d33eee948 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 23 Oct 2011 08:21:55 +0200 Subject: [PATCH 83/97] wl12xx: handle idle changes per-interface Idle changes are currently handled per hardware. However, some operations should be done only per-interface. Signed-off-by: Eliad Peller Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index aa1c0f3ebeeb..dbb088eadf71 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2540,13 +2540,6 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, } } - if (changed & IEEE80211_CONF_CHANGE_IDLE && !is_ap) { - ret = wl1271_sta_handle_idle(wl, wlvif, - conf->flags & IEEE80211_CONF_IDLE); - if (ret < 0) - wl1271_warning("idle mode change failed %d", ret); - } - /* * if mac80211 changes the PSM mode, make sure the mode is not * incorrectly changed after the pspoll failure active window. @@ -3617,6 +3610,12 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, do_join = true; } + if (changed & BSS_CHANGED_IDLE) { + ret = wl1271_sta_handle_idle(wl, wlvif, bss_conf->idle); + if (ret < 0) + wl1271_warning("idle mode change failed %d", ret); + } + if ((changed & BSS_CHANGED_CQM)) { bool enable = false; if (bss_conf->cqm_rssi_thold) From b693289406f0b8ca70ab77e745be6196d5740eb0 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Tue, 8 Nov 2011 15:56:55 +0200 Subject: [PATCH 84/97] wl12xx: fix SDIO suspend/resume wl1271_suspend/resume() accessed the wrong struct and not wl1271 which caused it to think that wow was enabled when it wasn't. Signed-off-by: Eyal Shapira Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/sdio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index ed97f9cee3f0..468a50553fac 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -289,7 +289,8 @@ static int wl1271_suspend(struct device *dev) /* Tell MMC/SDIO core it's OK to power down the card * (if it isn't already), but not to remove it completely */ struct sdio_func *func = dev_to_sdio_func(dev); - struct wl1271 *wl = sdio_get_drvdata(func); + struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); + struct wl1271 *wl = platform_get_drvdata(glue->core); mmc_pm_flag_t sdio_flags; int ret = 0; @@ -324,7 +325,8 @@ out: static int wl1271_resume(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); - struct wl1271 *wl = sdio_get_drvdata(func); + struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); + struct wl1271 *wl = platform_get_drvdata(glue->core); dev_dbg(dev, "wl1271 resume\n"); if (wl->wow_enabled) { From 2131d3c2f99b081806fdae7662c92fe6acda52af Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Tue, 18 Oct 2011 09:23:41 +0200 Subject: [PATCH 85/97] wl12xx: Validate FEM index from ini file and FW Check for out of bound FEM index to prevent reading beyond ini memory end. Signed-off-by: Pontus Fuchs Cc: stable@kernel.org Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index afd597387e7e..e0d217979485 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -121,6 +121,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) if (!wl->nvs) return -ENODEV; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from INI out of bounds"); + return -EINVAL; + } + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); if (!gen_parms) return -ENOMEM; @@ -144,6 +149,12 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) gp->tx_bip_fem_manufacturer = gen_parms->general_params.tx_bip_fem_manufacturer; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from FW out of bounds"); + ret = -EINVAL; + goto out; + } + wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); @@ -163,6 +174,11 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) if (!wl->nvs) return -ENODEV; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from ini out of bounds"); + return -EINVAL; + } + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); if (!gen_parms) return -ENOMEM; @@ -187,6 +203,12 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) gp->tx_bip_fem_manufacturer = gen_parms->general_params.tx_bip_fem_manufacturer; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from FW out of bounds"); + ret = -EINVAL; + goto out; + } + wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); From f6efe96edd9c41c624c8f4ddbc4930c1a2d8f1e1 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Tue, 18 Oct 2011 09:23:42 +0200 Subject: [PATCH 86/97] wl12xx: Check buffer bound when processing nvs data An nvs with malformed contents could cause the processing of the calibration data to read beyond the end of the buffer. Prevent this from happening by adding bound checking. Signed-off-by: Pontus Fuchs Cc: stable@kernel.org Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/boot.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 6e140bf4e236..8f9cf5a816ea 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -348,6 +348,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) nvs_ptr += 3; for (i = 0; i < burst_len; i++) { + if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len) + goto out_badnvs; + val = (nvs_ptr[0] | (nvs_ptr[1] << 8) | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); @@ -359,6 +362,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) nvs_ptr += 4; dest_addr += 4; } + + if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) + goto out_badnvs; } /* @@ -370,6 +376,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) */ nvs_ptr = (u8 *)wl->nvs + ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4); + + if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) + goto out_badnvs; + nvs_len -= nvs_ptr - (u8 *)wl->nvs; /* Now we must set the partition correctly */ @@ -385,6 +395,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) kfree(nvs_aligned); return 0; + +out_badnvs: + wl1271_error("nvs data is malformed"); + return -EILSEQ; } static void wl1271_boot_enable_interrupts(struct wl1271 *wl) From 560f00241b6d95bde73a570c29d6919b36fdf852 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 8 Nov 2011 18:46:54 +0200 Subject: [PATCH 87/97] wl12xx: configure probe-resp template according to notification When operating in AP-mode, replace our probe-response template when a notification is recieved from mac80211. We preserve the "legacy" way of configuring a probe-response according to beacon for IBSS mode and for versions of hostapd that do not support this feature. Signed-off-by: Guy Eilam Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 57 ++++++++++++++++++++++++---- drivers/net/wireless/wl12xx/wl12xx.h | 1 + 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index dbb088eadf71..3750a6e479f3 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3299,11 +3299,30 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb, skb_trim(skb, skb->len - len); } -static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, - struct ieee80211_vif *vif, - u8 *probe_rsp_data, - size_t probe_rsp_len, - u32 rates) +static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates) +{ + struct sk_buff *skb; + int ret; + + skb = ieee80211_proberesp_get(wl->hw, wl->vif); + if (!skb) + return -EINVAL; + + ret = wl1271_cmd_template_set(wl, + CMD_TEMPL_AP_PROBE_RESPONSE, + skb->data, + skb->len, 0, + rates); + + dev_kfree_skb(skb); + return ret; +} + +static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl, + struct ieee80211_vif *vif, + u8 *probe_rsp_data, + size_t probe_rsp_len, + u32 rates) { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; @@ -3416,6 +3435,16 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, wlvif->beacon_int = bss_conf->beacon_int; } + if ((changed & BSS_CHANGED_AP_PROBE_RESP) && is_ap) { + u32 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); + ret = wl1271_ap_set_probe_resp_tmpl(wl, rate); + if (ret < 0) + goto out; + + wl1271_debug(DEBUG_AP, "probe response updated"); + set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); + } + if ((changed & BSS_CHANGED_BEACON)) { struct ieee80211_hdr *hdr; u32 min_rate; @@ -3424,8 +3453,10 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); u16 tmpl_id; - if (!beacon) + if (!beacon) { + ret = -EINVAL; goto out; + } wl1271_debug(DEBUG_MASTER, "beacon updated"); @@ -3446,6 +3477,13 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, goto out; } + /* + * In case we already have a probe-resp beacon set explicitly + * by usermode, don't use the beacon data. + */ + if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags)) + goto end_bcn; + /* remove TIM ie from probe response */ wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); @@ -3464,7 +3502,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); if (is_ap) - ret = wl1271_ap_set_probe_resp_tmpl(wl, vif, + ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif, beacon->data, beacon->len, min_rate); @@ -3474,12 +3512,15 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, beacon->data, beacon->len, 0, min_rate); +end_bcn: dev_kfree_skb(beacon); if (ret < 0) goto out; } out: + if (ret != 0) + wl1271_error("beacon info change failed: %d", ret); return ret; } @@ -3536,6 +3577,8 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, goto out; clear_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags); + clear_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, + &wlvif->flags); wl1271_debug(DEBUG_AP, "stopped AP"); } } diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index e58e801f7aea..f1c911774bfd 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -268,6 +268,7 @@ enum wl12xx_vif_flags { WLVIF_FLAG_RX_STREAMING_STARTED, WLVIF_FLAG_PSPOLL_FAILURE, WLVIF_FLAG_CS_PROGRESS, + WLVIF_FLAG_AP_PROBE_RESP_SET, }; struct wl1271_link { From 9c1b190b10972be9c0d53c658e537c54de530b7f Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 8 Nov 2011 18:46:55 +0200 Subject: [PATCH 88/97] wl12xx: indicate probe-resp offloading support The wl12xx driver supports probe-response offloading, and the WPS, WPS2 and P2P special cases as well. Signed-off-by: Guy Eilam Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 3750a6e479f3..08b06ee6d515 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -5017,6 +5017,13 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->wiphy->reg_notifier = wl1271_reg_notify; + /* the FW answers probe-requests in AP-mode */ + wl->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; + wl->hw->wiphy->probe_resp_offload = + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; + SET_IEEE80211_DEV(wl->hw, wl->dev); wl->hw->sta_data_size = sizeof(struct wl1271_station); From 97127e67218e5970a5a7df0513ded730b19a67e9 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 9 Nov 2011 13:12:45 +0200 Subject: [PATCH 89/97] wl12xx: init CMD_TEMPL_KLV to sizeof(ieee80211_qos_hdr) The keep alive template should have a max size of sizeof(struct ieee80211_qos_hdr). Additionally, Remove the redundant wl12xx_qos_null_data_template struct. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/init.c | 6 +++--- drivers/net/wireless/wl12xx/wl12xx_80211.h | 5 ----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index c413abd26d1c..88891cdfdd4a 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -65,7 +65,7 @@ int wl1271_init_templates_config(struct wl1271 *wl) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, sizeof - (struct wl12xx_qos_null_data_template), + (struct ieee80211_qos_hdr), 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; @@ -114,8 +114,8 @@ int wl1271_init_templates_config(struct wl1271 *wl) for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, - WL1271_CMD_TEMPL_DFLT_SIZE, i, - WL1271_RATE_AUTOMATIC); + sizeof(struct ieee80211_qos_hdr), + i, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; } diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h index f7971d3b0898..8f0ffaf62309 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h @@ -116,11 +116,6 @@ struct wl12xx_ps_poll_template { u8 ta[ETH_ALEN]; } __packed; -struct wl12xx_qos_null_data_template { - struct ieee80211_header header; - __le16 qos_ctl; -} __packed; - struct wl12xx_arp_rsp_template { struct ieee80211_hdr_3addr hdr; From 341f2c11b5ce7689d3f0acb04574fe6424aa6be0 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 22 Nov 2011 19:52:59 +0200 Subject: [PATCH 90/97] wl12xx: avoid bail out when probe-resp is not set by mac80211 During reconfig we can get the BSS_CHANGED_AP_PROBE_RESP indication even if a probe-resp has not been set in the first place. Therefore ignore the error when not getting a probe-resp from mac80211. Resort to the legacy probe-resp in this case. Also take this opportunity to add a vif argument to the set_probe_resp function. Reported-by: Eliad Peller Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 08b06ee6d515..8c58001c76d4 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3299,14 +3299,15 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb, skb_trim(skb, skb->len - len); } -static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates) +static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates, + struct ieee80211_vif *vif) { struct sk_buff *skb; int ret; - skb = ieee80211_proberesp_get(wl->hw, wl->vif); + skb = ieee80211_proberesp_get(wl->hw, vif); if (!skb) - return -EINVAL; + return -EOPNOTSUPP; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, @@ -3437,12 +3438,10 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, if ((changed & BSS_CHANGED_AP_PROBE_RESP) && is_ap) { u32 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - ret = wl1271_ap_set_probe_resp_tmpl(wl, rate); - if (ret < 0) - goto out; - - wl1271_debug(DEBUG_AP, "probe response updated"); - set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); + if (!wl1271_ap_set_probe_resp_tmpl(wl, rate, vif)) { + wl1271_debug(DEBUG_AP, "probe response updated"); + set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); + } } if ((changed & BSS_CHANGED_BEACON)) { From 358989352e70975d1c50ac2a49fc86d41d0518bd Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Wed, 30 Nov 2011 15:35:09 +0100 Subject: [PATCH 91/97] wl12xx: Print nvs/fw file name if loading fails. Print the name of nvs/fw if request_firmware fails. This will make troubleshooting a bit easier. Signed-off-by: Pontus Fuchs Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8c58001c76d4..8ff1bf5be013 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1055,7 +1055,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) ret = request_firmware(&fw, fw_name, wl->dev); if (ret < 0) { - wl1271_error("could not get firmware: %d", ret); + wl1271_error("could not get firmware %s: %d", fw_name, ret); return ret; } @@ -1093,7 +1093,8 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) ret = request_firmware(&fw, WL12XX_NVS_NAME, wl->dev); if (ret < 0) { - wl1271_error("could not get nvs file: %d", ret); + wl1271_error("could not get nvs file %s: %d", WL12XX_NVS_NAME, + ret); return ret; } From 12d4b9759143aaa280195834820bc15d795e71c1 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 23 Oct 2011 08:21:54 +0200 Subject: [PATCH 92/97] wl12xx: leave IV calculation to HW for CCMP Use an appropriate mac80211 flags in CCMP keys to indicate we are calculating the CCMP IV in HW, but require room for the IV to be reserved in the skb. The space is reserved by mac80211. depends on "mac80211: support adding IV-room in the skb for CCMP keys". Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8ff1bf5be013..d1416752feea 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2986,7 +2986,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, case WLAN_CIPHER_SUITE_CCMP: key_type = KEY_AES; - key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); break; From e0d62536d032db689adf9c8162a9d2caf4714f44 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 8 Nov 2011 16:07:52 +0200 Subject: [PATCH 93/97] wl12xx: don't explicitly check for unjoined ibss After the ibss carrier issue was fixed, we can revert the following patch: commit 48309fd477ef867babb6819f67fe082c133a5fa9 Author: Shahar Lev Date: Fri Oct 7 18:17:25 2011 +0200 wl12xx: remove warning message during IBSS Tx mac80211 sets the carrier on an IBSS interface even when no network is joined. Ignore garbage frames transmitted on a disconnected IBSS interface without printing warnings. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/tx.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index fa518a5b7c8b..36eb0d66fd66 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -427,15 +427,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, } hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); if (hlid == WL12XX_INVALID_LINK_ID) { - if (wlvif->bss_type == BSS_TYPE_IBSS && - !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) { - /* It's ok to drop packets when not joined to IBSS */ - wl1271_debug(DEBUG_TX, "dropping skb while IBSS not " - " joined"); - } else { - wl1271_error("invalid hlid. dropping skb 0x%p", skb); - } - + wl1271_error("invalid hlid. dropping skb 0x%p", skb); return -EINVAL; } From abc47470ef63cdde2efdf358ae373afb16f358c0 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 6 Dec 2011 12:15:05 +0200 Subject: [PATCH 94/97] wl12xx: fix testmode test/interrogate commands fix several issues in testmode test/interrogate commands: 1. check the driver state is not OFF. 2. wakeup the chip from elp (if needed) 3. fix memory leak in wl1271_tm_cmd_interrogate() Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/testmode.c | 74 +++++++++++++++++++------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 61fff45686ad..2f9ebff2ded3 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -29,6 +29,7 @@ #include "debug.h" #include "acx.h" #include "reg.h" +#include "ps.h" #define WL1271_TM_MAX_DATA_LENGTH 1024 @@ -88,31 +89,47 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) return -EMSGSIZE; mutex_lock(&wl->mutex); - ret = wl1271_cmd_test(wl, buf, buf_len, answer); - mutex_unlock(&wl->mutex); + if (wl->state == WL1271_STATE_OFF) { + ret = -EINVAL; + goto out; + } + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + + ret = wl1271_cmd_test(wl, buf, buf_len, answer); if (ret < 0) { wl1271_warning("testmode cmd test failed: %d", ret); - return ret; + goto out_sleep; } if (answer) { len = nla_total_size(buf_len); skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len); - if (!skb) - return -ENOMEM; + if (!skb) { + ret = -ENOMEM; + goto out_sleep; + } NLA_PUT(skb, WL1271_TM_ATTR_DATA, buf_len, buf); ret = cfg80211_testmode_reply(skb); if (ret < 0) - return ret; + goto out_sleep; } - return 0; +out_sleep: + wl1271_ps_elp_sleep(wl); +out: + mutex_unlock(&wl->mutex); + + return ret; nla_put_failure: kfree_skb(skb); - return -EMSGSIZE; + ret = -EMSGSIZE; + goto out_sleep; } static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) @@ -129,33 +146,50 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]); - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) - return -ENOMEM; - mutex_lock(&wl->mutex); - ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd)); - mutex_unlock(&wl->mutex); + if (wl->state == WL1271_STATE_OFF) { + ret = -EINVAL; + goto out; + } + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out_sleep; + } + + ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd)); if (ret < 0) { wl1271_warning("testmode cmd interrogate failed: %d", ret); - kfree(cmd); - return ret; + goto out_free; } skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd)); if (!skb) { - kfree(cmd); - return -ENOMEM; + ret = -ENOMEM; + goto out_free; } NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd); - return 0; +out_free: + kfree(cmd); +out_sleep: + wl1271_ps_elp_sleep(wl); +out: + mutex_unlock(&wl->mutex); + + return ret; nla_put_failure: kfree_skb(skb); - return -EMSGSIZE; + ret = -EMSGSIZE; + goto out_free; } static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[]) From 188e7f54c38b9bf144ddc81b4b734cb6ea49f31e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 6 Dec 2011 12:15:06 +0200 Subject: [PATCH 95/97] wl12xx: remove redundant commands from plt init During plt init we configure some redundant commands, which are not needed for plt (specifically, we shouldn't configure any role-specific params, as there are no active roles). remove them. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 61 +----------------------------- 1 file changed, 1 insertion(+), 60 deletions(-) diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index d1416752feea..2f7bfa86c8cd 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -641,9 +641,7 @@ static void wl1271_conf_init(struct wl1271 *wl) static int wl1271_plt_init(struct wl1271 *wl) { - struct conf_tx_ac_category *conf_ac; - struct conf_tx_tid *conf_tid; - int ret, i; + int ret; if (wl->chip.id == CHIP_ID_1283_PG20) ret = wl128x_cmd_general_parms(wl); @@ -672,10 +670,6 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_init_templates_config(wl); - if (ret < 0) - return ret; - ret = wl1271_acx_init_mem_config(wl); if (ret < 0) return ret; @@ -685,63 +679,10 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; - ret = wl1271_acx_dco_itrim_params(wl); - if (ret < 0) - goto out_free_memmap; - - /* Initialize connection monitoring thresholds */ - ret = wl1271_acx_conn_monit_params(wl, NULL, false); /* TODO: fix */ - if (ret < 0) - goto out_free_memmap; - - /* Bluetooth WLAN coexistence */ - ret = wl1271_init_pta(wl); - if (ret < 0) - goto out_free_memmap; - - /* FM WLAN coexistence */ - ret = wl1271_acx_fm_coex(wl); - if (ret < 0) - goto out_free_memmap; - - /* Energy detection */ - ret = wl1271_init_energy_detection(wl); - if (ret < 0) - goto out_free_memmap; - ret = wl12xx_acx_mem_cfg(wl); if (ret < 0) goto out_free_memmap; - /* Default fragmentation threshold */ - ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); - if (ret < 0) - goto out_free_memmap; - - /* Default TID/AC configuration */ - BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); - for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { - conf_ac = &wl->conf.tx.ac_conf[i]; - /* TODO: fix */ - ret = wl1271_acx_ac_cfg(wl, NULL, conf_ac->ac, conf_ac->cw_min, - conf_ac->cw_max, conf_ac->aifsn, - conf_ac->tx_op_limit); - if (ret < 0) - goto out_free_memmap; - - conf_tid = &wl->conf.tx.tid_conf[i]; - /* TODO: fix */ - ret = wl1271_acx_tid_cfg(wl, NULL, conf_tid->queue_id, - conf_tid->channel_type, - conf_tid->tsid, - conf_tid->ps_scheme, - conf_tid->ack_policy, - conf_tid->apsd_conf[0], - conf_tid->apsd_conf[1]); - if (ret < 0) - goto out_free_memmap; - } - /* Enable data path */ ret = wl1271_cmd_data_path(wl, 1); if (ret < 0) From 3dbb5846db1f5df3619b927cc2a7dcaf65a38f1e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 6 Dec 2011 12:15:07 +0200 Subject: [PATCH 96/97] wl12xx: send testmode reply in wl1271_tm_cmd_interrogate wl1271_tm_cmd_interrogate creates a reply skb, but doesn't send it (and thus just leaks it). Add the missing cfg80211_testmode_reply() call. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/testmode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 2f9ebff2ded3..978cf2de713d 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -176,6 +176,9 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) } NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd); + ret = cfg80211_testmode_reply(skb); + if (ret < 0) + goto out_free; out_free: kfree(cmd); From 1b04b739f4c1d053bebb29657fb69bf03f180a97 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Wed, 7 Dec 2011 12:37:04 +0200 Subject: [PATCH 97/97] wl12xx: minor fix in sched_scan_ssid_list The user can pass broadcast SSID (ssid="") in the list of SSIDs for active scan. In this case the loop was attempting to match SSIDs in the filter list to this empty entry and marking them as HIDDEN (sending probe request) by mistake Signed-off-by: Eyal Shapira Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/scan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 330d6788a916..8599dab1fe2a 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -572,6 +572,9 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, * so they're used in probe requests. */ for (i = 0; i < req->n_ssids; i++) { + if (!req->ssids[i].ssid_len) + continue; + for (j = 0; j < cmd->n_ssids; j++) if (!memcmp(req->ssids[i].ssid, cmd->ssids[j].ssid,