From 784f694d0f3ca927361aa0c26de1aa340eb5b275 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:39 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index a52299e548f..bee44c7d67f 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 b7bd42769aa..1ae949f00c1 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 674ad2a9e40..7e3ff808fee 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 04db64c94e9..4692a91ca73 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 3a3c230fd29..b1f97bcc47c 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 884f82b6321..652471e8c61 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 128ccb79318..a8576181ab7 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 92115156522..15177bdfb54 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 1ec90fc7505..b8de2f5e052 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; -- cgit v1.2.3-70-g09d2 From 92c77c734f958474ac73af670834bc32cb833e54 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:40 +0200 Subject: 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 | 306 ++++++++++++++++++++----------------- drivers/net/wireless/wl12xx/init.h | 5 +- drivers/net/wireless/wl12xx/main.c | 8 +- 3 files changed, 171 insertions(+), 148 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 4692a91ca73..145601dddab 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,68 +208,32 @@ out: return ret; } -static int wl1271_ap_init_templates_config(struct wl1271 *wl) +static int wl12xx_init_rx_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); + ret = wl1271_acx_rx_msdu_life_time(wl); if (ret < 0) return ret; return 0; } -static int wl12xx_init_rx_config(struct wl1271 *wl) +int wl1271_init_phy_config(struct wl1271 *wl) { int ret; - ret = wl1271_acx_rx_msdu_life_time(wl); + ret = wl1271_acx_pd_threshold(wl); if (ret < 0) return ret; return 0; } -int wl1271_init_phy_config(struct wl1271 *wl) +static int wl12xx_init_phy_vif_config(struct wl1271 *wl) { int ret; - ret = wl1271_acx_pd_threshold(wl); - if (ret < 0) - return 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; + + 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; -int wl1271_hw_init(struct wl1271 *wl, struct ieee80211_vif *vif) + /* 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 b1f97bcc47c..64320c0224c 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 652471e8c61..901e43a8334 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; -- cgit v1.2.3-70-g09d2 From 87fbcb0f8c5c8fd57a4e3e7e638977c04ce1e0ca Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:41 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index bee44c7d67f..c99fc61113d 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 1ae949f00c1..234a8dc9055 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 3999fd52830..0419aafe5c5 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 145601dddab..c00bdf8a358 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 64320c0224c..81140b81f65 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 901e43a8334..0c43cf55f9b 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 b8de2f5e052..7e30dd53cb8 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); -- cgit v1.2.3-70-g09d2 From 30d0c8fd5b87d1c5486705d6420545a21533e115 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:42 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index ca044a74319..1ef9b0b4863 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 e3f93b4b342..81779f45ab4 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 c99fc61113d..6a2f758eb1d 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 0419aafe5c5..e63fea4b120 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 c00bdf8a358..37955dad1f9 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 0c43cf55f9b..195dcbdf1fc 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 7e30dd53cb8..6f3efbae740 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) -- cgit v1.2.3-70-g09d2 From d2d66c56cf6c8727662aa321991f791604c22094 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:43 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 1ef9b0b4863..015938f9480 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 81779f45ab4..2678e1d505f 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 6a2f758eb1d..ce734157980 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 234a8dc9055..d5749f5b3bf 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 e63fea4b120..620acbfd9ec 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 7e3ff808fee..af4cef366a3 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 37955dad1f9..ed27c5f06bb 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 195dcbdf1fc..8863ea542ea 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 6f3efbae740..d355c737044 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; }; -- cgit v1.2.3-70-g09d2 From cdf09495588fda7e9c15c25bc20cb828e07be314 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:44 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index ce734157980..b9bb76b22f5 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 af4cef366a3..30d05fd2467 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 8863ea542ea..d19c3fe3486 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 d355c737044..44a5daeff07 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; -- cgit v1.2.3-70-g09d2 From 536129c8ad35de87ff2f864f205a54ac32bfebcc Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:45 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index b9bb76b22f5..096a713a8c9 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 620acbfd9ec..8f88ad6496f 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 30d05fd2467..072addc0bff 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 ed27c5f06bb..e54cc693ff6 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 d19c3fe3486..5b13af0f8e8 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 dee4cfe9ccc..9cfa0b25a6f 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 a8576181ab7..197d2c2b1e7 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 15177bdfb54..a7ed43dc08c 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 bad9e29d49b..5561ec2d4b4 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 dc4f09adf08..ba9403a4540 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 44a5daeff07..97ed19c6769 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; /* -- cgit v1.2.3-70-g09d2 From 10bcf745ae737cfbca1796386d76b0636b086770 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:46 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 5b13af0f8e8..50ee9d40e64 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 97ed19c6769..0578d750528 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; -- cgit v1.2.3-70-g09d2 From fb0e707c838ac7d8aae7ab90ea448e5ac1e29697 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:47 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 50ee9d40e64..111a465ec54 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 0578d750528..d84c0deee36 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; -- cgit v1.2.3-70-g09d2 From 1fe9f1616ee0852e9422d1f676630e9a4531ace3 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:48 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 096a713a8c9..1f29eab8214 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 111a465ec54..0da9ddc8b6c 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 d84c0deee36..539cf40be53 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; /* -- cgit v1.2.3-70-g09d2 From bddb29b83a9874fda21c34abe7627cbf14fec10e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:49 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0da9ddc8b6c..006e1745813 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 197d2c2b1e7..e3b863b895f 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 539cf40be53..8d100561522 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) -- cgit v1.2.3-70-g09d2 From 6840e37aec6fd9ffa5b4cf62674af55afdb565ed Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:50 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 006e1745813..e0a557fc3a3 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 8d100561522..e6d3c214acf 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) -- cgit v1.2.3-70-g09d2 From 0603d891c5b5153f667a79357d4652824c22b54e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:51 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 015938f9480..9b4eef61bd0 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 2678e1d505f..7fccfcc55ca 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 1f29eab8214..918faca517c 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 d5749f5b3bf..bf2c45b8b91 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 8f88ad6496f..3309fea2e90 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 072addc0bff..28a4396fb8e 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 e54cc693ff6..1eaa0a3d927 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 e0a557fc3a3..b3d4ef5b900 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 c15ebf2efd4..ac3f20716f5 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 25eb9bc9b62..6ad0a0bd29b 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 e3b863b895f..9d0dfb516e2 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 e6d3c214acf..e249b459f62 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; -- cgit v1.2.3-70-g09d2 From 7edebf56ca424484b9e0e51a6188c93c7fdd3a41 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:52 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 918faca517c..36544ff6a79 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 bf2c45b8b91..fb40556a8ad 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 b3d4ef5b900..f4d3df15719 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 9d0dfb516e2..9372136b27e 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 5561ec2d4b4..538d8613b32 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 e249b459f62..4c69ae1635f 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; -- cgit v1.2.3-70-g09d2 From 154da67c7da14ffd8da292394f8cbc81cc5ea4e3 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:53 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 36544ff6a79..2a9a4b2032e 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 fb40556a8ad..25ab400f2eb 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 f4d3df15719..3358cfe5b01 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 538d8613b32..db55767d7d5 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 4c69ae1635f..a1084d1466b 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; -- cgit v1.2.3-70-g09d2 From a8ab39a4b588e8523be2fa75671bdc9612d3467a Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:54 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 2a9a4b2032e..d0124e63dad 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 25ab400f2eb..9624828b76e 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 3358cfe5b01..731e34bc275 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 db55767d7d5..53c6451a8fd 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 ba9403a4540..0964c933531 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 a1084d1466b..aa84899466a 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]; -- cgit v1.2.3-70-g09d2 From 98b8625301e55bd3e4340f704edc378e4707e577 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:55 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index d0124e63dad..89d263e7b56 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 3309fea2e90..d8d85682365 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 731e34bc275..63871b46c0c 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 53c6451a8fd..da8427f5d7a 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 aa84899466a..9fcaa03cd73 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 -- cgit v1.2.3-70-g09d2 From e936bbe0dc235458408c060deaa43f5b8b0bd705 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:56 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 63871b46c0c..effba53eb3f 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) { -- cgit v1.2.3-70-g09d2 From afaf8bdb2b08bbf493b03757243821df72b26c53 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:57 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 89d263e7b56..166d984cb5a 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 effba53eb3f..e8d73d70ced 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 da8427f5d7a..8db68c64943 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 9fcaa03cd73..752b6b99210 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 { -- cgit v1.2.3-70-g09d2 From 6a8997964366f51c39d8efcfdc0e6319b2bd01fa Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:58 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 166d984cb5a..68375ffb412 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 d8d85682365..439db1f8d27 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 e8d73d70ced..577266defe9 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 752b6b99210..9d4b72e96c2 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; -- cgit v1.2.3-70-g09d2 From f75c753f3c77b758fa5ace90c15b2ea3b7a3d46d Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:55:59 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 577266defe9..09983dee410 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 8db68c64943..509ae10f0e0 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 9d4b72e96c2..91e6cd36bf8 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; -- cgit v1.2.3-70-g09d2 From 252efa4f978a2901039fffc934060fb8ccf82ac7 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:00 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 28a4396fb8e..4e3474c11e0 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 09983dee410..76f46638066 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 91e6cd36bf8..d6d5a7bff31 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) -- cgit v1.2.3-70-g09d2 From 6ec45dc282f6983d5685758c5e8993bc2c818d3c Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:01 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 4e3474c11e0..7a9913a3f71 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 76f46638066..cb2355354bf 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 d6d5a7bff31..7166a79e00e 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; }; -- cgit v1.2.3-70-g09d2 From 74ec839557878007c3f97d1bc89e09fde5d0f3fa Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:02 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 439db1f8d27..cd390e0da51 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 7a9913a3f71..6c48b8c3f5b 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 cb2355354bf..fd2b9f21acf 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 7166a79e00e..9d9d3fbd14e 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) -- cgit v1.2.3-70-g09d2 From 04324d99818d16da4f64e266b45cad2e5803b961 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:03 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 9b4eef61bd0..5b70cc19e1d 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 cd390e0da51..e53f96830c2 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 6c48b8c3f5b..775ad952ac8 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 fd2b9f21acf..72ab25657da 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 9d9d3fbd14e..5a82450d8c7 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) -- cgit v1.2.3-70-g09d2 From d0802abdf9c60b1dadb097e806022f3449b0cc6b Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:04 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index e53f96830c2..ee42a43d6a6 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 775ad952ac8..8c31274228e 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 1eaa0a3d927..80e89e31987 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 72ab25657da..984dae881a8 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 509ae10f0e0..6ce61635f3b 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 5a82450d8c7..fcc779147c1 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) -- cgit v1.2.3-70-g09d2 From c7ffb902cca655e4d6bdda4156407008573bb214 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:05 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 68375ffb412..102a8a5371e 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 9624828b76e..d2670d379b7 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 ee42a43d6a6..f0398d037d4 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 8c31274228e..486c8ee0101 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 49c1a0ede5b..1d878ba47bf 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 984dae881a8..f712f0fb50b 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; - - cnt = status->tx_lnk_free_pkts[hlid] - - wl->links[hlid].prev_freed_pkts; + 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; - wl->links[hlid].prev_freed_pkts = - status->tx_lnk_free_pkts[hlid]; - wl->links[hlid].allocated_pkts -= cnt; + lnk->prev_freed_pkts = status->tx_lnk_free_pkts[hlid]; + lnk->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 6ce61635f3b..1b3d8e3f35a 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 0964c933531..add4402d793 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 fcc779147c1..5fd3c262bc5 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; -- cgit v1.2.3-70-g09d2 From 170d0e6732c5fb1d4103ded3da95a5630c24e5dd Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 5 Oct 2011 11:56:06 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index f712f0fb50b..194d7cc366d 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 5fd3c262bc5..074de4e1fb3 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; }; -- cgit v1.2.3-70-g09d2 From 1d095475f58680af17e4a0e8dd84269b3f08ce54 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:49 +0200 Subject: 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 | 171 ++++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 194d7cc366d..3667acf0a03 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1888,60 +1888,12 @@ static int wl12xx_init_vif_data(struct ieee80211_vif *vif) return 0; } -static int wl1271_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static bool wl12xx_init_fw(struct wl1271 *wl) { - 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; - - wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", - ieee80211_vif_type_p2p(vif), vif->addr); - - mutex_lock(&wl->mutex); - if (wl->vif) { - wl1271_debug(DEBUG_MAC80211, - "multiple vifs are not supported yet"); - ret = -EBUSY; - goto out; - } - - /* - * in some very corner case HW recovery scenarios its possible to - * 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)) { - ret = -EBUSY; - goto out; - } - - ret = wl12xx_init_vif_data(vif); - 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; - 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) { - wl1271_error("cannot start because not in off state: %d", - wl->state); - ret = -EBUSY; - goto out; - } + struct wiphy *wiphy = wl->hw->wiphy; + int ret; while (retries) { retries--; @@ -1957,30 +1909,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, 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; - } - - ret = wl12xx_cmd_role_enable(wl, vif->addr, - role_type, &wlvif->role_id); - if (ret < 0) - goto irq_disable; - - ret = wl1271_init_vif_specific(wl, vif); - if (ret < 0) - goto irq_disable; - booted = true; break; @@ -2007,9 +1935,6 @@ power_off: 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 */ @@ -2027,6 +1952,96 @@ power_off: 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 wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + int ret = 0; + u8 role_type; + bool booted = false; + + wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", + ieee80211_vif_type_p2p(vif), vif->addr); + + mutex_lock(&wl->mutex); + if (wl->vif) { + wl1271_debug(DEBUG_MAC80211, + "multiple vifs are not supported yet"); + ret = -EBUSY; + goto out; + } + + /* + * in some very corner case HW recovery scenarios its possible to + * 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)) { + ret = -EBUSY; + goto out; + } + + ret = wl12xx_init_vif_data(vif); + 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; + goto out; + } + + /* + * TODO: after the nvs issue will be solved, move this block + * to start(), and make sure here the driver is ON. + */ + 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); + + 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, + WL1271_ROLE_DEVICE, + &wlvif->dev_role_id); + if (ret < 0) + goto out; + } + + 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; + set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); out: mutex_unlock(&wl->mutex); -- cgit v1.2.3-70-g09d2 From 4438aca9e16901d8d32a025ca27ad8284a117e09 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:50 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index f0398d037d4..bbc8004edf4 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 3667acf0a03..0606b0d8aab 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 1b3d8e3f35a..951ff03b7f4 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 074de4e1fb3..b350f0bdd38 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]; -- cgit v1.2.3-70-g09d2 From d6a3cc2ef962ad4392a2401cae513a18a6d35099 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:51 +0200 Subject: 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 | 109 +++++++++++++---------------------- drivers/net/wireless/wl12xx/tx.h | 5 +- drivers/net/wireless/wl12xx/wl12xx.h | 1 - 4 files changed, 55 insertions(+), 92 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0606b0d8aab..abe5ef8807b 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 951ff03b7f4..6c0135b2782 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,41 +887,30 @@ 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) { - 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++) { + 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); - 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); - } - } - } + else + wlvif->sta.ba_rx_bitmap = 0; - 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) +{ + int i; + struct sk_buff *skb; + struct ieee80211_tx_info *info; 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 add4402d793..050a0479260 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 b350f0bdd38..4802f685de6 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; -- cgit v1.2.3-70-g09d2 From baf6277ae964b1d3830aa74b13e87ff9ba29145c Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:52 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index abe5ef8807b..e53829aab92 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); - - /* - * 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); + mutex_unlock(&wl->mutex); + cancel_delayed_work_sync(&wlvif->pspoll_work); - 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, -- cgit v1.2.3-70-g09d2 From 83587505a2b63bb434f76b26a22f48283b86a467 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:53 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 102a8a5371e..ff653e8832a 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 d2670d379b7..8182cf1b486 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 e53829aab92..acfc49743d2 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 9372136b27e..e1a8ce092e3 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 4802f685de6..33ccdf84c43 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; /* -- cgit v1.2.3-70-g09d2 From 87627214738fcfd44803e90193f9f2f4583ce68b Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:54 +0200 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index acfc49743d2..56d59239867 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 33ccdf84c43..55561c597ad 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); -- cgit v1.2.3-70-g09d2 From a32d0cdfcb7e5d41f210e13cbc78dc86a5a85a08 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:55 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 56d59239867..0623f5dc02c 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 6c0135b2782..c7be15186c4 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 050a0479260..fe29ff524e9 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); -- cgit v1.2.3-70-g09d2 From a4e4130dcea01f3e0dfcbfeaf0d815b971e6e515 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 11 Oct 2011 11:49:15 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 80e89e31987..4af7e2fb52f 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 0623f5dc02c..b52deac368f 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 55561c597ad..fd78f8c1ebc 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; -- cgit v1.2.3-70-g09d2 From 4b730b6a814fe52425d90ff3db3d8deefb22fb24 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:57 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 486c8ee0101..dbc40bb49bc 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 fd78f8c1ebc..de9a2b63940 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); -- cgit v1.2.3-70-g09d2 From 48e93e402ad19f570bae323b07911bdf6562af8e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:58 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index bbc8004edf4..669b081848e 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 b52deac368f..8d87df53bbe 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 c7be15186c4..8c35d37ba60 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 de9a2b63940..d58488598d1 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) -- cgit v1.2.3-70-g09d2 From 9eb599e9c62dcfd4efece1936c385381b366b684 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:12:59 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 5b70cc19e1d..21e74ca4ddb 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 7fccfcc55ca..c06119b053e 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 669b081848e..4abff8274ac 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 dbc40bb49bc..be9e1121c8f 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 8d87df53bbe..5ce01f1379a 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 9cfa0b25a6f..dd2f8b714a7 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 8c35d37ba60..a06aa4e8df7 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 fe29ff524e9..2dbb24e6d54 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 d58488598d1..52d1cd0ddb6 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); -- cgit v1.2.3-70-g09d2 From ba8447f64159927baf673d827e404605471d8f68 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:00 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index be9e1121c8f..cfb2835c118 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 5ce01f1379a..d91e8bcccaa 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; - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; + wl12xx_for_each_wlvif_sta(wl, wlvif) { + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + continue; - wl1271_check_operstate(wl, dev->operstate); + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; - 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 e1a8ce092e3..687f59b871e 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 a06aa4e8df7..bbb101b5de0 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 52d1cd0ddb6..efb35a66fa5 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; -- cgit v1.2.3-70-g09d2 From eee514e3d6cecc7abdf1b27734169004fefb0941 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:01 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index d91e8bcccaa..ac5be732340 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 687f59b871e..765f08ba29a 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 bbb101b5de0..8965fd1384d 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 efb35a66fa5..489c20555df 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 { -- cgit v1.2.3-70-g09d2 From 53d40d0b863e22b697f8d85e1f95cb6f9d2d95b1 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:02 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index ac5be732340..41cc5fe27d8 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 8965fd1384d..a60d8feb69e 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 489c20555df..9b28e478930 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 { -- cgit v1.2.3-70-g09d2 From c29bb001e448ef57e077db9f1c5ae864e3f8abab Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:03 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index cfb2835c118..d8b183bba52 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 41cc5fe27d8..2fe0ee144a9 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 ac3f20716f5..8cd81cec284 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 9b28e478930..ea6b7293175 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 { -- cgit v1.2.3-70-g09d2 From 8181aecce9ea3731ff5554c6f9cf16bf249a61fa Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:04 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 2fe0ee144a9..63340ad8451 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 ea6b7293175..9de57dd71c3 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 { -- cgit v1.2.3-70-g09d2 From 0744bdb60b51dce54553d5af9a6133f1fe419032 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:05 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 63340ad8451..9042445e0d0 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 a60d8feb69e..3cf7166dab6 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 9de57dd71c3..5b5c9309334 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 { -- cgit v1.2.3-70-g09d2 From 10c8cd01e329b2973eddddafe67ae499eef83b19 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:06 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 9042445e0d0..fb5951cb69e 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 5b5c9309334..740a9b19cea 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, -- cgit v1.2.3-70-g09d2 From 836d6600ea0e785fcf8159a3c4b7350276bcd49a Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:07 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index d8b183bba52..1f60a1f6335 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 fb5951cb69e..73973b4fc57 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 740a9b19cea..bf410f8d01c 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 { -- cgit v1.2.3-70-g09d2 From 52630c5d89840bf09826fe89cc15f868e92223ef Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:08 +0200 Subject: 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 | 22 ++++++++++++---------- drivers/net/wireless/wl12xx/main.c | 12 ++++++++---- drivers/net/wireless/wl12xx/wl12xx.h | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index 1f60a1f6335..a47312db5a2 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 73973b4fc57..0647d460b69 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 bf410f8d01c..fc8c9758fc0 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 { -- cgit v1.2.3-70-g09d2 From 1b92f15ee0e0f06222d4fd36dc36960d217243b3 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:09 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index ff653e8832a..6cf8cdc72b5 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 8182cf1b486..968d5bdc0b6 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 a47312db5a2..fd2e7b2d938 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 0647d460b69..8e395f1f4b1 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 8cd81cec284..8153408233b 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 765f08ba29a..2711438fdde 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 3cf7166dab6..604913ff42b 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 fc8c9758fc0..a689ad02a35 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; -- cgit v1.2.3-70-g09d2 From 61f845f4f441a90e5328a78c6c4e0646d99fc2f0 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:10 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 6cf8cdc72b5..4c5c51810fd 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 8e395f1f4b1..5137275d359 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 a689ad02a35..02dedd191bd 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; -- cgit v1.2.3-70-g09d2 From 6bd650299046f00df6d7374c7f61c5afe6df6696 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:11 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 4af7e2fb52f..74f569099b5 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 5137275d359..cffb40be7b5 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 02dedd191bd..2689522ba4e 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; -- cgit v1.2.3-70-g09d2 From 9f259c4e5e42d5f0c25675dc1088cd96dc81a9f1 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:12 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index cffb40be7b5..b2640edcc3a 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); -- cgit v1.2.3-70-g09d2 From 6e8cd3310491b10db20d0f7eaf5713b05fa7b753 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:13 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 4c5c51810fd..65bf9526576 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 4abff8274ac..d6c2d0c1b6c 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 b2640edcc3a..08fc9d46428 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 8153408233b..84a1afac6f5 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 6ad0a0bd29b..a12052f0202 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 604913ff42b..185a65d971f 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) -- cgit v1.2.3-70-g09d2 From f02774343030c2794bb58b6150420dfefc31c39f Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:14 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 08fc9d46428..433a06fae40 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); } -- cgit v1.2.3-70-g09d2 From e5a359f873f50cc123d5ca97637caa30fa095bb9 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:15 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 21e74ca4ddb..e2e46705059 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 c06119b053e..b2d85bea637 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 74f569099b5..ba286d0a74a 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 433a06fae40..cd2722562e6 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 185a65d971f..69ac03f5d54 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 2689522ba4e..d169d52f6d1 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; }; -- cgit v1.2.3-70-g09d2 From f750c82045d8f5d0d6d59e517eb485ffbbe014b2 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:16 +0200 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index cd2722562e6..6e6ac63fb8c 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); -- cgit v1.2.3-70-g09d2 From e4120df982c2051f3cfc02f6278798c5166a72f8 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 10 Oct 2011 10:13:17 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 6e6ac63fb8c..f29d18daaa8 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 69ac03f5d54..5aeef95229e 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 d169d52f6d1..8815fd9a0f4 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) -- cgit v1.2.3-70-g09d2 From c7e7c227b63836933ef736fa2d7cc526174b1563 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 6 Oct 2011 22:59:37 +0300 Subject: 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 (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 3fe388b87c2..af08c8609c6 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 621b3483ca2..fe67262ba19 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 f25d5d9212e..00000000000 --- 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 "); - -- cgit v1.2.3-70-g09d2 From fbe936bcb59d8e6e054c325a441082b55538bf8f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 4 Oct 2011 23:10:28 +0300 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 516a8980723..5a4268012da 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 -- cgit v1.2.3-70-g09d2 From b65019f661733ece3be0680be307d238d4dec68e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 4 Oct 2011 23:36:47 +0300 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 0f971867786..16f0c71f6d4 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; } -- cgit v1.2.3-70-g09d2 From 025aef8fcfbdf680376c4f7aa31b9ac85cebc700 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 5 Oct 2011 09:00:12 +0300 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 5a4268012da..e7ee5d155d3 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); } -- cgit v1.2.3-70-g09d2 From 0969d6793f4899a4c5f56443d50f272068b97142 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 5 Oct 2011 09:29:13 +0300 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 16f0c71f6d4..2dd659886a0 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; -- cgit v1.2.3-70-g09d2 From ce2a217c8268906640ebf7291d7a06210a35dd2f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 5 Oct 2011 14:12:55 +0300 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index f29d18daaa8..3262e8a6c47 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); -- cgit v1.2.3-70-g09d2 From a390e85cfe91c346ff4745bcd45ad0a7e7101aa2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Oct 2011 10:07:44 +0300 Subject: 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 | 174 ++++----------------- drivers/net/wireless/wl12xx/spi.c | 161 +++---------------- drivers/net/wireless/wl12xx/wl12xx.h | 17 +- drivers/net/wireless/wl12xx/wl12xx_platform_data.c | 4 +- include/linux/wl12xx.h | 5 +- 8 files changed, 184 insertions(+), 312 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c index c2da66f4504..1a7df8a7ed2 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 e839341dfaf..e82dad19aa3 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 3262e8a6c47..1cf98778505 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 e7ee5d155d3..78e5352c403 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); -} - -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); -} + struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); + struct sdio_func *func = dev_to_sdio_func(glue->dev); -static void wl1271_sdio_enable_interrupts(struct wl1271 *wl) -{ - enable_irq(wl->irq); + sdio_claim_host(func); + sdio_set_block_size(func, blksz); + sdio_release_host(func); } -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; - } - - 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 (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, wl1271_hardirq, wl1271_irq, - irqflags, - DRIVER_NAME, wl); - if (ret < 0) { - wl1271_error("request_irq() failed: %d", ret); - goto out_free_hw; + goto out_free_glue; } - 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 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) + wlan_data->pwr_in_suspend = true; - 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 2dd659886a0..22c1337ba88 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; - } - - 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; + goto out_free_glue; } - 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 8815fd9a0f4..d2028939eee 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 973b11060a8..3c96b332184 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 4b697395326..0d6373195d3 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 -- cgit v1.2.3-70-g09d2 From 4b32a2c9a636eaab69c797d9ebc7e086a6bd2fb7 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Oct 2011 10:46:20 +0300 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h index e82dad19aa3..d398cbcea98 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 1cf98778505..56927051f66 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) { -- cgit v1.2.3-70-g09d2 From f79f890c9ccd8d10f7e5e2f7c590b0c2e854bfb6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 6 Oct 2011 13:05:25 +0300 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 56927051f66..c72f7497db0 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 d2028939eee..158714a1092 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; -- cgit v1.2.3-70-g09d2 From 0f4e31222a2c0b93f25a87effd2033cb78c7a79c Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 7 Oct 2011 11:02:42 +0300 Subject: 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 (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index e2e46705059..bde1d862bdd 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 d4e628db76b..4ce634b925c 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 65bf9526576..2413c43d089 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 00000000000..b85fd8c41e8 --- /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 d6c2d0c1b6c..a9e0b7383bb 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 fd2e7b2d938..e22df6ce139 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 ba286d0a74a..c6084f8a9c4 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 1a7df8a7ed2..079ad380e8f 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 c72f7497db0..44d52efedc7 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 84a1afac6f5..9f4e8c03cc8 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 dd2f8b714a7..8c277c0cb37 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 2711438fdde..fb2c4319749 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 78e5352c403..55c63adb1d0 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 22c1337ba88..bcc7d7c95a2 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 4ae8effaee2..61fff45686a 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 5aeef95229e..5351f015fee 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 158714a1092..b7036df5939 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" -- cgit v1.2.3-70-g09d2 From 3c4d386868dcbfb9fa51427e314fde39ee70b0ff Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 7 Oct 2011 14:14:25 +0300 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 55c63adb1d0..57e72b4b8d2 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); -- cgit v1.2.3-70-g09d2 From e5d3625e8741d204e8c3f0a959f92c9e901519aa Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 7 Oct 2011 14:33:29 +0300 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index bcc7d7c95a2..976d3d55683 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; } -- cgit v1.2.3-70-g09d2 From 48309fd477ef867babb6819f67fe082c133a5fa9 Mon Sep 17 00:00:00 2001 From: Shahar Lev Date: Fri, 7 Oct 2011 18:17:25 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 5351f015fee..27a45e1459c 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; } -- cgit v1.2.3-70-g09d2 From ccb62000d5e92772b6d5c2acce2f56263886ed89 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 7 Oct 2011 15:54:15 +0300 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 44d52efedc7..a2d16933ccb 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 57e72b4b8d2..ed97f9cee3f 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 976d3d55683..9e6f7fa0f9a 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; -- cgit v1.2.3-70-g09d2 From 0f1680147ce2509383e053fa843020e0e9f3c6ce Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 11 Oct 2011 13:52:25 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index a2d16933ccb..f76be5ad8ab 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 27a45e1459c..c7ad4f5976c 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) { /* -- cgit v1.2.3-70-g09d2 From 679a673414473239d189b5b41ea4014b088be7b9 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 11 Oct 2011 11:55:44 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 2413c43d089..afd597387e7 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 968d5bdc0b6..3f7d0b93c24 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 f76be5ad8ab..44070e66cfe 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 fb2c4319749..898d03d5b52 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 c7ad4f5976c..3a9d2a6b8a0 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: -- cgit v1.2.3-70-g09d2 From d6fa37c9ffa2a613943dd1c32f220a3e6e9eb77c Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 11 Oct 2011 11:57:39 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 44070e66cfe..c05be03907e 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, -- cgit v1.2.3-70-g09d2 From a693534b1a46ee934606cec52b12baeaebba0342 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 24 Oct 2011 17:25:20 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index e22df6ce139..00ce794eeba 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 c6084f8a9c4..14ff01efc0b 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 9f4e8c03cc8..a7a11088dd3 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; -- cgit v1.2.3-70-g09d2 From fa5e13756ad5112842bd5e765d66b6c6074b74b7 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 31 Oct 2011 12:24:49 +0200 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index a9e0b7383bb..2e14b436101 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); -- cgit v1.2.3-70-g09d2 From 2f8e81ad42cee6e1503462105f540214b1fb3e54 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 1 Nov 2011 15:12:50 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index c05be03907e..51d519f93d7 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; -- cgit v1.2.3-70-g09d2 From ce39defb5c6312a89a0c7be48797d6fb8fe9abad Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 3 Nov 2011 08:44:41 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 14ff01efc0b..c413abd26d1 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 51d519f93d7..b9a3fe49727 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 3a9d2a6b8a0..a07ee8201d6 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 b7036df5939..e58e801f7ae 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) -- cgit v1.2.3-70-g09d2 From e62c9ce4a4c0e0ffd5718e962ba4606cd5d0d600 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 3 Nov 2011 08:44:42 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index b9a3fe49727..aa1c0f3ebee 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: -- cgit v1.2.3-70-g09d2 From 3f3fd78e33213b1684ac1e4deacbcf7ed1828e3c Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 3 Nov 2011 08:44:43 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h index 3f570f39758..df34d5977b9 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 -- cgit v1.2.3-70-g09d2 From bfafba8a4c61841ab850887d6dfe2741ad037ab6 Mon Sep 17 00:00:00 2001 From: Guy Eilam Date: Tue, 1 Nov 2011 09:23:51 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index 04bb8fbf93f..1bcfb017058 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 898d03d5b52..a13c49e27a3 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) -- cgit v1.2.3-70-g09d2 From 8a0f2ee37810aa4a4f46baf08b2ad587e138eb58 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 1 Nov 2011 09:23:52 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index a07ee8201d6..fa518a5b7c8 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; -- cgit v1.2.3-70-g09d2 From c31e494689128203ef04fb946f05a72d33eee948 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 23 Oct 2011 08:21:55 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index aa1c0f3ebee..dbb088eadf7 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) -- cgit v1.2.3-70-g09d2 From b693289406f0b8ca70ab77e745be6196d5740eb0 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Tue, 8 Nov 2011 15:56:55 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index ed97f9cee3f..468a50553fa 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) { -- cgit v1.2.3-70-g09d2 From 36acbb1adadf1ba300f14ee904a7d3f23120e0d6 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Mon, 14 Nov 2011 12:42:48 +0200 Subject: Bluetooth: Allow to set AMP type for virtual HCI Type can be changed during re-opening device /dev/vhci. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/hci_vhci.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 2e302a11ab5..2ed6ab1c6e1 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -41,6 +41,8 @@ #define VERSION "1.3" +static bool amp; + struct vhci_data { struct hci_dev *hdev; @@ -239,6 +241,9 @@ static int vhci_open(struct inode *inode, struct file *file) hdev->bus = HCI_VIRTUAL; hdev->driver_data = data; + if (amp) + hdev->dev_type = HCI_AMP; + hdev->open = vhci_open_dev; hdev->close = vhci_close_dev; hdev->flush = vhci_flush; @@ -303,6 +308,9 @@ static void __exit vhci_exit(void) module_init(vhci_init); module_exit(vhci_exit); +module_param(amp, bool, 0644); +MODULE_PARM_DESC(amp, "Create AMP controller device"); + MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); MODULE_VERSION(VERSION); -- cgit v1.2.3-70-g09d2 From 2ac654f740b574c58ee02bac3816cf466a1bfb41 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Wed, 16 Nov 2011 20:40:42 -0800 Subject: Bluetooth: btmrvl: support Marvell Bluetooth device SD8797 The SD8797 firmware image is shared with mwifiex driver. Whoever gets loaded first will be responsible for firmware downloading. Signed-off-by: Bing Zhao Signed-off-by: Frank Huang Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/Kconfig | 6 +++--- drivers/bluetooth/btmrvl_sdio.c | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 11b41fd40c2..5ccf142ef0b 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -188,7 +188,7 @@ config BT_MRVL The core driver to support Marvell Bluetooth devices. This driver is required if you want to support - Marvell Bluetooth devices, such as 8688/8787. + Marvell Bluetooth devices, such as 8688/8787/8797. Say Y here to compile Marvell Bluetooth driver into the kernel or say M to compile it as module. @@ -201,8 +201,8 @@ config BT_MRVL_SDIO The driver for Marvell Bluetooth chipsets with SDIO interface. This driver is required if you want to use Marvell Bluetooth - devices with SDIO interface. Currently SD8688/SD8787 chipsets are - supported. + devices with SDIO interface. Currently SD8688/SD8787/SD8797 + chipsets are supported. Say Y here to compile support for Marvell BT-over-SDIO driver into the kernel or say M to compile it as module. diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index c827d737cce..37b56398c8a 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -64,7 +64,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = { .io_port_1 = 0x01, .io_port_2 = 0x02, }; -static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = { +static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = { .cfg = 0x00, .host_int_mask = 0x02, .host_intstatus = 0x03, @@ -91,7 +91,14 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { .helper = NULL, .firmware = "mrvl/sd8787_uapsta.bin", - .reg = &btmrvl_reg_8787, + .reg = &btmrvl_reg_87xx, + .sd_blksz_fw_dl = 256, +}; + +static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { + .helper = NULL, + .firmware = "mrvl/sd8797_uapsta.bin", + .reg = &btmrvl_reg_87xx, .sd_blksz_fw_dl = 256, }; @@ -102,6 +109,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { /* Marvell SD8787 Bluetooth device */ { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), .driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, + /* Marvell SD8797 Bluetooth device */ + { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), + .driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, { } /* Terminating entry */ }; @@ -1075,3 +1085,4 @@ MODULE_LICENSE("GPL v2"); MODULE_FIRMWARE("sd8688_helper.bin"); MODULE_FIRMWARE("sd8688.bin"); MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); +MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); -- cgit v1.2.3-70-g09d2 From 2131d3c2f99b081806fdae7662c92fe6acda52af Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Tue, 18 Oct 2011 09:23:41 +0200 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index afd597387e7..e0d21797948 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); -- cgit v1.2.3-70-g09d2 From f6efe96edd9c41c624c8f4ddbc4930c1a2d8f1e1 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Tue, 18 Oct 2011 09:23:42 +0200 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 6e140bf4e23..8f9cf5a816e 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) -- cgit v1.2.3-70-g09d2 From 560f00241b6d95bde73a570c29d6919b36fdf852 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 8 Nov 2011 18:46:54 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index dbb088eadf7..3750a6e479f 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 e58e801f7ae..f1c911774bf 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 { -- cgit v1.2.3-70-g09d2 From 9c1b190b10972be9c0d53c658e537c54de530b7f Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 8 Nov 2011 18:46:55 +0200 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 3750a6e479f..08b06ee6d51 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); -- cgit v1.2.3-70-g09d2 From 97127e67218e5970a5a7df0513ded730b19a67e9 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 9 Nov 2011 13:12:45 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index c413abd26d1..88891cdfdd4 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 f7971d3b089..8f0ffaf6230 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; -- cgit v1.2.3-70-g09d2 From 341f2c11b5ce7689d3f0acb04574fe6424aa6be0 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 22 Nov 2011 19:52:59 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 08b06ee6d51..8c58001c76d 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)) { -- cgit v1.2.3-70-g09d2 From 358989352e70975d1c50ac2a49fc86d41d0518bd Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Wed, 30 Nov 2011 15:35:09 +0100 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8c58001c76d..8ff1bf5be01 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; } -- cgit v1.2.3-70-g09d2 From 12d4b9759143aaa280195834820bc15d795e71c1 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 23 Oct 2011 08:21:54 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8ff1bf5be01..d1416752fee 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; -- cgit v1.2.3-70-g09d2 From e0d62536d032db689adf9c8162a9d2caf4714f44 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 8 Nov 2011 16:07:52 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index fa518a5b7c8..36eb0d66fd6 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; } -- cgit v1.2.3-70-g09d2 From 54a8a79c55ce283c94ce4c67a98d28c21830405a Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 22 Nov 2011 09:32:57 +0800 Subject: btusb: fix a memory leak in btusb_send_frame() This patch fixes the following memory leak reported by kmemleak: unreferenced object 0xffff880060a53840 (size 192): comm "softirq", pid 0, jiffies 4320571771 (age 1406.569s) hex dump (first 32 bytes): 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [] create_object+0x187/0x28b [] kmemleak_alloc+0x73/0x98 [] __kmalloc+0xfc/0x123 [] usb_alloc_urb+0x1e/0x48 [] btusb_send_frame+0x86/0x385 [btusb] [] hci_send_frame+0xa0/0xa5 [bluetooth] [] hci_cmd_task+0xa0/0xfb [bluetooth] [] tasklet_action+0x8f/0xef [] __do_softirq+0xf4/0x1db [] run_ksoftirqd+0x84/0x129 [] kthread+0xa0/0xa8 [] kernel_thread_helper+0x4/0x10 [] 0xffffffffffffffff The problem is that when inc_tx() returns non-zero, we forgot to call usb_free_urb(). Cc: Marcel Holtmann Cc: "Gustavo F. Padovan" Signed-off-by: WANG Cong Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btusb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index fe4ebc375b3..eabc437ce50 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -777,9 +777,8 @@ skip_waking: usb_mark_last_busy(data->udev); } - usb_free_urb(urb); - done: + usb_free_urb(urb); return err; } -- cgit v1.2.3-70-g09d2 From 839fafbe0dc35fabeb9bd3be9727fd74d12c0b9d Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Tue, 29 Nov 2011 22:08:00 +0100 Subject: rt2x00: Use kcalloc instead of kzalloc to allocate array The advantage of kcalloc is, that will prevent integer overflows which could result from the multiplication of number of elements and size and it is also a bit nicer to read. The semantic patch that makes this change is available in https://lkml.org/lkml/2011/11/25/107 Signed-off-by: Thomas Meyer Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index edd317fa7c0..c3e1aa7c1a8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -831,11 +831,11 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, if (spec->supported_rates & SUPPORT_RATE_OFDM) num_rates += 8; - channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL); + channels = kcalloc(spec->num_channels, sizeof(*channels), GFP_KERNEL); if (!channels) return -ENOMEM; - rates = kzalloc(sizeof(*rates) * num_rates, GFP_KERNEL); + rates = kcalloc(num_rates, sizeof(*rates), GFP_KERNEL); if (!rates) goto exit_free_channels; -- cgit v1.2.3-70-g09d2 From 2b50b8f58803f4c8521c6aa5401ed01cd36a1f77 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Tue, 29 Nov 2011 22:08:00 +0100 Subject: iwlegacy: Use kcalloc instead of kzalloc to allocate array The advantage of kcalloc is, that will prevent integer overflows which could result from the multiplication of number of elements and size and it is also a bit nicer to read. The semantic patch that makes this change is available in https://lkml.org/lkml/2011/11/25/107 Signed-off-by: Thomas Meyer Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/common.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 7e2924f332a..881ba043770 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -2786,9 +2786,8 @@ il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id) /* Driver ilate data, only for Tx (not command) queues, * not shared with device. */ if (id != il->cmd_queue) { - txq->txb = - kzalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX, - GFP_KERNEL); + txq->txb = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->txb[0]), + GFP_KERNEL); if (!txq->txb) { IL_ERR("kmalloc for auxiliary BD " "structures failed\n"); -- cgit v1.2.3-70-g09d2 From 8ff08b4318b06eb3661bea0067ae587afc01e649 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 30 Nov 2011 10:58:14 -0600 Subject: rtl8192c: Do not log firmware load message unless actually done A previous commit fixed a problem whereby the rtl8192c driver loaded the firmware from disk many times; however, the log message was not moved. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index fa393dfe136..931d97979b0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -262,10 +262,10 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) u32 fwsize; enum version_8192c version = rtlhal->version; - pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); if (!rtlhal->pfirmware) return 1; + pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; pfwdata = (u8 *) rtlhal->pfirmware; fwsize = rtlhal->fwsize; -- cgit v1.2.3-70-g09d2 From b9b6968b0d9d0fe3891c5f87aa6e53b7ee67cf7f Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Thu, 1 Dec 2011 11:14:19 +0530 Subject: ath9k_hw: sync to latest AR9462 INI based on systems change to improve rx dynamic range, and enables heavy clip for 5G HT40 MCS0 to improve spectral mask power. also remove an unused function declaration Cc: Wilson Tsao Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9462_2p0_initvals.h | 42 +++++++++++----------- drivers/net/wireless/ath/ath9k/hw.h | 1 - 2 files changed, 21 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 259a6f312af..dc2054f0378 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -41,24 +41,24 @@ static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = { static const u32 ar9462_2p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, - {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, - {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x5ac640de}, - {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x0796be89}, + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, + {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, + {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, + {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81}, {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, - {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, - {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x92c84d2e}, - {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, + {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, + {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x33795d5e}, {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c782}, - {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, + {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0}, @@ -81,6 +81,15 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a3a4, 0x00000010, 0x00000010, 0x00000000, 0x00000000}, + {0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}, + {0x0000a3ac, 0xaaaaaa00, 0xaaaaaa30, 0xaaaaaa00, 0xaaaaaa00}, + {0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, + {0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, + {0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, + {0x0000a428, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, + {0x0000a42c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, + {0x0000a430, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000}, {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -1107,11 +1116,11 @@ static const u32 ar9462_2p0_baseband_core[][2] = { {0x00009e30, 0x06336f77}, {0x00009e34, 0x6af6532f}, {0x00009e38, 0x0cc80c00}, - {0x00009e40, 0x0d261820}, + {0x00009e40, 0x15262820}, {0x00009e4c, 0x00001004}, {0x00009e50, 0x00ff03f1}, - {0x00009e54, 0xe4c355c7}, - {0x00009e58, 0xfd897735}, + {0x00009e54, 0xe4c555c2}, + {0x00009e58, 0xfd857722}, {0x00009e5c, 0xe9198724}, {0x00009fc0, 0x803e4788}, {0x00009fc4, 0x0001efb5}, @@ -1142,9 +1151,6 @@ static const u32 ar9462_2p0_baseband_core[][2] = { {0x0000a398, 0x001f0e0f}, {0x0000a39c, 0x0075393f}, {0x0000a3a0, 0xb79f6427}, - {0x0000a3a4, 0x00000000}, - {0x0000a3a8, 0xaaaaaaaa}, - {0x0000a3ac, 0x3c466478}, {0x0000a3c0, 0x20202020}, {0x0000a3c4, 0x22222220}, {0x0000a3c8, 0x20200020}, @@ -1167,12 +1173,6 @@ static const u32 ar9462_2p0_baseband_core[][2] = { {0x0000a40c, 0x00820820}, {0x0000a414, 0x1ce739ce}, {0x0000a418, 0x2d001dce}, - {0x0000a41c, 0x1ce739ce}, - {0x0000a420, 0x000001ce}, - {0x0000a424, 0x1ce739ce}, - {0x0000a428, 0x000001ce}, - {0x0000a42c, 0x1ce739ce}, - {0x0000a430, 0x1ce739ce}, {0x0000a434, 0x00000000}, {0x0000a438, 0x00001801}, {0x0000a43c, 0x00100000}, diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index c9c3b188996..36968c04611 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -1110,7 +1110,6 @@ bool ath9k_hw_disable(struct ath_hw *ah); void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test); void ath9k_hw_setopmode(struct ath_hw *ah); void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); -void ath9k_hw_setbssidmask(struct ath_hw *ah); void ath9k_hw_write_associd(struct ath_hw *ah); u32 ath9k_hw_gettsf32(struct ath_hw *ah); u64 ath9k_hw_gettsf64(struct ath_hw *ah); -- cgit v1.2.3-70-g09d2 From e7104195a9b43f05d908ced9ce5db137e1f3616b Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Thu, 1 Dec 2011 18:14:01 +0530 Subject: ath9k: clarify max_streams for AR9462 max_streams for AR9462 is '2'. it does not fixes anything, but improves the code readability Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index e9711e2b48c..41b72faca77 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -258,6 +258,8 @@ static void setup_ht_cap(struct ath_softc *sc, if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) max_streams = 1; + else if (AR_SREV_9462(ah)) + max_streams = 2; else if (AR_SREV_9300_20_OR_LATER(ah)) max_streams = 3; else -- cgit v1.2.3-70-g09d2 From 158969a26553cba63b7ac674159413d32bb57489 Mon Sep 17 00:00:00 2001 From: "Hsu, Kenny" Date: Fri, 2 Dec 2011 08:48:26 -0800 Subject: iwlwifi: add tm commands for sram reading by dumpit Create new testmode commands and attributes to suppot sram data reading. Because the amount of sram data may exceed single skb packet size. Using the nl80211 dump it funtion to deliver sram data to userspace. - IWL_TM_CMD_APP2DEV_READ_SRAM - IWL_TM_CMD_APP2DEV_DUMP_SRAM - IWL_TM_ATTR_SRAM_ADDR - IWL_TM_ATTR_SRAM_SIZE - IWL_TM_ATTR_SRAM_DUMP Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 7 ++ drivers/net/wireless/iwlwifi/iwl-sv-open.c | 109 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-testmode.h | 27 ++++++- 3 files changed, 141 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 0c95ad3048a..cb24adbae08 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -790,6 +790,12 @@ struct iwl_testmode_trace { dma_addr_t dma_addr; bool trace_enabled; }; +struct iwl_testmode_sram { + u32 buff_size; + u32 num_chunks; + u8 *buff_addr; + bool sram_readed; +}; #endif struct iwl_wipan_noa_data { @@ -1070,6 +1076,7 @@ struct iwl_priv { bool led_registered; #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL struct iwl_testmode_trace testmode_trace; + struct iwl_testmode_sram testmode_sram; u32 tm_fixed_rate; #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index be16cafbbc2..593f42d9fb0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -106,6 +106,10 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, }, + + [IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, }, + [IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, }, + [IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, }, }; /* @@ -177,6 +181,18 @@ void iwl_testmode_init(struct iwl_priv *priv) { priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; priv->testmode_trace.trace_enabled = false; + priv->testmode_sram.sram_readed = false; +} + +void iwl_sram_cleanup(struct iwl_priv *priv) +{ + if (priv->testmode_sram.sram_readed) { + kfree(priv->testmode_sram.buff_addr); + priv->testmode_sram.buff_addr = NULL; + priv->testmode_sram.buff_size = 0; + priv->testmode_sram.num_chunks = 0; + priv->testmode_sram.sram_readed = false; + } } static void iwl_trace_cleanup(struct iwl_priv *priv) @@ -201,6 +217,7 @@ static void iwl_trace_cleanup(struct iwl_priv *priv) void iwl_testmode_cleanup(struct iwl_priv *priv) { iwl_trace_cleanup(priv); + iwl_sram_cleanup(priv); } /* @@ -644,6 +661,89 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) return 0; } +/* + * This function handles the user application commands for SRAM data dump + * + * It retrieves the mandatory fields IWL_TM_ATTR_SRAM_ADDR and + * IWL_TM_ATTR_SRAM_SIZE to decide the memory area for SRAM data reading + * + * Several error will be retured, -EBUSY if the SRAM data retrieved by + * previous command has not been delivered to userspace, or -ENOMSG if + * the mandatory fields (IWL_TM_ATTR_SRAM_ADDR,IWL_TM_ATTR_SRAM_SIZE) + * are missing, or -ENOMEM if the buffer allocation fails. + * + * Otherwise 0 is replied indicating the success of the SRAM reading. + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + u32 base, ofs, size; + + if (priv->testmode_sram.sram_readed) + return -EBUSY; + + if (!tb[IWL_TM_ATTR_SRAM_ADDR]) { + IWL_DEBUG_INFO(priv, "Error finding SRAM offset address\n"); + return -ENOMSG; + } + ofs = nla_get_u32(tb[IWL_TM_ATTR_SRAM_ADDR]); + if (!tb[IWL_TM_ATTR_SRAM_SIZE]) { + IWL_DEBUG_INFO(priv, "Error finding size for SRAM reading\n"); + return -ENOMSG; + } + size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]); + priv->testmode_sram.buff_size = (size / 4) * 4; + priv->testmode_sram.buff_addr = + kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL); + if (priv->testmode_sram.buff_addr == NULL) { + IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + return -ENOMEM; + } + base = 0x800000; + _iwl_read_targ_mem_words(bus(priv), base + ofs, + priv->testmode_sram.buff_addr, + priv->testmode_sram.buff_size / 4); + priv->testmode_sram.num_chunks = + DIV_ROUND_UP(priv->testmode_sram.buff_size, TRACE_CHUNK_SIZE); + priv->testmode_sram.sram_readed = true; + return 0; +} + +static int iwl_testmode_sram_dump(struct ieee80211_hw *hw, struct nlattr **tb, + struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct iwl_priv *priv = hw->priv; + int idx, length; + + if (priv->testmode_sram.sram_readed) { + idx = cb->args[4]; + if (idx >= priv->testmode_sram.num_chunks) { + iwl_sram_cleanup(priv); + return -ENOENT; + } + length = TRACE_CHUNK_SIZE; + if (((idx + 1) == priv->testmode_sram.num_chunks) && + (priv->testmode_sram.buff_size % TRACE_CHUNK_SIZE)) + length = priv->testmode_sram.buff_size % + TRACE_CHUNK_SIZE; + + NLA_PUT(skb, IWL_TM_ATTR_SRAM_DUMP, length, + priv->testmode_sram.buff_addr + + (TRACE_CHUNK_SIZE * idx)); + idx++; + cb->args[4] = idx; + return 0; + } else + return -EFAULT; + + nla_put_failure: + return -ENOBUFS; +} + /* The testmode gnl message handler that takes the gnl message from the * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then @@ -721,6 +821,11 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) result = iwl_testmode_ownership(hw, tb); break; + case IWL_TM_CMD_APP2DEV_READ_SRAM: + IWL_DEBUG_INFO(priv, "testmode sram read cmd to driver\n"); + result = iwl_testmode_sram(hw, tb); + break; + default: IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); result = -ENOSYS; @@ -769,6 +874,10 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); result = iwl_testmode_trace_dump(hw, tb, skb, cb); break; + case IWL_TM_CMD_APP2DEV_DUMP_SRAM: + IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n"); + result = iwl_testmode_sram_dump(hw, tb, skb, cb); + break; default: result = -EINVAL; break; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 177964850b7..95c87058677 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -103,14 +103,20 @@ * @IWL_TM_CMD_DEV2APP_EEPROM_RSP: * commands from kernel space to carry the eeprom response * to user application + * * @IWL_TM_CMD_APP2DEV_OWNERSHIP: * commands from user application to own change the ownership of the uCode * if application has the ownership, the only host command from * testmode will deliver to uCode. Default owner is driver + * * @IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: * @IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32: * commands from user applicaiton to indirectly access peripheral register * + * @IWL_TM_CMD_APP2DEV_READ_SRAM: + * @IWL_TM_CMD_APP2DEV_DUMP_SRAM: + * commands from user applicaiton to read data in sram + * */ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_UCODE = 1, @@ -132,7 +138,9 @@ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_OWNERSHIP = 17, IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32 = 18, IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32 = 19, - IWL_TM_CMD_MAX = 20, + IWL_TM_CMD_APP2DEV_READ_SRAM = 20, + IWL_TM_CMD_APP2DEV_DUMP_SRAM = 21, + IWL_TM_CMD_MAX = 22, }; /* @@ -202,6 +210,18 @@ enum iwl_tm_cmd_t { * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_OWNERSHIP, * The mandatory fields are: * IWL_TM_ATTR_UCODE_OWNER for the new owner + * + * @IWL_TM_ATTR_SRAM_ADDR: + * @IWL_TM_ATTR_SRAM_SIZE: + * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_READ_SRAM, + * The mandatory fields are: + * IWL_TM_ATTR_SRAM_ADDR for the address in sram + * IWL_TM_ATTR_SRAM_SIZE for the buffer size of data reading + * + * @IWL_TM_ATTR_SRAM_DUMP: + * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_DUMP_SRAM, + * IWL_TM_ATTR_SRAM_DUMP for the data in sram + * */ enum iwl_tm_attr_t { IWL_TM_ATTR_NOT_APPLICABLE = 0, @@ -219,7 +239,10 @@ enum iwl_tm_attr_t { IWL_TM_ATTR_TRACE_DUMP = 12, IWL_TM_ATTR_FIXRATE = 13, IWL_TM_ATTR_UCODE_OWNER = 14, - IWL_TM_ATTR_MAX = 15, + IWL_TM_ATTR_SRAM_ADDR = 15, + IWL_TM_ATTR_SRAM_SIZE = 16, + IWL_TM_ATTR_SRAM_DUMP = 17, + IWL_TM_ATTR_MAX = 18, }; /* uCode trace buffer */ -- cgit v1.2.3-70-g09d2 From 835df183011db2342b42d06e17c708854ab6defb Mon Sep 17 00:00:00 2001 From: Kenny Hsu Date: Fri, 2 Dec 2011 08:48:27 -0800 Subject: iwlwifi: add range checking in tm sram read command The size of sram may alter according to ucode type. Retrieve the maximum sram size by current ucode type for range checking to prevent wrong data access. Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 593f42d9fb0..a8d0ef649a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -680,7 +680,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) { struct iwl_priv *priv = hw->priv; - u32 base, ofs, size; + u32 base, ofs, size, maxsize; if (priv->testmode_sram.sram_readed) return -EBUSY; @@ -695,6 +695,27 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) return -ENOMSG; } size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]); + switch (priv->ucode_type) { + case IWL_UCODE_REGULAR: + maxsize = trans(priv)->ucode_rt.data.len; + break; + case IWL_UCODE_INIT: + maxsize = trans(priv)->ucode_init.data.len; + break; + case IWL_UCODE_WOWLAN: + maxsize = trans(priv)->ucode_wowlan.data.len; + break; + case IWL_UCODE_NONE: + IWL_DEBUG_INFO(priv, "Error, uCode does not been loaded\n"); + return -ENOSYS; + default: + IWL_DEBUG_INFO(priv, "Error, unsupported uCode type\n"); + return -ENOSYS; + } + if ((ofs + size) > maxsize) { + IWL_DEBUG_INFO(priv, "Invalid offset/size: out of range\n"); + return -EINVAL; + } priv->testmode_sram.buff_size = (size / 4) * 4; priv->testmode_sram.buff_addr = kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL); -- cgit v1.2.3-70-g09d2 From a2f759fc41579205ad86ef17efe57e730a1af9e6 Mon Sep 17 00:00:00 2001 From: "Hsu, Kenny" Date: Fri, 2 Dec 2011 08:48:28 -0800 Subject: iwlwifi: add generic chunk size of tm dumpit packet Use generic chunk size of dumpit packet for all necessary testmode commands instead of add declaration individually. Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 20 ++++++++++---------- drivers/net/wireless/iwlwifi/iwl-testmode.h | 4 +++- 2 files changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index a8d0ef649a7..4ea64d65b35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -575,7 +575,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) } priv->testmode_trace.num_chunks = DIV_ROUND_UP(priv->testmode_trace.buff_size, - TRACE_CHUNK_SIZE); + DUMP_CHUNK_SIZE); break; case IWL_TM_CMD_APP2DEV_END_TRACE: @@ -607,15 +607,15 @@ static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb, idx = cb->args[4]; if (idx >= priv->testmode_trace.num_chunks) return -ENOENT; - length = TRACE_CHUNK_SIZE; + length = DUMP_CHUNK_SIZE; if (((idx + 1) == priv->testmode_trace.num_chunks) && - (priv->testmode_trace.buff_size % TRACE_CHUNK_SIZE)) + (priv->testmode_trace.buff_size % DUMP_CHUNK_SIZE)) length = priv->testmode_trace.buff_size % - TRACE_CHUNK_SIZE; + DUMP_CHUNK_SIZE; NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length, priv->testmode_trace.trace_addr + - (TRACE_CHUNK_SIZE * idx)); + (DUMP_CHUNK_SIZE * idx)); idx++; cb->args[4] = idx; return 0; @@ -728,7 +728,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) priv->testmode_sram.buff_addr, priv->testmode_sram.buff_size / 4); priv->testmode_sram.num_chunks = - DIV_ROUND_UP(priv->testmode_sram.buff_size, TRACE_CHUNK_SIZE); + DIV_ROUND_UP(priv->testmode_sram.buff_size, DUMP_CHUNK_SIZE); priv->testmode_sram.sram_readed = true; return 0; } @@ -746,15 +746,15 @@ static int iwl_testmode_sram_dump(struct ieee80211_hw *hw, struct nlattr **tb, iwl_sram_cleanup(priv); return -ENOENT; } - length = TRACE_CHUNK_SIZE; + length = DUMP_CHUNK_SIZE; if (((idx + 1) == priv->testmode_sram.num_chunks) && - (priv->testmode_sram.buff_size % TRACE_CHUNK_SIZE)) + (priv->testmode_sram.buff_size % DUMP_CHUNK_SIZE)) length = priv->testmode_sram.buff_size % - TRACE_CHUNK_SIZE; + DUMP_CHUNK_SIZE; NLA_PUT(skb, IWL_TM_ATTR_SRAM_DUMP, length, priv->testmode_sram.buff_addr + - (TRACE_CHUNK_SIZE * idx)); + (DUMP_CHUNK_SIZE * idx)); idx++; cb->args[4] = idx; return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 95c87058677..e20f3d39027 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -250,6 +250,8 @@ enum iwl_tm_attr_t { #define TRACE_BUFF_SIZE_MIN 0x20000 #define TRACE_BUFF_SIZE_DEF TRACE_BUFF_SIZE_MIN #define TRACE_BUFF_PADD 0x2000 -#define TRACE_CHUNK_SIZE (PAGE_SIZE - 1024) + +/* Maximum data size of each dump it packet */ +#define DUMP_CHUNK_SIZE (PAGE_SIZE - 1024) #endif -- cgit v1.2.3-70-g09d2 From f05f2efd84de22d3fa6e49145b601077f8ba8d2f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 2 Dec 2011 08:48:29 -0800 Subject: iwlwifi: declare static for iwl_sram_cleanup function Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 4ea64d65b35..21b2fbb4dc3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -184,7 +184,7 @@ void iwl_testmode_init(struct iwl_priv *priv) priv->testmode_sram.sram_readed = false; } -void iwl_sram_cleanup(struct iwl_priv *priv) +static void iwl_sram_cleanup(struct iwl_priv *priv) { if (priv->testmode_sram.sram_readed) { kfree(priv->testmode_sram.buff_addr); -- cgit v1.2.3-70-g09d2 From d6846347a0e1bc111b67a1366380419231b97984 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 2 Dec 2011 08:48:31 -0800 Subject: iwlagn: remove TX_REPLY_LIMIT debug This macro is unused right now. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debug.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 44a7bdd7ccf..a842d711fc1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -206,8 +206,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_STATS_LIMIT(p, f, a...) \ IWL_DEBUG_LIMIT(p, IWL_DL_STATS, f, ## a) #define IWL_DEBUG_TX_REPLY(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a) -#define IWL_DEBUG_TX_REPLY_LIMIT(p, f, a...) \ - IWL_DEBUG_LIMIT(p, IWL_DL_TX_REPLY, f, ## a) #define IWL_DEBUG_TX_QUEUES(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_QUEUES, f, ## a) #define IWL_DEBUG_RADIO(p, f, a...) IWL_DEBUG(p, IWL_DL_RADIO, f, ## a) #define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a) -- cgit v1.2.3-70-g09d2 From 145274408049d21274e3c645066aa7980165c71e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 2 Dec 2011 08:48:32 -0800 Subject: iwlagn: remove HC_DUMP debug This debug level is unused, remove it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debug.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index a842d711fc1..32206088c64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -140,7 +140,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DL_STATE (1 << 3) /* 0x000000F0 - 0x00000010 */ #define IWL_DL_MACDUMP (1 << 4) -#define IWL_DL_HCMD_DUMP (1 << 5) +/* unused (1 << 5) */ #define IWL_DL_EEPROM (1 << 6) #define IWL_DL_RADIO (1 << 7) /* 0x00000F00 - 0x00000100 */ @@ -184,7 +184,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) #define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) #define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) -#define IWL_DEBUG_HC_DUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD_DUMP, f, ## a) #define IWL_DEBUG_EEPROM(p, f, a...) IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a) #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) -- cgit v1.2.3-70-g09d2 From d28a21d8aaccadf930085cf581abc9b5e048026d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 2 Dec 2011 08:48:33 -0800 Subject: iwlagn: remove MACDUMP debug This is only used for TX debugging where there already is more debugging and tracing is more useful anyway, so remove it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debug.h | 3 +-- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 32206088c64..95740c131a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -139,7 +139,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DL_HCMD (1 << 2) #define IWL_DL_STATE (1 << 3) /* 0x000000F0 - 0x00000010 */ -#define IWL_DL_MACDUMP (1 << 4) +/* unused (1 << 4) */ /* unused (1 << 5) */ #define IWL_DL_EEPROM (1 << 6) #define IWL_DL_RADIO (1 << 7) @@ -175,7 +175,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a) #define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a) -#define IWL_DEBUG_MACDUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_MACDUMP, f, ## a) #define IWL_DEBUG_TEMP(p, f, a...) IWL_DEBUG(p, IWL_DL_TEMP, f, ## a) #define IWL_DEBUG_SCAN(p, f, a...) IWL_DEBUG(p, IWL_DL_SCAN, f, ## a) #define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a) diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 05b1f0d2f38..794b735264e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -481,15 +481,11 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MACDUMP(priv, "enter\n"); - IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); if (iwlagn_tx_skb(priv, skb)) dev_kfree_skb_any(skb); - - IWL_DEBUG_MACDUMP(priv, "leave\n"); } static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, -- cgit v1.2.3-70-g09d2 From 112f11dc219ec8f9b0cf5cf9f55fef1096006908 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 2 Dec 2011 08:48:34 -0800 Subject: iwlagn: make debug levels more readable Using the actual shifted constants here allows one to read and or them more easily. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debug.h | 58 +++++++++++++++----------------- 1 file changed, 27 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 95740c131a1..f8fc2393dd4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -134,44 +134,40 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) */ /* 0x0000000F - 0x00000001 */ -#define IWL_DL_INFO (1 << 0) -#define IWL_DL_MAC80211 (1 << 1) -#define IWL_DL_HCMD (1 << 2) -#define IWL_DL_STATE (1 << 3) +#define IWL_DL_INFO 0x00000001 +#define IWL_DL_MAC80211 0x00000002 +#define IWL_DL_HCMD 0x00000004 +#define IWL_DL_STATE 0x00000008 /* 0x000000F0 - 0x00000010 */ -/* unused (1 << 4) */ -/* unused (1 << 5) */ -#define IWL_DL_EEPROM (1 << 6) -#define IWL_DL_RADIO (1 << 7) +#define IWL_DL_EEPROM 0x00000040 +#define IWL_DL_RADIO 0x00000080 /* 0x00000F00 - 0x00000100 */ -#define IWL_DL_POWER (1 << 8) -#define IWL_DL_TEMP (1 << 9) -/* reserved (1 << 10) */ -#define IWL_DL_SCAN (1 << 11) +#define IWL_DL_POWER 0x00000100 +#define IWL_DL_TEMP 0x00000200 +#define IWL_DL_SCAN 0x00000800 /* 0x0000F000 - 0x00001000 */ -#define IWL_DL_ASSOC (1 << 12) -#define IWL_DL_DROP (1 << 13) -/* reserved (1 << 14) */ -#define IWL_DL_COEX (1 << 15) +#define IWL_DL_ASSOC 0x00001000 +#define IWL_DL_DROP 0x00002000 +#define IWL_DL_COEX 0x00008000 /* 0x000F0000 - 0x00010000 */ -#define IWL_DL_FW (1 << 16) -#define IWL_DL_RF_KILL (1 << 17) -#define IWL_DL_FW_ERRORS (1 << 18) -#define IWL_DL_LED (1 << 19) +#define IWL_DL_FW 0x00010000 +#define IWL_DL_RF_KILL 0x00020000 +#define IWL_DL_FW_ERRORS 0x00040000 +#define IWL_DL_LED 0x00080000 /* 0x00F00000 - 0x00100000 */ -#define IWL_DL_RATE (1 << 20) -#define IWL_DL_CALIB (1 << 21) -#define IWL_DL_WEP (1 << 22) -#define IWL_DL_TX (1 << 23) +#define IWL_DL_RATE 0x00100000 +#define IWL_DL_CALIB 0x00200000 +#define IWL_DL_WEP 0x00400000 +#define IWL_DL_TX 0x00800000 /* 0x0F000000 - 0x01000000 */ -#define IWL_DL_RX (1 << 24) -#define IWL_DL_ISR (1 << 25) -#define IWL_DL_HT (1 << 26) +#define IWL_DL_RX 0x01000000 +#define IWL_DL_ISR 0x02000000 +#define IWL_DL_HT 0x04000000 /* 0xF0000000 - 0x10000000 */ -#define IWL_DL_11H (1 << 28) -#define IWL_DL_STATS (1 << 29) -#define IWL_DL_TX_REPLY (1 << 30) -#define IWL_DL_TX_QUEUES (1 << 31) +#define IWL_DL_11H 0x10000000 +#define IWL_DL_STATS 0x20000000 +#define IWL_DL_TX_REPLY 0x40000000 +#define IWL_DL_TX_QUEUES 0x80000000 #define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a) #define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a) -- cgit v1.2.3-70-g09d2 From ca4c18231935bafeb2a36eec67f6d11076223084 Mon Sep 17 00:00:00 2001 From: "Hsu, Kenny" Date: Fri, 2 Dec 2011 08:48:35 -0800 Subject: iwlwifi: add WOWLAN uCode loading support by testmode Create new tm command for WOWLAN uCode loading to support further debugging function in userspace. - IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 16 ++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-testmode.h | 5 ++++- 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 21b2fbb4dc3..3c976262876 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -463,6 +463,21 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) "Error starting the device: %d\n", status); break; + case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: + iwl_scan_cancel_timeout(priv, 200); + iwl_trans_stop_device(trans(priv)); + status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN); + if (status) { + IWL_DEBUG_INFO(priv, + "Error loading WOWLAN ucode: %d\n", status); + break; + } + status = iwl_alive_start(priv); + if (status) + IWL_DEBUG_INFO(priv, + "Error starting the device: %d\n", status); + break; + case IWL_TM_CMD_APP2DEV_GET_EEPROM: if (priv->eeprom) { skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, @@ -826,6 +841,7 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: case IWL_TM_CMD_APP2DEV_GET_EEPROM: case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: + case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); result = iwl_testmode_driver(hw, tb); break; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index e20f3d39027..deedd27c5f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -117,6 +117,8 @@ * @IWL_TM_CMD_APP2DEV_DUMP_SRAM: * commands from user applicaiton to read data in sram * + * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Weak On Wireless LAN uCode image + * */ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_UCODE = 1, @@ -140,7 +142,8 @@ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32 = 19, IWL_TM_CMD_APP2DEV_READ_SRAM = 20, IWL_TM_CMD_APP2DEV_DUMP_SRAM = 21, - IWL_TM_CMD_MAX = 22, + IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW = 22, + IWL_TM_CMD_MAX = 23, }; /* -- cgit v1.2.3-70-g09d2 From 6d5f3ec52939607511a660b01fc34d11ad71ae24 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 2 Dec 2011 08:48:36 -0800 Subject: iwlwifi: Rename file name from iwl-sv-open.c to iwl-testmode.c The file dealing with all the operations through testmode, rename it. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-sv-open.c | 925 ---------------------------- drivers/net/wireless/iwlwifi/iwl-testmode.c | 925 ++++++++++++++++++++++++++++ 3 files changed, 926 insertions(+), 926 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-sv-open.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-testmode.c (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index a7ab280994c..5a052a5e4fb 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -18,7 +18,7 @@ iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o -iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-sv-open.o +iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-testmode.o CFLAGS_iwl-devtrace.o := -I$(src) diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c deleted file mode 100644 index 3c976262876..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ /dev/null @@ -1,925 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-debug.h" -#include "iwl-io.h" -#include "iwl-agn.h" -#include "iwl-testmode.h" -#include "iwl-trans.h" - -/* The TLVs used in the gnl message policy between the kernel module and - * user space application. iwl_testmode_gnl_msg_policy is to be carried - * through the NL80211_CMD_TESTMODE channel regulated by nl80211. - * See iwl-testmode.h - */ -static -struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { - [IWL_TM_ATTR_COMMAND] = { .type = NLA_U32, }, - - [IWL_TM_ATTR_UCODE_CMD_ID] = { .type = NLA_U8, }, - [IWL_TM_ATTR_UCODE_CMD_DATA] = { .type = NLA_UNSPEC, }, - - [IWL_TM_ATTR_REG_OFFSET] = { .type = NLA_U32, }, - [IWL_TM_ATTR_REG_VALUE8] = { .type = NLA_U8, }, - [IWL_TM_ATTR_REG_VALUE32] = { .type = NLA_U32, }, - - [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, - [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, - - [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, }, - - [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, - [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, }, - [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, }, - - [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, - - [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, }, - - [IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, }, - [IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, }, - [IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, }, -}; - -/* - * See the struct iwl_rx_packet in iwl-commands.h for the format of the - * received events from the device - */ -static inline int get_event_length(struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - if (pkt) - return le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; - else - return 0; -} - - -/* - * This function multicasts the spontaneous messages from the device to the - * user space. It is invoked whenever there is a received messages - * from the device. This function is called within the ISR of the rx handlers - * in iwlagn driver. - * - * The parsing of the message content is left to the user space application, - * The message content is treated as unattacked raw data and is encapsulated - * with IWL_TM_ATTR_UCODE_RX_PKT multicasting to the user space. - * - * @priv: the instance of iwlwifi device - * @rxb: pointer to rx data content received by the ISR - * - * See the message policies and TLVs in iwl_testmode_gnl_msg_policy[]. - * For the messages multicasting to the user application, the mandatory - * TLV fields are : - * IWL_TM_ATTR_COMMAND must be IWL_TM_CMD_DEV2APP_UCODE_RX_PKT - * IWL_TM_ATTR_UCODE_RX_PKT for carrying the message content - */ - -static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct ieee80211_hw *hw = priv->hw; - struct sk_buff *skb; - void *data; - int length; - - data = (void *)rxb_addr(rxb); - length = get_event_length(rxb); - - if (!data || length == 0) - return; - - skb = cfg80211_testmode_alloc_event_skb(hw->wiphy, 20 + length, - GFP_ATOMIC); - if (skb == NULL) { - IWL_DEBUG_INFO(priv, - "Run out of memory for messages to user space ?\n"); - return; - } - NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT); - NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data); - cfg80211_testmode_event(skb, GFP_ATOMIC); - return; - -nla_put_failure: - kfree_skb(skb); - IWL_DEBUG_INFO(priv, "Ouch, overran buffer, check allocation!\n"); -} - -void iwl_testmode_init(struct iwl_priv *priv) -{ - priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; - priv->testmode_trace.trace_enabled = false; - priv->testmode_sram.sram_readed = false; -} - -static void iwl_sram_cleanup(struct iwl_priv *priv) -{ - if (priv->testmode_sram.sram_readed) { - kfree(priv->testmode_sram.buff_addr); - priv->testmode_sram.buff_addr = NULL; - priv->testmode_sram.buff_size = 0; - priv->testmode_sram.num_chunks = 0; - priv->testmode_sram.sram_readed = false; - } -} - -static void iwl_trace_cleanup(struct iwl_priv *priv) -{ - if (priv->testmode_trace.trace_enabled) { - if (priv->testmode_trace.cpu_addr && - priv->testmode_trace.dma_addr) - dma_free_coherent(bus(priv)->dev, - priv->testmode_trace.total_size, - priv->testmode_trace.cpu_addr, - priv->testmode_trace.dma_addr); - priv->testmode_trace.trace_enabled = false; - priv->testmode_trace.cpu_addr = NULL; - priv->testmode_trace.trace_addr = NULL; - priv->testmode_trace.dma_addr = 0; - priv->testmode_trace.buff_size = 0; - priv->testmode_trace.total_size = 0; - } -} - - -void iwl_testmode_cleanup(struct iwl_priv *priv) -{ - iwl_trace_cleanup(priv); - iwl_sram_cleanup(priv); -} - -/* - * This function handles the user application commands to the ucode. - * - * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_CMD_ID and - * IWL_TM_ATTR_UCODE_CMD_DATA and calls to the handler to send the - * host command to the ucode. - * - * If any mandatory field is missing, -ENOMSG is replied to the user space - * application; otherwise, the actual execution result of the host command to - * ucode is replied. - * - * @hw: ieee80211_hw object that represents the device - * @tb: gnl message fields from the user space - */ -static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) -{ - struct iwl_priv *priv = hw->priv; - struct iwl_host_cmd cmd; - - memset(&cmd, 0, sizeof(struct iwl_host_cmd)); - - if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] || - !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) { - IWL_DEBUG_INFO(priv, - "Error finding ucode command mandatory fields\n"); - return -ENOMSG; - } - - cmd.flags = CMD_ON_DEMAND; - cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); - cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); - cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); - cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; - IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," - " len %d\n", cmd.id, cmd.flags, cmd.len[0]); - /* ok, let's submit the command to ucode */ - return iwl_trans_send_cmd(trans(priv), &cmd); -} - - -/* - * This function handles the user application commands for register access. - * - * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the - * handlers respectively. - * - * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the - * mandatory fields(IWL_TM_ATTR_REG_OFFSET,IWL_TM_ATTR_REG_VALUE32, - * IWL_TM_ATTR_REG_VALUE8) are missing; Otherwise 0 is replied indicating - * the success of the command execution. - * - * If IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_READ32, the register read - * value is returned with IWL_TM_ATTR_REG_VALUE32. - * - * @hw: ieee80211_hw object that represents the device - * @tb: gnl message fields from the user space - */ -static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) -{ - struct iwl_priv *priv = hw->priv; - u32 ofs, val32; - u8 val8; - struct sk_buff *skb; - int status = 0; - - if (!tb[IWL_TM_ATTR_REG_OFFSET]) { - IWL_DEBUG_INFO(priv, "Error finding register offset\n"); - return -ENOMSG; - } - ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]); - IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs); - - switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { - case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: - val32 = iwl_read32(bus(priv), ofs); - IWL_INFO(priv, "32bit value to read 0x%x\n", val32); - - skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); - if (!skb) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); - return -ENOMEM; - } - NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32); - status = cfg80211_testmode_reply(skb); - if (status < 0) - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", status); - break; - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: - if (!tb[IWL_TM_ATTR_REG_VALUE32]) { - IWL_DEBUG_INFO(priv, - "Error finding value to write\n"); - return -ENOMSG; - } else { - val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); - IWL_INFO(priv, "32bit value to write 0x%x\n", val32); - iwl_write32(bus(priv), ofs, val32); - } - break; - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: - if (!tb[IWL_TM_ATTR_REG_VALUE8]) { - IWL_DEBUG_INFO(priv, "Error finding value to write\n"); - return -ENOMSG; - } else { - val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); - IWL_INFO(priv, "8bit value to write 0x%x\n", val8); - iwl_write8(bus(priv), ofs, val8); - } - break; - case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: - val32 = iwl_read_prph(bus(priv), ofs); - IWL_INFO(priv, "32bit value to read 0x%x\n", val32); - - skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); - if (!skb) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); - return -ENOMEM; - } - NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32); - status = cfg80211_testmode_reply(skb); - if (status < 0) - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", status); - break; - case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32: - if (!tb[IWL_TM_ATTR_REG_VALUE32]) { - IWL_DEBUG_INFO(priv, - "Error finding value to write\n"); - return -ENOMSG; - } else { - val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); - IWL_INFO(priv, "32bit value to write 0x%x\n", val32); - iwl_write_prph(bus(priv), ofs, val32); - } - break; - default: - IWL_DEBUG_INFO(priv, "Unknown testmode register command ID\n"); - return -ENOSYS; - } - - return status; - -nla_put_failure: - kfree_skb(skb); - return -EMSGSIZE; -} - - -static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) -{ - struct iwl_notification_wait calib_wait; - int ret; - - iwlagn_init_notification_wait(priv, &calib_wait, - CALIBRATION_COMPLETE_NOTIFICATION, - NULL, NULL); - ret = iwlagn_init_alive_start(priv); - if (ret) { - IWL_DEBUG_INFO(priv, - "Error configuring init calibration: %d\n", ret); - goto cfg_init_calib_error; - } - - ret = iwlagn_wait_notification(priv, &calib_wait, 2 * HZ); - if (ret) - IWL_DEBUG_INFO(priv, "Error detecting" - " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); - return ret; - -cfg_init_calib_error: - iwlagn_remove_notification(priv, &calib_wait); - return ret; -} - -/* - * This function handles the user application commands for driver. - * - * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the - * handlers respectively. - * - * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned - * value of the actual command execution is replied to the user application. - * - * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP - * is used for carry the message while IWL_TM_ATTR_COMMAND must set to - * IWL_TM_CMD_DEV2APP_SYNC_RSP. - * - * @hw: ieee80211_hw object that represents the device - * @tb: gnl message fields from the user space - */ -static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) -{ - struct iwl_priv *priv = hw->priv; - struct sk_buff *skb; - unsigned char *rsp_data_ptr = NULL; - int status = 0, rsp_data_len = 0; - - switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { - case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: - rsp_data_ptr = (unsigned char *)priv->cfg->name; - rsp_data_len = strlen(priv->cfg->name); - skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, - rsp_data_len + 20); - if (!skb) { - IWL_DEBUG_INFO(priv, - "Error allocating memory\n"); - return -ENOMEM; - } - NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, - IWL_TM_CMD_DEV2APP_SYNC_RSP); - NLA_PUT(skb, IWL_TM_ATTR_SYNC_RSP, - rsp_data_len, rsp_data_ptr); - status = cfg80211_testmode_reply(skb); - if (status < 0) - IWL_DEBUG_INFO(priv, "Error sending msg : %d\n", - status); - break; - - case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: - status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_INIT); - if (status) - IWL_DEBUG_INFO(priv, - "Error loading init ucode: %d\n", status); - break; - - case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: - iwl_testmode_cfg_init_calib(priv); - iwl_trans_stop_device(trans(priv)); - break; - - case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: - status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR); - if (status) { - IWL_DEBUG_INFO(priv, - "Error loading runtime ucode: %d\n", status); - break; - } - status = iwl_alive_start(priv); - if (status) - IWL_DEBUG_INFO(priv, - "Error starting the device: %d\n", status); - break; - - case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: - iwl_scan_cancel_timeout(priv, 200); - iwl_trans_stop_device(trans(priv)); - status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN); - if (status) { - IWL_DEBUG_INFO(priv, - "Error loading WOWLAN ucode: %d\n", status); - break; - } - status = iwl_alive_start(priv); - if (status) - IWL_DEBUG_INFO(priv, - "Error starting the device: %d\n", status); - break; - - case IWL_TM_CMD_APP2DEV_GET_EEPROM: - if (priv->eeprom) { - skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, - priv->cfg->base_params->eeprom_size + 20); - if (!skb) { - IWL_DEBUG_INFO(priv, - "Error allocating memory\n"); - return -ENOMEM; - } - NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, - IWL_TM_CMD_DEV2APP_EEPROM_RSP); - NLA_PUT(skb, IWL_TM_ATTR_EEPROM, - priv->cfg->base_params->eeprom_size, - priv->eeprom); - status = cfg80211_testmode_reply(skb); - if (status < 0) - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", - status); - } else - return -EFAULT; - break; - - case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: - if (!tb[IWL_TM_ATTR_FIXRATE]) { - IWL_DEBUG_INFO(priv, - "Error finding fixrate setting\n"); - return -ENOMSG; - } - priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]); - break; - - default: - IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); - return -ENOSYS; - } - return status; - -nla_put_failure: - kfree_skb(skb); - return -EMSGSIZE; -} - - -/* - * This function handles the user application commands for uCode trace - * - * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the - * handlers respectively. - * - * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned - * value of the actual command execution is replied to the user application. - * - * @hw: ieee80211_hw object that represents the device - * @tb: gnl message fields from the user space - */ -static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) -{ - struct iwl_priv *priv = hw->priv; - struct sk_buff *skb; - int status = 0; - struct device *dev = bus(priv)->dev; - - switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { - case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: - if (priv->testmode_trace.trace_enabled) - return -EBUSY; - - if (!tb[IWL_TM_ATTR_TRACE_SIZE]) - priv->testmode_trace.buff_size = TRACE_BUFF_SIZE_DEF; - else - priv->testmode_trace.buff_size = - nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]); - if (!priv->testmode_trace.buff_size) - return -EINVAL; - if (priv->testmode_trace.buff_size < TRACE_BUFF_SIZE_MIN || - priv->testmode_trace.buff_size > TRACE_BUFF_SIZE_MAX) - return -EINVAL; - - priv->testmode_trace.total_size = - priv->testmode_trace.buff_size + TRACE_BUFF_PADD; - priv->testmode_trace.cpu_addr = - dma_alloc_coherent(dev, - priv->testmode_trace.total_size, - &priv->testmode_trace.dma_addr, - GFP_KERNEL); - if (!priv->testmode_trace.cpu_addr) - return -ENOMEM; - priv->testmode_trace.trace_enabled = true; - priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN( - priv->testmode_trace.cpu_addr, 0x100); - memset(priv->testmode_trace.trace_addr, 0x03B, - priv->testmode_trace.buff_size); - skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, - sizeof(priv->testmode_trace.dma_addr) + 20); - if (!skb) { - IWL_DEBUG_INFO(priv, - "Error allocating memory\n"); - iwl_trace_cleanup(priv); - return -ENOMEM; - } - NLA_PUT(skb, IWL_TM_ATTR_TRACE_ADDR, - sizeof(priv->testmode_trace.dma_addr), - (u64 *)&priv->testmode_trace.dma_addr); - status = cfg80211_testmode_reply(skb); - if (status < 0) { - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", - status); - } - priv->testmode_trace.num_chunks = - DIV_ROUND_UP(priv->testmode_trace.buff_size, - DUMP_CHUNK_SIZE); - break; - - case IWL_TM_CMD_APP2DEV_END_TRACE: - iwl_trace_cleanup(priv); - break; - default: - IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n"); - return -ENOSYS; - } - return status; - -nla_put_failure: - kfree_skb(skb); - if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) == - IWL_TM_CMD_APP2DEV_BEGIN_TRACE) - iwl_trace_cleanup(priv); - return -EMSGSIZE; -} - -static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb, - struct sk_buff *skb, - struct netlink_callback *cb) -{ - struct iwl_priv *priv = hw->priv; - int idx, length; - - if (priv->testmode_trace.trace_enabled && - priv->testmode_trace.trace_addr) { - idx = cb->args[4]; - if (idx >= priv->testmode_trace.num_chunks) - return -ENOENT; - length = DUMP_CHUNK_SIZE; - if (((idx + 1) == priv->testmode_trace.num_chunks) && - (priv->testmode_trace.buff_size % DUMP_CHUNK_SIZE)) - length = priv->testmode_trace.buff_size % - DUMP_CHUNK_SIZE; - - NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length, - priv->testmode_trace.trace_addr + - (DUMP_CHUNK_SIZE * idx)); - idx++; - cb->args[4] = idx; - return 0; - } else - return -EFAULT; - - nla_put_failure: - return -ENOBUFS; -} - -/* - * This function handles the user application switch ucode ownership. - * - * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and - * decide who the current owner of the uCode - * - * If the current owner is OWNERSHIP_TM, then the only host command - * can deliver to uCode is from testmode, all the other host commands - * will dropped. - * - * default driver is the owner of uCode in normal operational mode - * - * @hw: ieee80211_hw object that represents the device - * @tb: gnl message fields from the user space - */ -static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) -{ - struct iwl_priv *priv = hw->priv; - u8 owner; - - if (!tb[IWL_TM_ATTR_UCODE_OWNER]) { - IWL_DEBUG_INFO(priv, "Error finding ucode owner\n"); - return -ENOMSG; - } - - owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); - if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM)) - priv->shrd->ucode_owner = owner; - else { - IWL_DEBUG_INFO(priv, "Invalid owner\n"); - return -EINVAL; - } - return 0; -} - -/* - * This function handles the user application commands for SRAM data dump - * - * It retrieves the mandatory fields IWL_TM_ATTR_SRAM_ADDR and - * IWL_TM_ATTR_SRAM_SIZE to decide the memory area for SRAM data reading - * - * Several error will be retured, -EBUSY if the SRAM data retrieved by - * previous command has not been delivered to userspace, or -ENOMSG if - * the mandatory fields (IWL_TM_ATTR_SRAM_ADDR,IWL_TM_ATTR_SRAM_SIZE) - * are missing, or -ENOMEM if the buffer allocation fails. - * - * Otherwise 0 is replied indicating the success of the SRAM reading. - * - * @hw: ieee80211_hw object that represents the device - * @tb: gnl message fields from the user space - */ -static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) -{ - struct iwl_priv *priv = hw->priv; - u32 base, ofs, size, maxsize; - - if (priv->testmode_sram.sram_readed) - return -EBUSY; - - if (!tb[IWL_TM_ATTR_SRAM_ADDR]) { - IWL_DEBUG_INFO(priv, "Error finding SRAM offset address\n"); - return -ENOMSG; - } - ofs = nla_get_u32(tb[IWL_TM_ATTR_SRAM_ADDR]); - if (!tb[IWL_TM_ATTR_SRAM_SIZE]) { - IWL_DEBUG_INFO(priv, "Error finding size for SRAM reading\n"); - return -ENOMSG; - } - size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]); - switch (priv->ucode_type) { - case IWL_UCODE_REGULAR: - maxsize = trans(priv)->ucode_rt.data.len; - break; - case IWL_UCODE_INIT: - maxsize = trans(priv)->ucode_init.data.len; - break; - case IWL_UCODE_WOWLAN: - maxsize = trans(priv)->ucode_wowlan.data.len; - break; - case IWL_UCODE_NONE: - IWL_DEBUG_INFO(priv, "Error, uCode does not been loaded\n"); - return -ENOSYS; - default: - IWL_DEBUG_INFO(priv, "Error, unsupported uCode type\n"); - return -ENOSYS; - } - if ((ofs + size) > maxsize) { - IWL_DEBUG_INFO(priv, "Invalid offset/size: out of range\n"); - return -EINVAL; - } - priv->testmode_sram.buff_size = (size / 4) * 4; - priv->testmode_sram.buff_addr = - kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL); - if (priv->testmode_sram.buff_addr == NULL) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); - return -ENOMEM; - } - base = 0x800000; - _iwl_read_targ_mem_words(bus(priv), base + ofs, - priv->testmode_sram.buff_addr, - priv->testmode_sram.buff_size / 4); - priv->testmode_sram.num_chunks = - DIV_ROUND_UP(priv->testmode_sram.buff_size, DUMP_CHUNK_SIZE); - priv->testmode_sram.sram_readed = true; - return 0; -} - -static int iwl_testmode_sram_dump(struct ieee80211_hw *hw, struct nlattr **tb, - struct sk_buff *skb, - struct netlink_callback *cb) -{ - struct iwl_priv *priv = hw->priv; - int idx, length; - - if (priv->testmode_sram.sram_readed) { - idx = cb->args[4]; - if (idx >= priv->testmode_sram.num_chunks) { - iwl_sram_cleanup(priv); - return -ENOENT; - } - length = DUMP_CHUNK_SIZE; - if (((idx + 1) == priv->testmode_sram.num_chunks) && - (priv->testmode_sram.buff_size % DUMP_CHUNK_SIZE)) - length = priv->testmode_sram.buff_size % - DUMP_CHUNK_SIZE; - - NLA_PUT(skb, IWL_TM_ATTR_SRAM_DUMP, length, - priv->testmode_sram.buff_addr + - (DUMP_CHUNK_SIZE * idx)); - idx++; - cb->args[4] = idx; - return 0; - } else - return -EFAULT; - - nla_put_failure: - return -ENOBUFS; -} - - -/* The testmode gnl message handler that takes the gnl message from the - * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then - * invoke the corresponding handlers. - * - * This function is invoked when there is user space application sending - * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated - * by nl80211. - * - * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before - * dispatching it to the corresponding handler. - * - * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application; - * -ENOSYS is replied to the user application if the command is unknown; - * Otherwise, the command is dispatched to the respective handler. - * - * @hw: ieee80211_hw object that represents the device - * @data: pointer to user space message - * @len: length in byte of @data - */ -int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) -{ - struct nlattr *tb[IWL_TM_ATTR_MAX]; - struct iwl_priv *priv = hw->priv; - int result; - - result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, - iwl_testmode_gnl_msg_policy); - if (result != 0) { - IWL_DEBUG_INFO(priv, - "Error parsing the gnl message : %d\n", result); - return result; - } - - /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ - if (!tb[IWL_TM_ATTR_COMMAND]) { - IWL_DEBUG_INFO(priv, "Error finding testmode command type\n"); - return -ENOMSG; - } - /* in case multiple accesses to the device happens */ - mutex_lock(&priv->shrd->mutex); - - switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { - case IWL_TM_CMD_APP2DEV_UCODE: - IWL_DEBUG_INFO(priv, "testmode cmd to uCode\n"); - result = iwl_testmode_ucode(hw, tb); - break; - case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: - case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: - case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32: - IWL_DEBUG_INFO(priv, "testmode cmd to register\n"); - result = iwl_testmode_reg(hw, tb); - break; - case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: - case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: - case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: - case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: - case IWL_TM_CMD_APP2DEV_GET_EEPROM: - case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: - case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: - IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); - result = iwl_testmode_driver(hw, tb); - break; - - case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: - case IWL_TM_CMD_APP2DEV_END_TRACE: - case IWL_TM_CMD_APP2DEV_READ_TRACE: - IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n"); - result = iwl_testmode_trace(hw, tb); - break; - - case IWL_TM_CMD_APP2DEV_OWNERSHIP: - IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n"); - result = iwl_testmode_ownership(hw, tb); - break; - - case IWL_TM_CMD_APP2DEV_READ_SRAM: - IWL_DEBUG_INFO(priv, "testmode sram read cmd to driver\n"); - result = iwl_testmode_sram(hw, tb); - break; - - default: - IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); - result = -ENOSYS; - break; - } - - mutex_unlock(&priv->shrd->mutex); - return result; -} - -int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, - struct netlink_callback *cb, - void *data, int len) -{ - struct nlattr *tb[IWL_TM_ATTR_MAX]; - struct iwl_priv *priv = hw->priv; - int result; - u32 cmd; - - if (cb->args[3]) { - /* offset by 1 since commands start at 0 */ - cmd = cb->args[3] - 1; - } else { - result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, - iwl_testmode_gnl_msg_policy); - if (result) { - IWL_DEBUG_INFO(priv, - "Error parsing the gnl message : %d\n", result); - return result; - } - - /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ - if (!tb[IWL_TM_ATTR_COMMAND]) { - IWL_DEBUG_INFO(priv, - "Error finding testmode command type\n"); - return -ENOMSG; - } - cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); - cb->args[3] = cmd + 1; - } - - /* in case multiple accesses to the device happens */ - mutex_lock(&priv->shrd->mutex); - switch (cmd) { - case IWL_TM_CMD_APP2DEV_READ_TRACE: - IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); - result = iwl_testmode_trace_dump(hw, tb, skb, cb); - break; - case IWL_TM_CMD_APP2DEV_DUMP_SRAM: - IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n"); - result = iwl_testmode_sram_dump(hw, tb, skb, cb); - break; - default: - result = -EINVAL; - break; - } - - mutex_unlock(&priv->shrd->mutex); - return result; -} diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c new file mode 100644 index 00000000000..3c976262876 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -0,0 +1,925 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-debug.h" +#include "iwl-io.h" +#include "iwl-agn.h" +#include "iwl-testmode.h" +#include "iwl-trans.h" + +/* The TLVs used in the gnl message policy between the kernel module and + * user space application. iwl_testmode_gnl_msg_policy is to be carried + * through the NL80211_CMD_TESTMODE channel regulated by nl80211. + * See iwl-testmode.h + */ +static +struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { + [IWL_TM_ATTR_COMMAND] = { .type = NLA_U32, }, + + [IWL_TM_ATTR_UCODE_CMD_ID] = { .type = NLA_U8, }, + [IWL_TM_ATTR_UCODE_CMD_DATA] = { .type = NLA_UNSPEC, }, + + [IWL_TM_ATTR_REG_OFFSET] = { .type = NLA_U32, }, + [IWL_TM_ATTR_REG_VALUE8] = { .type = NLA_U8, }, + [IWL_TM_ATTR_REG_VALUE32] = { .type = NLA_U32, }, + + [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, + [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, + + [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, }, + + [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, + [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, }, + [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, }, + + [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, + + [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, }, + + [IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, }, + [IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, }, + [IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, }, +}; + +/* + * See the struct iwl_rx_packet in iwl-commands.h for the format of the + * received events from the device + */ +static inline int get_event_length(struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + if (pkt) + return le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + else + return 0; +} + + +/* + * This function multicasts the spontaneous messages from the device to the + * user space. It is invoked whenever there is a received messages + * from the device. This function is called within the ISR of the rx handlers + * in iwlagn driver. + * + * The parsing of the message content is left to the user space application, + * The message content is treated as unattacked raw data and is encapsulated + * with IWL_TM_ATTR_UCODE_RX_PKT multicasting to the user space. + * + * @priv: the instance of iwlwifi device + * @rxb: pointer to rx data content received by the ISR + * + * See the message policies and TLVs in iwl_testmode_gnl_msg_policy[]. + * For the messages multicasting to the user application, the mandatory + * TLV fields are : + * IWL_TM_ATTR_COMMAND must be IWL_TM_CMD_DEV2APP_UCODE_RX_PKT + * IWL_TM_ATTR_UCODE_RX_PKT for carrying the message content + */ + +static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct ieee80211_hw *hw = priv->hw; + struct sk_buff *skb; + void *data; + int length; + + data = (void *)rxb_addr(rxb); + length = get_event_length(rxb); + + if (!data || length == 0) + return; + + skb = cfg80211_testmode_alloc_event_skb(hw->wiphy, 20 + length, + GFP_ATOMIC); + if (skb == NULL) { + IWL_DEBUG_INFO(priv, + "Run out of memory for messages to user space ?\n"); + return; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT); + NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data); + cfg80211_testmode_event(skb, GFP_ATOMIC); + return; + +nla_put_failure: + kfree_skb(skb); + IWL_DEBUG_INFO(priv, "Ouch, overran buffer, check allocation!\n"); +} + +void iwl_testmode_init(struct iwl_priv *priv) +{ + priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; + priv->testmode_trace.trace_enabled = false; + priv->testmode_sram.sram_readed = false; +} + +static void iwl_sram_cleanup(struct iwl_priv *priv) +{ + if (priv->testmode_sram.sram_readed) { + kfree(priv->testmode_sram.buff_addr); + priv->testmode_sram.buff_addr = NULL; + priv->testmode_sram.buff_size = 0; + priv->testmode_sram.num_chunks = 0; + priv->testmode_sram.sram_readed = false; + } +} + +static void iwl_trace_cleanup(struct iwl_priv *priv) +{ + if (priv->testmode_trace.trace_enabled) { + if (priv->testmode_trace.cpu_addr && + priv->testmode_trace.dma_addr) + dma_free_coherent(bus(priv)->dev, + priv->testmode_trace.total_size, + priv->testmode_trace.cpu_addr, + priv->testmode_trace.dma_addr); + priv->testmode_trace.trace_enabled = false; + priv->testmode_trace.cpu_addr = NULL; + priv->testmode_trace.trace_addr = NULL; + priv->testmode_trace.dma_addr = 0; + priv->testmode_trace.buff_size = 0; + priv->testmode_trace.total_size = 0; + } +} + + +void iwl_testmode_cleanup(struct iwl_priv *priv) +{ + iwl_trace_cleanup(priv); + iwl_sram_cleanup(priv); +} + +/* + * This function handles the user application commands to the ucode. + * + * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_CMD_ID and + * IWL_TM_ATTR_UCODE_CMD_DATA and calls to the handler to send the + * host command to the ucode. + * + * If any mandatory field is missing, -ENOMSG is replied to the user space + * application; otherwise, the actual execution result of the host command to + * ucode is replied. + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + struct iwl_host_cmd cmd; + + memset(&cmd, 0, sizeof(struct iwl_host_cmd)); + + if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] || + !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) { + IWL_DEBUG_INFO(priv, + "Error finding ucode command mandatory fields\n"); + return -ENOMSG; + } + + cmd.flags = CMD_ON_DEMAND; + cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); + cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); + cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); + cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; + IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," + " len %d\n", cmd.id, cmd.flags, cmd.len[0]); + /* ok, let's submit the command to ucode */ + return iwl_trans_send_cmd(trans(priv), &cmd); +} + + +/* + * This function handles the user application commands for register access. + * + * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the + * handlers respectively. + * + * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the + * mandatory fields(IWL_TM_ATTR_REG_OFFSET,IWL_TM_ATTR_REG_VALUE32, + * IWL_TM_ATTR_REG_VALUE8) are missing; Otherwise 0 is replied indicating + * the success of the command execution. + * + * If IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_READ32, the register read + * value is returned with IWL_TM_ATTR_REG_VALUE32. + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + u32 ofs, val32; + u8 val8; + struct sk_buff *skb; + int status = 0; + + if (!tb[IWL_TM_ATTR_REG_OFFSET]) { + IWL_DEBUG_INFO(priv, "Error finding register offset\n"); + return -ENOMSG; + } + ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]); + IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs); + + switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { + case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: + val32 = iwl_read32(bus(priv), ofs); + IWL_INFO(priv, "32bit value to read 0x%x\n", val32); + + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); + if (!skb) { + IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + return -ENOMEM; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32); + status = cfg80211_testmode_reply(skb); + if (status < 0) + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", status); + break; + case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: + if (!tb[IWL_TM_ATTR_REG_VALUE32]) { + IWL_DEBUG_INFO(priv, + "Error finding value to write\n"); + return -ENOMSG; + } else { + val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); + IWL_INFO(priv, "32bit value to write 0x%x\n", val32); + iwl_write32(bus(priv), ofs, val32); + } + break; + case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: + if (!tb[IWL_TM_ATTR_REG_VALUE8]) { + IWL_DEBUG_INFO(priv, "Error finding value to write\n"); + return -ENOMSG; + } else { + val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); + IWL_INFO(priv, "8bit value to write 0x%x\n", val8); + iwl_write8(bus(priv), ofs, val8); + } + break; + case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: + val32 = iwl_read_prph(bus(priv), ofs); + IWL_INFO(priv, "32bit value to read 0x%x\n", val32); + + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); + if (!skb) { + IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + return -ENOMEM; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32); + status = cfg80211_testmode_reply(skb); + if (status < 0) + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", status); + break; + case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32: + if (!tb[IWL_TM_ATTR_REG_VALUE32]) { + IWL_DEBUG_INFO(priv, + "Error finding value to write\n"); + return -ENOMSG; + } else { + val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); + IWL_INFO(priv, "32bit value to write 0x%x\n", val32); + iwl_write_prph(bus(priv), ofs, val32); + } + break; + default: + IWL_DEBUG_INFO(priv, "Unknown testmode register command ID\n"); + return -ENOSYS; + } + + return status; + +nla_put_failure: + kfree_skb(skb); + return -EMSGSIZE; +} + + +static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) +{ + struct iwl_notification_wait calib_wait; + int ret; + + iwlagn_init_notification_wait(priv, &calib_wait, + CALIBRATION_COMPLETE_NOTIFICATION, + NULL, NULL); + ret = iwlagn_init_alive_start(priv); + if (ret) { + IWL_DEBUG_INFO(priv, + "Error configuring init calibration: %d\n", ret); + goto cfg_init_calib_error; + } + + ret = iwlagn_wait_notification(priv, &calib_wait, 2 * HZ); + if (ret) + IWL_DEBUG_INFO(priv, "Error detecting" + " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); + return ret; + +cfg_init_calib_error: + iwlagn_remove_notification(priv, &calib_wait); + return ret; +} + +/* + * This function handles the user application commands for driver. + * + * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the + * handlers respectively. + * + * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned + * value of the actual command execution is replied to the user application. + * + * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP + * is used for carry the message while IWL_TM_ATTR_COMMAND must set to + * IWL_TM_CMD_DEV2APP_SYNC_RSP. + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + struct sk_buff *skb; + unsigned char *rsp_data_ptr = NULL; + int status = 0, rsp_data_len = 0; + + switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { + case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: + rsp_data_ptr = (unsigned char *)priv->cfg->name; + rsp_data_len = strlen(priv->cfg->name); + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, + rsp_data_len + 20); + if (!skb) { + IWL_DEBUG_INFO(priv, + "Error allocating memory\n"); + return -ENOMEM; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, + IWL_TM_CMD_DEV2APP_SYNC_RSP); + NLA_PUT(skb, IWL_TM_ATTR_SYNC_RSP, + rsp_data_len, rsp_data_ptr); + status = cfg80211_testmode_reply(skb); + if (status < 0) + IWL_DEBUG_INFO(priv, "Error sending msg : %d\n", + status); + break; + + case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: + status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_INIT); + if (status) + IWL_DEBUG_INFO(priv, + "Error loading init ucode: %d\n", status); + break; + + case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: + iwl_testmode_cfg_init_calib(priv); + iwl_trans_stop_device(trans(priv)); + break; + + case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: + status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR); + if (status) { + IWL_DEBUG_INFO(priv, + "Error loading runtime ucode: %d\n", status); + break; + } + status = iwl_alive_start(priv); + if (status) + IWL_DEBUG_INFO(priv, + "Error starting the device: %d\n", status); + break; + + case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: + iwl_scan_cancel_timeout(priv, 200); + iwl_trans_stop_device(trans(priv)); + status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN); + if (status) { + IWL_DEBUG_INFO(priv, + "Error loading WOWLAN ucode: %d\n", status); + break; + } + status = iwl_alive_start(priv); + if (status) + IWL_DEBUG_INFO(priv, + "Error starting the device: %d\n", status); + break; + + case IWL_TM_CMD_APP2DEV_GET_EEPROM: + if (priv->eeprom) { + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, + priv->cfg->base_params->eeprom_size + 20); + if (!skb) { + IWL_DEBUG_INFO(priv, + "Error allocating memory\n"); + return -ENOMEM; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, + IWL_TM_CMD_DEV2APP_EEPROM_RSP); + NLA_PUT(skb, IWL_TM_ATTR_EEPROM, + priv->cfg->base_params->eeprom_size, + priv->eeprom); + status = cfg80211_testmode_reply(skb); + if (status < 0) + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", + status); + } else + return -EFAULT; + break; + + case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: + if (!tb[IWL_TM_ATTR_FIXRATE]) { + IWL_DEBUG_INFO(priv, + "Error finding fixrate setting\n"); + return -ENOMSG; + } + priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]); + break; + + default: + IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); + return -ENOSYS; + } + return status; + +nla_put_failure: + kfree_skb(skb); + return -EMSGSIZE; +} + + +/* + * This function handles the user application commands for uCode trace + * + * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the + * handlers respectively. + * + * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned + * value of the actual command execution is replied to the user application. + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + struct sk_buff *skb; + int status = 0; + struct device *dev = bus(priv)->dev; + + switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { + case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: + if (priv->testmode_trace.trace_enabled) + return -EBUSY; + + if (!tb[IWL_TM_ATTR_TRACE_SIZE]) + priv->testmode_trace.buff_size = TRACE_BUFF_SIZE_DEF; + else + priv->testmode_trace.buff_size = + nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]); + if (!priv->testmode_trace.buff_size) + return -EINVAL; + if (priv->testmode_trace.buff_size < TRACE_BUFF_SIZE_MIN || + priv->testmode_trace.buff_size > TRACE_BUFF_SIZE_MAX) + return -EINVAL; + + priv->testmode_trace.total_size = + priv->testmode_trace.buff_size + TRACE_BUFF_PADD; + priv->testmode_trace.cpu_addr = + dma_alloc_coherent(dev, + priv->testmode_trace.total_size, + &priv->testmode_trace.dma_addr, + GFP_KERNEL); + if (!priv->testmode_trace.cpu_addr) + return -ENOMEM; + priv->testmode_trace.trace_enabled = true; + priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN( + priv->testmode_trace.cpu_addr, 0x100); + memset(priv->testmode_trace.trace_addr, 0x03B, + priv->testmode_trace.buff_size); + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, + sizeof(priv->testmode_trace.dma_addr) + 20); + if (!skb) { + IWL_DEBUG_INFO(priv, + "Error allocating memory\n"); + iwl_trace_cleanup(priv); + return -ENOMEM; + } + NLA_PUT(skb, IWL_TM_ATTR_TRACE_ADDR, + sizeof(priv->testmode_trace.dma_addr), + (u64 *)&priv->testmode_trace.dma_addr); + status = cfg80211_testmode_reply(skb); + if (status < 0) { + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", + status); + } + priv->testmode_trace.num_chunks = + DIV_ROUND_UP(priv->testmode_trace.buff_size, + DUMP_CHUNK_SIZE); + break; + + case IWL_TM_CMD_APP2DEV_END_TRACE: + iwl_trace_cleanup(priv); + break; + default: + IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n"); + return -ENOSYS; + } + return status; + +nla_put_failure: + kfree_skb(skb); + if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) == + IWL_TM_CMD_APP2DEV_BEGIN_TRACE) + iwl_trace_cleanup(priv); + return -EMSGSIZE; +} + +static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb, + struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct iwl_priv *priv = hw->priv; + int idx, length; + + if (priv->testmode_trace.trace_enabled && + priv->testmode_trace.trace_addr) { + idx = cb->args[4]; + if (idx >= priv->testmode_trace.num_chunks) + return -ENOENT; + length = DUMP_CHUNK_SIZE; + if (((idx + 1) == priv->testmode_trace.num_chunks) && + (priv->testmode_trace.buff_size % DUMP_CHUNK_SIZE)) + length = priv->testmode_trace.buff_size % + DUMP_CHUNK_SIZE; + + NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length, + priv->testmode_trace.trace_addr + + (DUMP_CHUNK_SIZE * idx)); + idx++; + cb->args[4] = idx; + return 0; + } else + return -EFAULT; + + nla_put_failure: + return -ENOBUFS; +} + +/* + * This function handles the user application switch ucode ownership. + * + * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and + * decide who the current owner of the uCode + * + * If the current owner is OWNERSHIP_TM, then the only host command + * can deliver to uCode is from testmode, all the other host commands + * will dropped. + * + * default driver is the owner of uCode in normal operational mode + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + u8 owner; + + if (!tb[IWL_TM_ATTR_UCODE_OWNER]) { + IWL_DEBUG_INFO(priv, "Error finding ucode owner\n"); + return -ENOMSG; + } + + owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); + if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM)) + priv->shrd->ucode_owner = owner; + else { + IWL_DEBUG_INFO(priv, "Invalid owner\n"); + return -EINVAL; + } + return 0; +} + +/* + * This function handles the user application commands for SRAM data dump + * + * It retrieves the mandatory fields IWL_TM_ATTR_SRAM_ADDR and + * IWL_TM_ATTR_SRAM_SIZE to decide the memory area for SRAM data reading + * + * Several error will be retured, -EBUSY if the SRAM data retrieved by + * previous command has not been delivered to userspace, or -ENOMSG if + * the mandatory fields (IWL_TM_ATTR_SRAM_ADDR,IWL_TM_ATTR_SRAM_SIZE) + * are missing, or -ENOMEM if the buffer allocation fails. + * + * Otherwise 0 is replied indicating the success of the SRAM reading. + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + u32 base, ofs, size, maxsize; + + if (priv->testmode_sram.sram_readed) + return -EBUSY; + + if (!tb[IWL_TM_ATTR_SRAM_ADDR]) { + IWL_DEBUG_INFO(priv, "Error finding SRAM offset address\n"); + return -ENOMSG; + } + ofs = nla_get_u32(tb[IWL_TM_ATTR_SRAM_ADDR]); + if (!tb[IWL_TM_ATTR_SRAM_SIZE]) { + IWL_DEBUG_INFO(priv, "Error finding size for SRAM reading\n"); + return -ENOMSG; + } + size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]); + switch (priv->ucode_type) { + case IWL_UCODE_REGULAR: + maxsize = trans(priv)->ucode_rt.data.len; + break; + case IWL_UCODE_INIT: + maxsize = trans(priv)->ucode_init.data.len; + break; + case IWL_UCODE_WOWLAN: + maxsize = trans(priv)->ucode_wowlan.data.len; + break; + case IWL_UCODE_NONE: + IWL_DEBUG_INFO(priv, "Error, uCode does not been loaded\n"); + return -ENOSYS; + default: + IWL_DEBUG_INFO(priv, "Error, unsupported uCode type\n"); + return -ENOSYS; + } + if ((ofs + size) > maxsize) { + IWL_DEBUG_INFO(priv, "Invalid offset/size: out of range\n"); + return -EINVAL; + } + priv->testmode_sram.buff_size = (size / 4) * 4; + priv->testmode_sram.buff_addr = + kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL); + if (priv->testmode_sram.buff_addr == NULL) { + IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + return -ENOMEM; + } + base = 0x800000; + _iwl_read_targ_mem_words(bus(priv), base + ofs, + priv->testmode_sram.buff_addr, + priv->testmode_sram.buff_size / 4); + priv->testmode_sram.num_chunks = + DIV_ROUND_UP(priv->testmode_sram.buff_size, DUMP_CHUNK_SIZE); + priv->testmode_sram.sram_readed = true; + return 0; +} + +static int iwl_testmode_sram_dump(struct ieee80211_hw *hw, struct nlattr **tb, + struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct iwl_priv *priv = hw->priv; + int idx, length; + + if (priv->testmode_sram.sram_readed) { + idx = cb->args[4]; + if (idx >= priv->testmode_sram.num_chunks) { + iwl_sram_cleanup(priv); + return -ENOENT; + } + length = DUMP_CHUNK_SIZE; + if (((idx + 1) == priv->testmode_sram.num_chunks) && + (priv->testmode_sram.buff_size % DUMP_CHUNK_SIZE)) + length = priv->testmode_sram.buff_size % + DUMP_CHUNK_SIZE; + + NLA_PUT(skb, IWL_TM_ATTR_SRAM_DUMP, length, + priv->testmode_sram.buff_addr + + (DUMP_CHUNK_SIZE * idx)); + idx++; + cb->args[4] = idx; + return 0; + } else + return -EFAULT; + + nla_put_failure: + return -ENOBUFS; +} + + +/* The testmode gnl message handler that takes the gnl message from the + * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then + * invoke the corresponding handlers. + * + * This function is invoked when there is user space application sending + * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated + * by nl80211. + * + * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before + * dispatching it to the corresponding handler. + * + * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application; + * -ENOSYS is replied to the user application if the command is unknown; + * Otherwise, the command is dispatched to the respective handler. + * + * @hw: ieee80211_hw object that represents the device + * @data: pointer to user space message + * @len: length in byte of @data + */ +int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) +{ + struct nlattr *tb[IWL_TM_ATTR_MAX]; + struct iwl_priv *priv = hw->priv; + int result; + + result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, + iwl_testmode_gnl_msg_policy); + if (result != 0) { + IWL_DEBUG_INFO(priv, + "Error parsing the gnl message : %d\n", result); + return result; + } + + /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ + if (!tb[IWL_TM_ATTR_COMMAND]) { + IWL_DEBUG_INFO(priv, "Error finding testmode command type\n"); + return -ENOMSG; + } + /* in case multiple accesses to the device happens */ + mutex_lock(&priv->shrd->mutex); + + switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { + case IWL_TM_CMD_APP2DEV_UCODE: + IWL_DEBUG_INFO(priv, "testmode cmd to uCode\n"); + result = iwl_testmode_ucode(hw, tb); + break; + case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: + case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: + case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: + case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: + case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32: + IWL_DEBUG_INFO(priv, "testmode cmd to register\n"); + result = iwl_testmode_reg(hw, tb); + break; + case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: + case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: + case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: + case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: + case IWL_TM_CMD_APP2DEV_GET_EEPROM: + case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: + case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: + IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); + result = iwl_testmode_driver(hw, tb); + break; + + case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: + case IWL_TM_CMD_APP2DEV_END_TRACE: + case IWL_TM_CMD_APP2DEV_READ_TRACE: + IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n"); + result = iwl_testmode_trace(hw, tb); + break; + + case IWL_TM_CMD_APP2DEV_OWNERSHIP: + IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n"); + result = iwl_testmode_ownership(hw, tb); + break; + + case IWL_TM_CMD_APP2DEV_READ_SRAM: + IWL_DEBUG_INFO(priv, "testmode sram read cmd to driver\n"); + result = iwl_testmode_sram(hw, tb); + break; + + default: + IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); + result = -ENOSYS; + break; + } + + mutex_unlock(&priv->shrd->mutex); + return result; +} + +int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, + struct netlink_callback *cb, + void *data, int len) +{ + struct nlattr *tb[IWL_TM_ATTR_MAX]; + struct iwl_priv *priv = hw->priv; + int result; + u32 cmd; + + if (cb->args[3]) { + /* offset by 1 since commands start at 0 */ + cmd = cb->args[3] - 1; + } else { + result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, + iwl_testmode_gnl_msg_policy); + if (result) { + IWL_DEBUG_INFO(priv, + "Error parsing the gnl message : %d\n", result); + return result; + } + + /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ + if (!tb[IWL_TM_ATTR_COMMAND]) { + IWL_DEBUG_INFO(priv, + "Error finding testmode command type\n"); + return -ENOMSG; + } + cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); + cb->args[3] = cmd + 1; + } + + /* in case multiple accesses to the device happens */ + mutex_lock(&priv->shrd->mutex); + switch (cmd) { + case IWL_TM_CMD_APP2DEV_READ_TRACE: + IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); + result = iwl_testmode_trace_dump(hw, tb, skb, cb); + break; + case IWL_TM_CMD_APP2DEV_DUMP_SRAM: + IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n"); + result = iwl_testmode_sram_dump(hw, tb, skb, cb); + break; + default: + result = -EINVAL; + break; + } + + mutex_unlock(&priv->shrd->mutex); + return result; +} -- cgit v1.2.3-70-g09d2 From 481f564ac72b2f6c77ba80e7a31932365bd21a35 Mon Sep 17 00:00:00 2001 From: Don Fry Date: Fri, 2 Dec 2011 08:48:37 -0800 Subject: iwlwifi: rename iwl-agn-ucode as iwl-ucode iwl-agn-ucode is generic ucode operations, not limited just to iwlagn. Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 688 --------------------------- drivers/net/wireless/iwlwifi/iwl-ucode.c | 688 +++++++++++++++++++++++++++ 3 files changed, 689 insertions(+), 689 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-ucode.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-ucode.c (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 5a052a5e4fb..86344cefd32 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -1,7 +1,7 @@ # WIFI obj-$(CONFIG_IWLWIFI) += iwlwifi.o iwlwifi-objs := iwl-agn.o iwl-agn-rs.o iwl-mac80211.o -iwlwifi-objs += iwl-agn-ucode.o iwl-agn-tx.o +iwlwifi-objs += iwl-ucode.o iwl-agn-tx.o iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c deleted file mode 100644 index 76949106daf..00000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ /dev/null @@ -1,688 +0,0 @@ -/****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include - -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-agn-hw.h" -#include "iwl-agn.h" -#include "iwl-agn-calib.h" -#include "iwl-trans.h" -#include "iwl-fh.h" - -static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { - {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, - 0, COEX_UNASSOC_IDLE_FLAGS}, - {COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP, - 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, - {COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP, - 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, - {COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP, - 0, COEX_CALIBRATION_FLAGS}, - {COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP, - 0, COEX_PERIODIC_CALIBRATION_FLAGS}, - {COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP, - 0, COEX_CONNECTION_ESTAB_FLAGS}, - {COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP, - 0, COEX_ASSOCIATED_IDLE_FLAGS}, - {COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP, - 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, - {COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP, - 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, - {COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP, - 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, - {COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS}, - {COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS}, - {COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP, - 0, COEX_STAND_ALONE_DEBUG_FLAGS}, - {COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP, - 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, - {COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS}, - {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS} -}; - -/****************************************************************************** - * - * uCode download functions - * - ******************************************************************************/ - -static void iwl_free_fw_desc(struct iwl_bus *bus, struct fw_desc *desc) -{ - if (desc->v_addr) - dma_free_coherent(bus->dev, desc->len, - desc->v_addr, desc->p_addr); - desc->v_addr = NULL; - desc->len = 0; -} - -static void iwl_free_fw_img(struct iwl_bus *bus, struct fw_img *img) -{ - iwl_free_fw_desc(bus, &img->code); - iwl_free_fw_desc(bus, &img->data); -} - -void iwl_dealloc_ucode(struct iwl_trans *trans) -{ - iwl_free_fw_img(bus(trans), &trans->ucode_rt); - iwl_free_fw_img(bus(trans), &trans->ucode_init); - iwl_free_fw_img(bus(trans), &trans->ucode_wowlan); -} - -int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, - const void *data, size_t len) -{ - if (!len) { - desc->v_addr = NULL; - return -EINVAL; - } - - desc->v_addr = dma_alloc_coherent(bus->dev, len, - &desc->p_addr, GFP_KERNEL); - if (!desc->v_addr) - return -ENOMEM; - - desc->len = len; - memcpy(desc->v_addr, data, len); - return 0; -} - -/* - * ucode - */ -static int iwlagn_load_section(struct iwl_trans *trans, const char *name, - struct fw_desc *image, u32 dst_addr) -{ - struct iwl_bus *bus = bus(trans); - dma_addr_t phy_addr = image->p_addr; - u32 byte_cnt = image->len; - int ret; - - trans->ucode_write_complete = 0; - - iwl_write_direct32(bus, - FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); - - iwl_write_direct32(bus, - FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); - - iwl_write_direct32(bus, - FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), - phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); - - iwl_write_direct32(bus, - FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), - (iwl_get_dma_hi_addr(phy_addr) - << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); - - iwl_write_direct32(bus, - FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), - 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | - 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | - FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); - - iwl_write_direct32(bus, - FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | - FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); - - IWL_DEBUG_FW(bus, "%s uCode section being loaded...\n", name); - ret = wait_event_timeout(trans->shrd->wait_command_queue, - trans->ucode_write_complete, 5 * HZ); - if (!ret) { - IWL_ERR(trans, "Could not load the %s uCode section\n", - name); - return -ETIMEDOUT; - } - - return 0; -} - -static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, - enum iwl_ucode_type ucode_type) -{ - switch (ucode_type) { - case IWL_UCODE_INIT: - return &trans->ucode_init; - case IWL_UCODE_WOWLAN: - return &trans->ucode_wowlan; - case IWL_UCODE_REGULAR: - return &trans->ucode_rt; - case IWL_UCODE_NONE: - break; - } - return NULL; -} - -static int iwlagn_load_given_ucode(struct iwl_trans *trans, - enum iwl_ucode_type ucode_type) -{ - int ret = 0; - struct fw_img *image = iwl_get_ucode_image(trans, ucode_type); - - - if (!image) { - IWL_ERR(trans, "Invalid ucode requested (%d)\n", - ucode_type); - return -EINVAL; - } - - ret = iwlagn_load_section(trans, "INST", &image->code, - IWLAGN_RTC_INST_LOWER_BOUND); - if (ret) - return ret; - - return iwlagn_load_section(trans, "DATA", &image->data, - IWLAGN_RTC_DATA_LOWER_BOUND); -} - -/* - * Calibration - */ -static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) -{ - struct iwl_calib_xtal_freq_cmd cmd; - __le16 *xtal_calib = - (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL); - - iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); - cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); - cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); - return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); -} - -static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) -{ - struct iwl_calib_temperature_offset_cmd cmd; - __le16 *offset_calib = - (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); - - memset(&cmd, 0, sizeof(cmd)); - iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); - memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(*offset_calib)); - if (!(cmd.radio_sensor_offset)) - cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; - - IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", - le16_to_cpu(cmd.radio_sensor_offset)); - return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); -} - -static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv) -{ - struct iwl_calib_temperature_offset_v2_cmd cmd; - __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, - EEPROM_KELVIN_TEMPERATURE); - __le16 *offset_calib_low = - (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); - struct iwl_eeprom_calib_hdr *hdr; - - memset(&cmd, 0, sizeof(cmd)); - iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); - hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, - EEPROM_CALIB_ALL); - memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, - sizeof(*offset_calib_high)); - memcpy(&cmd.radio_sensor_offset_low, offset_calib_low, - sizeof(*offset_calib_low)); - if (!(cmd.radio_sensor_offset_low)) { - IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); - cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; - cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; - } - memcpy(&cmd.burntVoltageRef, &hdr->voltage, - sizeof(hdr->voltage)); - - IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", - le16_to_cpu(cmd.radio_sensor_offset_high)); - IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n", - le16_to_cpu(cmd.radio_sensor_offset_low)); - IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n", - le16_to_cpu(cmd.burntVoltageRef)); - - return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); -} - -static int iwlagn_send_calib_cfg(struct iwl_priv *priv) -{ - struct iwl_calib_cfg_cmd calib_cfg_cmd; - struct iwl_host_cmd cmd = { - .id = CALIBRATION_CFG_CMD, - .len = { sizeof(struct iwl_calib_cfg_cmd), }, - .data = { &calib_cfg_cmd, }, - }; - - memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); - calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; - calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; - calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; - calib_cfg_cmd.ucd_calib_cfg.flags = - IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; - - return iwl_trans_send_cmd(trans(priv), &cmd); -} - -int iwlagn_rx_calib_result(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; - int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; - - /* reduce the size of the length field itself */ - len -= 4; - - if (iwl_calib_set(priv, hdr, len)) - IWL_ERR(priv, "Failed to record calibration data %d\n", - hdr->op_code); - - return 0; -} - -int iwlagn_init_alive_start(struct iwl_priv *priv) -{ - int ret; - - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { - /* - * Tell uCode we are ready to perform calibration - * need to perform this before any calibration - * no need to close the envlope since we are going - * to load the runtime uCode later. - */ - ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, - BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); - if (ret) - return ret; - - } - - ret = iwlagn_send_calib_cfg(priv); - if (ret) - return ret; - - /** - * temperature offset calibration is only needed for runtime ucode, - * so prepare the value now. - */ - if (priv->cfg->need_temp_offset_calib) { - if (priv->cfg->temp_offset_v2) - return iwlagn_set_temperature_offset_calib_v2(priv); - else - return iwlagn_set_temperature_offset_calib(priv); - } - - return 0; -} - -static int iwlagn_send_wimax_coex(struct iwl_priv *priv) -{ - struct iwl_wimax_coex_cmd coex_cmd; - - if (priv->cfg->base_params->support_wimax_coexist) { - /* UnMask wake up src at associated sleep */ - coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK; - - /* UnMask wake up src at unassociated sleep */ - coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK; - memcpy(coex_cmd.sta_prio, cu_priorities, - sizeof(struct iwl_wimax_coex_event_entry) * - COEX_NUM_OF_EVENTS); - - /* enabling the coexistence feature */ - coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK; - - /* enabling the priorities tables */ - coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK; - } else { - /* coexistence is disabled */ - memset(&coex_cmd, 0, sizeof(coex_cmd)); - } - return iwl_trans_send_cmd_pdu(trans(priv), - COEX_PRIORITY_TABLE_CMD, CMD_SYNC, - sizeof(coex_cmd), &coex_cmd); -} - -static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { - ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | - (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), - ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | - (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), - ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | - (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), - ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | - (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), - ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | - (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), - ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | - (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), - ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | - (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), - ((BT_COEX_PRIO_TBL_PRIO_COEX_OFF << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | - (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), - ((BT_COEX_PRIO_TBL_PRIO_COEX_ON << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | - (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), - 0, 0, 0, 0, 0, 0, 0 -}; - -void iwlagn_send_prio_tbl(struct iwl_priv *priv) -{ - struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd; - - memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, - sizeof(iwlagn_bt_prio_tbl)); - if (iwl_trans_send_cmd_pdu(trans(priv), - REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, - sizeof(prio_tbl_cmd), &prio_tbl_cmd)) - IWL_ERR(priv, "failed to send BT prio tbl command\n"); -} - -int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) -{ - struct iwl_bt_coex_prot_env_cmd env_cmd; - int ret; - - env_cmd.action = action; - env_cmd.type = type; - ret = iwl_trans_send_cmd_pdu(trans(priv), - REPLY_BT_COEX_PROT_ENV, CMD_SYNC, - sizeof(env_cmd), &env_cmd); - if (ret) - IWL_ERR(priv, "failed to send BT env command\n"); - return ret; -} - - -static int iwlagn_alive_notify(struct iwl_priv *priv) -{ - struct iwl_rxon_context *ctx; - int ret; - - if (!priv->tx_cmd_pool) - priv->tx_cmd_pool = - kmem_cache_create("iwlagn_dev_cmd", - sizeof(struct iwl_device_cmd), - sizeof(void *), 0, NULL); - - if (!priv->tx_cmd_pool) - return -ENOMEM; - - iwl_trans_tx_start(trans(priv)); - for_each_context(priv, ctx) - ctx->last_tx_rejected = false; - - ret = iwlagn_send_wimax_coex(priv); - if (ret) - return ret; - - if (!priv->cfg->no_xtal_calib) { - ret = iwlagn_set_Xtal_calib(priv); - if (ret) - return ret; - } - - return iwl_send_calib_results(priv); -} - - -/** - * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host, - * using sample data 100 bytes apart. If these sample points are good, - * it's a pretty good bet that everything between them is good, too. - */ -static int iwl_verify_inst_sparse(struct iwl_bus *bus, - struct fw_desc *fw_desc) -{ - __le32 *image = (__le32 *)fw_desc->v_addr; - u32 len = fw_desc->len; - u32 val; - u32 i; - - IWL_DEBUG_FW(bus, "ucode inst image size is %u\n", len); - - for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { - /* read data comes through single port, auto-incr addr */ - /* NOTE: Use the debugless read so we don't flood kernel log - * if IWL_DL_IO is set */ - iwl_write_direct32(bus, HBUS_TARG_MEM_RADDR, - i + IWLAGN_RTC_INST_LOWER_BOUND); - val = iwl_read32(bus, HBUS_TARG_MEM_RDAT); - if (val != le32_to_cpu(*image)) - return -EIO; - } - - return 0; -} - -static void iwl_print_mismatch_inst(struct iwl_bus *bus, - struct fw_desc *fw_desc) -{ - __le32 *image = (__le32 *)fw_desc->v_addr; - u32 len = fw_desc->len; - u32 val; - u32 offs; - int errors = 0; - - IWL_DEBUG_FW(bus, "ucode inst image size is %u\n", len); - - iwl_write_direct32(bus, HBUS_TARG_MEM_RADDR, - IWLAGN_RTC_INST_LOWER_BOUND); - - for (offs = 0; - offs < len && errors < 20; - offs += sizeof(u32), image++) { - /* read data comes through single port, auto-incr addr */ - val = iwl_read32(bus, HBUS_TARG_MEM_RDAT); - if (val != le32_to_cpu(*image)) { - IWL_ERR(bus, "uCode INST section at " - "offset 0x%x, is 0x%x, s/b 0x%x\n", - offs, val, le32_to_cpu(*image)); - errors++; - } - } -} - -/** - * iwl_verify_ucode - determine which instruction image is in SRAM, - * and verify its contents - */ -static int iwl_verify_ucode(struct iwl_trans *trans, - enum iwl_ucode_type ucode_type) -{ - struct fw_img *img = iwl_get_ucode_image(trans, ucode_type); - - if (!img) { - IWL_ERR(trans, "Invalid ucode requested (%d)\n", ucode_type); - return -EINVAL; - } - - if (!iwl_verify_inst_sparse(bus(trans), &img->code)) { - IWL_DEBUG_FW(trans, "uCode is good in inst SRAM\n"); - return 0; - } - - IWL_ERR(trans, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); - - iwl_print_mismatch_inst(bus(trans), &img->code); - return -EIO; -} - -struct iwlagn_alive_data { - bool valid; - u8 subtype; -}; - -static void iwlagn_alive_fn(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - void *data) -{ - struct iwlagn_alive_data *alive_data = data; - struct iwl_alive_resp *palive; - - palive = &pkt->u.alive_frame; - - IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision " - "0x%01X 0x%01X\n", - palive->is_valid, palive->ver_type, - palive->ver_subtype); - - priv->device_pointers.error_event_table = - le32_to_cpu(palive->error_event_table_ptr); - priv->device_pointers.log_event_table = - le32_to_cpu(palive->log_event_table_ptr); - - alive_data->subtype = palive->ver_subtype; - alive_data->valid = palive->is_valid == UCODE_VALID_OK; -} - -#define UCODE_ALIVE_TIMEOUT HZ -#define UCODE_CALIB_TIMEOUT (2*HZ) - -int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, - enum iwl_ucode_type ucode_type) -{ - struct iwl_notification_wait alive_wait; - struct iwlagn_alive_data alive_data; - int ret; - enum iwl_ucode_type old_type; - - ret = iwl_trans_start_device(trans(priv)); - if (ret) - return ret; - - iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE, - iwlagn_alive_fn, &alive_data); - - old_type = priv->ucode_type; - priv->ucode_type = ucode_type; - - ret = iwlagn_load_given_ucode(trans(priv), ucode_type); - if (ret) { - priv->ucode_type = old_type; - iwlagn_remove_notification(priv, &alive_wait); - return ret; - } - - iwl_trans_kick_nic(trans(priv)); - - /* - * Some things may run in the background now, but we - * just wait for the ALIVE notification here. - */ - ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT); - if (ret) { - priv->ucode_type = old_type; - return ret; - } - - if (!alive_data.valid) { - IWL_ERR(priv, "Loaded ucode is not valid!\n"); - priv->ucode_type = old_type; - return -EIO; - } - - /* - * This step takes a long time (60-80ms!!) and - * WoWLAN image should be loaded quickly, so - * skip it for WoWLAN. - */ - if (ucode_type != IWL_UCODE_WOWLAN) { - ret = iwl_verify_ucode(trans(priv), ucode_type); - if (ret) { - priv->ucode_type = old_type; - return ret; - } - - /* delay a bit to give rfkill time to run */ - msleep(5); - } - - ret = iwlagn_alive_notify(priv); - if (ret) { - IWL_WARN(priv, - "Could not complete ALIVE transition: %d\n", ret); - priv->ucode_type = old_type; - return ret; - } - - return 0; -} - -int iwlagn_run_init_ucode(struct iwl_priv *priv) -{ - struct iwl_notification_wait calib_wait; - int ret; - - lockdep_assert_held(&priv->shrd->mutex); - - /* No init ucode required? Curious, but maybe ok */ - if (!trans(priv)->ucode_init.code.len) - return 0; - - if (priv->ucode_type != IWL_UCODE_NONE) - return 0; - - iwlagn_init_notification_wait(priv, &calib_wait, - CALIBRATION_COMPLETE_NOTIFICATION, - NULL, NULL); - - /* Will also start the device */ - ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_INIT); - if (ret) - goto error; - - ret = iwlagn_init_alive_start(priv); - if (ret) - goto error; - - /* - * Some things may run in the background now, but we - * just wait for the calibration complete notification. - */ - ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT); - - goto out; - - error: - iwlagn_remove_notification(priv, &calib_wait); - out: - /* Whatever happened, stop the device */ - iwl_trans_stop_device(trans(priv)); - return ret; -} diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c new file mode 100644 index 00000000000..76949106daf --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -0,0 +1,688 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-io.h" +#include "iwl-agn-hw.h" +#include "iwl-agn.h" +#include "iwl-agn-calib.h" +#include "iwl-trans.h" +#include "iwl-fh.h" + +static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { + {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, + 0, COEX_UNASSOC_IDLE_FLAGS}, + {COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP, + 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, + {COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP, + 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, + {COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP, + 0, COEX_CALIBRATION_FLAGS}, + {COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP, + 0, COEX_PERIODIC_CALIBRATION_FLAGS}, + {COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP, + 0, COEX_CONNECTION_ESTAB_FLAGS}, + {COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP, + 0, COEX_ASSOCIATED_IDLE_FLAGS}, + {COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP, + 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, + {COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP, + 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, + {COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP, + 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, + {COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS}, + {COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS}, + {COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP, + 0, COEX_STAND_ALONE_DEBUG_FLAGS}, + {COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP, + 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, + {COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS}, + {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS} +}; + +/****************************************************************************** + * + * uCode download functions + * + ******************************************************************************/ + +static void iwl_free_fw_desc(struct iwl_bus *bus, struct fw_desc *desc) +{ + if (desc->v_addr) + dma_free_coherent(bus->dev, desc->len, + desc->v_addr, desc->p_addr); + desc->v_addr = NULL; + desc->len = 0; +} + +static void iwl_free_fw_img(struct iwl_bus *bus, struct fw_img *img) +{ + iwl_free_fw_desc(bus, &img->code); + iwl_free_fw_desc(bus, &img->data); +} + +void iwl_dealloc_ucode(struct iwl_trans *trans) +{ + iwl_free_fw_img(bus(trans), &trans->ucode_rt); + iwl_free_fw_img(bus(trans), &trans->ucode_init); + iwl_free_fw_img(bus(trans), &trans->ucode_wowlan); +} + +int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, + const void *data, size_t len) +{ + if (!len) { + desc->v_addr = NULL; + return -EINVAL; + } + + desc->v_addr = dma_alloc_coherent(bus->dev, len, + &desc->p_addr, GFP_KERNEL); + if (!desc->v_addr) + return -ENOMEM; + + desc->len = len; + memcpy(desc->v_addr, data, len); + return 0; +} + +/* + * ucode + */ +static int iwlagn_load_section(struct iwl_trans *trans, const char *name, + struct fw_desc *image, u32 dst_addr) +{ + struct iwl_bus *bus = bus(trans); + dma_addr_t phy_addr = image->p_addr; + u32 byte_cnt = image->len; + int ret; + + trans->ucode_write_complete = 0; + + iwl_write_direct32(bus, + FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); + + iwl_write_direct32(bus, + FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); + + iwl_write_direct32(bus, + FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), + phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); + + iwl_write_direct32(bus, + FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), + (iwl_get_dma_hi_addr(phy_addr) + << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); + + iwl_write_direct32(bus, + FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), + 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | + 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | + FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); + + iwl_write_direct32(bus, + FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | + FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); + + IWL_DEBUG_FW(bus, "%s uCode section being loaded...\n", name); + ret = wait_event_timeout(trans->shrd->wait_command_queue, + trans->ucode_write_complete, 5 * HZ); + if (!ret) { + IWL_ERR(trans, "Could not load the %s uCode section\n", + name); + return -ETIMEDOUT; + } + + return 0; +} + +static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, + enum iwl_ucode_type ucode_type) +{ + switch (ucode_type) { + case IWL_UCODE_INIT: + return &trans->ucode_init; + case IWL_UCODE_WOWLAN: + return &trans->ucode_wowlan; + case IWL_UCODE_REGULAR: + return &trans->ucode_rt; + case IWL_UCODE_NONE: + break; + } + return NULL; +} + +static int iwlagn_load_given_ucode(struct iwl_trans *trans, + enum iwl_ucode_type ucode_type) +{ + int ret = 0; + struct fw_img *image = iwl_get_ucode_image(trans, ucode_type); + + + if (!image) { + IWL_ERR(trans, "Invalid ucode requested (%d)\n", + ucode_type); + return -EINVAL; + } + + ret = iwlagn_load_section(trans, "INST", &image->code, + IWLAGN_RTC_INST_LOWER_BOUND); + if (ret) + return ret; + + return iwlagn_load_section(trans, "DATA", &image->data, + IWLAGN_RTC_DATA_LOWER_BOUND); +} + +/* + * Calibration + */ +static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) +{ + struct iwl_calib_xtal_freq_cmd cmd; + __le16 *xtal_calib = + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL); + + iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); + cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); + cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); + return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); +} + +static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) +{ + struct iwl_calib_temperature_offset_cmd cmd; + __le16 *offset_calib = + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); + + memset(&cmd, 0, sizeof(cmd)); + iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); + memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(*offset_calib)); + if (!(cmd.radio_sensor_offset)) + cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; + + IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", + le16_to_cpu(cmd.radio_sensor_offset)); + return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); +} + +static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv) +{ + struct iwl_calib_temperature_offset_v2_cmd cmd; + __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, + EEPROM_KELVIN_TEMPERATURE); + __le16 *offset_calib_low = + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); + struct iwl_eeprom_calib_hdr *hdr; + + memset(&cmd, 0, sizeof(cmd)); + iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); + hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, + EEPROM_CALIB_ALL); + memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, + sizeof(*offset_calib_high)); + memcpy(&cmd.radio_sensor_offset_low, offset_calib_low, + sizeof(*offset_calib_low)); + if (!(cmd.radio_sensor_offset_low)) { + IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); + cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; + cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; + } + memcpy(&cmd.burntVoltageRef, &hdr->voltage, + sizeof(hdr->voltage)); + + IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", + le16_to_cpu(cmd.radio_sensor_offset_high)); + IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n", + le16_to_cpu(cmd.radio_sensor_offset_low)); + IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n", + le16_to_cpu(cmd.burntVoltageRef)); + + return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); +} + +static int iwlagn_send_calib_cfg(struct iwl_priv *priv) +{ + struct iwl_calib_cfg_cmd calib_cfg_cmd; + struct iwl_host_cmd cmd = { + .id = CALIBRATION_CFG_CMD, + .len = { sizeof(struct iwl_calib_cfg_cmd), }, + .data = { &calib_cfg_cmd, }, + }; + + memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); + calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; + calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; + calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; + calib_cfg_cmd.ucd_calib_cfg.flags = + IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; + + return iwl_trans_send_cmd(trans(priv), &cmd); +} + +int iwlagn_rx_calib_result(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb, + struct iwl_device_cmd *cmd) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; + int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + + /* reduce the size of the length field itself */ + len -= 4; + + if (iwl_calib_set(priv, hdr, len)) + IWL_ERR(priv, "Failed to record calibration data %d\n", + hdr->op_code); + + return 0; +} + +int iwlagn_init_alive_start(struct iwl_priv *priv) +{ + int ret; + + if (priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist) { + /* + * Tell uCode we are ready to perform calibration + * need to perform this before any calibration + * no need to close the envlope since we are going + * to load the runtime uCode later. + */ + ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, + BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); + if (ret) + return ret; + + } + + ret = iwlagn_send_calib_cfg(priv); + if (ret) + return ret; + + /** + * temperature offset calibration is only needed for runtime ucode, + * so prepare the value now. + */ + if (priv->cfg->need_temp_offset_calib) { + if (priv->cfg->temp_offset_v2) + return iwlagn_set_temperature_offset_calib_v2(priv); + else + return iwlagn_set_temperature_offset_calib(priv); + } + + return 0; +} + +static int iwlagn_send_wimax_coex(struct iwl_priv *priv) +{ + struct iwl_wimax_coex_cmd coex_cmd; + + if (priv->cfg->base_params->support_wimax_coexist) { + /* UnMask wake up src at associated sleep */ + coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK; + + /* UnMask wake up src at unassociated sleep */ + coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK; + memcpy(coex_cmd.sta_prio, cu_priorities, + sizeof(struct iwl_wimax_coex_event_entry) * + COEX_NUM_OF_EVENTS); + + /* enabling the coexistence feature */ + coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK; + + /* enabling the priorities tables */ + coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK; + } else { + /* coexistence is disabled */ + memset(&coex_cmd, 0, sizeof(coex_cmd)); + } + return iwl_trans_send_cmd_pdu(trans(priv), + COEX_PRIORITY_TABLE_CMD, CMD_SYNC, + sizeof(coex_cmd), &coex_cmd); +} + +static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { + ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_COEX_OFF << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + ((BT_COEX_PRIO_TBL_PRIO_COEX_ON << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | + (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), + 0, 0, 0, 0, 0, 0, 0 +}; + +void iwlagn_send_prio_tbl(struct iwl_priv *priv) +{ + struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd; + + memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, + sizeof(iwlagn_bt_prio_tbl)); + if (iwl_trans_send_cmd_pdu(trans(priv), + REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, + sizeof(prio_tbl_cmd), &prio_tbl_cmd)) + IWL_ERR(priv, "failed to send BT prio tbl command\n"); +} + +int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) +{ + struct iwl_bt_coex_prot_env_cmd env_cmd; + int ret; + + env_cmd.action = action; + env_cmd.type = type; + ret = iwl_trans_send_cmd_pdu(trans(priv), + REPLY_BT_COEX_PROT_ENV, CMD_SYNC, + sizeof(env_cmd), &env_cmd); + if (ret) + IWL_ERR(priv, "failed to send BT env command\n"); + return ret; +} + + +static int iwlagn_alive_notify(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx; + int ret; + + if (!priv->tx_cmd_pool) + priv->tx_cmd_pool = + kmem_cache_create("iwlagn_dev_cmd", + sizeof(struct iwl_device_cmd), + sizeof(void *), 0, NULL); + + if (!priv->tx_cmd_pool) + return -ENOMEM; + + iwl_trans_tx_start(trans(priv)); + for_each_context(priv, ctx) + ctx->last_tx_rejected = false; + + ret = iwlagn_send_wimax_coex(priv); + if (ret) + return ret; + + if (!priv->cfg->no_xtal_calib) { + ret = iwlagn_set_Xtal_calib(priv); + if (ret) + return ret; + } + + return iwl_send_calib_results(priv); +} + + +/** + * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host, + * using sample data 100 bytes apart. If these sample points are good, + * it's a pretty good bet that everything between them is good, too. + */ +static int iwl_verify_inst_sparse(struct iwl_bus *bus, + struct fw_desc *fw_desc) +{ + __le32 *image = (__le32 *)fw_desc->v_addr; + u32 len = fw_desc->len; + u32 val; + u32 i; + + IWL_DEBUG_FW(bus, "ucode inst image size is %u\n", len); + + for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { + /* read data comes through single port, auto-incr addr */ + /* NOTE: Use the debugless read so we don't flood kernel log + * if IWL_DL_IO is set */ + iwl_write_direct32(bus, HBUS_TARG_MEM_RADDR, + i + IWLAGN_RTC_INST_LOWER_BOUND); + val = iwl_read32(bus, HBUS_TARG_MEM_RDAT); + if (val != le32_to_cpu(*image)) + return -EIO; + } + + return 0; +} + +static void iwl_print_mismatch_inst(struct iwl_bus *bus, + struct fw_desc *fw_desc) +{ + __le32 *image = (__le32 *)fw_desc->v_addr; + u32 len = fw_desc->len; + u32 val; + u32 offs; + int errors = 0; + + IWL_DEBUG_FW(bus, "ucode inst image size is %u\n", len); + + iwl_write_direct32(bus, HBUS_TARG_MEM_RADDR, + IWLAGN_RTC_INST_LOWER_BOUND); + + for (offs = 0; + offs < len && errors < 20; + offs += sizeof(u32), image++) { + /* read data comes through single port, auto-incr addr */ + val = iwl_read32(bus, HBUS_TARG_MEM_RDAT); + if (val != le32_to_cpu(*image)) { + IWL_ERR(bus, "uCode INST section at " + "offset 0x%x, is 0x%x, s/b 0x%x\n", + offs, val, le32_to_cpu(*image)); + errors++; + } + } +} + +/** + * iwl_verify_ucode - determine which instruction image is in SRAM, + * and verify its contents + */ +static int iwl_verify_ucode(struct iwl_trans *trans, + enum iwl_ucode_type ucode_type) +{ + struct fw_img *img = iwl_get_ucode_image(trans, ucode_type); + + if (!img) { + IWL_ERR(trans, "Invalid ucode requested (%d)\n", ucode_type); + return -EINVAL; + } + + if (!iwl_verify_inst_sparse(bus(trans), &img->code)) { + IWL_DEBUG_FW(trans, "uCode is good in inst SRAM\n"); + return 0; + } + + IWL_ERR(trans, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); + + iwl_print_mismatch_inst(bus(trans), &img->code); + return -EIO; +} + +struct iwlagn_alive_data { + bool valid; + u8 subtype; +}; + +static void iwlagn_alive_fn(struct iwl_priv *priv, + struct iwl_rx_packet *pkt, + void *data) +{ + struct iwlagn_alive_data *alive_data = data; + struct iwl_alive_resp *palive; + + palive = &pkt->u.alive_frame; + + IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision " + "0x%01X 0x%01X\n", + palive->is_valid, palive->ver_type, + palive->ver_subtype); + + priv->device_pointers.error_event_table = + le32_to_cpu(palive->error_event_table_ptr); + priv->device_pointers.log_event_table = + le32_to_cpu(palive->log_event_table_ptr); + + alive_data->subtype = palive->ver_subtype; + alive_data->valid = palive->is_valid == UCODE_VALID_OK; +} + +#define UCODE_ALIVE_TIMEOUT HZ +#define UCODE_CALIB_TIMEOUT (2*HZ) + +int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, + enum iwl_ucode_type ucode_type) +{ + struct iwl_notification_wait alive_wait; + struct iwlagn_alive_data alive_data; + int ret; + enum iwl_ucode_type old_type; + + ret = iwl_trans_start_device(trans(priv)); + if (ret) + return ret; + + iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE, + iwlagn_alive_fn, &alive_data); + + old_type = priv->ucode_type; + priv->ucode_type = ucode_type; + + ret = iwlagn_load_given_ucode(trans(priv), ucode_type); + if (ret) { + priv->ucode_type = old_type; + iwlagn_remove_notification(priv, &alive_wait); + return ret; + } + + iwl_trans_kick_nic(trans(priv)); + + /* + * Some things may run in the background now, but we + * just wait for the ALIVE notification here. + */ + ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT); + if (ret) { + priv->ucode_type = old_type; + return ret; + } + + if (!alive_data.valid) { + IWL_ERR(priv, "Loaded ucode is not valid!\n"); + priv->ucode_type = old_type; + return -EIO; + } + + /* + * This step takes a long time (60-80ms!!) and + * WoWLAN image should be loaded quickly, so + * skip it for WoWLAN. + */ + if (ucode_type != IWL_UCODE_WOWLAN) { + ret = iwl_verify_ucode(trans(priv), ucode_type); + if (ret) { + priv->ucode_type = old_type; + return ret; + } + + /* delay a bit to give rfkill time to run */ + msleep(5); + } + + ret = iwlagn_alive_notify(priv); + if (ret) { + IWL_WARN(priv, + "Could not complete ALIVE transition: %d\n", ret); + priv->ucode_type = old_type; + return ret; + } + + return 0; +} + +int iwlagn_run_init_ucode(struct iwl_priv *priv) +{ + struct iwl_notification_wait calib_wait; + int ret; + + lockdep_assert_held(&priv->shrd->mutex); + + /* No init ucode required? Curious, but maybe ok */ + if (!trans(priv)->ucode_init.code.len) + return 0; + + if (priv->ucode_type != IWL_UCODE_NONE) + return 0; + + iwlagn_init_notification_wait(priv, &calib_wait, + CALIBRATION_COMPLETE_NOTIFICATION, + NULL, NULL); + + /* Will also start the device */ + ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_INIT); + if (ret) + goto error; + + ret = iwlagn_init_alive_start(priv); + if (ret) + goto error; + + /* + * Some things may run in the background now, but we + * just wait for the calibration complete notification. + */ + ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT); + + goto out; + + error: + iwlagn_remove_notification(priv, &calib_wait); + out: + /* Whatever happened, stop the device */ + iwl_trans_stop_device(trans(priv)); + return ret; +} -- cgit v1.2.3-70-g09d2 From b96b09db60f8e0d9c6bc3ea00447953c16d8b2fc Mon Sep 17 00:00:00 2001 From: Don Fry Date: Fri, 2 Dec 2011 08:48:38 -0800 Subject: iwlwifi: replace iwl_priv reference with iwl_trans for ucode. Replace the references to the iwl_priv structure with the iwl_trans structure as the priv structure is never referenced other than to access the trans structure. Rename from iwlagn to iwl. Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++-- drivers/net/wireless/iwlwifi/iwl-agn.h | 4 +-- drivers/net/wireless/iwlwifi/iwl-ucode.c | 62 ++++++++++++++++---------------- 3 files changed, 36 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4d20be9dea3..daf010dad70 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1232,14 +1232,14 @@ int iwl_alive_start(struct iwl_priv *priv) priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; priv->cur_rssi_ctx = NULL; - iwlagn_send_prio_tbl(priv); + iwl_send_prio_tbl(trans(priv)); /* FIXME: w/a to force change uCode BT state machine */ - ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, + ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); if (ret) return ret; - ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, + ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_CLOSE, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); if (ret) return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 2f446a35351..0db0a8fb567 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -108,8 +108,8 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf, int iwlagn_rx_calib_result(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, struct iwl_device_cmd *cmd); -int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); -void iwlagn_send_prio_tbl(struct iwl_priv *priv); +int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type); +void iwl_send_prio_tbl(struct iwl_trans *trans); int iwlagn_run_init_ucode(struct iwl_priv *priv); int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, enum iwl_ucode_type ucode_type); diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 76949106daf..0da4b8ece11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -122,7 +122,7 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, /* * ucode */ -static int iwlagn_load_section(struct iwl_trans *trans, const char *name, +static int iwl_load_section(struct iwl_trans *trans, const char *name, struct fw_desc *image, u32 dst_addr) { struct iwl_bus *bus = bus(trans); @@ -188,7 +188,7 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, return NULL; } -static int iwlagn_load_given_ucode(struct iwl_trans *trans, +static int iwl_load_given_ucode(struct iwl_trans *trans, enum iwl_ucode_type ucode_type) { int ret = 0; @@ -201,19 +201,19 @@ static int iwlagn_load_given_ucode(struct iwl_trans *trans, return -EINVAL; } - ret = iwlagn_load_section(trans, "INST", &image->code, + ret = iwl_load_section(trans, "INST", &image->code, IWLAGN_RTC_INST_LOWER_BOUND); if (ret) return ret; - return iwlagn_load_section(trans, "DATA", &image->data, + return iwl_load_section(trans, "DATA", &image->data, IWLAGN_RTC_DATA_LOWER_BOUND); } /* * Calibration */ -static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) +static int iwl_set_Xtal_calib(struct iwl_priv *priv) { struct iwl_calib_xtal_freq_cmd cmd; __le16 *xtal_calib = @@ -225,7 +225,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); } -static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) +static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) { struct iwl_calib_temperature_offset_cmd cmd; __le16 *offset_calib = @@ -242,7 +242,7 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); } -static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv) +static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) { struct iwl_calib_temperature_offset_v2_cmd cmd; __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, @@ -277,7 +277,7 @@ static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv) return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); } -static int iwlagn_send_calib_cfg(struct iwl_priv *priv) +static int iwl_send_calib_cfg(struct iwl_trans *trans) { struct iwl_calib_cfg_cmd calib_cfg_cmd; struct iwl_host_cmd cmd = { @@ -293,7 +293,7 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv) calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; - return iwl_trans_send_cmd(trans(priv), &cmd); + return iwl_trans_send_cmd(trans, &cmd); } int iwlagn_rx_calib_result(struct iwl_priv *priv, @@ -326,14 +326,14 @@ int iwlagn_init_alive_start(struct iwl_priv *priv) * no need to close the envlope since we are going * to load the runtime uCode later. */ - ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, + ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); if (ret) return ret; } - ret = iwlagn_send_calib_cfg(priv); + ret = iwl_send_calib_cfg(trans(priv)); if (ret) return ret; @@ -343,15 +343,15 @@ int iwlagn_init_alive_start(struct iwl_priv *priv) */ if (priv->cfg->need_temp_offset_calib) { if (priv->cfg->temp_offset_v2) - return iwlagn_set_temperature_offset_calib_v2(priv); + return iwl_set_temperature_offset_calib_v2(priv); else - return iwlagn_set_temperature_offset_calib(priv); + return iwl_set_temperature_offset_calib(priv); } return 0; } -static int iwlagn_send_wimax_coex(struct iwl_priv *priv) +static int iwl_send_wimax_coex(struct iwl_priv *priv) { struct iwl_wimax_coex_cmd coex_cmd; @@ -379,7 +379,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv) sizeof(coex_cmd), &coex_cmd); } -static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { +static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | @@ -401,42 +401,42 @@ static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { 0, 0, 0, 0, 0, 0, 0 }; -void iwlagn_send_prio_tbl(struct iwl_priv *priv) +void iwl_send_prio_tbl(struct iwl_trans *trans) { struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd; - memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, - sizeof(iwlagn_bt_prio_tbl)); - if (iwl_trans_send_cmd_pdu(trans(priv), + memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl, + sizeof(iwl_bt_prio_tbl)); + if (iwl_trans_send_cmd_pdu(trans, REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, sizeof(prio_tbl_cmd), &prio_tbl_cmd)) - IWL_ERR(priv, "failed to send BT prio tbl command\n"); + IWL_ERR(trans, "failed to send BT prio tbl command\n"); } -int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) +int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type) { struct iwl_bt_coex_prot_env_cmd env_cmd; int ret; env_cmd.action = action; env_cmd.type = type; - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = iwl_trans_send_cmd_pdu(trans, REPLY_BT_COEX_PROT_ENV, CMD_SYNC, sizeof(env_cmd), &env_cmd); if (ret) - IWL_ERR(priv, "failed to send BT env command\n"); + IWL_ERR(trans, "failed to send BT env command\n"); return ret; } -static int iwlagn_alive_notify(struct iwl_priv *priv) +static int iwl_alive_notify(struct iwl_priv *priv) { struct iwl_rxon_context *ctx; int ret; if (!priv->tx_cmd_pool) priv->tx_cmd_pool = - kmem_cache_create("iwlagn_dev_cmd", + kmem_cache_create("iwl_dev_cmd", sizeof(struct iwl_device_cmd), sizeof(void *), 0, NULL); @@ -447,12 +447,12 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) for_each_context(priv, ctx) ctx->last_tx_rejected = false; - ret = iwlagn_send_wimax_coex(priv); + ret = iwl_send_wimax_coex(priv); if (ret) return ret; if (!priv->cfg->no_xtal_calib) { - ret = iwlagn_set_Xtal_calib(priv); + ret = iwl_set_Xtal_calib(priv); if (ret) return ret; } @@ -548,7 +548,7 @@ struct iwlagn_alive_data { u8 subtype; }; -static void iwlagn_alive_fn(struct iwl_priv *priv, +static void iwl_alive_fn(struct iwl_priv *priv, struct iwl_rx_packet *pkt, void *data) { @@ -587,12 +587,12 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, return ret; iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE, - iwlagn_alive_fn, &alive_data); + iwl_alive_fn, &alive_data); old_type = priv->ucode_type; priv->ucode_type = ucode_type; - ret = iwlagn_load_given_ucode(trans(priv), ucode_type); + ret = iwl_load_given_ucode(trans(priv), ucode_type); if (ret) { priv->ucode_type = old_type; iwlagn_remove_notification(priv, &alive_wait); @@ -633,7 +633,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, msleep(5); } - ret = iwlagn_alive_notify(priv); + ret = iwl_alive_notify(priv); if (ret) { IWL_WARN(priv, "Could not complete ALIVE transition: %d\n", ret); -- cgit v1.2.3-70-g09d2 From a96b724d5ad7d44184d6a871bc1d35b005f2d53e Mon Sep 17 00:00:00 2001 From: Don Fry Date: Fri, 2 Dec 2011 08:48:39 -0800 Subject: iwlwifi: move ucode_type from iwl_priv to iwl_shared Move the ucode_type variable from the iwl_priv to the iwl_shared structure with associated code changes. Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-shared.h | 20 +++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-testmode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 10 +++++----- drivers/net/wireless/iwlwifi/iwl-trans.h | 7 ------- drivers/net/wireless/iwlwifi/iwl-ucode.c | 25 ++++++++++++------------ 7 files changed, 43 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 68b04f5b10c..ccbcab40e78 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -234,11 +234,12 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, /* default is to dump the entire data segment */ if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { + struct iwl_trans *trans = trans(priv); priv->dbgfs_sram_offset = 0x800000; - if (priv->ucode_type == IWL_UCODE_INIT) - priv->dbgfs_sram_len = trans(priv)->ucode_init.data.len; + if (trans->shrd->ucode_type == IWL_UCODE_INIT) + priv->dbgfs_sram_len = trans->ucode_init.data.len; else - priv->dbgfs_sram_len = trans(priv)->ucode_rt.data.len; + priv->dbgfs_sram_len = trans->ucode_rt.data.len; } len = priv->dbgfs_sram_len; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index cb24adbae08..0019a23d6d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -889,7 +889,6 @@ struct iwl_priv { u32 ucode_ver; /* version of ucode, copy of iwl_ucode.ver */ - enum iwl_ucode_type ucode_type; char firmware_name[25]; struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX]; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 30af95b19f7..aa4905a2e79 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -256,6 +256,23 @@ struct iwl_tid_data { struct iwl_ht_agg agg; }; +/** + * enum iwl_ucode_type + * + * The type of ucode currently loaded on the hardware. + * + * @IWL_UCODE_NONE: No ucode loaded + * @IWL_UCODE_REGULAR: Normal runtime ucode + * @IWL_UCODE_INIT: Initial ucode + * @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode + */ +enum iwl_ucode_type { + IWL_UCODE_NONE, + IWL_UCODE_REGULAR, + IWL_UCODE_INIT, + IWL_UCODE_WOWLAN, +}; + /** * struct iwl_shared - shared fields for all the layers of the driver * @@ -300,6 +317,9 @@ struct iwl_shared { struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; wait_queue_head_t wait_command_queue; + + /* ucode related variables */ + enum iwl_ucode_type ucode_type; }; /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 3c976262876..ed2a3d749b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -710,7 +710,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) return -ENOMSG; } size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]); - switch (priv->ucode_type) { + switch (priv->shrd->ucode_type) { case IWL_UCODE_REGULAR: maxsize = trans(priv)->ucode_rt.data.len; break; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index ee126f844a5..becd92173dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -595,7 +595,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) IWL_TRANS_GET_PCIE_TRANS(trans); base = priv->device_pointers.error_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { + if (trans->shrd->ucode_type == IWL_UCODE_INIT) { if (!base) base = priv->init_errlog_ptr; } else { @@ -607,7 +607,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) IWL_ERR(trans, "Not valid error log pointer 0x%08X for %s uCode\n", base, - (priv->ucode_type == IWL_UCODE_INIT) + (trans->shrd->ucode_type == IWL_UCODE_INIT) ? "Init" : "RT"); return; } @@ -710,7 +710,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, return pos; base = priv->device_pointers.log_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { + if (trans->shrd->ucode_type == IWL_UCODE_INIT) { if (!base) base = priv->init_evtlog_ptr; } else { @@ -824,7 +824,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, struct iwl_priv *priv = priv(trans); base = priv->device_pointers.log_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { + if (trans->shrd->ucode_type == IWL_UCODE_INIT) { logsize = priv->init_evtlog_size; if (!base) base = priv->init_evtlog_ptr; @@ -838,7 +838,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, IWL_ERR(trans, "Invalid event log pointer 0x%08X for %s uCode\n", base, - (priv->ucode_type == IWL_UCODE_INIT) + (trans->shrd->ucode_type == IWL_UCODE_INIT) ? "Init" : "RT"); return -EINVAL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 50227ebc0ee..4a29b8ab998 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -220,13 +220,6 @@ struct fw_img { struct fw_desc data; /* firmware data image */ }; -enum iwl_ucode_type { - IWL_UCODE_NONE, - IWL_UCODE_REGULAR, - IWL_UCODE_INIT, - IWL_UCODE_WOWLAN, -}; - /** * struct iwl_trans - transport common data * @ops - pointer to iwl_trans_ops diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 0da4b8ece11..1b23b99c474 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -579,27 +579,28 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, { struct iwl_notification_wait alive_wait; struct iwlagn_alive_data alive_data; + struct iwl_trans *trans = trans(priv); int ret; enum iwl_ucode_type old_type; - ret = iwl_trans_start_device(trans(priv)); + ret = iwl_trans_start_device(trans); if (ret) return ret; iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE, iwl_alive_fn, &alive_data); - old_type = priv->ucode_type; - priv->ucode_type = ucode_type; + old_type = trans->shrd->ucode_type; + trans->shrd->ucode_type = ucode_type; - ret = iwl_load_given_ucode(trans(priv), ucode_type); + ret = iwl_load_given_ucode(trans, ucode_type); if (ret) { - priv->ucode_type = old_type; + trans->shrd->ucode_type = old_type; iwlagn_remove_notification(priv, &alive_wait); return ret; } - iwl_trans_kick_nic(trans(priv)); + iwl_trans_kick_nic(trans); /* * Some things may run in the background now, but we @@ -607,13 +608,13 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, */ ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT); if (ret) { - priv->ucode_type = old_type; + trans->shrd->ucode_type = old_type; return ret; } if (!alive_data.valid) { IWL_ERR(priv, "Loaded ucode is not valid!\n"); - priv->ucode_type = old_type; + trans->shrd->ucode_type = old_type; return -EIO; } @@ -623,9 +624,9 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, * skip it for WoWLAN. */ if (ucode_type != IWL_UCODE_WOWLAN) { - ret = iwl_verify_ucode(trans(priv), ucode_type); + ret = iwl_verify_ucode(trans, ucode_type); if (ret) { - priv->ucode_type = old_type; + trans->shrd->ucode_type = old_type; return ret; } @@ -637,7 +638,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, if (ret) { IWL_WARN(priv, "Could not complete ALIVE transition: %d\n", ret); - priv->ucode_type = old_type; + trans->shrd->ucode_type = old_type; return ret; } @@ -655,7 +656,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) if (!trans(priv)->ucode_init.code.len) return 0; - if (priv->ucode_type != IWL_UCODE_NONE) + if (priv->shrd->ucode_type != IWL_UCODE_NONE) return 0; iwlagn_init_notification_wait(priv, &calib_wait, -- cgit v1.2.3-70-g09d2 From 79e3b16b7123018610f2754ce1bd219c5dd844f5 Mon Sep 17 00:00:00 2001 From: Don Fry Date: Fri, 2 Dec 2011 08:48:40 -0800 Subject: iwlwifi: move ucode notification from iwl_priv to iwl_shared Move the notification structures for ucode operations from the iwl_priv structure to the iwl_shared structure, with associated code changes. Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 51 ------------------- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 16 +++--- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 6 +-- drivers/net/wireless/iwlwifi/iwl-agn.h | 16 ------ drivers/net/wireless/iwlwifi/iwl-core.c | 15 +----- drivers/net/wireless/iwlwifi/iwl-dev.h | 33 ------------ drivers/net/wireless/iwlwifi/iwl-shared.h | 56 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-testmode.c | 6 +-- drivers/net/wireless/iwlwifi/iwl-ucode.c | 78 ++++++++++++++++++++++++++--- 9 files changed, 143 insertions(+), 134 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 0bc96221735..575d1bb8e8c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -934,57 +934,6 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) return ant; } -/* notification wait support */ -void iwlagn_init_notification_wait(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry, - u8 cmd, - void (*fn)(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - void *data), - void *fn_data) -{ - wait_entry->fn = fn; - wait_entry->fn_data = fn_data; - wait_entry->cmd = cmd; - wait_entry->triggered = false; - wait_entry->aborted = false; - - spin_lock_bh(&priv->notif_wait_lock); - list_add(&wait_entry->list, &priv->notif_waits); - spin_unlock_bh(&priv->notif_wait_lock); -} - -int iwlagn_wait_notification(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry, - unsigned long timeout) -{ - int ret; - - ret = wait_event_timeout(priv->notif_waitq, - wait_entry->triggered || wait_entry->aborted, - timeout); - - spin_lock_bh(&priv->notif_wait_lock); - list_del(&wait_entry->list); - spin_unlock_bh(&priv->notif_wait_lock); - - if (wait_entry->aborted) - return -EIO; - - /* return value is always >= 0 */ - if (ret <= 0) - return -ETIMEDOUT; - return 0; -} - -void iwlagn_remove_notification(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry) -{ - spin_lock_bh(&priv->notif_wait_lock); - list_del(&wait_entry->list); - spin_unlock_bh(&priv->notif_wait_lock); -} - #ifdef CONFIG_PM_SLEEP static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 087fd52e572..90c55ea4cc3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -1131,9 +1131,9 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; /* set up notification wait support */ - spin_lock_init(&priv->notif_wait_lock); - INIT_LIST_HEAD(&priv->notif_waits); - init_waitqueue_head(&priv->notif_waitq); + spin_lock_init(&priv->shrd->notif_wait_lock); + INIT_LIST_HEAD(&priv->shrd->notif_waits); + init_waitqueue_head(&priv->shrd->notif_waitq); /* Set up BT Rx handlers */ if (priv->cfg->lib->bt_rx_handler_setup) @@ -1152,11 +1152,11 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, * even if the RX handler consumes the RXB we have * access to it in the notification wait entry. */ - if (!list_empty(&priv->notif_waits)) { + if (!list_empty(&priv->shrd->notif_waits)) { struct iwl_notification_wait *w; - spin_lock(&priv->notif_wait_lock); - list_for_each_entry(w, &priv->notif_waits, list) { + spin_lock(&priv->shrd->notif_wait_lock); + list_for_each_entry(w, &priv->shrd->notif_waits, list) { if (w->cmd != pkt->hdr.cmd) continue; IWL_DEBUG_RX(priv, @@ -1167,9 +1167,9 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, if (w->fn) w->fn(priv, pkt, w->fn_data); } - spin_unlock(&priv->notif_wait_lock); + spin_unlock(&priv->shrd->notif_wait_lock); - wake_up_all(&priv->notif_waitq); + wake_up_all(&priv->shrd->notif_waitq); } if (priv->pre_rx_handler) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 00b38711c15..466e4ab544f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -60,7 +60,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, u8 old_dev_type = send->dev_type; int ret; - iwlagn_init_notification_wait(priv, &disable_wait, + iwl_init_notification_wait(priv->shrd, &disable_wait, REPLY_WIPAN_DEACTIVATION_COMPLETE, NULL, NULL); @@ -74,9 +74,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, if (ret) { IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); - iwlagn_remove_notification(priv, &disable_wait); + iwl_remove_notification(priv->shrd, &disable_wait); } else { - ret = iwlagn_wait_notification(priv, &disable_wait, HZ); + ret = iwl_wait_notification(priv->shrd, &disable_wait, HZ); if (ret) IWL_ERR(priv, "Timed out waiting for PAN disable\n"); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 0db0a8fb567..f2f10702754 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -356,22 +356,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); -/* notification wait support */ -void __acquires(wait_entry) -iwlagn_init_notification_wait(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry, - u8 cmd, - void (*fn)(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - void *data), - void *fn_data); -int __must_check __releases(wait_entry) -iwlagn_wait_notification(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry, - unsigned long timeout); -void __releases(wait_entry) -iwlagn_remove_notification(struct iwl_priv *priv, - struct iwl_notification_wait *wait_entry); extern int iwlagn_init_alive_start(struct iwl_priv *priv); extern int iwl_alive_start(struct iwl_priv *priv); /* svtool */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b24623b3bdb..3b6f48bfe0e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -836,19 +836,6 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, } #endif -static void iwlagn_abort_notification_waits(struct iwl_priv *priv) -{ - unsigned long flags; - struct iwl_notification_wait *wait_entry; - - spin_lock_irqsave(&priv->notif_wait_lock, flags); - list_for_each_entry(wait_entry, &priv->notif_waits, list) - wait_entry->aborted = true; - spin_unlock_irqrestore(&priv->notif_wait_lock, flags); - - wake_up_all(&priv->notif_waitq); -} - void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) { unsigned int reload_msec; @@ -860,7 +847,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) /* Cancel currently queued command. */ clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); - iwlagn_abort_notification_waits(priv); + iwl_abort_notification_waits(priv->shrd); /* Keep the restart process from trying to send host * commands by clearing the ready bit */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 0019a23d6d4..6f6a647d34f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -689,35 +689,6 @@ struct iwl_force_reset { */ #define IWLAGN_EXT_BEACON_TIME_POS 22 -/** - * struct iwl_notification_wait - notification wait entry - * @list: list head for global list - * @fn: function called with the notification - * @cmd: command ID - * - * This structure is not used directly, to wait for a - * notification declare it on the stack, and call - * iwlagn_init_notification_wait() with appropriate - * parameters. Then do whatever will cause the ucode - * to notify the driver, and to wait for that then - * call iwlagn_wait_notification(). - * - * Each notification is one-shot. If at some point we - * need to support multi-shot notifications (which - * can't be allocated on the stack) we need to modify - * the code for them. - */ -struct iwl_notification_wait { - struct list_head list; - - void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, - void *data); - void *fn_data; - - u8 cmd; - bool triggered, aborted; -}; - struct iwl_rxon_context { struct ieee80211_vif *vif; @@ -992,10 +963,6 @@ struct iwl_priv { /* counts reply_tx error */ struct reply_tx_error_statistics reply_tx_stats; struct reply_agg_tx_error_statistics reply_agg_tx_stats; - /* notification wait support */ - struct list_head notif_waits; - spinlock_t notif_wait_lock; - wait_queue_head_t notif_waitq; /* remain-on-channel offload support */ struct ieee80211_channel *hw_roc_channel; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index aa4905a2e79..39aa9cf5b84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -273,6 +273,35 @@ enum iwl_ucode_type { IWL_UCODE_WOWLAN, }; +/** + * struct iwl_notification_wait - notification wait entry + * @list: list head for global list + * @fn: function called with the notification + * @cmd: command ID + * + * This structure is not used directly, to wait for a + * notification declare it on the stack, and call + * iwlagn_init_notification_wait() with appropriate + * parameters. Then do whatever will cause the ucode + * to notify the driver, and to wait for that then + * call iwlagn_wait_notification(). + * + * Each notification is one-shot. If at some point we + * need to support multi-shot notifications (which + * can't be allocated on the stack) we need to modify + * the code for them. + */ +struct iwl_notification_wait { + struct list_head list; + + void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, + void *data); + void *fn_data; + + u8 cmd; + bool triggered, aborted; +}; + /** * struct iwl_shared - shared fields for all the layers of the driver * @@ -290,6 +319,10 @@ enum iwl_ucode_type { * @sta_lock: protects the station table. * If lock and sta_lock are needed, lock must be acquired first. * @mutex: + * @ucode_type: indicator of loaded ucode image + * @notif_waits: things waiting for notification + * @notif_wait_lock: lock protecting notification + * @notif_waitq: head of notification wait queue */ struct iwl_shared { #ifdef CONFIG_IWLWIFI_DEBUG @@ -320,6 +353,11 @@ struct iwl_shared { /* ucode related variables */ enum iwl_ucode_type ucode_type; + + /* notification wait support */ + struct list_head notif_waits; + spinlock_t notif_wait_lock; + wait_queue_head_t notif_waitq; }; /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ @@ -463,6 +501,24 @@ bool iwl_check_for_ct_kill(struct iwl_priv *priv); void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac); void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac); +/* notification wait support */ +void iwl_abort_notification_waits(struct iwl_shared *shrd); +void __acquires(wait_entry) +iwl_init_notification_wait(struct iwl_shared *shrd, + struct iwl_notification_wait *wait_entry, + u8 cmd, + void (*fn)(struct iwl_priv *priv, + struct iwl_rx_packet *pkt, + void *data), + void *fn_data); +int __must_check __releases(wait_entry) +iwl_wait_notification(struct iwl_shared *shrd, + struct iwl_notification_wait *wait_entry, + unsigned long timeout); +void __releases(wait_entry) +iwl_remove_notification(struct iwl_shared *shrd, + struct iwl_notification_wait *wait_entry); + #ifdef CONFIG_IWLWIFI_DEBUGFS void iwl_reset_traffic_log(struct iwl_priv *priv); #endif /* CONFIG_IWLWIFI_DEBUGFS */ diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index ed2a3d749b1..ff72dbcfd52 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -373,7 +373,7 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) struct iwl_notification_wait calib_wait; int ret; - iwlagn_init_notification_wait(priv, &calib_wait, + iwl_init_notification_wait(priv->shrd, &calib_wait, CALIBRATION_COMPLETE_NOTIFICATION, NULL, NULL); ret = iwlagn_init_alive_start(priv); @@ -383,14 +383,14 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) goto cfg_init_calib_error; } - ret = iwlagn_wait_notification(priv, &calib_wait, 2 * HZ); + ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ); if (ret) IWL_DEBUG_INFO(priv, "Error detecting" " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); return ret; cfg_init_calib_error: - iwlagn_remove_notification(priv, &calib_wait); + iwl_remove_notification(priv->shrd, &calib_wait); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 1b23b99c474..b365de457b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -571,6 +571,70 @@ static void iwl_alive_fn(struct iwl_priv *priv, alive_data->valid = palive->is_valid == UCODE_VALID_OK; } +/* notification wait support */ +void iwl_init_notification_wait(struct iwl_shared *shrd, + struct iwl_notification_wait *wait_entry, + u8 cmd, + void (*fn)(struct iwl_priv *priv, + struct iwl_rx_packet *pkt, + void *data), + void *fn_data) +{ + wait_entry->fn = fn; + wait_entry->fn_data = fn_data; + wait_entry->cmd = cmd; + wait_entry->triggered = false; + wait_entry->aborted = false; + + spin_lock_bh(&shrd->notif_wait_lock); + list_add(&wait_entry->list, &shrd->notif_waits); + spin_unlock_bh(&shrd->notif_wait_lock); +} + +int iwl_wait_notification(struct iwl_shared *shrd, + struct iwl_notification_wait *wait_entry, + unsigned long timeout) +{ + int ret; + + ret = wait_event_timeout(shrd->notif_waitq, + wait_entry->triggered || wait_entry->aborted, + timeout); + + spin_lock_bh(&shrd->notif_wait_lock); + list_del(&wait_entry->list); + spin_unlock_bh(&shrd->notif_wait_lock); + + if (wait_entry->aborted) + return -EIO; + + /* return value is always >= 0 */ + if (ret <= 0) + return -ETIMEDOUT; + return 0; +} + +void iwl_remove_notification(struct iwl_shared *shrd, + struct iwl_notification_wait *wait_entry) +{ + spin_lock_bh(&shrd->notif_wait_lock); + list_del(&wait_entry->list); + spin_unlock_bh(&shrd->notif_wait_lock); +} + +void iwl_abort_notification_waits(struct iwl_shared *shrd) +{ + unsigned long flags; + struct iwl_notification_wait *wait_entry; + + spin_lock_irqsave(&shrd->notif_wait_lock, flags); + list_for_each_entry(wait_entry, &shrd->notif_waits, list) + wait_entry->aborted = true; + spin_unlock_irqrestore(&shrd->notif_wait_lock, flags); + + wake_up_all(&shrd->notif_waitq); +} + #define UCODE_ALIVE_TIMEOUT HZ #define UCODE_CALIB_TIMEOUT (2*HZ) @@ -587,7 +651,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, if (ret) return ret; - iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE, + iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE, iwl_alive_fn, &alive_data); old_type = trans->shrd->ucode_type; @@ -596,7 +660,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, ret = iwl_load_given_ucode(trans, ucode_type); if (ret) { trans->shrd->ucode_type = old_type; - iwlagn_remove_notification(priv, &alive_wait); + iwl_remove_notification(trans->shrd, &alive_wait); return ret; } @@ -606,7 +670,8 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, * Some things may run in the background now, but we * just wait for the ALIVE notification here. */ - ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT); + ret = iwl_wait_notification(trans->shrd, &alive_wait, + UCODE_ALIVE_TIMEOUT); if (ret) { trans->shrd->ucode_type = old_type; return ret; @@ -659,7 +724,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) if (priv->shrd->ucode_type != IWL_UCODE_NONE) return 0; - iwlagn_init_notification_wait(priv, &calib_wait, + iwl_init_notification_wait(priv->shrd, &calib_wait, CALIBRATION_COMPLETE_NOTIFICATION, NULL, NULL); @@ -676,12 +741,13 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) * Some things may run in the background now, but we * just wait for the calibration complete notification. */ - ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT); + ret = iwl_wait_notification(priv->shrd, &calib_wait, + UCODE_CALIB_TIMEOUT); goto out; error: - iwlagn_remove_notification(priv, &calib_wait); + iwl_remove_notification(priv->shrd, &calib_wait); out: /* Whatever happened, stop the device */ iwl_trans_stop_device(trans(priv)); -- cgit v1.2.3-70-g09d2 From 439678f8b0fca7aeca06c6581e3679eef618721a Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 5 Dec 2011 19:13:39 +0100 Subject: bcma: pci: use fixed windows when possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some cores are mapped in the fixed way, they registers can be accessed all the time. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/bcma/host_pci.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 1b51d8b7ac8..b0994c0e05d 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -21,48 +21,58 @@ static void bcma_host_pci_switch_core(struct bcma_device *core) pr_debug("Switched to core: 0x%X\n", core->id.id); } -static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) +/* Provides access to the requested core. Returns base offset that has to be + * used. It makes use of fixed windows when possible. */ +static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core) { + switch (core->id.id) { + case BCMA_CORE_CHIPCOMMON: + return 3 * BCMA_CORE_SIZE; + case BCMA_CORE_PCIE: + return 2 * BCMA_CORE_SIZE; + } + if (core->bus->mapped_core != core) bcma_host_pci_switch_core(core); + return 0; +} + +static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) +{ + offset += bcma_host_pci_provide_access_to_core(core); return ioread8(core->bus->mmio + offset); } static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset) { - if (core->bus->mapped_core != core) - bcma_host_pci_switch_core(core); + offset += bcma_host_pci_provide_access_to_core(core); return ioread16(core->bus->mmio + offset); } static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset) { - if (core->bus->mapped_core != core) - bcma_host_pci_switch_core(core); + offset += bcma_host_pci_provide_access_to_core(core); return ioread32(core->bus->mmio + offset); } static void bcma_host_pci_write8(struct bcma_device *core, u16 offset, u8 value) { - if (core->bus->mapped_core != core) - bcma_host_pci_switch_core(core); + offset += bcma_host_pci_provide_access_to_core(core); iowrite8(value, core->bus->mmio + offset); } static void bcma_host_pci_write16(struct bcma_device *core, u16 offset, u16 value) { - if (core->bus->mapped_core != core) - bcma_host_pci_switch_core(core); + offset += bcma_host_pci_provide_access_to_core(core); iowrite16(value, core->bus->mmio + offset); } static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, u32 value) { - if (core->bus->mapped_core != core) - bcma_host_pci_switch_core(core); + offset += bcma_host_pci_provide_access_to_core(core); iowrite32(value, core->bus->mmio + offset); } -- cgit v1.2.3-70-g09d2 From c8e8868e3bf2ee0b6e606ce43af023b5f6edc954 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Nov 2011 13:08:40 +0100 Subject: ath9k: always issue a full hw reset after waking up from full-sleep mode After waking up from full sleep, registers are accessible, but rx/tx typically fails. A fast channel change will not recover from this, so ensure that a full-sleep -> wake transition is always followed by a full reset. The reason why this hasn't created any serious problems yet is that it's hidden by the (wrong) behavior of enabling/disabling the radio when the wiphy idle state changes. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 12 ++++++++++-- drivers/net/wireless/ath/ath9k/xmit.c | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index fd59c1f25c4..3733828e72b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -118,7 +118,7 @@ void ath9k_ps_restore(struct ath_softc *sc) if (--sc->ps_usecount != 0) goto unlock; - if (sc->ps_idle) + if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK)) mode = ATH9K_PM_FULL_SLEEP; else if (sc->ps_enabled && !(sc->ps_flags & (PS_WAIT_FOR_BEACON | @@ -332,7 +332,8 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, hchan = ah->curchan; } - if (fastcc && !ath9k_hw_check_alive(ah)) + if (fastcc && (ah->chip_fullsleep || + !ath9k_hw_check_alive(ah))) fastcc = false; if (!ath_prepare_reset(sc, retry_tx, flush)) @@ -1183,6 +1184,13 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) } } + /* + * Cannot tx while the hardware is in full sleep, it first needs a full + * chip reset to recover from that + */ + if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_FULL_SLEEP)) + goto exit; + if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) { /* * We are using PS-Poll and mac80211 can request TX while in diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 80639e3e4ac..9e65c3198ca 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1954,7 +1954,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, skb_pull(skb, padsize); } - if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { + if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) { sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; ath_dbg(common, ATH_DBG_PS, "Going back to sleep after having received TX status (0x%lx)\n", -- cgit v1.2.3-70-g09d2 From c0c1174144dd619456be5930d733028a055ef425 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Nov 2011 13:08:41 +0100 Subject: ath9k: rework power state handling Turning off the radio when mac80211 tells the driver that it's idle is not a good idea, as idle interfaces might still occasionally scan or send packets. The only time the radio can be safely turned off is when drv_stop has been called. In the mean time, use sc->ps_idle only to indicate network sleep vs full sleep. Move the LED GPIO changes out of the PCI suspend/resume path, the start/stop functions already take care of that. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 156 ++++++++++------------------------ drivers/net/wireless/ath/ath9k/pci.c | 21 +---- 2 files changed, 47 insertions(+), 130 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3733828e72b..8b0feecf3fa 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -887,82 +887,6 @@ chip_reset: #undef SCHED_INTR } -static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ieee80211_channel *channel = hw->conf.channel; - int r; - - ath9k_ps_wakeup(sc); - spin_lock_bh(&sc->sc_pcu_lock); - atomic_set(&ah->intr_ref_cnt, -1); - - ath9k_hw_configpcipowersave(ah, false); - - if (!ah->curchan) - ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah); - - r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); - if (r) { - ath_err(common, - "Unable to reset channel (%u MHz), reset status %d\n", - channel->center_freq, r); - } - - ath_complete_reset(sc, true); - - /* Enable LED */ - ath9k_hw_cfg_output(ah, ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(ah, ah->led_pin, 0); - - spin_unlock_bh(&sc->sc_pcu_lock); - - ath9k_ps_restore(sc); -} - -void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) -{ - struct ath_hw *ah = sc->sc_ah; - struct ieee80211_channel *channel = hw->conf.channel; - int r; - - ath9k_ps_wakeup(sc); - - ath_cancel_work(sc); - - spin_lock_bh(&sc->sc_pcu_lock); - - /* - * Keep the LED on when the radio is disabled - * during idle unassociated state. - */ - if (!sc->ps_idle) { - ath9k_hw_set_gpio(ah, ah->led_pin, 1); - ath9k_hw_cfg_gpio_input(ah, ah->led_pin); - } - - ath_prepare_reset(sc, false, true); - - if (!ah->curchan) - ah->curchan = ath9k_cmn_get_curchannel(hw, ah); - - r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); - if (r) { - ath_err(ath9k_hw_common(sc->sc_ah), - "Unable to reset channel (%u MHz), reset status %d\n", - channel->center_freq, r); - } - - ath9k_hw_phy_disable(ah); - - ath9k_hw_configpcipowersave(ah, true); - - spin_unlock_bh(&sc->sc_pcu_lock); - ath9k_ps_restore(sc); -} - static int ath_reset(struct ath_softc *sc, bool retry_tx) { int r; @@ -1098,6 +1022,9 @@ static int ath9k_start(struct ieee80211_hw *hw) * and then setup of the interrupt mask. */ spin_lock_bh(&sc->sc_pcu_lock); + + atomic_set(&ah->intr_ref_cnt, -1); + r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); if (r) { ath_err(common, @@ -1139,6 +1066,18 @@ static int ath9k_start(struct ieee80211_hw *hw) goto mutex_unlock; } + if (ah->led_pin >= 0) { + ath9k_hw_cfg_output(ah, ah->led_pin, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(ah, ah->led_pin, 0); + } + + /* + * Reset key cache to sane defaults (all entries cleared) instead of + * semi-random values after suspend/resume. + */ + ath9k_cmn_init_crypto(sc->sc_ah); + spin_unlock_bh(&sc->sc_pcu_lock); if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && @@ -1237,6 +1176,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); + bool prev_idle; mutex_lock(&sc->mutex); @@ -1267,35 +1207,45 @@ static void ath9k_stop(struct ieee80211_hw *hw) * before setting the invalid flag. */ ath9k_hw_disable_interrupts(ah); - if (!(sc->sc_flags & SC_OP_INVALID)) { - ath_drain_all_txq(sc, false); - ath_stoprecv(sc); - ath9k_hw_phy_disable(ah); - } else - sc->rx.rxlink = NULL; + spin_unlock_bh(&sc->sc_pcu_lock); + + /* we can now sync irq and kill any running tasklets, since we already + * disabled interrupts and not holding a spin lock */ + synchronize_irq(sc->irq); + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); + + prev_idle = sc->ps_idle; + sc->ps_idle = true; + + spin_lock_bh(&sc->sc_pcu_lock); + + if (ah->led_pin >= 0) { + ath9k_hw_set_gpio(ah, ah->led_pin, 1); + ath9k_hw_cfg_gpio_input(ah, ah->led_pin); + } + + ath_prepare_reset(sc, false, true); if (sc->rx.frag) { dev_kfree_skb_any(sc->rx.frag); sc->rx.frag = NULL; } - /* disable HAL and put h/w to sleep */ - ath9k_hw_disable(ah); + if (!ah->curchan) + ah->curchan = ath9k_cmn_get_curchannel(hw, ah); - spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); + ath9k_hw_phy_disable(ah); - /* we can now sync irq and kill any running tasklets, since we already - * disabled interrupts and not holding a spin lock */ - synchronize_irq(sc->irq); - tasklet_kill(&sc->intr_tq); - tasklet_kill(&sc->bcon_tasklet); + ath9k_hw_configpcipowersave(ah, true); - ath9k_ps_restore(sc); + spin_unlock_bh(&sc->sc_pcu_lock); - sc->ps_idle = true; - ath_radio_disable(sc, hw); + ath9k_ps_restore(sc); sc->sc_flags |= SC_OP_INVALID; + sc->ps_idle = prev_idle; mutex_unlock(&sc->mutex); @@ -1635,8 +1585,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_conf *conf = &hw->conf; - bool disable_radio = false; + ath9k_ps_wakeup(sc); mutex_lock(&sc->mutex); /* @@ -1645,16 +1595,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) * of the changes. Likewise we must only disable the radio towards * the end. */ - if (changed & IEEE80211_CONF_CHANGE_IDLE) { + if (changed & IEEE80211_CONF_CHANGE_IDLE) sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); - if (!sc->ps_idle) { - ath_radio_enable(sc, hw); - ath_dbg(common, ATH_DBG_CONFIG, - "not-idle: enabling radio\n"); - } else { - disable_radio = true; - } - } /* * We just prepare to enable PS. We have to wait until our AP has @@ -1760,18 +1702,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ath_dbg(common, ATH_DBG_CONFIG, "Set power: %d\n", conf->power_level); sc->config.txpowlimit = 2 * conf->power_level; - ath9k_ps_wakeup(sc); ath9k_cmn_update_txpow(ah, sc->curtxpow, sc->config.txpowlimit, &sc->curtxpow); - ath9k_ps_restore(sc); - } - - if (disable_radio) { - ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); - ath_radio_disable(sc, hw); } mutex_unlock(&sc->mutex); + ath9k_ps_restore(sc); return 0; } diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 2dcdf63cb39..a439edc5dc0 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -307,12 +307,11 @@ static int ath_pci_suspend(struct device *device) struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_softc *sc = hw->priv; - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); - /* The device has to be moved to FULLSLEEP forcibly. * Otherwise the chip never moved to full sleep, * when no interface is up. */ + ath9k_hw_disable(sc->sc_ah); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); return 0; @@ -321,8 +320,6 @@ static int ath_pci_suspend(struct device *device) static int ath_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath_softc *sc = hw->priv; u32 val; /* @@ -334,22 +331,6 @@ static int ath_pci_resume(struct device *device) if ((val & 0x0000ff00) != 0) pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - ath9k_ps_wakeup(sc); - /* Enable LED */ - ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); - - /* - * Reset key cache to sane defaults (all entries cleared) instead of - * semi-random values after suspend/resume. - */ - ath9k_cmn_init_crypto(sc->sc_ah); - ath9k_ps_restore(sc); - - sc->ps_idle = true; - ath_radio_disable(sc, hw); - return 0; } -- cgit v1.2.3-70-g09d2 From 9df0d6a20a4e6d15684cc8f2e3f0155be0801592 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Nov 2011 13:08:42 +0100 Subject: ath9k: only drop packets in drv_flush when asked to Recently more places in mac80211 call drv_flush to ensure proper order for state changes wrt. powersave, channel changes, etc. On some systems such calls lead to spurious logspam about failing to stop tx dma, as well as hardware resets that go along with that. Instead of dropping packets in a place where it's completely unnecessary, only do it when drop == true. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 8b0feecf3fa..36315c83d4c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2275,9 +2275,6 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) return; } - if (drop) - timeout = 1; - for (j = 0; j < timeout; j++) { bool npend = false; @@ -2295,21 +2292,22 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) } if (!npend) - goto out; + break; } - ath9k_ps_wakeup(sc); - spin_lock_bh(&sc->sc_pcu_lock); - drain_txq = ath_drain_all_txq(sc, false); - spin_unlock_bh(&sc->sc_pcu_lock); + if (drop) { + ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + drain_txq = ath_drain_all_txq(sc, false); + spin_unlock_bh(&sc->sc_pcu_lock); - if (!drain_txq) - ath_reset(sc, false); + if (!drain_txq) + ath_reset(sc, false); - ath9k_ps_restore(sc); - ieee80211_wake_queues(hw); + ath9k_ps_restore(sc); + ieee80211_wake_queues(hw); + } -out: ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); mutex_unlock(&sc->mutex); } -- cgit v1.2.3-70-g09d2 From daa1b6ee45170404efb3002ae2ff06e572f7ceba Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Nov 2011 13:08:43 +0100 Subject: ath9k: cancel all workqueue activity when going idle Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 36315c83d4c..714c7d82eb5 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1595,8 +1595,11 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) * of the changes. Likewise we must only disable the radio towards * the end. */ - if (changed & IEEE80211_CONF_CHANGE_IDLE) + if (changed & IEEE80211_CONF_CHANGE_IDLE) { sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); + if (sc->ps_idle) + ath_cancel_work(sc); + } /* * We just prepare to enable PS. We have to wait until our AP has -- cgit v1.2.3-70-g09d2 From a9b2ce03b2a071420c10f3873869480fbb7f4493 Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Fri, 2 Dec 2011 22:39:14 -0500 Subject: ath9k: trivial: cosmetic fix in calibration debug log Add missed space and change typo in calibration debugging log. Signed-off-by: Nikolay Martynov Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_calib.c | 2 +- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 88279e325dc..157337febc2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -203,7 +203,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) i); ath_dbg(common, ATH_DBG_CALIBRATE, - "Orignal: Chn %diq_corr_meas = 0x%08x\n", + "Original: Chn %d iq_corr_meas = 0x%08x\n", i, ah->totalIqCorrMeas[i]); iqCorrNeg = 0; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index ddeba8693fa..23b3a6c5780 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -226,7 +226,7 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) i); ath_dbg(common, ATH_DBG_CALIBRATE, - "Orignal: Chn %diq_corr_meas = 0x%08x\n", + "Original: Chn %d iq_corr_meas = 0x%08x\n", i, ah->totalIqCorrMeas[i]); iqCorrNeg = 0; -- cgit v1.2.3-70-g09d2 From 86951359c1ee35dbae5e11d7cd959e2cb8e6051f Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Fri, 2 Dec 2011 22:39:15 -0500 Subject: ath9k: change calibration debug log to output all calibration types To help debugging write a log entry when long calibration, short calibration or ANI is performed. Signed-off-by: Nikolay Martynov Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 714c7d82eb5..8c36362da1e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -562,7 +562,6 @@ void ath_ani_calibrate(unsigned long data) /* Long calibration runs independently of short calibration. */ if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { longcal = true; - ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); common->ani.longcal_timer = timestamp; } @@ -570,8 +569,6 @@ void ath_ani_calibrate(unsigned long data) if (!common->ani.caldone) { if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { shortcal = true; - ath_dbg(common, ATH_DBG_ANI, - "shortcal @%lu\n", jiffies); common->ani.shortcal_timer = timestamp; common->ani.resetcal_timer = timestamp; } @@ -606,6 +603,11 @@ void ath_ani_calibrate(unsigned long data) ah->rxchainmask, longcal); } + ath_dbg(common, ATH_DBG_ANI, + "Calibration @%lu finished: %s %s %s, caldone: %s\n", jiffies, + longcal ? "long" : "", shortcal ? "short" : "", + aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); + ath9k_ps_restore(sc); set_timer: -- cgit v1.2.3-70-g09d2 From 4279425cef58808c0cdc616b8fff17c8308617bd Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Fri, 2 Dec 2011 22:39:16 -0500 Subject: ath9k: use config.enable_ani to check if ani should be performed Currently in ath9k code there is an attempt which is meant to disable ANI for ar9100 and ar9340. But it doesn't really achieve this. All it does is disable ANI init and setup (i.e. calls to ath9k_hw_ani_setup and ath9k_hw_ani_init). Since ath9k_hw_ani_setup is not called ah->config.ani_poll_interval is never initialized (i.e. it is always zero) and ath_ani_calibrate always executes ANI procedures (over uninitialized ANI parameters). Moreover, ath_ani_calibrate is being called each 1ms because common->ani.timer is set to zero interval because ah->config.ani_poll_interval==0 (and thus smallest value of all intervals). Normally it should not be called this often. This patch changes the code so config.enable_ani is used to check if ANI should be performed. config.enable_ani is initialized to true by default. This patch sets it to false for ar9100 and ar9340. Signed-off-by: Nikolay Martynov Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 5 +++-- drivers/net/wireless/ath/ath9k/hw.c | 6 +++++- drivers/net/wireless/ath/ath9k/main.c | 5 +++-- 3 files changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 0b9a0e8a495..f8ce4ea6f65 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -808,7 +808,8 @@ void ath9k_htc_ani_work(struct work_struct *work) } /* Verify whether we must check ANI */ - if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { + if (ah->config.enable_ani && + (timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { aniflag = true; common->ani.checkani_timer = timestamp; } @@ -838,7 +839,7 @@ set_timer: * short calibration and long calibration. */ cal_interval = ATH_LONG_CALINTERVAL; - if (priv->ah->config.enable_ani) + if (ah->config.enable_ani) cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); if (!common->ani.caldone) cal_interval = min(cal_interval, (u32)short_cal_interval); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index caf572cf270..9871072bbf0 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -504,7 +504,7 @@ static int ath9k_hw_post_init(struct ath_hw *ah) return ecode; } - if (!AR_SREV_9100(ah) && !AR_SREV_9340(ah)) { + if (ah->config.enable_ani) { ath9k_hw_ani_setup(ah); ath9k_hw_ani_init(ah); } @@ -610,6 +610,10 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (!AR_SREV_9300_20_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_MRC_CCK; + /* disable ANI for 9100 and 9340 */ + if (AR_SREV_9100(ah) || AR_SREV_9340(ah)) + ah->config.enable_ani = false; + ath9k_hw_init_mode_regs(ah); if (!ah->is_pciexpress) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 8c36362da1e..5007297c944 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -582,8 +582,9 @@ void ath_ani_calibrate(unsigned long data) } /* Verify whether we must check ANI */ - if ((timestamp - common->ani.checkani_timer) >= - ah->config.ani_poll_interval) { + if (sc->sc_ah->config.enable_ani + && (timestamp - common->ani.checkani_timer) >= + ah->config.ani_poll_interval) { aniflag = true; common->ani.checkani_timer = timestamp; } -- cgit v1.2.3-70-g09d2 From 4f17c48e3902c823e4af68d2de9546f5b707533d Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Tue, 6 Dec 2011 21:57:17 -0500 Subject: ath9k: enable ANI for ar9100 chips Enable ANI for ar9100 since it seems to be working fine (and as a matter of fact ANI was always performed for ar9100 since code which was supposed to disable it didn't achieve this goal). This patch sets config.enable_ani to default (true) value for ar9100. Signed-off-by: Nikolay Martynov Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 9871072bbf0..7f8fc65f2cb 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -610,8 +610,8 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (!AR_SREV_9300_20_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_MRC_CCK; - /* disable ANI for 9100 and 9340 */ - if (AR_SREV_9100(ah) || AR_SREV_9340(ah)) + /* disable ANI for 9340 */ + if (AR_SREV_9340(ah)) ah->config.enable_ani = false; ath9k_hw_init_mode_regs(ah); -- cgit v1.2.3-70-g09d2 From abc47470ef63cdde2efdf358ae373afb16f358c0 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 6 Dec 2011 12:15:05 +0200 Subject: 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 | 72 +++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 61fff45686a..2f9ebff2ded 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]); + mutex_lock(&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) - return -ENOMEM; + if (!cmd) { + ret = -ENOMEM; + goto out_sleep; + } - mutex_lock(&wl->mutex); ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd)); - mutex_unlock(&wl->mutex); - 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[]) -- cgit v1.2.3-70-g09d2 From 188e7f54c38b9bf144ddc81b4b734cb6ea49f31e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 6 Dec 2011 12:15:06 +0200 Subject: 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(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index d1416752fee..2f7bfa86c8c 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) -- cgit v1.2.3-70-g09d2 From 3dbb5846db1f5df3619b927cc2a7dcaf65a38f1e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 6 Dec 2011 12:15:07 +0200 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 2f9ebff2ded..978cf2de713 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); -- cgit v1.2.3-70-g09d2 From 1b04b739f4c1d053bebb29657fb69bf03f180a97 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Wed, 7 Dec 2011 12:37:04 +0200 Subject: 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(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 330d6788a91..8599dab1fe2 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, -- cgit v1.2.3-70-g09d2 From cf00f379d82d170712150588accd2ebe316c2226 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 8 Dec 2011 16:15:58 -0500 Subject: wl12xx: silence tx_attr uninitialized warning in wl1271_tx_fill_hdr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC [M] drivers/net/wireless/wl12xx/tx.o drivers/net/wireless/wl12xx/tx.c: In function ‘wl1271_tx_fill_hdr’: drivers/net/wireless/wl12xx/tx.c:288:6: warning: ‘tx_attr’ may be used uninitialized in this function Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 36eb0d66fd6..7d727ee6ddf 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -285,7 +285,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct wl1271_tx_hw_descr *desc; int aligned_len, ac, rate_idx; s64 hosttime; - u16 tx_attr; + u16 tx_attr = 0; bool is_dummy; desc = (struct wl1271_tx_hw_descr *) skb->data; -- cgit v1.2.3-70-g09d2 From b6a27d1e6b8e163dee054c9cd03639c62756c2e2 Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Thu, 8 Dec 2011 21:43:39 -0500 Subject: iwlwifi regression in 20111205 merge It looks like the regression was introduced between 20111202 and 20111205 (linux-next tree). Symptoms: connection to AP seem to be established, but no data goes though it in any way. Tested on intel 5300. Peek at the changes have shown that it looks like at least part of the code wasn't merged properly. It was originally committed into iwl_agn.c but code in question was moved to iwl-mac80211.c. This patch puts code in place and my card works again. Signed-off-by: Nikolay Martynov Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 794b735264e..55308b88faa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -517,6 +517,17 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } + switch (key->cipher) { + case WLAN_CIPHER_SUITE_TKIP: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + /* fall through */ + case WLAN_CIPHER_SUITE_CCMP: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + break; + default: + break; + } + /* * We could program these keys into the hardware as well, but we * don't expect much multicast traffic in IBSS and having keys -- cgit v1.2.3-70-g09d2