From 5af70c864a1539bd1d3f3fcb04ab9558491c9103 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 28 Feb 2012 00:41:28 +0200 Subject: wl12xx: set the ELP entry delay to the FW dyn-ps timeout With PSM handled in FW, the checks in wl1271_elp_work() are always true. Thus during active traffic we constantly enter and exit ELP (many times per second). As each ELP exit takes ~10ms, this can have an adverse effect on throughput and interactivity. Set the ELP timeout to the dyn-ps timeout. This period is longer and avoids the above problem. It also makes sense to stay out of ELP while we are awake on the network, to minimize delays in Tx/Rx. The same thing was done by the mac80211 dynamic-ps mechanism before the FW DPS changes. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/ps.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index 23d67501c50a..78f598b4f97b 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -69,8 +69,6 @@ out: mutex_unlock(&wl->mutex); } -#define ELP_ENTRY_DELAY 5 - /* Routines to toggle sleep mode while in ELP */ void wl1271_ps_elp_sleep(struct wl1271 *wl) { @@ -90,7 +88,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) } ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, - msecs_to_jiffies(ELP_ENTRY_DELAY)); + msecs_to_jiffies(wl->conf.conn.dynamic_ps_timeout)); } int wl1271_ps_elp_wakeup(struct wl1271 *wl) -- cgit v1.2.3-70-g09d2 From 0b0e32b792b4077c113ae70d6de12b5f301e0882 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 28 Feb 2012 00:41:29 +0200 Subject: wl12xx: change bits in the link_map under spin lock These bits are used in op_tx to determine if a packet should be dropped. As such we should use the spin lock to sync the state. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index b776d9d5efe8..ef994dacf8d2 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -459,23 +459,32 @@ out: int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) { + unsigned long flags; u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS); if (link >= WL12XX_MAX_LINKS) return -EBUSY; + /* these bits are used by op_tx */ + spin_lock_irqsave(&wl->wl_lock, flags); __set_bit(link, wl->links_map); __set_bit(link, wlvif->links_map); + spin_unlock_irqrestore(&wl->wl_lock, flags); *hlid = link; return 0; } void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) { + unsigned long flags; + if (*hlid == WL12XX_INVALID_LINK_ID) return; + /* these bits are used by op_tx */ + spin_lock_irqsave(&wl->wl_lock, flags); __clear_bit(*hlid, wl->links_map); __clear_bit(*hlid, wlvif->links_map); + spin_unlock_irqrestore(&wl->wl_lock, flags); *hlid = WL12XX_INVALID_LINK_ID; } -- cgit v1.2.3-70-g09d2 From 6246ca003f2560e30b9696757efc271284b809f6 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 28 Feb 2012 00:41:30 +0200 Subject: wl12xx: reset link Tx queues when freeing it Before, the link was first freed (invalidating it in the map), and later on vif removal, all valid wlvif-related links were reset. Since these links were already invalid, we failed to reset them. The bug was made worse by op_stop, which set the tx_queue_count to 0 arbitrarily. This resulted in a negative tx_queue_count in some scenarios. Fix this by resetting the Tx-queues of a link when freeing it. Add a WARN_ON and reset all link Tx-queues in op_stop, to avoid a negative tx_queue_count. [changed WARN_ON to WARN_ON_ONCE -- Luca] Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 7 +++++++ drivers/net/wireless/wl12xx/main.c | 1 - drivers/net/wireless/wl12xx/tx.c | 13 ++++++++++--- 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index ef994dacf8d2..ae1f3d7f34d2 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -485,6 +485,13 @@ void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) __clear_bit(*hlid, wl->links_map); __clear_bit(*hlid, wlvif->links_map); spin_unlock_irqrestore(&wl->wl_lock, flags); + + /* + * At this point op_tx() will not add more packets to the queues. We + * can purge them. + */ + wl1271_tx_reset_link_queues(wl, *hlid); + *hlid = WL12XX_INVALID_LINK_ID; } diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index adf9bbcf88fd..712e38530153 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -4228,7 +4228,6 @@ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) 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); diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 6446e4d3e8f9..8f5ab047aec8 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -527,6 +527,7 @@ static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl, if (skb) { int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); spin_lock_irqsave(&wl->wl_lock, flags); + WARN_ON_ONCE(wl->tx_queue_count[q] <= 0); wl->tx_queue_count[q]--; spin_unlock_irqrestore(&wl->wl_lock, flags); } @@ -602,6 +603,7 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) skb = wl->dummy_packet; q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); spin_lock_irqsave(&wl->wl_lock, flags); + WARN_ON_ONCE(wl->tx_queue_count[q] <= 0); wl->tx_queue_count[q]--; spin_unlock_irqrestore(&wl->wl_lock, flags); } @@ -959,7 +961,6 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif) else wlvif->sta.ba_rx_bitmap = 0; - wl1271_tx_reset_link_queues(wl, i); wl->links[i].allocated_pkts = 0; wl->links[i].prev_freed_pkts = 0; } @@ -973,8 +974,14 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues) struct sk_buff *skb; struct ieee80211_tx_info *info; - for (i = 0; i < NUM_TX_QUEUES; i++) - wl->tx_queue_count[i] = 0; + /* only reset the queues if something bad happened */ + if (WARN_ON_ONCE(wl1271_tx_total_queue_count(wl) != 0)) { + for (i = 0; i < WL12XX_MAX_LINKS; i++) + wl1271_tx_reset_link_queues(wl, i); + + for (i = 0; i < NUM_TX_QUEUES; i++) + wl->tx_queue_count[i] = 0; + } wl->stopped_queues_map = 0; -- cgit v1.2.3-70-g09d2 From 49c9cd26445aa8bc8348c384c943b758c57c47a9 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 28 Feb 2012 00:41:31 +0200 Subject: wl12xx: avoid starving the system hlid Re-factor the Tx scheduler so that the system_hlid is taken into account before restarting an iteration over the wlvifs. Previously this hlid had a lower priority and would starve if some wlvif had many packets. In addition avoid iterating over wlvifs past last_wlvif when performing the a second pass. If we had packets in those wlvifs they would have been found earlier. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/tx.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 8f5ab047aec8..6640c3975cfb 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -572,6 +572,7 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) struct wl12xx_vif *wlvif = wl->last_wlvif; struct sk_buff *skb = NULL; + /* continue from last wlvif (round robin) */ if (wlvif) { wl12xx_for_each_wlvif_continue(wl, wlvif) { skb = wl12xx_vif_skb_dequeue(wl, wlvif); @@ -582,7 +583,11 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) } } - /* do another pass */ + /* dequeue from the system HLID before the restarting wlvif list */ + if (!skb) + skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[wl->system_hlid]); + + /* do a new pass over the wlvif list */ if (!skb) { wl12xx_for_each_wlvif(wl, wlvif) { skb = wl12xx_vif_skb_dequeue(wl, wlvif); @@ -590,12 +595,16 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) wl->last_wlvif = wlvif; break; } + + /* + * No need to continue after last_wlvif. The previous + * pass should have found it. + */ + if (wlvif == wl->last_wlvif) + break; } } - 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; -- cgit v1.2.3-70-g09d2 From 18aa755b84715f36e2811734f95cb822bcacfd89 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 28 Feb 2012 00:41:32 +0200 Subject: wl12xx: flush all Tx queues on tx_flush timeout Ensure our queues are empty at the end of a tx_flush(), in case we timeout on passively waiting for them. This makes sure no left-overs are transmitted when we are on the wrong channel. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/tx.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 6640c3975cfb..8f78fddcb723 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -1040,6 +1040,7 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues) void wl1271_tx_flush(struct wl1271 *wl) { unsigned long timeout; + int i; timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT); while (!time_after(jiffies, timeout)) { @@ -1057,6 +1058,12 @@ void wl1271_tx_flush(struct wl1271 *wl) } wl1271_warning("Unable to flush all TX buffers, timed out."); + + /* forcibly flush all Tx buffers on our queues */ + mutex_lock(&wl->mutex); + for (i = 0; i < WL12XX_MAX_LINKS; i++) + wl1271_tx_reset_link_queues(wl, i); + mutex_unlock(&wl->mutex); } u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set) -- cgit v1.2.3-70-g09d2 From b9239b665889582835fbd54730902eee08aa42d7 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 28 Feb 2012 00:41:33 +0200 Subject: wl12xx: flush Tx during suspend and 802.11h chan switch Flush our Tx queues before suspending or changing the channel due to a channel_switch element in the AP beacon. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 712e38530153..ad1a4addaab5 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1737,6 +1737,8 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); WARN_ON(!wow || !wow->any); + wl1271_tx_flush(wl); + wl->wow_enabled = true; wl12xx_for_each_wlvif(wl, wlvif) { ret = wl1271_configure_suspend(wl, wlvif); @@ -4496,6 +4498,8 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch"); + wl1271_tx_flush(wl); + mutex_lock(&wl->mutex); if (unlikely(wl->state == WL1271_STATE_OFF)) { -- cgit v1.2.3-70-g09d2 From d7b63b9fc7ee73e75a4c7fdb899a7c43ded7d25f Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 28 Feb 2012 00:41:34 +0200 Subject: wl12xx: increase dynamic PS timeout to 200ms This ensures the user won't encounter lag associated with getting in and out of PSM when the card is in use. 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 ad1a4addaab5..418b2b82c185 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -246,7 +246,7 @@ static struct conf_drv_settings default_conf = { .psm_entry_retries = 8, .psm_exit_retries = 16, .psm_entry_nullfunc_retries = 3, - .dynamic_ps_timeout = 100, + .dynamic_ps_timeout = 200, .forced_ps = false, .keep_alive_interval = 55000, .max_listen_interval = 20, -- cgit v1.2.3-70-g09d2 From 349345a4ec631cd98767b58b065535dd2278697c Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 4 Mar 2012 10:55:45 +0200 Subject: wl12xx: don't start dev role on ibss vifs device role is used for scanning and sending packets before connection. however, since we don't need to send packets before ibss creation, there is no need to start the device on idle-off. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 418b2b82c185..93636ea84dae 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3746,10 +3746,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, ibss_joined = true; } else { if (test_and_clear_bit(WLVIF_FLAG_IBSS_JOINED, - &wlvif->flags)) { + &wlvif->flags)) wl1271_unjoin(wl, wlvif); - wl12xx_start_dev(wl, wlvif); - } } } @@ -3767,7 +3765,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, do_join = true; } - if (changed & BSS_CHANGED_IDLE) { + if (changed & BSS_CHANGED_IDLE && !is_ibss) { ret = wl1271_sta_handle_idle(wl, wlvif, bss_conf->idle); if (ret < 0) wl1271_warning("idle mode change failed %d", ret); -- cgit v1.2.3-70-g09d2 From 8a6a84a471f7de1845174d1dd66b35074d9d9398 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 4 Mar 2012 10:55:46 +0200 Subject: wl12xx: consider bss_conf->idle instead of hw->conf.flags On disassociation, check only whether the current vif is idle, instead of checking whether the device is idle. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 93636ea84dae..b771106c0a1e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3901,7 +3901,6 @@ sta_not_found: /* restore the bssid filter and go to dummy bssid */ if (was_assoc) { - u32 conf_flags = wl->hw->conf.flags; /* * we might have to disable roc, if there was * no IF_OPER_UP notification. @@ -3924,7 +3923,7 @@ sta_not_found: } wl1271_unjoin(wl, wlvif); - if (!(conf_flags & IEEE80211_CONF_IDLE)) + if (!bss_conf->idle) wl12xx_start_dev(wl, wlvif); } } -- cgit v1.2.3-70-g09d2 From 2d6cf2b51fa3492c479c6d1f86496e120b51e1d8 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 4 Mar 2012 10:55:47 +0200 Subject: wl12xx: implement sta_state callback Implement sta_state callback instead of the sta_add/remove callbacks. Update the fw regarding peer state and ht caps only after the station was authorized. Otherwise, the fw might try establishing BA session before the sta is authorized. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 137 ++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index b771106c0a1e..8569ac3760df 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -4233,100 +4233,128 @@ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) wl->active_sta_count--; } -static int wl1271_op_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static int wl12xx_sta_add(struct wl1271 *wl, + struct wl12xx_vif *wlvif, + 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; u8 hlid; - mutex_lock(&wl->mutex); - - if (unlikely(wl->state == WL1271_STATE_OFF)) - goto out; - - if (wlvif->bss_type != BSS_TYPE_AP_BSS) - goto out; - wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); ret = wl1271_allocate_sta(wl, wlvif, sta); if (ret < 0) - goto out; + return ret; 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; - ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid); if (ret < 0) - goto out_sleep; + wl1271_free_sta(wl, wlvif, hlid); - ret = wl12xx_cmd_set_peer_state(wl, hlid); - if (ret < 0) - goto out_sleep; + return ret; +} - ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, hlid); - if (ret < 0) - goto out_sleep; +static int wl12xx_sta_remove(struct wl1271 *wl, + struct wl12xx_vif *wlvif, + struct ieee80211_sta *sta) +{ + struct wl1271_station *wl_sta; + int ret = 0, id; -out_sleep: - wl1271_ps_elp_sleep(wl); + wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid); + + wl_sta = (struct wl1271_station *)sta->drv_priv; + id = wl_sta->hlid; + if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map))) + return -EINVAL; -out_free_sta: + ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid); if (ret < 0) - wl1271_free_sta(wl, wlvif, hlid); + return ret; -out: - mutex_unlock(&wl->mutex); + wl1271_free_sta(wl, wlvif, wl_sta->hlid); return ret; } -static int wl1271_op_sta_remove(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static int wl12xx_update_sta_state(struct wl1271 *wl, + struct wl12xx_vif *wlvif, + struct ieee80211_sta *sta, + enum ieee80211_sta_state old_state, + enum ieee80211_sta_state new_state) { - struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271_station *wl_sta; - int ret = 0, id; + u8 hlid; + bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; + bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; + int ret; - mutex_lock(&wl->mutex); + wl_sta = (struct wl1271_station *)sta->drv_priv; + hlid = wl_sta->hlid; - if (unlikely(wl->state == WL1271_STATE_OFF)) - goto out; + /* Add station (AP mode) */ + if (is_ap && + old_state == IEEE80211_STA_NOTEXIST && + new_state == IEEE80211_STA_NONE) + return wl12xx_sta_add(wl, wlvif, sta); + + /* Remove station (AP mode) */ + if (is_ap && + old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST) { + /* must not fail */ + wl12xx_sta_remove(wl, wlvif, sta); + return 0; + } - if (wlvif->bss_type != BSS_TYPE_AP_BSS) - goto out; + /* Authorize station (AP mode) */ + if (is_ap && + new_state == IEEE80211_STA_AUTHORIZED) { + ret = wl12xx_cmd_set_peer_state(wl, hlid); + if (ret < 0) + return ret; - wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid); + ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, + hlid); + return ret; + } - wl_sta = (struct wl1271_station *)sta->drv_priv; - id = wl_sta->hlid; - if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map))) + return 0; +} + +static int wl12xx_op_sta_state(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + enum ieee80211_sta_state old_state, + enum ieee80211_sta_state new_state) +{ + struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + int ret; + + wl1271_debug(DEBUG_MAC80211, "mac80211 sta %d state=%d->%d", + sta->aid, old_state, new_state); + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state == WL1271_STATE_OFF)) { + ret = -EBUSY; goto out; + } ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; - ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid); - if (ret < 0) - goto out_sleep; + ret = wl12xx_update_sta_state(wl, wlvif, sta, old_state, new_state); - wl1271_free_sta(wl, wlvif, wl_sta->hlid); - -out_sleep: wl1271_ps_elp_sleep(wl); - out: mutex_unlock(&wl->mutex); + if (new_state < old_state) + return 0; return ret; } @@ -4795,8 +4823,7 @@ static const struct ieee80211_ops wl1271_ops = { .conf_tx = wl1271_op_conf_tx, .get_tsf = wl1271_op_get_tsf, .get_survey = wl1271_op_get_survey, - .sta_add = wl1271_op_sta_add, - .sta_remove = wl1271_op_sta_remove, + .sta_state = wl12xx_op_sta_state, .ampdu_action = wl1271_op_ampdu_action, .tx_frames_pending = wl1271_tx_frames_pending, .set_bitrate_mask = wl12xx_set_bitrate_mask, -- cgit v1.2.3-70-g09d2 From 9fd6f21ba295810e36299981411f62719364d9e9 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 4 Mar 2012 10:55:48 +0200 Subject: wl12xx: set authorized AP on sta_state notification wl12xx currently looks for AP authorization by registering a netdev notifier and waiting for the IF_OPER_UP notification, which is quite cumbersome. Use the newly introduced sta_state callback (waiting for assoc -> auth notification) instead, in order to simplify it. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 117 +++++++---------------------------- drivers/net/wireless/wl12xx/wl12xx.h | 3 +- 2 files changed, 23 insertions(+), 97 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8569ac3760df..a330b0c0ae61 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -392,15 +392,15 @@ 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 DEFINE_MUTEX(wl_list_mutex); -static LIST_HEAD(wl_list); - -static int wl1271_check_operstate(struct wl1271 *wl, struct wl12xx_vif *wlvif, - unsigned char operstate) +static int wl12xx_set_authorized(struct wl1271 *wl, + struct wl12xx_vif *wlvif) { int ret; - if (operstate != IF_OPER_UP) + if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS)) + return -EINVAL; + + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) return 0; if (test_and_set_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags)) @@ -415,76 +415,6 @@ static int wl1271_check_operstate(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_info("Association completed."); return 0; } -static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, - void *arg) -{ - struct net_device *dev = arg; - struct wireless_dev *wdev; - struct wiphy *wiphy; - 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. */ - if (what != NETDEV_CHANGE) - return NOTIFY_DONE; - - wdev = dev->ieee80211_ptr; - if (wdev == NULL) - return NOTIFY_DONE; - - wiphy = wdev->wiphy; - if (wiphy == NULL) - return NOTIFY_DONE; - - hw = wiphy_priv(wiphy); - if (hw == NULL) - return NOTIFY_DONE; - - wl_temp = hw->priv; - mutex_lock(&wl_list_mutex); - list_for_each_entry(wl, &wl_list, list) { - if (wl == wl_temp) - break; - } - mutex_unlock(&wl_list_mutex); - if (wl != wl_temp) - return NOTIFY_DONE; - - mutex_lock(&wl->mutex); - - if (wl->state == WL1271_STATE_OFF) - goto out; - - if (dev->operstate != IF_OPER_UP) - goto out; - /* - * The correct behavior should be just getting the appropriate wlvif - * from the given dev, but currently we don't have a mac80211 - * interface for it. - */ - wl12xx_for_each_wlvif_sta(wl, wlvif) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); - - if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) - continue; - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - wl1271_check_operstate(wl, wlvif, - ieee80211_get_operstate(vif)); - - wl1271_ps_elp_sleep(wl); - } -out: - mutex_unlock(&wl->mutex); - - return NOTIFY_OK; -} static int wl1271_reg_notify(struct wiphy *wiphy, struct regulatory_request *request) @@ -1626,10 +1556,6 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) } -static struct notifier_block wl1271_dev_notifier = { - .notifier_call = wl1271_dev_notify, -}; - #ifdef CONFIG_PM static int wl1271_configure_suspend_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) @@ -1856,10 +1782,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->state = WL1271_STATE_OFF; mutex_unlock(&wl->mutex); - mutex_lock(&wl_list_mutex); - list_del(&wl->list); - mutex_unlock(&wl_list_mutex); - wl1271_flush_deferred_work(wl); cancel_delayed_work_sync(&wl->scan_complete_work); cancel_work_sync(&wl->netstack_work); @@ -2270,11 +2192,6 @@ out: out_unlock: mutex_unlock(&wl->mutex); - mutex_lock(&wl_list_mutex); - if (!ret) - list_add(&wl->list, &wl_list); - mutex_unlock(&wl_list_mutex); - return ret; } @@ -3967,8 +3884,8 @@ sta_not_found: if (ret < 0) goto out; - wl1271_check_operstate(wl, wlvif, - ieee80211_get_operstate(vif)); + if (test_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags)) + wl12xx_set_authorized(wl, wlvif); } /* * stop device role if started (we might already be in @@ -4321,6 +4238,20 @@ static int wl12xx_update_sta_state(struct wl1271 *wl, return ret; } + /* Authorize station */ + if (is_sta && + new_state == IEEE80211_STA_AUTHORIZED) { + set_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags); + return wl12xx_set_authorized(wl, wlvif); + } + + if (is_sta && + old_state == IEEE80211_STA_AUTHORIZED && + new_state == IEEE80211_STA_ASSOC) { + clear_bit(WLVIF_FLAG_STA_AUTHORIZED, &wlvif->flags); + return 0; + } + return 0; } @@ -5144,8 +5075,6 @@ static int wl1271_register_hw(struct wl1271 *wl) wl1271_debugfs_init(wl); - register_netdevice_notifier(&wl1271_dev_notifier); - wl1271_notice("loaded"); out: @@ -5157,7 +5086,6 @@ static void wl1271_unregister_hw(struct wl1271 *wl) if (wl->plt) wl1271_plt_stop(wl); - unregister_netdevice_notifier(&wl1271_dev_notifier); ieee80211_unregister_hw(wl->hw); wl->mac80211_registered = false; @@ -5278,7 +5206,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) wl = hw->priv; memset(wl, 0, sizeof(*wl)); - INIT_LIST_HEAD(&wl->list); INIT_LIST_HEAD(&wl->wlvif_list); wl->hw = hw; diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 90352415e2aa..b26b1be9a98b 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -265,6 +265,7 @@ enum wl12xx_flags { enum wl12xx_vif_flags { WLVIF_FLAG_INITIALIZED, WLVIF_FLAG_STA_ASSOCIATED, + WLVIF_FLAG_STA_AUTHORIZED, WLVIF_FLAG_IBSS_JOINED, WLVIF_FLAG_AP_STARTED, WLVIF_FLAG_IN_PS, @@ -452,8 +453,6 @@ struct wl1271 { bool enable_11a; - struct list_head list; - /* Most recently reported noise in dBm */ s8 noise; -- cgit v1.2.3-70-g09d2 From b32b2b0f8ea82cb51d70b88815c25e0f1c0cf7a5 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 4 Mar 2012 10:55:49 +0200 Subject: wl12xx: increment session_counter for device role as well The sesssion_counter has to be incremented each time the dev is started (similar to sta role). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index ae1f3d7f34d2..1ef212f6440f 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -531,7 +531,7 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, goto out_free; } cmd->device.hlid = wlvif->dev_hlid; - cmd->device.session = wlvif->session_counter; + cmd->device.session = wl12xx_get_new_session_id(wl, wlvif); wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d", cmd->role_id, cmd->device.hlid, cmd->device.session); -- cgit v1.2.3-70-g09d2 From 249e9698899643a799951a6e772facae346f0941 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 4 Mar 2012 10:55:50 +0200 Subject: wl12xx: set correct vif type in change_interface callback In some cases, the wrong vif type was set in the change_interface callback (P2P_CLIENT/P2P_GO instead of STA/AP) Signed-off-by: Eliad Peller 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 a330b0c0ae61..65f91d7bad31 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2336,7 +2336,7 @@ static int wl12xx_op_change_interface(struct ieee80211_hw *hw, set_bit(WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, &wl->flags); wl1271_op_remove_interface(hw, vif); - vif->type = ieee80211_iftype_p2p(new_type, p2p); + vif->type = new_type; vif->p2p = p2p; ret = wl1271_op_add_interface(hw, vif); -- cgit v1.2.3-70-g09d2 From 121af04995d29e3287b849a768789c668d39dce3 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 4 Mar 2012 10:55:51 +0200 Subject: wl12xx: don't handle change_channel while associated Currently, CHANGE_CHANNEL indication while associated is considered as roaming attempt. However, with the new auth/assoc redesign, we no longer have to handle this case, so remove it. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 41 +++++++++++++------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 65f91d7bad31..85bbe7f4f517 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -2515,35 +2515,22 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_warning("rate policy for channel " "failed %d", ret); - if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, - &wlvif->flags)) { - if (wl12xx_dev_role_started(wlvif)) { - /* roaming */ - ret = wl12xx_croc(wl, - wlvif->dev_role_id); - if (ret < 0) - return ret; - } - ret = wl1271_join(wl, wlvif, false); + /* + * change the ROC channel. do it only if we are + * not idle. otherwise, CROC will be called + * anyway. + */ + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, + &wlvif->flags) && + wl12xx_dev_role_started(wlvif) && + !(conf->flags & IEEE80211_CONF_IDLE)) { + ret = wl12xx_stop_dev(wl, wlvif); if (ret < 0) - wl1271_warning("cmd join on channel " - "failed %d", ret); - } else { - /* - * change the ROC channel. do it only if we are - * not idle. otherwise, CROC will be called - * anyway. - */ - if (wl12xx_dev_role_started(wlvif) && - !(conf->flags & IEEE80211_CONF_IDLE)) { - ret = wl12xx_stop_dev(wl, wlvif); - if (ret < 0) - return ret; + return ret; - ret = wl12xx_start_dev(wl, wlvif); - if (ret < 0) - return ret; - } + ret = wl12xx_start_dev(wl, wlvif); + if (ret < 0) + return ret; } } } -- cgit v1.2.3-70-g09d2 From 97fd311a2615d8f35e796b11a14b6cf3d335d423 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 4 Mar 2012 10:55:52 +0200 Subject: wl12xx: don't allow scanning while device is in ROC return EBUSY on scan when there is any role in ROC (not necessarily the one we are going to use) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 85bbe7f4f517..1d5f2d5614fb 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3057,8 +3057,6 @@ 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; @@ -3086,8 +3084,8 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, if (ret < 0) goto out; - if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) && - test_bit(wlvif->role_id, wl->roc_map)) { + /* fail if there is any role in ROC */ + if (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) < WL12XX_MAX_ROLES) { /* don't allow scanning right now */ ret = -EBUSY; goto out_sleep; -- cgit v1.2.3-70-g09d2 From 6667776d3cf32dd3809a18917c2b7adb8ef12aa2 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 4 Mar 2012 10:55:53 +0200 Subject: wl12xx: configure the correct beacon_interval We didn't update the beacon interval on association (or on a change notification when working as sta), so the default interval (100ms) was always used. Update the beacon interval according to the bss_conf before starting the sta role (on association). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 1d5f2d5614fb..89bf9eadc840 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -3723,6 +3723,7 @@ sta_not_found: u32 rates; int ieoffset; wlvif->aid = bss_conf->aid; + wlvif->beacon_int = bss_conf->beacon_int; set_assoc = true; /* -- cgit v1.2.3-70-g09d2 From e9ba7152c1f5babd6ad9ad45619e0a10b4c08554 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 4 Mar 2012 10:55:54 +0200 Subject: wl12xx: avoid bug_on_recovery during fw switch Add a flag to indicate we initiated a recovery work on purpose, in order to avoid triggering BUG() (when the bug_on_recovery module param was set). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/main.c | 5 ++++- drivers/net/wireless/wl12xx/wl12xx.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 89bf9eadc840..3c966f2e00d0 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1154,7 +1154,8 @@ static void wl1271_recovery_work(struct work_struct *work) wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); - BUG_ON(bug_on_recovery); + BUG_ON(bug_on_recovery && + !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); /* * Advance security sequence number to overcome potential progress @@ -2133,6 +2134,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (wl12xx_need_fw_change(wl, vif_count, true)) { wl12xx_force_active_psm(wl); + set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); mutex_unlock(&wl->mutex); wl1271_recovery_work(&wl->recovery_work); return 0; @@ -2317,6 +2319,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, WARN_ON(iter != wlvif); if (wl12xx_need_fw_change(wl, vif_count, false)) { wl12xx_force_active_psm(wl); + set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); wl12xx_queue_recovery_work(wl); cancel_recovery = false; } diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index b26b1be9a98b..6e13a3073e9f 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -260,6 +260,7 @@ enum wl12xx_flags { WL1271_FLAG_SOFT_GEMINI, WL1271_FLAG_RECOVERY_IN_PROGRESS, WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, + WL1271_FLAG_INTENDED_FW_RECOVERY, }; enum wl12xx_vif_flags { -- cgit v1.2.3-70-g09d2 From 8ccd16e6cb17a1e961617cc67798bbb222e4cd13 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 4 Mar 2012 10:55:55 +0200 Subject: wl12xx: print the tx packet len Add the packet length to the tx debug print. 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 3c966f2e00d0..95a76a5f9eeb 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -1459,7 +1459,8 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) goto out; } - wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q); + wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d len %d", + hlid, q, skb->len); skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); wl->tx_queue_count[q]++; -- cgit v1.2.3-70-g09d2 From a0f6d6caef4033aa9c3e2ea2ceae256c4347a419 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 24 Feb 2012 21:36:05 -0800 Subject: mwifiex: handle auto authentication mode correctly When authentication type is configured to NL80211_AUTHTYPE_AUTOMATIC, driver tries to connect using open mode. The association is failed if AP is configured in shared mode. This patch adds code to try association using shared mode as well if open mode association fails. Now since we returned exact error code in association response handler (instead of -1), corresponding changes are done in mwifiex_process_cmdresp(). Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 10 ++++++---- drivers/net/wireless/mwifiex/cmdevt.c | 8 +++----- drivers/net/wireless/mwifiex/join.c | 2 +- drivers/net/wireless/mwifiex/main.h | 1 + drivers/net/wireless/mwifiex/sta_ioctl.c | 11 +++++++++++ 5 files changed, 22 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index a460fb0cc503..6a81101bab44 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -873,6 +873,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, priv->sec_info.wpa2_enabled = false; priv->wep_key_curr_index = 0; priv->sec_info.encryption_mode = 0; + priv->sec_info.is_authtype_auto = 0; ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); if (mode == NL80211_IFTYPE_ADHOC) { @@ -894,11 +895,12 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, } /* Now handle infra mode. "sme" is valid for infra mode only */ - if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC - || sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) + if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) { auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; - else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) - auth_type = NL80211_AUTHTYPE_SHARED_KEY; + priv->sec_info.is_authtype_auto = 1; + } else { + auth_type = sme->auth_type; + } if (sme->crypto.n_ciphers_pairwise) { priv->sec_info.encryption_mode = diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 6623db69e157..c82eb7ff2fa2 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -771,7 +771,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) /* Check init command response */ if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) { - if (ret == -1) { + if (ret) { dev_err(adapter->dev, "%s: cmd %#x failed during " "initialization\n", __func__, cmdresp_no); mwifiex_init_fw_complete(adapter); @@ -781,10 +781,8 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) } if (adapter->curr_cmd) { - if (adapter->curr_cmd->wait_q_enabled && (!ret)) - adapter->cmd_wait_q.status = 0; - else if (adapter->curr_cmd->wait_q_enabled && (ret == -1)) - adapter->cmd_wait_q.status = -1; + if (adapter->curr_cmd->wait_q_enabled) + adapter->cmd_wait_q.status = ret; /* Clean up and put current command back to cmd_free_q */ mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index ee439fc2f4f3..5c95e4839004 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -585,7 +585,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, le16_to_cpu(assoc_rsp->cap_info_bitmap), le16_to_cpu(assoc_rsp->a_id)); - ret = -1; + ret = le16_to_cpu(assoc_rsp->status_code); goto done; } diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 4c8621706278..dddb5563398a 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -219,6 +219,7 @@ struct mwifiex_802_11_security { u8 wapi_key_on; u8 wep_enabled; u32 authentication_mode; + u8 is_authtype_auto; u32 encryption_mode; }; diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 866026ecca44..e10161f5894c 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -249,6 +249,17 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, * application retrieval */ priv->assoc_rsp_size = 0; ret = mwifiex_associate(priv, bss_desc); + + /* If auth type is auto and association fails using open mode, + * try to connect using shared mode */ + if (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG && + priv->sec_info.is_authtype_auto && + priv->sec_info.wep_enabled) { + priv->sec_info.authentication_mode = + NL80211_AUTHTYPE_SHARED_KEY; + ret = mwifiex_associate(priv, bss_desc); + } + if (bss) cfg80211_put_bss(bss); } else { -- cgit v1.2.3-70-g09d2 From d6157bf78015e53371e806e0f8fd44ef6a1bfc5d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Feb 2012 19:58:39 +0100 Subject: Revert "ath9k_hw: Fix false tx hung detection in AR9003 chips" The approach of this change is flawed, as it triggers tx status processing from more callsites, yet the chips only have one global tx status queue. Subsequent patches will properly fix the issue that this one tried to address. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 8 ++------ drivers/net/wireless/ath/ath9k/beacon.c | 6 ------ 2 files changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 8d1bca03bc0e..01d5c1a4d746 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -326,7 +326,6 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_status *ts) { - struct ar9003_txc *txc = (struct ar9003_txc *) ds; struct ar9003_txs *ads; u32 status; @@ -336,11 +335,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, if ((status & AR_TxDone) == 0) return -EINPROGRESS; - ts->qid = MS(ads->ds_info, AR_TxQcuNum); - if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid)) - ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; - else - return -ENOENT; + ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) || (MS(ads->ds_info, AR_TxRxDesc) != 1)) { @@ -354,6 +349,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ts_seqnum = MS(status, AR_SeqNum); ts->tid = MS(status, AR_TxTid); + ts->qid = MS(ads->ds_info, AR_TxQcuNum); ts->desc_id = MS(ads->status1, AR_TxDescId); ts->ts_tstamp = ads->status4; ts->ts_status = 0; diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index b8967e482e6e..6d1e46577db0 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -355,7 +355,6 @@ void ath_beacon_tasklet(unsigned long data) struct ath_common *common = ath9k_hw_common(ah); struct ath_buf *bf = NULL; struct ieee80211_vif *vif; - struct ath_tx_status ts; bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); int slot; u32 bfaddr, bc = 0; @@ -462,11 +461,6 @@ void ath_beacon_tasklet(unsigned long data) ath9k_hw_txstart(ah, sc->beacon.beaconq); sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */ - if (edma) { - spin_lock_bh(&sc->sc_pcu_lock); - ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts); - spin_unlock_bh(&sc->sc_pcu_lock); - } } } -- cgit v1.2.3-70-g09d2 From 4286df60edfe19d3407fa112bf4bdfeeadda897c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Feb 2012 19:58:40 +0100 Subject: ath9k: do not call ath9k_hw_txprocdesc on AR9003 outside of the tx tasklet Since AR9003 uses a global tx status queue, processing tx status outside of the regular tx tasklet is dangerous and messes up hardware/software synchronization of tx status events. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 3 ++- 1 file changed, 2 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 02e95c8e7465..cc2535c38bed 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2300,6 +2300,7 @@ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw) struct ath_vif *avp; struct ath_buf *bf; struct ath_tx_status ts; + bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); int status; vif = sc->beacon.bslot[0]; @@ -2310,7 +2311,7 @@ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw) if (!avp->is_bslot_active) return 0; - if (!sc->beacon.tx_processed) { + if (!sc->beacon.tx_processed && !edma) { tasklet_disable(&sc->bcon_tasklet); bf = avp->av_bcbuf; -- cgit v1.2.3-70-g09d2 From 627e67a656bbb1d616c1ca2d056138a164111a52 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Feb 2012 19:58:41 +0100 Subject: ath9k_hw: enable interrupts for beacon tx completion events Not doing so could cause the tx status queue to overflow during longer periods of time without non-beacon tx. These events are also required for proper drv_tx_last_beacon handling. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/mac.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index e196aba77acf..5f4ae6c9a93c 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -745,7 +745,11 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah) qi.tqi_aifs = 1; qi.tqi_cwmin = 0; qi.tqi_cwmax = 0; - /* NB: don't enable any interrupts */ + + if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) + qi.tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE | + TXQ_FLAG_TXERRINT_ENABLE; + return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); } EXPORT_SYMBOL(ath9k_hw_beaconq_setup); -- cgit v1.2.3-70-g09d2 From 4e0ad2591adde7bec878a4b37a073427aec3e19c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 27 Feb 2012 19:58:42 +0100 Subject: ath9k: fix drv_tx_last_beacon on AR9003 by processing beacon tx status Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 2 +- drivers/net/wireless/ath/ath9k/xmit.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 6d1e46577db0..43882f9e25c4 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -91,7 +91,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, info.txpower = MAX_RATE_POWER; info.keyix = ATH9K_TXKEYIX_INVALID; info.keytype = ATH9K_KEY_TYPE_CLEAR; - info.flags = ATH9K_TXDESC_NOACK; + info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_INTREQ; info.buf_addr[0] = bf->bf_buf_addr; info.buf_len[0] = roundup(skb->len, 4); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 5dd27d2712fc..9f785015a7dc 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2296,9 +2296,12 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) break; } - /* Skip beacon completions */ - if (ts.qid == sc->beacon.beaconq) + /* Process beacon completions separately */ + if (ts.qid == sc->beacon.beaconq) { + sc->beacon.tx_processed = true; + sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); continue; + } txq = &sc->tx.txq[ts.qid]; -- cgit v1.2.3-70-g09d2 From f8f8a660ba501ad14617ccd0d91a1ed8ce54d6d0 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 28 Feb 2012 00:56:05 +0100 Subject: ssb: remove 5GHz antenna gain from sprom There is no 2.4 GHz or 5GHz antenna gain stored in sprom. The sprom just stores the gain values for antenna 1 and 2 or 1 to 4 for more recent sprom versions. On old devices antenna 2 was used for 5 GHz wifi. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/phy.c | 2 +- drivers/ssb/pci.c | 41 ++++++++++++------------------------ drivers/ssb/pcmcia.c | 12 ++++------- drivers/ssb/sdio.c | 12 ++++------- include/linux/ssb/ssb.h | 7 +----- 5 files changed, 24 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c index 96faaef3661b..950334197f40 100644 --- a/drivers/net/wireless/b43legacy/phy.c +++ b/drivers/net/wireless/b43legacy/phy.c @@ -1860,7 +1860,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev) * which accounts for the factor of 4 */ #define REG_MAX_PWR 20 max_pwr = min(REG_MAX_PWR * 4 - - dev->dev->bus->sprom.antenna_gain.ghz24.a0 + - dev->dev->bus->sprom.antenna_gain.a0 - 0x6, max_pwr); /* find the desired power in Q5.2 - power_level is in dBm diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index befa89eac6f3..ed4124469a3a 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c @@ -331,7 +331,6 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) { int i; u16 v; - s8 gain; u16 loc[3]; if (out->revision == 3) /* rev 3 moved MAC */ @@ -390,20 +389,12 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); /* Extract the antenna gain values. */ - gain = r123_extract_antgain(out->revision, in, - SSB_SPROM1_AGAIN_BG, - SSB_SPROM1_AGAIN_BG_SHIFT); - out->antenna_gain.ghz24.a0 = gain; - out->antenna_gain.ghz24.a1 = gain; - out->antenna_gain.ghz24.a2 = gain; - out->antenna_gain.ghz24.a3 = gain; - gain = r123_extract_antgain(out->revision, in, - SSB_SPROM1_AGAIN_A, - SSB_SPROM1_AGAIN_A_SHIFT); - out->antenna_gain.ghz5.a0 = gain; - out->antenna_gain.ghz5.a1 = gain; - out->antenna_gain.ghz5.a2 = gain; - out->antenna_gain.ghz5.a3 = gain; + out->antenna_gain.a0 = r123_extract_antgain(out->revision, in, + SSB_SPROM1_AGAIN_BG, + SSB_SPROM1_AGAIN_BG_SHIFT); + out->antenna_gain.a1 = r123_extract_antgain(out->revision, in, + SSB_SPROM1_AGAIN_A, + SSB_SPROM1_AGAIN_A_SHIFT); } /* Revs 4 5 and 8 have partially shared layout */ @@ -504,16 +495,14 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) } /* Extract the antenna gain values. */ - SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01, + SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01, SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT); - SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01, + SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01, SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT); - SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23, + SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23, SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT); - SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23, + SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23, SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT); - memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, - sizeof(out->antenna_gain.ghz5)); sprom_extract_r458(out, in); @@ -602,16 +591,14 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); /* Extract the antenna gain values. */ - SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01, + SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); - SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01, + SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); - SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23, + SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); - SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23, + SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); - memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, - sizeof(out->antenna_gain.ghz5)); /* Extract cores power info info */ for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index c821c6b2a6a0..fbafed5b729b 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -676,14 +676,10 @@ static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev, case SSB_PCMCIA_CIS_ANTGAIN: GOTO_ERROR_ON(tuple->TupleDataLen != 2, "antg tpl size"); - sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1]; - sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1]; - sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1]; - sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1]; - sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1]; - sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1]; - sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1]; - sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1]; + sprom->antenna_gain.a0 = tuple->TupleData[1]; + sprom->antenna_gain.a1 = tuple->TupleData[1]; + sprom->antenna_gain.a2 = tuple->TupleData[1]; + sprom->antenna_gain.a3 = tuple->TupleData[1]; break; case SSB_PCMCIA_CIS_BFLAGS: GOTO_ERROR_ON((tuple->TupleDataLen != 3) && diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c index 63fd709038ca..b2d36f7736c5 100644 --- a/drivers/ssb/sdio.c +++ b/drivers/ssb/sdio.c @@ -551,14 +551,10 @@ int ssb_sdio_get_invariants(struct ssb_bus *bus, case SSB_SDIO_CIS_ANTGAIN: GOTO_ERROR_ON(tuple->size != 2, "antg tpl size"); - sprom->antenna_gain.ghz24.a0 = tuple->data[1]; - sprom->antenna_gain.ghz24.a1 = tuple->data[1]; - sprom->antenna_gain.ghz24.a2 = tuple->data[1]; - sprom->antenna_gain.ghz24.a3 = tuple->data[1]; - sprom->antenna_gain.ghz5.a0 = tuple->data[1]; - sprom->antenna_gain.ghz5.a1 = tuple->data[1]; - sprom->antenna_gain.ghz5.a2 = tuple->data[1]; - sprom->antenna_gain.ghz5.a3 = tuple->data[1]; + sprom->antenna_gain.a0 = tuple->data[1]; + sprom->antenna_gain.a1 = tuple->data[1]; + sprom->antenna_gain.a2 = tuple->data[1]; + sprom->antenna_gain.a3 = tuple->data[1]; break; case SSB_SDIO_CIS_BFLAGS: GOTO_ERROR_ON((tuple->size != 3) && diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index f1696213e3b5..1de56757e949 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -94,12 +94,7 @@ struct ssb_sprom { * on each band. Values in dBm/4 (Q5.2). Negative gain means the * loss in the connectors is bigger than the gain. */ struct { - struct { - s8 a0, a1, a2, a3; - } ghz24; /* 2.4GHz band */ - struct { - s8 a0, a1, a2, a3; - } ghz5; /* 5GHz band */ + s8 a0, a1, a2, a3; } antenna_gain; struct { -- cgit v1.2.3-70-g09d2 From 1c9351cf2180924c91bb85e5ba607f24a3d875b1 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 28 Feb 2012 00:56:09 +0100 Subject: bcma: export bcma_find_core This function is needed by the bcm47xx arch code to get the number of the ieee80211 core. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/main.c | 3 ++- include/linux/bcma/bcma.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index b8379b90d045..7e138ec21357 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -61,7 +61,7 @@ static struct bus_type bcma_bus_type = { .dev_attrs = bcma_device_attrs, }; -static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) +struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) { struct bcma_device *core; @@ -71,6 +71,7 @@ static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) } return NULL; } +EXPORT_SYMBOL_GPL(bcma_find_core); static void bcma_release_core_dev(struct device *dev) { diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index b9f65fbee42f..46bbd088c4ad 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -284,6 +284,7 @@ static inline void bcma_maskset16(struct bcma_device *cc, bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set); } +extern struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid); extern bool bcma_core_is_enabled(struct bcma_device *core); extern void bcma_core_disable(struct bcma_device *core, u32 flags); extern int bcma_core_enable(struct bcma_device *core, u32 flags); -- cgit v1.2.3-70-g09d2 From a027237a56f7d519eee5749cfb720e568d0bb0b6 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 28 Feb 2012 00:56:10 +0100 Subject: bcma: add support for sprom not found on the device On SoCs the sprom is stored in the nvram in a special partition on the flash chip. The nvram contains the sprom for the main bus, but sometimes also for a pci devices using bcma. This patch makes it possible for the arch code to register a function to fetch the needed sprom from the nvram and provide it to the bcma code. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/sprom.c | 77 ++++++++++++++++++++++++++++++++++++++++++----- include/linux/bcma/bcma.h | 6 ++++ 2 files changed, 75 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index ca7752510d5b..916ae255ff64 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -2,6 +2,8 @@ * Broadcom specific AMBA * SPROM reading * + * Copyright 2011, 2012, Hauke Mehrtens + * * Licensed under the GNU/GPL. See COPYING for details. */ @@ -14,6 +16,45 @@ #include #include +static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out); + +/** + * bcma_arch_register_fallback_sprom - Registers a method providing a + * fallback SPROM if no SPROM is found. + * + * @sprom_callback: The callback function. + * + * With this function the architecture implementation may register a + * callback handler which fills the SPROM data structure. The fallback is + * used for PCI based BCMA devices, where no valid SPROM can be found + * in the shadow registers and to provide the SPROM for SoCs where BCMA is + * to controll the system bus. + * + * This function is useful for weird architectures that have a half-assed + * BCMA device hardwired to their PCI bus. + * + * This function is available for architecture code, only. So it is not + * exported. + */ +int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus, + struct ssb_sprom *out)) +{ + if (get_fallback_sprom) + return -EEXIST; + get_fallback_sprom = sprom_callback; + + return 0; +} + +static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus, + struct ssb_sprom *out) +{ + if (!get_fallback_sprom) + return -ENOENT; + + return get_fallback_sprom(bus, out); +} + /************************************************** * R/W ops. **************************************************/ @@ -246,23 +287,43 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) SSB_SROM8_FEM_ANTSWLUT_SHIFT); } +static bool bcma_is_sprom_available(struct bcma_bus *bus) +{ + u32 sromctrl; + + if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) + return false; + + if (bus->drv_cc.core->id.rev >= 32) { + sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL); + return sromctrl & BCMA_CC_SROM_CONTROL_PRESENT; + } + return true; +} + int bcma_sprom_get(struct bcma_bus *bus) { u16 offset; u16 *sprom; - u32 sromctrl; int err = 0; if (!bus->drv_cc.core) return -EOPNOTSUPP; - if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) - return -ENOENT; - - if (bus->drv_cc.core->id.rev >= 32) { - sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL); - if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT)) - return -ENOENT; + if (!bcma_is_sprom_available(bus)) { + /* + * Maybe there is no SPROM on the device? + * Now we ask the arch code if there is some sprom + * available for this device in some other storage. + */ + err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); + if (err) { + pr_warn("Using fallback SPROM failed (err %d)\n", err); + } else { + pr_debug("Using SPROM revision %d provided by" + " platform.\n", bus->sprom.revision); + return 0; + } } sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 46bbd088c4ad..5af9a075498f 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -176,6 +176,12 @@ int __bcma_driver_register(struct bcma_driver *drv, struct module *owner); extern void bcma_driver_unregister(struct bcma_driver *drv); +/* Set a fallback SPROM. + * See kdoc at the function definition for complete documentation. */ +extern int bcma_arch_register_fallback_sprom( + int (*sprom_callback)(struct bcma_bus *bus, + struct ssb_sprom *out)); + struct bcma_bus { /* The MMIO area. */ void __iomem *mmio; -- cgit v1.2.3-70-g09d2 From eb416ad37db897efe9b2a5b79bd671f5966fa443 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Mon, 27 Feb 2012 22:04:11 -0800 Subject: mwifiex: correct bitrates advertised to cfg80211 1. Driver and firmware do not support 22Mbps and 72Mbps bitrates. Remove them from the rate table advertised to cfg80211. 2. First 4 rates from mwifiex_rates table are not valid for 5GHz/A band. Set correct bitrate array's index and no of rates for ieee80211_supported_band for 5GHz band. Signed-off-by: Avinash Patil Signed-off-by: Nishant Sarmukadam Signed-off-by: Amitkumar Karwar Signed-off-by: Yogesh Ashok Powar Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 6a81101bab44..55293a3ac317 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -613,7 +613,6 @@ static struct ieee80211_rate mwifiex_rates[] = { {.bitrate = 20, .hw_value = 4, }, {.bitrate = 55, .hw_value = 11, }, {.bitrate = 110, .hw_value = 22, }, - {.bitrate = 220, .hw_value = 44, }, {.bitrate = 60, .hw_value = 12, }, {.bitrate = 90, .hw_value = 18, }, {.bitrate = 120, .hw_value = 24, }, @@ -622,7 +621,6 @@ static struct ieee80211_rate mwifiex_rates[] = { {.bitrate = 360, .hw_value = 72, }, {.bitrate = 480, .hw_value = 96, }, {.bitrate = 540, .hw_value = 108, }, - {.bitrate = 720, .hw_value = 144, }, }; /* Channel definitions to be advertised to cfg80211 */ @@ -688,8 +686,8 @@ static struct ieee80211_channel mwifiex_channels_5ghz[] = { static struct ieee80211_supported_band mwifiex_band_5ghz = { .channels = mwifiex_channels_5ghz, .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz), - .bitrates = mwifiex_rates - 4, - .n_bitrates = ARRAY_SIZE(mwifiex_rates) + 4, + .bitrates = mwifiex_rates + 4, + .n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4, }; -- cgit v1.2.3-70-g09d2 From b9be5f39bdabb25708a9de294c2cae7bdd8dfb17 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 27 Feb 2012 22:04:14 -0800 Subject: mwifiex: remove unnecessary struct mwifiex_802_11_ssid Use struct cfg80211_ssid available in include/net/cfg80211.h instead of having similar definition in driver. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 4 ++-- drivers/net/wireless/mwifiex/decl.h | 5 ----- drivers/net/wireless/mwifiex/ioctl.h | 4 ++-- drivers/net/wireless/mwifiex/join.c | 4 ++-- drivers/net/wireless/mwifiex/main.h | 15 +++++++-------- drivers/net/wireless/mwifiex/scan.c | 7 +++---- drivers/net/wireless/mwifiex/sta_event.c | 2 +- drivers/net/wireless/mwifiex/sta_ioctl.c | 5 ++--- 8 files changed, 19 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 55293a3ac317..6a91c2fa89fe 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -839,12 +839,12 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, u8 *bssid, int mode, struct ieee80211_channel *channel, struct cfg80211_connect_params *sme, bool privacy) { - struct mwifiex_802_11_ssid req_ssid; + struct cfg80211_ssid req_ssid; int ret, auth_type = 0; struct cfg80211_bss *bss = NULL; u8 is_scanning_required = 0; - memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); + memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); req_ssid.ssid_len = ssid_len; if (ssid_len > IEEE80211_MAX_SSID_LEN) { diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 3735c775495c..be5fd1652e53 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -91,11 +91,6 @@ struct mwifiex_fw_image { u32 fw_len; }; -struct mwifiex_802_11_ssid { - u32 ssid_len; - u8 ssid[IEEE80211_MAX_SSID_LEN]; -}; - struct mwifiex_wait_queue { wait_queue_head_t wait; int status; diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index d5d81f1fe41c..7ca4e8234f3e 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -50,7 +50,7 @@ struct mwifiex_chan_freq { }; struct mwifiex_ssid_bssid { - struct mwifiex_802_11_ssid ssid; + struct cfg80211_ssid ssid; u8 bssid[ETH_ALEN]; }; @@ -122,7 +122,7 @@ struct mwifiex_ver_ext { struct mwifiex_bss_info { u32 bss_mode; - struct mwifiex_802_11_ssid ssid; + struct cfg80211_ssid ssid; u32 bss_chan; u32 region_code; u32 media_connected; diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 5c95e4839004..bce9991612c8 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -714,7 +714,7 @@ done: int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, - struct mwifiex_802_11_ssid *req_ssid) + struct cfg80211_ssid *req_ssid) { int rsn_ie_len = 0; struct mwifiex_adapter *adapter = priv->adapter; @@ -1245,7 +1245,7 @@ int mwifiex_associate(struct mwifiex_private *priv, */ int mwifiex_adhoc_start(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *adhoc_ssid) + struct cfg80211_ssid *adhoc_ssid) { dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n", priv->adhoc_channel); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index dddb5563398a..a0bd4ebd262a 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -244,7 +244,7 @@ struct ieee_types_generic { struct mwifiex_bssdescriptor { u8 mac_address[ETH_ALEN]; - struct mwifiex_802_11_ssid ssid; + struct cfg80211_ssid ssid; u32 privacy; s32 rssi; u32 channel; @@ -388,7 +388,7 @@ struct mwifiex_private { s16 bcn_rssi_avg; s16 bcn_nf_avg; struct mwifiex_bssdescriptor *attempted_bss_desc; - struct mwifiex_802_11_ssid prev_ssid; + struct cfg80211_ssid prev_ssid; u8 prev_bssid[ETH_ALEN]; struct mwifiex_current_bss_params curr_bss_params; u16 beacon_period; @@ -747,8 +747,7 @@ void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, struct cmd_ctrl_node *cmd_node); int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); -s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, - struct mwifiex_802_11_ssid *ssid2); +s32 mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2); int mwifiex_associate(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc); int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, @@ -760,12 +759,12 @@ void mwifiex_reset_connect_state(struct mwifiex_private *priv); u8 mwifiex_band_to_radio_type(u8 band); int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac); int mwifiex_adhoc_start(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *adhoc_ssid); + struct cfg80211_ssid *adhoc_ssid); int mwifiex_adhoc_join(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc); int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, - struct mwifiex_802_11_ssid *req_ssid); + struct cfg80211_ssid *req_ssid); int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, struct mwifiex_bssdescriptor *bss_desc); @@ -898,7 +897,7 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, struct net_device *dev); int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter); int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, - struct mwifiex_802_11_ssid *req_ssid); + struct cfg80211_ssid *req_ssid); int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); int mwifiex_enable_hs(struct mwifiex_adapter *adapter); int mwifiex_disable_auto_ds(struct mwifiex_private *priv); @@ -907,7 +906,7 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, struct mwifiex_rate_cfg *rate); int mwifiex_request_scan(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *req_ssid); + struct cfg80211_ssid *req_ssid); int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, struct mwifiex_user_scan_cfg *scan_req); int mwifiex_change_adhoc_chan(struct mwifiex_private *priv, int channel); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 8f10038d1b45..67422f64f9fe 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -163,8 +163,7 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) * This function compares two SSIDs and checks if they match. */ s32 -mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, - struct mwifiex_802_11_ssid *ssid2) +mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2) { if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len)) return -1; @@ -1851,7 +1850,7 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv, * firmware, filtered on a specific SSID. */ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *req_ssid) + struct cfg80211_ssid *req_ssid) { struct mwifiex_adapter *adapter = priv->adapter; int ret = 0; @@ -1896,7 +1895,7 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, * scan, depending upon whether an SSID is provided or not. */ int mwifiex_request_scan(struct mwifiex_private *priv, - struct mwifiex_802_11_ssid *req_ssid) + struct cfg80211_ssid *req_ssid) { int ret; diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index d7aa21da84d0..b9b59db60454 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -101,7 +101,7 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv) memcpy(&priv->prev_ssid, &priv->curr_bss_params.bss_descriptor.ssid, - sizeof(struct mwifiex_802_11_ssid)); + sizeof(struct cfg80211_ssid)); memcpy(priv->prev_bssid, priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index e10161f5894c..593d285111d2 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -192,7 +192,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, * first. */ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, - struct mwifiex_802_11_ssid *req_ssid) + struct cfg80211_ssid *req_ssid) { int ret; struct mwifiex_adapter *adapter = priv->adapter; @@ -464,8 +464,7 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv, info->bss_mode = priv->bss_mode; - memcpy(&info->ssid, &bss_desc->ssid, - sizeof(struct mwifiex_802_11_ssid)); + memcpy(&info->ssid, &bss_desc->ssid, sizeof(struct cfg80211_ssid)); memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN); -- cgit v1.2.3-70-g09d2 From be0b281e8f7afd56d2250a568b85dafc850bc9ae Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 27 Feb 2012 22:04:15 -0800 Subject: mwifiex: fix bug in wildcard scan handling Currently if valid SSID list is provided in scan request, driver performs specific SSID scan otherwise wildcard scan is chosen. When wpa_supplicant provides valid SSID list followed by zero-length SSID for wildcard scan, only specific SSID scan is performed by driver. Actually driver is expected to do both type of scanning in this case. The patch fixes this issue. Also, use SSID list pointer provided by stack directly, instead of copying SSID's to local structure. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 10 ++++----- drivers/net/wireless/mwifiex/fw.h | 10 +++------ drivers/net/wireless/mwifiex/scan.c | 40 ++++++++++++++++----------------- 3 files changed, 27 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 6a91c2fa89fe..b4890a01ba92 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1106,12 +1106,10 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, dev_err(priv->adapter->dev, "failed to alloc scan_req\n"); return -ENOMEM; } - for (i = 0; i < request->n_ssids; i++) { - memcpy(priv->user_scan_cfg->ssid_list[i].ssid, - request->ssids[i].ssid, request->ssids[i].ssid_len); - priv->user_scan_cfg->ssid_list[i].max_len = - request->ssids[i].ssid_len; - } + + priv->user_scan_cfg->num_ssids = request->n_ssids; + priv->user_scan_cfg->ssid_list = request->ssids; + for (i = 0; i < request->n_channels; i++) { chan = request->channels[i]; priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value; diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index c82620094a53..fc4ffee6c6b9 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -852,11 +852,6 @@ struct mwifiex_user_scan_chan { u32 scan_time; } __packed; -struct mwifiex_user_scan_ssid { - u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; - u8 max_len; -} __packed; - struct mwifiex_user_scan_cfg { /* * BSS mode to be sent in the firmware command @@ -867,8 +862,9 @@ struct mwifiex_user_scan_cfg { u8 reserved; /* BSSID filter sent in the firmware command to limit the results */ u8 specific_bssid[ETH_ALEN]; - /* SSID filter list used in the to limit the scan results */ - struct mwifiex_user_scan_ssid ssid_list[MWIFIEX_MAX_SSID_LIST_LENGTH]; + /* SSID filter list used in the firmware to limit the scan results */ + struct cfg80211_ssid *ssid_list; + u8 num_ssids; /* Variable number (fixed maximum) of channels to scan up */ struct mwifiex_user_scan_chan chan_list[MWIFIEX_USER_SCAN_CHAN_MAX]; } __packed; diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 67422f64f9fe..fd0302fe5bd8 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -737,7 +737,7 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv, u16 scan_dur; u8 channel; u8 radio_type; - u32 ssid_idx; + int i; u8 ssid_filter; u8 rates[MWIFIEX_SUPPORTED_RATES]; u32 rates_size; @@ -792,14 +792,8 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv, user_scan_in->specific_bssid, sizeof(scan_cfg_out->specific_bssid)); - for (ssid_idx = 0; - ((ssid_idx < ARRAY_SIZE(user_scan_in->ssid_list)) - && (*user_scan_in->ssid_list[ssid_idx].ssid - || user_scan_in->ssid_list[ssid_idx].max_len)); - ssid_idx++) { - - ssid_len = strlen(user_scan_in->ssid_list[ssid_idx]. - ssid) + 1; + for (i = 0; i < user_scan_in->num_ssids; i++) { + ssid_len = user_scan_in->ssid_list[i].ssid_len; wildcard_ssid_tlv = (struct mwifiex_ie_types_wildcard_ssid_params *) @@ -810,19 +804,26 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv, (u16) (ssid_len + sizeof(wildcard_ssid_tlv-> max_ssid_length))); - /* max_ssid_length = 0 tells firmware to perform - specific scan for the SSID filled */ - wildcard_ssid_tlv->max_ssid_length = 0; + /* + * max_ssid_length = 0 tells firmware to perform + * specific scan for the SSID filled, whereas + * max_ssid_length = IEEE80211_MAX_SSID_LEN is for + * wildcard scan. + */ + if (ssid_len) + wildcard_ssid_tlv->max_ssid_length = 0; + else + wildcard_ssid_tlv->max_ssid_length = + IEEE80211_MAX_SSID_LEN; memcpy(wildcard_ssid_tlv->ssid, - user_scan_in->ssid_list[ssid_idx].ssid, - ssid_len); + user_scan_in->ssid_list[i].ssid, ssid_len); tlv_pos += (sizeof(wildcard_ssid_tlv->header) + le16_to_cpu(wildcard_ssid_tlv->header.len)); - dev_dbg(adapter->dev, "info: scan: ssid_list[%d]: %s, %d\n", - ssid_idx, wildcard_ssid_tlv->ssid, + dev_dbg(adapter->dev, "info: scan: ssid[%d]: %s, %d\n", + i, wildcard_ssid_tlv->ssid, wildcard_ssid_tlv->max_ssid_length); /* Empty wildcard ssid with a maxlen will match many or @@ -831,7 +832,6 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv, filtered. */ if (!ssid_len && wildcard_ssid_tlv->max_ssid_length) ssid_filter = false; - } /* @@ -840,7 +840,7 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv, * truncate scan results. That is not an issue with an SSID * or BSSID filter applied to the scan results in the firmware. */ - if ((ssid_idx && ssid_filter) + if ((i && ssid_filter) || memcmp(scan_cfg_out->specific_bssid, &zero_mac, sizeof(zero_mac))) *filtered_scan = true; @@ -1876,8 +1876,8 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, return -ENOMEM; } - memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid, - req_ssid->ssid_len); + scan_cfg->ssid_list = req_ssid; + scan_cfg->num_ssids = 1; ret = mwifiex_scan_networks(priv, scan_cfg); -- cgit v1.2.3-70-g09d2 From d53c74e5a124b0aaed7e9b5c462d1806aad54757 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 28 Feb 2012 20:54:43 +0530 Subject: ath9k: completely zero intialize valid_phy_rate_idx its better to zero initialize the 'valid_phy_rate_idx' array completely Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 2 +- drivers/net/wireless/ath/ath9k/rc.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index b8c6c38cbb98..6407af22f7b9 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1226,7 +1226,7 @@ static void ath_rc_init(struct ath_softc *sc, ath_rc_init_valid_rate_idx(ath_rc_priv); for (i = 0; i < WLAN_RC_PHY_MAX; i++) { - for (j = 0; j < MAX_TX_RATE_PHY; j++) + for (j = 0; j < RATE_TABLE_SIZE; j++) ath_rc_priv->valid_phy_rateidx[i][j] = 0; ath_rc_priv->valid_phy_ratecnt[i] = 0; } diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index b7a4bcd3eec7..75f8e9b06b28 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -25,8 +25,6 @@ struct ath_softc; #define ATH_RATE_MAX 30 #define RATE_TABLE_SIZE 72 -#define MAX_TX_RATE_PHY 48 - #define RC_INVALID 0x0000 #define RC_LEGACY 0x0001 -- cgit v1.2.3-70-g09d2 From 6a01f0c08d20a2b1356c1cb90ef97a0dc412b64c Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 28 Feb 2012 20:54:44 +0530 Subject: ath9k: make use of list_for_each_entry_safe this does the same thing as the previous code Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 7e1a91af1497..4633f513a80b 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -169,22 +169,17 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc, enum ath9k_rx_qtype qtype, int size) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); - u32 nbuf = 0; + struct ath_buf *bf, *tbf; if (list_empty(&sc->rx.rxbuf)) { ath_dbg(common, QUEUE, "No free rx buf available\n"); return; } - while (!list_empty(&sc->rx.rxbuf)) { - nbuf++; - + list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) if (!ath_rx_edma_buf_link(sc, qtype)) break; - if (nbuf >= size) - break; - } } static void ath_rx_remove_buffer(struct ath_softc *sc, -- cgit v1.2.3-70-g09d2 From 5809802180b2b638762465cbad3f51a9ac8ff0b3 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 28 Feb 2012 20:45:06 +0100 Subject: b43: prevent firmware on bcm5354 from taking over wrong GPIO pins When using the bcm5354 (Soc with integrated LP-PHY Wifi) with a recent firmware >= 478.104 it runs out of memory after a very short time in OpenWrt after doing an active scan or any thing else where packages are send. This was cased by a gpio misconfiguration, the firmware triggered the GPIO pins used for buttons on some devices and that caused an other driver (OpenWrt diag) listening for these buttons irqs to send many messages to the user space. This patch fixes the bug for my devices (Asus WL-520GU) and makes it work with firmware 666.2. Now the firmware just uses LED GPIO pin number 1 and not the button pins any more. This is the GPIO Pin layout used on my device, see [0]. GPIO pin layout: pin# name type 0 power led 1 wlan led 2 reset button 3 ses buttom This is the nvram configuration output of "nvram show |grep gpio" related nvram configuration: wl0gpio2=11 wl0gpio3=11 wl0gpio0=11 wl0gpio1=0x02 reset_gpio=2 [0]: https://dev.openwrt.org/browser/trunk/package/broadcom-diag/src/diag.c Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5189cf38123a..1d633f3b3274 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2706,6 +2706,8 @@ static int b43_gpio_init(struct b43_wldev *dev) mask |= 0x0060; set |= 0x0060; } + if (dev->dev->chip_id == 0x5354) + set &= 0xff02; if (0 /* FIXME: conditional unknown */ ) { b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK) -- cgit v1.2.3-70-g09d2 From 41eedf39dfb145fb8fa04cd5b799f7bdc7679696 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 1 Mar 2012 10:02:08 +0300 Subject: rndis_wlan: integer overflows in rndis_wlan_do_link_up_work() If "offset" is negative then we can get past this check: if (offset > CONTROL_BUFFER_SIZE) Or if we pick a very high "req_ie_len" then we can get around the check: if (offset + req_ie_len > CONTROL_BUFFER_SIZE) I made "resp_ie_len" and "req_ie_len" unsigned. I don't know if it was intentional that they were signed in the original. Signed-off-by: Dan Carpenter Acked-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index a330c69583d6..dde45effef14 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2755,9 +2755,10 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct ndis_80211_assoc_info *info = NULL; u8 bssid[ETH_ALEN]; - int resp_ie_len, req_ie_len; + unsigned int resp_ie_len, req_ie_len; + unsigned int offset; u8 *req_ie, *resp_ie; - int ret, offset; + int ret; bool roamed = false; bool match_bss; @@ -2785,7 +2786,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) ret = get_association_info(usbdev, info, CONTROL_BUFFER_SIZE); if (!ret) { req_ie_len = le32_to_cpu(info->req_ie_length); - if (req_ie_len > 0) { + if (req_ie_len > CONTROL_BUFFER_SIZE) + req_ie_len = CONTROL_BUFFER_SIZE; + if (req_ie_len != 0) { offset = le32_to_cpu(info->offset_req_ies); if (offset > CONTROL_BUFFER_SIZE) @@ -2799,7 +2802,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) } resp_ie_len = le32_to_cpu(info->resp_ie_length); - if (resp_ie_len > 0) { + if (resp_ie_len > CONTROL_BUFFER_SIZE) + resp_ie_len = CONTROL_BUFFER_SIZE; + if (resp_ie_len != 0) { offset = le32_to_cpu(info->offset_resp_ies); if (offset > CONTROL_BUFFER_SIZE) -- cgit v1.2.3-70-g09d2 From b26e395038a219685c7f78f3be8aeb578c4a5b60 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 29 Feb 2012 09:36:28 +0300 Subject: rndis_wlan: remove unneeded variables We never use the "len" variable. Signed-off-by: Dan Carpenter Acked-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index dde45effef14..1bde2eb54255 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1790,9 +1790,8 @@ static struct ndis_80211_pmkid *remove_pmkid(struct usbnet *usbdev, struct cfg80211_pmksa *pmksa, int max_pmkids) { - int i, len, count, newlen, err; + int i, count, newlen, err; - len = le32_to_cpu(pmkids->length); count = le32_to_cpu(pmkids->bssid_info_count); if (count > max_pmkids) @@ -1831,9 +1830,8 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, struct cfg80211_pmksa *pmksa, int max_pmkids) { - int i, err, len, count, newlen; + int i, err, count, newlen; - len = le32_to_cpu(pmkids->length); count = le32_to_cpu(pmkids->bssid_info_count); if (count > max_pmkids) -- cgit v1.2.3-70-g09d2 From 551d6fe6cb67ea6f7ca4425a5085b05d34f39730 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 29 Feb 2012 09:36:57 +0300 Subject: rndis_wlan: make some variables unsigned These variables can never be less than zero because we cap them in get_device_pmkids(). Let's make them unsigned here because it's simpler to not have to worry about negative numbers when we read the code. Signed-off-by: Dan Carpenter Acked-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 1bde2eb54255..454f2f182342 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1790,7 +1790,8 @@ static struct ndis_80211_pmkid *remove_pmkid(struct usbnet *usbdev, struct cfg80211_pmksa *pmksa, int max_pmkids) { - int i, count, newlen, err; + int i, newlen, err; + unsigned int count; count = le32_to_cpu(pmkids->bssid_info_count); @@ -1830,7 +1831,8 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev, struct cfg80211_pmksa *pmksa, int max_pmkids) { - int i, err, count, newlen; + int i, err, newlen; + unsigned int count; count = le32_to_cpu(pmkids->bssid_info_count); -- cgit v1.2.3-70-g09d2 From e4e02da2ef01deb36aa80fce6ee0bc3e9725ffe8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 29 Feb 2012 09:37:53 +0300 Subject: rndis_wlan: prevent integer overflow in indication() If we pick a high value for "offset" then it could lead to an integer overflow and we would get past the check for: if (offset + len > buflen) { ... Signed-off-by: Dan Carpenter Acked-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 454f2f182342..ce138d846193 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -3043,7 +3043,7 @@ static void rndis_wlan_media_specific_indication(struct usbnet *usbdev, struct rndis_indicate *msg, int buflen) { struct ndis_80211_status_indication *indication; - int len, offset; + unsigned int len, offset; offset = offsetof(struct rndis_indicate, status) + le32_to_cpu(msg->offset); @@ -3055,7 +3055,7 @@ static void rndis_wlan_media_specific_indication(struct usbnet *usbdev, return; } - if (offset + len > buflen) { + if (len > buflen || offset > buflen || offset + len > buflen) { netdev_info(usbdev->net, "media specific indication, too large to fit to buffer (%i > %i)\n", offset + len, buflen); return; -- cgit v1.2.3-70-g09d2 From f808e4ad05704d4ba0082fbb27640294c6fa4eae Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 29 Feb 2012 16:24:54 +0200 Subject: rndis_wlan: fix le16/le32_to_cpu mix up with config.beacon_period 'beacon_period' in 'struct ndis_80211_conf' is __le32 instead of __le16 so le32_to_cpu must be used instead of le16_to_cpu. Also correct 'beacon_interval' variables used for passing this value forward from u16 to u32 and rename those variables 'beacon_period' This is to avoid confusion because 'beacon_interval' is defined as __le16 at other structure, 'struct ndis_80211_fixed_ies'. Reported-by: Dan Carpenter Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index ce138d846193..c831c1f2bd07 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1350,7 +1350,7 @@ static int set_channel(struct usbnet *usbdev, int channel) } static struct ieee80211_channel *get_current_channel(struct usbnet *usbdev, - u16 *beacon_interval) + u32 *beacon_period) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct ieee80211_channel *channel; @@ -1370,8 +1370,8 @@ static struct ieee80211_channel *get_current_channel(struct usbnet *usbdev, if (!channel) return NULL; - if (beacon_interval) - *beacon_interval = le16_to_cpu(config.beacon_period); + if (beacon_period) + *beacon_period = le32_to_cpu(config.beacon_period); return channel; } @@ -2683,7 +2683,7 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, s32 signal; u64 timestamp; u16 capability; - u16 beacon_interval = 0; + u32 beacon_period = 0; __le32 rssi; u8 ie_buf[34]; int len, ret, ie_len; @@ -2708,7 +2708,7 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, } /* Get channel and beacon interval */ - channel = get_current_channel(usbdev, &beacon_interval); + channel = get_current_channel(usbdev, &beacon_period); if (!channel) { netdev_warn(usbdev->net, "%s(): could not get channel.\n", __func__); @@ -2738,11 +2738,11 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, netdev_dbg(usbdev->net, "%s(): channel:%d(freq), bssid:[%pM], tsf:%d, " "capa:%x, beacon int:%d, resp_ie(len:%d, essid:'%.32s'), " "signal:%d\n", __func__, (channel ? channel->center_freq : -1), - bssid, (u32)timestamp, capability, beacon_interval, ie_len, + bssid, (u32)timestamp, capability, beacon_period, ie_len, ssid.essid, signal); bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid, - timestamp, capability, beacon_interval, ie_buf, ie_len, + timestamp, capability, beacon_period, ie_buf, ie_len, signal, GFP_KERNEL); cfg80211_put_bss(bss); } -- cgit v1.2.3-70-g09d2 From f096ce6d244a380a78e19a7d7a25d9a4a6a6c9b7 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 29 Feb 2012 16:25:00 +0200 Subject: rndis_wlan: use RNDIS_WLAN_NUM_KEYS for all key index checks Use new RNDIS_WLAN_NUM_KEYS for checks in add_wep_key() and add_wpa_key(). Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index c831c1f2bd07..0e238400b046 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1387,13 +1387,15 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, netdev_dbg(usbdev->net, "%s(idx: %d, len: %d)\n", __func__, index, key_len); - if ((key_len != 5 && key_len != 13) || index < 0 || index > 3) + if (index < 0 || index >= RNDIS_WLAN_NUM_KEYS) return -EINVAL; if (key_len == 5) cipher = WLAN_CIPHER_SUITE_WEP40; - else + else if (key_len == 13) cipher = WLAN_CIPHER_SUITE_WEP104; + else + return -EINVAL; memset(&ndis_key, 0, sizeof(ndis_key)); @@ -1436,7 +1438,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, bool is_addr_ok; int ret; - if (index < 0 || index >= 4) { + if (index < 0 || index >= RNDIS_WLAN_NUM_KEYS) { netdev_dbg(usbdev->net, "%s(): index out of range (%i)\n", __func__, index); return -EINVAL; -- cgit v1.2.3-70-g09d2 From 461bc26c93f27d306a0e74cf642b33eb9d2d4112 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 29 Feb 2012 16:25:05 +0200 Subject: rndis_wlan: use u8 for key indexes cfg80211 uses u8 for key indexes and so should rndis_wlan. Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 0e238400b046..d66e2980bc27 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -518,7 +518,7 @@ struct rndis_wlan_private { __le32 current_command_oid; /* encryption stuff */ - int encr_tx_key_index; + u8 encr_tx_key_index; struct rndis_wlan_encr_key encr_keys[RNDIS_WLAN_NUM_KEYS]; int wpa_version; @@ -634,7 +634,7 @@ static u32 get_bcm4320_power_dbm(struct rndis_wlan_private *priv) } } -static bool is_wpa_key(struct rndis_wlan_private *priv, int idx) +static bool is_wpa_key(struct rndis_wlan_private *priv, u8 idx) { int cipher = priv->encr_keys[idx].cipher; @@ -1377,7 +1377,7 @@ static struct ieee80211_channel *get_current_channel(struct usbnet *usbdev, /* index must be 0 - N, as per NDIS */ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, - int index) + u8 index) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct ndis_80211_wep_key ndis_key; @@ -1387,7 +1387,7 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, netdev_dbg(usbdev->net, "%s(idx: %d, len: %d)\n", __func__, index, key_len); - if (index < 0 || index >= RNDIS_WLAN_NUM_KEYS) + if (index >= RNDIS_WLAN_NUM_KEYS) return -EINVAL; if (key_len == 5) @@ -1430,7 +1430,7 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, } static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, - int index, const u8 *addr, const u8 *rx_seq, + u8 index, const u8 *addr, const u8 *rx_seq, int seq_len, u32 cipher, __le32 flags) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); @@ -1438,7 +1438,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, bool is_addr_ok; int ret; - if (index < 0 || index >= RNDIS_WLAN_NUM_KEYS) { + if (index >= RNDIS_WLAN_NUM_KEYS) { netdev_dbg(usbdev->net, "%s(): index out of range (%i)\n", __func__, index); return -EINVAL; @@ -1526,7 +1526,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, return 0; } -static int restore_key(struct usbnet *usbdev, int key_idx) +static int restore_key(struct usbnet *usbdev, u8 key_idx) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct rndis_wlan_encr_key key; @@ -1552,13 +1552,13 @@ static void restore_keys(struct usbnet *usbdev) restore_key(usbdev, i); } -static void clear_key(struct rndis_wlan_private *priv, int idx) +static void clear_key(struct rndis_wlan_private *priv, u8 idx) { memset(&priv->encr_keys[idx], 0, sizeof(priv->encr_keys[idx])); } /* remove_key is for both wep and wpa */ -static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid) +static int remove_key(struct usbnet *usbdev, u8 index, const u8 *bssid) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct ndis_80211_remove_key remove_key; -- cgit v1.2.3-70-g09d2 From 62ebeed8d00aef75eac4fd6c161cae75a41965ca Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 1 Mar 2012 00:40:08 +0400 Subject: p54spi: Release GPIO lines and IRQ on error in p54spi_probe This makes it possible to reload driver if insmod has failed due to missing firmware. Signed-off-by: Max Filippov Cc: stable Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 7faed62c6378..f7929906d437 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -618,19 +618,19 @@ static int __devinit p54spi_probe(struct spi_device *spi) ret = spi_setup(spi); if (ret < 0) { dev_err(&priv->spi->dev, "spi_setup failed"); - goto err_free_common; + goto err_free; } ret = gpio_request(p54spi_gpio_power, "p54spi power"); if (ret < 0) { dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret); - goto err_free_common; + goto err_free; } ret = gpio_request(p54spi_gpio_irq, "p54spi irq"); if (ret < 0) { dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret); - goto err_free_common; + goto err_free_gpio_power; } gpio_direction_output(p54spi_gpio_power, 0); @@ -641,7 +641,7 @@ static int __devinit p54spi_probe(struct spi_device *spi) priv->spi); if (ret < 0) { dev_err(&priv->spi->dev, "request_irq() failed"); - goto err_free_common; + goto err_free_gpio_irq; } irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING); @@ -673,6 +673,12 @@ static int __devinit p54spi_probe(struct spi_device *spi) return 0; err_free_common: + free_irq(gpio_to_irq(p54spi_gpio_irq), spi); +err_free_gpio_irq: + gpio_free(p54spi_gpio_irq); +err_free_gpio_power: + gpio_free(p54spi_gpio_power); +err_free: p54_free_common(priv->hw); return ret; } -- cgit v1.2.3-70-g09d2 From 380aeef8941c6b8a3e8de86b5ca000ca986e3b17 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 1 Mar 2012 10:22:30 +0300 Subject: mwifiex: endian bug in mwifiex_drv_change_adhoc_chan() In mwifiex_drv_change_adhoc_chan() we pass channel to mwifiex_bss_ioctl_ibss_channel() which sets the high 16 bits. This works on little endian systems but not on big endian ones. I've changed mwifiex_drv_change_adhoc_chan() to use a 16 bit variable. This matches the other functions in the file. I considered changing mwifiex_change_adhoc_chan() as well but it turns out that the function isn't implemented so I just removed the definition. Signed-off-by: Dan Carpenter Acked-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/main.h | 3 +-- drivers/net/wireless/mwifiex/sta_ioctl.c | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index a0bd4ebd262a..6dc116647411 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -909,10 +909,9 @@ int mwifiex_request_scan(struct mwifiex_private *priv, struct cfg80211_ssid *req_ssid); int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, struct mwifiex_user_scan_cfg *scan_req); -int mwifiex_change_adhoc_chan(struct mwifiex_private *priv, int channel); int mwifiex_set_radio(struct mwifiex_private *priv, u8 option); -int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel); +int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel); int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, int key_len, u8 key_index, int disable); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 593d285111d2..0ae1209646c1 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -609,7 +609,7 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv, * - Start/Join the IBSS */ int -mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) +mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel) { int ret; struct mwifiex_bss_info bss_info; @@ -646,7 +646,7 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid); ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET, - (u16 *) &channel); + &channel); /* Do specific SSID scanning */ if (mwifiex_request_scan(priv, &bss_info.ssid)) { -- cgit v1.2.3-70-g09d2 From 48de1a17fc41613b7e9d61037fa989256d04234f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 2 Mar 2012 13:21:22 -0600 Subject: rtlwifi: Detect misread of end-point count In the unlikely event of a misread of the USB end point count, the driver generates a divide fault. To prevent this, add a check of the value returned by _rtl_usb_init(). In addition, add some logging to indicate why the condition occurred. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/usb.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index ffcf89fe45e4..b0eee0eb5679 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -346,9 +346,14 @@ static int _rtl_usb_init(struct ieee80211_hw *hw) pep_desc->bEndpointAddress, pep_desc->wMaxPacketSize, pep_desc->bInterval); } - if (rtlusb->in_ep_nums < rtlpriv->cfg->usb_interface_cfg->in_ep_num) - return -EINVAL ; - + if (rtlusb->in_ep_nums < rtlpriv->cfg->usb_interface_cfg->in_ep_num) { + pr_err("Too few input end points found\n"); + return -EINVAL; + } + if (rtlusb->out_ep_nums == 0) { + pr_err("No output end points found\n"); + return -EINVAL; + } /* usb endpoint mapping */ err = rtlpriv->cfg->usb_interface_cfg->usb_endpoint_mapping(hw); rtlusb->usb_mq_to_hwq = rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq; @@ -976,6 +981,8 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, } rtlpriv->cfg->ops->init_sw_leds(hw); err = _rtl_usb_init(hw); + if (err) + goto error_out; err = _rtl_usb_init_sw(hw); /* Init mac80211 sw */ err = rtl_init_core(hw); -- cgit v1.2.3-70-g09d2 From 8f526ab4aa1b145bda2baf56e223050c7ef3e1b0 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 2 Mar 2012 13:22:46 -0600 Subject: rtlwifi: Remove extraneous value return In usb.c, routine _rtl_usb_init_sw() always returns 0, and rtl_usb_probe() never checks the returned value. Thus we can change _rtl_usb_init_sw() to a void routine. In addition, remove the underscore at the beginning of the name of the routine. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/usb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index b0eee0eb5679..2e1e352864bb 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -362,7 +362,7 @@ static int _rtl_usb_init(struct ieee80211_hw *hw) return err; } -static int _rtl_usb_init_sw(struct ieee80211_hw *hw) +static void rtl_usb_init_sw(struct ieee80211_hw *hw) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -397,7 +397,6 @@ static int _rtl_usb_init_sw(struct ieee80211_hw *hw) /* HIMR_EX - turn all on */ rtlusb->irq_mask[1] = 0xFFFFFFFF; rtlusb->disableHWSM = true; - return 0; } #define __RADIO_TAP_SIZE_RSV 32 @@ -983,7 +982,7 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, err = _rtl_usb_init(hw); if (err) goto error_out; - err = _rtl_usb_init_sw(hw); + rtl_usb_init_sw(hw); /* Init mac80211 sw */ err = rtl_init_core(hw); if (err) { -- cgit v1.2.3-70-g09d2 From ebecdcc12fed5d3c81853dea61a0a78a5aefab52 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 2 Mar 2012 15:23:36 -0600 Subject: rtlwifi: rtl8192c: Prevent sleeping from invalid context in rtl8192cu When driver rtl8192cu is used with the debug level set to 3 or greater, the result is "sleeping function called from invalid context" due to an rcu_read_lock() call in the DM refresh routine in driver rtl8192c. This lock is not necessary as the USB driver does not use the struct being protected, thus the lock is set only when a PCI interface is active. This bug is reported in https://bugzilla.kernel.org/show_bug.cgi?id=42775. Reported-by: Ronald Wahl Tested-by: Ronald Wahl Signed-off-by: Larry Finger Cc: Stable Cc: Ronald Wahl Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index cb5535cf3ae2..8646ff2a55ce 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -1201,13 +1201,18 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) "PreState = %d, CurState = %d\n", p_ra->pre_ratr_state, p_ra->ratr_state); - rcu_read_lock(); - sta = ieee80211_find_sta(mac->vif, mac->bssid); + /* Only the PCI card uses sta in the update rate table + * callback routine */ + if (rtlhal->interface == INTF_PCI) { + rcu_read_lock(); + sta = ieee80211_find_sta(mac->vif, mac->bssid); + } rtlpriv->cfg->ops->update_rate_tbl(hw, sta, p_ra->ratr_state); p_ra->pre_ratr_state = p_ra->ratr_state; - rcu_read_unlock(); + if (rtlhal->interface == INTF_PCI) + rcu_read_unlock(); } } } -- cgit v1.2.3-70-g09d2 From 3bc7e29c984ffda0b6133c2b34233023ff36f370 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Mar 2012 22:55:45 +0100 Subject: brcm80211: fmac: remove unnecessary NULL pointer check In brcmf_usb_up() the variable devinfo was checked for being a NULL pointer, but this can not happen. Also the check was done after dereferencing the pointer. This patch removes the check. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Kan Yan Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index d4a9e8e7deb3..8616961a066e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -712,9 +712,6 @@ static int brcmf_usb_up(struct device *dev) struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); u16 ifnum; - if (devinfo == NULL) - return -EINVAL; - if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) return 0; -- cgit v1.2.3-70-g09d2 From ac94f196a5fed4915b82d71b9b111867d78df992 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Mar 2012 22:55:46 +0100 Subject: brcm80211: fmac: remove brcmf_usb_attrib structure Several fields in this structure are only written once or not used at all. Remaining two fields have been moved and brcmf_usb_attrib definition has been removed. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Kan Yan Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 17 +++++++++-------- drivers/net/wireless/brcm80211/brcmfmac/usb.h | 16 ++-------------- 2 files changed, 11 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 8616961a066e..0418a40fce8d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -897,8 +897,8 @@ brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo) sizeof(struct bootrom_id_le)); return false; } else { - devinfo->bus_pub.attrib.devid = chipid; - devinfo->bus_pub.attrib.chiprev = chiprev; + devinfo->bus_pub.devid = chipid; + devinfo->bus_pub.chiprev = chiprev; } return true; } @@ -1064,7 +1064,7 @@ static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len) if (devinfo == NULL) return -EINVAL; - if (devinfo->bus_pub.attrib.devid == 0xDEAD) + if (devinfo->bus_pub.devid == 0xDEAD) return -EINVAL; err = brcmf_usb_dl_writeimage(devinfo, fw, len); @@ -1085,7 +1085,7 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo) if (!devinfo) return -EINVAL; - if (devinfo->bus_pub.attrib.devid == 0xDEAD) + if (devinfo->bus_pub.devid == 0xDEAD) return -EINVAL; /* Check we are runnable */ @@ -1124,18 +1124,19 @@ static bool brcmf_usb_chip_support(int chipid, int chiprev) static int brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo) { - struct brcmf_usb_attrib *attr; + int devid, chiprev; int err; brcmf_dbg(TRACE, "enter\n"); if (devinfo == NULL) return -ENODEV; - attr = &devinfo->bus_pub.attrib; + devid = devinfo->bus_pub.devid; + chiprev = devinfo->bus_pub.chiprev; - if (!brcmf_usb_chip_support(attr->devid, attr->chiprev)) { + if (!brcmf_usb_chip_support(devid, chiprev)) { brcmf_dbg(ERROR, "unsupported chip %d rev %d\n", - attr->devid, attr->chiprev); + devid, chiprev); return -EINVAL; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.h b/drivers/net/wireless/brcm80211/brcmfmac/usb.h index b31da7b83ff7..3377d63e6c8b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.h @@ -50,19 +50,6 @@ struct brcmf_stats { }; -struct brcmf_usb_attrib { - int bustype; - int vid; - int pid; - int devid; - int chiprev; /* chip revsion number */ - int mtu; - int nchan; /* Data Channels */ - int has_2nd_bulk_in_ep; -}; - -struct brcmf_usbdev_info; - struct brcmf_usbdev { struct brcmf_bus *bus; struct brcmf_usbdev_info *devinfo; @@ -70,7 +57,8 @@ struct brcmf_usbdev { struct brcmf_stats stats; int ntxq, nrxq, rxsize; u32 bus_mtu; - struct brcmf_usb_attrib attrib; + int devid; + int chiprev; /* chip revsion number */ }; /* IO Request Block (IRB) */ -- cgit v1.2.3-70-g09d2 From 1d9c1796bc448d76429e0937ef69e4f29cd1adad Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Mar 2012 22:55:47 +0100 Subject: brcm80211: fmac: use counters in brcmf_bus structure The usb code defines a structure for counting statistics. However, it should use the statistics entry provided in brcmf_bus as that is exposed to the net_device. The usb private statistics counter only remains with counters for control packets between driver and usb device. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky (Zhenhui) Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 8 ++++---- drivers/net/wireless/brcm80211/brcmfmac/usb.h | 11 ----------- 2 files changed, 4 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 0418a40fce8d..a2a0c45201ac 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -514,9 +514,9 @@ static void brcmf_usb_tx_complete(struct urb *urb) brcmf_usb_del_fromq(devinfo, req); if (urb->status == 0) - devinfo->bus_pub.stats.tx_packets++; + devinfo->bus_pub.bus->dstats.tx_packets++; else - devinfo->bus_pub.stats.tx_errors++; + devinfo->bus_pub.bus->dstats.tx_errors++; dev_kfree_skb(req->skb); req->skb = NULL; @@ -536,9 +536,9 @@ static void brcmf_usb_rx_complete(struct urb *urb) req->skb = NULL; if (urb->status == 0) { - devinfo->bus_pub.stats.rx_packets++; + devinfo->bus_pub.bus->dstats.rx_packets++; } else { - devinfo->bus_pub.stats.rx_errors++; + devinfo->bus_pub.bus->dstats.rx_errors++; dev_kfree_skb(skb); brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); return; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.h b/drivers/net/wireless/brcm80211/brcmfmac/usb.h index 3377d63e6c8b..acfa5e89872f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.h @@ -33,21 +33,10 @@ enum brcmf_usb_pnp_state { }; struct brcmf_stats { - u32 tx_errors; - u32 tx_packets; - u32 tx_multicast; u32 tx_ctlpkts; u32 tx_ctlerrs; - u32 tx_dropped; - u32 tx_flushed; - u32 rx_errors; - u32 rx_packets; - u32 rx_multicast; u32 rx_ctlpkts; u32 rx_ctlerrs; - u32 rx_dropped; - u32 rx_flushed; - }; struct brcmf_usbdev { -- cgit v1.2.3-70-g09d2 From 549040abbc03e87bdee2964fea5e4c827471d4df Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Mar 2012 22:55:48 +0100 Subject: brcm80211: fmac: initialize host interface drivers regardless result The module init function of brcmfmac calls init functions for SDIO and USB doing driver registration. This patch removes terminating the module init when a driver registration for one host interface fails. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky (Zhenhui) Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 4 +--- drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | 4 ++-- drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 14 +++----------- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 4 ++-- 4 files changed, 8 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 83ca3cc2cccb..4688904908ec 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -604,7 +604,7 @@ void brcmf_sdio_exit(void) sdio_unregister_driver(&brcmf_sdmmc_driver); } -int brcmf_sdio_init(void) +void brcmf_sdio_init(void) { int ret; @@ -614,6 +614,4 @@ int brcmf_sdio_init(void) if (ret) brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret); - - return ret; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index b7671b30692f..366916494be4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h @@ -108,11 +108,11 @@ extern int brcmf_add_if(struct device *dev, int ifidx, #ifdef CONFIG_BRCMFMAC_SDIO extern void brcmf_sdio_exit(void); -extern int brcmf_sdio_init(void); +extern void brcmf_sdio_init(void); #endif #ifdef CONFIG_BRCMFMAC_USB extern void brcmf_usb_exit(void); -extern int brcmf_usb_init(void); +extern void brcmf_usb_init(void); #endif #endif /* _BRCMF_BUS_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index c4da05817443..e7345569e9de 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -1183,21 +1183,13 @@ exit: static int __init brcmfmac_init(void) { - int ret = 0; - #ifdef CONFIG_BRCMFMAC_SDIO - ret = brcmf_sdio_init(); - if (ret) - goto fail; + brcmf_sdio_init(); #endif #ifdef CONFIG_BRCMFMAC_USB - ret = brcmf_usb_init(); - if (ret) - goto fail; + brcmf_usb_init(); #endif - -fail: - return ret; + return 0; } static void __exit brcmfmac_exit(void) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a2a0c45201ac..82364223e817 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -1615,7 +1615,7 @@ void brcmf_usb_exit(void) g_image.len = 0; } -int brcmf_usb_init(void) +void brcmf_usb_init(void) { - return usb_register(&brcmf_usbdrvr); + usb_register(&brcmf_usbdrvr); } -- cgit v1.2.3-70-g09d2 From e64a4b708fd5b719b54f7f969895b66bcba71486 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Mar 2012 22:55:49 +0100 Subject: brcm80211: fmac: remove firmware requests from init_module syscall As indicated in [1] on netdev mailing list drivers should not block on the init_module() syscall. This patch defers the actual driver registration to a workqueue so the init_module() syscall can complete without delay. [1] http://article.gmane.org/gmane.linux.network/217729/ Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky (Zhenhui) Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index e7345569e9de..2a1e5ae0c402 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -1181,7 +1181,7 @@ exit: } #endif /* DEBUG */ -static int __init brcmfmac_init(void) +static void brcmf_driver_init(struct work_struct *work) { #ifdef CONFIG_BRCMFMAC_SDIO brcmf_sdio_init(); @@ -1189,11 +1189,21 @@ static int __init brcmfmac_init(void) #ifdef CONFIG_BRCMFMAC_USB brcmf_usb_init(); #endif +} +static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init); + +static int __init brcmfmac_module_init(void) +{ + if (!schedule_work(&brcmf_driver_work)) + return -EBUSY; + return 0; } -static void __exit brcmfmac_exit(void) +static void __exit brcmfmac_module_exit(void) { + cancel_work_sync(&brcmf_driver_work); + #ifdef CONFIG_BRCMFMAC_SDIO brcmf_sdio_exit(); #endif @@ -1202,5 +1212,5 @@ static void __exit brcmfmac_exit(void) #endif } -module_init(brcmfmac_init); -module_exit(brcmfmac_exit); +module_init(brcmfmac_module_init); +module_exit(brcmfmac_module_exit); -- cgit v1.2.3-70-g09d2 From b0c359b2f68e982ac9334a5f2c04c3a67dee4d50 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Mar 2012 22:55:50 +0100 Subject: brcm80211: smac: remove firmware requests from init_module syscall As indicated in [1] on netdev mailing list drivers should not block on the init_module() syscall. This patch defers the actual driver registration to a workqueue so the init_module() syscall can complete without delay. [1] http://article.gmane.org/gmane.linux.network/217729/ Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Alwin Beukers Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 31 +++++++++++++--------- 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index fec0f10773e5..569ab8abd2a1 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -1169,25 +1169,31 @@ static struct bcma_driver brcms_bcma_driver = { /** * This is the main entry point for the brcmsmac driver. * - * This function determines if a device pointed to by pdev is a WL device, - * and if so, performs a brcms_attach() on it. - * + * This function is scheduled upon module initialization and + * does the driver registration, which result in brcms_bcma_probe() + * call resulting in the driver bringup. */ -static int __init brcms_module_init(void) +static void brcms_driver_init(struct work_struct *work) { - int error = -ENODEV; + int error; + error = bcma_driver_register(&brcms_bcma_driver); + if (error) + pr_err("%s: register returned %d\n", __func__, error); +} + +static DECLARE_WORK(brcms_driver_work, brcms_driver_init); + +static int __init brcms_module_init(void) +{ #ifdef DEBUG if (msglevel != 0xdeadbeef) brcm_msg_level = msglevel; -#endif /* DEBUG */ - - error = bcma_driver_register(&brcms_bcma_driver); - pr_err("%s: register returned %d\n", __func__, error); - if (!error) - return 0; +#endif + if (!schedule_work(&brcms_driver_work)) + return -EBUSY; - return error; + return 0; } /** @@ -1199,6 +1205,7 @@ static int __init brcms_module_init(void) */ static void __exit brcms_module_exit(void) { + cancel_work_sync(&brcms_driver_work); bcma_driver_unregister(&brcms_bcma_driver); } -- cgit v1.2.3-70-g09d2 From 769009b89d8c29c410a99eee3cd63764b1fff869 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 2 Mar 2012 22:55:51 +0100 Subject: brcm80211: smac: cleanup couple of debug output statements Tidying up some debug statements in brcms_c_ampdu_dotxstatus_complete() that got broken strings to satisfy checkpatch, but the rules changed. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Alwin Beukers Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c index dbee69620a90..95b5902bc4b3 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c @@ -959,14 +959,13 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, if (supr_status) { update_rate = false; if (supr_status == TX_STATUS_SUPR_BADCH) { - wiphy_err(wiphy, "%s: Pkt tx suppressed, " - "illegal channel possibly %d\n", + wiphy_err(wiphy, + "%s: Pkt tx suppressed, illegal channel possibly %d\n", __func__, CHSPEC_CHANNEL( wlc->default_bss->chanspec)); } else { if (supr_status != TX_STATUS_SUPR_FRAG) - wiphy_err(wiphy, "%s:" - "supr_status 0x%x\n", + wiphy_err(wiphy, "%s: supr_status 0x%x\n", __func__, supr_status); } /* no need to retry for badch; will fail again */ @@ -988,9 +987,8 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, } } else if (txs->phyerr) { update_rate = false; - wiphy_err(wiphy, "wl%d: ampdu tx phy " - "error (0x%x)\n", wlc->pub->unit, - txs->phyerr); + wiphy_err(wiphy, "%s: ampdu tx phy error (0x%x)\n", + __func__, txs->phyerr); if (brcm_msg_level & LOG_ERROR_VAL) { brcmu_prpkt("txpkt (AMPDU)", p); @@ -1018,10 +1016,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, ack_recd = false; if (ba_recd) { bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX); - BCMMSG(wlc->wiphy, "tid %d seq %d," - " start_seq %d, bindex %d set %d, index %d\n", - tid, seq, start_seq, bindex, - isset(bitmap, bindex), index); + BCMMSG(wiphy, + "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n", + tid, seq, start_seq, bindex, + isset(bitmap, bindex), index); /* if acked then clear bit and free packet */ if ((bindex < AMPDU_TX_BA_MAX_WSIZE) && isset(bitmap, bindex)) { -- cgit v1.2.3-70-g09d2 From 804483e90794256f9ed53e795ffbf1e94de237c8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 22:18:41 +0100 Subject: cfg80211/mac80211: report signal strength for mgmt frames Add the signal strength (in dBm only for now) to frames that are received via nl80211's various frame APIs. Signed-off-by: Johannes Berg Acked-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath6kl/wmi.c | 6 ++++-- include/linux/nl80211.h | 6 ++++++ include/net/cfg80211.h | 8 +++++--- net/mac80211/rx.c | 13 +++++++++++-- net/wireless/mlme.c | 7 ++++--- net/wireless/nl80211.c | 9 +++++++-- net/wireless/nl80211.h | 3 ++- 7 files changed, 39 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 18fa9aa8af92..97abf4699b41 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -556,7 +556,8 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len, dlen, freq, vif->probe_req_report); if (vif->probe_req_report || vif->nw_type == AP_NETWORK) - cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC); + cfg80211_rx_mgmt(vif->ndev, freq, 0, + ev->data, dlen, GFP_ATOMIC); return 0; } @@ -595,7 +596,8 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len, return -EINVAL; } ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq); - cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC); + cfg80211_rx_mgmt(vif->ndev, freq, 0, + ev->data, dlen, GFP_ATOMIC); return 0; } diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 9f46c62b1eee..c37d67add090 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1203,6 +1203,10 @@ enum nl80211_commands { * the list. This needs to be used when the driver advertises the * capability to timeout the stations. * + * @NL80211_ATTR_RX_SIGNAL_DBM: signal strength in dBm (as a 32-bit int); + * this attribute is (depending on the driver capabilities) added to + * received frames indicated with %NL80211_CMD_FRAME. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1450,6 +1454,8 @@ enum nl80211_attrs { NL80211_ATTR_INACTIVITY_TIMEOUT, + NL80211_ATTR_RX_SIGNAL_DBM, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 804805827736..4682c35a92c4 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -3189,6 +3189,7 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp); * cfg80211_rx_mgmt - notification of received, unprocessed management frame * @dev: network device * @freq: Frequency on which the frame was received in MHz + * @sig_dbm: signal strength in mBm, or 0 if unknown * @buf: Management frame (header + body) * @len: length of the frame data * @gfp: context flags @@ -3201,8 +3202,8 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp); * This function is called whenever an Action frame is received for a station * mode interface, but is not processed in kernel. */ -bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, - size_t len, gfp_t gfp); +bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_dbm, + const u8 *buf, size_t len, gfp_t gfp); /** * cfg80211_mgmt_tx_status - notification of TX status for management frame @@ -3315,6 +3316,7 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr, * @frame: the frame * @len: length of the frame * @freq: frequency the frame was received on + * @sig_dbm: signal strength in mBm, or 0 if unknown * @gfp: allocation flags * * Use this function to report to userspace when a beacon was @@ -3323,7 +3325,7 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr, */ void cfg80211_report_obss_beacon(struct wiphy *wiphy, const u8 *frame, size_t len, - int freq, gfp_t gfp); + int freq, int sig_dbm, gfp_t gfp); /* * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 10bbbd33b314..5f6e32ca0858 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2188,9 +2188,14 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) if (rx->sdata->vif.type == NL80211_IFTYPE_AP && ieee80211_is_beacon(mgmt->frame_control) && !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { + int sig = 0; + + if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) + sig = status->signal; + cfg80211_report_obss_beacon(rx->local->hw.wiphy, rx->skb->data, rx->skb->len, - status->freq, GFP_ATOMIC); + status->freq, sig, GFP_ATOMIC); rx->flags |= IEEE80211_RX_BEACON_REPORTED; } @@ -2414,6 +2419,7 @@ static ieee80211_rx_result debug_noinline ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) { struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); + int sig = 0; /* skip known-bad action frames and return them in the next handler */ if (status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM) @@ -2426,7 +2432,10 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) * it transmitted were processed or returned. */ - if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, + if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) + sig = status->signal; + + if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, sig, rx->skb->data, rx->skb->len, GFP_ATOMIC)) { if (rx->sta) diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index fb1e72179117..f5a7ac3a0939 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -814,8 +814,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, cookie); } -bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, - size_t len, gfp_t gfp) +bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_mbm, + const u8 *buf, size_t len, gfp_t gfp) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; @@ -854,7 +854,8 @@ bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, /* found match! */ /* Indicate the received Action frame to user space */ - if (nl80211_send_mgmt(rdev, dev, reg->nlpid, freq, + if (nl80211_send_mgmt(rdev, dev, reg->nlpid, + freq, sig_mbm, buf, len, gfp)) continue; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4b6afc338aac..39dbdf2adb12 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7686,7 +7686,8 @@ bool nl80211_unexpected_4addr_frame(struct net_device *dev, int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, struct net_device *netdev, u32 nlpid, - int freq, const u8 *buf, size_t len, gfp_t gfp) + int freq, int sig_dbm, + const u8 *buf, size_t len, gfp_t gfp) { struct sk_buff *msg; void *hdr; @@ -7704,6 +7705,8 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); + if (sig_dbm) + NLA_PUT_U32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm); NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); genlmsg_end(msg, hdr); @@ -7965,7 +7968,7 @@ EXPORT_SYMBOL(cfg80211_probe_status); void cfg80211_report_obss_beacon(struct wiphy *wiphy, const u8 *frame, size_t len, - int freq, gfp_t gfp) + int freq, int sig_dbm, gfp_t gfp) { struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct sk_buff *msg; @@ -7988,6 +7991,8 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); if (freq) NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); + if (sig_dbm) + NLA_PUT_U32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm); NLA_PUT(msg, NL80211_ATTR_FRAME, len, frame); genlmsg_end(msg, hdr); diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 12bf4d185abe..4ffe50df9f31 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -92,7 +92,8 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev, gfp_t gfp); int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, - struct net_device *netdev, u32 nlpid, int freq, + struct net_device *netdev, u32 nlpid, + int freq, int sig_dbm, const u8 *buf, size_t len, gfp_t gfp); void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, struct net_device *netdev, u64 cookie, -- cgit v1.2.3-70-g09d2 From da473b61ad9e25e2ac3efb58d95c5b573260c6a8 Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Sat, 3 Mar 2012 09:48:56 +0800 Subject: ath5k: allow AP and mesh mode to operate simultaneously This patch allows the possibility of having the mesh point and AP to be operated simultaneously in one single radio. Previously, mesh point fails to generate the mesh beacon if virtual AP is created for the same radio. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 1 + drivers/net/wireless/ath/ath5k/base.c | 6 ++++-- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 6640326f7005..8d434b8f5855 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1320,6 +1320,7 @@ struct ath5k_hw { struct ieee80211_vif *bslot[ATH_BCBUF]; u16 num_ap_vifs; u16 num_adhoc_vifs; + u16 num_mesh_vifs; unsigned int bhalq, /* SW q for outgoing beacons */ bmisscount, /* missed beacon transmits */ bintval, /* beacon interval in TU */ diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a339693fbe26..b51d58c414d2 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1867,7 +1867,8 @@ ath5k_beacon_send(struct ath5k_hw *ah) ah->bmisscount = 0; } - if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) || + if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + + ah->num_mesh_vifs > 1) || ah->opmode == NL80211_IFTYPE_MESH_POINT) { u64 tsf = ath5k_hw_get_tsf64(ah); u32 tsftu = TSF_TO_TU(tsf); @@ -1952,7 +1953,8 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf) u64 hw_tsf; intval = ah->bintval & AR5K_BEACON_PERIOD; - if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) { + if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + + ah->num_mesh_vifs > 1) { intval /= ATH_BCBUF; /* staggered multi-bss beacons */ if (intval < 15) ATH5K_WARN(ah, "intval %u is too low, min 15\n", diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index af4c7ecb4b30..5c5329955414 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -134,6 +134,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ah->num_ap_vifs++; else if (avf->opmode == NL80211_IFTYPE_ADHOC) ah->num_adhoc_vifs++; + else if (avf->opmode == NL80211_IFTYPE_MESH_POINT) + ah->num_mesh_vifs++; } /* Any MAC address is fine, all others are included through the @@ -175,6 +177,8 @@ ath5k_remove_interface(struct ieee80211_hw *hw, ah->num_ap_vifs--; else if (avf->opmode == NL80211_IFTYPE_ADHOC) ah->num_adhoc_vifs--; + else if (avf->opmode == NL80211_IFTYPE_MESH_POINT) + ah->num_mesh_vifs--; ath5k_update_bssid_mask_and_opmode(ah, NULL); mutex_unlock(&ah->lock); -- cgit v1.2.3-70-g09d2 From a9b89e2567c743483e6354f64d7a7e3a8c101e9e Mon Sep 17 00:00:00 2001 From: Jingjun Wu Date: Fri, 2 Mar 2012 20:52:14 -0600 Subject: rtlwifi: rtl8192ce: Fix loss of receive performance Driver rtl8192ce when used with the RTL8188CE device would start at about 20 Mbps on a 54 Mbps connection, but quickly drop to 1 Mbps. One of the symptoms is that the AP would need to retransmit each packet 4 of 5 times before the driver would acknowledge it. Recovery is possible only by unloading and reloading the driver. This problem was reported at https://bugzilla.redhat.com/show_bug.cgi?id=770207. The problem is due to a missing update of the gain setting. Signed-off-by: Jingjun Wu Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index 8646ff2a55ce..d8d73dbb5780 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -520,6 +520,10 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw) dm_digtable.cur_igvalue, dm_digtable.pre_igvalue, dm_digtable.backoff_val); + dm_digtable.cur_igvalue += 2; + if (dm_digtable.cur_igvalue > 0x3f) + dm_digtable.cur_igvalue = 0x3f; + if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) { rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, dm_digtable.cur_igvalue); -- cgit v1.2.3-70-g09d2 From 972a31367f94967716b000fd8fac33d259ebcfed Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 3 Mar 2012 21:24:43 +0100 Subject: p54: pass interface setup errors back to mac80211 Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 40f4eb7da7b2..ee8af1f047c8 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -227,6 +227,7 @@ static int p54_add_interface(struct ieee80211_hw *dev, struct ieee80211_vif *vif) { struct p54_common *priv = dev->priv; + int err; vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; @@ -251,9 +252,9 @@ static int p54_add_interface(struct ieee80211_hw *dev, } memcpy(priv->mac_addr, vif->addr, ETH_ALEN); - p54_setup_mac(priv); + err = p54_setup_mac(priv); mutex_unlock(&priv->conf_mutex); - return 0; + return err; } static void p54_remove_interface(struct ieee80211_hw *dev, -- cgit v1.2.3-70-g09d2 From 26627687e881e79c8c8f9076f79181c2beefcae7 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 3 Mar 2012 21:25:19 +0100 Subject: p54pci: use new driver.pm interface for suspend/resume Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 48 +++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index b1f51a215792..45df728183fd 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -624,36 +624,39 @@ static void __devexit p54p_remove(struct pci_dev *pdev) } #ifdef CONFIG_PM -static int p54p_suspend(struct pci_dev *pdev, pm_message_t state) +static int p54p_suspend(struct device *device) { - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct p54p_priv *priv = dev->priv; - - if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) { - ieee80211_stop_queues(dev); - p54p_stop(dev); - } + struct pci_dev *pdev = to_pci_dev(device); pci_save_state(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); + pci_set_power_state(pdev, PCI_D3hot); + pci_disable_device(pdev); return 0; } -static int p54p_resume(struct pci_dev *pdev) +static int p54p_resume(struct device *device) { - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct p54p_priv *priv = dev->priv; + struct pci_dev *pdev = to_pci_dev(device); + int err; - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); + err = pci_reenable_device(pdev); + if (err) + return err; + return pci_set_power_state(pdev, PCI_D0); +} - if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) { - p54p_open(dev); - ieee80211_wake_queues(dev); - } +static const struct dev_pm_ops p54pci_pm_ops = { + .suspend = p54p_suspend, + .resume = p54p_resume, + .freeze = p54p_suspend, + .thaw = p54p_resume, + .poweroff = p54p_suspend, + .restore = p54p_resume, +}; - return 0; -} +#define P54P_PM_OPS (&p54pci_pm_ops) +#else +#define P54P_PM_OPS (NULL) #endif /* CONFIG_PM */ static struct pci_driver p54p_driver = { @@ -661,10 +664,7 @@ static struct pci_driver p54p_driver = { .id_table = p54p_table, .probe = p54p_probe, .remove = __devexit_p(p54p_remove), -#ifdef CONFIG_PM - .suspend = p54p_suspend, - .resume = p54p_resume, -#endif /* CONFIG_PM */ + .driver.pm = P54P_PM_OPS, }; static int __init p54p_init(void) -- cgit v1.2.3-70-g09d2 From 342bbf3fee2fa9a18147e74b2e3c4229a4564912 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 4 Mar 2012 08:50:46 -0800 Subject: iwlwifi: always monitor for stuck queues If we only monitor while associated, the following can happen: - we're associated, and the queue stuck check runs, setting the queue "touch" time to X - we disassociate, stopping the monitoring, which leaves the time set to X - almost 2s later, we associate, and enqueue a frame - before the frame is transmitted, we monitor for stuck queues, and find the time set to X, although it is now later than X + 2000ms, so we decide that the queue is stuck and erroneously restart the device It happens more with P2P because there we can go between associated/unassociated frequently. Cc: stable@vger.kernel.org Reported-by: Ben Cahill Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 275e08966059..8551c95e7437 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1345,20 +1345,10 @@ void iwl_bg_watchdog(unsigned long data) if (timeout == 0) return; - /* monitor and check for stuck cmd queue */ - if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue)) - return; - - /* monitor and check for other stuck queues */ - if (iwl_is_any_associated(priv)) { - for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { - /* skip as we already checked the command queue */ - if (cnt == priv->shrd->cmd_queue) - continue; - if (iwl_check_stuck_queue(priv, cnt)) - return; - } - } + /* monitor and check for stuck queues */ + for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) + if (iwl_check_stuck_queue(priv, cnt)) + return; mod_timer(&priv->watchdog, jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout))); -- cgit v1.2.3-70-g09d2 From e9a8e8ec1e487536568adc4b3efa8f56e4391a7b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 5 Mar 2012 21:10:07 +0300 Subject: airo: fix test for FLAG_RADIO_DOWN We should be doing a shift (1 << FLAG_RADIO_DOWN) here before testing the flag. As luck would have it, this test works almost correctly. The current code tests for FLAG_RADIO_OFF instead of FLAG_RADIO_DOWN. #define FLAG_RADIO_OFF 0 /* User disabling of MAC */ #define FLAG_RADIO_DOWN 1 /* ifup/ifdown disabling of MAC */ Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 1c008c61b95c..ddc061dd150c 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1869,7 +1869,7 @@ static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) static void try_auto_wep(struct airo_info *ai) { - if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) { + if (auto_wep && !test_bit(FLAG_RADIO_DOWN, &ai->flags)) { ai->expires = RUN_AT(3*HZ); wake_up_interruptible(&ai->thr_wait); } -- cgit v1.2.3-70-g09d2 From d316383dfdb51d46fb9681a68b395a5735f3f4b3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:19 -0800 Subject: iwlwifi: move iwl_clear_driver_stations to user There's only one place using this function, so move it where it's needed. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 35 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 35 ---------------------------------- 2 files changed, 35 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e0fef9f257c2..a7f3a7023d88 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -738,6 +738,41 @@ int iwl_alive_start(struct iwl_priv *priv) return iwl_power_update_mode(priv, true); } +/** + * iwl_clear_driver_stations - clear knowledge of all stations from driver + * @priv: iwl priv struct + * + * This is called during iwl_down() to make sure that in the case + * we're coming there from a hardware restart mac80211 will be + * able to reconfigure stations -- if we're getting there in the + * normal down flow then the stations will already be cleared. + */ +static void iwl_clear_driver_stations(struct iwl_priv *priv) +{ + unsigned long flags; + struct iwl_rxon_context *ctx; + + spin_lock_irqsave(&priv->shrd->sta_lock, flags); + memset(priv->stations, 0, sizeof(priv->stations)); + priv->num_stations = 0; + + priv->ucode_key_table = 0; + + for_each_context(priv, ctx) { + /* + * Remove all key information that is not stored as part + * of station information since mac80211 may not have had + * a chance to remove all the keys. When device is + * reconfigured by mac80211 after an error all keys will + * be reconfigured. + */ + memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys)); + ctx->key_mapping_keys = 0; + } + + spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); +} + void iwl_down(struct iwl_priv *priv) { int exit_pending; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index cb484e273b93..ef0cdf5b32fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -232,41 +232,6 @@ int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, struct iwl_device_cmd *cmd); -/** - * iwl_clear_driver_stations - clear knowledge of all stations from driver - * @priv: iwl priv struct - * - * This is called during iwl_down() to make sure that in the case - * we're coming there from a hardware restart mac80211 will be - * able to reconfigure stations -- if we're getting there in the - * normal down flow then the stations will already be cleared. - */ -static inline void iwl_clear_driver_stations(struct iwl_priv *priv) -{ - unsigned long flags; - struct iwl_rxon_context *ctx; - - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - memset(priv->stations, 0, sizeof(priv->stations)); - priv->num_stations = 0; - - priv->ucode_key_table = 0; - - for_each_context(priv, ctx) { - /* - * Remove all key information that is not stored as part - * of station information since mac80211 may not have had - * a chance to remove all the keys. When device is - * reconfigured by mac80211 after an error all keys will - * be reconfigured. - */ - memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys)); - ctx->key_mapping_keys = 0; - } - - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); -} - static inline int iwl_sta_id(struct ieee80211_sta *sta) { if (WARN_ON(!sta)) -- cgit v1.2.3-70-g09d2 From f2b69ef022aba3fe436bb03664cf12b261cb64d1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:20 -0800 Subject: iwlwifi: remove an unused argument The station ID argument to the function iwlagn_tx_cmd_build_hwcrypto isn't used 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-agn-tx.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 5f78567f4180..81a3b0e3a8e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -208,10 +208,9 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, } static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - struct iwl_tx_cmd *tx_cmd, - struct sk_buff *skb_frag, - int sta_id) + struct ieee80211_tx_info *info, + struct iwl_tx_cmd *tx_cmd, + struct sk_buff *skb_frag) { struct ieee80211_key_conf *keyconf = info->control.hw_key; @@ -358,7 +357,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) tx_cmd->len = cpu_to_le16(len); if (info->control.hw_key) - iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); + iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb); /* TODO need this for burst mode later on */ iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id); -- cgit v1.2.3-70-g09d2 From 71cb99241d63b26a41c9cce6ed441bc30f90224a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:21 -0800 Subject: iwlwifi: reduce sta_lock hold time in TX When we TX, we hold the sta_lock for a long time, a lot of which isn't needed. Reduce the time we hold the lock. Note that this doesn't really change anything as the code is already under the other spinlock, but it makes the code easier to read. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 81a3b0e3a8e0..59509d80f73f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -341,13 +341,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (info->flags & IEEE80211_TX_CTL_AMPDU) is_agg = true; - /* irqs already disabled/saved above when locking priv->shrd->lock */ - spin_lock(&priv->shrd->sta_lock); - dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC); if (unlikely(!dev_cmd)) - goto drop_unlock_sta; + goto drop_unlock_priv; memset(dev_cmd, 0, sizeof(*dev_cmd)); tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; @@ -372,6 +369,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) info->driver_data[0] = ctx; info->driver_data[1] = dev_cmd; + /* irqs already disabled/saved above when locking priv->shrd->lock */ + spin_lock(&priv->shrd->sta_lock); + if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) { u8 *qc = NULL; struct iwl_tid_data *tid_data; -- cgit v1.2.3-70-g09d2 From 40e4e6868c532b439754154d69a2837dbf9bd91e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:22 -0800 Subject: iwlwifi: simplify code in iwlagn_key_sta_id Simplify the code by returning directly in the error case and replacing the switch/if with a single if statement. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index f1298cd6a19a..3eb8fd4771b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -1080,32 +1080,19 @@ static u8 iwlagn_key_sta_id(struct iwl_priv *priv, struct ieee80211_sta *sta) { struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; - u8 sta_id = IWL_INVALID_STATION; if (sta) - sta_id = iwl_sta_id(sta); + return iwl_sta_id(sta); /* * The device expects GTKs for station interfaces to be * installed as GTKs for the AP station. If we have no * station ID, then use the ap_sta_id in that case. */ - if (!sta && vif && vif_priv->ctx) { - switch (vif->type) { - case NL80211_IFTYPE_STATION: - sta_id = vif_priv->ctx->ap_sta_id; - break; - default: - /* - * In all other cases, the key will be - * used either for TX only or is bound - * to a station already. - */ - break; - } - } + if (vif->type == NL80211_IFTYPE_STATION && vif_priv->ctx) + return vif_priv->ctx->ap_sta_id; - return sta_id; + return IWL_INVALID_STATION; } static int iwlagn_send_sta_key(struct iwl_priv *priv, -- cgit v1.2.3-70-g09d2 From 9451ca1a31be44f8235c3f8f998ff27fc7a8395e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:23 -0800 Subject: iwlwifi: build some station commands directly In the powersave related functions we only need to set a few parameters for the station command and can otherwise leave it blank -- there's no need to copy it from the database. This allows us to not use the sta lock here. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 20 +++++++++----------- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 16 ++++++---------- 2 files changed, 15 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 3eb8fd4771b6..6b9af994cfa4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -1437,16 +1437,14 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) { - unsigned long flags; - - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK; - priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; - priv->stations[sta_id].sta.sta.modify_mask = - STA_MODIFY_SLEEP_TX_COUNT_MSK; - priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + struct iwl_addsta_cmd cmd = { + .mode = STA_CONTROL_MODIFY_MSK, + .station_flags = STA_FLG_PWR_SAVE_MSK, + .station_flags_msk = STA_FLG_PWR_SAVE_MSK, + .sta.sta_id = sta_id, + .sta.modify_mask = STA_MODIFY_SLEEP_TX_COUNT_MSK, + .sleep_tx_count = cpu_to_le16(cnt), + }; + iwl_send_add_sta(priv, &cmd, CMD_ASYNC); } diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 03f770543d8e..9fba532d35cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -1505,17 +1505,13 @@ static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw, static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) { - unsigned long flags; - - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; - priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; - priv->stations[sta_id].sta.sta.modify_mask = 0; - priv->stations[sta_id].sta.sleep_tx_count = 0; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + struct iwl_addsta_cmd cmd = { + .mode = STA_CONTROL_MODIFY_MSK, + .station_flags_msk = STA_FLG_PWR_SAVE_MSK, + .sta.sta_id = sta_id, + }; + iwl_send_add_sta(priv, &cmd, CMD_ASYNC); } static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, -- cgit v1.2.3-70-g09d2 From 015c15e1067c988fc87fb550b222f075c8d3f47c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:24 -0800 Subject: iwlwifi: introduce per-queue locks Instead of (ab)using the sta_lock, make the transport layer lock its own TX queue data structures with a lock per queue. This also unifies with the cmd queue lock. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 20 +++++++++------ drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 31 ++++++++++++++--------- drivers/net/wireless/iwlwifi/iwl-trans.h | 2 -- 4 files changed, 33 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 5b26b71ae3d5..b1029468ccbd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -169,6 +169,7 @@ struct iwl_queue { * @meta: array of meta data for each command/tx buffer * @dma_addr_cmd: physical address of cmd/tx buffer array * @txb: array of per-TFD driver data + * lock: queue lock * @time_stamp: time (in jiffies) of last read_ptr change * @need_update: indicates need to update read/write index * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled @@ -187,6 +188,7 @@ struct iwl_tx_queue { struct iwl_device_cmd **cmd; struct iwl_cmd_meta *meta; struct sk_buff **skbs; + spinlock_t lock; unsigned long time_stamp; u8 need_update; u8 sched_retry; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 82e34484fa5e..1cb1dd29b3fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -217,6 +217,8 @@ void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, { struct iwl_tfd *tfd_tmp = txq->tfds; + lockdep_assert_held(&txq->lock); + iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], dma_dir); /* free SKB */ @@ -621,7 +623,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) struct iwl_device_cmd *out_cmd; struct iwl_cmd_meta *out_meta; dma_addr_t phys_addr; - unsigned long flags; u32 idx; u16 copy_size, cmd_size; bool is_ct_kill = false; @@ -680,10 +681,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) return -EIO; } - spin_lock_irqsave(&trans->hcmd_lock, flags); + spin_lock_bh(&txq->lock); if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { - spin_unlock_irqrestore(&trans->hcmd_lock, flags); + spin_unlock_bh(&txq->lock); IWL_ERR(trans, "No space in command queue\n"); is_ct_kill = iwl_check_for_ct_kill(priv(trans)); @@ -790,7 +791,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) iwl_txq_update_write_ptr(trans, txq); out: - spin_unlock_irqrestore(&trans->hcmd_lock, flags); + spin_unlock_bh(&txq->lock); return idx; } @@ -809,6 +810,8 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id, struct iwl_queue *q = &txq->q; int nfreed = 0; + lockdep_assert_held(&txq->lock); + if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) { IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), " "index %d is out of range [0-%d] %d %d.\n", __func__, @@ -850,7 +853,6 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb, struct iwl_cmd_meta *meta; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; - unsigned long flags; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced @@ -864,6 +866,8 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb, return; } + spin_lock(&txq->lock); + cmd_index = get_cmd_index(&txq->q, index); cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; @@ -880,8 +884,6 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb, rxb->page = NULL; } - spin_lock_irqsave(&trans->hcmd_lock, flags); - iwl_hcmd_queue_reclaim(trans, txq_id, index); if (!(meta->flags & CMD_ASYNC)) { @@ -898,7 +900,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb, meta->flags = 0; - spin_unlock_irqrestore(&trans->hcmd_lock, flags); + spin_unlock(&txq->lock); } #define HOST_COMPLETE_TIMEOUT (2 * HZ) @@ -1041,6 +1043,8 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, if (WARN_ON(txq_id == trans->shrd->cmd_queue)) return 0; + lockdep_assert_held(&txq->lock); + /*Since we free until index _not_ inclusive, the one before index is * the last we will free. This one must be used */ last_to_free = iwl_queue_dec_wrap(index, q->n_bd); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 9f8b23909404..f47426a5ef4d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -390,6 +390,8 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, if (ret) return ret; + spin_lock_init(&txq->lock); + /* * Tell nic where to find circular buffer of Tx Frame Descriptors for * given Tx queue, and enable the DMA channel used for that queue. @@ -409,8 +411,6 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; struct iwl_queue *q = &txq->q; enum dma_data_direction dma_dir; - unsigned long flags; - spinlock_t *lock; if (!q->n_bd) return; @@ -418,22 +418,19 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) /* In the command queue, all the TBs are mapped as BIDI * so unmap them as such. */ - if (txq_id == trans->shrd->cmd_queue) { + if (txq_id == trans->shrd->cmd_queue) dma_dir = DMA_BIDIRECTIONAL; - lock = &trans->hcmd_lock; - } else { + else dma_dir = DMA_TO_DEVICE; - lock = &trans->shrd->sta_lock; - } - spin_lock_irqsave(lock, flags); + spin_lock_bh(&txq->lock); while (q->write_ptr != q->read_ptr) { /* The read_ptr needs to bound by q->n_window */ iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr), dma_dir); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } - spin_unlock_irqrestore(lock, flags); + spin_unlock_bh(&txq->lock); } /** @@ -1358,6 +1355,8 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, txq = &trans_pcie->txq[txq_id]; q = &txq->q; + spin_lock(&txq->lock); + /* In AGG mode, the index in the ring must correspond to the WiFi * sequence number. This is a HW requirements to help the SCD to parse * the BA. @@ -1404,7 +1403,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, &dev_cmd->hdr, firstlen, DMA_BIDIRECTIONAL); if (unlikely(dma_mapping_error(trans->dev, txcmd_phys))) - return -1; + goto out_err; dma_unmap_addr_set(out_meta, mapping, txcmd_phys); dma_unmap_len_set(out_meta, len, firstlen); @@ -1426,7 +1425,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, dma_unmap_addr(out_meta, mapping), dma_unmap_len(out_meta, len), DMA_BIDIRECTIONAL); - return -1; + goto out_err; } } @@ -1481,7 +1480,11 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, iwl_stop_queue(trans, txq, "Queue is full"); } } + spin_unlock(&txq->lock); return 0; + out_err: + spin_unlock(&txq->lock); + return -1; } static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) @@ -1560,6 +1563,8 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, int tfd_num = ssn & (txq->q.n_bd - 1); int freed = 0; + spin_lock(&txq->lock); + txq->time_stamp = jiffies; if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && @@ -1574,6 +1579,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, IWL_DEBUG_TX_QUEUES(trans, "Bad queue mapping txq_id %d, " "agg_txq[sta_id[tid] %d", txq_id, trans_pcie->agg_txq[sta_id][tid]); + spin_unlock(&txq->lock); return 1; } @@ -1587,6 +1593,8 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, status != TX_STATUS_FAIL_PASSIVE_NO_RX)) iwl_wake_queue(trans, txq, "Packets reclaimed"); } + + spin_unlock(&txq->lock); return 0; } @@ -2267,7 +2275,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, trans->ops = &trans_ops_pcie; trans->shrd = shrd; trans_pcie->trans = trans; - spin_lock_init(&trans->hcmd_lock); spin_lock_init(&trans_pcie->irq_lock); /* W/A - seems to solve weird behavior. We need to remove this if we diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 4e7e6c0eede9..e2f21cfc2cd4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -309,7 +309,6 @@ enum iwl_trans_state { * @ops - pointer to iwl_trans_ops * @op_mode - pointer to the op_mode * @shrd - pointer to iwl_shared which holds shared data from the upper layer - * @hcmd_lock: protects HCMD * @reg_lock - protect hw register access * @dev - pointer to struct device * that represents the device * @irq - the irq number for the device @@ -326,7 +325,6 @@ struct iwl_trans { struct iwl_op_mode *op_mode; struct iwl_shared *shrd; enum iwl_trans_state state; - spinlock_t hcmd_lock; spinlock_t reg_lock; struct device *dev; -- cgit v1.2.3-70-g09d2 From fa23cb04b38a9950b21ee756e4419a737d496371 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:25 -0800 Subject: iwlwifi: make sta lock private & BH lock Now that the transport has its own locking, there's no need to have the sta_lock in the shared data. Also, it can be a BH lock as it's not used from IRQ handlers. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 141 ++++++++++++----------------- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 46 ++++------ drivers/net/wireless/iwlwifi/iwl-agn.c | 7 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 6 ++ drivers/net/wireless/iwlwifi/iwl-shared.h | 3 - 5 files changed, 88 insertions(+), 115 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 6b9af994cfa4..4bd50daeac1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -34,9 +34,10 @@ #include "iwl-agn.h" #include "iwl-trans.h" -/* priv->shrd->sta_lock must be held */ static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) { + lockdep_assert_held(&priv->sta_lock); + if (sta_id >= IWLAGN_STATION_COUNT) { IWL_ERR(priv, "invalid sta_id %u", sta_id); return -EINVAL; @@ -64,7 +65,6 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, struct iwl_rx_packet *pkt) { u8 sta_id = addsta->sta.sta_id; - unsigned long flags; int ret = -EIO; if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { @@ -76,7 +76,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", sta_id); - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock(&priv->sta_lock); switch (pkt->u.add_sta.status) { case ADD_STA_SUCCESS_MSK: @@ -118,7 +118,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, priv->stations[sta_id].sta.mode == STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", addsta->sta.addr); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock(&priv->sta_lock); return ret; } @@ -317,18 +317,17 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, const u8 *addr, bool is_ap, struct ieee80211_sta *sta, u8 *sta_id_r) { - unsigned long flags_spin; int ret = 0; u8 sta_id; struct iwl_addsta_cmd sta_cmd; *sta_id_r = 0; - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_bh(&priv->sta_lock); sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Unable to prepare station %pM for addition\n", addr); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_bh(&priv->sta_lock); return -EINVAL; } @@ -340,7 +339,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) { IWL_DEBUG_INFO(priv, "STA %d already in process of being " "added.\n", sta_id); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_bh(&priv->sta_lock); return -EEXIST; } @@ -348,24 +347,24 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not " "adding again.\n", sta_id, addr); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_bh(&priv->sta_lock); return -EEXIST; } priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_bh(&priv->sta_lock); /* Add station to device's station table */ ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) { - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_bh(&priv->sta_lock); IWL_ERR(priv, "Adding station %pM failed.\n", priv->stations[sta_id].sta.sta.addr); priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_bh(&priv->sta_lock); } *sta_id_r = sta_id; return ret; @@ -373,11 +372,11 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, /** * iwl_sta_ucode_deactivate - deactivate ucode status for a station - * - * priv->shrd->sta_lock must be held */ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) { + lockdep_assert_held(&priv->sta_lock); + /* Ucode must be active and driver must be non active */ if ((priv->stations[sta_id].used & (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) != @@ -396,8 +395,6 @@ static int iwl_send_remove_station(struct iwl_priv *priv, { struct iwl_rx_packet *pkt; int ret; - - unsigned long flags_spin; struct iwl_rem_sta_cmd rm_sta_cmd; struct iwl_host_cmd cmd = { @@ -429,11 +426,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv, switch (pkt->u.rem_sta.status) { case REM_STA_SUCCESS_MSK: if (!temporary) { - spin_lock_irqsave(&priv->shrd->sta_lock, - flags_spin); + spin_lock_bh(&priv->sta_lock); iwl_sta_ucode_deactivate(priv, sta_id); - spin_unlock_irqrestore(&priv->shrd->sta_lock, - flags_spin); + spin_unlock_bh(&priv->sta_lock); } IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); break; @@ -454,7 +449,6 @@ static int iwl_send_remove_station(struct iwl_priv *priv, int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, const u8 *addr) { - unsigned long flags; u8 tid; if (!iwl_is_ready(priv->shrd)) { @@ -475,7 +469,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, if (WARN_ON(sta_id == IWL_INVALID_STATION)) return -EINVAL; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", @@ -505,11 +499,11 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, if (WARN_ON(priv->num_stations < 0)) priv->num_stations = 0; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return iwl_send_remove_station(priv, addr, sta_id, false); out_err: - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return -EINVAL; } @@ -525,12 +519,11 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { int i; - unsigned long flags_spin; bool cleared = false; IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n"); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_bh(&priv->sta_lock); for (i = 0; i < IWLAGN_STATION_COUNT; i++) { if (ctx && ctx->ctxid != priv->stations[i].ctxid) continue; @@ -542,7 +535,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, cleared = true; } } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_bh(&priv->sta_lock); if (!cleared) IWL_DEBUG_INFO(priv, @@ -561,7 +554,6 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { struct iwl_addsta_cmd sta_cmd; struct iwl_link_quality_cmd lq; - unsigned long flags_spin; int i; bool found = false; int ret; @@ -574,7 +566,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_bh(&priv->sta_lock); for (i = 0; i < IWLAGN_STATION_COUNT; i++) { if (ctx->ctxid != priv->stations[i].ctxid) continue; @@ -601,20 +593,17 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) sizeof(struct iwl_link_quality_cmd)); send_lq = true; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, - flags_spin); + spin_unlock_bh(&priv->sta_lock); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) { - spin_lock_irqsave(&priv->shrd->sta_lock, - flags_spin); + spin_lock_bh(&priv->sta_lock); IWL_ERR(priv, "Adding station %pM failed.\n", priv->stations[i].sta.sta.addr); priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; - spin_unlock_irqrestore(&priv->shrd->sta_lock, - flags_spin); + spin_unlock_bh(&priv->sta_lock); } /* * Rate scaling has already been initialized, send @@ -623,12 +612,12 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) if (send_lq) iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_bh(&priv->sta_lock); priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; } } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_bh(&priv->sta_lock); if (!found) IWL_DEBUG_INFO(priv, "Restoring all known stations .... " "no stations to be restored.\n"); @@ -639,16 +628,15 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { - unsigned long flags; int sta_id = ctx->ap_sta_id; int ret; struct iwl_addsta_cmd sta_cmd; struct iwl_link_quality_cmd lq; bool active, have_lq = false; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return; } @@ -661,7 +649,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); if (active) { ret = iwl_send_remove_station( @@ -671,9 +659,9 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) IWL_ERR(priv, "failed to remove STA %pM (%d)\n", priv->stations[sta_id].sta.sta.addr, ret); } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) @@ -696,10 +684,9 @@ int iwl_get_free_ucode_key_offset(struct iwl_priv *priv) void iwl_dealloc_bcast_stations(struct iwl_priv *priv) { - unsigned long flags; int i; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); for (i = 0; i < IWLAGN_STATION_COUNT; i++) { if (!(priv->stations[i].used & IWL_STA_BCAST)) continue; @@ -711,7 +698,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv) kfree(priv->stations[i].lq); priv->stations[i].lq = NULL; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); } #ifdef CONFIG_IWLWIFI_DEBUG @@ -783,8 +770,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_link_quality_cmd *lq, u8 flags, bool init) { int ret = 0; - unsigned long flags_spin; - struct iwl_host_cmd cmd = { .id = REPLY_TX_LINK_QUALITY_CMD, .len = { sizeof(struct iwl_link_quality_cmd), }, @@ -796,12 +781,12 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, return -EINVAL; - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_bh(&priv->sta_lock); if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_bh(&priv->sta_lock); return -EINVAL; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_bh(&priv->sta_lock); iwl_dump_lq_cmd(priv, lq); if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) @@ -819,9 +804,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, IWL_DEBUG_INFO(priv, "init LQ command complete, " "clearing sta addition status for sta %d\n", lq->sta_id); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_bh(&priv->sta_lock); priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_bh(&priv->sta_lock); } return ret; } @@ -906,7 +891,6 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, int ret; u8 sta_id; struct iwl_link_quality_cmd *link_cmd; - unsigned long flags; if (sta_id_r) *sta_id_r = IWL_INVALID_STATION; @@ -920,9 +904,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, if (sta_id_r) *sta_id_r = sta_id; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); priv->stations[sta_id].used |= IWL_STA_LOCAL; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); /* Set up default rate scaling table in device's station table */ link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id); @@ -937,9 +921,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, if (ret) IWL_ERR(priv, "Link quality command failed (%d)\n", ret); - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return 0; } @@ -1100,14 +1084,13 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv, u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags) { - unsigned long flags; __le16 key_flags; struct iwl_addsta_cmd sta_cmd; int i; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags |= STA_KEY_FLG_MAP_KEY_MSK; @@ -1174,7 +1157,6 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, struct ieee80211_sta *sta) { - unsigned long flags; struct iwl_addsta_cmd sta_cmd; u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta); __le16 key_flags; @@ -1183,11 +1165,11 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, if (sta_id == IWL_INVALID_STATION) return -ENOENT; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) sta_id = IWL_INVALID_STATION; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); if (sta_id == IWL_INVALID_STATION) return 0; @@ -1287,21 +1269,20 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { struct iwl_link_quality_cmd *link_cmd; - unsigned long flags; u8 sta_id; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Unable to prepare broadcast station\n"); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return -EINVAL; } priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used |= IWL_STA_BCAST; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id); if (!link_cmd) { @@ -1310,9 +1291,9 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv, return -ENOMEM; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return 0; } @@ -1326,7 +1307,6 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv, int iwl_update_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { - unsigned long flags; struct iwl_link_quality_cmd *link_cmd; u8 sta_id = ctx->bcast_sta_id; @@ -1336,13 +1316,13 @@ int iwl_update_bcast_station(struct iwl_priv *priv, return -ENOMEM; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); if (priv->stations[sta_id].lq) kfree(priv->stations[sta_id].lq); else IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n"); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return 0; } @@ -1366,18 +1346,17 @@ int iwl_update_bcast_stations(struct iwl_priv *priv) */ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) { - unsigned long flags; struct iwl_addsta_cmd sta_cmd; lockdep_assert_held(&priv->shrd->mutex); /* Remove "disable" flag, to enable Tx for this TID */ - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } @@ -1385,7 +1364,6 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, int tid, u16 ssn) { - unsigned long flags; int sta_id; struct iwl_addsta_cmd sta_cmd; @@ -1395,14 +1373,14 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, if (sta_id == IWL_INVALID_STATION) return -ENXIO; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); priv->stations[sta_id].sta.station_flags_msk = 0; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } @@ -1410,7 +1388,6 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, int tid) { - unsigned long flags; int sta_id; struct iwl_addsta_cmd sta_cmd; @@ -1422,13 +1399,13 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, return -ENXIO; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); priv->stations[sta_id].sta.station_flags_msk = 0; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 59509d80f73f..4e69189a631d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -370,7 +370,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) info->driver_data[1] = dev_cmd; /* irqs already disabled/saved above when locking priv->shrd->lock */ - spin_lock(&priv->shrd->sta_lock); + spin_lock(&priv->sta_lock); if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) { u8 *qc = NULL; @@ -417,7 +417,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) !ieee80211_has_morefrags(fc)) priv->tid_data[sta_id][tid].seq_number = seq_number; - spin_unlock(&priv->shrd->sta_lock); + spin_unlock(&priv->sta_lock); spin_unlock_irqrestore(&priv->shrd->lock, flags); /* @@ -435,7 +435,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) drop_unlock_sta: if (dev_cmd) kmem_cache_free(priv->tx_cmd_pool, dev_cmd); - spin_unlock(&priv->shrd->sta_lock); + spin_unlock(&priv->sta_lock); drop_unlock_priv: spin_unlock_irqrestore(&priv->shrd->lock, flags); return -1; @@ -455,7 +455,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, return -ENXIO; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); tid_data = &priv->tid_data[sta_id][tid]; @@ -475,7 +475,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, IWL_WARN(priv, "Stopping AGG while state not ON " "or starting for %d on %d (%d)\n", sta_id, tid, priv->tid_data[sta_id][tid].agg.state); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return 0; } @@ -489,7 +489,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, tid_data->next_reclaimed); priv->tid_data[sta_id][tid].agg.state = IWL_EMPTYING_HW_QUEUE_DELBA; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return 0; } @@ -498,12 +498,10 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, turn_off: priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; - /* do not restore/save irqs */ - spin_unlock(&priv->shrd->sta_lock); - spin_lock(&priv->shrd->lock); + spin_unlock_bh(&priv->sta_lock); + spin_lock_irqsave(&priv->shrd->lock, flags); iwl_trans_tx_agg_disable(trans(priv), sta_id, tid); - spin_unlock_irqrestore(&priv->shrd->lock, flags); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); @@ -515,7 +513,6 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn) { struct iwl_tid_data *tid_data; - unsigned long flags; int sta_id; int ret; @@ -539,7 +536,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, if (ret) return ret; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); tid_data = &priv->tid_data[sta_id][tid]; tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); @@ -548,7 +545,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, ret = iwl_trans_tx_agg_alloc(trans(priv), sta_id, tid); if (ret) { - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return ret; } @@ -565,7 +562,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); return ret; } @@ -575,14 +572,13 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, { struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - unsigned long flags; u16 ssn; buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, sta_priv->sta_id, tid, buf_size, ssn); @@ -638,7 +634,7 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid) struct ieee80211_vif *vif; u8 *addr; - lockdep_assert_held(&priv->shrd->sta_lock); + lockdep_assert_held(&priv->sta_lock); addr = priv->stations[sta_id].sta.sta.addr; ctx = priv->stations[sta_id].ctxid; @@ -1005,7 +1001,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, int sta_id; int freed; struct ieee80211_tx_info *info; - unsigned long flags; struct sk_buff_head skbs; struct sk_buff *skb; struct iwl_rxon_context *ctx; @@ -1016,7 +1011,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> IWLAGN_TX_RES_RA_POS; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock(&priv->sta_lock); if (is_agg) iwl_rx_reply_tx_agg(priv, tx_resp); @@ -1106,7 +1101,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, } iwl_check_abort_status(priv, tx_resp->frame_count, status); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock(&priv->sta_lock); return 0; } @@ -1127,7 +1122,6 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, struct ieee80211_tx_info *info; struct ieee80211_hdr *hdr; struct sk_buff *skb; - unsigned long flags; int sta_id; int tid; int freed; @@ -1149,12 +1143,12 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, tid = ba_resp->tid; agg = &priv->tid_data[sta_id][tid].agg; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock(&priv->sta_lock); if (unlikely(!agg->wait_for_ba)) { if (unlikely(ba_resp->bitmap)) IWL_ERR(priv, "Received BA when not expected\n"); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock(&priv->sta_lock); return 0; } @@ -1165,7 +1159,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, * transmitted ... if not, it's too late anyway). */ if (iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, ba_resp_scd_ssn, 0, &reclaimed_skbs)) { - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock(&priv->sta_lock); return 0; } @@ -1230,6 +1224,6 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, ieee80211_tx_status_irqsafe(priv->hw, skb); } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock(&priv->sta_lock); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a7f3a7023d88..0090fab3aacb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -749,10 +749,9 @@ int iwl_alive_start(struct iwl_priv *priv) */ static void iwl_clear_driver_stations(struct iwl_priv *priv) { - unsigned long flags; struct iwl_rxon_context *ctx; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_bh(&priv->sta_lock); memset(priv->stations, 0, sizeof(priv->stations)); priv->num_stations = 0; @@ -770,7 +769,7 @@ static void iwl_clear_driver_stations(struct iwl_priv *priv) ctx->key_mapping_keys = 0; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_bh(&priv->sta_lock); } void iwl_down(struct iwl_priv *priv) @@ -1039,7 +1038,7 @@ static int iwl_init_drv(struct iwl_priv *priv) { int ret; - spin_lock_init(&priv->shrd->sta_lock); + spin_lock_init(&priv->sta_lock); mutex_init(&priv->shrd->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 6e5bf0a14609..dc57522594a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -719,6 +719,12 @@ struct iwl_priv { /*data shared among all the driver's layers */ struct iwl_shared *shrd; + /* + * protects the station table, if shrd->lock and sta_lock are + * needed, shrd->lock must be acquired first + */ + spinlock_t sta_lock; + /* ieee device used by generic ieee processing code */ struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index a6441623e6b1..3a0f0a4c58d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -360,8 +360,6 @@ struct iwl_cfg { * @nic: pointer to the nic data * @hw_params: see struct iwl_hw_params * @lock: protect general shared data - * @sta_lock: protects the station table. - * If lock and sta_lock are needed, lock must be acquired first. * @mutex: * @wait_command_queue: the wait_queue for SYNC host command nad uCode load * @eeprom: pointer to the eeprom/OTP image @@ -391,7 +389,6 @@ struct iwl_shared { struct iwl_hw_params hw_params; spinlock_t lock; - spinlock_t sta_lock; struct mutex mutex; wait_queue_head_t wait_command_queue; -- cgit v1.2.3-70-g09d2 From 4ff70fcdf3c424c3fdca253e7b7556f77eaf39be Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:26 -0800 Subject: iwlwifi: introduce statistics lock The statistics are currently only half-heartedly locked against concurrent reading & modification so introduce a lock to really protect them. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 16 +++++++--------- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 8 ++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 21 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 6 files changed, 40 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 988ee454a944..12acc81ed419 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -655,7 +655,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) struct iwl_sensitivity_data *data = NULL; struct statistics_rx_non_phy *rx_info; struct statistics_rx_phy *ofdm, *cck; - unsigned long flags; struct statistics_general_data statis; if (priv->disable_sens_cal) @@ -668,13 +667,13 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) return; } - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_bh(&priv->statistics.lock); rx_info = &priv->statistics.rx_non_phy; ofdm = &priv->statistics.rx_ofdm; cck = &priv->statistics.rx_cck; if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_bh(&priv->statistics.lock); return; } @@ -698,7 +697,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) statis.beacon_energy_c = le32_to_cpu(rx_info->beacon_energy_c); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_bh(&priv->statistics.lock); IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); @@ -958,7 +957,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) u16 stat_chnum = INITIALIZATION_VALUE; u8 rxon_band24; u8 stat_band24; - unsigned long flags; struct statistics_rx_non_phy *rx_info; /* @@ -983,13 +981,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) return; } - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_bh(&priv->statistics.lock); rx_info = &priv->statistics.rx_non_phy; if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_bh(&priv->statistics.lock); return; } @@ -1004,7 +1002,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) { IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n", rxon_chnum, rxon_band24); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_bh(&priv->statistics.lock); return; } @@ -1023,7 +1021,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER; chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER; - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_bh(&priv->statistics.lock); data->beacon_count++; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 5be0d3695d03..0f8dd0f96fa6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -88,6 +88,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) void iwlagn_temperature(struct iwl_priv *priv) { + lockdep_assert_held(&priv->statistics.lock); + /* store temperature from correct statistics (in Celsius) */ priv->temperature = le32_to_cpu(priv->statistics.common.temperature); iwl_tt_handler(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 30bb5bbb0cd7..bc21586aed63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -266,6 +266,8 @@ static bool iwlagn_good_ack_health(struct iwl_priv *priv, if (priv->agg_tids_count) return true; + lockdep_assert_held(&priv->statistics.lock); + old = &priv->statistics.tx; actual_delta = le32_to_cpu(cur->actual_ack_cnt) - @@ -509,6 +511,8 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n", len); + spin_lock(&priv->statistics.lock); + if (len == sizeof(struct iwl_bt_notif_statistics)) { struct iwl_bt_notif_statistics *stats; stats = &pkt->u.stats_bt; @@ -542,6 +546,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n", len, sizeof(struct iwl_bt_notif_statistics), sizeof(struct iwl_notif_statistics)); + spin_unlock(&priv->statistics.lock); return 0; } @@ -585,6 +590,9 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, } if (cfg(priv)->lib->temperature && change) cfg(priv)->lib->temperature(priv); + + spin_unlock(&priv->statistics.lock); + return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0090fab3aacb..47c788607024 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1233,6 +1233,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans) */ spin_lock_init(&trans(priv)->reg_lock); spin_lock_init(&priv->shrd->lock); + spin_lock_init(&priv->statistics.lock); /*********************** * 3. Read REV register diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index ad74138e1c70..628af563e4e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -920,6 +920,8 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) int p = 0; u32 flag; + lockdep_assert_held(&priv->statistics.lock); + flag = le32_to_cpu(priv->statistics.flag); p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag); @@ -967,6 +969,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, * the last statistics notification from uCode * might not reflect the current uCode activity */ + spin_lock_bh(&priv->statistics.lock); ofdm = &priv->statistics.rx_ofdm; cck = &priv->statistics.rx_cck; general = &priv->statistics.rx_non_phy; @@ -1363,6 +1366,8 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, accum_ht->unsupport_mcs, delta_ht->unsupport_mcs, max_ht->unsupport_mcs); + spin_unlock_bh(&priv->statistics.lock); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); return ret; @@ -1392,6 +1397,8 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, * the last statistics notification from uCode * might not reflect the current uCode activity */ + spin_lock_bh(&priv->statistics.lock); + tx = &priv->statistics.tx; accum_tx = &priv->accum_stats.tx; delta_tx = &priv->delta_stats.tx; @@ -1554,6 +1561,9 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, fmt_hex, "antenna C:", tx->tx_power.ant_c); } + + spin_unlock_bh(&priv->statistics.lock); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); return ret; @@ -1586,6 +1596,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, * the last statistics notification from uCode * might not reflect the current uCode activity */ + + spin_lock_bh(&priv->statistics.lock); + general = &priv->statistics.common; dbg = &priv->statistics.common.dbg; div = &priv->statistics.common.div; @@ -1670,6 +1683,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, accum_general->num_of_sos_states, delta_general->num_of_sos_states, max_general->num_of_sos_states); + + spin_unlock_bh(&priv->statistics.lock); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); return ret; @@ -1713,6 +1729,9 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, * the last statistics notification from uCode * might not reflect the current uCode activity */ + + spin_lock_bh(&priv->statistics.lock); + bt = &priv->statistics.bt_activity; accum_bt = &priv->accum_stats.bt_activity; @@ -1758,6 +1777,8 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, le32_to_cpu(priv->statistics.num_bt_kills), priv->statistics.accum_num_bt_kills); + spin_unlock_bh(&priv->statistics.lock); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index dc57522594a6..daf233026b5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -851,6 +851,7 @@ struct iwl_priv { struct statistics_bt_activity bt_activity; __le32 num_bt_kills, accum_num_bt_kills; #endif + spinlock_t lock; } statistics; #ifdef CONFIG_IWLWIFI_DEBUGFS struct { -- cgit v1.2.3-70-g09d2 From 08ae86ac3f9d9c9a60d2883c82cd72a5c66b94db Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:27 -0800 Subject: iwlwifi: remove shared lock Some data doesn't need protection, some of the lock places are simply useless, and some data can be protected with the mutex instead. Thus the shared lock can be removed by making those changes. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 7 ------- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 3 --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 3 --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 9 --------- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 +---- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ---- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 9 ++------- drivers/net/wireless/iwlwifi/iwl-shared.h | 1 - 9 files changed, 3 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 1527dec7a267..ccaeead29c2f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -63,12 +63,8 @@ /* NIC configuration for 5000 series */ static void iwl5000_nic_config(struct iwl_priv *priv) { - unsigned long flags; - iwl_rf_config(priv); - spin_lock_irqsave(&priv->shrd->lock, flags); - /* W/A : NIC is stuck in a reset state after Early PCIe power off * (PCIe power is lost before PERST# is asserted), * causing ME FW to lose ownership and not being able to obtain it back. @@ -76,9 +72,6 @@ static void iwl5000_nic_config(struct iwl_priv *priv) iwl_set_bits_mask_prph(trans(priv), APMG_PS_CTRL_REG, APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); - - - spin_unlock_irqrestore(&priv->shrd->lock, flags); } static struct iwl_sensitivity_ranges iwl5000_sensitivity = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 0f8dd0f96fa6..2470ca767589 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -710,7 +710,6 @@ int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, struct iwl_device_cmd *cmd) { - unsigned long flags; struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg; @@ -756,9 +755,7 @@ int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, /* FIXME: based on notification, adjust the prio_boost */ - spin_lock_irqsave(&priv->shrd->lock, flags); priv->bt_ci_compliance = coex->bt_ci_compliance; - spin_unlock_irqrestore(&priv->shrd->lock, flags); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index a7d67135e3dc..9895b807246b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -870,19 +870,16 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, { struct iwl_scale_tbl_info *tbl; bool full_concurrent = priv->bt_full_concurrent; - unsigned long flags; if (priv->bt_ant_couple_ok) { /* * Is there a need to switch between * full concurrency and 3-wire? */ - spin_lock_irqsave(&priv->shrd->lock, flags); if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) full_concurrent = true; else full_concurrent = false; - spin_unlock_irqrestore(&priv->shrd->lock, flags); } if ((priv->bt_traffic_load != priv->last_bt_traffic_load) || (priv->bt_full_concurrent != full_concurrent)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 73653a6cf32d..a8c790028d53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -590,8 +590,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - unsigned long flags; - ch_info = iwl_get_channel_info(priv, channel->band, channel->hw_value); if (!is_channel_valid(ch_info)) { @@ -600,8 +598,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) goto out; } - spin_lock_irqsave(&priv->shrd->lock, flags); - for_each_context(priv, ctx) { /* Configure HT40 channels */ if (ctx->ht.enabled != conf_is_ht(conf)) @@ -636,8 +632,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) ctx->vif); } - spin_unlock_irqrestore(&priv->shrd->lock, flags); - iwl_update_bcast_stations(priv); /* diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 4e69189a631d..2b722ccb730a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -259,18 +259,15 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_device_cmd *dev_cmd = NULL; struct iwl_tx_cmd *tx_cmd; - __le16 fc; u8 hdr_len; u16 len, seq_number = 0; u8 sta_id, tid = IWL_MAX_TID_COUNT; - unsigned long flags; bool is_agg = false; if (info->control.vif) ctx = iwl_rxon_ctx_from_vif(info->control.vif); - spin_lock_irqsave(&priv->shrd->lock, flags); if (iwl_is_rfkill(priv->shrd)) { IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); goto drop_unlock_priv; @@ -369,7 +366,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) info->driver_data[0] = ctx; info->driver_data[1] = dev_cmd; - /* irqs already disabled/saved above when locking priv->shrd->lock */ spin_lock(&priv->sta_lock); if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) { @@ -418,7 +414,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) priv->tid_data[sta_id][tid].seq_number = seq_number; spin_unlock(&priv->sta_lock); - spin_unlock_irqrestore(&priv->shrd->lock, flags); /* * Avoid atomic ops if it isn't an associated client. @@ -437,7 +432,6 @@ drop_unlock_sta: kmem_cache_free(priv->tx_cmd_pool, dev_cmd); spin_unlock(&priv->sta_lock); drop_unlock_priv: - spin_unlock_irqrestore(&priv->shrd->lock, flags); return -1; } @@ -445,7 +439,6 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid) { struct iwl_tid_data *tid_data; - unsigned long flags; int sta_id; sta_id = iwl_sta_id(sta); @@ -500,9 +493,7 @@ turn_off: spin_unlock_bh(&priv->sta_lock); - spin_lock_irqsave(&priv->shrd->lock, flags); iwl_trans_tx_agg_disable(trans(priv), sta_id, tid); - spin_unlock_irqrestore(&priv->shrd->lock, flags); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 47c788607024..ada9d9e4402b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -552,13 +552,11 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) { struct iwl_ct_kill_config cmd; struct iwl_ct_kill_throttling_config adv_cmd; - unsigned long flags; int ret = 0; - spin_lock_irqsave(&priv->shrd->lock, flags); iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + priv->thermal_throttle.ct_kill_toggle = false; if (cfg(priv)->base_params->support_ct_kill_exit) { @@ -1232,7 +1230,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans) * we should init now */ spin_lock_init(&trans(priv)->reg_lock); - spin_lock_init(&priv->shrd->lock); spin_lock_init(&priv->statistics.lock); /*********************** diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index daf233026b5e..5b537dbe0af4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -719,10 +719,6 @@ struct iwl_priv { /*data shared among all the driver's layers */ struct iwl_shared *shrd; - /* - * protects the station table, if shrd->lock and sta_lock are - * needed, shrd->lock must be acquired first - */ spinlock_t sta_lock; /* ieee device used by generic ieee processing code */ diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 9fba532d35cd..dcee30f0d629 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -779,8 +779,6 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, goto out; } - spin_lock_irq(&priv->shrd->lock); - priv->current_ht_config.smps = conf->smps_mode; /* Configure HT40 channels */ @@ -797,8 +795,6 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, iwl_set_rxon_ht(priv, ht_conf); iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif); - spin_unlock_irq(&priv->shrd->lock); - iwl_set_rate(priv); /* * at this point, staging_rxon has the @@ -1133,7 +1129,6 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; struct iwl_rxon_context *ctx = vif_priv->ctx; - unsigned long flags; int q; if (WARN_ON(!ctx)) @@ -1153,7 +1148,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, q = AC_NUM - 1 - queue; - spin_lock_irqsave(&priv->shrd->lock, flags); + mutex_lock(&priv->shrd->mutex); ctx->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); @@ -1165,7 +1160,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0; - spin_unlock_irqrestore(&priv->shrd->lock, flags); + mutex_unlock(&priv->shrd->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 3a0f0a4c58d3..7720fc34c278 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -388,7 +388,6 @@ struct iwl_shared { struct iwl_nic *nic; struct iwl_hw_params hw_params; - spinlock_t lock; struct mutex mutex; wait_queue_head_t wait_command_queue; -- cgit v1.2.3-70-g09d2 From 5c40d8603d8ed03aa851d20ad8a9155fc79a1b07 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:28 -0800 Subject: iwlwifi: make EXIT_PENDING depend on mac80211 There's no reason to set EXIT_PENDING when we start removing the module, as mac80211 will cleanly shut down the device in this case. Additionally, there's no point in rejecting commands to the device when we're cleaning up as that only leads to unwanted errors from mac80211 being printed, such as failed to remove key (...) from hardware (-16) Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-mac80211.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-scan.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 7 ------- 5 files changed, 1 insertion(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index a8c790028d53..7a86a359e573 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -422,9 +422,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) lockdep_assert_held(&priv->shrd->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) - return -EINVAL; - if (!iwl_is_alive(priv->shrd)) return -EBUSY; @@ -560,9 +557,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&priv->shrd->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) - goto out; - if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) { IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); goto out; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ada9d9e4402b..c14eda048948 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1378,12 +1378,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) iwl_dbgfs_unregister(priv); - /* ieee80211_unregister_hw call wil cause iwlagn_mac_stop to - * to be called and iwl_down since we are removing the device - * we need to set STATUS_EXIT_PENDING bit. - */ - set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); - iwl_testmode_cleanup(priv); iwlagn_mac_unregister(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index dcee30f0d629..7f63ba93ba5d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -649,8 +649,6 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_STOP: IWL_DEBUG_HT(priv, "stop Rx\n"); ret = iwl_sta_rx_agg_stop(priv, sta, tid); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) - ret = 0; break; case IEEE80211_AMPDU_TX_START: if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) @@ -666,8 +664,6 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", priv->agg_tids_count); } - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) - ret = 0; if (!priv->agg_tids_count && cfg(priv)->ht_params && cfg(priv)->ht_params->use_rts_for_aggregation) { /* diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 42ee1c410efd..766572b9ac89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -69,8 +69,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) if (!test_bit(STATUS_READY, &priv->shrd->status) || !test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) || !test_bit(STATUS_SCAN_HW, &priv->shrd->status) || - test_bit(STATUS_FW_ERROR, &priv->shrd->status) || - test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + test_bit(STATUS_FW_ERROR, &priv->shrd->status)) return -EIO; ret = iwl_trans_send_cmd(trans(priv), &cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 1cb1dd29b3fe..de2a0d91d658 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -914,9 +914,6 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) return -EINVAL; - if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status)) - return -EBUSY; - ret = iwl_enqueue_hcmd(trans, cmd); if (ret < 0) { IWL_DEBUG_QUIET_RFKILL(trans, @@ -938,10 +935,6 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); - if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status)) - return -EBUSY; - - if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) { IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n", get_cmd_string(cmd->id)); -- cgit v1.2.3-70-g09d2 From fb5fe5b9da167f25fd44818327338eeec20c2a5a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:29 -0800 Subject: iwlwifi: simplify auth/assoc flow With mac80211 now giving us station information (via the sta_state callback) before auth/assoc we can get rid of tx_sync by adding the station early for the case of managed interfaces. Keep AP mode actions the same for now. As we now get the BSSID early, we can also get rid of iwl_reprogram_ap_sta(). We can still optimise the number of RXONs we send to the device, but that can be done later. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 7 - drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 45 ------ drivers/net/wireless/iwlwifi/iwl-agn.h | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 3 - drivers/net/wireless/iwlwifi/iwl-mac80211.c | 207 ++++++++++++---------------- 5 files changed, 90 insertions(+), 173 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 7a86a359e573..e806ad82e7e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -274,8 +274,6 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, } memcpy(active, &ctx->staging, sizeof(*active)); - iwl_reprogram_ap_sta(priv, ctx); - /* IBSS beacon needs to be sent after setting assoc */ if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC)) if (iwlagn_update_beacon(priv, ctx->vif)) @@ -431,10 +429,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) if (!ctx->is_active) return 0; - /* override BSSID if necessary due to preauth */ - if (ctx->preauth_bssid) - memcpy(ctx->staging.bssid_addr, ctx->bssid, ETH_ALEN); - /* always get timestamp with Rx frame */ ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; @@ -920,7 +914,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, if (!priv->disable_chain_noise_cal) iwlagn_chain_noise_reset(priv); priv->start_calib = 1; - WARN_ON(ctx->preauth_bssid); } if (changes & BSS_CHANGED_IBSS) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 4bd50daeac1a..222a8f46365f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -626,51 +626,6 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) "complete.\n"); } -void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) -{ - int sta_id = ctx->ap_sta_id; - int ret; - struct iwl_addsta_cmd sta_cmd; - struct iwl_link_quality_cmd lq; - bool active, have_lq = false; - - spin_lock_bh(&priv->sta_lock); - if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - spin_unlock_bh(&priv->sta_lock); - return; - } - - memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); - sta_cmd.mode = 0; - if (priv->stations[sta_id].lq) { - memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq)); - have_lq = true; - } - - active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE; - priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; - spin_unlock_bh(&priv->sta_lock); - - if (active) { - ret = iwl_send_remove_station( - priv, priv->stations[sta_id].sta.sta.addr, - sta_id, true); - if (ret) - IWL_ERR(priv, "failed to remove STA %pM (%d)\n", - priv->stations[sta_id].sta.sta.addr, ret); - } - spin_lock_bh(&priv->sta_lock); - priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; - spin_unlock_bh(&priv->sta_lock); - - ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); - if (ret) - IWL_ERR(priv, "failed to re-add STA %pM (%d)\n", - priv->stations[sta_id].sta.sta.addr, ret); - if (have_lq) - iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); -} - int iwl_get_free_ucode_key_offset(struct iwl_priv *priv) { int i; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index ef0cdf5b32fa..a142a197b2e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -227,7 +227,6 @@ void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id, struct iwl_link_quality_cmd *link_cmd); int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_link_quality_cmd *lq, u8 flags, bool init); -void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, struct iwl_device_cmd *cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 5b537dbe0af4..9ea9002cc839 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -671,9 +671,6 @@ struct iwl_rxon_context { u8 extension_chan_offset; } ht; - u8 bssid[ETH_ALEN]; - bool preauth_bssid; - bool last_tx_rejected; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 7f63ba93ba5d..005763fa38ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -692,12 +692,9 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; bool is_ap = vif->type == NL80211_IFTYPE_STATION; - int ret = 0; + int ret; u8 sta_id; - IWL_DEBUG_MAC80211(priv, "received request to add station %pM\n", - sta->addr); - mutex_lock(&priv->shrd->mutex); IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", sta->addr); sta_priv->sta_id = IWL_INVALID_STATION; @@ -712,16 +709,98 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_ERR(priv, "Unable to add station %pM (%d)\n", sta->addr, ret); /* Should we return success if return code is EEXIST ? */ - goto out; + return ret; } sta_priv->sta_id = sta_id; - /* Initialize rate scaling */ - IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", - sta->addr); - iwl_rs_rate_init(priv, sta, sta_id); - out: + return 0; +} + +static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); + struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; + int ret; + + IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", + sta->addr); + ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr); + if (ret) + IWL_DEBUG_QUIET_RFKILL(priv, "Error removing station %pM\n", + sta->addr); + return ret; +} + +static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + enum ieee80211_sta_state old_state, + enum ieee80211_sta_state new_state) +{ + struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); + enum { + NONE, ADD, REMOVE, RATE_INIT, ADD_RATE_INIT, + } op = NONE; + int ret; + + IWL_DEBUG_MAC80211(priv, "station %pM state change %d->%d\n", + sta->addr, old_state, new_state); + + mutex_lock(&priv->shrd->mutex); + if (vif->type == NL80211_IFTYPE_STATION) { + if (old_state == IEEE80211_STA_NOTEXIST && + new_state == IEEE80211_STA_NONE) + op = ADD; + else if (old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST) + op = REMOVE; + else if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC) + op = RATE_INIT; + } else { + if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC) + op = ADD_RATE_INIT; + else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTH) + op = REMOVE; + } + + switch (op) { + case ADD: + ret = iwlagn_mac_sta_add(hw, vif, sta); + break; + case REMOVE: + ret = iwlagn_mac_sta_remove(hw, vif, sta); + break; + case ADD_RATE_INIT: + ret = iwlagn_mac_sta_add(hw, vif, sta); + if (ret) + break; + /* fall through */ + case RATE_INIT: + /* Initialize rate scaling */ + IWL_DEBUG_INFO(priv, + "Initializing rate scaling for station %pM\n", + sta->addr); + iwl_rs_rate_init(priv, sta, iwl_sta_id(sta)); + ret = 0; + break; + default: + ret = 0; + break; + } + + /* + * mac80211 might WARN if we fail, but due the way we + * (badly) handle hard rfkill, we might fail here + */ + if (iwl_is_rfkill(priv->shrd)) + ret = 0; + mutex_unlock(&priv->shrd->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -1003,86 +1082,6 @@ static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) return 0; } -static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const u8 *bssid, - enum ieee80211_tx_sync_type type) -{ - struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; - struct iwl_rxon_context *ctx = vif_priv->ctx; - int ret; - u8 sta_id; - - if (ctx->ctxid != IWL_RXON_CTX_PAN) - return 0; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); - - if (iwl_is_associated_ctx(ctx)) { - ret = 0; - goto out; - } - - if (ctx->preauth_bssid || test_bit(STATUS_SCAN_HW, - &priv->shrd->status)) { - ret = -EBUSY; - goto out; - } - - ret = iwl_add_station_common(priv, ctx, bssid, true, NULL, &sta_id); - if (ret) - goto out; - - if (WARN_ON(sta_id != ctx->ap_sta_id)) { - ret = -EIO; - goto out_remove_sta; - } - - memcpy(ctx->bssid, bssid, ETH_ALEN); - ctx->preauth_bssid = true; - - ret = iwlagn_commit_rxon(priv, ctx); - - if (ret == 0) - goto out; - - out_remove_sta: - iwl_remove_station(priv, sta_id, bssid); - out: - mutex_unlock(&priv->shrd->mutex); - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return ret; -} - -static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const u8 *bssid, - enum ieee80211_tx_sync_type type) -{ - struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; - struct iwl_rxon_context *ctx = vif_priv->ctx; - - if (ctx->ctxid != IWL_RXON_CTX_PAN) - return; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); - - if (iwl_is_associated_ctx(ctx)) - goto out; - - iwl_remove_station(priv, ctx->ap_sta_id, bssid); - ctx->preauth_bssid = false; - /* no need to commit */ - out: - mutex_unlock(&priv->shrd->mutex); - IWL_DEBUG_MAC80211(priv, "leave\n"); -} - static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, enum ieee80211_rssi_event rssi_event) { @@ -1471,29 +1470,6 @@ static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, return ret; } -static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); - struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - int ret; - - IWL_DEBUG_MAC80211(priv, "enter: received request to remove " - "station %pM\n", sta->addr); - mutex_lock(&priv->shrd->mutex); - IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", - sta->addr); - ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr); - if (ret) - IWL_DEBUG_QUIET_RFKILL(priv, "Error removing station %pM\n", - sta->addr); - mutex_unlock(&priv->shrd->mutex); - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return ret; -} - static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) { struct iwl_addsta_cmd cmd = { @@ -1559,8 +1535,7 @@ struct ieee80211_ops iwlagn_hw_ops = { .ampdu_action = iwlagn_mac_ampdu_action, .hw_scan = iwlagn_mac_hw_scan, .sta_notify = iwlagn_mac_sta_notify, - .sta_add = iwlagn_mac_sta_add, - .sta_remove = iwlagn_mac_sta_remove, + .sta_state = iwlagn_mac_sta_state, .channel_switch = iwlagn_mac_channel_switch, .flush = iwlagn_mac_flush, .tx_last_beacon = iwlagn_mac_tx_last_beacon, @@ -1569,8 +1544,6 @@ struct ieee80211_ops iwlagn_hw_ops = { .rssi_callback = iwlagn_mac_rssi_callback, CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd) CFG80211_TESTMODE_DUMP(iwlagn_mac_testmode_dump) - .tx_sync = iwlagn_mac_tx_sync, - .finish_tx_sync = iwlagn_mac_finish_tx_sync, .set_tim = iwlagn_mac_set_tim, }; -- cgit v1.2.3-70-g09d2 From a8bceb392a739321ec20d03a91a86ebdde9c07bb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:30 -0800 Subject: iwlwifi: remove per-device debug level There's no need for the per-device debug level that we expose in debugfs since the module parameter is writable in sysfs. At the same time, simplify code by changing iwl_get_debug_level(shrd) & IWL_DL_ISR) to iwl_have_debug_level(IWL_DL_ISR) Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 10 ++--- drivers/net/wireless/iwlwifi/iwl-debug.c | 4 +- drivers/net/wireless/iwlwifi/iwl-debug.h | 12 +++--- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 55 +----------------------- drivers/net/wireless/iwlwifi/iwl-shared.h | 27 +----------- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 10 ++--- 6 files changed, 22 insertions(+), 96 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8551c95e7437..8d25fd6be645 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -836,7 +836,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) unsigned long reload_jiffies; #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS) + if (iwl_have_debug_level(IWL_DL_FW_ERRORS)) iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS); #endif @@ -1004,7 +1004,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv) { u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE; - if (iwl_get_debug_level(priv->shrd) & IWL_DL_TX) { + if (iwl_have_debug_level(IWL_DL_TX)) { if (!priv->tx_traffic) { priv->tx_traffic = kzalloc(traffic_size, GFP_KERNEL); @@ -1012,7 +1012,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv) return -ENOMEM; } } - if (iwl_get_debug_level(priv->shrd) & IWL_DL_RX) { + if (iwl_have_debug_level(IWL_DL_RX)) { if (!priv->rx_traffic) { priv->rx_traffic = kzalloc(traffic_size, GFP_KERNEL); @@ -1039,7 +1039,7 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, __le16 fc; u16 len; - if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_TX))) + if (likely(!iwl_have_debug_level(IWL_DL_TX))) return; if (!priv->tx_traffic) @@ -1063,7 +1063,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, __le16 fc; u16 len; - if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_RX))) + if (likely(!iwl_have_debug_level(IWL_DL_RX))) return; if (!priv->rx_traffic) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.c b/drivers/net/wireless/iwlwifi/iwl-debug.c index 4bc2e70051d6..059efabda184 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.c +++ b/drivers/net/wireless/iwlwifi/iwl-debug.c @@ -104,7 +104,7 @@ void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only, } #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) -void __iwl_dbg(struct iwl_shared *shared, struct device *dev, +void __iwl_dbg(struct device *dev, u32 level, bool limit, const char *function, const char *fmt, ...) { @@ -116,7 +116,7 @@ void __iwl_dbg(struct iwl_shared *shared, struct device *dev, va_start(args, fmt); vaf.va = &args; #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(shared) & level && + if (iwl_have_debug_level(level) && (!limit || net_ratelimit())) dev_err(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U', function, &vaf); diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 01b23303d736..163d259198be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -47,12 +47,12 @@ void __iwl_crit(struct device *dev, const char *fmt, ...); #define IWL_CRIT(m, f, a...) __iwl_crit(trans(m)->dev, f, ## a) #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) -void __iwl_dbg(struct iwl_shared *shared, struct device *dev, +void __iwl_dbg(struct device *dev, u32 level, bool limit, const char *function, const char *fmt, ...); #else static inline void -__iwl_dbg(struct iwl_shared *shared, struct device *dev, +__iwl_dbg(struct device *dev, u32 level, bool limit, const char *function, const char *fmt, ...) {} @@ -65,14 +65,14 @@ do { \ } while (0) #define IWL_DEBUG(m, level, fmt, args...) \ - __iwl_dbg((m)->shrd, trans(m)->dev, level, false, __func__, fmt, ##args) + __iwl_dbg(trans(m)->dev, level, false, __func__, fmt, ##args) #define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ - __iwl_dbg((m)->shrd, trans(m)->dev, level, true, __func__, fmt, ##args) + __iwl_dbg(trans(m)->dev, level, true, __func__, fmt, ##args) #ifdef CONFIG_IWLWIFI_DEBUG #define iwl_print_hex_dump(m, level, p, len) \ do { \ - if (iwl_get_debug_level((m)->shrd) & level) \ + if (iwl_have_debug_level(level)) \ print_hex_dump(KERN_DEBUG, "iwl data: ", \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ } while (0) @@ -82,7 +82,7 @@ do { \ IWL_ERR(m, fmt, ##args); \ else \ __iwl_err(trans(m)->dev, true, \ - !(iwl_get_debug_level((m)->shrd) & IWL_DL_RADIO),\ + !iwl_have_debug_level(IWL_DL_RADIO), \ fmt, ##args); \ } while (0) #else diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 628af563e4e1..dd502e82e410 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -845,8 +845,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, IWL_ERR(priv, "Can not allocate buffer\n"); return -ENOMEM; } - if (priv->tx_traffic && - (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) { + if (priv->tx_traffic && iwl_have_debug_level(IWL_DL_TX)) { ptr = priv->tx_traffic; pos += scnprintf(buf + pos, bufsz - pos, "Tx Traffic idx: %u\n", priv->tx_traffic_idx); @@ -864,8 +863,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, } } - if (priv->rx_traffic && - (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) { + if (priv->rx_traffic && iwl_have_debug_level(IWL_DL_RX)) { ptr = priv->rx_traffic; pos += scnprintf(buf + pos, bufsz - pos, "Rx Traffic idx: %u\n", priv->rx_traffic_idx); @@ -2507,52 +2505,6 @@ DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); DEBUGFS_READ_FILE_OPS(reply_tx_error); DEBUGFS_WRITE_FILE_OPS(echo_test); -#ifdef CONFIG_IWLWIFI_DEBUG -static ssize_t iwl_dbgfs_debug_level_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - struct iwl_shared *shrd = priv->shrd; - char buf[11]; - int len; - - len = scnprintf(buf, sizeof(buf), "0x%.8x", - iwl_get_debug_level(shrd)); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t iwl_dbgfs_debug_level_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - struct iwl_shared *shrd = priv->shrd; - char buf[11]; - unsigned long val; - int ret; - - if (count > sizeof(buf)) - return -EINVAL; - - memset(buf, 0, sizeof(buf)); - if (copy_from_user(buf, user_buf, count)) - return -EFAULT; - - ret = strict_strtoul(buf, 0, &val); - if (ret) - return ret; - - shrd->dbg_level_dev = val; - if (iwl_alloc_traffic_mem(priv)) - IWL_ERR(priv, "Not enough memory to generate traffic log\n"); - - return count; -} -DEBUGFS_READ_WRITE_FILE_OPS(debug_level); -#endif /* CONFIG_IWLWIFI_DEBUG */ - /* * Create the debugfs files and directories * @@ -2617,9 +2569,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR); if (iwl_advanced_bt_coexist(priv)) DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); -#ifdef CONFIG_IWLWIFI_DEBUG - DEBUGFS_ADD_FILE(debug_level, dir_debug, S_IRUSR | S_IWUSR); -#endif DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 7720fc34c278..239dfbc57bee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -346,8 +346,6 @@ struct iwl_cfg { /** * struct iwl_shared - shared fields for all the layers of the driver * - * @dbg_level_dev: dbg level set per device. Prevails on - * iwlagn_mod_params.debug_level if set (!= 0) * @ucode_owner: IWL_OWNERSHIP_* * @cmd_queue: command queue number * @status: STATUS_* @@ -370,10 +368,6 @@ struct iwl_cfg { * @device_pointers: pointers to ucode event tables */ struct iwl_shared { -#ifdef CONFIG_IWLWIFI_DEBUG - u32 dbg_level_dev; -#endif /* CONFIG_IWLWIFI_DEBUG */ - #define IWL_OWNERSHIP_DRIVER 0 #define IWL_OWNERSHIP_TM 1 u8 ucode_owner; @@ -417,27 +411,10 @@ struct iwl_shared { #define trans(_m) ((_m)->shrd->trans) #define hw_params(_m) ((_m)->shrd->hw_params) -#ifdef CONFIG_IWLWIFI_DEBUG -/* - * iwl_get_debug_level: Return active debug level for device - * - * Using sysfs it is possible to set per device debug level. This debug - * level will be used if set, otherwise the global debug level which can be - * set via module parameter is used. - */ -static inline u32 iwl_get_debug_level(struct iwl_shared *shrd) -{ - if (shrd->dbg_level_dev) - return shrd->dbg_level_dev; - else - return iwlagn_mod_params.debug_level; -} -#else -static inline u32 iwl_get_debug_level(struct iwl_shared *shrd) +static inline bool iwl_have_debug_level(u32 level) { - return iwlagn_mod_params.debug_level; + return iwlagn_mod_params.debug_level & level; } -#endif static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 2c910fddaaf6..6495945637b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -881,7 +881,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, } #ifdef CONFIG_IWLWIFI_DEBUG - if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log) + if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log) size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; #else @@ -901,7 +901,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, if (!*buf) return -ENOMEM; } - if ((iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) || full_log) { + if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) { /* * if uCode has wrapped back to top of log, * start at the oldest entry, @@ -960,7 +960,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) inta = trans_pcie->inta; #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) { + if (iwl_have_debug_level(IWL_DL_ISR)) { /* just for debug */ inta_mask = iwl_read32(trans, CSR_INT_MASK); IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ", @@ -989,7 +989,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) } #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { + if (iwl_have_debug_level(IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) { IWL_DEBUG_ISR(trans, "Scheduler finished to transmit " @@ -1301,7 +1301,7 @@ static irqreturn_t iwl_isr(int irq, void *data) } #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { + if (iwl_have_debug_level(IWL_DL_ISR)) { inta_fh = iwl_read32(trans, CSR_FH_INT_STATUS); IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, " "fh 0x%08x\n", inta, inta_mask, inta_fh); -- cgit v1.2.3-70-g09d2 From 54708d8df355b7ecf1d25d4049336840e6107d96 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:31 -0800 Subject: iwlwifi: remove SKU from config There's no SKU override, we always just use it from EEPROM. As such, we can remove it from the config and use it in hw_param only. Since iwl_eeprom_check_sku() really needs to fill it in also rename that to iwl_eeprom_init_hw_params(). Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 ++--- drivers/net/wireless/iwlwifi/iwl-core.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 20 +++++++++----------- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 2 +- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-shared.h | 2 -- 7 files changed, 19 insertions(+), 24 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 2470ca767589..79ac7cb1701b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -235,7 +235,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK | IWL_PAN_SCD_MULTICAST_MSK; - if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE) + if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK; IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c14eda048948..e1bf12578f87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1124,13 +1124,12 @@ static void iwl_set_hw_params(struct iwl_priv *priv) get_order(IWL_RX_BUF_SIZE_4K); if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL) - cfg(priv)->sku &= ~EEPROM_SKU_CAP_11N_ENABLE; + hw_params(priv).sku &= ~EEPROM_SKU_CAP_11N_ENABLE; hw_params(priv).num_ampdu_queues = cfg(priv)->base_params->num_of_ampdu_queues; hw_params(priv).shadow_reg_enable = cfg(priv)->base_params->shadow_reg_enable; - hw_params(priv).sku = cfg(priv)->sku; hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout; /* Device-specific setup */ @@ -1257,7 +1256,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans) if (err) goto out_free_eeprom; - err = iwl_eeprom_check_sku(priv); + err = iwl_eeprom_init_hw_params(priv); if (err) goto out_free_eeprom; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8d25fd6be645..c5df3e3d975b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -137,7 +137,7 @@ int iwl_init_geos(struct iwl_priv *priv) sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; - if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE) + if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) iwl_init_ht_hw_capab(priv, &sband->ht_cap, IEEE80211_BAND_5GHZ); @@ -147,7 +147,7 @@ int iwl_init_geos(struct iwl_priv *priv) sband->bitrates = rates; sband->n_bitrates = IWL_RATE_COUNT_LEGACY; - if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE) + if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) iwl_init_ht_hw_capab(priv, &sband->ht_cap, IEEE80211_BAND_2GHZ); @@ -202,11 +202,11 @@ int iwl_init_geos(struct iwl_priv *priv) priv->tx_power_next = max_tx_power; if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && - cfg(priv)->sku & EEPROM_SKU_CAP_BAND_52GHZ) { + hw_params(priv).sku & EEPROM_SKU_CAP_BAND_52GHZ) { IWL_INFO(priv, "Incorrectly detected BG card as ABG. " "Please send your %s to maintainer.\n", trans(priv)->hw_id_str); - cfg(priv)->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; + hw_params(priv).sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; } IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 07e93787bce8..d8668bccc083 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -252,26 +252,24 @@ err: } -int iwl_eeprom_check_sku(struct iwl_priv *priv) +int iwl_eeprom_init_hw_params(struct iwl_priv *priv) { struct iwl_shared *shrd = priv->shrd; u16 radio_cfg; - if (!cfg(priv)->sku) { - /* not using sku overwrite */ - cfg(priv)->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP); - if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE && - !cfg(priv)->ht_params) { - IWL_ERR(priv, "Invalid 11n configuration\n"); - return -EINVAL; - } + hw_params(priv).sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP); + if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE && + !cfg(priv)->ht_params) { + IWL_ERR(priv, "Invalid 11n configuration\n"); + return -EINVAL; } - if (!cfg(priv)->sku) { + + if (!hw_params(priv).sku) { IWL_ERR(priv, "Invalid device sku\n"); return -EINVAL; } - IWL_INFO(priv, "Device SKU: 0x%X\n", cfg(priv)->sku); + IWL_INFO(priv, "Device SKU: 0x%X\n", hw_params(priv).sku); if (!cfg(priv)->valid_tx_ant && !cfg(priv)->valid_rx_ant) { /* not using .cfg overwrite */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index cbb86116917b..3b17056d5675 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -309,7 +309,7 @@ struct iwl_eeprom_ops { int iwl_eeprom_init(struct iwl_trans *trans, u32 hw_rev); void iwl_eeprom_free(struct iwl_shared *shrd); int iwl_eeprom_check_version(struct iwl_priv *priv); -int iwl_eeprom_check_sku(struct iwl_priv *priv); +int iwl_eeprom_init_hw_params(struct iwl_priv *priv); const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset); u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset); int iwl_init_channel_map(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 005763fa38ab..8b26f3217823 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -161,7 +161,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, hw->flags |= IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; - if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE) + if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | IEEE80211_HW_SUPPORTS_STATIC_SMPS; @@ -633,7 +633,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", sta->addr, tid); - if (!(cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)) + if (!(hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)) return -EACCES; IWL_DEBUG_MAC80211(priv, "enter\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 239dfbc57bee..11184f1c4365 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -282,7 +282,6 @@ enum iwl_led_mode { * @max_data_size: The maximal length of the fw data section * @valid_tx_ant: valid transmit antenna * @valid_rx_ant: valid receive antenna - * @sku: sku information from EEPROM * @eeprom_ver: EEPROM version * @eeprom_calib_ver: EEPROM calibration version * @lib: pointer to the lib ops @@ -321,7 +320,6 @@ struct iwl_cfg { const u32 max_inst_size; u8 valid_tx_ant; u8 valid_rx_ant; - u16 sku; u16 eeprom_ver; u16 eeprom_calib_ver; const struct iwl_lib_ops *lib; -- cgit v1.2.3-70-g09d2 From 7e79a3937a44b1dc5f457e6dbb8c50e93719286a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:32 -0800 Subject: iwlwifi: use valid TX/RX antenna from hw_params It's not really a good idea to write to the global static configuration. Use the valid TX/RX antenna information only from the HW params struct except in the case where the values from the config are used to override the values from the EEPROM. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 7 +++-- drivers/net/wireless/iwlwifi/iwl-2000.c | 7 +++-- drivers/net/wireless/iwlwifi/iwl-5000.c | 16 ++++++------ drivers/net/wireless/iwlwifi/iwl-6000.c | 7 +++-- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 9 ++++--- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 38 +++++++++++++++------------- 8 files changed, 46 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 605ee3df1d82..22eb0622ac21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -131,14 +131,13 @@ static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); - hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant); + hw_params(priv).tx_chains_num = + num_of_ant(hw_params(priv).valid_tx_ant); if (cfg(priv)->rx_with_siso_diversity) hw_params(priv).rx_chains_num = 1; else hw_params(priv).rx_chains_num = - num_of_ant(cfg(priv)->valid_rx_ant); - hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant; - hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant; + num_of_ant(hw_params(priv).valid_rx_ant); iwl1000_set_ct_threshold(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index e6e8c79a80d8..43d17a4564e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -127,14 +127,13 @@ static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); - hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant); + hw_params(priv).tx_chains_num = + num_of_ant(hw_params(priv).valid_tx_ant); if (cfg(priv)->rx_with_siso_diversity) hw_params(priv).rx_chains_num = 1; else hw_params(priv).rx_chains_num = - num_of_ant(cfg(priv)->valid_rx_ant); - hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant; - hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant; + num_of_ant(hw_params(priv).valid_rx_ant); iwl2000_set_ct_threshold(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index ccaeead29c2f..8cdc4a35a973 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -167,10 +167,10 @@ static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant); - hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant); - hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant; - hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant; + hw_params(priv).tx_chains_num = + num_of_ant(hw_params(priv).valid_tx_ant); + hw_params(priv).rx_chains_num = + num_of_ant(hw_params(priv).valid_rx_ant); iwl5000_set_ct_threshold(priv); @@ -190,10 +190,10 @@ static void iwl5150_hw_set_hw_params(struct iwl_priv *priv) hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant); - hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant); - hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant; - hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant; + hw_params(priv).tx_chains_num = + num_of_ant(hw_params(priv).valid_tx_ant); + hw_params(priv).rx_chains_num = + num_of_ant(hw_params(priv).valid_rx_ant); iwl5150_set_ct_threshold(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 223e60a1b79d..720e8e6e62ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -149,14 +149,13 @@ static void iwl6000_hw_set_hw_params(struct iwl_priv *priv) hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant); + hw_params(priv).tx_chains_num = + num_of_ant(hw_params(priv).valid_tx_ant); if (cfg(priv)->rx_with_siso_diversity) hw_params(priv).rx_chains_num = 1; else hw_params(priv).rx_chains_num = - num_of_ant(cfg(priv)->valid_rx_ant); - hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant; - hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant; + num_of_ant(hw_params(priv).valid_rx_ant); iwl6000_set_ct_threshold(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 12acc81ed419..84fc5ce91b35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -848,7 +848,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, * connect the first valid tx chain */ first_chain = - find_first_chain(cfg(priv)->valid_tx_ant); + find_first_chain(hw_params(priv).valid_tx_ant); data->disconn_array[first_chain] = 0; active_chains |= BIT(first_chain); IWL_DEBUG_CALIB(priv, @@ -1082,7 +1082,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) iwlagn_gain_computation(priv, average_noise, min_average_noise_antenna_i, min_average_noise, - find_first_chain(cfg(priv)->valid_rx_ant)); + find_first_chain(hw_params(priv).valid_rx_ant)); /* Some power changes may have been made during the calibration. * Update and commit the RXON diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e1bf12578f87..6cec7e63c171 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -699,7 +699,7 @@ int iwl_alive_start(struct iwl_priv *priv) priv->active_rate = IWL_RATES_MASK; /* Configure Tx antenna selection based on H/W config */ - iwlagn_send_tx_ant_config(priv, cfg(priv)->valid_tx_ant); + iwlagn_send_tx_ant_config(priv, hw_params(priv).valid_tx_ant); if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) { struct iwl_rxon_cmd *active_rxon = diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index dd502e82e410..b6740c33b519 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1546,15 +1546,18 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { pos += scnprintf(buf + pos, bufsz - pos, "tx power: (1/2 dB step)\n"); - if ((cfg(priv)->valid_tx_ant & ANT_A) && tx->tx_power.ant_a) + if ((hw_params(priv).valid_tx_ant & ANT_A) && + tx->tx_power.ant_a) pos += scnprintf(buf + pos, bufsz - pos, fmt_hex, "antenna A:", tx->tx_power.ant_a); - if ((cfg(priv)->valid_tx_ant & ANT_B) && tx->tx_power.ant_b) + if ((hw_params(priv).valid_tx_ant & ANT_B) && + tx->tx_power.ant_b) pos += scnprintf(buf + pos, bufsz - pos, fmt_hex, "antenna B:", tx->tx_power.ant_b); - if ((cfg(priv)->valid_tx_ant & ANT_C) && tx->tx_power.ant_c) + if ((hw_params(priv).valid_tx_ant & ANT_C) && + tx->tx_power.ant_c) pos += scnprintf(buf + pos, bufsz - pos, fmt_hex, "antenna C:", tx->tx_power.ant_c); diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index d8668bccc083..6915b33add36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -271,25 +271,27 @@ int iwl_eeprom_init_hw_params(struct iwl_priv *priv) IWL_INFO(priv, "Device SKU: 0x%X\n", hw_params(priv).sku); - if (!cfg(priv)->valid_tx_ant && !cfg(priv)->valid_rx_ant) { - /* not using .cfg overwrite */ - radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG); - cfg(priv)->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); - cfg(priv)->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); - if (!cfg(priv)->valid_tx_ant || !cfg(priv)->valid_rx_ant) { - IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n", - cfg(priv)->valid_tx_ant, - cfg(priv)->valid_rx_ant); - return -EINVAL; - } - IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", - cfg(priv)->valid_tx_ant, cfg(priv)->valid_rx_ant); + radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG); + + hw_params(priv).valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg); + hw_params(priv).valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg); + + /* check overrides (some devices have wrong EEPROM) */ + if (cfg(priv)->valid_tx_ant) + hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant; + if (cfg(priv)->valid_rx_ant) + hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant; + + if (!hw_params(priv).valid_tx_ant || !hw_params(priv).valid_rx_ant) { + IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n", + hw_params(priv).valid_tx_ant, + hw_params(priv).valid_rx_ant); + return -EINVAL; } - /* - * for some special cases, - * EEPROM did not reflect the correct antenna setting - * so overwrite the valid tx/rx antenna from .cfg - */ + + IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", + hw_params(priv).valid_tx_ant, hw_params(priv).valid_rx_ant); + return 0; } -- cgit v1.2.3-70-g09d2 From 706c4ff67cb86134a3a93413a595a7c5559b7cc2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:33 -0800 Subject: iwlwifi: make config const Writing to the global config structures is always wrong. To protect against such mistakes in the future, mark them const. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-2000.c | 12 ++--- drivers/net/wireless/iwlwifi/iwl-5000.c | 14 +++--- drivers/net/wireless/iwlwifi/iwl-6000.c | 49 +++++++++--------- drivers/net/wireless/iwlwifi/iwl-cfg.h | 82 +++++++++++++++---------------- drivers/net/wireless/iwlwifi/iwl-drv.c | 2 +- drivers/net/wireless/iwlwifi/iwl-drv.h | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 2 +- drivers/net/wireless/iwlwifi/iwl-pci.c | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 2 +- drivers/net/wireless/iwlwifi/iwl-ucode.c | 4 +- 11 files changed, 90 insertions(+), 89 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 22eb0622ac21..2199a0e5c4f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -196,13 +196,13 @@ static struct iwl_ht_params iwl1000_ht_params = { .base_params = &iwl1000_base_params, \ .led_mode = IWL_LED_BLINK -struct iwl_cfg iwl1000_bgn_cfg = { +const struct iwl_cfg iwl1000_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN", IWL_DEVICE_1000, .ht_params = &iwl1000_ht_params, }; -struct iwl_cfg iwl1000_bg_cfg = { +const struct iwl_cfg iwl1000_bg_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 1000 BG", IWL_DEVICE_1000, }; @@ -221,13 +221,13 @@ struct iwl_cfg iwl1000_bg_cfg = { .led_mode = IWL_LED_RF_STATE, \ .rx_with_siso_diversity = true -struct iwl_cfg iwl100_bgn_cfg = { +const struct iwl_cfg iwl100_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 100 BGN", IWL_DEVICE_100, .ht_params = &iwl1000_ht_params, }; -struct iwl_cfg iwl100_bg_cfg = { +const struct iwl_cfg iwl100_bg_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 100 BG", IWL_DEVICE_100, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 43d17a4564e3..1ba020723537 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -248,13 +248,13 @@ static struct iwl_bt_params iwl2030_bt_params = { .led_mode = IWL_LED_RF_STATE, \ .iq_invert = true \ -struct iwl_cfg iwl2000_2bgn_cfg = { +const struct iwl_cfg iwl2000_2bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 2200 BGN", IWL_DEVICE_2000, .ht_params = &iwl2000_ht_params, }; -struct iwl_cfg iwl2000_2bgn_d_cfg = { +const struct iwl_cfg iwl2000_2bgn_d_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 2200D BGN", IWL_DEVICE_2000, .ht_params = &iwl2000_ht_params, @@ -278,7 +278,7 @@ struct iwl_cfg iwl2000_2bgn_d_cfg = { .adv_pm = true, \ .iq_invert = true \ -struct iwl_cfg iwl2030_2bgn_cfg = { +const struct iwl_cfg iwl2030_2bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN", IWL_DEVICE_2030, .ht_params = &iwl2000_ht_params, @@ -302,13 +302,13 @@ struct iwl_cfg iwl2030_2bgn_cfg = { .rx_with_siso_diversity = true, \ .iq_invert = true \ -struct iwl_cfg iwl105_bgn_cfg = { +const struct iwl_cfg iwl105_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 105 BGN", IWL_DEVICE_105, .ht_params = &iwl2000_ht_params, }; -struct iwl_cfg iwl105_bgn_d_cfg = { +const struct iwl_cfg iwl105_bgn_d_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 105D BGN", IWL_DEVICE_105, .ht_params = &iwl2000_ht_params, @@ -333,7 +333,7 @@ struct iwl_cfg iwl105_bgn_d_cfg = { .rx_with_siso_diversity = true, \ .iq_invert = true \ -struct iwl_cfg iwl135_bgn_cfg = { +const struct iwl_cfg iwl135_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 135 BGN", IWL_DEVICE_135, .ht_params = &iwl2000_ht_params, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 8cdc4a35a973..dff75a09eb48 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -349,7 +349,7 @@ static struct iwl_ht_params iwl5000_ht_params = { .base_params = &iwl5000_base_params, \ .led_mode = IWL_LED_BLINK -struct iwl_cfg iwl5300_agn_cfg = { +const struct iwl_cfg iwl5300_agn_cfg = { .name = "Intel(R) Ultimate N WiFi Link 5300 AGN", IWL_DEVICE_5000, /* at least EEPROM 0x11A has wrong info */ @@ -358,7 +358,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .ht_params = &iwl5000_ht_params, }; -struct iwl_cfg iwl5100_bgn_cfg = { +const struct iwl_cfg iwl5100_bgn_cfg = { .name = "Intel(R) WiFi Link 5100 BGN", IWL_DEVICE_5000, .valid_tx_ant = ANT_B, /* .cfg overwrite */ @@ -366,14 +366,14 @@ struct iwl_cfg iwl5100_bgn_cfg = { .ht_params = &iwl5000_ht_params, }; -struct iwl_cfg iwl5100_abg_cfg = { +const struct iwl_cfg iwl5100_abg_cfg = { .name = "Intel(R) WiFi Link 5100 ABG", IWL_DEVICE_5000, .valid_tx_ant = ANT_B, /* .cfg overwrite */ .valid_rx_ant = ANT_AB, /* .cfg overwrite */ }; -struct iwl_cfg iwl5100_agn_cfg = { +const struct iwl_cfg iwl5100_agn_cfg = { .name = "Intel(R) WiFi Link 5100 AGN", IWL_DEVICE_5000, .valid_tx_ant = ANT_B, /* .cfg overwrite */ @@ -381,7 +381,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .ht_params = &iwl5000_ht_params, }; -struct iwl_cfg iwl5350_agn_cfg = { +const struct iwl_cfg iwl5350_agn_cfg = { .name = "Intel(R) WiMAX/WiFi Link 5350 AGN", .fw_name_pre = IWL5000_FW_PRE, .ucode_api_max = IWL5000_UCODE_API_MAX, @@ -411,14 +411,14 @@ struct iwl_cfg iwl5350_agn_cfg = { .led_mode = IWL_LED_BLINK, \ .internal_wimax_coex = true -struct iwl_cfg iwl5150_agn_cfg = { +const struct iwl_cfg iwl5150_agn_cfg = { .name = "Intel(R) WiMAX/WiFi Link 5150 AGN", IWL_DEVICE_5150, .ht_params = &iwl5000_ht_params, }; -struct iwl_cfg iwl5150_abg_cfg = { +const struct iwl_cfg iwl5150_abg_cfg = { .name = "Intel(R) WiMAX/WiFi Link 5150 ABG", IWL_DEVICE_5150, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 720e8e6e62ae..ef896630625d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -354,40 +354,41 @@ static struct iwl_bt_params iwl6000_bt_params = { .need_temp_offset_calib = true, \ .led_mode = IWL_LED_RF_STATE -struct iwl_cfg iwl6005_2agn_cfg = { +const struct iwl_cfg iwl6005_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6205 AGN", IWL_DEVICE_6005, .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl6005_2abg_cfg = { +const struct iwl_cfg iwl6005_2abg_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6205 ABG", IWL_DEVICE_6005, }; -struct iwl_cfg iwl6005_2bg_cfg = { +const struct iwl_cfg iwl6005_2bg_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6205 BG", IWL_DEVICE_6005, }; -struct iwl_cfg iwl6005_2agn_sff_cfg = { +const struct iwl_cfg iwl6005_2agn_sff_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6205S AGN", IWL_DEVICE_6005, .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl6005_2agn_d_cfg = { +const struct iwl_cfg iwl6005_2agn_d_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6205D AGN", IWL_DEVICE_6005, .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl6005_2agn_mow1_cfg = { +const struct iwl_cfg iwl6005_2agn_mow1_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6206 AGN", IWL_DEVICE_6005, .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl6005_2agn_mow2_cfg = { + +const struct iwl_cfg iwl6005_2agn_mow2_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6207 AGN", IWL_DEVICE_6005, .ht_params = &iwl6000_ht_params, @@ -409,53 +410,53 @@ struct iwl_cfg iwl6005_2agn_mow2_cfg = { .led_mode = IWL_LED_RF_STATE, \ .adv_pm = true \ -struct iwl_cfg iwl6030_2agn_cfg = { +const struct iwl_cfg iwl6030_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6230 AGN", IWL_DEVICE_6030, .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl6030_2abg_cfg = { +const struct iwl_cfg iwl6030_2abg_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6230 ABG", IWL_DEVICE_6030, }; -struct iwl_cfg iwl6030_2bgn_cfg = { +const struct iwl_cfg iwl6030_2bgn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6230 BGN", IWL_DEVICE_6030, .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl6030_2bg_cfg = { +const struct iwl_cfg iwl6030_2bg_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6230 BG", IWL_DEVICE_6030, }; -struct iwl_cfg iwl6035_2agn_cfg = { +const struct iwl_cfg iwl6035_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", IWL_DEVICE_6030, .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl1030_bgn_cfg = { +const struct iwl_cfg iwl1030_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN", IWL_DEVICE_6030, .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl1030_bg_cfg = { +const struct iwl_cfg iwl1030_bg_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 1030 BG", IWL_DEVICE_6030, }; -struct iwl_cfg iwl130_bgn_cfg = { +const struct iwl_cfg iwl130_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 130 BGN", IWL_DEVICE_6030, .ht_params = &iwl6000_ht_params, .rx_with_siso_diversity = true, }; -struct iwl_cfg iwl130_bg_cfg = { +const struct iwl_cfg iwl130_bg_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 130 BG", IWL_DEVICE_6030, .rx_with_siso_diversity = true, @@ -480,18 +481,18 @@ struct iwl_cfg iwl130_bg_cfg = { .pa_type = IWL_PA_INTERNAL, \ .led_mode = IWL_LED_BLINK -struct iwl_cfg iwl6000i_2agn_cfg = { +const struct iwl_cfg iwl6000i_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN", IWL_DEVICE_6000i, .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl6000i_2abg_cfg = { +const struct iwl_cfg iwl6000i_2abg_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6200 ABG", IWL_DEVICE_6000i, }; -struct iwl_cfg iwl6000i_2bg_cfg = { +const struct iwl_cfg iwl6000i_2bg_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6200 BG", IWL_DEVICE_6000i, }; @@ -512,13 +513,13 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .led_mode = IWL_LED_BLINK, \ .internal_wimax_coex = true -struct iwl_cfg iwl6050_2agn_cfg = { +const struct iwl_cfg iwl6050_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN", IWL_DEVICE_6050, .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl6050_2abg_cfg = { +const struct iwl_cfg iwl6050_2abg_cfg = { .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG", IWL_DEVICE_6050, }; @@ -537,18 +538,18 @@ struct iwl_cfg iwl6050_2abg_cfg = { .led_mode = IWL_LED_BLINK, \ .internal_wimax_coex = true -struct iwl_cfg iwl6150_bgn_cfg = { +const struct iwl_cfg iwl6150_bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN", IWL_DEVICE_6150, .ht_params = &iwl6000_ht_params, }; -struct iwl_cfg iwl6150_bg_cfg = { +const struct iwl_cfg iwl6150_bg_cfg = { .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG", IWL_DEVICE_6150, }; -struct iwl_cfg iwl6000_3agn_cfg = { +const struct iwl_cfg iwl6000_3agn_cfg = { .name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN", .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, diff --git a/drivers/net/wireless/iwlwifi/iwl-cfg.h b/drivers/net/wireless/iwlwifi/iwl-cfg.h index 1ad14bbccc99..82152311d73b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-cfg.h +++ b/drivers/net/wireless/iwlwifi/iwl-cfg.h @@ -68,46 +68,46 @@ * This file declares the config structures for all devices. */ -extern struct iwl_cfg iwl5300_agn_cfg; -extern struct iwl_cfg iwl5100_agn_cfg; -extern struct iwl_cfg iwl5350_agn_cfg; -extern struct iwl_cfg iwl5100_bgn_cfg; -extern struct iwl_cfg iwl5100_abg_cfg; -extern struct iwl_cfg iwl5150_agn_cfg; -extern struct iwl_cfg iwl5150_abg_cfg; -extern struct iwl_cfg iwl6005_2agn_cfg; -extern struct iwl_cfg iwl6005_2abg_cfg; -extern struct iwl_cfg iwl6005_2bg_cfg; -extern struct iwl_cfg iwl6005_2agn_sff_cfg; -extern struct iwl_cfg iwl6005_2agn_d_cfg; -extern struct iwl_cfg iwl6005_2agn_mow1_cfg; -extern struct iwl_cfg iwl6005_2agn_mow2_cfg; -extern struct iwl_cfg iwl1030_bgn_cfg; -extern struct iwl_cfg iwl1030_bg_cfg; -extern struct iwl_cfg iwl6030_2agn_cfg; -extern struct iwl_cfg iwl6030_2abg_cfg; -extern struct iwl_cfg iwl6030_2bgn_cfg; -extern struct iwl_cfg iwl6030_2bg_cfg; -extern struct iwl_cfg iwl6000i_2agn_cfg; -extern struct iwl_cfg iwl6000i_2abg_cfg; -extern struct iwl_cfg iwl6000i_2bg_cfg; -extern struct iwl_cfg iwl6000_3agn_cfg; -extern struct iwl_cfg iwl6050_2agn_cfg; -extern struct iwl_cfg iwl6050_2abg_cfg; -extern struct iwl_cfg iwl6150_bgn_cfg; -extern struct iwl_cfg iwl6150_bg_cfg; -extern struct iwl_cfg iwl1000_bgn_cfg; -extern struct iwl_cfg iwl1000_bg_cfg; -extern struct iwl_cfg iwl100_bgn_cfg; -extern struct iwl_cfg iwl100_bg_cfg; -extern struct iwl_cfg iwl130_bgn_cfg; -extern struct iwl_cfg iwl130_bg_cfg; -extern struct iwl_cfg iwl2000_2bgn_cfg; -extern struct iwl_cfg iwl2000_2bgn_d_cfg; -extern struct iwl_cfg iwl2030_2bgn_cfg; -extern struct iwl_cfg iwl6035_2agn_cfg; -extern struct iwl_cfg iwl105_bgn_cfg; -extern struct iwl_cfg iwl105_bgn_d_cfg; -extern struct iwl_cfg iwl135_bgn_cfg; +extern const struct iwl_cfg iwl5300_agn_cfg; +extern const struct iwl_cfg iwl5100_agn_cfg; +extern const struct iwl_cfg iwl5350_agn_cfg; +extern const struct iwl_cfg iwl5100_bgn_cfg; +extern const struct iwl_cfg iwl5100_abg_cfg; +extern const struct iwl_cfg iwl5150_agn_cfg; +extern const struct iwl_cfg iwl5150_abg_cfg; +extern const struct iwl_cfg iwl6005_2agn_cfg; +extern const struct iwl_cfg iwl6005_2abg_cfg; +extern const struct iwl_cfg iwl6005_2bg_cfg; +extern const struct iwl_cfg iwl6005_2agn_sff_cfg; +extern const struct iwl_cfg iwl6005_2agn_d_cfg; +extern const struct iwl_cfg iwl6005_2agn_mow1_cfg; +extern const struct iwl_cfg iwl6005_2agn_mow2_cfg; +extern const struct iwl_cfg iwl1030_bgn_cfg; +extern const struct iwl_cfg iwl1030_bg_cfg; +extern const struct iwl_cfg iwl6030_2agn_cfg; +extern const struct iwl_cfg iwl6030_2abg_cfg; +extern const struct iwl_cfg iwl6030_2bgn_cfg; +extern const struct iwl_cfg iwl6030_2bg_cfg; +extern const struct iwl_cfg iwl6000i_2agn_cfg; +extern const struct iwl_cfg iwl6000i_2abg_cfg; +extern const struct iwl_cfg iwl6000i_2bg_cfg; +extern const struct iwl_cfg iwl6000_3agn_cfg; +extern const struct iwl_cfg iwl6050_2agn_cfg; +extern const struct iwl_cfg iwl6050_2abg_cfg; +extern const struct iwl_cfg iwl6150_bgn_cfg; +extern const struct iwl_cfg iwl6150_bg_cfg; +extern const struct iwl_cfg iwl1000_bgn_cfg; +extern const struct iwl_cfg iwl1000_bg_cfg; +extern const struct iwl_cfg iwl100_bgn_cfg; +extern const struct iwl_cfg iwl100_bg_cfg; +extern const struct iwl_cfg iwl130_bgn_cfg; +extern const struct iwl_cfg iwl130_bg_cfg; +extern const struct iwl_cfg iwl2000_2bgn_cfg; +extern const struct iwl_cfg iwl2000_2bgn_d_cfg; +extern const struct iwl_cfg iwl2030_2bgn_cfg; +extern const struct iwl_cfg iwl6035_2agn_cfg; +extern const struct iwl_cfg iwl105_bgn_cfg; +extern const struct iwl_cfg iwl105_bgn_d_cfg; +extern const struct iwl_cfg iwl135_bgn_cfg; #endif /* __iwl_pci_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 8ff52568cf6e..76fc4407b19e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -68,7 +68,7 @@ #include "iwl-op-mode.h" int iwl_drv_start(struct iwl_shared *shrd, - struct iwl_trans *trans, struct iwl_cfg *cfg) + struct iwl_trans *trans, const struct iwl_cfg *cfg) { int ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h index 90534a23ddc8..3b771c1d9096 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/iwlwifi/iwl-drv.h @@ -105,7 +105,7 @@ * function. */ int iwl_drv_start(struct iwl_shared *shrd, - struct iwl_trans *trans, struct iwl_cfg *cfg); + struct iwl_trans *trans, const struct iwl_cfg *cfg); /** * iwl_drv_stop - stop the drv diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 6915b33add36..f965ee333920 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -512,7 +512,7 @@ static int iwl_find_otp_image(struct iwl_trans *trans, * iwl_get_max_txpower_avg - get the highest tx power from all chains. * find the highest tx power from all chains for the channel */ -static s8 iwl_get_max_txpower_avg(struct iwl_cfg *cfg, +static s8 iwl_get_max_txpower_avg(const struct iwl_cfg *cfg, struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element, s8 *max_txpower_in_half_dbm) { diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 06e004157dcc..d109b0f32e33 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -263,7 +263,7 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); + const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); struct iwl_shared *shrd; struct iwl_trans *iwl_trans; int err; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 11184f1c4365..4efc9e13f9ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -374,7 +374,7 @@ struct iwl_shared { bool wowlan; u8 valid_contexts; - struct iwl_cfg *cfg; + const struct iwl_cfg *cfg; struct iwl_priv *priv; struct iwl_trans *trans; struct iwl_nic *nic; diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index b16efc00ba6e..206a61c991dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -692,7 +692,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first) { - struct iwl_cfg *cfg = cfg(nic); + const struct iwl_cfg *cfg = cfg(nic); const char *name_pre = cfg->fw_name_pre; char tag[8]; @@ -1045,7 +1045,7 @@ static int iwl_parse_tlv_firmware(struct iwl_nic *nic, static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) { struct iwl_nic *nic = context; - struct iwl_cfg *cfg = cfg(nic); + const struct iwl_cfg *cfg = cfg(nic); struct iwl_fw *fw = &nic->fw; struct iwl_ucode_header *ucode; int err; -- cgit v1.2.3-70-g09d2 From ce9e80af4f2c5dffb0df470538573d473c91d540 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:34 -0800 Subject: iwlwifi: reduce IDI code ifdef The code in the two branches of the #ifdef is almost the same so move the common code outside the #ifdef. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-pci.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index d109b0f32e33..c5e339ee918b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -278,17 +278,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #ifdef CONFIG_IWLWIFI_IDI iwl_trans = iwl_trans_idi_alloc(shrd, pdev, ent); - if (iwl_trans == NULL) { - err = -ENOMEM; - goto out_free_bus; - } - - shrd->trans = iwl_trans; - pci_set_drvdata(pdev, iwl_trans); - - err = iwl_drv_start(shrd, iwl_trans, cfg); #else iwl_trans = iwl_trans_pcie_alloc(shrd, pdev, ent); +#endif if (iwl_trans == NULL) { err = -ENOMEM; goto out_free_bus; @@ -298,7 +290,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, iwl_trans); err = iwl_drv_start(shrd, iwl_trans, cfg); -#endif if (err) goto out_free_trans; -- cgit v1.2.3-70-g09d2 From 2dd4f9f731f593a52a3fdca20bb32a78d917baf7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:35 -0800 Subject: iwlwifi: clean up (wowlan) suspend flow In the WoWLAN suspend flow, instead of accessing registers directly, ask the transport to do the required setup at the end of suspend. If the transport doesn't implement this, don't tell the stack we support WoWLAN. When the device suspends w/o WoWLAN, mac80211 will have stopped it already, which has already called iwl_apm_stop() via stop_hw(). Thus, it isn't necessary to call it again in pcie_suspend and we can simply do nothing there. This unifies the regular and WoWLAN suspend. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 5 ++--- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 32 +++++++++++---------------- drivers/net/wireless/iwlwifi/iwl-trans.h | 11 +++++++++ 3 files changed, 26 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 8b26f3217823..8c7ca7318c00 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -196,6 +196,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, WIPHY_FLAG_IBSS_RSN; if (nic(priv)->fw.ucode_wowlan.code.len && + trans(priv)->ops->wowlan_suspend && device_can_wakeup(trans(priv)->dev)) { hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | @@ -412,9 +413,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, device_set_wakeup_enable(trans(priv)->dev, true); - /* Now let the ucode operate on its own */ - iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); + iwl_trans_wowlan_suspend(trans(priv)); goto out; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index f47426a5ef4d..bb8f2fdf1281 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1303,6 +1303,17 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); } +static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans) +{ + /* let the ucode operate on its own */ + iwl_write32(trans, CSR_UCODE_DRV_GP1_SET, + CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); + + iwl_disable_interrupts(trans); + iwl_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); +} + static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx, u8 sta_id, u8 tid) @@ -1641,25 +1652,6 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans) #ifdef CONFIG_PM_SLEEP static int iwl_trans_pcie_suspend(struct iwl_trans *trans) { - /* - * This function is called when system goes into suspend state - * mac80211 will call iwlagn_mac_stop() from the mac80211 suspend - * function first but since iwlagn_mac_stop() has no knowledge of - * who the caller is, - * it will not call apm_ops.stop() to stop the DMA operation. - * Calling apm_ops.stop here to make sure we stop the DMA. - * - * But of course ... if we have configured WoWLAN then we did other - * things already :-) - */ - if (!trans->shrd->wowlan) { - iwl_apm_stop(trans); - } else { - iwl_disable_interrupts(trans); - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - } - return 0; } @@ -2227,6 +2219,8 @@ const struct iwl_trans_ops trans_ops_pcie = { .start_fw = iwl_trans_pcie_start_fw, .stop_device = iwl_trans_pcie_stop_device, + .wowlan_suspend = iwl_trans_pcie_wowlan_suspend, + .wake_any_queue = iwl_trans_pcie_wake_any_queue, .send_cmd = iwl_trans_pcie_send_cmd, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index e2f21cfc2cd4..83f04c9d77e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -210,6 +210,9 @@ struct iwl_host_cmd { * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* * @stop_device:stops the whole device (embedded CPU put to reset) * May sleep + * @wowlan_suspend: put the device into the correct mode for WoWLAN during + * suspend. This is optional, if not implemented WoWLAN will not be + * supported. This callback may sleep. * @send_cmd:send a host command * May sleep only if CMD_SYNC is set * @tx: send an skb @@ -247,6 +250,8 @@ struct iwl_trans_ops { void (*fw_alive)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans); + void (*wowlan_suspend)(struct iwl_trans *trans); + void (*wake_any_queue)(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, const char *msg); @@ -396,6 +401,12 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans) trans->state = IWL_TRANS_NO_FW; } +static inline void iwl_trans_wowlan_suspend(struct iwl_trans *trans) +{ + might_sleep(); + trans->ops->wowlan_suspend(trans); +} + static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, const char *msg) -- cgit v1.2.3-70-g09d2 From 15b86bff995525a38126eb44a951765a57ea2f4c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:36 -0800 Subject: iwlwifi: move wowlan bool into priv With the new WoWLAN flow into the transport there no longer is a need for this to be shared, so move it into priv. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-mac80211.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 1 - 8 files changed, 10 insertions(+), 9 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 79ac7cb1701b..626b0d184729 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1193,7 +1193,7 @@ int iwlagn_suspend(struct iwl_priv *priv, iwl_trans_stop_device(trans(priv)); - priv->shrd->wowlan = true; + priv->wowlan = true; ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_WOWLAN); if (ret) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 222a8f46365f..7a713ba9bdee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -586,7 +586,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) sizeof(struct iwl_addsta_cmd)); send_lq = false; if (priv->stations[i].lq) { - if (priv->shrd->wowlan) + if (priv->wowlan) iwl_sta_fill_lq(priv, ctx, i, &lq); else memcpy(&lq, priv->stations[i].lq, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 2b722ccb730a..e5ebc36a14c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -126,7 +126,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, u8 data_retry_limit; u8 rate_plcp; - if (priv->shrd->wowlan) { + if (priv->wowlan) { rts_retry_limit = IWLAGN_LOW_RETRY_LIMIT; data_retry_limit = IWLAGN_LOW_RETRY_LIMIT; } else { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6cec7e63c171..6dd4faead7cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -701,7 +701,7 @@ int iwl_alive_start(struct iwl_priv *priv) /* Configure Tx antenna selection based on H/W config */ iwlagn_send_tx_ant_config(priv, hw_params(priv).valid_tx_ant); - if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) { + if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { struct iwl_rxon_cmd *active_rxon = (struct iwl_rxon_cmd *)&ctx->active; /* apply any changes in staging */ @@ -716,7 +716,7 @@ int iwl_alive_start(struct iwl_priv *priv) iwlagn_set_rxon_chain(priv, ctx); } - if (!priv->shrd->wowlan) { + if (!priv->wowlan) { /* WoWLAN ucode will not reply in the same way, skip it */ iwl_reset_run_time_calib(priv); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9ea9002cc839..ef71463e84ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -787,6 +787,8 @@ struct iwl_priv { bool new_scan_threshold_behaviour; + bool wowlan; + /* EEPROM MAC addresses */ struct mac_address addresses[2]; diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 8c7ca7318c00..8160f615f71a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -418,7 +418,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, goto out; error: - priv->shrd->wowlan = false; + priv->wowlan = false; iwlagn_prepare_restart(priv); ieee80211_restart_hw(priv->hw); out: @@ -474,7 +474,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) /* we'll clear ctx->vif during iwlagn_prepare_restart() */ vif = ctx->vif; - priv->shrd->wowlan = false; + priv->wowlan = false; device_set_wakeup_enable(trans(priv)->dev, false); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index fd008c4e41fd..1ef3c4da1605 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -348,7 +348,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, dtimper = priv->hw->conf.ps_dtim_period ?: 1; - if (priv->shrd->wowlan) + if (priv->wowlan) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper); else if (!cfg(priv)->base_params->no_idle_support && priv->hw->conf.flags & IEEE80211_CONF_IDLE) diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 4efc9e13f9ec..a7dbcabafc96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -371,7 +371,6 @@ struct iwl_shared { u8 ucode_owner; u8 cmd_queue; unsigned long status; - bool wowlan; u8 valid_contexts; const struct iwl_cfg *cfg; -- cgit v1.2.3-70-g09d2 From 2c6ab7ff8fa9af22a2a616656da6e5a0567da285 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:37 -0800 Subject: iwlwifi: use ieee80211_tx_status We currently use the _irqsafe version, but that isn't recommended together with ieee80211_rx() as it can cause races. If the device reports a TX-status and RX in that order then with the current combination mac80211 might process them in the other order, which can cause issues with powersaving clients. Use ieee80211_tx_status() to avoid this race. Since we don't want to call it with locks held, process the frame queues later -- this is fine as they are on the stack. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index e5ebc36a14c8..1914bee1891e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1007,6 +1007,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, if (is_agg) iwl_rx_reply_tx_agg(priv, tx_resp); + __skb_queue_head_init(&skbs); + if (tx_resp->frame_count == 1) { u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); @@ -1026,8 +1028,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, next_reclaimed = ssn; } - __skb_queue_head_init(&skbs); - if (tid != IWL_TID_NON_QOS) { priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed; @@ -1040,8 +1040,9 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, ssn, status, &skbs)); iwlagn_check_ratid_empty(priv, sta_id, tid); freed = 0; - while (!skb_queue_empty(&skbs)) { - skb = __skb_dequeue(&skbs); + + /* process frames */ + skb_queue_walk(&skbs, skb) { hdr = (struct ieee80211_hdr *)skb->data; if (!ieee80211_is_data_qos(hdr->frame_control)) @@ -1083,8 +1084,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, if (!is_agg) iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); - ieee80211_tx_status_irqsafe(priv->hw, skb); - freed++; } @@ -1093,6 +1092,12 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, iwl_check_abort_status(priv, tx_resp->frame_count, status); spin_unlock(&priv->sta_lock); + + while (!skb_queue_empty(&skbs)) { + skb = __skb_dequeue(&skbs); + ieee80211_tx_status(priv->hw, skb); + } + return 0; } @@ -1186,9 +1191,8 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, iwlagn_check_ratid_empty(priv, sta_id, tid); freed = 0; - while (!skb_queue_empty(&reclaimed_skbs)) { - skb = __skb_dequeue(&reclaimed_skbs); + skb_queue_walk(&reclaimed_skbs, skb) { hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_data_qos(hdr->frame_control)) @@ -1211,10 +1215,14 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); } - - ieee80211_tx_status_irqsafe(priv->hw, skb); } spin_unlock(&priv->sta_lock); + + while (!skb_queue_empty(&reclaimed_skbs)) { + skb = __skb_dequeue(&reclaimed_skbs); + ieee80211_tx_status(priv->hw, skb); + } + return 0; } -- cgit v1.2.3-70-g09d2 From 65b94a4abfd55b3304be25ffed9832455d41e1dd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:38 -0800 Subject: iwlwifi: pass response packet directly When CMD_WANT_SKB is set for a (synchronous) command, the response is passed back to the caller which is then responsible for freeing it. Make this more abstract with real API, passing directly the response packet in the new cmd.resp_pkt member and also introduce iwl_free_resp() to free the pages -- this way the upper layers don't have to directly touch the page implementation. NOTE: This breaks IDI -- the new code isn't reflected there yet! Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-scan.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-shared.h | 5 ----- drivers/net/wireless/iwlwifi/iwl-testmode.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 16 ++++++++++------ drivers/net/wireless/iwlwifi/iwl-trans.h | 13 +++++++++++-- 6 files changed, 28 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 7a713ba9bdee..9ef8da47ad04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -160,7 +160,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, /*else the command was successfully sent in SYNC mode, need to free * the reply page */ - iwl_free_pages(priv->shrd, cmd.reply_page); + iwl_free_resp(&cmd); if (cmd.handler_status) IWL_ERR(priv, "%s - error in the CMD response %d", __func__, @@ -415,7 +415,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, if (ret) return ret; - pkt = (struct iwl_rx_packet *)cmd.reply_page; + pkt = cmd.resp_pkt; if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", pkt->hdr.flags); @@ -438,7 +438,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, break; } } - iwl_free_pages(priv->shrd, cmd.reply_page); + iwl_free_resp(&cmd); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 766572b9ac89..c0fc3687a2fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -76,7 +76,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) if (ret) return ret; - pkt = (struct iwl_rx_packet *)cmd.reply_page; + pkt = cmd.resp_pkt; if (pkt->u.status != CAN_ABORT_STATUS) { /* The scan abort will return 1 for success or * 2 for "failure". A failure condition can be @@ -88,7 +88,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) ret = -EIO; } - iwl_free_pages(priv->shrd, cmd.reply_page); + iwl_free_resp(&cmd); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index a7dbcabafc96..53244d88f1ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -413,11 +413,6 @@ static inline bool iwl_have_debug_level(u32 level) return iwlagn_mod_params.debug_level & level; } -static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page) -{ - free_pages(page, shrd->hw_params.rx_page_order); -} - /** * iwl_queue_inc_wrap - increment queue index, wrap back to beginning * @index -- current index diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 23eea06a74ad..cc1f3e990ad6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -292,7 +292,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) return ret; /* Handling return of SKB to the user */ - pkt = (struct iwl_rx_packet *)cmd.reply_page; + pkt = cmd.resp_pkt; if (!pkt) { IWL_ERR(priv, "HCMD received a null response packet\n"); return ret; @@ -309,7 +309,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) /* The reply is in a page, that we cannot send to user space. */ memcpy(reply_buf, &(pkt->hdr), reply_len); - iwl_free_pages(priv->shrd, cmd.reply_page); + iwl_free_resp(&cmd); NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT); NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, reply_len, reply_buf); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index de2a0d91d658..771fae2f9fd8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -879,9 +879,13 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb, /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { - meta->source->reply_page = (unsigned long)rxb_addr(rxb); - meta->source->handler_status = handler_status; + struct page *p = rxb->page; + rxb->page = NULL; + meta->source->resp_pkt = pkt; + meta->source->_rx_page_addr = (unsigned long)page_address(p); + meta->source->_rx_page_order = hw_params(trans).rx_page_order; + meta->source->handler_status = handler_status; } iwl_hcmd_queue_reclaim(trans, txq_id, index); @@ -985,7 +989,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) } } - if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) { + if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) { IWL_ERR(trans, "Error: Response NULL in '%s'\n", get_cmd_string(cmd->id)); ret = -EIO; @@ -1006,9 +1010,9 @@ cancel: ~CMD_WANT_SKB; } - if (cmd->reply_page) { - iwl_free_pages(trans->shrd, cmd->reply_page); - cmd->reply_page = 0; + if (cmd->resp_pkt) { + iwl_free_resp(cmd); + cmd->resp_pkt = NULL; } return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 83f04c9d77e5..e8ab8d8ca484 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -173,7 +173,9 @@ enum iwl_hcmd_dataflag { * struct iwl_host_cmd - Host command to the uCode * * @data: array of chunks that composes the data of the host command - * @reply_page: pointer to the page that holds the response to the host command + * @resp_pkt: response packet, if %CMD_WANT_SKB was set + * @_rx_page_order: (internally used to free response packet) + * @_rx_page_addr: (internally used to free response packet) * @handler_status: return value of the handler of the command * (put in setup_rx_handlers) - valid for SYNC mode only * @flags: can be CMD_* @@ -183,7 +185,9 @@ enum iwl_hcmd_dataflag { */ struct iwl_host_cmd { const void *data[IWL_MAX_CMD_TFDS]; - unsigned long reply_page; + struct iwl_rx_packet *resp_pkt; + unsigned long _rx_page_addr; + u32 _rx_page_order; int handler_status; u32 flags; @@ -192,6 +196,11 @@ struct iwl_host_cmd { u8 id; }; +static inline void iwl_free_resp(struct iwl_host_cmd *cmd) +{ + free_pages(cmd->_rx_page_addr, cmd->_rx_page_order); +} + /** * struct iwl_trans_ops - transport specific operations * -- cgit v1.2.3-70-g09d2 From 48a2d66f58d2bf1818acf5ff7ed9897a9977a96e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:39 -0800 Subject: iwlwifi: don't pass iwl_rx_mem_buffer to upper layers struct iwl_rx_mem_buffer implementation details (DMA address, list pointers) that the upper layers don't need. Introduce iwl_rx_cmd_buffer that is passed upstream and only contains the needed data (the page). Additionally, access this data only via accessor functions, allowing us to change the implementation in the future. These accessors are rxb_addr() (as before) and rxb_steal_page() to take ownership of the data. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 41 ++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-agn.h | 12 +++---- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +-- drivers/net/wireless/iwlwifi/iwl-op-mode.h | 6 ++-- drivers/net/wireless/iwlwifi/iwl-scan.c | 8 ++--- drivers/net/wireless/iwlwifi/iwl-shared.h | 18 +++++++--- drivers/net/wireless/iwlwifi/iwl-testmode.c | 4 +-- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 8 ++++- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 21 ++++++++---- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 5 ++- drivers/net/wireless/iwlwifi/iwl-ucode.c | 2 +- 14 files changed, 80 insertions(+), 57 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 626b0d184729..e96af5133e06 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -707,7 +707,7 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv, } int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index bc21586aed63..8e025e0df50d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -131,7 +131,7 @@ const char *get_cmd_string(u8 cmd) ******************************************************************************/ static int iwlagn_rx_reply_error(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -146,7 +146,7 @@ static int iwlagn_rx_reply_error(struct iwl_priv *priv, return 0; } -static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, +static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -177,7 +177,7 @@ static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, static int iwlagn_rx_spectrum_measure_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -195,7 +195,7 @@ static int iwlagn_rx_spectrum_measure_notif(struct iwl_priv *priv, } static int iwlagn_rx_pm_sleep_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { #ifdef CONFIG_IWLWIFI_DEBUG @@ -208,7 +208,7 @@ static int iwlagn_rx_pm_sleep_notif(struct iwl_priv *priv, } static int iwlagn_rx_pm_debug_statistics_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -222,7 +222,7 @@ static int iwlagn_rx_pm_debug_statistics_notif(struct iwl_priv *priv, } static int iwlagn_rx_beacon_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -489,7 +489,7 @@ iwlagn_accumulative_statistics(struct iwl_priv *priv, #endif static int iwlagn_rx_statistics(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { unsigned long stamp = jiffies; @@ -597,7 +597,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, } static int iwlagn_rx_reply_statistics(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -620,7 +620,7 @@ static int iwlagn_rx_reply_statistics(struct iwl_priv *priv, /* Handle notification from uCode that card's power state is changing * due to software, hardware, or critical temperature RFKILL */ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -673,7 +673,7 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv, } static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { @@ -698,7 +698,7 @@ static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv, /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ static int iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -765,12 +765,14 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, struct ieee80211_hdr *hdr, u16 len, u32 ampdu_status, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct ieee80211_rx_status *stats) { struct sk_buff *skb; __le16 fc = hdr->frame_control; struct iwl_rxon_context *ctx; + struct page *p; + int offset; /* We only process data packets if the interface is open */ if (unlikely(!priv->is_open)) { @@ -790,7 +792,9 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, return; } - skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); + offset = (void *)hdr - rxb_addr(rxb); + p = rxb_steal_page(rxb); + skb_add_rx_frag(skb, 0, p, offset, len); iwl_update_stats(priv, false, fc, len); @@ -817,7 +821,6 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); ieee80211_rx(priv->hw, skb); - rxb->page = NULL; } static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) @@ -923,7 +926,7 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, /* Called for REPLY_RX (legacy ABG frames), or * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct ieee80211_hdr *header; @@ -1043,7 +1046,7 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, } static int iwlagn_rx_noa_notification(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_wipan_noa_data *new_data, *old_data; @@ -1094,7 +1097,7 @@ static int iwlagn_rx_noa_notification(struct iwl_priv *priv, */ void iwl_setup_rx_handlers(struct iwl_priv *priv) { - int (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, + int (**handlers)(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); handlers = priv->rx_handlers; @@ -1149,8 +1152,8 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) } -int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb, - struct iwl_device_cmd *cmd) +int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, + struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 9ef8da47ad04..736f8dc404df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -123,7 +123,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, return ret; } -int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, +int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 1914bee1891e..dd28785e1a5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -977,7 +977,7 @@ static void iwl_check_abort_status(struct iwl_priv *priv, } } -int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, +int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -1108,7 +1108,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, * of frames sent via aggregation. */ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index a142a197b2e4..a9c018a7b8ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -82,7 +82,7 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv); void iwlagn_prepare_restart(struct iwl_priv *priv); void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb); int __must_check iwl_rx_dispatch(struct iwl_op_mode *op_mode, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac); void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac); @@ -110,7 +110,7 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf, /* uCode */ int iwlagn_rx_calib_result(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); @@ -142,9 +142,9 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid); int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); -int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, +int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); static inline u32 iwl_tx_status_to_mac80211(u32 status) @@ -179,7 +179,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv); /* bt coex */ void iwlagn_send_advance_bt_config(struct iwl_priv *priv); int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv); void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv); @@ -227,7 +227,7 @@ void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id, struct iwl_link_quality_cmd *link_cmd); int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_link_quality_cmd *lq, u8 flags, bool init); -int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, +int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ef71463e84ea..5957209b2f37 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -729,9 +729,9 @@ struct iwl_priv { enum ieee80211_band band; void (*pre_rx_handler)(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); + struct iwl_rx_cmd_buffer *rxb); int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index d4fc9be2d2f3..41e58a136715 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h @@ -67,7 +67,7 @@ struct iwl_op_mode; struct iwl_trans; struct sk_buff; struct iwl_device_cmd; -struct iwl_rx_mem_buffer; +struct iwl_rx_cmd_buffer; /** * DOC: Operational mode - what is it ? @@ -125,7 +125,7 @@ struct iwl_rx_mem_buffer; struct iwl_op_mode_ops { struct iwl_op_mode *(*start)(struct iwl_trans *trans); void (*stop)(struct iwl_op_mode *op_mode); - int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb, + int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); void (*queue_full)(struct iwl_op_mode *op_mode, u8 ac); void (*queue_not_full)(struct iwl_op_mode *op_mode, u8 ac); @@ -156,7 +156,7 @@ static inline void iwl_op_mode_stop(struct iwl_op_mode *op_mode) } static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { return op_mode->ops->rx(op_mode, rxb, cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index c0fc3687a2fd..28899dabe6fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -260,7 +260,7 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) /* Service response to REPLY_SCAN_CMD (0x80) */ static int iwl_rx_reply_scan(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { #ifdef CONFIG_IWLWIFI_DEBUG @@ -275,7 +275,7 @@ static int iwl_rx_reply_scan(struct iwl_priv *priv, /* Service SCAN_START_NOTIFICATION (0x82) */ static int iwl_rx_scan_start_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -302,7 +302,7 @@ static int iwl_rx_scan_start_notif(struct iwl_priv *priv, /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ static int iwl_rx_scan_results_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { #ifdef CONFIG_IWLWIFI_DEBUG @@ -328,7 +328,7 @@ static int iwl_rx_scan_results_notif(struct iwl_priv *priv, /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ static int iwl_rx_scan_complete_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 53244d88f1ab..ed1811d43550 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -433,13 +433,21 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd) return --index & (n_bd - 1); } -struct iwl_rx_mem_buffer { - dma_addr_t page_dma; - struct page *page; - struct list_head list; +struct iwl_rx_cmd_buffer { + struct page *_page; }; -#define rxb_addr(r) page_address(r->page) +static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r) +{ + return page_address(r->_page); +} + +static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) +{ + struct page *p = r->_page; + r->_page = NULL; + return p; +} /* * mac80211 queues, ACs, hardware queues, FIFOs. diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index cc1f3e990ad6..b24b166a9482 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -131,7 +131,7 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { * 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) +static inline int get_event_length(struct iwl_rx_cmd_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); if (pkt) @@ -162,7 +162,7 @@ static inline int get_event_length(struct iwl_rx_mem_buffer *rxb) */ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) + struct iwl_rx_cmd_buffer *rxb) { struct ieee80211_hw *hw = priv->hw; struct sk_buff *skb; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index b1029468ccbd..632d4099900e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -49,6 +49,12 @@ struct iwl_host_cmd; /*This file includes the declaration that are internal to the * trans_pcie layer */ +struct iwl_rx_mem_buffer { + dma_addr_t page_dma; + struct page *page; + struct list_head list; +}; + /** * struct isr_statistics - interrupt statistics * @@ -287,7 +293,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id); int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); void iwl_tx_cmd_complete(struct iwl_trans *trans, - struct iwl_rx_mem_buffer *rxb, int handler_status); + struct iwl_rx_cmd_buffer *rxb, int handler_status); void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, struct iwl_tx_queue *txq, u16 byte_cnt); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 6495945637b9..68e89be60bef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -367,8 +367,6 @@ void iwl_bg_rx_replenish(struct work_struct *data) */ static void iwl_rx_handle(struct iwl_trans *trans) { - struct iwl_rx_mem_buffer *rxb; - struct iwl_rx_packet *pkt; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_queue *rxq = &trans_pcie->rxq; @@ -402,6 +400,9 @@ static void iwl_rx_handle(struct iwl_trans *trans) while (i != r) { int len, err; u16 sequence; + struct iwl_rx_mem_buffer *rxb; + struct iwl_rx_cmd_buffer rxcb; + struct iwl_rx_packet *pkt; rxb = rxq->queue[i]; @@ -418,7 +419,9 @@ static void iwl_rx_handle(struct iwl_trans *trans) dma_unmap_page(trans->dev, rxb->page_dma, PAGE_SIZE << hw_params(trans).rx_page_order, DMA_FROM_DEVICE); - pkt = rxb_addr(rxb); + + rxcb._page = rxb->page; + pkt = rxb_addr(&rxcb); IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); @@ -461,10 +464,10 @@ static void iwl_rx_handle(struct iwl_trans *trans) "reclaim is false, SEQ_RX_FRAME unset: %s\n", get_cmd_string(pkt->hdr.cmd)); - err = iwl_op_mode_rx(trans->op_mode, rxb, cmd); + err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); /* - * XXX: After here, we should always check rxb->page + * XXX: After here, we should always check rxcb._page * against NULL before touching it or its virtual * memory (pkt). Because some rx_handler might have * already taken or freed the pages. @@ -475,12 +478,16 @@ static void iwl_rx_handle(struct iwl_trans *trans) * and fire off the (possibly) blocking * iwl_trans_send_cmd() * as we reclaim the driver command queue */ - if (rxb->page) - iwl_tx_cmd_complete(trans, rxb, err); + if (rxcb._page) + iwl_tx_cmd_complete(trans, &rxcb, err); else IWL_WARN(trans, "Claim null rxb?\n"); } + /* page was stolen from us */ + if (rxcb._page == NULL) + rxb->page = NULL; + /* Reuse the page if possible. For notification packets and * SKBs that fail to Rx correctly, add them back into the * rx_free list for reuse later. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 771fae2f9fd8..0513b90da040 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -841,7 +841,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id, * will be executed. The attached skb (if present) will only be freed * if the callback returns 1 */ -void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb, +void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb, int handler_status) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -879,9 +879,8 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb, /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { - struct page *p = rxb->page; + struct page *p = rxb_steal_page(rxb); - rxb->page = NULL; meta->source->resp_pkt = pkt; meta->source->_rx_page_addr = (unsigned long)page_address(p); meta->source->_rx_page_order = hw_params(trans).rx_page_order; diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 206a61c991dd..12e79d04374f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -228,7 +228,7 @@ static int iwl_send_calib_cfg(struct iwl_trans *trans) } int iwlagn_rx_calib_result(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, + struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); -- cgit v1.2.3-70-g09d2 From df2f3216ccde52bb43df78e0b869a0dd1637cf15 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:40 -0800 Subject: iwlwifi: refactor PCI-E RX path Just make the code easier to read with less indentation. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 216 ++++++++++++----------- 1 file changed, 110 insertions(+), 106 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 68e89be60bef..bf560e9f87b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -358,6 +358,113 @@ void iwl_bg_rx_replenish(struct work_struct *data) iwlagn_rx_replenish(trans_pcie->trans); } +static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_rx_queue *rxq = &trans_pcie->rxq; + struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; + struct iwl_device_cmd *cmd; + unsigned long flags; + int len, err; + u16 sequence; + struct iwl_rx_cmd_buffer rxcb; + struct iwl_rx_packet *pkt; + bool reclaim; + int index, cmd_index; + + if (WARN_ON(!rxb)) + return; + + dma_unmap_page(trans->dev, rxb->page_dma, + PAGE_SIZE << hw_params(trans).rx_page_order, + DMA_FROM_DEVICE); + + rxcb._page = rxb->page; + pkt = rxb_addr(&rxcb); + + IWL_DEBUG_RX(trans, "%s, 0x%02x\n", + get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); + + + len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + len += sizeof(u32); /* account for status word */ + trace_iwlwifi_dev_rx(priv(trans), pkt, len); + + /* Reclaim a command buffer only if this packet is a response + * to a (driver-originated) command. + * If the packet (e.g. Rx frame) originated from uCode, + * there is no command buffer to reclaim. + * Ucode should set SEQ_RX_FRAME bit if ucode-originated, + * but apparently a few don't get set; catch them here. */ + reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) && + (pkt->hdr.cmd != REPLY_RX_PHY_CMD) && + (pkt->hdr.cmd != REPLY_RX) && + (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) && + (pkt->hdr.cmd != REPLY_COMPRESSED_BA) && + (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && + (pkt->hdr.cmd != REPLY_TX); + + sequence = le16_to_cpu(pkt->hdr.sequence); + index = SEQ_TO_INDEX(sequence); + cmd_index = get_cmd_index(&txq->q, index); + + if (reclaim) + cmd = txq->cmd[cmd_index]; + else + cmd = NULL; + + /* warn if this is cmd response / notification and the uCode + * didn't set the SEQ_RX_FRAME for a frame that is + * uCode-originated + * If you saw this code after the second half of 2012, then + * please remove it + */ + WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false && + (!(pkt->hdr.sequence & SEQ_RX_FRAME)), + "reclaim is false, SEQ_RX_FRAME unset: %s\n", + get_cmd_string(pkt->hdr.cmd)); + + err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); + + /* + * XXX: After here, we should always check rxcb._page + * against NULL before touching it or its virtual + * memory (pkt). Because some rx_handler might have + * already taken or freed the pages. + */ + + if (reclaim) { + /* Invoke any callbacks, transfer the buffer to caller, + * and fire off the (possibly) blocking + * iwl_trans_send_cmd() + * as we reclaim the driver command queue */ + if (rxcb._page) + iwl_tx_cmd_complete(trans, &rxcb, err); + else + IWL_WARN(trans, "Claim null rxb?\n"); + } + + /* page was stolen from us */ + if (rxcb._page == NULL) + rxb->page = NULL; + + /* Reuse the page if possible. For notification packets and + * SKBs that fail to Rx correctly, add them back into the + * rx_free list for reuse later. */ + spin_lock_irqsave(&rxq->lock, flags); + if (rxb->page != NULL) { + rxb->page_dma = + dma_map_page(trans->dev, rxb->page, 0, + PAGE_SIZE << hw_params(trans).rx_page_order, + DMA_FROM_DEVICE); + list_add_tail(&rxb->list, &rxq->rx_free); + rxq->free_count++; + } else + list_add_tail(&rxb->list, &rxq->rx_used); + spin_unlock_irqrestore(&rxq->lock, flags); +} + /** * iwl_rx_handle - Main entry function for receiving responses from uCode * @@ -367,18 +474,12 @@ void iwl_bg_rx_replenish(struct work_struct *data) */ static void iwl_rx_handle(struct iwl_trans *trans) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_queue *rxq = &trans_pcie->rxq; - struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; - struct iwl_device_cmd *cmd; u32 r, i; - int reclaim; - unsigned long flags; u8 fill_rx = 0; u32 count = 8; int total_empty; - int index, cmd_index; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ @@ -398,111 +499,14 @@ static void iwl_rx_handle(struct iwl_trans *trans) fill_rx = 1; while (i != r) { - int len, err; - u16 sequence; struct iwl_rx_mem_buffer *rxb; - struct iwl_rx_cmd_buffer rxcb; - struct iwl_rx_packet *pkt; rxb = rxq->queue[i]; - - /* If an RXB doesn't have a Rx queue slot associated with it, - * then a bug has been introduced in the queue refilling - * routines -- catch it here */ - if (WARN_ON(rxb == NULL)) { - i = (i + 1) & RX_QUEUE_MASK; - continue; - } - rxq->queue[i] = NULL; - dma_unmap_page(trans->dev, rxb->page_dma, - PAGE_SIZE << hw_params(trans).rx_page_order, - DMA_FROM_DEVICE); - - rxcb._page = rxb->page; - pkt = rxb_addr(&rxcb); - - IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r, - i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); - - len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; - len += sizeof(u32); /* account for status word */ - trace_iwlwifi_dev_rx(priv(trans), pkt, len); - - /* Reclaim a command buffer only if this packet is a response - * to a (driver-originated) command. - * If the packet (e.g. Rx frame) originated from uCode, - * there is no command buffer to reclaim. - * Ucode should set SEQ_RX_FRAME bit if ucode-originated, - * but apparently a few don't get set; catch them here. */ - reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) && - (pkt->hdr.cmd != REPLY_RX_PHY_CMD) && - (pkt->hdr.cmd != REPLY_RX) && - (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) && - (pkt->hdr.cmd != REPLY_COMPRESSED_BA) && - (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && - (pkt->hdr.cmd != REPLY_TX); - - sequence = le16_to_cpu(pkt->hdr.sequence); - index = SEQ_TO_INDEX(sequence); - cmd_index = get_cmd_index(&txq->q, index); - - if (reclaim) - cmd = txq->cmd[cmd_index]; - else - cmd = NULL; - - /* warn if this is cmd response / notification and the uCode - * didn't set the SEQ_RX_FRAME for a frame that is - * uCode-originated - * If you saw this code after the second half of 2012, then - * please remove it - */ - WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false && - (!(pkt->hdr.sequence & SEQ_RX_FRAME)), - "reclaim is false, SEQ_RX_FRAME unset: %s\n", - get_cmd_string(pkt->hdr.cmd)); - - err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); - - /* - * XXX: After here, we should always check rxcb._page - * against NULL before touching it or its virtual - * memory (pkt). Because some rx_handler might have - * already taken or freed the pages. - */ - - if (reclaim) { - /* Invoke any callbacks, transfer the buffer to caller, - * and fire off the (possibly) blocking - * iwl_trans_send_cmd() - * as we reclaim the driver command queue */ - if (rxcb._page) - iwl_tx_cmd_complete(trans, &rxcb, err); - else - IWL_WARN(trans, "Claim null rxb?\n"); - } - - /* page was stolen from us */ - if (rxcb._page == NULL) - rxb->page = NULL; + IWL_DEBUG_RX(trans, "rxbuf: r = %d, i = %d (%p)\n", rxb); - /* Reuse the page if possible. For notification packets and - * SKBs that fail to Rx correctly, add them back into the - * rx_free list for reuse later. */ - spin_lock_irqsave(&rxq->lock, flags); - if (rxb->page != NULL) { - rxb->page_dma = dma_map_page(trans->dev, rxb->page, - 0, PAGE_SIZE << - hw_params(trans).rx_page_order, - DMA_FROM_DEVICE); - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; - } else - list_add_tail(&rxb->list, &rxq->rx_used); - - spin_unlock_irqrestore(&rxq->lock, flags); + iwl_rx_handle_rxbuf(trans, rxb); i = (i + 1) & RX_QUEUE_MASK; /* If there are a lot of unused frames, -- cgit v1.2.3-70-g09d2 From c977a33d84fb3d706faa0b62f9671f49b16dde34 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:41 -0800 Subject: iwlwifi: transport's tx_agg_alloc must not sleep The annotation/documentation is wrong, we call it in a context that can't sleep. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index e8ab8d8ca484..0197f31f3bec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -229,7 +229,7 @@ static inline void iwl_free_resp(struct iwl_host_cmd *cmd) * @reclaim: free packet until ssn. Returns a list of freed packets. * Must be atomic * @tx_agg_alloc: allocate resources for a TX BA session - * May sleep + * Must be atomic * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is * ready and a successful ADDBA response has been received. * May sleep @@ -474,8 +474,6 @@ static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans, static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans, int sta_id, int tid) { - might_sleep(); - if (trans->state != IWL_TRANS_FW_ALIVE) IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); -- cgit v1.2.3-70-g09d2 From bffc66ce2210b149fd171eccad2aef9802c0b35d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:42 -0800 Subject: iwlwifi: move queue functions to PCI-E iwl_queue_inc_wrap/iwl_queue_dec_wrap aren't shared functions, they are PCI-E specific, so move them into the appropriate header. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-shared.h | 20 -------------------- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index ed1811d43550..787d726efbc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -413,26 +413,6 @@ static inline bool iwl_have_debug_level(u32 level) return iwlagn_mod_params.debug_level & level; } -/** - * iwl_queue_inc_wrap - increment queue index, wrap back to beginning - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl_queue_inc_wrap(int index, int n_bd) -{ - return ++index & (n_bd - 1); -} - -/** - * iwl_queue_dec_wrap - decrement queue index, wrap back to end - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl_queue_dec_wrap(int index, int n_bd) -{ - return --index & (n_bd - 1); -} - struct iwl_rx_cmd_buffer { struct page *_page; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 632d4099900e..44952c371d33 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -115,6 +115,26 @@ struct iwl_dma_ptr { size_t size; }; +/** + * iwl_queue_inc_wrap - increment queue index, wrap back to beginning + * @index -- current index + * @n_bd -- total number of entries in queue (must be power of 2) + */ +static inline int iwl_queue_inc_wrap(int index, int n_bd) +{ + return ++index & (n_bd - 1); +} + +/** + * iwl_queue_dec_wrap - decrement queue index, wrap back to end + * @index -- current index + * @n_bd -- total number of entries in queue (must be power of 2) + */ +static inline int iwl_queue_dec_wrap(int index, int n_bd) +{ + return --index & (n_bd - 1); +} + /* * This queue number is required for proper operation * because the ucode will stop/start the scheduler as -- cgit v1.2.3-70-g09d2 From 930dfd5f20eba2cef41cdb2db04108b359b97594 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:43 -0800 Subject: iwlwifi: iwl_rx_cmd_buffer belongs to transport API This is how the transport passes things up into higher layers, so it belongs to the transport API. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-shared.h | 17 ----------------- drivers/net/wireless/iwlwifi/iwl-trans.h | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 787d726efbc8..2b9d21a7207d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -67,7 +67,6 @@ #include #include #include -#include /* for page_address */ #include #include "iwl-commands.h" @@ -413,22 +412,6 @@ static inline bool iwl_have_debug_level(u32 level) return iwlagn_mod_params.debug_level & level; } -struct iwl_rx_cmd_buffer { - struct page *_page; -}; - -static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r) -{ - return page_address(r->_page); -} - -static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) -{ - struct page *p = r->_page; - r->_page = NULL; - return p; -} - /* * mac80211 queues, ACs, hardware queues, FIFOs. * diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0197f31f3bec..b09192a028de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -64,6 +64,7 @@ #define __iwl_trans_h__ #include +#include /* for page_address */ #include "iwl-shared.h" #include "iwl-debug.h" @@ -201,6 +202,22 @@ static inline void iwl_free_resp(struct iwl_host_cmd *cmd) free_pages(cmd->_rx_page_addr, cmd->_rx_page_order); } +struct iwl_rx_cmd_buffer { + struct page *_page; +}; + +static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r) +{ + return page_address(r->_page); +} + +static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) +{ + struct page *p = r->_page; + r->_page = NULL; + return p; +} + /** * struct iwl_trans_ops - transport specific operations * -- cgit v1.2.3-70-g09d2 From 70a18c5d57998433d9f4de058a5286fbd16ed839 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:44 -0800 Subject: iwlwifi: move tid_to_ac to PCI-E Currently, queue mapping is handled in the transport. This may change, but until then the code for it can be close to where it's used rather than in iwl-shared.h. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-shared.h | 46 ------------------------ drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 46 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 2b9d21a7207d..740a058b22ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -412,52 +412,6 @@ static inline bool iwl_have_debug_level(u32 level) return iwlagn_mod_params.debug_level & level; } -/* - * mac80211 queues, ACs, hardware queues, FIFOs. - * - * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues - * - * Mac80211 uses the following numbers, which we get as from it - * by way of skb_get_queue_mapping(skb): - * - * VO 0 - * VI 1 - * BE 2 - * BK 3 - * - * - * Regular (not A-MPDU) frames are put into hardware queues corresponding - * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their - * own queue per aggregation session (RA/TID combination), such queues are - * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In - * order to map frames to the right queue, we also need an AC->hw queue - * mapping. This is implemented here. - * - * Due to the way hw queues are set up (by the hw specific modules like - * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity - * mapping. - */ - -static const u8 tid_to_ac[] = { - IEEE80211_AC_BE, - IEEE80211_AC_BK, - IEEE80211_AC_BK, - IEEE80211_AC_BE, - IEEE80211_AC_VI, - IEEE80211_AC_VI, - IEEE80211_AC_VO, - IEEE80211_AC_VO -}; - -static inline int get_ac_from_tid(u16 tid) -{ - if (likely(tid < ARRAY_SIZE(tid_to_ac))) - return tid_to_ac[tid]; - - /* no support for TIDs 8-15 yet */ - return -EINVAL; -} - enum iwl_rxon_context_id { IWL_RXON_CTX_BSS, IWL_RXON_CTX_PAN, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 0513b90da040..0164154f9c97 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -41,6 +41,43 @@ #define IWL_TX_CRC_SIZE 4 #define IWL_TX_DELIMITER_SIZE 4 +/* + * mac80211 queues, ACs, hardware queues, FIFOs. + * + * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues + * + * Mac80211 uses the following numbers, which we get as from it + * by way of skb_get_queue_mapping(skb): + * + * VO 0 + * VI 1 + * BE 2 + * BK 3 + * + * + * Regular (not A-MPDU) frames are put into hardware queues corresponding + * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their + * own queue per aggregation session (RA/TID combination), such queues are + * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In + * order to map frames to the right queue, we also need an AC->hw queue + * mapping. This is implemented here. + * + * Due to the way hw queues are set up (by the hw specific code), the AC->hw + * queue mapping is the identity mapping. + */ + +static const u8 tid_to_ac[] = { + IEEE80211_AC_BE, + IEEE80211_AC_BK, + IEEE80211_AC_BK, + IEEE80211_AC_BE, + IEEE80211_AC_VI, + IEEE80211_AC_VI, + IEEE80211_AC_VO, + IEEE80211_AC_VO +}; + + /** * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array */ @@ -442,6 +479,15 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, scd_retry ? "BA" : "AC/CMD", txq_id); } +static inline int get_ac_from_tid(u16 tid) +{ + if (likely(tid < ARRAY_SIZE(tid_to_ac))) + return tid_to_ac[tid]; + + /* no support for TIDs 8-15 yet */ + return -EINVAL; +} + static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie, u8 ctx, u16 tid) { -- cgit v1.2.3-70-g09d2 From 0439bb6200153406abb81b469b82d2336be0d175 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:45 -0800 Subject: iwlwifi: move IWL_MASK into file using it Only used in two places in the same file, no need to be in iwl-shared.h. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-shared.h | 1 - drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 740a058b22ee..976e6c584ac7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -444,7 +444,6 @@ iwl_remove_notification(struct iwl_shared *shrd, struct iwl_notification_wait *wait_entry); #define IWL_CMD(x) case x: return #x -#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) #define IWL_TRAFFIC_ENTRIES (256) #define IWL_TRAFFIC_ENTRY_SIZE (64) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index bb8f2fdf1281..3ae2fd720ed8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -78,6 +78,8 @@ #include "iwl-core.h" #include "iwl-ucode.h" +#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) + static int iwl_trans_rx_alloc(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = -- cgit v1.2.3-70-g09d2 From 61f0439277abb4f65d99b362b62cbabbde7032a0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:46 -0800 Subject: iwlwifi: move traffic log definitions These are DVM specific, and shouldn't be in iwl-shared.h. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.h | 4 ++++ drivers/net/wireless/iwlwifi/iwl-shared.h | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 42630f5e8de7..db44115a6775 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -265,6 +265,10 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, #define IWL_SCAN_CHECK_WATCHDOG (HZ * 7) +/* traffic log definitions */ +#define IWL_TRAFFIC_ENTRIES (256) +#define IWL_TRAFFIC_ENTRY_SIZE (64) + /***************************************************** * S e n d i n g H o s t C o m m a n d s * *****************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 976e6c584ac7..b816e70d1445 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -445,9 +445,6 @@ iwl_remove_notification(struct iwl_shared *shrd, #define IWL_CMD(x) case x: return #x -#define IWL_TRAFFIC_ENTRIES (256) -#define IWL_TRAFFIC_ENTRY_SIZE (64) - /***************************************************** * DRIVER STATUS FUNCTIONS ******************************************************/ -- cgit v1.2.3-70-g09d2 From ab0bd5b32a9c7ea2e7cc69d56c82a96be340c269 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:47 -0800 Subject: iwlwifi: fix station HT parameters My patch "iwlwifi: simplify auth/assoc flow" caused a serious throughput degradation due to me forgetting that there are HT settings in the station table. To restore throughput, set these parameters correctly when the sta moves to assoc state. This patch should probably be merged with the auth/assoc redesign patch for upstream. In that case, this paragraph should be added to the commit log as the third paragraph (before talking about RXON): However, as we only get the station HT data when the station moves into assoc state, we also need to program this into the device (and copy it into our database) then. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 81 +++++++++++++++++++++-------- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 + drivers/net/wireless/iwlwifi/iwl-mac80211.c | 18 +++++-- 3 files changed, 75 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 736f8dc404df..ca080265a829 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -169,34 +169,38 @@ int iwl_send_add_sta(struct iwl_priv *priv, return cmd.handler_status; } -static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, - struct ieee80211_sta *sta, - struct iwl_rxon_context *ctx) +static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, + struct ieee80211_sta *sta, + struct iwl_rxon_context *ctx, + __le32 *flags, __le32 *mask) { struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap; - __le32 sta_flags; u8 mimo_ps_mode; + *mask = STA_FLG_RTS_MIMO_PROT_MSK | + STA_FLG_MIMO_DIS_MSK | + STA_FLG_HT40_EN_MSK | + STA_FLG_MAX_AGG_SIZE_MSK | + STA_FLG_AGG_MPDU_DENSITY_MSK; + *flags = 0; + if (!sta || !sta_ht_inf->ht_supported) - goto done; + return; mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; - IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n", + + IWL_DEBUG_INFO(priv, "STA %pM SM PS mode: %s\n", (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ? "static" : (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ? "dynamic" : "disabled"); - sta_flags = priv->stations[index].sta.station_flags; - - sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK); - switch (mimo_ps_mode) { case WLAN_HT_CAP_SM_PS_STATIC: - sta_flags |= STA_FLG_MIMO_DIS_MSK; + *flags |= STA_FLG_MIMO_DIS_MSK; break; case WLAN_HT_CAP_SM_PS_DYNAMIC: - sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK; + *flags |= STA_FLG_RTS_MIMO_PROT_MSK; break; case WLAN_HT_CAP_SM_PS_DISABLED: break; @@ -205,20 +209,53 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, break; } - sta_flags |= cpu_to_le32( - (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS); + *flags |= cpu_to_le32( + (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS); - sta_flags |= cpu_to_le32( - (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); + *flags |= cpu_to_le32( + (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap)) - sta_flags |= STA_FLG_HT40_EN_MSK; - else - sta_flags &= ~STA_FLG_HT40_EN_MSK; + *flags |= STA_FLG_HT40_EN_MSK; +} + +int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + struct ieee80211_sta *sta) +{ + u8 sta_id = iwl_sta_id(sta); + __le32 flags, mask; + struct iwl_addsta_cmd cmd; + + if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION)) + return -EINVAL; - priv->stations[index].sta.station_flags = sta_flags; - done: - return; + iwl_sta_calc_ht_flags(priv, sta, ctx, &flags, &mask); + + spin_lock_bh(&priv->sta_lock); + priv->stations[sta_id].sta.station_flags &= ~mask; + priv->stations[sta_id].sta.station_flags |= flags; + spin_unlock_bh(&priv->sta_lock); + + memset(&cmd, 0, sizeof(cmd)); + cmd.mode = STA_CONTROL_MODIFY_MSK; + cmd.station_flags_msk = mask; + cmd.station_flags = flags; + cmd.sta.sta_id = sta_id; + + return iwl_send_add_sta(priv, &cmd, CMD_SYNC); +} + +static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, + struct ieee80211_sta *sta, + struct iwl_rxon_context *ctx) +{ + __le32 flags, mask; + + iwl_sta_calc_ht_flags(priv, sta, ctx, &flags, &mask); + + lockdep_assert_held(&priv->sta_lock); + priv->stations[index].sta.station_flags &= ~mask; + priv->stations[index].sta.station_flags |= flags; } /** diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index a9c018a7b8ba..70100f9a2e5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -229,6 +229,8 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_link_quality_cmd *lq, u8 flags, bool init); int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); +int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + struct ieee80211_sta *sta); static inline int iwl_sta_id(struct ieee80211_sta *sta) diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 8160f615f71a..7f937151a8af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -740,8 +740,9 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, enum ieee80211_sta_state new_state) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); + struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; enum { - NONE, ADD, REMOVE, RATE_INIT, ADD_RATE_INIT, + NONE, ADD, REMOVE, HT_RATE_INIT, ADD_RATE_INIT, } op = NONE; int ret; @@ -758,7 +759,7 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, op = REMOVE; else if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC) - op = RATE_INIT; + op = HT_RATE_INIT; } else { if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC) @@ -779,8 +780,6 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, ret = iwlagn_mac_sta_add(hw, vif, sta); if (ret) break; - /* fall through */ - case RATE_INIT: /* Initialize rate scaling */ IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", @@ -788,6 +787,17 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, iwl_rs_rate_init(priv, sta, iwl_sta_id(sta)); ret = 0; break; + case HT_RATE_INIT: + /* Initialize rate scaling */ + ret = iwl_sta_update_ht(priv, vif_priv->ctx, sta); + if (ret) + break; + IWL_DEBUG_INFO(priv, + "Initializing rate scaling for station %pM\n", + sta->addr); + iwl_rs_rate_init(priv, sta, iwl_sta_id(sta)); + ret = 0; + break; default: ret = 0; break; -- cgit v1.2.3-70-g09d2 From 7db5b989a0e28a40ce61ef0b26da1af18289d711 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:48 -0800 Subject: iwlwifi: move uCode deallocation to drv This shouldn't be in the op_mode, as it will later be switchable at runtime. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 -- drivers/net/wireless/iwlwifi/iwl-drv.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6dd4faead7cd..c3b594647def 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1385,8 +1385,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) /*This will stop the queues, move the device to low power state */ iwl_trans_stop_device(trans(priv)); - iwl_dealloc_ucode(nic(priv)); - iwl_eeprom_free(priv->shrd); /*netif_stop_queue(dev); */ diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 76fc4407b19e..590f57662754 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -99,5 +99,7 @@ void iwl_drv_stop(struct iwl_shared *shrd) if (shrd->nic->op_mode) iwl_op_mode_stop(shrd->nic->op_mode); + iwl_dealloc_ucode(shrd->nic); + kfree(shrd->nic); } -- cgit v1.2.3-70-g09d2 From 702e0630ee50c5f72e84da59daf5b23729140b62 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:49 -0800 Subject: iwlwifi: move iwl_base_params to shared header This is used from there, so should be in it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.h | 42 ------------------------------ drivers/net/wireless/iwlwifi/iwl-shared.h | 43 +++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index db44115a6775..7259cbf77da4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -95,48 +95,6 @@ struct iwl_lib_ops { void (*temperature)(struct iwl_priv *priv); }; -/* - * @max_ll_items: max number of OTP blocks - * @shadow_ram_support: shadow support for OTP memory - * @led_compensation: compensate on the led on/off time per HW according - * to the deviation to achieve the desired led frequency. - * The detail algorithm is described in iwl-led.c - * @chain_noise_num_beacons: number of beacons used to compute chain noise - * @adv_thermal_throttle: support advance thermal throttle - * @support_ct_kill_exit: support ct kill exit condition - * @support_wimax_coexist: support wimax/wifi co-exist - * @plcp_delta_threshold: plcp error rate threshold used to trigger - * radio tuning when there is a high receiving plcp error rate - * @chain_noise_scale: default chain noise scale used for gain computation - * @wd_timeout: TX queues watchdog timeout - * @max_event_log_size: size of event log buffer size for ucode event logging - * @shadow_reg_enable: HW shadhow register bit - * @no_idle_support: do not support idle mode - * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up - * wd_disable: disable watchdog timer - */ -struct iwl_base_params { - int eeprom_size; - int num_of_queues; /* def: HW dependent */ - int num_of_ampdu_queues;/* def: HW dependent */ - /* for iwl_apm_init() */ - u32 pll_cfg_val; - - const u16 max_ll_items; - const bool shadow_ram_support; - u16 led_compensation; - bool adv_thermal_throttle; - bool support_ct_kill_exit; - const bool support_wimax_coexist; - u8 plcp_delta_threshold; - s32 chain_noise_scale; - unsigned int wd_timeout; - u32 max_event_log_size; - const bool shadow_reg_enable; - const bool no_idle_support; - const bool hd_v2; - const bool wd_disable; -}; /* * @advanced_bt_coexist: support advanced bt coexist * @bt_init_traffic_load: specify initial bt traffic load diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index b816e70d1445..ef80e0386c30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -267,6 +267,49 @@ enum iwl_led_mode { IWL_LED_DISABLE, }; +/* + * @max_ll_items: max number of OTP blocks + * @shadow_ram_support: shadow support for OTP memory + * @led_compensation: compensate on the led on/off time per HW according + * to the deviation to achieve the desired led frequency. + * The detail algorithm is described in iwl-led.c + * @chain_noise_num_beacons: number of beacons used to compute chain noise + * @adv_thermal_throttle: support advance thermal throttle + * @support_ct_kill_exit: support ct kill exit condition + * @support_wimax_coexist: support wimax/wifi co-exist + * @plcp_delta_threshold: plcp error rate threshold used to trigger + * radio tuning when there is a high receiving plcp error rate + * @chain_noise_scale: default chain noise scale used for gain computation + * @wd_timeout: TX queues watchdog timeout + * @max_event_log_size: size of event log buffer size for ucode event logging + * @shadow_reg_enable: HW shadhow register bit + * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up + * @no_idle_support: do not support idle mode + * wd_disable: disable watchdog timer + */ +struct iwl_base_params { + int eeprom_size; + int num_of_queues; /* def: HW dependent */ + int num_of_ampdu_queues;/* def: HW dependent */ + /* for iwl_apm_init() */ + u32 pll_cfg_val; + + const u16 max_ll_items; + const bool shadow_ram_support; + u16 led_compensation; + bool adv_thermal_throttle; + bool support_ct_kill_exit; + const bool support_wimax_coexist; + u8 plcp_delta_threshold; + s32 chain_noise_scale; + unsigned int wd_timeout; + u32 max_event_log_size; + const bool shadow_reg_enable; + const bool hd_v2; + const bool no_idle_support; + const bool wd_disable; +}; + /** * struct iwl_cfg * @name: Offical name of the device -- cgit v1.2.3-70-g09d2 From 15854ef94f54ae8fa8b95eb66a2cfa5dcff481e9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:50 -0800 Subject: iwlwifi: move firmware request into drv Firmware request is a base driver flow, it isn't related to any specific mode. Move the code related to it into the base driver file iwl-drv.c. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-drv.c | 625 +++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-ucode.c | 622 ------------------------------ drivers/net/wireless/iwlwifi/iwl-wifi.h | 5 - 3 files changed, 625 insertions(+), 627 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 590f57662754..343f41eb4e4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -61,12 +61,637 @@ * *****************************************************************************/ #include +#include +#include +#include #include "iwl-drv.h" #include "iwl-trans.h" #include "iwl-wifi.h" +#include "iwl-shared.h" #include "iwl-op-mode.h" +static void iwl_free_fw_desc(struct iwl_nic *nic, struct fw_desc *desc) +{ + if (desc->v_addr) + dma_free_coherent(trans(nic)->dev, desc->len, + desc->v_addr, desc->p_addr); + desc->v_addr = NULL; + desc->len = 0; +} + +static void iwl_free_fw_img(struct iwl_nic *nic, struct fw_img *img) +{ + iwl_free_fw_desc(nic, &img->code); + iwl_free_fw_desc(nic, &img->data); +} + +static void iwl_dealloc_ucode(struct iwl_nic *nic) +{ + iwl_free_fw_img(nic, &nic->fw.ucode_rt); + iwl_free_fw_img(nic, &nic->fw.ucode_init); + iwl_free_fw_img(nic, &nic->fw.ucode_wowlan); +} + +static int iwl_alloc_fw_desc(struct iwl_nic *nic, struct fw_desc *desc, + const void *data, size_t len) +{ + if (!len) { + desc->v_addr = NULL; + return -EINVAL; + } + + desc->v_addr = dma_alloc_coherent(trans(nic)->dev, len, + &desc->p_addr, GFP_KERNEL); + if (!desc->v_addr) + return -ENOMEM; + + desc->len = len; + memcpy(desc->v_addr, data, len); + return 0; +} + +static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); + +#define UCODE_EXPERIMENTAL_INDEX 100 +#define UCODE_EXPERIMENTAL_TAG "exp" + +static int iwl_request_firmware(struct iwl_nic *nic, bool first) +{ + const struct iwl_cfg *cfg = cfg(nic); + const char *name_pre = cfg->fw_name_pre; + char tag[8]; + + if (first) { +#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE + nic->fw_index = UCODE_EXPERIMENTAL_INDEX; + strcpy(tag, UCODE_EXPERIMENTAL_TAG); + } else if (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) { +#endif + nic->fw_index = cfg->ucode_api_max; + sprintf(tag, "%d", nic->fw_index); + } else { + nic->fw_index--; + sprintf(tag, "%d", nic->fw_index); + } + + if (nic->fw_index < cfg->ucode_api_min) { + IWL_ERR(nic, "no suitable firmware found!\n"); + return -ENOENT; + } + + sprintf(nic->firmware_name, "%s%s%s", name_pre, tag, ".ucode"); + + IWL_DEBUG_INFO(nic, "attempting to load firmware %s'%s'\n", + (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) + ? "EXPERIMENTAL " : "", + nic->firmware_name); + + return request_firmware_nowait(THIS_MODULE, 1, nic->firmware_name, + trans(nic)->dev, + GFP_KERNEL, nic, iwl_ucode_callback); +} + +struct iwlagn_firmware_pieces { + const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data; + size_t inst_size, data_size, init_size, init_data_size, + wowlan_inst_size, wowlan_data_size; + + u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; + u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; +}; + +static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic, + const struct firmware *ucode_raw, + struct iwlagn_firmware_pieces *pieces) +{ + struct iwl_ucode_header *ucode = (void *)ucode_raw->data; + u32 api_ver, hdr_size, build; + char buildstr[25]; + const u8 *src; + + nic->fw.ucode_ver = le32_to_cpu(ucode->ver); + api_ver = IWL_UCODE_API(nic->fw.ucode_ver); + + switch (api_ver) { + default: + hdr_size = 28; + if (ucode_raw->size < hdr_size) { + IWL_ERR(nic, "File size too small!\n"); + return -EINVAL; + } + build = le32_to_cpu(ucode->u.v2.build); + pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); + pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); + pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); + pieces->init_data_size = + le32_to_cpu(ucode->u.v2.init_data_size); + src = ucode->u.v2.data; + break; + case 0: + case 1: + case 2: + hdr_size = 24; + if (ucode_raw->size < hdr_size) { + IWL_ERR(nic, "File size too small!\n"); + return -EINVAL; + } + build = 0; + pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size); + pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); + pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); + pieces->init_data_size = + le32_to_cpu(ucode->u.v1.init_data_size); + src = ucode->u.v1.data; + break; + } + + if (build) + sprintf(buildstr, " build %u%s", build, + (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) + ? " (EXP)" : ""); + else + buildstr[0] = '\0'; + + snprintf(nic->fw.fw_version, + sizeof(nic->fw.fw_version), + "%u.%u.%u.%u%s", + IWL_UCODE_MAJOR(nic->fw.ucode_ver), + IWL_UCODE_MINOR(nic->fw.ucode_ver), + IWL_UCODE_API(nic->fw.ucode_ver), + IWL_UCODE_SERIAL(nic->fw.ucode_ver), + buildstr); + + /* Verify size of file vs. image size info in file's header */ + if (ucode_raw->size != hdr_size + pieces->inst_size + + pieces->data_size + pieces->init_size + + pieces->init_data_size) { + + IWL_ERR(nic, + "uCode file size %d does not match expected size\n", + (int)ucode_raw->size); + return -EINVAL; + } + + pieces->inst = src; + src += pieces->inst_size; + pieces->data = src; + src += pieces->data_size; + pieces->init = src; + src += pieces->init_size; + pieces->init_data = src; + src += pieces->init_data_size; + + return 0; +} + +static int iwl_parse_tlv_firmware(struct iwl_nic *nic, + const struct firmware *ucode_raw, + struct iwlagn_firmware_pieces *pieces, + struct iwl_ucode_capabilities *capa) +{ + struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data; + struct iwl_ucode_tlv *tlv; + size_t len = ucode_raw->size; + const u8 *data; + int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative; + int tmp; + u64 alternatives; + u32 tlv_len; + enum iwl_ucode_tlv_type tlv_type; + const u8 *tlv_data; + char buildstr[25]; + u32 build; + + if (len < sizeof(*ucode)) { + IWL_ERR(nic, "uCode has invalid length: %zd\n", len); + return -EINVAL; + } + + if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) { + IWL_ERR(nic, "invalid uCode magic: 0X%x\n", + le32_to_cpu(ucode->magic)); + return -EINVAL; + } + + /* + * Check which alternatives are present, and "downgrade" + * when the chosen alternative is not present, warning + * the user when that happens. Some files may not have + * any alternatives, so don't warn in that case. + */ + alternatives = le64_to_cpu(ucode->alternatives); + tmp = wanted_alternative; + if (wanted_alternative > 63) + wanted_alternative = 63; + while (wanted_alternative && !(alternatives & BIT(wanted_alternative))) + wanted_alternative--; + if (wanted_alternative && wanted_alternative != tmp) + IWL_WARN(nic, + "uCode alternative %d not available, choosing %d\n", + tmp, wanted_alternative); + + nic->fw.ucode_ver = le32_to_cpu(ucode->ver); + build = le32_to_cpu(ucode->build); + + if (build) + sprintf(buildstr, " build %u%s", build, + (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) + ? " (EXP)" : ""); + else + buildstr[0] = '\0'; + + snprintf(nic->fw.fw_version, + sizeof(nic->fw.fw_version), + "%u.%u.%u.%u%s", + IWL_UCODE_MAJOR(nic->fw.ucode_ver), + IWL_UCODE_MINOR(nic->fw.ucode_ver), + IWL_UCODE_API(nic->fw.ucode_ver), + IWL_UCODE_SERIAL(nic->fw.ucode_ver), + buildstr); + + data = ucode->data; + + len -= sizeof(*ucode); + + while (len >= sizeof(*tlv)) { + u16 tlv_alt; + + len -= sizeof(*tlv); + tlv = (void *)data; + + tlv_len = le32_to_cpu(tlv->length); + tlv_type = le16_to_cpu(tlv->type); + tlv_alt = le16_to_cpu(tlv->alternative); + tlv_data = tlv->data; + + if (len < tlv_len) { + IWL_ERR(nic, "invalid TLV len: %zd/%u\n", + len, tlv_len); + return -EINVAL; + } + len -= ALIGN(tlv_len, 4); + data += sizeof(*tlv) + ALIGN(tlv_len, 4); + + /* + * Alternative 0 is always valid. + * + * Skip alternative TLVs that are not selected. + */ + if (tlv_alt != 0 && tlv_alt != wanted_alternative) + continue; + + switch (tlv_type) { + case IWL_UCODE_TLV_INST: + pieces->inst = tlv_data; + pieces->inst_size = tlv_len; + break; + case IWL_UCODE_TLV_DATA: + pieces->data = tlv_data; + pieces->data_size = tlv_len; + break; + case IWL_UCODE_TLV_INIT: + pieces->init = tlv_data; + pieces->init_size = tlv_len; + break; + case IWL_UCODE_TLV_INIT_DATA: + pieces->init_data = tlv_data; + pieces->init_data_size = tlv_len; + break; + case IWL_UCODE_TLV_BOOT: + IWL_ERR(nic, "Found unexpected BOOT ucode\n"); + break; + case IWL_UCODE_TLV_PROBE_MAX_LEN: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + capa->max_probe_length = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_PAN: + if (tlv_len) + goto invalid_tlv_len; + capa->flags |= IWL_UCODE_TLV_FLAGS_PAN; + break; + case IWL_UCODE_TLV_FLAGS: + /* must be at least one u32 */ + if (tlv_len < sizeof(u32)) + goto invalid_tlv_len; + /* and a proper number of u32s */ + if (tlv_len % sizeof(u32)) + goto invalid_tlv_len; + /* + * This driver only reads the first u32 as + * right now no more features are defined, + * if that changes then either the driver + * will not work with the new firmware, or + * it'll not take advantage of new features. + */ + capa->flags = le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_INIT_EVTLOG_PTR: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_evtlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_evtlog_size = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_INIT_ERRLOG_PTR: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_errlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_evtlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_evtlog_size = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_errlog_ptr = + le32_to_cpup((__le32 *)tlv_data); + break; + case IWL_UCODE_TLV_ENHANCE_SENS_TBL: + if (tlv_len) + goto invalid_tlv_len; + nic->fw.enhance_sensitivity_table = true; + break; + case IWL_UCODE_TLV_WOWLAN_INST: + pieces->wowlan_inst = tlv_data; + pieces->wowlan_inst_size = tlv_len; + break; + case IWL_UCODE_TLV_WOWLAN_DATA: + pieces->wowlan_data = tlv_data; + pieces->wowlan_data_size = tlv_len; + break; + case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + capa->standard_phy_calibration_size = + le32_to_cpup((__le32 *)tlv_data); + break; + default: + IWL_DEBUG_INFO(nic, "unknown TLV: %d\n", tlv_type); + break; + } + } + + if (len) { + IWL_ERR(nic, "invalid TLV after parsing: %zd\n", len); + iwl_print_hex_dump(nic, IWL_DL_FW, (u8 *)data, len); + return -EINVAL; + } + + return 0; + + invalid_tlv_len: + IWL_ERR(nic, "TLV %d has invalid size: %u\n", tlv_type, tlv_len); + iwl_print_hex_dump(nic, IWL_DL_FW, tlv_data, tlv_len); + + return -EINVAL; +} + +/** + * iwl_ucode_callback - callback when firmware was loaded + * + * If loaded successfully, copies the firmware into buffers + * for the card to fetch (via DMA). + */ +static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) +{ + struct iwl_nic *nic = context; + const struct iwl_cfg *cfg = cfg(nic); + struct iwl_fw *fw = &nic->fw; + struct iwl_ucode_header *ucode; + int err; + struct iwlagn_firmware_pieces pieces; + const unsigned int api_max = cfg->ucode_api_max; + unsigned int api_ok = cfg->ucode_api_ok; + const unsigned int api_min = cfg->ucode_api_min; + u32 api_ver; + + fw->ucode_capa.max_probe_length = 200; + fw->ucode_capa.standard_phy_calibration_size = + IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; + + if (!api_ok) + api_ok = api_max; + + memset(&pieces, 0, sizeof(pieces)); + + if (!ucode_raw) { + if (nic->fw_index <= api_ok) + IWL_ERR(nic, + "request for firmware file '%s' failed.\n", + nic->firmware_name); + goto try_again; + } + + IWL_DEBUG_INFO(nic, "Loaded firmware file '%s' (%zd bytes).\n", + nic->firmware_name, ucode_raw->size); + + /* Make sure that we got at least the API version number */ + if (ucode_raw->size < 4) { + IWL_ERR(nic, "File size way too small!\n"); + goto try_again; + } + + /* Data from ucode file: header followed by uCode images */ + ucode = (struct iwl_ucode_header *)ucode_raw->data; + + if (ucode->ver) + err = iwl_parse_v1_v2_firmware(nic, ucode_raw, &pieces); + else + err = iwl_parse_tlv_firmware(nic, ucode_raw, &pieces, + &fw->ucode_capa); + + if (err) + goto try_again; + + api_ver = IWL_UCODE_API(nic->fw.ucode_ver); + + /* + * api_ver should match the api version forming part of the + * firmware filename ... but we don't check for that and only rely + * on the API version read from firmware header from here on forward + */ + /* no api version check required for experimental uCode */ + if (nic->fw_index != UCODE_EXPERIMENTAL_INDEX) { + if (api_ver < api_min || api_ver > api_max) { + IWL_ERR(nic, + "Driver unable to support your firmware API. " + "Driver supports v%u, firmware is v%u.\n", + api_max, api_ver); + goto try_again; + } + + if (api_ver < api_ok) { + if (api_ok != api_max) + IWL_ERR(nic, "Firmware has old API version, " + "expected v%u through v%u, got v%u.\n", + api_ok, api_max, api_ver); + else + IWL_ERR(nic, "Firmware has old API version, " + "expected v%u, got v%u.\n", + api_max, api_ver); + IWL_ERR(nic, "New firmware can be obtained from " + "http://www.intellinuxwireless.org/.\n"); + } + } + + IWL_INFO(nic, "loaded firmware version %s", nic->fw.fw_version); + + /* + * For any of the failures below (before allocating pci memory) + * we will try to load a version with a smaller API -- maybe the + * user just got a corrupted version of the latest API. + */ + + IWL_DEBUG_INFO(nic, "f/w package hdr ucode version raw = 0x%x\n", + nic->fw.ucode_ver); + IWL_DEBUG_INFO(nic, "f/w package hdr runtime inst size = %Zd\n", + pieces.inst_size); + IWL_DEBUG_INFO(nic, "f/w package hdr runtime data size = %Zd\n", + pieces.data_size); + IWL_DEBUG_INFO(nic, "f/w package hdr init inst size = %Zd\n", + pieces.init_size); + IWL_DEBUG_INFO(nic, "f/w package hdr init data size = %Zd\n", + pieces.init_data_size); + + /* Verify that uCode images will fit in card's SRAM */ + if (pieces.inst_size > cfg->max_inst_size) { + IWL_ERR(nic, "uCode instr len %Zd too large to fit in\n", + pieces.inst_size); + goto try_again; + } + + if (pieces.data_size > cfg->max_data_size) { + IWL_ERR(nic, "uCode data len %Zd too large to fit in\n", + pieces.data_size); + goto try_again; + } + + if (pieces.init_size > cfg->max_inst_size) { + IWL_ERR(nic, "uCode init instr len %Zd too large to fit in\n", + pieces.init_size); + goto try_again; + } + + if (pieces.init_data_size > cfg->max_data_size) { + IWL_ERR(nic, "uCode init data len %Zd too large to fit in\n", + pieces.init_data_size); + goto try_again; + } + + /* Allocate ucode buffers for card's bus-master loading ... */ + + /* Runtime instructions and 2 copies of data: + * 1) unmodified from disk + * 2) backup cache for save/restore during power-downs */ + if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.code, + pieces.inst, pieces.inst_size)) + goto err_pci_alloc; + if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.data, + pieces.data, pieces.data_size)) + goto err_pci_alloc; + + /* Initialization instructions and data */ + if (pieces.init_size && pieces.init_data_size) { + if (iwl_alloc_fw_desc(nic, + &nic->fw.ucode_init.code, + pieces.init, pieces.init_size)) + goto err_pci_alloc; + if (iwl_alloc_fw_desc(nic, + &nic->fw.ucode_init.data, + pieces.init_data, pieces.init_data_size)) + goto err_pci_alloc; + } + + /* WoWLAN instructions and data */ + if (pieces.wowlan_inst_size && pieces.wowlan_data_size) { + if (iwl_alloc_fw_desc(nic, + &nic->fw.ucode_wowlan.code, + pieces.wowlan_inst, + pieces.wowlan_inst_size)) + goto err_pci_alloc; + if (iwl_alloc_fw_desc(nic, + &nic->fw.ucode_wowlan.data, + pieces.wowlan_data, + pieces.wowlan_data_size)) + goto err_pci_alloc; + } + + /* Now that we can no longer fail, copy information */ + + /* + * The (size - 16) / 12 formula is based on the information recorded + * for each event, which is of mode 1 (including timestamp) for all + * new microcodes that include this information. + */ + nic->init_evtlog_ptr = pieces.init_evtlog_ptr; + if (pieces.init_evtlog_size) + nic->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; + else + nic->init_evtlog_size = + cfg->base_params->max_event_log_size; + nic->init_errlog_ptr = pieces.init_errlog_ptr; + nic->inst_evtlog_ptr = pieces.inst_evtlog_ptr; + if (pieces.inst_evtlog_size) + nic->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; + else + nic->inst_evtlog_size = + cfg->base_params->max_event_log_size; + nic->inst_errlog_ptr = pieces.inst_errlog_ptr; + + /* + * figure out the offset of chain noise reset and gain commands + * base on the size of standard phy calibration commands table size + */ + if (fw->ucode_capa.standard_phy_calibration_size > + IWL_MAX_PHY_CALIBRATE_TBL_SIZE) + fw->ucode_capa.standard_phy_calibration_size = + IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE; + + /* We have our copies now, allow OS release its copies */ + release_firmware(ucode_raw); + complete(&nic->request_firmware_complete); + + nic->op_mode = iwl_dvm_ops.start(nic->shrd->trans); + + if (!nic->op_mode) + goto out_unbind; + + return; + + try_again: + /* try next, if any */ + release_firmware(ucode_raw); + if (iwl_request_firmware(nic, false)) + goto out_unbind; + return; + + err_pci_alloc: + IWL_ERR(nic, "failed to allocate pci memory\n"); + iwl_dealloc_ucode(nic); + release_firmware(ucode_raw); + out_unbind: + complete(&nic->request_firmware_complete); + device_release_driver(trans(nic)->dev); +} + int iwl_drv_start(struct iwl_shared *shrd, struct iwl_trans *trans, const struct iwl_cfg *cfg) { diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 12e79d04374f..64a9c5ce5f89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -28,11 +28,8 @@ *****************************************************************************/ #include -#include #include #include -#include -#include #include "iwl-ucode.h" #include "iwl-wifi.h" @@ -83,46 +80,6 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { * ******************************************************************************/ -static void iwl_free_fw_desc(struct iwl_nic *nic, struct fw_desc *desc) -{ - if (desc->v_addr) - dma_free_coherent(trans(nic)->dev, desc->len, - desc->v_addr, desc->p_addr); - desc->v_addr = NULL; - desc->len = 0; -} - -static void iwl_free_fw_img(struct iwl_nic *nic, struct fw_img *img) -{ - iwl_free_fw_desc(nic, &img->code); - iwl_free_fw_desc(nic, &img->data); -} - -void iwl_dealloc_ucode(struct iwl_nic *nic) -{ - iwl_free_fw_img(nic, &nic->fw.ucode_rt); - iwl_free_fw_img(nic, &nic->fw.ucode_init); - iwl_free_fw_img(nic, &nic->fw.ucode_wowlan); -} - -static int iwl_alloc_fw_desc(struct iwl_nic *nic, struct fw_desc *desc, - const void *data, size_t len) -{ - if (!len) { - desc->v_addr = NULL; - return -EINVAL; - } - - desc->v_addr = dma_alloc_coherent(trans(nic)->dev, len, - &desc->p_addr, GFP_KERNEL); - if (!desc->v_addr) - return -ENOMEM; - - desc->len = len; - memcpy(desc->v_addr, data, len); - return 0; -} - static inline struct fw_img *iwl_get_ucode_image(struct iwl_nic *nic, enum iwl_ucode_type ucode_type) { @@ -685,582 +642,3 @@ int iwl_run_init_ucode(struct iwl_trans *trans) iwl_trans_stop_device(trans); return ret; } - -static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); - -#define UCODE_EXPERIMENTAL_TAG "exp" - -int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first) -{ - const struct iwl_cfg *cfg = cfg(nic); - const char *name_pre = cfg->fw_name_pre; - char tag[8]; - - if (first) { -#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE - nic->fw_index = UCODE_EXPERIMENTAL_INDEX; - strcpy(tag, UCODE_EXPERIMENTAL_TAG); - } else if (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) { -#endif - nic->fw_index = cfg->ucode_api_max; - sprintf(tag, "%d", nic->fw_index); - } else { - nic->fw_index--; - sprintf(tag, "%d", nic->fw_index); - } - - if (nic->fw_index < cfg->ucode_api_min) { - IWL_ERR(nic, "no suitable firmware found!\n"); - return -ENOENT; - } - - sprintf(nic->firmware_name, "%s%s%s", name_pre, tag, ".ucode"); - - IWL_DEBUG_INFO(nic, "attempting to load firmware %s'%s'\n", - (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) - ? "EXPERIMENTAL " : "", - nic->firmware_name); - - return request_firmware_nowait(THIS_MODULE, 1, nic->firmware_name, - trans(nic)->dev, - GFP_KERNEL, nic, iwl_ucode_callback); -} - -struct iwlagn_firmware_pieces { - const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data; - size_t inst_size, data_size, init_size, init_data_size, - wowlan_inst_size, wowlan_data_size; - - u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; - u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; -}; - -static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic, - const struct firmware *ucode_raw, - struct iwlagn_firmware_pieces *pieces) -{ - struct iwl_ucode_header *ucode = (void *)ucode_raw->data; - u32 api_ver, hdr_size, build; - char buildstr[25]; - const u8 *src; - - nic->fw.ucode_ver = le32_to_cpu(ucode->ver); - api_ver = IWL_UCODE_API(nic->fw.ucode_ver); - - switch (api_ver) { - default: - hdr_size = 28; - if (ucode_raw->size < hdr_size) { - IWL_ERR(nic, "File size too small!\n"); - return -EINVAL; - } - build = le32_to_cpu(ucode->u.v2.build); - pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); - pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); - pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); - pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); - src = ucode->u.v2.data; - break; - case 0: - case 1: - case 2: - hdr_size = 24; - if (ucode_raw->size < hdr_size) { - IWL_ERR(nic, "File size too small!\n"); - return -EINVAL; - } - build = 0; - pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size); - pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); - pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); - pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size); - src = ucode->u.v1.data; - break; - } - - if (build) - sprintf(buildstr, " build %u%s", build, - (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) - ? " (EXP)" : ""); - else - buildstr[0] = '\0'; - - snprintf(nic->fw.fw_version, - sizeof(nic->fw.fw_version), - "%u.%u.%u.%u%s", - IWL_UCODE_MAJOR(nic->fw.ucode_ver), - IWL_UCODE_MINOR(nic->fw.ucode_ver), - IWL_UCODE_API(nic->fw.ucode_ver), - IWL_UCODE_SERIAL(nic->fw.ucode_ver), - buildstr); - - /* Verify size of file vs. image size info in file's header */ - if (ucode_raw->size != hdr_size + pieces->inst_size + - pieces->data_size + pieces->init_size + - pieces->init_data_size) { - - IWL_ERR(nic, - "uCode file size %d does not match expected size\n", - (int)ucode_raw->size); - return -EINVAL; - } - - pieces->inst = src; - src += pieces->inst_size; - pieces->data = src; - src += pieces->data_size; - pieces->init = src; - src += pieces->init_size; - pieces->init_data = src; - src += pieces->init_data_size; - - return 0; -} - -static int iwl_parse_tlv_firmware(struct iwl_nic *nic, - const struct firmware *ucode_raw, - struct iwlagn_firmware_pieces *pieces, - struct iwl_ucode_capabilities *capa) -{ - struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data; - struct iwl_ucode_tlv *tlv; - size_t len = ucode_raw->size; - const u8 *data; - int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative; - int tmp; - u64 alternatives; - u32 tlv_len; - enum iwl_ucode_tlv_type tlv_type; - const u8 *tlv_data; - char buildstr[25]; - u32 build; - - if (len < sizeof(*ucode)) { - IWL_ERR(nic, "uCode has invalid length: %zd\n", len); - return -EINVAL; - } - - if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) { - IWL_ERR(nic, "invalid uCode magic: 0X%x\n", - le32_to_cpu(ucode->magic)); - return -EINVAL; - } - - /* - * Check which alternatives are present, and "downgrade" - * when the chosen alternative is not present, warning - * the user when that happens. Some files may not have - * any alternatives, so don't warn in that case. - */ - alternatives = le64_to_cpu(ucode->alternatives); - tmp = wanted_alternative; - if (wanted_alternative > 63) - wanted_alternative = 63; - while (wanted_alternative && !(alternatives & BIT(wanted_alternative))) - wanted_alternative--; - if (wanted_alternative && wanted_alternative != tmp) - IWL_WARN(nic, - "uCode alternative %d not available, choosing %d\n", - tmp, wanted_alternative); - - nic->fw.ucode_ver = le32_to_cpu(ucode->ver); - build = le32_to_cpu(ucode->build); - - if (build) - sprintf(buildstr, " build %u%s", build, - (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) - ? " (EXP)" : ""); - else - buildstr[0] = '\0'; - - snprintf(nic->fw.fw_version, - sizeof(nic->fw.fw_version), - "%u.%u.%u.%u%s", - IWL_UCODE_MAJOR(nic->fw.ucode_ver), - IWL_UCODE_MINOR(nic->fw.ucode_ver), - IWL_UCODE_API(nic->fw.ucode_ver), - IWL_UCODE_SERIAL(nic->fw.ucode_ver), - buildstr); - - data = ucode->data; - - len -= sizeof(*ucode); - - while (len >= sizeof(*tlv)) { - u16 tlv_alt; - - len -= sizeof(*tlv); - tlv = (void *)data; - - tlv_len = le32_to_cpu(tlv->length); - tlv_type = le16_to_cpu(tlv->type); - tlv_alt = le16_to_cpu(tlv->alternative); - tlv_data = tlv->data; - - if (len < tlv_len) { - IWL_ERR(nic, "invalid TLV len: %zd/%u\n", - len, tlv_len); - return -EINVAL; - } - len -= ALIGN(tlv_len, 4); - data += sizeof(*tlv) + ALIGN(tlv_len, 4); - - /* - * Alternative 0 is always valid. - * - * Skip alternative TLVs that are not selected. - */ - if (tlv_alt != 0 && tlv_alt != wanted_alternative) - continue; - - switch (tlv_type) { - case IWL_UCODE_TLV_INST: - pieces->inst = tlv_data; - pieces->inst_size = tlv_len; - break; - case IWL_UCODE_TLV_DATA: - pieces->data = tlv_data; - pieces->data_size = tlv_len; - break; - case IWL_UCODE_TLV_INIT: - pieces->init = tlv_data; - pieces->init_size = tlv_len; - break; - case IWL_UCODE_TLV_INIT_DATA: - pieces->init_data = tlv_data; - pieces->init_data_size = tlv_len; - break; - case IWL_UCODE_TLV_BOOT: - IWL_ERR(nic, "Found unexpected BOOT ucode\n"); - break; - case IWL_UCODE_TLV_PROBE_MAX_LEN: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - capa->max_probe_length = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_PAN: - if (tlv_len) - goto invalid_tlv_len; - capa->flags |= IWL_UCODE_TLV_FLAGS_PAN; - break; - case IWL_UCODE_TLV_FLAGS: - /* must be at least one u32 */ - if (tlv_len < sizeof(u32)) - goto invalid_tlv_len; - /* and a proper number of u32s */ - if (tlv_len % sizeof(u32)) - goto invalid_tlv_len; - /* - * This driver only reads the first u32 as - * right now no more features are defined, - * if that changes then either the driver - * will not work with the new firmware, or - * it'll not take advantage of new features. - */ - capa->flags = le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_INIT_EVTLOG_PTR: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->init_evtlog_ptr = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->init_evtlog_size = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_INIT_ERRLOG_PTR: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->init_errlog_ptr = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->inst_evtlog_ptr = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->inst_evtlog_size = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - pieces->inst_errlog_ptr = - le32_to_cpup((__le32 *)tlv_data); - break; - case IWL_UCODE_TLV_ENHANCE_SENS_TBL: - if (tlv_len) - goto invalid_tlv_len; - nic->fw.enhance_sensitivity_table = true; - break; - case IWL_UCODE_TLV_WOWLAN_INST: - pieces->wowlan_inst = tlv_data; - pieces->wowlan_inst_size = tlv_len; - break; - case IWL_UCODE_TLV_WOWLAN_DATA: - pieces->wowlan_data = tlv_data; - pieces->wowlan_data_size = tlv_len; - break; - case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE: - if (tlv_len != sizeof(u32)) - goto invalid_tlv_len; - capa->standard_phy_calibration_size = - le32_to_cpup((__le32 *)tlv_data); - break; - default: - IWL_DEBUG_INFO(nic, "unknown TLV: %d\n", tlv_type); - break; - } - } - - if (len) { - IWL_ERR(nic, "invalid TLV after parsing: %zd\n", len); - iwl_print_hex_dump(nic, IWL_DL_FW, (u8 *)data, len); - return -EINVAL; - } - - return 0; - - invalid_tlv_len: - IWL_ERR(nic, "TLV %d has invalid size: %u\n", tlv_type, tlv_len); - iwl_print_hex_dump(nic, IWL_DL_FW, tlv_data, tlv_len); - - return -EINVAL; -} - -/** - * iwl_ucode_callback - callback when firmware was loaded - * - * If loaded successfully, copies the firmware into buffers - * for the card to fetch (via DMA). - */ -static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) -{ - struct iwl_nic *nic = context; - const struct iwl_cfg *cfg = cfg(nic); - struct iwl_fw *fw = &nic->fw; - struct iwl_ucode_header *ucode; - int err; - struct iwlagn_firmware_pieces pieces; - const unsigned int api_max = cfg->ucode_api_max; - unsigned int api_ok = cfg->ucode_api_ok; - const unsigned int api_min = cfg->ucode_api_min; - u32 api_ver; - - fw->ucode_capa.max_probe_length = 200; - fw->ucode_capa.standard_phy_calibration_size = - IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; - - if (!api_ok) - api_ok = api_max; - - memset(&pieces, 0, sizeof(pieces)); - - if (!ucode_raw) { - if (nic->fw_index <= api_ok) - IWL_ERR(nic, - "request for firmware file '%s' failed.\n", - nic->firmware_name); - goto try_again; - } - - IWL_DEBUG_INFO(nic, "Loaded firmware file '%s' (%zd bytes).\n", - nic->firmware_name, ucode_raw->size); - - /* Make sure that we got at least the API version number */ - if (ucode_raw->size < 4) { - IWL_ERR(nic, "File size way too small!\n"); - goto try_again; - } - - /* Data from ucode file: header followed by uCode images */ - ucode = (struct iwl_ucode_header *)ucode_raw->data; - - if (ucode->ver) - err = iwl_parse_v1_v2_firmware(nic, ucode_raw, &pieces); - else - err = iwl_parse_tlv_firmware(nic, ucode_raw, &pieces, - &fw->ucode_capa); - - if (err) - goto try_again; - - api_ver = IWL_UCODE_API(nic->fw.ucode_ver); - - /* - * api_ver should match the api version forming part of the - * firmware filename ... but we don't check for that and only rely - * on the API version read from firmware header from here on forward - */ - /* no api version check required for experimental uCode */ - if (nic->fw_index != UCODE_EXPERIMENTAL_INDEX) { - if (api_ver < api_min || api_ver > api_max) { - IWL_ERR(nic, - "Driver unable to support your firmware API. " - "Driver supports v%u, firmware is v%u.\n", - api_max, api_ver); - goto try_again; - } - - if (api_ver < api_ok) { - if (api_ok != api_max) - IWL_ERR(nic, "Firmware has old API version, " - "expected v%u through v%u, got v%u.\n", - api_ok, api_max, api_ver); - else - IWL_ERR(nic, "Firmware has old API version, " - "expected v%u, got v%u.\n", - api_max, api_ver); - IWL_ERR(nic, "New firmware can be obtained from " - "http://www.intellinuxwireless.org/.\n"); - } - } - - IWL_INFO(nic, "loaded firmware version %s", nic->fw.fw_version); - - /* - * For any of the failures below (before allocating pci memory) - * we will try to load a version with a smaller API -- maybe the - * user just got a corrupted version of the latest API. - */ - - IWL_DEBUG_INFO(nic, "f/w package hdr ucode version raw = 0x%x\n", - nic->fw.ucode_ver); - IWL_DEBUG_INFO(nic, "f/w package hdr runtime inst size = %Zd\n", - pieces.inst_size); - IWL_DEBUG_INFO(nic, "f/w package hdr runtime data size = %Zd\n", - pieces.data_size); - IWL_DEBUG_INFO(nic, "f/w package hdr init inst size = %Zd\n", - pieces.init_size); - IWL_DEBUG_INFO(nic, "f/w package hdr init data size = %Zd\n", - pieces.init_data_size); - - /* Verify that uCode images will fit in card's SRAM */ - if (pieces.inst_size > cfg->max_inst_size) { - IWL_ERR(nic, "uCode instr len %Zd too large to fit in\n", - pieces.inst_size); - goto try_again; - } - - if (pieces.data_size > cfg->max_data_size) { - IWL_ERR(nic, "uCode data len %Zd too large to fit in\n", - pieces.data_size); - goto try_again; - } - - if (pieces.init_size > cfg->max_inst_size) { - IWL_ERR(nic, "uCode init instr len %Zd too large to fit in\n", - pieces.init_size); - goto try_again; - } - - if (pieces.init_data_size > cfg->max_data_size) { - IWL_ERR(nic, "uCode init data len %Zd too large to fit in\n", - pieces.init_data_size); - goto try_again; - } - - /* Allocate ucode buffers for card's bus-master loading ... */ - - /* Runtime instructions and 2 copies of data: - * 1) unmodified from disk - * 2) backup cache for save/restore during power-downs */ - if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.code, - pieces.inst, pieces.inst_size)) - goto err_pci_alloc; - if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.data, - pieces.data, pieces.data_size)) - goto err_pci_alloc; - - /* Initialization instructions and data */ - if (pieces.init_size && pieces.init_data_size) { - if (iwl_alloc_fw_desc(nic, - &nic->fw.ucode_init.code, - pieces.init, pieces.init_size)) - goto err_pci_alloc; - if (iwl_alloc_fw_desc(nic, - &nic->fw.ucode_init.data, - pieces.init_data, pieces.init_data_size)) - goto err_pci_alloc; - } - - /* WoWLAN instructions and data */ - if (pieces.wowlan_inst_size && pieces.wowlan_data_size) { - if (iwl_alloc_fw_desc(nic, - &nic->fw.ucode_wowlan.code, - pieces.wowlan_inst, - pieces.wowlan_inst_size)) - goto err_pci_alloc; - if (iwl_alloc_fw_desc(nic, - &nic->fw.ucode_wowlan.data, - pieces.wowlan_data, - pieces.wowlan_data_size)) - goto err_pci_alloc; - } - - /* Now that we can no longer fail, copy information */ - - /* - * The (size - 16) / 12 formula is based on the information recorded - * for each event, which is of mode 1 (including timestamp) for all - * new microcodes that include this information. - */ - nic->init_evtlog_ptr = pieces.init_evtlog_ptr; - if (pieces.init_evtlog_size) - nic->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; - else - nic->init_evtlog_size = - cfg->base_params->max_event_log_size; - nic->init_errlog_ptr = pieces.init_errlog_ptr; - nic->inst_evtlog_ptr = pieces.inst_evtlog_ptr; - if (pieces.inst_evtlog_size) - nic->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; - else - nic->inst_evtlog_size = - cfg->base_params->max_event_log_size; - nic->inst_errlog_ptr = pieces.inst_errlog_ptr; - - /* - * figure out the offset of chain noise reset and gain commands - * base on the size of standard phy calibration commands table size - */ - if (fw->ucode_capa.standard_phy_calibration_size > - IWL_MAX_PHY_CALIBRATE_TBL_SIZE) - fw->ucode_capa.standard_phy_calibration_size = - IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE; - - /* We have our copies now, allow OS release its copies */ - release_firmware(ucode_raw); - complete(&nic->request_firmware_complete); - - nic->op_mode = iwl_dvm_ops.start(nic->shrd->trans); - - if (!nic->op_mode) - goto out_unbind; - - return; - - try_again: - /* try next, if any */ - release_firmware(ucode_raw); - if (iwl_request_firmware(nic, false)) - goto out_unbind; - return; - - err_pci_alloc: - IWL_ERR(nic, "failed to allocate pci memory\n"); - iwl_dealloc_ucode(nic); - release_firmware(ucode_raw); - out_unbind: - complete(&nic->request_firmware_complete); - device_release_driver(trans(nic)->dev); -} - diff --git a/drivers/net/wireless/iwlwifi/iwl-wifi.h b/drivers/net/wireless/iwlwifi/iwl-wifi.h index d5cba07a24c8..d157931e1e95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-wifi.h +++ b/drivers/net/wireless/iwlwifi/iwl-wifi.h @@ -66,8 +66,6 @@ #include "iwl-shared.h" #include "iwl-ucode.h" -#define UCODE_EXPERIMENTAL_INDEX 100 - /** * struct iwl_nic - nic common data * @fw: the iwl_fw structure @@ -99,9 +97,6 @@ struct iwl_nic { }; -int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first); -void iwl_dealloc_ucode(struct iwl_nic *nic); - int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type); void iwl_send_prio_tbl(struct iwl_trans *trans); int iwl_init_alive_start(struct iwl_trans *trans); -- cgit v1.2.3-70-g09d2 From 2e7eb117586198386e5a06d0bc4279a9d7cbaeb6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 5 Mar 2012 11:24:51 -0800 Subject: iwlwifi: move firmware completion wait This doesn't belong into the op_mode, it has to be in the drv stop flow instead. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 -- drivers/net/wireless/iwlwifi/iwl-drv.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c3b594647def..8bb3f173bfa0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1371,8 +1371,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) { struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); - wait_for_completion(&nic(priv)->request_firmware_complete); - IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); iwl_dbgfs_unregister(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 343f41eb4e4f..1a588f36b591 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -720,6 +720,8 @@ int iwl_drv_start(struct iwl_shared *shrd, void iwl_drv_stop(struct iwl_shared *shrd) { + wait_for_completion(&shrd->nic->request_firmware_complete); + /* op_mode can be NULL if its start failed */ if (shrd->nic->op_mode) iwl_op_mode_stop(shrd->nic->op_mode); -- cgit v1.2.3-70-g09d2 From 2f40b9404903dba89d70d706ee71263f9babd109 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Mon, 5 Mar 2012 17:20:37 -0800 Subject: mac80211_hwsim: Add tsf to beacons, probe responses and radiotap header. Generate a tsf from internal kernel clock. Prepare the path for having different tsf offsets on each phy. This will be useful for testing mesh synchronization algorithms. Signed-off-by: Javier Cardona Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index ba16f05df0fc..14a3cac19a30 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "mac80211_hwsim.h" @@ -321,11 +322,15 @@ struct mac80211_hwsim_data { struct dentry *debugfs_group; int power_level; + + /* difference between this hw's clock and the real clock, in usecs */ + u64 tsf_offset; }; struct hwsim_radiotap_hdr { struct ieee80211_radiotap_header hdr; + __le64 rt_tsft; u8 rt_flags; u8 rt_rate; __le16 rt_channel; @@ -367,6 +372,12 @@ static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } +static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) +{ + struct timeval tv = ktime_to_timeval(ktime_get_real()); + u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec; + return cpu_to_le64(now + data->tsf_offset); +} static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, struct sk_buff *tx_skb) @@ -391,7 +402,9 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_TSFT) | (1 << IEEE80211_RADIOTAP_CHANNEL)); + hdr->rt_tsft = __mac80211_hwsim_get_tsf(data); hdr->rt_flags = 0; hdr->rt_rate = txrate->bitrate / 5; hdr->rt_channel = cpu_to_le16(data->channel->center_freq); @@ -610,7 +623,8 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, } memset(&rx_status, 0, sizeof(rx_status)); - /* TODO: set mactime */ + rx_status.mactime = le64_to_cpu(__mac80211_hwsim_get_tsf(data)); + rx_status.flag |= RX_FLAG_MACTIME_MPDU; rx_status.freq = data->channel->center_freq; rx_status.band = data->channel->band; rx_status.rate_idx = info->control.rates[0].idx; @@ -667,6 +681,12 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) bool ack; struct ieee80211_tx_info *txi; u32 _pid; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; + struct mac80211_hwsim_data *data = hw->priv; + + if (ieee80211_is_beacon(mgmt->frame_control) || + ieee80211_is_probe_resp(mgmt->frame_control)) + mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data); mac80211_hwsim_monitor_rx(hw, skb); @@ -763,9 +783,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, struct ieee80211_vif *vif) { struct ieee80211_hw *hw = arg; + struct mac80211_hwsim_data *data = hw->priv; struct sk_buff *skb; struct ieee80211_tx_info *info; u32 _pid; + struct ieee80211_mgmt *mgmt; hwsim_check_magic(vif); @@ -779,6 +801,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, return; info = IEEE80211_SKB_CB(skb); + mgmt = (struct ieee80211_mgmt *) skb->data; + mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data); + mac80211_hwsim_monitor_rx(hw, skb); /* wmediumd mode check */ -- cgit v1.2.3-70-g09d2 From 12ce8ba3eb09bb83509a459835917a3100ad8db1 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Mon, 5 Mar 2012 17:20:38 -0800 Subject: mac80211: Modify tsf via debugfs in mesh interfaces Signed-off-by: Javier Cardona Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 18 ++++++++++++++++++ net/mac80211/debugfs_netdev.c | 7 ++++++- 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 14a3cac19a30..b4f6cb3298a4 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -379,6 +379,22 @@ static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data) return cpu_to_le64(now + data->tsf_offset); } +static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mac80211_hwsim_data *data = hw->priv; + return le64_to_cpu(__mac80211_hwsim_get_tsf(data)); +} + +static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u64 tsf) +{ + struct mac80211_hwsim_data *data = hw->priv; + struct timeval tv = ktime_to_timeval(ktime_get_real()); + u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec; + data->tsf_offset = tsf - now; +} + static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, struct sk_buff *tx_skb) { @@ -1224,6 +1240,8 @@ static struct ieee80211_ops mac80211_hwsim_ops = .sw_scan_start = mac80211_hwsim_sw_scan, .sw_scan_complete = mac80211_hwsim_sw_scan_complete, .flush = mac80211_hwsim_flush, + .get_tsf = mac80211_hwsim_get_tsf, + .set_tsf = mac80211_hwsim_set_tsf, }; diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9f484d8905fd..f6de8a65f402 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -538,11 +538,15 @@ static void add_monitor_files(struct ieee80211_sub_if_data *sdata) #ifdef CONFIG_MAC80211_MESH +static void add_mesh_files(struct ieee80211_sub_if_data *sdata) +{ + DEBUGFS_ADD_MODE(tsf, 0600); +} + static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) { struct dentry *dir = debugfs_create_dir("mesh_stats", sdata->debugfs.dir); - #define MESHSTATS_ADD(name)\ debugfs_create_file(#name, 0400, dir, sdata, &name##_ops); @@ -595,6 +599,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata) switch (sdata->vif.type) { case NL80211_IFTYPE_MESH_POINT: #ifdef CONFIG_MAC80211_MESH + add_mesh_files(sdata); add_mesh_stats(sdata); add_mesh_config(sdata); #endif -- cgit v1.2.3-70-g09d2 From 62e2c102cc1d2600381410c089ca9a37359577d2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 6 Mar 2012 11:06:37 +0100 Subject: ath5k: do not stop queues for full calibration Some calibration types interfere with tx activity, but the queue stop does not prevent that. In fact, some calibration types need tx activity to properly function, so stopping the queues for them is counterproductive. In some tests this patch has been shown to improve stability, especially in AP or ad-hoc mode. Signed-off-by: Felix Fietkau Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index b51d58c414d2..0e643b016b32 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2332,15 +2332,6 @@ ath5k_calibrate_work(struct work_struct *work) "got new rfgain, resetting\n"); ieee80211_queue_work(ah->hw, &ah->reset_work); } - - /* TODO: On full calibration we should stop TX here, - * so that it doesn't interfere (mostly due to gain_f - * calibration that messes with tx packets -see phy.c). - * - * NOTE: Stopping the queues from above is not enough - * to stop TX but saves us from disconecting (at least - * we don't lose packets). */ - ieee80211_stop_queues(ah->hw); } else ah->ah_cal_mask |= AR5K_CALIBRATION_SHORT; @@ -2355,10 +2346,9 @@ ath5k_calibrate_work(struct work_struct *work) ah->curchan->center_freq)); /* Clear calibration flags */ - if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) { - ieee80211_wake_queues(ah->hw); + if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; - } else if (ah->ah_cal_mask & AR5K_CALIBRATION_SHORT) + else if (ah->ah_cal_mask & AR5K_CALIBRATION_SHORT) ah->ah_cal_mask &= ~AR5K_CALIBRATION_SHORT; } -- cgit v1.2.3-70-g09d2 From 5c17ddc4a047c59638c7eb8537aa887a1ddb9b0b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 6 Mar 2012 11:06:38 +0100 Subject: ath5k: do not re-run AGC calibration periodically All other Atheros drivers run the AGC gain calibration and DC offset calibration only after reset. Running them periodically has caused stability issues on some (primarily AR2315/2413/5413/5414 based) devices, leading to messages such as: ath5k phy0: gain calibration timeout (2462MHz) ath5k phy0: calibration of channel 11 failed Related bug reports: https://dev.openwrt.org/ticket/10574 https://bugzilla.redhat.com/show_bug.cgi?id=795141 Signed-off-by: Felix Fietkau Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/phy.c | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index e1f8613426a9..3a2845489a1b 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1871,31 +1871,15 @@ ath5k_hw_phy_calibrate(struct ath5k_hw *ah, ret = 0; } - /* On full calibration do an AGC calibration and - * request a PAPD probe for gainf calibration if - * needed */ - if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) { - - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL); - - ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF, - 0, false); - if (ret) { - ATH5K_ERR(ah, - "gain calibration timeout (%uMHz)\n", - channel->center_freq); - } - - if ((ah->ah_radio == AR5K_RF5111 || - ah->ah_radio == AR5K_RF5112) - && (channel->hw_value != AR5K_MODE_11B)) - ath5k_hw_request_rfgain_probe(ah); - } - - /* Update noise floor - * XXX: Only do this after AGC calibration */ + /* On full calibration request a PAPD probe for + * gainf calibration if needed */ + if ((ah->ah_cal_mask & AR5K_CALIBRATION_FULL) && + (ah->ah_radio == AR5K_RF5111 || + ah->ah_radio == AR5K_RF5112) && + channel->hw_value != AR5K_MODE_11B) + ath5k_hw_request_rfgain_probe(ah); + + /* Update noise floor */ if (!(ah->ah_cal_mask & AR5K_CALIBRATION_NF)) ath5k_hw_update_noise_floor(ah); -- cgit v1.2.3-70-g09d2 From 4ac887cfdad909f16ee1886fe4fa19b452fc7fd3 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Tue, 6 Mar 2012 15:50:47 +0100 Subject: bcma: return error in bcma_sprom_get() when fallback fails When not SPROM is available a fallback mechanism is used. However, when that fails the code currently continues. This patch assures that the bcma_sprom_get() function aborts when that happens. Cc: Rafal Milecki Cc: Hauke Mehrtens Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/bcma/sprom.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 916ae255ff64..fba8066857d2 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -49,10 +49,23 @@ int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus, struct ssb_sprom *out) { - if (!get_fallback_sprom) - return -ENOENT; + int err; - return get_fallback_sprom(bus, out); + if (!get_fallback_sprom) { + err = -ENOENT; + goto fail; + } + + err = get_fallback_sprom(bus, out); + if (err) + goto fail; + + pr_debug("Using SPROM revision %d provided by" + " platform.\n", bus->sprom.revision); + return 0; +fail: + pr_warn("Using fallback SPROM failed (err %d)\n", err); + return err; } /************************************************** @@ -317,13 +330,7 @@ int bcma_sprom_get(struct bcma_bus *bus) * available for this device in some other storage. */ err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); - if (err) { - pr_warn("Using fallback SPROM failed (err %d)\n", err); - } else { - pr_debug("Using SPROM revision %d provided by" - " platform.\n", bus->sprom.revision); - return 0; - } + return err; } sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), -- cgit v1.2.3-70-g09d2 From 10d8493cd9efd38b1947b7a74276dbdc8311aa1a Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Tue, 6 Mar 2012 15:50:48 +0100 Subject: bcma: add support for on-chip OTP memory used for SPROM storage Wireless Broadcom chips can have either their SPROM data stored on either external SPROM or on-chip OTP memory. Both are accessed through the same register space. This patch adds support for the on-chip OTP memory. Tested with: BCM43224 OTP and SPROM BCM4331 SPROM BCM4313 OTP This patch is in response to linux-wireless thread [1]. [1] http://article.gmane.org/gmane.linux.kernel.wireless.general/85426 Tested-by: Saul St. John Tested-by: Rafal Milecki Tested-by: Hauke Mehrtens Cc: Larry Finger Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/bcma/sprom.c | 126 +++++++++++++++++++++++----- include/linux/bcma/bcma_driver_chipcommon.h | 10 ++- 2 files changed, 115 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index fba8066857d2..cdcf75c0954f 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -300,37 +300,128 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) SSB_SROM8_FEM_ANTSWLUT_SHIFT); } -static bool bcma_is_sprom_available(struct bcma_bus *bus) +/* + * Indicates the presence of external SPROM. + */ +static bool bcma_sprom_ext_available(struct bcma_bus *bus) { - u32 sromctrl; + u32 chip_status; + u32 srom_control; + u32 present_mask; - if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) - return false; + if (bus->drv_cc.core->id.rev >= 31) { + if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) + return false; - if (bus->drv_cc.core->id.rev >= 32) { - sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL); - return sromctrl & BCMA_CC_SROM_CONTROL_PRESENT; + srom_control = bcma_read32(bus->drv_cc.core, + BCMA_CC_SROM_CONTROL); + return srom_control & BCMA_CC_SROM_CONTROL_PRESENT; } - return true; + + /* older chipcommon revisions use chip status register */ + chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT); + switch (bus->chipinfo.id) { + case 0x4313: + present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT; + break; + + case 0x4331: + present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT; + break; + + default: + return true; + } + + return chip_status & present_mask; +} + +/* + * Indicates that on-chip OTP memory is present and enabled. + */ +static bool bcma_sprom_onchip_available(struct bcma_bus *bus) +{ + u32 chip_status; + u32 otpsize = 0; + bool present; + + chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT); + switch (bus->chipinfo.id) { + case 0x4313: + present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT; + break; + + case 0x4331: + present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT; + break; + + case 43224: + case 43225: + /* for these chips OTP is always available */ + present = true; + break; + + default: + present = false; + break; + } + + if (present) { + otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS; + otpsize >>= BCMA_CC_CAP_OTPS_SHIFT; + } + + return otpsize != 0; +} + +/* + * Verify OTP is filled and determine the byte + * offset where SPROM data is located. + * + * On error, returns 0; byte offset otherwise. + */ +static int bcma_sprom_onchip_offset(struct bcma_bus *bus) +{ + struct bcma_device *cc = bus->drv_cc.core; + u32 offset; + + /* verify OTP status */ + if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0) + return 0; + + /* obtain bit offset from otplayout register */ + offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET); + return BCMA_CC_SPROM + (offset >> 3); } int bcma_sprom_get(struct bcma_bus *bus) { - u16 offset; + u16 offset = BCMA_CC_SPROM; u16 *sprom; int err = 0; if (!bus->drv_cc.core) return -EOPNOTSUPP; - if (!bcma_is_sprom_available(bus)) { + if (!bcma_sprom_ext_available(bus)) { /* - * Maybe there is no SPROM on the device? - * Now we ask the arch code if there is some sprom - * available for this device in some other storage. + * External SPROM takes precedence so check + * on-chip OTP only when no external SPROM + * is present. */ - err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); - return err; + if (bcma_sprom_onchip_available(bus)) { + /* determine offset */ + offset = bcma_sprom_onchip_offset(bus); + } + if (!offset) { + /* + * Maybe there is no SPROM on the device? + * Now we ask the arch code if there is some sprom + * available for this device in some other storage. + */ + err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); + return err; + } } sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), @@ -341,11 +432,6 @@ int bcma_sprom_get(struct bcma_bus *bus) if (bus->chipinfo.id == 0x4331) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); - /* Most cards have SPROM moved by additional offset 0x30 (48 dwords). - * According to brcm80211 this applies to cards with PCIe rev >= 6 - * TODO: understand this condition and use it */ - offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM : - BCMA_CC_SPROM_PCIE6; pr_debug("SPROM offset 0x%x\n", offset); bcma_sprom_read(bus, offset, sprom); diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index e72938b10714..8bbfe31fbac8 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -56,6 +56,9 @@ #define BCMA_CC_OTPS_HW_PROTECT 0x00000001 #define BCMA_CC_OTPS_SW_PROTECT 0x00000002 #define BCMA_CC_OTPS_CID_PROTECT 0x00000004 +#define BCMA_CC_OTPS_GU_PROG_IND 0x00000F00 /* General Use programmed indication */ +#define BCMA_CC_OTPS_GU_PROG_IND_SHIFT 8 +#define BCMA_CC_OTPS_GU_PROG_HW 0x00000100 /* HW region programmed */ #define BCMA_CC_OTPC 0x0014 /* OTP control */ #define BCMA_CC_OTPC_RECWAIT 0xFF000000 #define BCMA_CC_OTPC_PROGWAIT 0x00FFFF00 @@ -72,6 +75,8 @@ #define BCMA_CC_OTPP_READ 0x40000000 #define BCMA_CC_OTPP_START 0x80000000 #define BCMA_CC_OTPP_BUSY 0x80000000 +#define BCMA_CC_OTPL 0x001C /* OTP layout */ +#define BCMA_CC_OTPL_GURGN_OFFSET 0x00000FFF /* offset of general use region */ #define BCMA_CC_IRQSTAT 0x0020 #define BCMA_CC_IRQMASK 0x0024 #define BCMA_CC_IRQ_GPIO 0x00000001 /* gpio intr */ @@ -79,6 +84,10 @@ #define BCMA_CC_IRQ_WDRESET 0x80000000 /* watchdog reset occurred */ #define BCMA_CC_CHIPCTL 0x0028 /* Rev >= 11 only */ #define BCMA_CC_CHIPSTAT 0x002C /* Rev >= 11 only */ +#define BCMA_CC_CHIPST_4313_SPROM_PRESENT 1 +#define BCMA_CC_CHIPST_4313_OTP_PRESENT 2 +#define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2 +#define BCMA_CC_CHIPST_4331_OTP_PRESENT 4 #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ #define BCMA_CC_JCMD_START 0x80000000 #define BCMA_CC_JCMD_BUSY 0x80000000 @@ -256,7 +265,6 @@ #define BCMA_CC_PLLCTL_ADDR 0x0660 #define BCMA_CC_PLLCTL_DATA 0x0664 #define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ -#define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */ /* Divider allocation in 4716/47162/5356 */ #define BCMA_CC_PMU5_MAINPLL_CPU 1 -- cgit v1.2.3-70-g09d2 From c3b1e1e8a76fdaa507daaa95ba7bd1d8d0c74b6b Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 5 Mar 2012 01:03:33 +0100 Subject: NFC: Export NFCID1 from pn533 Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/nfc/pn533.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 1a1500bc8452..8be0ae626d73 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -736,6 +736,8 @@ static int pn533_target_found_type_a(struct nfc_target *nfc_tgt, u8 *tgt_data, nfc_tgt->sens_res = be16_to_cpu(tgt_type_a->sens_res); nfc_tgt->sel_res = tgt_type_a->sel_res; + nfc_tgt->nfcid1_len = tgt_type_a->nfcid_len; + memcpy(nfc_tgt->nfcid1, tgt_type_a->nfcid_data, nfc_tgt->nfcid1_len); return 0; } -- cgit v1.2.3-70-g09d2 From 98b3ac1b980b0c0ffff24fda8d13ab8c216df4d1 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 5 Mar 2012 01:03:39 +0100 Subject: NFC: Clear pn533 target structure The polled target structure should be memset to 0 in order to avoid sel_res and sens_res garbage. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/nfc/pn533.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 8be0ae626d73..a5766042f0ee 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -904,6 +904,8 @@ static int pn533_target_found(struct pn533 *dev, if (resp->tg != 1) return -EPROTO; + memset(&nfc_tgt, 0, sizeof(struct nfc_target)); + target_data_len = resp_len - sizeof(struct pn533_poll_response); switch (dev->poll_mod_curr) { -- cgit v1.2.3-70-g09d2 From 7975754f61b8e87ad0b34509a94c54c8d19ea15d Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 5 Mar 2012 01:03:45 +0100 Subject: NFC: Export sensf from pn533 sensf is the detection response for Felica NFC tags. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/nfc/pn533.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index a5766042f0ee..353bab775d7d 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -783,6 +783,9 @@ static int pn533_target_found_felica(struct nfc_target *nfc_tgt, u8 *tgt_data, else nfc_tgt->supported_protocols = NFC_PROTO_FELICA_MASK; + memcpy(nfc_tgt->sensf_res, &tgt_felica->opcode, 9); + nfc_tgt->sensf_res_len = 9; + return 0; } -- cgit v1.2.3-70-g09d2 From d8dc107248d336695ca6a964c5ffdc2f4d160a04 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 5 Mar 2012 01:03:46 +0100 Subject: NFC: Export Jewel/Topaz ID from pn533 The jewel ID is the NFCID1 for Topaz NFC tags. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/nfc/pn533.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 353bab775d7d..f5da5ae67ec1 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -828,6 +828,8 @@ static int pn533_target_found_jewel(struct nfc_target *nfc_tgt, u8 *tgt_data, nfc_tgt->supported_protocols = NFC_PROTO_JEWEL_MASK; nfc_tgt->sens_res = be16_to_cpu(tgt_jewel->sens_res); + nfc_tgt->nfcid1_len = 4; + memcpy(nfc_tgt->nfcid1, tgt_jewel->jewelid, nfc_tgt->nfcid1_len); return 0; } -- cgit v1.2.3-70-g09d2 From 2fbabfa467ce945deb92bf04c745b4d101fc21ee Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 5 Mar 2012 01:03:47 +0100 Subject: NFC: Export NFCID when detecting a p2p target with pn533 Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/nfc/pn533.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index f5da5ae67ec1..ef33f64143b5 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1316,6 +1316,8 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, nfc_dev_dbg(&dev->interface->dev, "Creating new target"); nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; + nfc_target.nfcid1_len = 10; + memcpy(nfc_target.nfcid1, resp->nfcid3t, nfc_target.nfcid1_len); rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1); if (rc) return 0; -- cgit v1.2.3-70-g09d2 From 47807d3dbb62e93850cbcb797db1a9ee1806f986 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 5 Mar 2012 01:03:50 +0100 Subject: NFC: Remove the rf mode parameter from the DEP link up routine When calling nfc_dep_link_up, we implicitely are in initiator mode. Which means we also can provide the general bytes as a function argument, as all drivers will eventually request them. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/nfc/pn533.c | 20 +++++--------------- include/net/nfc/nfc.h | 6 ++---- net/nfc/core.c | 22 +++++++++++----------- net/nfc/llcp/llcp.c | 2 +- net/nfc/netlink.c | 11 +++-------- net/nfc/nfc.h | 5 ++--- 6 files changed, 24 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index ef33f64143b5..cb6204f78300 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1340,21 +1340,15 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, } static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx, - u8 comm_mode, u8 rf_mode) + u8 comm_mode, u8* gb, size_t gb_len) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); struct pn533_cmd_jump_dep *cmd; - u8 cmd_len, local_gt_len, *local_gt; + u8 cmd_len; int rc; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - if (rf_mode == NFC_RF_TARGET) { - nfc_dev_err(&dev->interface->dev, "Target mode not supported"); - return -EOPNOTSUPP; - } - - if (dev->poll_mod_count) { nfc_dev_err(&dev->interface->dev, "Cannot bring the DEP link up while polling"); @@ -1367,11 +1361,7 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx, return -EBUSY; } - local_gt = nfc_get_local_general_bytes(dev->nfc_dev, &local_gt_len); - if (local_gt_len > NFC_MAX_GT_LEN) - return -EINVAL; - - cmd_len = sizeof(struct pn533_cmd_jump_dep) + local_gt_len; + cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len; cmd = kzalloc(cmd_len, GFP_KERNEL); if (cmd == NULL) return -ENOMEM; @@ -1380,9 +1370,9 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx, cmd->active = !comm_mode; cmd->baud = 0; - if (local_gt != NULL) { + if (gb != NULL && gb_len > 0) { cmd->next = 4; /* We have some Gi */ - memcpy(cmd->gt, local_gt, local_gt_len); + memcpy(cmd->gt, gb, gb_len); } else { cmd->next = 0; } diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index d253278e5a96..d608e4eac66f 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -53,8 +53,8 @@ struct nfc_ops { int (*dev_down)(struct nfc_dev *dev); int (*start_poll)(struct nfc_dev *dev, u32 protocols); void (*stop_poll)(struct nfc_dev *dev); - int (*dep_link_up)(struct nfc_dev *dev, int target_idx, - u8 comm_mode, u8 rf_mode); + int (*dep_link_up)(struct nfc_dev *dev, int target_idx, u8 comm_mode, + u8 *gb, size_t gb_len); int (*dep_link_down)(struct nfc_dev *dev); int (*activate_target)(struct nfc_dev *dev, u32 target_idx, u32 protocol); @@ -179,8 +179,6 @@ struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp); int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gt, u8 gt_len); -u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len); - int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, int ntargets); diff --git a/net/nfc/core.c b/net/nfc/core.c index 6089aca67b14..f4f526f73217 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -181,13 +181,13 @@ error: return rc; } -int nfc_dep_link_up(struct nfc_dev *dev, int target_index, - u8 comm_mode, u8 rf_mode) +int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode) { int rc = 0; + u8 *gb; + size_t gb_len; - pr_debug("dev_name=%s comm:%d rf:%d\n", - dev_name(&dev->dev), comm_mode, rf_mode); + pr_debug("dev_name=%s comm %d\n", dev_name(&dev->dev), comm_mode); if (!dev->ops->dep_link_up) return -EOPNOTSUPP; @@ -204,7 +204,13 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, goto error; } - rc = dev->ops->dep_link_up(dev, target_index, comm_mode, rf_mode); + gb = nfc_llcp_general_bytes(dev, &gb_len); + if (gb_len > NFC_MAX_GT_LEN) { + rc = -EINVAL; + goto error; + } + + rc = dev->ops->dep_link_up(dev, target_index, comm_mode, gb, gb_len); error: device_unlock(&dev->dev); @@ -367,12 +373,6 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) } EXPORT_SYMBOL(nfc_set_remote_general_bytes); -u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len) -{ - return nfc_llcp_general_bytes(dev, gt_len); -} -EXPORT_SYMBOL(nfc_get_local_general_bytes); - /** * nfc_alloc_send_skb - allocate a skb for data exchange responses * diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index a0cb133c610a..3ce646e35f6b 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -281,7 +281,7 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap) mutex_unlock(&local->sdp_lock); } -u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len) +u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) { struct nfc_llcp_local *local; diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index a1388e4efd6f..fa620d03799e 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -542,13 +542,12 @@ static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info) struct nfc_dev *dev; int rc, tgt_idx; u32 idx; - u8 comm, rf; + u8 comm; pr_debug("DEP link up\n"); if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || - !info->attrs[NFC_ATTR_COMM_MODE] || - !info->attrs[NFC_ATTR_RF_MODE]) + !info->attrs[NFC_ATTR_COMM_MODE]) return -EINVAL; idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); @@ -558,19 +557,15 @@ static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info) tgt_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]); comm = nla_get_u8(info->attrs[NFC_ATTR_COMM_MODE]); - rf = nla_get_u8(info->attrs[NFC_ATTR_RF_MODE]); if (comm != NFC_COMM_ACTIVE && comm != NFC_COMM_PASSIVE) return -EINVAL; - if (rf != NFC_RF_INITIATOR && comm != NFC_RF_TARGET) - return -EINVAL; - dev = nfc_get_device(idx); if (!dev) return -ENODEV; - rc = nfc_dep_link_up(dev, tgt_idx, comm, rf); + rc = nfc_dep_link_up(dev, tgt_idx, comm); nfc_put_device(dev); diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index 6d28d75995b0..2fd83b16df68 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h @@ -54,7 +54,7 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, int nfc_llcp_register_device(struct nfc_dev *dev); void nfc_llcp_unregister_device(struct nfc_dev *dev); int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); -u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len); +u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); int __init nfc_llcp_init(void); void nfc_llcp_exit(void); @@ -160,8 +160,7 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols); int nfc_stop_poll(struct nfc_dev *dev); -int nfc_dep_link_up(struct nfc_dev *dev, int target_idx, - u8 comm_mode, u8 rf_mode); +int nfc_dep_link_up(struct nfc_dev *dev, int target_idx, u8 comm_mode); int nfc_dep_link_down(struct nfc_dev *dev); -- cgit v1.2.3-70-g09d2 From 9c083af8683808e486c20ca1f36da520d82e5981 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 3 Mar 2012 15:17:02 +0100 Subject: ath9k_hw: use cold instead of warm reset on AR9280 Cold reset is more reliable for getting the hardware out of some specific stuck states. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8c840cad3ac2..d582cf73098f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1386,10 +1386,16 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) static bool ath9k_hw_chip_reset(struct ath_hw *ah, struct ath9k_channel *chan) { - if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) { - if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) - return false; - } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) + int reset_type = ATH9K_RESET_WARM; + + if (AR_SREV_9280(ah)) { + if (ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) + reset_type = ATH9K_RESET_POWER_ON; + else + reset_type = ATH9K_RESET_COLD; + } + + if (!ath9k_hw_set_reset_reg(ah, reset_type)) return false; if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) -- cgit v1.2.3-70-g09d2 From 5baec7422c8c8f70c62b9493acf31d4854b09070 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 3 Mar 2012 15:17:03 +0100 Subject: ath9k: make MAC sample statistics optional They're more expensive than some of the other debug options and only used in very rare situations, so it sometimes makes sense to disable them while leaving in debugfs support. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Kconfig | 8 ++++++++ drivers/net/wireless/ath/ath9k/debug.c | 10 ++++++++++ drivers/net/wireless/ath/ath9k/debug.h | 20 +++++++++++++++----- drivers/net/wireless/ath/ath9k/init.c | 4 +++- 4 files changed, 36 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 595a272aa96e..e507e78398f3 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -81,6 +81,14 @@ config ATH9K_DFS_CERTIFIED developed. At this point enabling this option won't do anything except increase code size. +config ATH9K_MAC_DEBUG + bool "Atheros MAC statistics" + depends on ATH9K_DEBUGFS + default y + ---help--- + This option enables collection of statistics for Rx/Tx status + data and some other MAC related statistics + config ATH9K_RATE_CONTROL bool "Atheros ath9k rate control" depends on ATH9K diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 228c18189a3a..03a474092e8b 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -818,6 +818,7 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) TX_STAT_INC(qnum, delim_underrun); +#ifdef CONFIG_ATH9K_MAC_DEBUG spin_lock(&sc->debug.samp_lock); TX_SAMP_DBG(jiffies) = jiffies; TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0; @@ -844,6 +845,7 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES; spin_unlock(&sc->debug.samp_lock); +#endif #undef TX_SAMP_DBG } @@ -1019,6 +1021,7 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna; +#ifdef CONFIG_ATH9K_MAC_DEBUG spin_lock(&sc->debug.samp_lock); RX_SAMP_DBG(jiffies) = jiffies; RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0; @@ -1035,6 +1038,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES; spin_unlock(&sc->debug.samp_lock); +#endif + #undef RX_STAT_INC #undef RX_PHY_ERR_INC #undef RX_SAMP_DBG @@ -1278,6 +1283,8 @@ static const struct file_operations fops_modal_eeprom = { .llseek = default_llseek, }; +#ifdef CONFIG_ATH9K_MAC_DEBUG + void ath9k_debug_samp_bb_mac(struct ath_softc *sc) { #define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c) @@ -1551,6 +1558,7 @@ static const struct file_operations fops_samps = { .llseek = default_llseek, }; +#endif int ath9k_init_debug(struct ath_hw *ah) { @@ -1604,8 +1612,10 @@ int ath9k_init_debug(struct ath_hw *ah) &fops_base_eeprom); debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_modal_eeprom); +#ifdef CONFIG_ATH9K_MAC_DEBUG debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_samps); +#endif debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 776a24ada600..7a519582232a 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -235,16 +235,17 @@ struct ath9k_debug { struct dentry *debugfs_phy; u32 regidx; struct ath_stats stats; +#ifdef CONFIG_ATH9K_MAC_DEBUG spinlock_t samp_lock; struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES]; u8 sampidx; u8 tsidx; u8 rsidx; +#endif }; int ath9k_init_debug(struct ath_hw *ah); -void ath9k_debug_samp_bb_mac(struct ath_softc *sc); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts, struct ath_txq *txq, @@ -258,10 +259,6 @@ static inline int ath9k_init_debug(struct ath_hw *ah) return 0; } -static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc) -{ -} - static inline void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) { @@ -282,4 +279,17 @@ static inline void ath_debug_stat_rx(struct ath_softc *sc, #endif /* CONFIG_ATH9K_DEBUGFS */ +#ifdef CONFIG_ATH9K_MAC_DEBUG + +void ath9k_debug_samp_bb_mac(struct ath_softc *sc); + +#else + +static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc) +{ +} + +#endif + + #endif /* DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index d8b05961f7e3..944e9b518f19 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -555,8 +555,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, mutex_init(&sc->mutex); #ifdef CONFIG_ATH9K_DEBUGFS spin_lock_init(&sc->nodes_lock); - spin_lock_init(&sc->debug.samp_lock); INIT_LIST_HEAD(&sc->nodes); +#endif +#ifdef CONFIG_ATH9K_MAC_DEBUG + spin_lock_init(&sc->debug.samp_lock); #endif tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, -- cgit v1.2.3-70-g09d2 From fc16fd8808968063929bbb198eb8bb46d40e36ce Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 3 Mar 2012 15:17:04 +0100 Subject: ath9k: remove rssi/antenna information from recv debug stats The way this is implemented (simply storing the last value) is absolutely worthless for debugging anything, and the same information is also available through the MAC sample feature, so there's no point in keeping this around. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 31 ------------------------------- drivers/net/wireless/ath/ath9k/debug.h | 7 ------- 2 files changed, 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 03a474092e8b..c2edf688da49 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -943,27 +943,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); - len += snprintf(buf + len, size - len, - "%22s : %10d\n", "RSSI-CTL0", - sc->debug.stats.rxstats.rs_rssi_ctl0); - len += snprintf(buf + len, size - len, - "%22s : %10d\n", "RSSI-CTL1", - sc->debug.stats.rxstats.rs_rssi_ctl1); - len += snprintf(buf + len, size - len, - "%22s : %10d\n", "RSSI-CTL2", - sc->debug.stats.rxstats.rs_rssi_ctl2); - len += snprintf(buf + len, size - len, - "%22s : %10d\n", "RSSI-EXT0", - sc->debug.stats.rxstats.rs_rssi_ext0); - len += snprintf(buf + len, size - len, - "%22s : %10d\n", "RSSI-EXT1", - sc->debug.stats.rxstats.rs_rssi_ext1); - len += snprintf(buf + len, size - len, - "%22s : %10d\n", "RSSI-EXT2", - sc->debug.stats.rxstats.rs_rssi_ext2); - len += snprintf(buf + len, size - len, - "%22s : %10d\n", "Rx Antenna", - sc->debug.stats.rxstats.rs_antenna); len += snprintf(buf + len, size - len, "%22s : %10u\n", "RX-Pkts-All", sc->debug.stats.rxstats.rx_pkts_all); @@ -1011,16 +990,6 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) RX_PHY_ERR_INC(rs->rs_phyerr); } - sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0; - sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1; - sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2; - - sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0; - sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1; - sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2; - - sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna; - #ifdef CONFIG_ATH9K_MAC_DEBUG spin_lock(&sc->debug.samp_lock); RX_SAMP_DBG(jiffies) = jiffies; diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 7a519582232a..64fcfad467bf 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -165,13 +165,6 @@ struct ath_rx_stats { u32 post_delim_crc_err; u32 decrypt_busy_err; u32 phy_err_stats[ATH9K_PHYERR_MAX]; - int8_t rs_rssi_ctl0; - int8_t rs_rssi_ctl1; - int8_t rs_rssi_ctl2; - int8_t rs_rssi_ext0; - int8_t rs_rssi_ext1; - int8_t rs_rssi_ext2; - u8 rs_antenna; }; enum ath_reset_type { -- cgit v1.2.3-70-g09d2 From 3a2923e83c6036f55ad4a39c8ee9a7d4accd9539 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 3 Mar 2012 15:17:05 +0100 Subject: ath9k: get rid of double queueing of rx frames on EDMA Process rx status directly instead of separating the completion test from the actual rx status processing. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 18 ++++-------- drivers/net/wireless/ath/ath9k/ath9k.h | 1 - drivers/net/wireless/ath/ath9k/recv.c | 45 ++++++++++++++--------------- 3 files changed, 28 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 01d5c1a4d746..a66a13b76848 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -436,20 +436,14 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr; unsigned int phyerr; - /* TODO: byte swap on big endian for ar9300_10 */ - - if (!rxs) { - if ((rxsp->status11 & AR_RxDone) == 0) - return -EINPROGRESS; - - if (MS(rxsp->ds_info, AR_DescId) != 0x168c) - return -EINVAL; + if ((rxsp->status11 & AR_RxDone) == 0) + return -EINPROGRESS; - if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) - return -EINPROGRESS; + if (MS(rxsp->ds_info, AR_DescId) != 0x168c) + return -EINVAL; - return 0; - } + if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) + return -EINPROGRESS; rxs->rs_status = 0; rxs->rs_flags = 0; diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index c2ccba676eca..3d8e51cd5d8f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -299,7 +299,6 @@ struct ath_tx { struct ath_rx_edma { struct sk_buff_head rx_fifo; - struct sk_buff_head rx_buffers; u32 rx_fifo_hwsize; }; diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 4633f513a80b..c95b77cdf3bb 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -227,7 +227,6 @@ static void ath_rx_edma_cleanup(struct ath_softc *sc) static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size) { skb_queue_head_init(&rx_edma->rx_fifo); - skb_queue_head_init(&rx_edma->rx_buffers); rx_edma->rx_fifo_hwsize = size; } @@ -653,7 +652,9 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon) } static bool ath_edma_get_buffers(struct ath_softc *sc, - enum ath9k_rx_qtype qtype) + enum ath9k_rx_qtype qtype, + struct ath_rx_status *rs, + struct ath_buf **dest) { struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; struct ath_hw *ah = sc->sc_ah; @@ -672,7 +673,7 @@ static bool ath_edma_get_buffers(struct ath_softc *sc, dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr, common->rx_bufsize, DMA_FROM_DEVICE); - ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data); + ret = ath9k_hw_process_rxdesc_edma(ah, rs, skb->data); if (ret == -EINPROGRESS) { /*let device gain the buffer again*/ dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, @@ -685,20 +686,21 @@ static bool ath_edma_get_buffers(struct ath_softc *sc, /* corrupt descriptor, skip this one and the following one */ list_add_tail(&bf->list, &sc->rx.rxbuf); ath_rx_edma_buf_link(sc, qtype); - skb = skb_peek(&rx_edma->rx_fifo); - if (!skb) - return true; - bf = SKB_CB_ATHBUF(skb); - BUG_ON(!bf); + skb = skb_peek(&rx_edma->rx_fifo); + if (skb) { + bf = SKB_CB_ATHBUF(skb); + BUG_ON(!bf); - __skb_unlink(skb, &rx_edma->rx_fifo); - list_add_tail(&bf->list, &sc->rx.rxbuf); - ath_rx_edma_buf_link(sc, qtype); - return true; + __skb_unlink(skb, &rx_edma->rx_fifo); + list_add_tail(&bf->list, &sc->rx.rxbuf); + ath_rx_edma_buf_link(sc, qtype); + } else { + bf = NULL; + } } - skb_queue_tail(&rx_edma->rx_buffers, skb); + *dest = bf; return true; } @@ -706,18 +708,15 @@ static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc, struct ath_rx_status *rs, enum ath9k_rx_qtype qtype) { - struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; - struct sk_buff *skb; - struct ath_buf *bf; + struct ath_buf *bf = NULL; - while (ath_edma_get_buffers(sc, qtype)); - skb = __skb_dequeue(&rx_edma->rx_buffers); - if (!skb) - return NULL; + while (ath_edma_get_buffers(sc, qtype, rs, &bf)) { + if (!bf) + continue; - bf = SKB_CB_ATHBUF(skb); - ath9k_hw_process_rxdesc_edma(sc->sc_ah, rs, skb->data); - return bf; + return bf; + } + return NULL; } static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, -- cgit v1.2.3-70-g09d2 From 2ef167557c0a26c88162ecffb017bfcc51eb7b29 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 3 Mar 2012 15:17:06 +0100 Subject: ath9k: fix signal strength reporting issues On A-MPDU frames, the hardware only reports valid signal strength data for the last subframe. The driver also mangled rx_stats->rs_rssi using the ATH_EP_RND macro in a way that may make sense for ANI, but definitely not for reporting to mac80211. This patch changes the code to calculate the signal strength from the rssi directly instead of taking the average value, and flag everything but the last subframe in an A-MPDU to tell mac80211 to ignore the signal strength entirely, fixing signal strength fluctuation issues reported by various users. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index c95b77cdf3bb..1b1b279c304a 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -948,6 +948,7 @@ static void ath9k_process_rssi(struct ath_common *common, struct ath_softc *sc = hw->priv; struct ath_hw *ah = common->ah; int last_rssi; + int rssi = rx_stats->rs_rssi; if (!rx_stats->is_mybeacon || ((ah->opmode != NL80211_IFTYPE_STATION) && @@ -959,13 +960,12 @@ static void ath9k_process_rssi(struct ath_common *common, last_rssi = sc->last_rssi; if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) - rx_stats->rs_rssi = ATH_EP_RND(last_rssi, - ATH_RSSI_EP_MULTIPLIER); - if (rx_stats->rs_rssi < 0) - rx_stats->rs_rssi = 0; + rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); + if (rssi < 0) + rssi = 0; /* Update Beacon RSSI, this is used by ANI. */ - ah->stats.avgbrssi = rx_stats->rs_rssi; + ah->stats.avgbrssi = rssi; } /* @@ -1005,6 +1005,8 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common, rx_status->signal = ah->noise + rx_stats->rs_rssi; rx_status->antenna = rx_stats->rs_antenna; rx_status->flag |= RX_FLAG_MACTIME_MPDU; + if (rx_stats->rs_moreaggr) + rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; return 0; } -- cgit v1.2.3-70-g09d2 From e19918855dc4822a24787a6d0048205b011e5ecb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:36 -0800 Subject: iwlwifi: move ucode loading to op_mode uCode loading belongs to the op_mode, as it is dependent on various things there and the commands sent during it are specific to it. Move the prototypes to iwl-agn.h to indicate this. To make this possible, also move all the calibration handling (which is op_mode dependent after all). Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 26 ++-- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 9 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 10 ++ drivers/net/wireless/iwlwifi/iwl-dev.h | 2 + drivers/net/wireless/iwlwifi/iwl-mac80211.c | 4 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 14 +- drivers/net/wireless/iwlwifi/iwl-testmode.c | 8 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 1 - drivers/net/wireless/iwlwifi/iwl-trans.h | 19 --- drivers/net/wireless/iwlwifi/iwl-ucode.c | 205 +++++++++++++------------- drivers/net/wireless/iwlwifi/iwl-wifi.h | 8 - 13 files changed, 150 insertions(+), 160 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 84fc5ce91b35..29f94597b55f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -75,6 +75,14 @@ * INIT calibrations framework *****************************************************************************/ +/* Opaque calibration results */ +struct iwl_calib_result { + struct list_head list; + size_t cmd_len; + struct iwl_calib_hdr hdr; + /* data follows */ +}; + struct statistics_general_data { u32 beacon_silence_rssi_a; u32 beacon_silence_rssi_b; @@ -84,7 +92,7 @@ struct statistics_general_data { u32 beacon_energy_c; }; -int iwl_send_calib_results(struct iwl_trans *trans) +int iwl_send_calib_results(struct iwl_priv *priv) { struct iwl_host_cmd hcmd = { .id = REPLY_PHY_CALIBRATION_CMD, @@ -92,15 +100,15 @@ int iwl_send_calib_results(struct iwl_trans *trans) }; struct iwl_calib_result *res; - list_for_each_entry(res, &trans->calib_results, list) { + list_for_each_entry(res, &priv->calib_results, list) { int ret; hcmd.len[0] = res->cmd_len; hcmd.data[0] = &res->hdr; hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; - ret = iwl_trans_send_cmd(trans, &hcmd); + ret = iwl_trans_send_cmd(trans(priv), &hcmd); if (ret) { - IWL_ERR(trans, "Error %d on calib cmd %d\n", + IWL_ERR(priv, "Error %d on calib cmd %d\n", ret, res->hdr.op_code); return ret; } @@ -109,7 +117,7 @@ int iwl_send_calib_results(struct iwl_trans *trans) return 0; } -int iwl_calib_set(struct iwl_trans *trans, +int iwl_calib_set(struct iwl_priv *priv, const struct iwl_calib_hdr *cmd, int len) { struct iwl_calib_result *res, *tmp; @@ -121,7 +129,7 @@ int iwl_calib_set(struct iwl_trans *trans, memcpy(&res->hdr, cmd, len); res->cmd_len = len; - list_for_each_entry(tmp, &trans->calib_results, list) { + list_for_each_entry(tmp, &priv->calib_results, list) { if (tmp->hdr.op_code == res->hdr.op_code) { list_replace(&tmp->list, &res->list); kfree(tmp); @@ -130,16 +138,16 @@ int iwl_calib_set(struct iwl_trans *trans, } /* wasn't in list already */ - list_add_tail(&res->list, &trans->calib_results); + list_add_tail(&res->list, &priv->calib_results); return 0; } -void iwl_calib_free_results(struct iwl_trans *trans) +void iwl_calib_free_results(struct iwl_priv *priv) { struct iwl_calib_result *res, *tmp; - list_for_each_entry_safe(res, tmp, &trans->calib_results, list) { + list_for_each_entry_safe(res, tmp, &priv->calib_results, list) { list_del(&res->list); kfree(res); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index e96af5133e06..45b060a45d9d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1195,7 +1195,7 @@ int iwlagn_suspend(struct iwl_priv *priv, priv->wowlan = true; - ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_WOWLAN); + ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN); if (ret) goto out; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 8e025e0df50d..d16e73d1b5c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -1177,7 +1177,7 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, pkt->hdr.cmd); w->triggered = true; if (w->fn) - w->fn(trans(priv), pkt, w->fn_data); + w->fn(priv, pkt, w->fn_data); } spin_unlock(&priv->shrd->notif_wait_lock); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8bb3f173bfa0..f53308fb428e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -671,14 +671,14 @@ int iwl_alive_start(struct iwl_priv *priv) priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; priv->cur_rssi_ctx = NULL; - iwl_send_prio_tbl(trans(priv)); + iwl_send_prio_tbl(priv); /* FIXME: w/a to force change uCode BT state machine */ - ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN, + ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); if (ret) return ret; - ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_CLOSE, + ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); if (ret) return ret; @@ -1040,7 +1040,7 @@ static int iwl_init_drv(struct iwl_priv *priv) mutex_init(&priv->shrd->mutex); - INIT_LIST_HEAD(&trans(priv)->calib_results); + INIT_LIST_HEAD(&priv->calib_results); priv->ieee_channels = NULL; priv->ieee_rates = NULL; @@ -1105,6 +1105,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv) kfree(priv->scan_cmd); kfree(priv->beacon_cmd); kfree(rcu_dereference_raw(priv->noa_data)); + iwl_calib_free_results(priv); #ifdef CONFIG_IWLWIFI_DEBUGFS kfree(priv->wowlan_sram); #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 70100f9a2e5c..2a90d779eecf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -113,6 +113,16 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); +int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); +void iwl_send_prio_tbl(struct iwl_priv *priv); +int iwl_init_alive_start(struct iwl_priv *priv); +int iwl_run_init_ucode(struct iwl_priv *priv); +int iwl_load_ucode_wait_alive(struct iwl_priv *priv, + enum iwl_ucode_type ucode_type); +int iwl_send_calib_results(struct iwl_priv *priv); +int iwl_calib_set(struct iwl_priv *priv, + const struct iwl_calib_hdr *cmd, int len); +void iwl_calib_free_results(struct iwl_priv *priv); /* lib */ int iwlagn_send_tx_power(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 5957209b2f37..7199748faaab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -724,6 +724,8 @@ struct iwl_priv { struct ieee80211_rate *ieee_rates; struct kmem_cache *tx_cmd_pool; + struct list_head calib_results; + struct workqueue_struct *workqueue; enum ieee80211_band band; diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 7f937151a8af..37330addce79 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -278,13 +278,13 @@ static int __iwl_up(struct iwl_priv *priv) } } - ret = iwl_run_init_ucode(trans(priv)); + ret = iwl_run_init_ucode(priv); if (ret) { IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret); goto error; } - ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_REGULAR); + ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR); if (ret) { IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret); goto error; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index ef80e0386c30..dc5544653bc0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -233,7 +233,7 @@ enum iwl_ucode_type { struct iwl_notification_wait { struct list_head list; - void (*fn)(struct iwl_trans *trans, struct iwl_rx_packet *pkt, + void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, void *data); void *fn_data; @@ -472,12 +472,12 @@ bool iwl_check_for_ct_kill(struct iwl_priv *priv); 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_trans *trans, - struct iwl_rx_packet *pkt, - void *data), - void *fn_data); + 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, diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index b24b166a9482..ec803ea08675 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -422,7 +422,7 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) iwl_init_notification_wait(priv->shrd, &calib_wait, CALIBRATION_COMPLETE_NOTIFICATION, NULL, NULL); - ret = iwl_init_alive_start(trans(priv)); + ret = iwl_init_alive_start(priv); if (ret) { IWL_ERR(priv, "Fail init calibration: %d\n", ret); goto cfg_init_calib_error; @@ -484,7 +484,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) break; case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: - status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT); + status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT); if (status) IWL_ERR(priv, "Error loading init ucode: %d\n", status); break; @@ -495,7 +495,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) break; case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: - status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_REGULAR); + status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR); if (status) { IWL_ERR(priv, "Error loading runtime ucode: %d\n", status); @@ -510,7 +510,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: iwl_scan_cancel_timeout(priv, 200); iwl_trans_stop_device(trans); - status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_WOWLAN); + status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN); if (status) { IWL_ERR(priv, "Error loading WOWLAN ucode: %d\n", status); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 3ae2fd720ed8..f49aa181f4af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1632,7 +1632,6 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - iwl_calib_free_results(trans); iwl_trans_pcie_tx_free(trans); #ifndef CONFIG_IWLWIFI_IDI iwl_trans_pcie_rx_free(trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index b09192a028de..6fa0c860a5e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -315,14 +315,6 @@ struct iwl_trans_ops { u32 (*read32)(struct iwl_trans *trans, u32 ofs); }; -/* Opaque calibration results */ -struct iwl_calib_result { - struct list_head list; - size_t cmd_len; - struct iwl_calib_hdr hdr; - /* data follows */ -}; - /** * enum iwl_trans_state - state of the transport layer * @@ -349,7 +341,6 @@ enum iwl_trans_state { * @ucode_write_complete: indicates that the ucode has been copied. * @nvm_device_type: indicates OTP or eeprom * @pm_support: set to true in start_hw if link pm is supported - * @calib_results: list head for init calibration results */ struct iwl_trans { const struct iwl_trans_ops *ops; @@ -369,8 +360,6 @@ struct iwl_trans { int nvm_device_type; bool pm_support; - struct list_head calib_results; - /* pointer to trans specific struct */ /*Ensure that this pointer will always be aligned to sizeof pointer */ char trans_specific[0] __aligned(sizeof(void *)); @@ -573,14 +562,6 @@ static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs) return trans->ops->read32(trans, ofs); } -/***************************************************** -* Utils functions -******************************************************/ -int iwl_send_calib_results(struct iwl_trans *trans); -int iwl_calib_set(struct iwl_trans *trans, - const struct iwl_calib_hdr *cmd, int len); -void iwl_calib_free_results(struct iwl_trans *trans); - /***************************************************** * Transport layers implementations + their allocation function ******************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 64a9c5ce5f89..340575a01ead 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -80,16 +80,16 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { * ******************************************************************************/ -static inline struct fw_img *iwl_get_ucode_image(struct iwl_nic *nic, - enum iwl_ucode_type ucode_type) +static inline struct fw_img *iwl_get_ucode_image(struct iwl_priv *priv, + enum iwl_ucode_type ucode_type) { switch (ucode_type) { case IWL_UCODE_INIT: - return &nic->fw.ucode_init; + return &nic(priv)->fw.ucode_init; case IWL_UCODE_WOWLAN: - return &nic->fw.ucode_wowlan; + return &nic(priv)->fw.ucode_wowlan; case IWL_UCODE_REGULAR: - return &nic->fw.ucode_rt; + return &nic(priv)->fw.ucode_rt; case IWL_UCODE_NONE: break; } @@ -99,23 +99,23 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_nic *nic, /* * Calibration */ -static int iwl_set_Xtal_calib(struct iwl_trans *trans) +static int iwl_set_Xtal_calib(struct iwl_priv *priv) { struct iwl_calib_xtal_freq_cmd cmd; __le16 *xtal_calib = - (__le16 *)iwl_eeprom_query_addr(trans->shrd, EEPROM_XTAL); + (__le16 *)iwl_eeprom_query_addr(priv->shrd, 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(trans, (void *)&cmd, sizeof(cmd)); + return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); } -static int iwl_set_temperature_offset_calib(struct iwl_trans *trans) +static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) { struct iwl_calib_temperature_offset_cmd cmd; __le16 *offset_calib = - (__le16 *)iwl_eeprom_query_addr(trans->shrd, + (__le16 *)iwl_eeprom_query_addr(priv->shrd, EEPROM_RAW_TEMPERATURE); memset(&cmd, 0, sizeof(cmd)); @@ -124,48 +124,48 @@ static int iwl_set_temperature_offset_calib(struct iwl_trans *trans) if (!(cmd.radio_sensor_offset)) cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; - IWL_DEBUG_CALIB(trans, "Radio sensor offset: %d\n", + IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", le16_to_cpu(cmd.radio_sensor_offset)); - return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd)); + return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); } -static int iwl_set_temperature_offset_calib_v2(struct iwl_trans *trans) +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(trans->shrd, + __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv->shrd, EEPROM_KELVIN_TEMPERATURE); __le16 *offset_calib_low = - (__le16 *)iwl_eeprom_query_addr(trans->shrd, + (__le16 *)iwl_eeprom_query_addr(priv->shrd, 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(trans->shrd, + hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv->shrd, 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(trans, "no info in EEPROM, use default\n"); + 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(trans, "Radio sensor offset high: %d\n", + IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", le16_to_cpu(cmd.radio_sensor_offset_high)); - IWL_DEBUG_CALIB(trans, "Radio sensor offset low: %d\n", + IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n", le16_to_cpu(cmd.radio_sensor_offset_low)); - IWL_DEBUG_CALIB(trans, "Voltage Ref: %d\n", + IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n", le16_to_cpu(cmd.burntVoltageRef)); - return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd)); + return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); } -static int iwl_send_calib_cfg(struct iwl_trans *trans) +static int iwl_send_calib_cfg(struct iwl_priv *priv) { struct iwl_calib_cfg_cmd calib_cfg_cmd; struct iwl_host_cmd cmd = { @@ -181,7 +181,7 @@ static int iwl_send_calib_cfg(struct iwl_trans *trans) calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; - return iwl_trans_send_cmd(trans, &cmd); + return iwl_trans_send_cmd(trans(priv), &cmd); } int iwlagn_rx_calib_result(struct iwl_priv *priv, @@ -195,33 +195,33 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv, /* reduce the size of the length field itself */ len -= 4; - if (iwl_calib_set(trans(priv), hdr, len)) + if (iwl_calib_set(priv, hdr, len)) IWL_ERR(priv, "Failed to record calibration data %d\n", hdr->op_code); return 0; } -int iwl_init_alive_start(struct iwl_trans *trans) +int iwl_init_alive_start(struct iwl_priv *priv) { int ret; - if (cfg(trans)->bt_params && - cfg(trans)->bt_params->advanced_bt_coexist) { + if (cfg(priv)->bt_params && + cfg(priv)->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 = iwl_send_bt_env(trans, IWL_BT_COEX_ENV_OPEN, + ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); if (ret) return ret; } - ret = iwl_send_calib_cfg(trans); + ret = iwl_send_calib_cfg(priv); if (ret) return ret; @@ -229,21 +229,21 @@ int iwl_init_alive_start(struct iwl_trans *trans) * temperature offset calibration is only needed for runtime ucode, * so prepare the value now. */ - if (cfg(trans)->need_temp_offset_calib) { - if (cfg(trans)->temp_offset_v2) - return iwl_set_temperature_offset_calib_v2(trans); + if (cfg(priv)->need_temp_offset_calib) { + if (cfg(priv)->temp_offset_v2) + return iwl_set_temperature_offset_calib_v2(priv); else - return iwl_set_temperature_offset_calib(trans); + return iwl_set_temperature_offset_calib(priv); } return 0; } -static int iwl_send_wimax_coex(struct iwl_trans *trans) +static int iwl_send_wimax_coex(struct iwl_priv *priv) { struct iwl_wimax_coex_cmd coex_cmd; - if (cfg(trans)->base_params->support_wimax_coexist) { + if (cfg(priv)->base_params->support_wimax_coexist) { /* UnMask wake up src at associated sleep */ coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK; @@ -262,7 +262,7 @@ static int iwl_send_wimax_coex(struct iwl_trans *trans) /* coexistence is disabled */ memset(&coex_cmd, 0, sizeof(coex_cmd)); } - return iwl_trans_send_cmd_pdu(trans, + return iwl_trans_send_cmd_pdu(trans(priv), COEX_PRIORITY_TABLE_CMD, CMD_SYNC, sizeof(coex_cmd), &coex_cmd); } @@ -289,37 +289,36 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { 0, 0, 0, 0, 0, 0, 0 }; -void iwl_send_prio_tbl(struct iwl_trans *trans) +void iwl_send_prio_tbl(struct iwl_priv *priv) { struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd; memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl, sizeof(iwl_bt_prio_tbl)); - if (iwl_trans_send_cmd_pdu(trans, + if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, sizeof(prio_tbl_cmd), &prio_tbl_cmd)) - IWL_ERR(trans, "failed to send BT prio tbl command\n"); + IWL_ERR(priv, "failed to send BT prio tbl command\n"); } -int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type) +int iwl_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, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_COEX_PROT_ENV, CMD_SYNC, sizeof(env_cmd), &env_cmd); if (ret) - IWL_ERR(trans, "failed to send BT env command\n"); + IWL_ERR(priv, "failed to send BT env command\n"); return ret; } -static int iwl_alive_notify(struct iwl_trans *trans) +static int iwl_alive_notify(struct iwl_priv *priv) { - struct iwl_priv *priv = priv(trans); struct iwl_rxon_context *ctx; int ret; @@ -332,21 +331,21 @@ static int iwl_alive_notify(struct iwl_trans *trans) if (!priv->tx_cmd_pool) return -ENOMEM; - iwl_trans_fw_alive(trans); + iwl_trans_fw_alive(trans(priv)); for_each_context(priv, ctx) ctx->last_tx_rejected = false; - ret = iwl_send_wimax_coex(trans); + ret = iwl_send_wimax_coex(priv); if (ret) return ret; if (!cfg(priv)->no_xtal_calib) { - ret = iwl_set_Xtal_calib(trans); + ret = iwl_set_Xtal_calib(priv); if (ret) return ret; } - return iwl_send_calib_results(trans); + return iwl_send_calib_results(priv); } @@ -355,24 +354,23 @@ static int iwl_alive_notify(struct iwl_trans *trans) * using sample data 100 bytes apart. If these sample points are good, * it's a pretty good bet that everything between them is good, too. */ -static int iwl_verify_inst_sparse(struct iwl_nic *nic, - struct fw_desc *fw_desc) +static int iwl_verify_inst_sparse(struct iwl_priv *priv, + struct fw_desc *fw_desc) { - struct iwl_trans *trans = trans(nic); __le32 *image = (__le32 *)fw_desc->v_addr; u32 len = fw_desc->len; u32 val; u32 i; - IWL_DEBUG_FW(nic, "ucode inst image size is %u\n", len); + IWL_DEBUG_FW(priv, "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(trans, HBUS_TARG_MEM_RADDR, + iwl_write_direct32(trans(priv), HBUS_TARG_MEM_RADDR, i + IWLAGN_RTC_INST_LOWER_BOUND); - val = iwl_read32(trans, HBUS_TARG_MEM_RDAT); + val = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) return -EIO; } @@ -380,28 +378,27 @@ static int iwl_verify_inst_sparse(struct iwl_nic *nic, return 0; } -static void iwl_print_mismatch_inst(struct iwl_nic *nic, +static void iwl_print_mismatch_inst(struct iwl_priv *priv, struct fw_desc *fw_desc) { - struct iwl_trans *trans = trans(nic); __le32 *image = (__le32 *)fw_desc->v_addr; u32 len = fw_desc->len; u32 val; u32 offs; int errors = 0; - IWL_DEBUG_FW(nic, "ucode inst image size is %u\n", len); + IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len); - iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR, + iwl_write_direct32(trans(priv), 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(trans, HBUS_TARG_MEM_RDAT); + val = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { - IWL_ERR(nic, "uCode INST section at " + IWL_ERR(priv, "uCode INST section at " "offset 0x%x, is 0x%x, s/b 0x%x\n", offs, val, le32_to_cpu(*image)); errors++; @@ -413,24 +410,24 @@ static void iwl_print_mismatch_inst(struct iwl_nic *nic, * iwl_verify_ucode - determine which instruction image is in SRAM, * and verify its contents */ -static int iwl_verify_ucode(struct iwl_nic *nic, +static int iwl_verify_ucode(struct iwl_priv *priv, enum iwl_ucode_type ucode_type) { - struct fw_img *img = iwl_get_ucode_image(nic, ucode_type); + struct fw_img *img = iwl_get_ucode_image(priv, ucode_type); if (!img) { - IWL_ERR(nic, "Invalid ucode requested (%d)\n", ucode_type); + IWL_ERR(priv, "Invalid ucode requested (%d)\n", ucode_type); return -EINVAL; } - if (!iwl_verify_inst_sparse(nic, &img->code)) { - IWL_DEBUG_FW(nic, "uCode is good in inst SRAM\n"); + if (!iwl_verify_inst_sparse(priv, &img->code)) { + IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n"); return 0; } - IWL_ERR(nic, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); + IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); - iwl_print_mismatch_inst(nic, &img->code); + iwl_print_mismatch_inst(priv, &img->code); return -EIO; } @@ -439,7 +436,7 @@ struct iwl_alive_data { u8 subtype; }; -static void iwl_alive_fn(struct iwl_trans *trans, +static void iwl_alive_fn(struct iwl_priv *priv, struct iwl_rx_packet *pkt, void *data) { @@ -448,14 +445,14 @@ static void iwl_alive_fn(struct iwl_trans *trans, palive = &pkt->u.alive_frame; - IWL_DEBUG_FW(trans, "Alive ucode status 0x%08X revision " + IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision " "0x%01X 0x%01X\n", palive->is_valid, palive->ver_type, palive->ver_subtype); - trans->shrd->device_pointers.error_event_table = + priv->shrd->device_pointers.error_event_table = le32_to_cpu(palive->error_event_table_ptr); - trans->shrd->device_pointers.log_event_table = + priv->shrd->device_pointers.log_event_table = le32_to_cpu(palive->log_event_table_ptr); alive_data->subtype = palive->ver_subtype; @@ -464,12 +461,12 @@ static void iwl_alive_fn(struct iwl_trans *trans, /* notification wait support */ void iwl_init_notification_wait(struct iwl_shared *shrd, - struct iwl_notification_wait *wait_entry, - u8 cmd, - void (*fn)(struct iwl_trans *trans, - struct iwl_rx_packet *pkt, - void *data), - void *fn_data) + 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; @@ -529,7 +526,7 @@ void iwl_abort_notification_waits(struct iwl_shared *shrd) #define UCODE_ALIVE_TIMEOUT HZ #define UCODE_CALIB_TIMEOUT (2*HZ) -int iwl_load_ucode_wait_alive(struct iwl_trans *trans, +int iwl_load_ucode_wait_alive(struct iwl_priv *priv, enum iwl_ucode_type ucode_type) { struct iwl_notification_wait alive_wait; @@ -538,20 +535,20 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans, int ret; enum iwl_ucode_type old_type; - iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE, + iwl_init_notification_wait(priv->shrd, &alive_wait, REPLY_ALIVE, iwl_alive_fn, &alive_data); - old_type = trans->shrd->ucode_type; - trans->shrd->ucode_type = ucode_type; - fw = iwl_get_ucode_image(nic(trans), ucode_type); + old_type = priv->shrd->ucode_type; + priv->shrd->ucode_type = ucode_type; + fw = iwl_get_ucode_image(priv, ucode_type); if (!fw) return -EINVAL; - ret = iwl_trans_start_fw(trans, fw); + ret = iwl_trans_start_fw(trans(priv), fw); if (ret) { - trans->shrd->ucode_type = old_type; - iwl_remove_notification(trans->shrd, &alive_wait); + priv->shrd->ucode_type = old_type; + iwl_remove_notification(priv->shrd, &alive_wait); return ret; } @@ -559,16 +556,16 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans, * Some things may run in the background now, but we * just wait for the ALIVE notification here. */ - ret = iwl_wait_notification(trans->shrd, &alive_wait, + ret = iwl_wait_notification(priv->shrd, &alive_wait, UCODE_ALIVE_TIMEOUT); if (ret) { - trans->shrd->ucode_type = old_type; + priv->shrd->ucode_type = old_type; return ret; } if (!alive_data.valid) { - IWL_ERR(trans, "Loaded ucode is not valid!\n"); - trans->shrd->ucode_type = old_type; + IWL_ERR(priv, "Loaded ucode is not valid!\n"); + priv->shrd->ucode_type = old_type; return -EIO; } @@ -578,9 +575,9 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans, * skip it for WoWLAN. */ if (ucode_type != IWL_UCODE_WOWLAN) { - ret = iwl_verify_ucode(nic(trans), ucode_type); + ret = iwl_verify_ucode(priv, ucode_type); if (ret) { - trans->shrd->ucode_type = old_type; + priv->shrd->ucode_type = old_type; return ret; } @@ -588,41 +585,41 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans, msleep(5); } - ret = iwl_alive_notify(trans); + ret = iwl_alive_notify(priv); if (ret) { - IWL_WARN(trans, + IWL_WARN(priv, "Could not complete ALIVE transition: %d\n", ret); - trans->shrd->ucode_type = old_type; + priv->shrd->ucode_type = old_type; return ret; } return 0; } -int iwl_run_init_ucode(struct iwl_trans *trans) +int iwl_run_init_ucode(struct iwl_priv *priv) { struct iwl_notification_wait calib_wait; int ret; - lockdep_assert_held(&trans->shrd->mutex); + lockdep_assert_held(&priv->shrd->mutex); /* No init ucode required? Curious, but maybe ok */ - if (!nic(trans)->fw.ucode_init.code.len) + if (!nic(priv)->fw.ucode_init.code.len) return 0; - if (trans->shrd->ucode_type != IWL_UCODE_NONE) + if (priv->shrd->ucode_type != IWL_UCODE_NONE) return 0; - iwl_init_notification_wait(trans->shrd, &calib_wait, + iwl_init_notification_wait(priv->shrd, &calib_wait, CALIBRATION_COMPLETE_NOTIFICATION, NULL, NULL); /* Will also start the device */ - ret = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT); + ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT); if (ret) goto error; - ret = iwl_init_alive_start(trans); + ret = iwl_init_alive_start(priv); if (ret) goto error; @@ -630,15 +627,15 @@ int iwl_run_init_ucode(struct iwl_trans *trans) * Some things may run in the background now, but we * just wait for the calibration complete notification. */ - ret = iwl_wait_notification(trans->shrd, &calib_wait, + ret = iwl_wait_notification(priv->shrd, &calib_wait, UCODE_CALIB_TIMEOUT); goto out; error: - iwl_remove_notification(trans->shrd, &calib_wait); + iwl_remove_notification(priv->shrd, &calib_wait); out: /* Whatever happened, stop the device */ - iwl_trans_stop_device(trans); + iwl_trans_stop_device(trans(priv)); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-wifi.h b/drivers/net/wireless/iwlwifi/iwl-wifi.h index d157931e1e95..753e338e77d0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-wifi.h +++ b/drivers/net/wireless/iwlwifi/iwl-wifi.h @@ -95,12 +95,4 @@ struct iwl_nic { struct completion request_firmware_complete; }; - - -int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type); -void iwl_send_prio_tbl(struct iwl_trans *trans); -int iwl_init_alive_start(struct iwl_trans *trans); -int iwl_run_init_ucode(struct iwl_trans *trans); -int iwl_load_ucode_wait_alive(struct iwl_trans *trans, - enum iwl_ucode_type ucode_type); #endif /* __iwl_wifi_h__ */ -- cgit v1.2.3-70-g09d2 From 0692fe41b36159be5d8c7d4eef0699e79c383c85 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:37 -0800 Subject: iwlwifi: split out firmware store Through the driver, struct iwl_fw will store the firmware. Split this out into a separate file, iwl-fw.h, and make all other code use it. To do this, also move the log pointers into it, and remove the knowledge of "nic" from everything. Now the op_mode has a fw pointer, and (unfortunately) for now the shared data also needs to keep one for the transport to access dump the error log -- I think that will move later. Since I wanted to constify the firmware pointers, some more changes were needed. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 5 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 2 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 12 -- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 9 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + drivers/net/wireless/iwlwifi/iwl-drv.c | 49 ++++---- drivers/net/wireless/iwlwifi/iwl-fw.h | 146 +++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-mac80211.c | 10 +- drivers/net/wireless/iwlwifi/iwl-op-mode.h | 4 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 5 +- drivers/net/wireless/iwlwifi/iwl-testmode.c | 16 +-- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 23 ++-- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 9 +- drivers/net/wireless/iwlwifi/iwl-trans.h | 5 +- drivers/net/wireless/iwlwifi/iwl-ucode.c | 21 ++-- drivers/net/wireless/iwlwifi/iwl-ucode.h | 60 ---------- drivers/net/wireless/iwlwifi/iwl-wifi.h | 10 -- 19 files changed, 236 insertions(+), 163 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-fw.h (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 29f94597b55f..4928f6f52bf1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -69,7 +69,6 @@ #include "iwl-trans.h" #include "iwl-agn.h" #include "iwl-wifi.h" -#include "iwl-ucode.h" /***************************************************************************** * INIT calibrations framework @@ -644,7 +643,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) data->last_bad_plcp_cnt_cck = 0; data->last_fa_cnt_cck = 0; - if (nic(priv)->fw.enhance_sensitivity_table) + if (priv->fw->enhance_sensitivity_table) ret |= iwl_enhance_sensitivity_write(priv); else ret |= iwl_sensitivity_write(priv); @@ -754,7 +753,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time); iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); - if (nic(priv)->fw.enhance_sensitivity_table) + if (priv->fw->enhance_sensitivity_table) iwl_enhance_sensitivity_write(priv); else iwl_sensitivity_write(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 45b060a45d9d..89be05615dd9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -77,7 +77,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED; tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; - if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) == 1) + if (IWL_UCODE_API(priv->fw->ucode_ver) == 1) tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; else tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f53308fb428e..c3040ad86e89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -41,7 +41,6 @@ #include -#include "iwl-ucode.h" #include "iwl-eeprom.h" #include "iwl-wifi.h" #include "iwl-dev.h" @@ -616,7 +615,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) .valid = cpu_to_le32(valid_tx_ant), }; - if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) > 1) { + if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) { IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); return iwl_trans_send_cmd_pdu(trans(priv), TX_ANT_CONFIGURATION_CMD, @@ -1174,9 +1173,9 @@ static void iwl_debug_config(struct iwl_priv *priv) #endif } -static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans) +static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, + const struct iwl_fw *fw) { - struct iwl_fw *fw = &nic(trans)->fw; int err = 0; struct iwl_priv *priv; struct ieee80211_hw *hw; @@ -1200,6 +1199,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans) priv = IWL_OP_MODE_GET_DVM(op_mode); priv->shrd = trans->shrd; priv->shrd->priv = priv; + priv->fw = fw; + /* TODO: remove fw from shared data later */ + priv->shrd->fw = fw; iwl_trans_configure(trans(priv), op_mode); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 2a90d779eecf..f55243828698 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -93,7 +93,7 @@ void iwl_nic_error(struct iwl_op_mode *op_mode); /* MAC80211 */ struct ieee80211_hw *iwl_alloc_all(void); int iwlagn_mac_setup_register(struct iwl_priv *priv, - struct iwl_ucode_capabilities *capa); + const struct iwl_ucode_capabilities *capa); void iwlagn_mac_unregister(struct iwl_priv *priv); /* RXON */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index c20618d92268..aa8993065cdf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -74,13 +74,6 @@ struct iwl_priv; -/* uCode version contains 4 values: Major/Minor/API/Serial */ -#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24) -#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16) -#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8) -#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF) - - /* Tx rates */ #define IWL_CCK_RATES 4 #define IWL_OFDM_RATES 8 @@ -3151,8 +3144,6 @@ struct iwl_enhance_sensitivity_cmd { */ /* Phy calibration command for series */ -/* The default calibrate table size if not specified by firmware */ -#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18 enum { IWL_PHY_CALIBRATE_DC_CMD = 8, IWL_PHY_CALIBRATE_LO_CMD = 9, @@ -3161,11 +3152,8 @@ enum { IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD = 18, - IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 19, }; -#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE (253) - /* This enum defines the bitmap of various calibrations to enable in both * init ucode and runtime ucode through CALIBRATION_CFG_CMD. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index b6740c33b519..0e63cb70c713 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -235,12 +235,11 @@ 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_nic *nic = nic(priv); priv->dbgfs_sram_offset = 0x800000; - if (nic->shrd->ucode_type == IWL_UCODE_INIT) - priv->dbgfs_sram_len = nic->fw.ucode_init.data.len; + if (priv->shrd->ucode_type == IWL_UCODE_INIT) + priv->dbgfs_sram_len = priv->fw->ucode_init.data.len; else - priv->dbgfs_sram_len = nic->fw.ucode_rt.data.len; + priv->dbgfs_sram_len = priv->fw->ucode_rt.data.len; } len = priv->dbgfs_sram_len; @@ -343,7 +342,7 @@ static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, priv->wowlan_sram, - nic(priv)->fw.ucode_wowlan.data.len); + priv->fw->ucode_wowlan.data.len); } static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 7199748faaab..4def9f961891 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -715,6 +715,7 @@ struct iwl_priv { /*data shared among all the driver's layers */ struct iwl_shared *shrd; + const struct iwl_fw *fw; spinlock_t sta_lock; diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 1a588f36b591..351b2f908383 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -71,6 +71,9 @@ #include "iwl-shared.h" #include "iwl-op-mode.h" +/* private includes */ +#include "iwl-ucode.h" + static void iwl_free_fw_desc(struct iwl_nic *nic, struct fw_desc *desc) { if (desc->v_addr) @@ -641,20 +644,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) * for each event, which is of mode 1 (including timestamp) for all * new microcodes that include this information. */ - nic->init_evtlog_ptr = pieces.init_evtlog_ptr; + fw->init_evtlog_ptr = pieces.init_evtlog_ptr; if (pieces.init_evtlog_size) - nic->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; + fw->init_evtlog_size = (pieces.init_evtlog_size - 16)/12; else - nic->init_evtlog_size = + fw->init_evtlog_size = cfg->base_params->max_event_log_size; - nic->init_errlog_ptr = pieces.init_errlog_ptr; - nic->inst_evtlog_ptr = pieces.inst_evtlog_ptr; + fw->init_errlog_ptr = pieces.init_errlog_ptr; + fw->inst_evtlog_ptr = pieces.inst_evtlog_ptr; if (pieces.inst_evtlog_size) - nic->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; + fw->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12; else - nic->inst_evtlog_size = + fw->inst_evtlog_size = cfg->base_params->max_event_log_size; - nic->inst_errlog_ptr = pieces.inst_errlog_ptr; + fw->inst_errlog_ptr = pieces.inst_errlog_ptr; /* * figure out the offset of chain noise reset and gain commands @@ -669,7 +672,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) release_firmware(ucode_raw); complete(&nic->request_firmware_complete); - nic->op_mode = iwl_dvm_ops.start(nic->shrd->trans); + nic->op_mode = iwl_dvm_ops.start(nic->shrd->trans, &nic->fw); if (!nic->op_mode) goto out_unbind; @@ -695,24 +698,27 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) int iwl_drv_start(struct iwl_shared *shrd, struct iwl_trans *trans, const struct iwl_cfg *cfg) { + struct iwl_nic *nic; int ret; shrd->cfg = cfg; - shrd->nic = kzalloc(sizeof(*shrd->nic), GFP_KERNEL); - if (!shrd->nic) { + nic = kzalloc(sizeof(*nic), GFP_KERNEL); + if (!nic) { dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_nic"); return -ENOMEM; } - shrd->nic->shrd = shrd; + nic->shrd = shrd; + shrd->nic = nic; - init_completion(&shrd->nic->request_firmware_complete); + init_completion(&nic->request_firmware_complete); - ret = iwl_request_firmware(shrd->nic, true); + ret = iwl_request_firmware(nic, true); if (ret) { dev_printk(KERN_ERR, trans->dev, "Couldn't request the fw"); - kfree(shrd->nic); + kfree(nic); + shrd->nic = NULL; } return ret; @@ -720,13 +726,16 @@ int iwl_drv_start(struct iwl_shared *shrd, void iwl_drv_stop(struct iwl_shared *shrd) { - wait_for_completion(&shrd->nic->request_firmware_complete); + struct iwl_nic *nic = shrd->nic; + + wait_for_completion(&nic->request_firmware_complete); /* op_mode can be NULL if its start failed */ - if (shrd->nic->op_mode) - iwl_op_mode_stop(shrd->nic->op_mode); + if (nic->op_mode) + iwl_op_mode_stop(nic->op_mode); - iwl_dealloc_ucode(shrd->nic); + iwl_dealloc_ucode(nic); - kfree(shrd->nic); + kfree(nic); + shrd->nic = NULL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h new file mode 100644 index 000000000000..453812a21176 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h @@ -0,0 +1,146 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef __iwl_fw_h__ +#define __iwl_fw_h__ +#include + +/** + * enum iwl_ucode_tlv_flag - ucode API flags + * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously + * was a separate TLV but moved here to save space. + * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID, + * treats good CRC threshold as a boolean + * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). + * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. + */ +enum iwl_ucode_tlv_flag { + IWL_UCODE_TLV_FLAGS_PAN = BIT(0), + IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), + IWL_UCODE_TLV_FLAGS_MFP = BIT(2), + IWL_UCODE_TLV_FLAGS_P2P = BIT(3), +}; + +/* The default calibrate table size if not specified by firmware file */ +#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18 +#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19 +#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE 253 + +struct iwl_ucode_capabilities { + u32 max_probe_length; + u32 standard_phy_calibration_size; + u32 flags; +}; + +/* one for each uCode image (inst/data, boot/init/runtime) */ +struct fw_desc { + dma_addr_t p_addr; /* hardware address */ + void *v_addr; /* software address */ + u32 len; /* size in bytes */ +}; + +struct fw_img { + struct fw_desc code; /* firmware code image */ + struct fw_desc data; /* firmware data image */ +}; + +/* uCode version contains 4 values: Major/Minor/API/Serial */ +#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24) +#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16) +#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8) +#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF) + +/** + * struct iwl_fw - variables associated with the firmware + * + * @ucode_ver: ucode version from the ucode file + * @fw_version: firmware version string + * @ucode_rt: run time ucode image + * @ucode_init: init ucode image + * @ucode_wowlan: wake on wireless ucode image (optional) + * @ucode_capa: capabilities parsed from the ucode file. + * @enhance_sensitivity_table: device can do enhanced sensitivity. + * @init_evtlog_ptr: event log offset for init ucode. + * @init_evtlog_size: event log size for init ucode. + * @init_errlog_ptr: error log offfset for init ucode. + * @inst_evtlog_ptr: event log offset for runtime ucode. + * @inst_evtlog_size: event log size for runtime ucode. + * @inst_errlog_ptr: error log offfset for runtime ucode. + */ +struct iwl_fw { + u32 ucode_ver; + + char fw_version[ETHTOOL_BUSINFO_LEN]; + + /* ucode images */ + struct fw_img ucode_rt; + struct fw_img ucode_init; + struct fw_img ucode_wowlan; + + struct iwl_ucode_capabilities ucode_capa; + bool enhance_sensitivity_table; + + u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; + u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; +}; + +#endif /* __iwl_fw_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 37330addce79..3bcd2a766074 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -42,7 +42,6 @@ #include -#include "iwl-ucode.h" #include "iwl-eeprom.h" #include "iwl-wifi.h" #include "iwl-dev.h" @@ -136,7 +135,7 @@ iwlagn_iface_combinations_p2p[] = { * other mac80211 functions grouped here. */ int iwlagn_mac_setup_register(struct iwl_priv *priv, - struct iwl_ucode_capabilities *capa) + const struct iwl_ucode_capabilities *capa) { int ret; struct ieee80211_hw *hw = priv->hw; @@ -195,7 +194,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, WIPHY_FLAG_DISABLE_BEACON_HINTS | WIPHY_FLAG_IBSS_RSN; - if (nic(priv)->fw.ucode_wowlan.code.len && + if (priv->fw->ucode_wowlan.code.len && trans(priv)->ops->wowlan_suspend && device_can_wakeup(trans(priv)->dev)) { hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | @@ -456,17 +455,16 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) #ifdef CONFIG_IWLWIFI_DEBUGFS if (ret == 0) { - struct iwl_nic *nic = nic(priv); if (!priv->wowlan_sram) priv->wowlan_sram = - kzalloc(nic->fw.ucode_wowlan.data.len, + kzalloc(priv->fw->ucode_wowlan.data.len, GFP_KERNEL); if (priv->wowlan_sram) _iwl_read_targ_mem_words( trans(priv), 0x800000, priv->wowlan_sram, - nic->fw.ucode_wowlan.data.len / 4); + priv->fw->ucode_wowlan.data.len / 4); } #endif } diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index 41e58a136715..55b8b27a9560 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h @@ -68,6 +68,7 @@ struct iwl_trans; struct sk_buff; struct iwl_device_cmd; struct iwl_rx_cmd_buffer; +struct iwl_fw; /** * DOC: Operational mode - what is it ? @@ -123,7 +124,8 @@ struct iwl_rx_cmd_buffer; * @nic_error: error notification. Must be atomic */ struct iwl_op_mode_ops { - struct iwl_op_mode *(*start)(struct iwl_trans *trans); + struct iwl_op_mode *(*start)(struct iwl_trans *trans, + const struct iwl_fw *fw); void (*stop)(struct iwl_op_mode *op_mode); int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index dc5544653bc0..3754c35a1a50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -70,6 +70,7 @@ #include #include "iwl-commands.h" +#include "iwl-fw.h" /** * DOC: shared area - role and goal @@ -418,8 +419,9 @@ struct iwl_shared { const struct iwl_cfg *cfg; struct iwl_priv *priv; struct iwl_trans *trans; - struct iwl_nic *nic; + void *nic; struct iwl_hw_params hw_params; + const struct iwl_fw *fw; struct mutex mutex; @@ -446,7 +448,6 @@ struct iwl_shared { /*Whatever _m is (iwl_trans, iwl_priv, these macros will work */ #define priv(_m) ((_m)->shrd->priv) #define cfg(_m) ((_m)->shrd->cfg) -#define nic(_m) ((_m)->shrd->nic) #define trans(_m) ((_m)->shrd->trans) #define hw_params(_m) ((_m)->shrd->hw_params) diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index ec803ea08675..fd25dd1d62e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -553,7 +553,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) case IWL_TM_CMD_APP2DEV_GET_FW_VERSION: IWL_INFO(priv, "uCode version raw: 0x%x\n", - nic(priv)->fw.ucode_ver); + priv->fw->ucode_ver); skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); if (!skb) { @@ -561,7 +561,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) return -ENOMEM; } NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION, - nic(priv)->fw.ucode_ver); + priv->fw->ucode_ver); status = cfg80211_testmode_reply(skb); if (status < 0) IWL_ERR(priv, "Error sending msg : %d\n", status); @@ -590,16 +590,16 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) } switch (priv->shrd->ucode_type) { case IWL_UCODE_REGULAR: - inst_size = nic(priv)->fw.ucode_rt.code.len; - data_size = nic(priv)->fw.ucode_rt.data.len; + inst_size = priv->fw->ucode_rt.code.len; + data_size = priv->fw->ucode_rt.data.len; break; case IWL_UCODE_INIT: - inst_size = nic(priv)->fw.ucode_init.code.len; - data_size = nic(priv)->fw.ucode_init.data.len; + inst_size = priv->fw->ucode_init.code.len; + data_size = priv->fw->ucode_init.data.len; break; case IWL_UCODE_WOWLAN: - inst_size = nic(priv)->fw.ucode_wowlan.code.len; - data_size = nic(priv)->fw.ucode_wowlan.data.len; + inst_size = priv->fw->ucode_wowlan.code.len; + data_size = priv->fw->ucode_wowlan.data.len; break; case IWL_UCODE_NONE: IWL_ERR(priv, "No uCode has not been loaded\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index bf560e9f87b7..69e4544afe24 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -602,17 +602,16 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) { u32 base; struct iwl_error_event_table table; - struct iwl_nic *nic = nic(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); base = trans->shrd->device_pointers.error_event_table; if (trans->shrd->ucode_type == IWL_UCODE_INIT) { if (!base) - base = nic->init_errlog_ptr; + base = trans->shrd->fw->init_errlog_ptr; } else { if (!base) - base = nic->inst_errlog_ptr; + base = trans->shrd->fw->inst_errlog_ptr; } if (!iwlagn_hw_valid_rtc_data_addr(base)) { @@ -634,7 +633,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) trans_pcie->isr_stats.err_code = table.error_id; - trace_iwlwifi_dev_ucode_error(priv(nic), table.error_id, table.tsf_low, + trace_iwlwifi_dev_ucode_error(priv(trans), table.error_id, table.tsf_low, table.data1, table.data2, table.line, table.blink1, table.blink2, table.ilink1, table.ilink2, table.bcon_time, table.gp1, @@ -700,7 +699,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) } IWL_ERR(trans, "Loaded firmware version: %s\n", - nic(trans)->fw.fw_version); + trans->shrd->fw->fw_version); iwl_dump_nic_error_log(trans); iwl_dump_csr(trans); @@ -726,7 +725,6 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, u32 ptr; /* SRAM byte address of log data */ u32 ev, time, data; /* event log data */ unsigned long reg_flags; - struct iwl_nic *nic = nic(trans); if (num_events == 0) return pos; @@ -734,10 +732,10 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, base = trans->shrd->device_pointers.log_event_table; if (trans->shrd->ucode_type == IWL_UCODE_INIT) { if (!base) - base = nic->init_evtlog_ptr; + base = trans->shrd->fw->init_evtlog_ptr; } else { if (!base) - base = nic->inst_evtlog_ptr; + base = trans->shrd->fw->inst_evtlog_ptr; } if (mode == 0) @@ -843,17 +841,16 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, u32 logsize; int pos = 0; size_t bufsz = 0; - struct iwl_nic *nic = nic(trans); base = trans->shrd->device_pointers.log_event_table; if (trans->shrd->ucode_type == IWL_UCODE_INIT) { - logsize = nic->init_evtlog_size; + logsize = trans->shrd->fw->init_evtlog_size; if (!base) - base = nic->init_evtlog_ptr; + base = trans->shrd->fw->init_evtlog_ptr; } else { - logsize = nic->inst_evtlog_size; + logsize = trans->shrd->fw->inst_evtlog_size; if (!base) - base = nic->inst_evtlog_ptr; + base = trans->shrd->fw->inst_evtlog_ptr; } if (!iwlagn_hw_valid_rtc_data_addr(base)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index f49aa181f4af..d7dbd80eb108 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -76,7 +76,6 @@ #include "iwl-eeprom.h" #include "iwl-agn-hw.h" #include "iwl-core.h" -#include "iwl-ucode.h" #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) @@ -947,7 +946,7 @@ static const u8 iwlagn_pan_ac_to_queue[] = { * ucode */ static int iwl_load_section(struct iwl_trans *trans, const char *name, - struct fw_desc *image, u32 dst_addr) + const struct fw_desc *image, u32 dst_addr) { dma_addr_t phy_addr = image->p_addr; u32 byte_cnt = image->len; @@ -995,7 +994,8 @@ static int iwl_load_section(struct iwl_trans *trans, const char *name, return 0; } -static int iwl_load_given_ucode(struct iwl_trans *trans, struct fw_img *image) +static int iwl_load_given_ucode(struct iwl_trans *trans, + const struct fw_img *image) { int ret = 0; @@ -1015,7 +1015,8 @@ static int iwl_load_given_ucode(struct iwl_trans *trans, struct fw_img *image) return 0; } -static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw) +static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, + const struct fw_img *fw) { int ret; struct iwl_trans_pcie *trans_pcie = diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 6fa0c860a5e2..ec5249c8a7f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -272,7 +272,7 @@ struct iwl_trans_ops { int (*start_hw)(struct iwl_trans *iwl_trans); void (*stop_hw)(struct iwl_trans *iwl_trans); - int (*start_fw)(struct iwl_trans *trans, struct fw_img *fw); + int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw); void (*fw_alive)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans); @@ -400,7 +400,8 @@ static inline void iwl_trans_fw_alive(struct iwl_trans *trans) trans->state = IWL_TRANS_FW_ALIVE; } -static inline int iwl_trans_start_fw(struct iwl_trans *trans, struct fw_img *fw) +static inline int iwl_trans_start_fw(struct iwl_trans *trans, + const struct fw_img *fw) { might_sleep(); diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 340575a01ead..f78b1552ef7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -31,7 +31,6 @@ #include #include -#include "iwl-ucode.h" #include "iwl-wifi.h" #include "iwl-dev.h" #include "iwl-core.h" @@ -80,16 +79,16 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { * ******************************************************************************/ -static inline struct fw_img *iwl_get_ucode_image(struct iwl_priv *priv, - enum iwl_ucode_type ucode_type) +static inline const struct fw_img * +iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type) { switch (ucode_type) { case IWL_UCODE_INIT: - return &nic(priv)->fw.ucode_init; + return &priv->fw->ucode_init; case IWL_UCODE_WOWLAN: - return &nic(priv)->fw.ucode_wowlan; + return &priv->fw->ucode_wowlan; case IWL_UCODE_REGULAR: - return &nic(priv)->fw.ucode_rt; + return &priv->fw->ucode_rt; case IWL_UCODE_NONE: break; } @@ -355,7 +354,7 @@ static int iwl_alive_notify(struct iwl_priv *priv) * it's a pretty good bet that everything between them is good, too. */ static int iwl_verify_inst_sparse(struct iwl_priv *priv, - struct fw_desc *fw_desc) + const struct fw_desc *fw_desc) { __le32 *image = (__le32 *)fw_desc->v_addr; u32 len = fw_desc->len; @@ -379,7 +378,7 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv, } static void iwl_print_mismatch_inst(struct iwl_priv *priv, - struct fw_desc *fw_desc) + const struct fw_desc *fw_desc) { __le32 *image = (__le32 *)fw_desc->v_addr; u32 len = fw_desc->len; @@ -413,7 +412,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, static int iwl_verify_ucode(struct iwl_priv *priv, enum iwl_ucode_type ucode_type) { - struct fw_img *img = iwl_get_ucode_image(priv, ucode_type); + const struct fw_img *img = iwl_get_ucode_image(priv, ucode_type); if (!img) { IWL_ERR(priv, "Invalid ucode requested (%d)\n", ucode_type); @@ -531,7 +530,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, { struct iwl_notification_wait alive_wait; struct iwl_alive_data alive_data; - struct fw_img *fw; + const struct fw_img *fw; int ret; enum iwl_ucode_type old_type; @@ -604,7 +603,7 @@ int iwl_run_init_ucode(struct iwl_priv *priv) lockdep_assert_held(&priv->shrd->mutex); /* No init ucode required? Curious, but maybe ok */ - if (!nic(priv)->fw.ucode_init.code.len) + if (!priv->fw->ucode_init.code.len) return 0; if (priv->shrd->ucode_type != IWL_UCODE_NONE) diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.h b/drivers/net/wireless/iwlwifi/iwl-ucode.h index 8bebeb003bef..cdab28784404 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.h +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.h @@ -126,22 +126,6 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_FLAGS = 18, }; -/** - * enum iwl_ucode_tlv_flag - ucode API flags - * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously - * was a separate TLV but moved here to save space. - * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID, - * treats good CRC threshold as a boolean - * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). - * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. - */ -enum iwl_ucode_tlv_flag { - IWL_UCODE_TLV_FLAGS_PAN = BIT(0), - IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), - IWL_UCODE_TLV_FLAGS_MFP = BIT(2), - IWL_UCODE_TLV_FLAGS_P2P = BIT(3), -}; - struct iwl_ucode_tlv { __le16 type; /* see above */ __le16 alternative; /* see comment */ @@ -173,48 +157,4 @@ struct iwl_tlv_ucode_header { u8 data[0]; }; -struct iwl_ucode_capabilities { - u32 max_probe_length; - u32 standard_phy_calibration_size; - u32 flags; -}; - -/* one for each uCode image (inst/data, boot/init/runtime) */ -struct fw_desc { - dma_addr_t p_addr; /* hardware address */ - void *v_addr; /* software address */ - u32 len; /* size in bytes */ -}; - -struct fw_img { - struct fw_desc code; /* firmware code image */ - struct fw_desc data; /* firmware data image */ -}; - -/** - * struct iwl_fw - variables associated with the firmware - * - * @ucode_ver: ucode version from the ucode file - * @fw_version: firmware version string - * @ucode_rt: run time ucode image - * @ucode_init: init ucode image - * @ucode_wowlan: wake on wireless ucode image (optional) - * @ucode_capa: capabilities parsed from the ucode file. - * @enhance_sensitivity_table: device can do enhanced sensitivity. - */ -struct iwl_fw { - - u32 ucode_ver; - - char fw_version[ETHTOOL_BUSINFO_LEN]; - - /* ucode images */ - struct fw_img ucode_rt; - struct fw_img ucode_init; - struct fw_img ucode_wowlan; - - struct iwl_ucode_capabilities ucode_capa; - bool enhance_sensitivity_table; -}; - #endif /* __iwl_ucode_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-wifi.h b/drivers/net/wireless/iwlwifi/iwl-wifi.h index 753e338e77d0..a71624d3ea23 100644 --- a/drivers/net/wireless/iwlwifi/iwl-wifi.h +++ b/drivers/net/wireless/iwlwifi/iwl-wifi.h @@ -64,7 +64,6 @@ #define __iwl_wifi_h__ #include "iwl-shared.h" -#include "iwl-ucode.h" /** * struct iwl_nic - nic common data @@ -73,12 +72,6 @@ * @op_mode: the running op_mode * @fw_index: firmware revision to try loading * @firmware_name: composite filename of ucode file to load - * @init_evtlog_ptr: event log offset for init ucode. - * @init_evtlog_size: event log size for init ucode. - * @init_errlog_ptr: error log offfset for init ucode. - * @inst_evtlog_ptr: event log offset for runtime ucode. - * @inst_evtlog_size: event log size for runtime ucode. - * @inst_errlog_ptr: error log offfset for runtime ucode. * @request_firmware_complete: the firmware has been obtained from user space */ struct iwl_nic { @@ -90,9 +83,6 @@ struct iwl_nic { int fw_index; /* firmware we're trying to load */ char firmware_name[25]; /* name of firmware file to load */ - u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; - u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; - struct completion request_firmware_complete; }; #endif /* __iwl_wifi_h__ */ -- cgit v1.2.3-70-g09d2 From 965974a631756ab2729469b9ecadfe61ee44dfc5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:38 -0800 Subject: iwlwifi: remove iwl-wifi.h This file was recently introduced, but then directly abused -- it contained private data that shouldn't have been used by anything but the implementation of firmware requests and some very core code. Now that it is no longer accessed by any code but the code in iwl-drv.c, we can dissolve it. Also rename the iwl_nic struct to iwl_drv to better reflect where and how it is used. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 1 - drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 1 - drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl-core.c | 1 - drivers/net/wireless/iwlwifi/iwl-debugfs.c | 1 - drivers/net/wireless/iwlwifi/iwl-drv.c | 272 ++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 1 - drivers/net/wireless/iwlwifi/iwl-shared.h | 2 +- drivers/net/wireless/iwlwifi/iwl-testmode.c | 1 - drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 1 - drivers/net/wireless/iwlwifi/iwl-ucode.c | 1 - drivers/net/wireless/iwlwifi/iwl-wifi.h | 88 -------- 12 files changed, 148 insertions(+), 223 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-wifi.h (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 4928f6f52bf1..588d107b82f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -68,7 +68,6 @@ #include "iwl-agn-calib.h" #include "iwl-trans.h" #include "iwl-agn.h" -#include "iwl-wifi.h" /***************************************************************************** * INIT calibrations framework diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 89be05615dd9..b06283282283 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -32,7 +32,6 @@ #include #include -#include "iwl-wifi.h" #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c3040ad86e89..cdfe76151072 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -42,7 +42,6 @@ #include #include "iwl-eeprom.h" -#include "iwl-wifi.h" #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c5df3e3d975b..9ae17c3bb885 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -41,7 +41,6 @@ #include "iwl-shared.h" #include "iwl-agn.h" #include "iwl-trans.h" -#include "iwl-wifi.h" const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 0e63cb70c713..bc3e267ed4c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -40,7 +40,6 @@ #include "iwl-core.h" #include "iwl-io.h" #include "iwl-agn.h" -#include "iwl-wifi.h" /* create and remove of files */ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 351b2f908383..f1beeab1e601 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -67,36 +67,58 @@ #include "iwl-drv.h" #include "iwl-trans.h" -#include "iwl-wifi.h" #include "iwl-shared.h" #include "iwl-op-mode.h" /* private includes */ #include "iwl-ucode.h" -static void iwl_free_fw_desc(struct iwl_nic *nic, struct fw_desc *desc) +/** + * struct iwl_drv - drv common data + * @fw: the iwl_fw structure + * @shrd: pointer to common shared structure + * @op_mode: the running op_mode + * @fw_index: firmware revision to try loading + * @firmware_name: composite filename of ucode file to load + * @request_firmware_complete: the firmware has been obtained from user space + */ +struct iwl_drv { + struct iwl_fw fw; + + struct iwl_shared *shrd; + struct iwl_op_mode *op_mode; + + int fw_index; /* firmware we're trying to load */ + char firmware_name[25]; /* name of firmware file to load */ + + struct completion request_firmware_complete; +}; + + + +static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc) { if (desc->v_addr) - dma_free_coherent(trans(nic)->dev, desc->len, + dma_free_coherent(trans(drv)->dev, desc->len, desc->v_addr, desc->p_addr); desc->v_addr = NULL; desc->len = 0; } -static void iwl_free_fw_img(struct iwl_nic *nic, struct fw_img *img) +static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img) { - iwl_free_fw_desc(nic, &img->code); - iwl_free_fw_desc(nic, &img->data); + iwl_free_fw_desc(drv, &img->code); + iwl_free_fw_desc(drv, &img->data); } -static void iwl_dealloc_ucode(struct iwl_nic *nic) +static void iwl_dealloc_ucode(struct iwl_drv *drv) { - iwl_free_fw_img(nic, &nic->fw.ucode_rt); - iwl_free_fw_img(nic, &nic->fw.ucode_init); - iwl_free_fw_img(nic, &nic->fw.ucode_wowlan); + iwl_free_fw_img(drv, &drv->fw.ucode_rt); + iwl_free_fw_img(drv, &drv->fw.ucode_init); + iwl_free_fw_img(drv, &drv->fw.ucode_wowlan); } -static int iwl_alloc_fw_desc(struct iwl_nic *nic, struct fw_desc *desc, +static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, const void *data, size_t len) { if (!len) { @@ -104,7 +126,7 @@ static int iwl_alloc_fw_desc(struct iwl_nic *nic, struct fw_desc *desc, return -EINVAL; } - desc->v_addr = dma_alloc_coherent(trans(nic)->dev, len, + desc->v_addr = dma_alloc_coherent(trans(drv)->dev, len, &desc->p_addr, GFP_KERNEL); if (!desc->v_addr) return -ENOMEM; @@ -119,40 +141,40 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); #define UCODE_EXPERIMENTAL_INDEX 100 #define UCODE_EXPERIMENTAL_TAG "exp" -static int iwl_request_firmware(struct iwl_nic *nic, bool first) +static int iwl_request_firmware(struct iwl_drv *drv, bool first) { - const struct iwl_cfg *cfg = cfg(nic); + const struct iwl_cfg *cfg = cfg(drv); const char *name_pre = cfg->fw_name_pre; char tag[8]; if (first) { #ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE - nic->fw_index = UCODE_EXPERIMENTAL_INDEX; + drv->fw_index = UCODE_EXPERIMENTAL_INDEX; strcpy(tag, UCODE_EXPERIMENTAL_TAG); - } else if (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) { + } else if (drv->fw_index == UCODE_EXPERIMENTAL_INDEX) { #endif - nic->fw_index = cfg->ucode_api_max; - sprintf(tag, "%d", nic->fw_index); + drv->fw_index = cfg->ucode_api_max; + sprintf(tag, "%d", drv->fw_index); } else { - nic->fw_index--; - sprintf(tag, "%d", nic->fw_index); + drv->fw_index--; + sprintf(tag, "%d", drv->fw_index); } - if (nic->fw_index < cfg->ucode_api_min) { - IWL_ERR(nic, "no suitable firmware found!\n"); + if (drv->fw_index < cfg->ucode_api_min) { + IWL_ERR(drv, "no suitable firmware found!\n"); return -ENOENT; } - sprintf(nic->firmware_name, "%s%s%s", name_pre, tag, ".ucode"); + sprintf(drv->firmware_name, "%s%s%s", name_pre, tag, ".ucode"); - IWL_DEBUG_INFO(nic, "attempting to load firmware %s'%s'\n", - (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) + IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n", + (drv->fw_index == UCODE_EXPERIMENTAL_INDEX) ? "EXPERIMENTAL " : "", - nic->firmware_name); + drv->firmware_name); - return request_firmware_nowait(THIS_MODULE, 1, nic->firmware_name, - trans(nic)->dev, - GFP_KERNEL, nic, iwl_ucode_callback); + return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name, + trans(drv)->dev, + GFP_KERNEL, drv, iwl_ucode_callback); } struct iwlagn_firmware_pieces { @@ -164,7 +186,7 @@ struct iwlagn_firmware_pieces { u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; }; -static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic, +static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv, const struct firmware *ucode_raw, struct iwlagn_firmware_pieces *pieces) { @@ -173,14 +195,14 @@ static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic, char buildstr[25]; const u8 *src; - nic->fw.ucode_ver = le32_to_cpu(ucode->ver); - api_ver = IWL_UCODE_API(nic->fw.ucode_ver); + drv->fw.ucode_ver = le32_to_cpu(ucode->ver); + api_ver = IWL_UCODE_API(drv->fw.ucode_ver); switch (api_ver) { default: hdr_size = 28; if (ucode_raw->size < hdr_size) { - IWL_ERR(nic, "File size too small!\n"); + IWL_ERR(drv, "File size too small!\n"); return -EINVAL; } build = le32_to_cpu(ucode->u.v2.build); @@ -196,7 +218,7 @@ static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic, case 2: hdr_size = 24; if (ucode_raw->size < hdr_size) { - IWL_ERR(nic, "File size too small!\n"); + IWL_ERR(drv, "File size too small!\n"); return -EINVAL; } build = 0; @@ -211,18 +233,18 @@ static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic, if (build) sprintf(buildstr, " build %u%s", build, - (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) + (drv->fw_index == UCODE_EXPERIMENTAL_INDEX) ? " (EXP)" : ""); else buildstr[0] = '\0'; - snprintf(nic->fw.fw_version, - sizeof(nic->fw.fw_version), + snprintf(drv->fw.fw_version, + sizeof(drv->fw.fw_version), "%u.%u.%u.%u%s", - IWL_UCODE_MAJOR(nic->fw.ucode_ver), - IWL_UCODE_MINOR(nic->fw.ucode_ver), - IWL_UCODE_API(nic->fw.ucode_ver), - IWL_UCODE_SERIAL(nic->fw.ucode_ver), + IWL_UCODE_MAJOR(drv->fw.ucode_ver), + IWL_UCODE_MINOR(drv->fw.ucode_ver), + IWL_UCODE_API(drv->fw.ucode_ver), + IWL_UCODE_SERIAL(drv->fw.ucode_ver), buildstr); /* Verify size of file vs. image size info in file's header */ @@ -230,7 +252,7 @@ static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic, pieces->data_size + pieces->init_size + pieces->init_data_size) { - IWL_ERR(nic, + IWL_ERR(drv, "uCode file size %d does not match expected size\n", (int)ucode_raw->size); return -EINVAL; @@ -248,7 +270,7 @@ static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic, return 0; } -static int iwl_parse_tlv_firmware(struct iwl_nic *nic, +static int iwl_parse_tlv_firmware(struct iwl_drv *drv, const struct firmware *ucode_raw, struct iwlagn_firmware_pieces *pieces, struct iwl_ucode_capabilities *capa) @@ -267,12 +289,12 @@ static int iwl_parse_tlv_firmware(struct iwl_nic *nic, u32 build; if (len < sizeof(*ucode)) { - IWL_ERR(nic, "uCode has invalid length: %zd\n", len); + IWL_ERR(drv, "uCode has invalid length: %zd\n", len); return -EINVAL; } if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) { - IWL_ERR(nic, "invalid uCode magic: 0X%x\n", + IWL_ERR(drv, "invalid uCode magic: 0X%x\n", le32_to_cpu(ucode->magic)); return -EINVAL; } @@ -290,27 +312,27 @@ static int iwl_parse_tlv_firmware(struct iwl_nic *nic, while (wanted_alternative && !(alternatives & BIT(wanted_alternative))) wanted_alternative--; if (wanted_alternative && wanted_alternative != tmp) - IWL_WARN(nic, + IWL_WARN(drv, "uCode alternative %d not available, choosing %d\n", tmp, wanted_alternative); - nic->fw.ucode_ver = le32_to_cpu(ucode->ver); + drv->fw.ucode_ver = le32_to_cpu(ucode->ver); build = le32_to_cpu(ucode->build); if (build) sprintf(buildstr, " build %u%s", build, - (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) + (drv->fw_index == UCODE_EXPERIMENTAL_INDEX) ? " (EXP)" : ""); else buildstr[0] = '\0'; - snprintf(nic->fw.fw_version, - sizeof(nic->fw.fw_version), + snprintf(drv->fw.fw_version, + sizeof(drv->fw.fw_version), "%u.%u.%u.%u%s", - IWL_UCODE_MAJOR(nic->fw.ucode_ver), - IWL_UCODE_MINOR(nic->fw.ucode_ver), - IWL_UCODE_API(nic->fw.ucode_ver), - IWL_UCODE_SERIAL(nic->fw.ucode_ver), + IWL_UCODE_MAJOR(drv->fw.ucode_ver), + IWL_UCODE_MINOR(drv->fw.ucode_ver), + IWL_UCODE_API(drv->fw.ucode_ver), + IWL_UCODE_SERIAL(drv->fw.ucode_ver), buildstr); data = ucode->data; @@ -329,7 +351,7 @@ static int iwl_parse_tlv_firmware(struct iwl_nic *nic, tlv_data = tlv->data; if (len < tlv_len) { - IWL_ERR(nic, "invalid TLV len: %zd/%u\n", + IWL_ERR(drv, "invalid TLV len: %zd/%u\n", len, tlv_len); return -EINVAL; } @@ -362,7 +384,7 @@ static int iwl_parse_tlv_firmware(struct iwl_nic *nic, pieces->init_data_size = tlv_len; break; case IWL_UCODE_TLV_BOOT: - IWL_ERR(nic, "Found unexpected BOOT ucode\n"); + IWL_ERR(drv, "Found unexpected BOOT ucode\n"); break; case IWL_UCODE_TLV_PROBE_MAX_LEN: if (tlv_len != sizeof(u32)) @@ -430,7 +452,7 @@ static int iwl_parse_tlv_firmware(struct iwl_nic *nic, case IWL_UCODE_TLV_ENHANCE_SENS_TBL: if (tlv_len) goto invalid_tlv_len; - nic->fw.enhance_sensitivity_table = true; + drv->fw.enhance_sensitivity_table = true; break; case IWL_UCODE_TLV_WOWLAN_INST: pieces->wowlan_inst = tlv_data; @@ -447,22 +469,22 @@ static int iwl_parse_tlv_firmware(struct iwl_nic *nic, le32_to_cpup((__le32 *)tlv_data); break; default: - IWL_DEBUG_INFO(nic, "unknown TLV: %d\n", tlv_type); + IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); break; } } if (len) { - IWL_ERR(nic, "invalid TLV after parsing: %zd\n", len); - iwl_print_hex_dump(nic, IWL_DL_FW, (u8 *)data, len); + IWL_ERR(drv, "invalid TLV after parsing: %zd\n", len); + iwl_print_hex_dump(drv, IWL_DL_FW, (u8 *)data, len); return -EINVAL; } return 0; invalid_tlv_len: - IWL_ERR(nic, "TLV %d has invalid size: %u\n", tlv_type, tlv_len); - iwl_print_hex_dump(nic, IWL_DL_FW, tlv_data, tlv_len); + IWL_ERR(drv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len); + iwl_print_hex_dump(drv, IWL_DL_FW, tlv_data, tlv_len); return -EINVAL; } @@ -475,9 +497,9 @@ static int iwl_parse_tlv_firmware(struct iwl_nic *nic, */ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) { - struct iwl_nic *nic = context; - const struct iwl_cfg *cfg = cfg(nic); - struct iwl_fw *fw = &nic->fw; + struct iwl_drv *drv = context; + const struct iwl_cfg *cfg = cfg(drv); + struct iwl_fw *fw = &drv->fw; struct iwl_ucode_header *ucode; int err; struct iwlagn_firmware_pieces pieces; @@ -496,19 +518,19 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) memset(&pieces, 0, sizeof(pieces)); if (!ucode_raw) { - if (nic->fw_index <= api_ok) - IWL_ERR(nic, + if (drv->fw_index <= api_ok) + IWL_ERR(drv, "request for firmware file '%s' failed.\n", - nic->firmware_name); + drv->firmware_name); goto try_again; } - IWL_DEBUG_INFO(nic, "Loaded firmware file '%s' (%zd bytes).\n", - nic->firmware_name, ucode_raw->size); + IWL_DEBUG_INFO(drv, "Loaded firmware file '%s' (%zd bytes).\n", + drv->firmware_name, ucode_raw->size); /* Make sure that we got at least the API version number */ if (ucode_raw->size < 4) { - IWL_ERR(nic, "File size way too small!\n"); + IWL_ERR(drv, "File size way too small!\n"); goto try_again; } @@ -516,15 +538,15 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) ucode = (struct iwl_ucode_header *)ucode_raw->data; if (ucode->ver) - err = iwl_parse_v1_v2_firmware(nic, ucode_raw, &pieces); + err = iwl_parse_v1_v2_firmware(drv, ucode_raw, &pieces); else - err = iwl_parse_tlv_firmware(nic, ucode_raw, &pieces, + err = iwl_parse_tlv_firmware(drv, ucode_raw, &pieces, &fw->ucode_capa); if (err) goto try_again; - api_ver = IWL_UCODE_API(nic->fw.ucode_ver); + api_ver = IWL_UCODE_API(drv->fw.ucode_ver); /* * api_ver should match the api version forming part of the @@ -532,9 +554,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) * on the API version read from firmware header from here on forward */ /* no api version check required for experimental uCode */ - if (nic->fw_index != UCODE_EXPERIMENTAL_INDEX) { + if (drv->fw_index != UCODE_EXPERIMENTAL_INDEX) { if (api_ver < api_min || api_ver > api_max) { - IWL_ERR(nic, + IWL_ERR(drv, "Driver unable to support your firmware API. " "Driver supports v%u, firmware is v%u.\n", api_max, api_ver); @@ -543,19 +565,19 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) if (api_ver < api_ok) { if (api_ok != api_max) - IWL_ERR(nic, "Firmware has old API version, " + IWL_ERR(drv, "Firmware has old API version, " "expected v%u through v%u, got v%u.\n", api_ok, api_max, api_ver); else - IWL_ERR(nic, "Firmware has old API version, " + IWL_ERR(drv, "Firmware has old API version, " "expected v%u, got v%u.\n", api_max, api_ver); - IWL_ERR(nic, "New firmware can be obtained from " + IWL_ERR(drv, "New firmware can be obtained from " "http://www.intellinuxwireless.org/.\n"); } } - IWL_INFO(nic, "loaded firmware version %s", nic->fw.fw_version); + IWL_INFO(drv, "loaded firmware version %s", drv->fw.fw_version); /* * For any of the failures below (before allocating pci memory) @@ -563,38 +585,38 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) * user just got a corrupted version of the latest API. */ - IWL_DEBUG_INFO(nic, "f/w package hdr ucode version raw = 0x%x\n", - nic->fw.ucode_ver); - IWL_DEBUG_INFO(nic, "f/w package hdr runtime inst size = %Zd\n", + IWL_DEBUG_INFO(drv, "f/w package hdr ucode version raw = 0x%x\n", + drv->fw.ucode_ver); + IWL_DEBUG_INFO(drv, "f/w package hdr runtime inst size = %Zd\n", pieces.inst_size); - IWL_DEBUG_INFO(nic, "f/w package hdr runtime data size = %Zd\n", + IWL_DEBUG_INFO(drv, "f/w package hdr runtime data size = %Zd\n", pieces.data_size); - IWL_DEBUG_INFO(nic, "f/w package hdr init inst size = %Zd\n", + IWL_DEBUG_INFO(drv, "f/w package hdr init inst size = %Zd\n", pieces.init_size); - IWL_DEBUG_INFO(nic, "f/w package hdr init data size = %Zd\n", + IWL_DEBUG_INFO(drv, "f/w package hdr init data size = %Zd\n", pieces.init_data_size); /* Verify that uCode images will fit in card's SRAM */ if (pieces.inst_size > cfg->max_inst_size) { - IWL_ERR(nic, "uCode instr len %Zd too large to fit in\n", + IWL_ERR(drv, "uCode instr len %Zd too large to fit in\n", pieces.inst_size); goto try_again; } if (pieces.data_size > cfg->max_data_size) { - IWL_ERR(nic, "uCode data len %Zd too large to fit in\n", + IWL_ERR(drv, "uCode data len %Zd too large to fit in\n", pieces.data_size); goto try_again; } if (pieces.init_size > cfg->max_inst_size) { - IWL_ERR(nic, "uCode init instr len %Zd too large to fit in\n", + IWL_ERR(drv, "uCode init instr len %Zd too large to fit in\n", pieces.init_size); goto try_again; } if (pieces.init_data_size > cfg->max_data_size) { - IWL_ERR(nic, "uCode init data len %Zd too large to fit in\n", + IWL_ERR(drv, "uCode init data len %Zd too large to fit in\n", pieces.init_data_size); goto try_again; } @@ -604,34 +626,34 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* Runtime instructions and 2 copies of data: * 1) unmodified from disk * 2) backup cache for save/restore during power-downs */ - if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.code, + if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_rt.code, pieces.inst, pieces.inst_size)) goto err_pci_alloc; - if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.data, + if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_rt.data, pieces.data, pieces.data_size)) goto err_pci_alloc; /* Initialization instructions and data */ if (pieces.init_size && pieces.init_data_size) { - if (iwl_alloc_fw_desc(nic, - &nic->fw.ucode_init.code, + if (iwl_alloc_fw_desc(drv, + &drv->fw.ucode_init.code, pieces.init, pieces.init_size)) goto err_pci_alloc; - if (iwl_alloc_fw_desc(nic, - &nic->fw.ucode_init.data, + if (iwl_alloc_fw_desc(drv, + &drv->fw.ucode_init.data, pieces.init_data, pieces.init_data_size)) goto err_pci_alloc; } /* WoWLAN instructions and data */ if (pieces.wowlan_inst_size && pieces.wowlan_data_size) { - if (iwl_alloc_fw_desc(nic, - &nic->fw.ucode_wowlan.code, + if (iwl_alloc_fw_desc(drv, + &drv->fw.ucode_wowlan.code, pieces.wowlan_inst, pieces.wowlan_inst_size)) goto err_pci_alloc; - if (iwl_alloc_fw_desc(nic, - &nic->fw.ucode_wowlan.data, + if (iwl_alloc_fw_desc(drv, + &drv->fw.ucode_wowlan.data, pieces.wowlan_data, pieces.wowlan_data_size)) goto err_pci_alloc; @@ -670,11 +692,11 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* We have our copies now, allow OS release its copies */ release_firmware(ucode_raw); - complete(&nic->request_firmware_complete); + complete(&drv->request_firmware_complete); - nic->op_mode = iwl_dvm_ops.start(nic->shrd->trans, &nic->fw); + drv->op_mode = iwl_dvm_ops.start(drv->shrd->trans, &drv->fw); - if (!nic->op_mode) + if (!drv->op_mode) goto out_unbind; return; @@ -682,43 +704,43 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) try_again: /* try next, if any */ release_firmware(ucode_raw); - if (iwl_request_firmware(nic, false)) + if (iwl_request_firmware(drv, false)) goto out_unbind; return; err_pci_alloc: - IWL_ERR(nic, "failed to allocate pci memory\n"); - iwl_dealloc_ucode(nic); + IWL_ERR(drv, "failed to allocate pci memory\n"); + iwl_dealloc_ucode(drv); release_firmware(ucode_raw); out_unbind: - complete(&nic->request_firmware_complete); - device_release_driver(trans(nic)->dev); + complete(&drv->request_firmware_complete); + device_release_driver(trans(drv)->dev); } int iwl_drv_start(struct iwl_shared *shrd, struct iwl_trans *trans, const struct iwl_cfg *cfg) { - struct iwl_nic *nic; + struct iwl_drv *drv; int ret; shrd->cfg = cfg; - nic = kzalloc(sizeof(*nic), GFP_KERNEL); - if (!nic) { - dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_nic"); + drv = kzalloc(sizeof(*drv), GFP_KERNEL); + if (!drv) { + dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_drv"); return -ENOMEM; } - nic->shrd = shrd; - shrd->nic = nic; + drv->shrd = shrd; + shrd->drv = drv; - init_completion(&nic->request_firmware_complete); + init_completion(&drv->request_firmware_complete); - ret = iwl_request_firmware(nic, true); + ret = iwl_request_firmware(drv, true); if (ret) { dev_printk(KERN_ERR, trans->dev, "Couldn't request the fw"); - kfree(nic); - shrd->nic = NULL; + kfree(drv); + shrd->drv = NULL; } return ret; @@ -726,16 +748,16 @@ int iwl_drv_start(struct iwl_shared *shrd, void iwl_drv_stop(struct iwl_shared *shrd) { - struct iwl_nic *nic = shrd->nic; + struct iwl_drv *drv = shrd->drv; - wait_for_completion(&nic->request_firmware_complete); + wait_for_completion(&drv->request_firmware_complete); /* op_mode can be NULL if its start failed */ - if (nic->op_mode) - iwl_op_mode_stop(nic->op_mode); + if (drv->op_mode) + iwl_op_mode_stop(drv->op_mode); - iwl_dealloc_ucode(nic); + iwl_dealloc_ucode(drv); - kfree(nic); - shrd->nic = NULL; + kfree(drv); + shrd->drv = NULL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 3bcd2a766074..3c9a8faba4e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -43,7 +43,6 @@ #include #include "iwl-eeprom.h" -#include "iwl-wifi.h" #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 3754c35a1a50..bb34766609db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -419,7 +419,7 @@ struct iwl_shared { const struct iwl_cfg *cfg; struct iwl_priv *priv; struct iwl_trans *trans; - void *nic; + void *drv; struct iwl_hw_params hw_params; const struct iwl_fw *fw; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index fd25dd1d62e0..c1ecf0fba372 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -70,7 +70,6 @@ #include #include -#include "iwl-wifi.h" #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-debug.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 69e4544afe24..c3c2de3b3169 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -34,7 +34,6 @@ #include "iwl-core.h" #include "iwl-io.h" #include "iwl-trans-pcie-int.h" -#include "iwl-wifi.h" #include "iwl-op-mode.h" #ifdef CONFIG_IWLWIFI_IDI diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index f78b1552ef7c..3747edb7c292 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -31,7 +31,6 @@ #include #include -#include "iwl-wifi.h" #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-wifi.h b/drivers/net/wireless/iwlwifi/iwl-wifi.h deleted file mode 100644 index a71624d3ea23..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-wifi.h +++ /dev/null @@ -1,88 +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) 2008 - 2012 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef __iwl_wifi_h__ -#define __iwl_wifi_h__ - -#include "iwl-shared.h" - -/** - * struct iwl_nic - nic common data - * @fw: the iwl_fw structure - * @shrd: pointer to common shared structure - * @op_mode: the running op_mode - * @fw_index: firmware revision to try loading - * @firmware_name: composite filename of ucode file to load - * @request_firmware_complete: the firmware has been obtained from user space - */ -struct iwl_nic { - struct iwl_fw fw; - - struct iwl_shared *shrd; - struct iwl_op_mode *op_mode; - - int fw_index; /* firmware we're trying to load */ - char firmware_name[25]; /* name of firmware file to load */ - - struct completion request_firmware_complete; -}; -#endif /* __iwl_wifi_h__ */ -- cgit v1.2.3-70-g09d2 From e10a0533a9172471b52bd9512838d766420a3baf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:39 -0800 Subject: iwlwifi: add wrappers for command sending Add wrappers to send commands from the DVM op-mode (which essentially consists of the current driver). This will allow us to move specific sanity checks there. Also, this removes iwl_trans_send_cmd_pdu() since that can now be taken care of in the DVM-specific wrapper. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 1 - drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 38 ++++++++++---- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 16 +++--- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 ++-- drivers/net/wireless/iwlwifi/iwl-agn.h | 5 ++ drivers/net/wireless/iwlwifi/iwl-core.c | 10 ++-- drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 4 +- drivers/net/wireless/iwlwifi/iwl-testmode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans.c | 77 ---------------------------- drivers/net/wireless/iwlwifi/iwl-trans.h | 3 -- drivers/net/wireless/iwlwifi/iwl-ucode.c | 8 +-- 17 files changed, 70 insertions(+), 128 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-trans.c (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index afa0bb8f3245..f2a903d01aa9 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -14,7 +14,6 @@ iwlwifi-objs += iwl-1000.o iwlwifi-objs += iwl-2000.o iwlwifi-objs += iwl-pci.o iwlwifi-objs += iwl-drv.o -iwlwifi-objs += iwl-trans.o iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index dff75a09eb48..aebdfd7e01a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -281,7 +281,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return iwl_trans_send_cmd(trans(priv), &hcmd); + return iwl_dvm_send_cmd(priv, &hcmd); } static struct iwl_lib_ops iwl5000_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index ef896630625d..150bef078609 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -232,7 +232,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return iwl_trans_send_cmd(trans(priv), &hcmd); + return iwl_dvm_send_cmd(priv, &hcmd); } static struct iwl_lib_ops iwl6000_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 588d107b82f4..579679edd5f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -104,7 +104,7 @@ int iwl_send_calib_results(struct iwl_priv *priv) hcmd.len[0] = res->cmd_len; hcmd.data[0] = &res->hdr; hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; - ret = iwl_trans_send_cmd(trans(priv), &hcmd); + ret = iwl_dvm_send_cmd(priv, &hcmd); if (ret) { IWL_ERR(priv, "Error %d on calib cmd %d\n", ret, res->hdr.op_code); @@ -500,7 +500,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), sizeof(u16)*HD_TABLE_SIZE); - return iwl_trans_send_cmd(trans(priv), &cmd_out); + return iwl_dvm_send_cmd(priv, &cmd_out); } /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ @@ -589,7 +589,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]), sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES); - return iwl_trans_send_cmd(trans(priv), &cmd_out); + return iwl_dvm_send_cmd(priv, &cmd_out); } void iwl_init_sensitivity(struct iwl_priv *priv) @@ -930,7 +930,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, priv->phy_calib_chain_noise_gain_cmd); cmd.delta_gain_1 = data->delta_gain_code[1]; cmd.delta_gain_2 = data->delta_gain_code[2]; - iwl_trans_send_cmd_pdu(trans(priv), REPLY_PHY_CALIBRATION_CMD, + iwl_dvm_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, CMD_ASYNC, sizeof(cmd), &cmd); data->radio_write = 1; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index b06283282283..4c777dfc0db0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -81,7 +81,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) else tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; - return iwl_trans_send_cmd_pdu(trans(priv), tx_ant_cfg_cmd, CMD_SYNC, + return iwl_dvm_send_cmd_pdu(priv, tx_ant_cfg_cmd, CMD_SYNC, sizeof(tx_power_cmd), &tx_power_cmd); } @@ -241,7 +241,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) flush_cmd.fifo_control); flush_cmd.flush_control = cpu_to_le16(flush_control); - return iwl_trans_send_cmd(trans(priv), &cmd); + return iwl_dvm_send_cmd(priv, &cmd); } void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) @@ -435,12 +435,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) if (cfg(priv)->bt_params->bt_session_2) { memcpy(&bt_cmd_2000.basic, &basic, sizeof(basic)); - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000); } else { memcpy(&bt_cmd_6000.basic, &basic, sizeof(basic)); - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000); } if (ret) @@ -1115,7 +1115,7 @@ int iwlagn_send_patterns(struct iwl_priv *priv, } cmd.data[0] = pattern_cmd; - err = iwl_trans_send_cmd(trans(priv), &cmd); + err = iwl_dvm_send_cmd(priv, &cmd); kfree(pattern_cmd); return err; } @@ -1241,13 +1241,13 @@ int iwlagn_suspend(struct iwl_priv *priv, .len[0] = sizeof(key_data.rsc_tsc), }; - ret = iwl_trans_send_cmd(trans(priv), &rsc_tsc_cmd); + ret = iwl_dvm_send_cmd(priv, &rsc_tsc_cmd); if (ret) goto out; } if (key_data.use_tkip) { - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_TKIP_PARAMS, CMD_SYNC, sizeof(tkip_cmd), &tkip_cmd); @@ -1263,7 +1263,7 @@ int iwlagn_suspend(struct iwl_priv *priv, kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN); kek_kck_cmd.replay_ctr = priv->replay_ctr; - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_KEK_KCK_MATERIAL, CMD_SYNC, sizeof(kek_kck_cmd), &kek_kck_cmd); @@ -1272,12 +1272,12 @@ int iwlagn_suspend(struct iwl_priv *priv, } } - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_D3_CONFIG, CMD_SYNC, + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_D3_CONFIG, CMD_SYNC, sizeof(d3_cfg_cmd), &d3_cfg_cmd); if (ret) goto out; - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER, + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_WAKEUP_FILTER, CMD_SYNC, sizeof(wakeup_filter_cmd), &wakeup_filter_cmd); if (ret) @@ -1289,3 +1289,21 @@ int iwlagn_suspend(struct iwl_priv *priv, return ret; } #endif + +int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +{ + return iwl_trans_send_cmd(trans(priv), cmd); +} + +int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id, + u32 flags, u16 len, const void *data) +{ + struct iwl_host_cmd cmd = { + .id = id, + .len = { len, }, + .data = { data, }, + .flags = flags, + }; + + return iwl_dvm_send_cmd(priv, &cmd); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index e806ad82e7e3..53114db9c9c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -39,7 +39,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, + ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -66,7 +66,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->dev_type = RXON_DEV_TYPE_P2P; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, + ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -92,7 +92,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, + ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -121,7 +121,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv, ctx->qos_data.qos_active, ctx->qos_data.def_qos_parm.qos_flags); - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->qos_cmd, CMD_SYNC, + ret = iwl_dvm_send_cmd_pdu(priv, ctx->qos_cmd, CMD_SYNC, sizeof(struct iwl_qosparam_cmd), &ctx->qos_data.def_qos_parm); if (ret) @@ -180,7 +180,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, ctx->staging.ofdm_ht_triple_stream_basic_rates; rxon_assoc.acquisition_data = ctx->staging.acquisition_data; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_assoc_cmd, + ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_assoc_cmd, CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc); return ret; } @@ -266,7 +266,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, * Associated RXON doesn't clear the station table in uCode, * so we don't need to restore stations etc. after this. */ - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, + ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC, sizeof(struct iwl_rxon_cmd), &ctx->staging); if (ret) { IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); @@ -385,7 +385,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) cmd.slots[0].width = cpu_to_le16(slot0); cmd.slots[1].width = cpu_to_le16(slot1); - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WIPAN_PARAMS, CMD_SYNC, + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, CMD_SYNC, sizeof(cmd), &cmd); if (ret) IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); @@ -771,7 +771,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, priv->phy_calib_chain_noise_reset_cmd); - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index ca080265a829..73a25f48cd53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -153,7 +153,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, might_sleep(); } - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = iwl_dvm_send_cmd(priv, &cmd); if (ret || (flags & CMD_ASYNC)) return ret; @@ -447,7 +447,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, cmd.flags |= CMD_WANT_SKB; - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = iwl_dvm_send_cmd(priv, &cmd); if (ret) return ret; @@ -785,7 +785,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, return -EINVAL; if (is_lq_table_valid(priv, ctx, lq)) - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = iwl_dvm_send_cmd(priv, &cmd); else ret = -EINVAL; @@ -970,7 +970,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, cmd.len[0] = cmd_size; if (not_empty || send_if_empty) - return iwl_trans_send_cmd(trans(priv), &cmd); + return iwl_dvm_send_cmd(priv, &cmd); else return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index cdfe76151072..3f59a773b3e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -197,7 +197,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) cmd.data[1] = priv->beacon_skb->data; cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; - return iwl_trans_send_cmd(trans(priv), &cmd); + return iwl_dvm_send_cmd(priv, &cmd); } static void iwl_bg_beacon_update(struct work_struct *work) @@ -563,7 +563,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) adv_cmd.critical_temperature_exit = cpu_to_le32(hw_params(priv).ct_kill_exit_threshold); - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(adv_cmd), &adv_cmd); if (ret) @@ -578,7 +578,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) cmd.critical_temperature_R = cpu_to_le32(hw_params(priv).ct_kill_threshold); - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) @@ -604,7 +604,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_RT_CFG_ALL; calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg); - return iwl_trans_send_cmd(trans(priv), &cmd); + return iwl_dvm_send_cmd(priv, &cmd); } @@ -616,7 +616,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) { IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); - return iwl_trans_send_cmd_pdu(trans(priv), + return iwl_dvm_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, CMD_SYNC, sizeof(struct iwl_tx_ant_config_cmd), diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index f55243828698..dfd86f288dee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -96,6 +96,11 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, const struct iwl_ucode_capabilities *capa); void iwlagn_mac_unregister(struct iwl_priv *priv); +/* commands */ +int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); +int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id, + u32 flags, u16 len, const void *data); + /* RXON */ int iwlagn_set_pan_params(struct iwl_priv *priv); int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9ae17c3bb885..aaea51ee4185 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -369,7 +369,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) le32_to_cpu(ctx->timing.beacon_init_val), le16_to_cpu(ctx->timing.atim_window)); - return iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_timing_cmd, + return iwl_dvm_send_cmd_pdu(priv, ctx->rxon_timing_cmd, CMD_SYNC, sizeof(ctx->timing), &ctx->timing); } @@ -958,7 +958,7 @@ void iwl_send_bt_config(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "BT coex %s\n", (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); - if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, + if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd)) IWL_ERR(priv, "failed to send BT Coex Config\n"); } @@ -971,12 +971,12 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) }; if (flags & CMD_ASYNC) - return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD, + return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, CMD_ASYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); else - return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD, + return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, CMD_SYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); @@ -1300,7 +1300,7 @@ int iwl_cmd_echo_test(struct iwl_priv *priv) .flags = CMD_SYNC, }; - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = iwl_dvm_send_cmd(priv, &cmd); if (ret) IWL_ERR(priv, "echo testing fail: 0X%x\n", ret); else diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 5c7741f07aa0..f2f706f084a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -112,7 +112,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) iwl_write32(trans(priv), CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); - return iwl_trans_send_cmd(trans(priv), &cmd); + return iwl_dvm_send_cmd(priv, &cmd); } /* Set led pattern command */ diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 1ef3c4da1605..46ca82062c2e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -336,7 +336,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) le32_to_cpu(cmd->sleep_interval[3]), le32_to_cpu(cmd->sleep_interval[4])); - return iwl_trans_send_cmd_pdu(trans(priv), POWER_TABLE_CMD, CMD_SYNC, + return iwl_dvm_send_cmd_pdu(priv, POWER_TABLE_CMD, CMD_SYNC, sizeof(struct iwl_powertable_cmd), cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 28899dabe6fb..dcba74883307 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -72,7 +72,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) test_bit(STATUS_FW_ERROR, &priv->shrd->status)) return -EIO; - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = iwl_dvm_send_cmd(priv, &cmd); if (ret) return ret; @@ -887,7 +887,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) if (ret) return ret; - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = iwl_dvm_send_cmd(priv, &cmd); if (ret) { clear_bit(STATUS_SCAN_HW, &priv->shrd->status); iwlagn_set_pan_params(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index c1ecf0fba372..f26765b3a661 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -282,7 +282,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) IWL_DEBUG_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," " len %d\n", cmd.id, cmd.flags, cmd.len[0]); - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = iwl_dvm_send_cmd(priv, &cmd); if (ret) { IWL_ERR(priv, "Failed to send hcmd\n"); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c deleted file mode 100644 index 506c062343b2..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ /dev/null @@ -1,77 +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) 2007 - 2012 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#include "iwl-trans.h" - -int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, - u32 flags, u16 len, const void *data) -{ - struct iwl_host_cmd cmd = { - .id = id, - .len = { len, }, - .data = { data, }, - .flags = flags, - }; - - return iwl_trans_send_cmd(trans, &cmd); -} diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index ec5249c8a7f4..a8d476a44c58 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -443,9 +443,6 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, return trans->ops->send_cmd(trans, cmd); } -int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, - u32 flags, u16 len, const void *data); - static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx, u8 sta_id, u8 tid) diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 3747edb7c292..1cbe8e9926f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -179,7 +179,7 @@ static int iwl_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_dvm_send_cmd(priv, &cmd); } int iwlagn_rx_calib_result(struct iwl_priv *priv, @@ -260,7 +260,7 @@ static int iwl_send_wimax_coex(struct iwl_priv *priv) /* coexistence is disabled */ memset(&coex_cmd, 0, sizeof(coex_cmd)); } - return iwl_trans_send_cmd_pdu(trans(priv), + return iwl_dvm_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD, CMD_SYNC, sizeof(coex_cmd), &coex_cmd); } @@ -293,7 +293,7 @@ void iwl_send_prio_tbl(struct iwl_priv *priv) memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl, sizeof(iwl_bt_prio_tbl)); - if (iwl_trans_send_cmd_pdu(trans(priv), + if (iwl_dvm_send_cmd_pdu(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"); @@ -306,7 +306,7 @@ int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) env_cmd.action = action; env_cmd.type = type; - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, CMD_SYNC, sizeof(env_cmd), &env_cmd); if (ret) -- cgit v1.2.3-70-g09d2 From 721c32f72d8007dc0148ee88c046a4ade794a7b7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:40 -0800 Subject: iwlwifi: move RF/CT kill check to command wrapper Currently, we cannot send any commands when the uCode is in RF or CT kill, but that will not be true for all new uCode versions, so we need to move the check into the uCode specific code. Also remove the duplicate rfkill check. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 19 ++++--------------- 2 files changed, 10 insertions(+), 15 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 4c777dfc0db0..11f24110d3fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1292,6 +1292,12 @@ int iwlagn_suspend(struct iwl_priv *priv, int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { + if (iwl_is_rfkill(priv->shrd) || iwl_is_ctkill(priv->shrd)) { + IWL_WARN(priv, "Not sending command - %s KILL\n", + iwl_is_rfkill(priv->shrd) ? "RF" : "CT"); + return -EIO; + } + return iwl_trans_send_cmd(trans(priv), cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 0164154f9c97..c85975e63d75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -721,12 +721,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE)) return -EINVAL; - if (iwl_is_rfkill(trans->shrd) || iwl_is_ctkill(trans->shrd)) { - IWL_WARN(trans, "Not sending command - %s KILL\n", - iwl_is_rfkill(trans->shrd) ? "RF" : "CT"); - return -EIO; - } - spin_lock_bh(&txq->lock); if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { @@ -965,7 +959,7 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) ret = iwl_enqueue_hcmd(trans, cmd); if (ret < 0) { - IWL_DEBUG_QUIET_RFKILL(trans, + IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; @@ -984,11 +978,6 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); - if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) { - IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n", - get_cmd_string(cmd->id)); - return -ECANCELED; - } if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) { IWL_ERR(trans, "Command %s failed: FW Error\n", get_cmd_string(cmd->id)); @@ -1002,7 +991,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) if (cmd_idx < 0) { ret = cmd_idx; clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); - IWL_DEBUG_QUIET_RFKILL(trans, + IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; @@ -1017,12 +1006,12 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) &trans_pcie->txq[trans->shrd->cmd_queue]; struct iwl_queue *q = &txq->q; - IWL_DEBUG_QUIET_RFKILL(trans, + IWL_ERR(trans, "Error sending %s: time out after %dms.\n", get_cmd_string(cmd->id), jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); - IWL_DEBUG_QUIET_RFKILL(trans, + IWL_ERR(trans, "Current CMD queue read_ptr %d write_ptr %d\n", q->read_ptr, q->write_ptr); -- cgit v1.2.3-70-g09d2 From 2cc39c94c15ba1d5f6f71ab73f3369f9c17856ad Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:41 -0800 Subject: iwlwifi: move lockdep assertion into DVM The fact that the mutex must be held is an implementation detail of DVM, but something has to ensure that no two synchronous cmds are submitted concurrently. Move the lockdep assertion into the DVM-specific code, but also make the transport abort if there are two concurrently commands. The assertion is much more useful though as the transport check can only catch it when it actually happens, while the assertion makes sure it can't possibly happen. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 8 ++++++++ drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 11 ++++++++--- 2 files changed, 16 insertions(+), 3 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 11f24110d3fe..238f824c2f3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1298,6 +1298,14 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return -EIO; } + /* + * Synchronous commands from this op-mode must hold + * the mutex, this ensures we don't try to send two + * (or more) synchronous commands at a time. + */ + if (cmd->flags & CMD_SYNC) + lockdep_assert_held(&priv->shrd->mutex); + return iwl_trans_send_cmd(trans(priv), cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index c85975e63d75..ca4ceeacc989 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -973,8 +973,6 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) int cmd_idx; int ret; - lockdep_assert_held(&trans->shrd->mutex); - IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); @@ -983,7 +981,14 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) get_cmd_string(cmd->id)); return -EIO; } - set_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); + + if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE, + &trans->shrd->status))) { + IWL_ERR(trans, "Command %s: a command is already active!\n", + get_cmd_string(cmd->id)); + return -EIO; + } + IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->id)); -- cgit v1.2.3-70-g09d2 From b1eea297d6b522b801c95b60b1e64fb61228c6c7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:42 -0800 Subject: iwlwifi: move mutex out of shared Now the mutex no longer needs to be shared, so move it into iwl_priv. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 20 +++---- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 20 +++---- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 18 +++---- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 32 +++++------ drivers/net/wireless/iwlwifi/iwl-core.c | 4 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 12 ++--- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 + drivers/net/wireless/iwlwifi/iwl-mac80211.c | 82 ++++++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 32 +++++------ drivers/net/wireless/iwlwifi/iwl-shared.h | 4 -- drivers/net/wireless/iwlwifi/iwl-testmode.c | 8 +-- drivers/net/wireless/iwlwifi/iwl-ucode.c | 2 +- 14 files changed, 122 insertions(+), 124 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 238f824c2f3e..90f1f8a506f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -246,7 +246,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) { - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); ieee80211_stop_queues(priv->hw); if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) { IWL_ERR(priv, "flush request fail\n"); @@ -256,7 +256,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) iwl_trans_wait_tx_queue_empty(trans(priv)); done: ieee80211_wake_queues(priv->hw); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /* @@ -453,7 +453,7 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena) struct iwl_rxon_context *ctx, *found_ctx = NULL; bool found_ap = false; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* Check whether AP or GO mode is active. */ if (rssi_ena) { @@ -566,7 +566,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) break; } - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); /* * We can not send command to firmware while scanning. When the scan @@ -594,7 +594,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) */ iwlagn_bt_coex_rssi_monitor(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /* @@ -969,7 +969,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, u16 p1k[IWLAGN_P1K_SIZE]; int ret, i; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) && @@ -1075,7 +1075,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } int iwlagn_send_patterns(struct iwl_priv *priv, @@ -1222,11 +1222,11 @@ int iwlagn_suspend(struct iwl_priv *priv, * constraints. Since we're in the suspend path * that isn't really a problem though. */ - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); ieee80211_iter_keys(priv->hw, ctx->vif, iwlagn_wowlan_program_keys, &key_data); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (key_data.error) { ret = -EIO; goto out; @@ -1304,7 +1304,7 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) * (or more) synchronous commands at a time. */ if (cmd->flags & CMD_SYNC) - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); return iwl_trans_send_cmd(trans(priv), cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 53114db9c9c3..2c5e7ec697e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -131,7 +131,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv, static int iwlagn_update_beacon(struct iwl_priv *priv, struct ieee80211_vif *vif) { - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif); @@ -313,7 +313,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; @@ -418,7 +418,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (!iwl_is_alive(priv->shrd)) return -EBUSY; @@ -549,7 +549,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) IWL_DEBUG_MAC80211(priv, "enter: changed %#x", changed); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) { IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); @@ -650,7 +650,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) iwlagn_commit_rxon(priv, ctx); } out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return ret; @@ -667,7 +667,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *ht_cap; bool need_multiple; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); switch (vif->type) { case NL80211_IFTYPE_STATION: @@ -792,17 +792,17 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, int ret; bool force = false; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (unlikely(!iwl_is_ready(priv->shrd))) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return; } if (unlikely(!ctx->vif)) { IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n"); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return; } @@ -931,7 +931,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, IWL_ERR(priv, "Error sending IBSS beacon\n"); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } void iwlagn_post_scan(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 73a25f48cd53..14fbdecccd26 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -811,7 +811,7 @@ void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u32 rate_flags = 0; __le32 rate_n_flags; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); memset(link_cmd, 0, sizeof(*link_cmd)); @@ -978,7 +978,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, int iwl_restore_default_wep_keys(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); return iwl_send_static_wepkey_cmd(priv, ctx, false); } @@ -989,7 +989,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", keyconf->keyidx); @@ -1014,7 +1014,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (keyconf->keylen != WEP_KEY_LEN_128 && keyconf->keylen != WEP_KEY_LEN_64) { @@ -1166,7 +1166,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, if (sta_id == IWL_INVALID_STATION) return 0; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); ctx->key_mapping_keys--; @@ -1206,7 +1206,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, if (sta_id == IWL_INVALID_STATION) return -EINVAL; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv); if (keyconf->hw_key_idx == WEP_INVALID_OFFSET) @@ -1340,7 +1340,7 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) { struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* Remove "disable" flag, to enable Tx for this TID */ spin_lock_bh(&priv->sta_lock); @@ -1359,7 +1359,7 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, int sta_id; struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) @@ -1383,7 +1383,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, int sta_id; struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 56d7c0e38163..85fe590ee721 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -310,7 +310,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) tt->tt_power_mode = IWL_POWER_INDEX_5; break; } - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (old_state == IWL_TI_CT_KILL) clear_bit(STATUS_CT_KILL, &priv->shrd->status); if (tt->state != IWL_TI_CT_KILL && @@ -341,7 +341,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) IWL_DEBUG_TEMP(priv, "Power Index change to %u\n", tt->tt_power_mode); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } } @@ -451,7 +451,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) * in case get disabled before */ iwl_set_rxon_ht(priv, &priv->current_ht_config); } - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (old_state == IWL_TI_CT_KILL) clear_bit(STATUS_CT_KILL, &priv->shrd->status); if (tt->state != IWL_TI_CT_KILL && @@ -486,7 +486,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) iwl_perform_ct_kill_task(priv, false); } } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3f59a773b3e0..863c27e20dbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -132,7 +132,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) * beacon contents. */ - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (!priv->beacon_ctx) { IWL_ERR(priv, "trying to build beacon w/o beacon context!\n"); @@ -206,7 +206,7 @@ static void iwl_bg_beacon_update(struct work_struct *work) container_of(work, struct iwl_priv, beacon_update); struct sk_buff *beacon; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (!priv->beacon_ctx) { IWL_ERR(priv, "updating beacon w/o beacon context!\n"); goto out; @@ -236,7 +236,7 @@ static void iwl_bg_beacon_update(struct work_struct *work) iwlagn_send_beacon_cmd(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static void iwl_bg_bt_runtime_config(struct work_struct *work) @@ -259,7 +259,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) container_of(work, struct iwl_priv, bt_full_concurrency); struct iwl_rxon_context *ctx; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) goto out; @@ -283,7 +283,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) iwlagn_send_advance_bt_config(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /** @@ -774,7 +774,7 @@ void iwl_down(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); iwl_scan_cancel_timeout(priv, 200); @@ -844,11 +844,11 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, run_time_calib_work); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || test_bit(STATUS_SCANNING, &priv->shrd->status)) { - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return; } @@ -857,7 +857,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) iwl_sensitivity_calibration(priv); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } void iwlagn_prepare_restart(struct iwl_priv *priv) @@ -869,7 +869,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv) u8 bt_status; bool bt_is_sco; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); for_each_context(priv, ctx) ctx->vif = NULL; @@ -907,9 +907,9 @@ static void iwl_bg_restart(struct work_struct *data) return; if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) { - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwlagn_prepare_restart(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); iwl_cancel_deferred_work(priv); ieee80211_restart_hw(priv->hw); } else { @@ -924,7 +924,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv) { struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (!priv->hw_roc_setup) return; @@ -947,9 +947,9 @@ static void iwlagn_disable_roc_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, hw_roc_disable_work.work); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwlagn_disable_roc(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /***************************************************************************** @@ -1036,7 +1036,7 @@ static int iwl_init_drv(struct iwl_priv *priv) spin_lock_init(&priv->sta_lock); - mutex_init(&priv->shrd->mutex); + mutex_init(&priv->mutex); INIT_LIST_HEAD(&priv->calib_results); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index aaea51ee4185..387eeeedb41d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -316,7 +316,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) conf = &priv->hw->conf; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd)); @@ -892,7 +892,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) bool defer; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (priv->tx_power_user_lmt == tx_power && !force) return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index bc3e267ed4c0..b9b6d628f59a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -761,9 +761,9 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, priv->power_data.debug_sleep_level_override = value; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_power_update_mode(priv, true); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return count; } @@ -1708,9 +1708,9 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, return -EINVAL; /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); ret = iwl_send_statistics_request(priv, CMD_SYNC, false); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); if (ret) { IWL_ERR(priv, @@ -2106,9 +2106,9 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, return -EFAULT; /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_send_statistics_request(priv, CMD_SYNC, true); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return count; } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 4def9f961891..73acbab6c248 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include "iwl-eeprom.h" @@ -718,6 +719,7 @@ struct iwl_priv { const struct iwl_fw *fw; spinlock_t sta_lock; + struct mutex mutex; /* ieee device used by generic ieee processing code */ struct ieee80211_hw *hw; diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 3c9a8faba4e6..30861765b512 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -261,7 +261,7 @@ static int __iwl_up(struct iwl_priv *priv) struct iwl_rxon_context *ctx; int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); @@ -310,9 +310,9 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "enter\n"); /* we should be verifying the device is ready to be opened */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); ret = __iwl_up(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); if (ret) return ret; @@ -340,9 +340,9 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) priv->is_open = 0; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_down(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); iwl_cancel_deferred_work(priv); @@ -367,7 +367,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, return; IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif) goto out; @@ -379,7 +379,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, priv->have_rekey_data = true; out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -396,7 +396,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, return -EINVAL; IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); /* Don't attempt WoWLAN when not associated, tear down instead. */ if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION || @@ -420,7 +420,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, iwlagn_prepare_restart(priv); ieee80211_restart_hw(priv->hw); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return ret; @@ -436,7 +436,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) int ret = -EIO; IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); @@ -481,7 +481,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) iwl_connection_init_rx_config(priv, ctx); iwlagn_set_rxon_chain(priv, ctx); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); ieee80211_resume_disconnect(vif); @@ -559,7 +559,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET) return 0; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 100); BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT); @@ -610,7 +610,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ret = -EINVAL; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return ret; @@ -633,7 +633,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, return -EACCES; IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); switch (action) { case IEEE80211_AMPDU_RX_START: @@ -675,7 +675,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, ret = iwlagn_tx_agg_oper(priv, vif, sta, tid, buf_size); break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return ret; } @@ -746,7 +746,7 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "station %pM state change %d->%d\n", sta->addr, old_state, new_state); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (vif->type == NL80211_IFTYPE_STATION) { if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) @@ -807,7 +807,7 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, if (iwl_is_rfkill(priv->shrd)) ret = 0; - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return ret; @@ -834,7 +834,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (iwl_is_rfkill(priv->shrd)) goto out; @@ -890,7 +890,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, } out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -920,7 +920,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, #undef CHK - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); for_each_context(priv, ctx) { ctx->staging.filter_flags &= ~filter_nand; @@ -932,7 +932,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, */ } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); /* * Receiving all multicast frames is always enabled by the @@ -948,7 +948,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "enter\n"); if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { @@ -974,7 +974,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); iwl_trans_wait_tx_queue_empty(trans(priv)); done: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -994,7 +994,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, return -EOPNOTSUPP; IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { err = -EBUSY; @@ -1065,7 +1065,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, iwlagn_disable_roc(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return err; @@ -1079,10 +1079,10 @@ static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) return -EOPNOTSUPP; IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, priv->hw_roc_duration); iwlagn_disable_roc(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; @@ -1094,7 +1094,7 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (cfg(priv)->bt_params && cfg(priv)->bt_params->advanced_bt_coexist) { @@ -1109,7 +1109,7 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, "ignoring RSSI callback\n"); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -1149,7 +1149,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, q = AC_NUM - 1 - queue; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); ctx->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); @@ -1161,7 +1161,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0; - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; @@ -1189,7 +1189,7 @@ static int iwl_setup_interface(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; int err; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* * This variable will be correct only when there's just @@ -1234,7 +1234,7 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, cancel_delayed_work_sync(&priv->hw_roc_disable_work); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwlagn_disable_roc(priv); @@ -1281,7 +1281,7 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, ctx->vif = NULL; priv->iw_mode = NL80211_IFTYPE_STATION; out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return err; @@ -1293,7 +1293,7 @@ static void iwl_teardown_interface(struct iwl_priv *priv, { struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (priv->scan_vif == vif) { iwl_scan_cancel_timeout(priv, 200); @@ -1325,7 +1325,7 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (WARN_ON(ctx->vif != vif)) { struct iwl_rxon_context *tmp; @@ -1338,7 +1338,7 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw, iwl_teardown_interface(priv, vif, false); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -1360,7 +1360,7 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, newtype = ieee80211_iftype_p2p(newtype, newp2p); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) { /* @@ -1424,7 +1424,7 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, err = 0; out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return err; @@ -1442,7 +1442,7 @@ static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, if (req->n_channels == 0) return -EINVAL; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); /* * If an internal scan is in progress, just set @@ -1471,7 +1471,7 @@ static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "leave\n"); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 46ca82062c2e..d76ff239d5f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -383,7 +383,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, int ret; bool update_chains; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* Don't update the RX chain when chain noise calibration is running */ update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index dcba74883307..6cf2cb318882 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -115,7 +115,7 @@ static void iwl_process_scan_complete(struct iwl_priv *priv) { bool aborted; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status)) return; @@ -172,7 +172,7 @@ out_settings: void iwl_force_scan_end(struct iwl_priv *priv) { - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n"); @@ -191,7 +191,7 @@ static void iwl_do_scan_abort(struct iwl_priv *priv) { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n"); @@ -230,7 +230,7 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) { unsigned long timeout = jiffies + msecs_to_jiffies(ms); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n"); @@ -595,7 +595,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) u8 scan_tx_antennas = hw_params(priv).valid_tx_ant; int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (vif) ctx = iwl_rxon_ctx_from_vif(vif); @@ -912,7 +912,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); cancel_delayed_work(&priv->scan_check); @@ -972,7 +972,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) IWL_DEBUG_SCAN(priv, "Start internal scan\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (priv->scan_type == IWL_SCAN_RADIO_RESET) { IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n"); @@ -987,7 +987,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band)) IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n"); unlock: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static void iwl_bg_scan_check(struct work_struct *data) @@ -1000,9 +1000,9 @@ static void iwl_bg_scan_check(struct work_struct *data) /* Since we are here firmware does not finish scan and * most likely is in bad shape, so we don't bother to * send abort command, just force scan complete to mac80211 */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_force_scan_end(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /** @@ -1060,9 +1060,9 @@ static void iwl_bg_abort_scan(struct work_struct *work) /* We keep scan_check work queued in case when firmware will not * report back scan completed notification */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 200); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static void iwl_bg_scan_completed(struct work_struct *work) @@ -1070,9 +1070,9 @@ static void iwl_bg_scan_completed(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, scan_completed); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_process_scan_complete(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } void iwl_setup_scan_deferred_work(struct iwl_priv *priv) @@ -1090,8 +1090,8 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->scan_completed); if (cancel_delayed_work_sync(&priv->scan_check)) { - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_force_scan_end(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index bb34766609db..30b942f77814 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -65,7 +65,6 @@ #include #include -#include #include #include @@ -399,7 +398,6 @@ struct iwl_cfg { * @nic: pointer to the nic data * @hw_params: see struct iwl_hw_params * @lock: protect general shared data - * @mutex: * @wait_command_queue: the wait_queue for SYNC host command nad uCode load * @eeprom: pointer to the eeprom/OTP image * @ucode_type: indicator of loaded ucode image @@ -423,8 +421,6 @@ struct iwl_shared { struct iwl_hw_params hw_params; const struct iwl_fw *fw; - struct mutex mutex; - wait_queue_head_t wait_command_queue; /* eeprom -- this is in the card's little endian byte order */ diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index f26765b3a661..095d71dc99c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -975,7 +975,7 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) return -ENOMSG; } /* in case multiple accesses to the device happens */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_UCODE: @@ -1027,7 +1027,7 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return result; } @@ -1062,7 +1062,7 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, } /* in case multiple accesses to the device happens */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); switch (cmd) { case IWL_TM_CMD_APP2DEV_READ_TRACE: IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); @@ -1077,6 +1077,6 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return result; } diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 1cbe8e9926f1..c1c5e1f2223a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -599,7 +599,7 @@ int iwl_run_init_ucode(struct iwl_priv *priv) struct iwl_notification_wait calib_wait; int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* No init ucode required? Curious, but maybe ok */ if (!priv->fw->ucode_init.code.len) -- cgit v1.2.3-70-g09d2 From c9eec95cb429359efd39a3c87fb1544fe2b77bc5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:43 -0800 Subject: iwlwifi: move rfkill status handling out of transport The transport layer should only check the hardware RF kill status, not impose any policy or reaction based on it, so move that out of it into the op_mode. For now keep the restriction on loading firmware, that will have to be removed later. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 5 +++ drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 24 +++------------ drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 39 ++++++++---------------- 3 files changed, 22 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 387eeeedb41d..a2ef78c6af60 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1460,6 +1460,11 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) { struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); + if (state) + set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + else + clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index c3c2de3b3169..e8d3129d5bde 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1016,30 +1016,16 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { - int hw_rf_kill = 0; - if (!(iwl_read32(trans, CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) - hw_rf_kill = 1; + bool hw_rfkill; + hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); IWL_WARN(trans, "RF_KILL bit toggled to %s.\n", - hw_rf_kill ? "disable radio" : "enable radio"); + hw_rfkill ? "disable radio" : "enable radio"); isr_stats->rfkill++; - /* driver only loads ucode once setting the interface up. - * the driver allows loading the ucode even if the radio - * is killed. Hence update the killswitch state here. The - * rfkill handler will care about restarting if needed. - */ - if (!test_bit(STATUS_ALIVE, &trans->shrd->status)) { - if (hw_rf_kill) - set_bit(STATUS_RF_KILL_HW, - &trans->shrd->status); - else - clear_bit(STATUS_RF_KILL_HW, - &trans->shrd->status); - iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rf_kill); - } + iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); handled |= CSR_INT_BIT_RF_KILL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index d7dbd80eb108..4a05216242a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1021,6 +1021,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, int ret; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + bool hw_rfkill; trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue; @@ -1039,14 +1040,11 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, } /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(trans, CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); - else - set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); + hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); + iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); - if (iwl_is_rfkill(trans->shrd)) { - iwl_op_mode_hw_rf_kill(trans->op_mode, true); + if (hw_rfkill) { iwl_enable_interrupts(trans); return -ERFKILL; } @@ -1506,6 +1504,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int err; + bool hw_rfkill; trans_pcie->inta_mask = CSR_INI_SET_MASK; @@ -1535,16 +1534,9 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) iwl_apm_init(trans); - /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(trans, - CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); - else - set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); - - iwl_op_mode_hw_rf_kill(trans->op_mode, - test_bit(STATUS_RF_KILL_HW, - &trans->shrd->status)); + hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); + iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); return err; @@ -1659,19 +1651,12 @@ static int iwl_trans_pcie_suspend(struct iwl_trans *trans) static int iwl_trans_pcie_resume(struct iwl_trans *trans) { - bool hw_rfkill = false; + bool hw_rfkill; iwl_enable_interrupts(trans); - if (!(iwl_read32(trans, CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) - hw_rfkill = true; - - if (hw_rfkill) - set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); - else - clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); - + hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); return 0; -- cgit v1.2.3-70-g09d2 From 3995deafdae1b802a117b3d6d18bc9e5ce3d1340 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:44 -0800 Subject: iwlwifi: rename ucode.h to fw-file.h That name better reflects the contents of the file and the fact that it isn't related to iwl-ucode.c. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-drv.c | 2 +- drivers/net/wireless/iwlwifi/iwl-fw-file.h | 160 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-ucode.h | 160 ----------------------------- 3 files changed, 161 insertions(+), 161 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-fw-file.h delete mode 100644 drivers/net/wireless/iwlwifi/iwl-ucode.h (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index f1beeab1e601..29a3ae48df6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -71,7 +71,7 @@ #include "iwl-op-mode.h" /* private includes */ -#include "iwl-ucode.h" +#include "iwl-fw-file.h" /** * struct iwl_drv - drv common data diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h new file mode 100644 index 000000000000..7ca6c9526357 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -0,0 +1,160 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef __iwl_fw_file_h__ +#define __iwl_fw_file_h__ + +#include + +/* v1/v2 uCode file layout */ +struct iwl_ucode_header { + __le32 ver; /* major/minor/API/serial */ + union { + struct { + __le32 inst_size; /* bytes of runtime code */ + __le32 data_size; /* bytes of runtime data */ + __le32 init_size; /* bytes of init code */ + __le32 init_data_size; /* bytes of init data */ + __le32 boot_size; /* bytes of bootstrap code */ + u8 data[0]; /* in same order as sizes */ + } v1; + struct { + __le32 build; /* build number */ + __le32 inst_size; /* bytes of runtime code */ + __le32 data_size; /* bytes of runtime data */ + __le32 init_size; /* bytes of init code */ + __le32 init_data_size; /* bytes of init data */ + __le32 boot_size; /* bytes of bootstrap code */ + u8 data[0]; /* in same order as sizes */ + } v2; + } u; +}; + +/* + * new TLV uCode file layout + * + * The new TLV file format contains TLVs, that each specify + * some piece of data. To facilitate "groups", for example + * different instruction image with different capabilities, + * bundled with the same init image, an alternative mechanism + * is provided: + * When the alternative field is 0, that means that the item + * is always valid. When it is non-zero, then it is only + * valid in conjunction with items of the same alternative, + * in which case the driver (user) selects one alternative + * to use. + */ + +enum iwl_ucode_tlv_type { + IWL_UCODE_TLV_INVALID = 0, /* unused */ + IWL_UCODE_TLV_INST = 1, + IWL_UCODE_TLV_DATA = 2, + IWL_UCODE_TLV_INIT = 3, + IWL_UCODE_TLV_INIT_DATA = 4, + IWL_UCODE_TLV_BOOT = 5, + IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ + IWL_UCODE_TLV_PAN = 7, + IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8, + IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, + IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, + IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, + IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, + IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, + IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, + IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, + IWL_UCODE_TLV_WOWLAN_INST = 16, + IWL_UCODE_TLV_WOWLAN_DATA = 17, + IWL_UCODE_TLV_FLAGS = 18, +}; + +struct iwl_ucode_tlv { + __le16 type; /* see above */ + __le16 alternative; /* see comment */ + __le32 length; /* not including type/length fields */ + u8 data[0]; +}; + +#define IWL_TLV_UCODE_MAGIC 0x0a4c5749 + +struct iwl_tlv_ucode_header { + /* + * The TLV style ucode header is distinguished from + * the v1/v2 style header by first four bytes being + * zero, as such is an invalid combination of + * major/minor/API/serial versions. + */ + __le32 zero; + __le32 magic; + u8 human_readable[64]; + __le32 ver; /* major/minor/API/serial */ + __le32 build; + __le64 alternatives; /* bitmask of valid alternatives */ + /* + * The data contained herein has a TLV layout, + * see above for the TLV header and types. + * Note that each TLV is padded to a length + * that is a multiple of 4 for alignment. + */ + u8 data[0]; +}; + +#endif /* __iwl_fw_file_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.h b/drivers/net/wireless/iwlwifi/iwl-ucode.h deleted file mode 100644 index cdab28784404..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.h +++ /dev/null @@ -1,160 +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) 2008 - 2012 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef __iwl_ucode_h__ -#define __iwl_ucode_h__ - -#include - -/* v1/v2 uCode file layout */ -struct iwl_ucode_header { - __le32 ver; /* major/minor/API/serial */ - union { - struct { - __le32 inst_size; /* bytes of runtime code */ - __le32 data_size; /* bytes of runtime data */ - __le32 init_size; /* bytes of init code */ - __le32 init_data_size; /* bytes of init data */ - __le32 boot_size; /* bytes of bootstrap code */ - u8 data[0]; /* in same order as sizes */ - } v1; - struct { - __le32 build; /* build number */ - __le32 inst_size; /* bytes of runtime code */ - __le32 data_size; /* bytes of runtime data */ - __le32 init_size; /* bytes of init code */ - __le32 init_data_size; /* bytes of init data */ - __le32 boot_size; /* bytes of bootstrap code */ - u8 data[0]; /* in same order as sizes */ - } v2; - } u; -}; - -/* - * new TLV uCode file layout - * - * The new TLV file format contains TLVs, that each specify - * some piece of data. To facilitate "groups", for example - * different instruction image with different capabilities, - * bundled with the same init image, an alternative mechanism - * is provided: - * When the alternative field is 0, that means that the item - * is always valid. When it is non-zero, then it is only - * valid in conjunction with items of the same alternative, - * in which case the driver (user) selects one alternative - * to use. - */ - -enum iwl_ucode_tlv_type { - IWL_UCODE_TLV_INVALID = 0, /* unused */ - IWL_UCODE_TLV_INST = 1, - IWL_UCODE_TLV_DATA = 2, - IWL_UCODE_TLV_INIT = 3, - IWL_UCODE_TLV_INIT_DATA = 4, - IWL_UCODE_TLV_BOOT = 5, - IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ - IWL_UCODE_TLV_PAN = 7, - IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8, - IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9, - IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10, - IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11, - IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, - IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, - IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, - IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, - IWL_UCODE_TLV_WOWLAN_INST = 16, - IWL_UCODE_TLV_WOWLAN_DATA = 17, - IWL_UCODE_TLV_FLAGS = 18, -}; - -struct iwl_ucode_tlv { - __le16 type; /* see above */ - __le16 alternative; /* see comment */ - __le32 length; /* not including type/length fields */ - u8 data[0]; -}; - -#define IWL_TLV_UCODE_MAGIC 0x0a4c5749 - -struct iwl_tlv_ucode_header { - /* - * The TLV style ucode header is distinguished from - * the v1/v2 style header by first four bytes being - * zero, as such is an invalid combination of - * major/minor/API/serial versions. - */ - __le32 zero; - __le32 magic; - u8 human_readable[64]; - __le32 ver; /* major/minor/API/serial */ - __le32 build; - __le64 alternatives; /* bitmask of valid alternatives */ - /* - * The data contained herein has a TLV layout, - * see above for the TLV header and types. - * Note that each TLV is padded to a length - * that is a multiple of 4 for alignment. - */ - u8 data[0]; -}; - -#endif /* __iwl_ucode_h__ */ -- cgit v1.2.3-70-g09d2 From 496bab39b5a8ef9c916cdb961dec5bbb5ba263f7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:45 -0800 Subject: iwlwifi: remove AMT check from transport As iwl_prepare_card_hw() is idempotent (and many cards support AMT anyway) there's no point in calling iwl_prepare_card_hw() only for AMT capable devices -- call it always and simplify the code that way. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 4a05216242a9..4a2d4b58cdc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1033,8 +1033,8 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0; trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; - if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) && - iwl_prepare_card_hw(trans)) { + /* This may fail if AMT took ownership of the device */ + if (iwl_prepare_card_hw(trans)) { IWL_WARN(trans, "Exit HW not ready\n"); return -EIO; } -- cgit v1.2.3-70-g09d2 From 0dde86b2f2999a25dcc62a27cb768c35a418890a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:46 -0800 Subject: iwlwifi: remove shadow_reg_enable from hw_params There's no need to copy shadow_reg_enable into hw_params since it is a pure hardware parameter that will never change, we can access it from the config directly. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 -- drivers/net/wireless/iwlwifi/iwl-power.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-shared.h | 1 - drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 2 +- 6 files changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 863c27e20dbc..f8163717d7d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1127,8 +1127,6 @@ static void iwl_set_hw_params(struct iwl_priv *priv) hw_params(priv).num_ampdu_queues = cfg(priv)->base_params->num_of_ampdu_queues; - hw_params(priv).shadow_reg_enable = - cfg(priv)->base_params->shadow_reg_enable; hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout; /* Device-specific setup */ diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index d76ff239d5f1..f79ff16e29f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -215,7 +215,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, else cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; - if (hw_params(priv).shadow_reg_enable) + if (cfg(priv)->base_params->shadow_reg_enable) cmd->flags |= IWL_POWER_SHADOW_REG_ENA; else cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; @@ -301,7 +301,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv, if (priv->power_data.bus_pm) cmd->flags |= IWL_POWER_PCI_PM_MSK; - if (hw_params(priv).shadow_reg_enable) + if (cfg(priv)->base_params->shadow_reg_enable) cmd->flags |= IWL_POWER_SHADOW_REG_ENA; else cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 30b942f77814..a5ab58ce0307 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -185,7 +185,6 @@ struct iwl_hw_params { u8 valid_tx_ant; u8 valid_rx_ant; u8 ht40_channel; - bool shadow_reg_enable; u16 sku; u32 rx_page_order; u32 ct_kill_threshold; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index e8d3129d5bde..911a9f113f1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -141,7 +141,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, if (q->need_update == 0) goto exit_unlock; - if (hw_params(trans).shadow_reg_enable) { + if (cfg(trans)->base_params->shadow_reg_enable) { /* shadow register enabled */ /* Device expects a multiple of 8 */ q->write_actual = (q->write & ~0x7); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index ca4ceeacc989..2573f7149f16 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -136,7 +136,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) if (txq->need_update == 0) return; - if (hw_params(trans).shadow_reg_enable) { + if (cfg(trans)->base_params->shadow_reg_enable) { /* shadow register enabled */ iwl_write32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 4a2d4b58cdc8..44050fa414d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -828,7 +828,7 @@ static int iwl_nic_init(struct iwl_trans *trans) if (iwl_tx_init(trans)) return -ENOMEM; - if (hw_params(trans).shadow_reg_enable) { + if (cfg(trans)->base_params->shadow_reg_enable) { /* enable shadow regs in HW */ iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); -- cgit v1.2.3-70-g09d2 From 84abd2cc066fc077c424d0faf7618be348a7efb2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:47 -0800 Subject: iwlwifi: move status check functions out of shared They are only used in the DVM op_mode. Also move the rfkill debug macros that depend on them. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.h | 64 +++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-debug.h | 16 -------- drivers/net/wireless/iwlwifi/iwl-shared.h | 42 -------------------- 4 files changed, 65 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 85fe590ee721..7712c5537370 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -34,6 +34,7 @@ #include +#include "iwl-agn.h" #include "iwl-eeprom.h" #include "iwl-dev.h" #include "iwl-core.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index dfd86f288dee..1f62d6d1fc65 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -383,4 +383,68 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, } #endif +/* status checks */ + +static inline int iwl_is_ready(struct iwl_shared *shrd) +{ + /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are + * set but EXIT_PENDING is not */ + return test_bit(STATUS_READY, &shrd->status) && + test_bit(STATUS_GEO_CONFIGURED, &shrd->status) && + !test_bit(STATUS_EXIT_PENDING, &shrd->status); +} + +static inline int iwl_is_alive(struct iwl_shared *shrd) +{ + return test_bit(STATUS_ALIVE, &shrd->status); +} + +static inline int iwl_is_init(struct iwl_shared *shrd) +{ + return test_bit(STATUS_INIT, &shrd->status); +} + +static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd) +{ + return test_bit(STATUS_RF_KILL_HW, &shrd->status); +} + +static inline int iwl_is_rfkill(struct iwl_shared *shrd) +{ + return iwl_is_rfkill_hw(shrd); +} + +static inline int iwl_is_ctkill(struct iwl_shared *shrd) +{ + return test_bit(STATUS_CT_KILL, &shrd->status); +} + +static inline int iwl_is_ready_rf(struct iwl_shared *shrd) +{ + if (iwl_is_rfkill(shrd)) + return 0; + + return iwl_is_ready(shrd); +} + +#ifdef CONFIG_IWLWIFI_DEBUG +#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \ +do { \ + if (!iwl_is_rfkill((m)->shrd)) \ + IWL_ERR(m, fmt, ##args); \ + else \ + __iwl_err(trans(m)->dev, true, \ + !iwl_have_debug_level(IWL_DL_RADIO), \ + fmt, ##args); \ +} while (0) +#else +#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \ +do { \ + if (!iwl_is_rfkill((m)->shrd)) \ + IWL_ERR(m, fmt, ##args); \ + else \ + __iwl_err(trans(m)->dev, true, true, fmt, ##args); \ +} while (0) +#endif /* CONFIG_IWLWIFI_DEBUG */ + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 163d259198be..a6b32a11e103 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -76,24 +76,8 @@ do { \ print_hex_dump(KERN_DEBUG, "iwl data: ", \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ } while (0) -#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \ -do { \ - if (!iwl_is_rfkill((m)->shrd)) \ - IWL_ERR(m, fmt, ##args); \ - else \ - __iwl_err(trans(m)->dev, true, \ - !iwl_have_debug_level(IWL_DL_RADIO), \ - fmt, ##args); \ -} while (0) #else #define iwl_print_hex_dump(m, level, p, len) -#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \ -do { \ - if (!iwl_is_rfkill((m)->shrd)) \ - IWL_ERR(m, fmt, ##args); \ - else \ - __iwl_err(trans(m)->dev, true, true, fmt, ##args); \ -} while (0) #endif /* CONFIG_IWLWIFI_DEBUG */ #ifdef CONFIG_IWLWIFI_DEBUGFS diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index a5ab58ce0307..5e12b504aacf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -508,46 +508,4 @@ iwl_remove_notification(struct iwl_shared *shrd, #define STATUS_CHANNEL_SWITCH_PENDING 19 #define STATUS_SCAN_COMPLETE 20 -static inline int iwl_is_ready(struct iwl_shared *shrd) -{ - /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are - * set but EXIT_PENDING is not */ - return test_bit(STATUS_READY, &shrd->status) && - test_bit(STATUS_GEO_CONFIGURED, &shrd->status) && - !test_bit(STATUS_EXIT_PENDING, &shrd->status); -} - -static inline int iwl_is_alive(struct iwl_shared *shrd) -{ - return test_bit(STATUS_ALIVE, &shrd->status); -} - -static inline int iwl_is_init(struct iwl_shared *shrd) -{ - return test_bit(STATUS_INIT, &shrd->status); -} - -static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd) -{ - return test_bit(STATUS_RF_KILL_HW, &shrd->status); -} - -static inline int iwl_is_rfkill(struct iwl_shared *shrd) -{ - return iwl_is_rfkill_hw(shrd); -} - -static inline int iwl_is_ctkill(struct iwl_shared *shrd) -{ - return test_bit(STATUS_CT_KILL, &shrd->status); -} - -static inline int iwl_is_ready_rf(struct iwl_shared *shrd) -{ - if (iwl_is_rfkill(shrd)) - return 0; - - return iwl_is_ready(shrd); -} - #endif /* #__iwl_shared_h__ */ -- cgit v1.2.3-70-g09d2 From 6c1011e1918be17f7f8ccca5442cd517f9c29d17 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:48 -0800 Subject: iwlwifi: make tracing use device as identifier Tracing used the priv pointer as an identifier, which has the problem that we don't have it in all code, and also some people say no pointers should be "leaked" to userspace. Use the device name instead, it is more useful anyway. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 9 +- drivers/net/wireless/iwlwifi/iwl-devtrace.h | 141 ++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-io.h | 6 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 16 +-- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 2 +- 6 files changed, 90 insertions(+), 86 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f8163717d7d1..276570025e52 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -353,11 +353,12 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, ev = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); time = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); if (mode == 0) { - trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev); + trace_iwlwifi_dev_ucode_cont_event( + trans(priv)->dev, 0, time, ev); } else { data = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); - trace_iwlwifi_dev_ucode_cont_event(priv, time, - data, ev); + trace_iwlwifi_dev_ucode_cont_event( + trans(priv)->dev, time, data, ev); } } /* Allow device to power down */ @@ -422,7 +423,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) else priv->event_log.wraps_once_count++; - trace_iwlwifi_dev_ucode_wrap_event(priv, + trace_iwlwifi_dev_ucode_wrap_event(trans(priv)->dev, num_wraps - priv->event_log.num_wraps, next_entry, priv->event_log.next_entry); diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 96e62338cec0..06203d6a1d86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -41,130 +41,134 @@ static inline void trace_ ## name(proto) {} static inline void trace_ ## name(proto) {} #endif -#define PRIV_ENTRY __field(void *, priv) -#define PRIV_ASSIGN __entry->priv = priv +#define DEV_ENTRY __string(dev, dev_name(dev)) +#define DEV_ASSIGN __assign_str(dev, dev_name(dev)) #undef TRACE_SYSTEM #define TRACE_SYSTEM iwlwifi_io TRACE_EVENT(iwlwifi_dev_ioread32, - TP_PROTO(void *priv, u32 offs, u32 val), - TP_ARGS(priv, offs, val), + TP_PROTO(const struct device *dev, u32 offs, u32 val), + TP_ARGS(dev, offs, val), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY __field(u32, offs) __field(u32, val) ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; __entry->offs = offs; __entry->val = val; ), - TP_printk("[%p] read io[%#x] = %#x", __entry->priv, __entry->offs, __entry->val) + TP_printk("[%s] read io[%#x] = %#x", + __get_str(dev), __entry->offs, __entry->val) ); TRACE_EVENT(iwlwifi_dev_iowrite8, - TP_PROTO(void *priv, u32 offs, u8 val), - TP_ARGS(priv, offs, val), + TP_PROTO(const struct device *dev, u32 offs, u8 val), + TP_ARGS(dev, offs, val), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY __field(u32, offs) __field(u8, val) ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; __entry->offs = offs; __entry->val = val; ), - TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val) + TP_printk("[%s] write io[%#x] = %#x)", + __get_str(dev), __entry->offs, __entry->val) ); TRACE_EVENT(iwlwifi_dev_iowrite32, - TP_PROTO(void *priv, u32 offs, u32 val), - TP_ARGS(priv, offs, val), + TP_PROTO(const struct device *dev, u32 offs, u32 val), + TP_ARGS(dev, offs, val), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY __field(u32, offs) __field(u32, val) ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; __entry->offs = offs; __entry->val = val; ), - TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val) + TP_printk("[%s] write io[%#x] = %#x)", + __get_str(dev), __entry->offs, __entry->val) ); TRACE_EVENT(iwlwifi_dev_irq, - TP_PROTO(void *priv), - TP_ARGS(priv), + TP_PROTO(const struct device *dev), + TP_ARGS(dev), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; ), /* TP_printk("") doesn't compile */ TP_printk("%d", 0) ); TRACE_EVENT(iwlwifi_dev_ict_read, - TP_PROTO(void *priv, u32 index, u32 value), - TP_ARGS(priv, index, value), + TP_PROTO(const struct device *dev, u32 index, u32 value), + TP_ARGS(dev, index, value), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY __field(u32, index) __field(u32, value) ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; __entry->index = index; __entry->value = value; ), - TP_printk("read ict[%d] = %#.8x", __entry->index, __entry->value) + TP_printk("[%s] read ict[%d] = %#.8x", + __get_str(dev), __entry->index, __entry->value) ); #undef TRACE_SYSTEM #define TRACE_SYSTEM iwlwifi_ucode TRACE_EVENT(iwlwifi_dev_ucode_cont_event, - TP_PROTO(void *priv, u32 time, u32 data, u32 ev), - TP_ARGS(priv, time, data, ev), + TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev), + TP_ARGS(dev, time, data, ev), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY __field(u32, time) __field(u32, data) __field(u32, ev) ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; __entry->time = time; __entry->data = data; __entry->ev = ev; ), - TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", - __entry->priv, __entry->time, __entry->data, __entry->ev) + TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u", + __get_str(dev), __entry->time, __entry->data, __entry->ev) ); TRACE_EVENT(iwlwifi_dev_ucode_wrap_event, - TP_PROTO(void *priv, u32 wraps, u32 n_entry, u32 p_entry), - TP_ARGS(priv, wraps, n_entry, p_entry), + TP_PROTO(const struct device *dev, u32 wraps, u32 n_entry, u32 p_entry), + TP_ARGS(dev, wraps, n_entry, p_entry), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY __field(u32, wraps) __field(u32, n_entry) __field(u32, p_entry) ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; __entry->wraps = wraps; __entry->n_entry = n_entry; __entry->p_entry = p_entry; ), - TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X", - __entry->priv, __entry->wraps, __entry->n_entry, + TP_printk("[%s] wraps=#%02d n=0x%X p=0x%X", + __get_str(dev), __entry->wraps, __entry->n_entry, __entry->p_entry) ); @@ -232,52 +236,52 @@ TRACE_EVENT(iwlwifi_dbg, #define TRACE_SYSTEM iwlwifi TRACE_EVENT(iwlwifi_dev_hcmd, - TP_PROTO(void *priv, u32 flags, + TP_PROTO(const struct device *dev, u32 flags, const void *hcmd0, size_t len0, const void *hcmd1, size_t len1, const void *hcmd2, size_t len2), - TP_ARGS(priv, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2), + TP_ARGS(dev, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY __dynamic_array(u8, hcmd0, len0) __dynamic_array(u8, hcmd1, len1) __dynamic_array(u8, hcmd2, len2) __field(u32, flags) ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; memcpy(__get_dynamic_array(hcmd0), hcmd0, len0); memcpy(__get_dynamic_array(hcmd1), hcmd1, len1); memcpy(__get_dynamic_array(hcmd2), hcmd2, len2); __entry->flags = flags; ), - TP_printk("[%p] hcmd %#.2x (%ssync)", - __entry->priv, ((u8 *)__get_dynamic_array(hcmd0))[0], + TP_printk("[%s] hcmd %#.2x (%ssync)", + __get_str(dev), ((u8 *)__get_dynamic_array(hcmd0))[0], __entry->flags & CMD_ASYNC ? "a" : "") ); TRACE_EVENT(iwlwifi_dev_rx, - TP_PROTO(void *priv, void *rxbuf, size_t len), - TP_ARGS(priv, rxbuf, len), + TP_PROTO(const struct device *dev, void *rxbuf, size_t len), + TP_ARGS(dev, rxbuf, len), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY __dynamic_array(u8, rxbuf, len) ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; memcpy(__get_dynamic_array(rxbuf), rxbuf, len); ), - TP_printk("[%p] RX cmd %#.2x", - __entry->priv, ((u8 *)__get_dynamic_array(rxbuf))[4]) + TP_printk("[%s] RX cmd %#.2x", + __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4]) ); TRACE_EVENT(iwlwifi_dev_tx, - TP_PROTO(void *priv, void *tfd, size_t tfdlen, + TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen, void *buf0, size_t buf0_len, void *buf1, size_t buf1_len), - TP_ARGS(priv, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len), + TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY __field(size_t, framelen) __dynamic_array(u8, tfd, tfdlen) @@ -291,29 +295,28 @@ TRACE_EVENT(iwlwifi_dev_tx, __dynamic_array(u8, buf1, buf1_len) ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; __entry->framelen = buf0_len + buf1_len; memcpy(__get_dynamic_array(tfd), tfd, tfdlen); memcpy(__get_dynamic_array(buf0), buf0, buf0_len); memcpy(__get_dynamic_array(buf1), buf1, buf1_len); ), - TP_printk("[%p] TX %.2x (%zu bytes)", - __entry->priv, - ((u8 *)__get_dynamic_array(buf0))[0], + TP_printk("[%s] TX %.2x (%zu bytes)", + __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0], __entry->framelen) ); TRACE_EVENT(iwlwifi_dev_ucode_error, - TP_PROTO(void *priv, u32 desc, u32 tsf_low, + TP_PROTO(const struct device *dev, u32 desc, u32 tsf_low, u32 data1, u32 data2, u32 line, u32 blink1, u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time, u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver, u32 brd_ver), - TP_ARGS(priv, desc, tsf_low, data1, data2, line, + TP_ARGS(dev, desc, tsf_low, data1, data2, line, blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2, gp3, ucode_ver, hw_ver, brd_ver), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY __field(u32, desc) __field(u32, tsf_low) __field(u32, data1) @@ -332,7 +335,7 @@ TRACE_EVENT(iwlwifi_dev_ucode_error, __field(u32, brd_ver) ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; __entry->desc = desc; __entry->tsf_low = tsf_low; __entry->data1 = data1; @@ -350,11 +353,11 @@ TRACE_EVENT(iwlwifi_dev_ucode_error, __entry->hw_ver = hw_ver; __entry->brd_ver = brd_ver; ), - TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, " + TP_printk("[%s] #%02d %010u data 0x%08X 0x%08X line %u, " "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X " "bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X " "hw 0x%08X brd 0x%08X", - __entry->priv, __entry->desc, __entry->tsf_low, + __get_str(dev), __entry->desc, __entry->tsf_low, __entry->data1, __entry->data2, __entry->line, __entry->blink1, __entry->blink2, __entry->ilink1, __entry->ilink2, @@ -364,23 +367,23 @@ TRACE_EVENT(iwlwifi_dev_ucode_error, ); TRACE_EVENT(iwlwifi_dev_ucode_event, - TP_PROTO(void *priv, u32 time, u32 data, u32 ev), - TP_ARGS(priv, time, data, ev), + TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev), + TP_ARGS(dev, time, data, ev), TP_STRUCT__entry( - PRIV_ENTRY + DEV_ENTRY __field(u32, time) __field(u32, data) __field(u32, ev) ), TP_fast_assign( - PRIV_ASSIGN; + DEV_ASSIGN; __entry->time = time; __entry->data = data; __entry->ev = ev; ), - TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", - __entry->priv, __entry->time, __entry->data, __entry->ev) + TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u", + __get_str(dev), __entry->time, __entry->data, __entry->ev) ); #endif /* __IWLWIFI_DEVICE_TRACE */ diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 782486fc2f8f..1136dc19936a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -35,20 +35,20 @@ static inline void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) { - trace_iwlwifi_dev_iowrite8(priv(trans), ofs, val); + trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); iwl_trans_write8(trans, ofs, val); } static inline void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val) { - trace_iwlwifi_dev_iowrite32(priv(trans), ofs, val); + trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val); iwl_trans_write32(trans, ofs, val); } static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs) { u32 val = iwl_trans_read32(trans, ofs); - trace_iwlwifi_dev_ioread32(priv(trans), ofs, val); + trace_iwlwifi_dev_ioread32(trans->dev, ofs, val); return val; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 911a9f113f1f..33a933b78e52 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -388,7 +388,7 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; len += sizeof(u32); /* account for status word */ - trace_iwlwifi_dev_rx(priv(trans), pkt, len); + trace_iwlwifi_dev_rx(trans->dev, pkt, len); /* Reclaim a command buffer only if this packet is a response * to a (driver-originated) command. @@ -632,7 +632,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) trans_pcie->isr_stats.err_code = table.error_id; - trace_iwlwifi_dev_ucode_error(priv(trans), table.error_id, table.tsf_low, + trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, table.data1, table.data2, table.line, table.blink1, table.blink2, table.ilink1, table.ilink2, table.bcon_time, table.gp1, @@ -764,7 +764,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, "EVT_LOG:0x%08x:%04u\n", time, ev); } else { - trace_iwlwifi_dev_ucode_event(priv(trans), 0, + trace_iwlwifi_dev_ucode_event(trans->dev, 0, time, ev); IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n", time, ev); @@ -778,7 +778,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, } else { IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n", time, data, ev); - trace_iwlwifi_dev_ucode_event(priv(trans), time, + trace_iwlwifi_dev_ucode_event(trans->dev, time, data, ev); } } @@ -1262,7 +1262,7 @@ static irqreturn_t iwl_isr(int irq, void *data) if (!trans) return IRQ_NONE; - trace_iwlwifi_dev_irq(priv(trans)); + trace_iwlwifi_dev_irq(trans->dev); trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1352,7 +1352,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) if (!trans_pcie->use_ict) return iwl_isr(irq, data); - trace_iwlwifi_dev_irq(priv(trans)); + trace_iwlwifi_dev_irq(trans->dev); spin_lock_irqsave(&trans_pcie->irq_lock, flags); @@ -1369,7 +1369,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); - trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index, read); + trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read); if (!read) { IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); goto none; @@ -1388,7 +1388,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT); read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); - trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index, + trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read); } while (read); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 2573f7149f16..844606b436ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -820,7 +820,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) /* check that tracing gets all possible blocks */ BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3); #ifdef CONFIG_IWLWIFI_DEVICE_TRACING - trace_iwlwifi_dev_hcmd(priv(trans), cmd->flags, + trace_iwlwifi_dev_hcmd(trans->dev, cmd->flags, trace_bufs[0], trace_lens[0], trace_bufs[1], trace_lens[1], trace_bufs[2], trace_lens[2]); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 44050fa414d1..ef4e1222a318 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1468,7 +1468,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); - trace_iwlwifi_dev_tx(priv(trans), + trace_iwlwifi_dev_tx(trans->dev, &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], sizeof(struct iwl_tfd), &dev_cmd->hdr, firstlen, -- cgit v1.2.3-70-g09d2 From 0e781842cb25ed3a9d0a91bdf05c0717150c9343 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:49 -0800 Subject: iwlwifi: virtualize command queue full behaviour When the command queue is full, the transport will return -ENOSPC, but the reaction to that depends on the op_mode. Virtualize that, the DVM op_mode checks for CT-kill and restarts the hardware otherwise. We may be able to get rid of this callback by putting the behaviour check into the wrapper but that needs more careful evaluation. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 +++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-op-mode.h | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-shared.h | 2 -- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 7 +------ 5 files changed, 21 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 276570025e52..7c3165ed85bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1403,6 +1403,16 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) ieee80211_free_hw(priv->hw); } +static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) +{ + struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); + + if (!iwl_check_for_ct_kill(priv)) { + IWL_ERR(priv, "Restarting adapter queue is full\n"); + iwl_nic_error(op_mode); + } +} + const struct iwl_op_mode_ops iwl_dvm_ops = { .start = iwl_op_mode_dvm_start, .stop = iwl_op_mode_dvm_stop, @@ -1412,6 +1422,7 @@ const struct iwl_op_mode_ops iwl_dvm_ops = { .hw_rf_kill = iwl_set_hw_rfkill_state, .free_skb = iwl_free_skb, .nic_error = iwl_nic_error, + .cmd_queue_full = iwl_cmd_queue_full, }; /***************************************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 1f62d6d1fc65..ec3a90c42efb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -90,6 +90,8 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state); void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac); void iwl_nic_error(struct iwl_op_mode *op_mode); +bool iwl_check_for_ct_kill(struct iwl_priv *priv); + /* MAC80211 */ struct ieee80211_hw *iwl_alloc_all(void); int iwlagn_mac_setup_register(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index 55b8b27a9560..a4a4907803ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h @@ -122,6 +122,7 @@ struct iwl_fw; * there are Tx packets pending in the transport layer. * Must be atomic * @nic_error: error notification. Must be atomic + * @cmd_queue_full: Called when the command queue gets full. Must be atomic. */ struct iwl_op_mode_ops { struct iwl_op_mode *(*start)(struct iwl_trans *trans, @@ -134,6 +135,7 @@ struct iwl_op_mode_ops { void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb); void (*nic_error)(struct iwl_op_mode *op_mode); + void (*cmd_queue_full)(struct iwl_op_mode *op_mode); }; /** @@ -192,6 +194,11 @@ static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode) op_mode->ops->nic_error(op_mode); } +static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode) +{ + op_mode->ops->cmd_queue_full(op_mode); +} + /***************************************************** * Op mode layers implementations ******************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 5e12b504aacf..8ee528479c95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -461,8 +461,6 @@ enum iwl_rxon_context_id { int iwlagn_hw_valid_rtc_data_addr(u32 addr); void iwl_nic_config(struct iwl_priv *priv); const char *get_cmd_string(u8 cmd); -bool iwl_check_for_ct_kill(struct iwl_priv *priv); - /* notification wait support */ void iwl_abort_notification_waits(struct iwl_shared *shrd); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 844606b436ed..7feeb2d52146 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -671,7 +671,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) dma_addr_t phys_addr; u32 idx; u16 copy_size, cmd_size; - bool is_ct_kill = false; bool had_nocopy = false; int i; u8 *cmd_dest; @@ -727,11 +726,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) spin_unlock_bh(&txq->lock); IWL_ERR(trans, "No space in command queue\n"); - is_ct_kill = iwl_check_for_ct_kill(priv(trans)); - if (!is_ct_kill) { - IWL_ERR(trans, "Restarting adapter queue is full\n"); - iwl_op_mode_nic_error(trans->op_mode); - } + iwl_op_mode_cmd_queue_full(trans->op_mode); return -ENOSPC; } -- cgit v1.2.3-70-g09d2 From 1b29dc94ac2e96c9a31b566dc609bf1d4eb87cc2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:50 -0800 Subject: iwlwifi: clean up iwl-core.h inclusions The transport doesn't need to include iwl-core.h any more. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 33a933b78e52..f1456211c294 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -30,8 +30,7 @@ #include #include -/*TODO: Remove include to iwl-core.h*/ -#include "iwl-core.h" +#include "iwl-prph.h" #include "iwl-io.h" #include "iwl-trans-pcie-int.h" #include "iwl-op-mode.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index ef4e1222a318..6090e9800ce4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -75,7 +75,6 @@ #include "iwl-shared.h" #include "iwl-eeprom.h" #include "iwl-agn-hw.h" -#include "iwl-core.h" #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) -- cgit v1.2.3-70-g09d2 From ae9625a1a947f33579c244b730001f2ea7d15045 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:51 -0800 Subject: iwlwifi: remove num_of_queues module parameter This is a hardware parameter, so it shouldn't be configurable by the user. Users can disable aggregation (which is the only thing affected) with 11n_disable. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 5 ----- drivers/net/wireless/iwlwifi/iwl-2000.c | 5 ----- drivers/net/wireless/iwlwifi/iwl-5000.c | 10 ---------- drivers/net/wireless/iwlwifi/iwl-6000.c | 5 ----- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 -- drivers/net/wireless/iwlwifi/iwl-shared.h | 2 -- 6 files changed, 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 2199a0e5c4f0..5039a9a47767 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -122,11 +122,6 @@ static struct iwl_sensitivity_ranges iwl1000_sensitivity = { static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) { - if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && - iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) - cfg(priv)->base_params->num_of_queues = - iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 1ba020723537..c1739626aeb4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -118,11 +118,6 @@ static struct iwl_sensitivity_ranges iwl2000_sensitivity = { static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) { - if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && - iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) - cfg(priv)->base_params->num_of_queues = - iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index aebdfd7e01a5..fc6ec07de877 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -157,11 +157,6 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) { - if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && - iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) - cfg(priv)->base_params->num_of_queues = - iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | @@ -180,11 +175,6 @@ static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) static void iwl5150_hw_set_hw_params(struct iwl_priv *priv) { - if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && - iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) - cfg(priv)->base_params->num_of_queues = - iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 150bef078609..a64f0f281249 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -139,11 +139,6 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = { static void iwl6000_hw_set_hw_params(struct iwl_priv *priv) { - if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES && - iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES) - cfg(priv)->base_params->num_of_queues = - iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7c3165ed85bc..8cf149cd20ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1471,8 +1471,6 @@ MODULE_PARM_DESC(debug, "debug output mask"); module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO); MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); -module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO); -MODULE_PARM_DESC(queues_num, "number of hw queues."); module_param_named(11n_disable, iwlagn_mod_params.disable_11n, uint, S_IRUGO); MODULE_PARM_DESC(11n_disable, "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX"); diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 8ee528479c95..ab2e1f771a11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -115,7 +115,6 @@ extern struct iwl_mod_params iwlagn_mod_params; * Holds the module parameters * * @sw_crypto: using hardware encryption, default = 0 - * @num_of_queues: number of tx queue, HW dependent * @disable_11n: disable 11n capabilities, default = 0, * use IWL_DISABLE_HT_* constants * @amsdu_size_8K: enable 8K amsdu size, default = 1 @@ -137,7 +136,6 @@ extern struct iwl_mod_params iwlagn_mod_params; */ struct iwl_mod_params { int sw_crypto; - int num_of_queues; unsigned int disable_11n; int amsdu_size_8K; int antenna; -- cgit v1.2.3-70-g09d2 From 3cc241ad713dcc4e193aec40307e9070bf817908 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:52 -0800 Subject: iwlwifi: remove max_txq_num from hw_params This can be used directly from the config now. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a2ef78c6af60..25fdb805abc3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1345,7 +1345,7 @@ void iwl_bg_watchdog(unsigned long data) return; /* monitor and check for stuck queues */ - for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) + for (cnt = 0; cnt < cfg(priv)->base_params->num_of_queues; cnt++) if (iwl_check_stuck_queue(priv, cnt)) return; -- cgit v1.2.3-70-g09d2 From ab5c0f1f2d525ed17f1abf727d213cf220ed26a8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:53 -0800 Subject: iwlwifi: keep plcp_delta_threshold in priv The base_params shouldn't be writable, so keep a copy of this in priv that can be modified. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 +++ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 ++ 4 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index d16e73d1b5c9..5c9c88b8609f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -320,7 +320,7 @@ static bool iwlagn_good_plcp_health(struct iwl_priv *priv, unsigned int msecs) { int delta; - int threshold = cfg(priv)->base_params->plcp_delta_threshold; + int threshold = priv->plcp_delta_threshold; if (threshold == IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) { IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8cf149cd20ca..ac23aa3dd6d7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1045,6 +1045,9 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->ieee_rates = NULL; priv->band = IEEE80211_BAND_2GHZ; + priv->plcp_delta_threshold = + cfg(priv)->base_params->plcp_delta_threshold; + priv->iw_mode = NL80211_IFTYPE_STATION; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index b9b6d628f59a..ade4134fc1ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2241,7 +2241,7 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, const size_t bufsz = sizeof(buf); pos += scnprintf(buf + pos, bufsz - pos, "%u\n", - cfg(priv)->base_params->plcp_delta_threshold); + priv->plcp_delta_threshold); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } @@ -2263,10 +2263,10 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, return -EINVAL; if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) - cfg(priv)->base_params->plcp_delta_threshold = + priv->plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE; else - cfg(priv)->base_params->plcp_delta_threshold = plcp; + priv->plcp_delta_threshold = plcp; return count; } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 73acbab6c248..0c397fd635a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -770,6 +770,8 @@ struct iwl_priv { struct iwl_channel_info *channel_info; /* channel info array */ u8 channel_count; /* # of channels */ + u8 plcp_delta_threshold; + /* thermal calibration */ s32 temperature; /* Celsius */ s32 last_temperature; -- cgit v1.2.3-70-g09d2 From e7a09438b3369732b9c5cfbca24d3bc894fc1ec1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:54 -0800 Subject: iwlwifi: use watchdog timeout from hw_params This is the version that can be modified, the config params should be read-only. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 25fdb805abc3..2422eef6d15f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1340,7 +1340,7 @@ void iwl_bg_watchdog(unsigned long data) if (iwl_is_rfkill(priv->shrd)) return; - timeout = cfg(priv)->base_params->wd_timeout; + timeout = hw_params(priv).wd_timeout; if (timeout == 0) return; @@ -1355,7 +1355,7 @@ void iwl_bg_watchdog(unsigned long data) void iwl_setup_watchdog(struct iwl_priv *priv) { - unsigned int timeout = cfg(priv)->base_params->wd_timeout; + unsigned int timeout = hw_params(priv).wd_timeout; if (!iwlagn_mod_params.wd_disable) { /* use system default */ diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index ade4134fc1ec..116c7851f3b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2368,7 +2368,7 @@ static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file, if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT) timeout = IWL_DEF_WD_TIMEOUT; - cfg(priv)->base_params->wd_timeout = timeout; + hw_params(priv).wd_timeout = timeout; iwl_setup_watchdog(priv); return count; } -- cgit v1.2.3-70-g09d2 From b9ad70da6a7ed166539b188a95e0aef119555e14 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:55 -0800 Subject: iwlwifi: put use_rts_for_aggregation into hw_params The hardware config ht_params shouldn't be modified, so copy the use_rts_for_aggregation parameter into hw_params and use/modify it there. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++++ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-shared.h | 2 ++ 6 files changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 2c5e7ec697e9..e191d394cfa0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -436,8 +436,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * force CTS-to-self frames protection if RTS-CTS is not preferred * one aggregation protection method */ - if (!(cfg(priv)->ht_params && - cfg(priv)->ht_params->use_rts_for_aggregation)) + if (!hw_params(priv).use_rts_for_aggregation) ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index dd28785e1a5c..151400cf51e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -594,8 +594,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, sta_priv->max_agg_bufsize = min(sta_priv->max_agg_bufsize, buf_size); - if (cfg(priv)->ht_params && - cfg(priv)->ht_params->use_rts_for_aggregation) { + if (hw_params(priv).use_rts_for_aggregation) { /* * switch to RTS/CTS if it is the prefer protection * method for HT traffic diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ac23aa3dd6d7..ce62a2fcd67f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1119,6 +1119,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv) static void iwl_set_hw_params(struct iwl_priv *priv) { + if (cfg(priv)->ht_params) + hw_params(priv).use_rts_for_aggregation = + cfg(priv)->ht_params->use_rts_for_aggregation; + if (iwlagn_mod_params.amsdu_size_8K) hw_params(priv).rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 116c7851f3b1..0a898c54c733 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2431,7 +2431,7 @@ static ssize_t iwl_dbgfs_protection_mode_read(struct file *file, if (cfg(priv)->ht_params) pos += scnprintf(buf + pos, bufsz - pos, "use %s for aggregation\n", - (cfg(priv)->ht_params->use_rts_for_aggregation) ? + (hw_params(priv).use_rts_for_aggregation) ? "rts/cts" : "cts-to-self"); else pos += scnprintf(buf + pos, bufsz - pos, "N/A"); @@ -2458,9 +2458,9 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, if (sscanf(buf, "%d", &rts) != 1) return -EINVAL; if (rts) - cfg(priv)->ht_params->use_rts_for_aggregation = true; + hw_params(priv).use_rts_for_aggregation = true; else - cfg(priv)->ht_params->use_rts_for_aggregation = false; + hw_params(priv).use_rts_for_aggregation = false; return count; } diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 30861765b512..d2c1d714c89c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -660,8 +660,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", priv->agg_tids_count); } - if (!priv->agg_tids_count && cfg(priv)->ht_params && - cfg(priv)->ht_params->use_rts_for_aggregation) { + if (!priv->agg_tids_count && + hw_params(priv).use_rts_for_aggregation) { /* * switch off RTS/CTS if it was previously enabled */ diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index ab2e1f771a11..7c9502703e82 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -174,6 +174,7 @@ struct iwl_mod_params { * relevant for 1000, 6000 and up * @wd_timeout: TX queues watchdog timeout * @struct iwl_sensitivity_ranges: range of sensitivity values + * @use_rts_for_aggregation: use rts/cts protection for HT traffic */ struct iwl_hw_params { u8 max_txq_num; @@ -183,6 +184,7 @@ struct iwl_hw_params { u8 valid_tx_ant; u8 valid_rx_ant; u8 ht40_channel; + bool use_rts_for_aggregation; u16 sku; u32 rx_page_order; u32 ct_kill_threshold; -- cgit v1.2.3-70-g09d2 From 6794f3ee1dc4a2f7ebed99a4c075f00bbebbcfdc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:56 -0800 Subject: iwlwifi: constify remaining config data The HW configuration settings base_params, ht_params and bt_params all should be const, make it so. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 5 +++-- drivers/net/wireless/iwlwifi/iwl-2000.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-5000.c | 5 +++-- drivers/net/wireless/iwlwifi/iwl-6000.c | 11 ++++++----- drivers/net/wireless/iwlwifi/iwl-shared.h | 6 +++--- 5 files changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 5039a9a47767..5abebc355f7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -157,7 +157,7 @@ static struct iwl_lib_ops iwl1000_lib = { .temperature = iwlagn_temperature, }; -static struct iwl_base_params iwl1000_base_params = { +static const struct iwl_base_params iwl1000_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .eeprom_size = OTP_LOW_IMAGE_SIZE, @@ -172,7 +172,8 @@ static struct iwl_base_params iwl1000_base_params = { .max_event_log_size = 128, .wd_disable = true, }; -static struct iwl_ht_params iwl1000_ht_params = { + +static const struct iwl_ht_params iwl1000_ht_params = { .ht_greenfield_support = true, .use_rts_for_aggregation = true, /* use rts/cts protection */ .smps_mode = IEEE80211_SMPS_DYNAMIC, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index c1739626aeb4..446d010dfe84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -175,7 +175,7 @@ static struct iwl_lib_ops iwl2030_lib = { .temperature = iwlagn_temperature, }; -static struct iwl_base_params iwl2000_base_params = { +static const struct iwl_base_params iwl2000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, @@ -194,7 +194,7 @@ static struct iwl_base_params iwl2000_base_params = { }; -static struct iwl_base_params iwl2030_base_params = { +static const struct iwl_base_params iwl2030_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, @@ -212,12 +212,12 @@ static struct iwl_base_params iwl2030_base_params = { .hd_v2 = true, }; -static struct iwl_ht_params iwl2000_ht_params = { +static const struct iwl_ht_params iwl2000_ht_params = { .ht_greenfield_support = true, .use_rts_for_aggregation = true, /* use rts/cts protection */ }; -static struct iwl_bt_params iwl2030_bt_params = { +static const struct iwl_bt_params iwl2030_bt_params = { /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .advanced_bt_coexist = true, .agg_time_limit = BT_AGG_THRESHOLD_DEF, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index fc6ec07de877..821ed3a36e52 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -310,7 +310,7 @@ static struct iwl_lib_ops iwl5150_lib = { .temperature = iwl5150_temperature, }; -static struct iwl_base_params iwl5000_base_params = { +static const struct iwl_base_params iwl5000_base_params = { .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, @@ -323,7 +323,8 @@ static struct iwl_base_params iwl5000_base_params = { .no_idle_support = true, .wd_disable = true, }; -static struct iwl_ht_params iwl5000_ht_params = { + +static const struct iwl_ht_params iwl5000_ht_params = { .ht_greenfield_support = true, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index a64f0f281249..d2e24824fc08 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -271,7 +271,7 @@ static struct iwl_lib_ops iwl6030_lib = { .temperature = iwlagn_temperature, }; -static struct iwl_base_params iwl6000_base_params = { +static const struct iwl_base_params iwl6000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, @@ -288,7 +288,7 @@ static struct iwl_base_params iwl6000_base_params = { .shadow_reg_enable = true, }; -static struct iwl_base_params iwl6050_base_params = { +static const struct iwl_base_params iwl6050_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, @@ -304,7 +304,8 @@ static struct iwl_base_params iwl6050_base_params = { .max_event_log_size = 1024, .shadow_reg_enable = true, }; -static struct iwl_base_params iwl6000_g2_base_params = { + +static const struct iwl_base_params iwl6000_g2_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE, .num_of_queues = IWLAGN_NUM_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, @@ -321,12 +322,12 @@ static struct iwl_base_params iwl6000_g2_base_params = { .shadow_reg_enable = true, }; -static struct iwl_ht_params iwl6000_ht_params = { +static const struct iwl_ht_params iwl6000_ht_params = { .ht_greenfield_support = true, .use_rts_for_aggregation = true, /* use rts/cts protection */ }; -static struct iwl_bt_params iwl6000_bt_params = { +static const struct iwl_bt_params iwl6000_bt_params = { /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .advanced_bt_coexist = true, .agg_time_limit = BT_AGG_THRESHOLD_DEF, diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 7c9502703e82..5a67fa141744 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -366,10 +366,10 @@ struct iwl_cfg { const struct iwl_lib_ops *lib; void (*additional_nic_config)(struct iwl_priv *priv); /* params not likely to change within a device family */ - struct iwl_base_params *base_params; + const struct iwl_base_params *base_params; /* params likely to change within a device family */ - struct iwl_ht_params *ht_params; - struct iwl_bt_params *bt_params; + const struct iwl_ht_params *ht_params; + const struct iwl_bt_params *bt_params; enum iwl_pa_type pa_type; /* if used set to IWL_PA_SYSTEM */ const bool need_temp_offset_calib; /* if used set to true */ const bool no_xtal_calib; -- cgit v1.2.3-70-g09d2 From f47208934b2aba432722baeb86a72fcbfd26b593 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:57 -0800 Subject: iwlwifi: fix notification wait bug In "iwlwifi: consolidate the start_device flow" Emmanuel added the return if the fw isn't there but forgot to take into account that the struct for notification wait needs to be added only after the check -- fix that. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-ucode.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index c1c5e1f2223a..686d456d226e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -533,9 +533,6 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, int ret; enum iwl_ucode_type old_type; - iwl_init_notification_wait(priv->shrd, &alive_wait, REPLY_ALIVE, - iwl_alive_fn, &alive_data); - old_type = priv->shrd->ucode_type; priv->shrd->ucode_type = ucode_type; fw = iwl_get_ucode_image(priv, ucode_type); @@ -543,6 +540,9 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, if (!fw) return -EINVAL; + iwl_init_notification_wait(priv->shrd, &alive_wait, REPLY_ALIVE, + iwl_alive_fn, &alive_data); + ret = iwl_trans_start_fw(trans(priv), fw); if (ret) { priv->shrd->ucode_type = old_type; -- cgit v1.2.3-70-g09d2 From 4bd14dd5f77bbe3c51f50f4e86d3b8960e6a518c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:58 -0800 Subject: iwlwifi: abstract out notification wait support This will be sharable, but needs to live in the op_mode as it is dependent on command processing. Make a library out of the notification wait code. Since I wrote all of the code originally and only Intel employees changed it, we can also relicense it to dual BSD/GPL. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 1 + drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 24 +--- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 11 +- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 + drivers/net/wireless/iwlwifi/iwl-notif-wait.c | 157 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-notif-wait.h | 130 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-shared.h | 55 --------- drivers/net/wireless/iwlwifi/iwl-testmode.c | 10 +- drivers/net/wireless/iwlwifi/iwl-ucode.c | 81 ++----------- 10 files changed, 314 insertions(+), 160 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-notif-wait.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-notif-wait.h (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index f2a903d01aa9..85d163ed3db1 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -14,6 +14,7 @@ iwlwifi-objs += iwl-1000.o iwlwifi-objs += iwl-2000.o iwlwifi-objs += iwl-pci.o iwlwifi-objs += iwl-drv.o +iwlwifi-objs += iwl-notif-wait.o iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 5c9c88b8609f..f17142bb5df1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -1142,9 +1142,7 @@ 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->shrd->notif_wait_lock); - INIT_LIST_HEAD(&priv->shrd->notif_waits); - init_waitqueue_head(&priv->shrd->notif_waitq); + iwl_notification_wait_init(&priv->notif_wait); /* Set up BT Rx handlers */ if (cfg(priv)->lib->bt_rx_handler_setup) @@ -1164,25 +1162,7 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, * even if the RX handler consumes the RXB we have * access to it in the notification wait entry. */ - if (!list_empty(&priv->shrd->notif_waits)) { - struct iwl_notification_wait *w; - - 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, - "Notif: %s, 0x%02x - wake the callers up\n", - get_cmd_string(pkt->hdr.cmd), - pkt->hdr.cmd); - w->triggered = true; - if (w->fn) - w->fn(priv, pkt, w->fn_data); - } - spin_unlock(&priv->shrd->notif_wait_lock); - - wake_up_all(&priv->shrd->notif_waitq); - } + iwl_notification_wait_notify(&priv->notif_wait, pkt); if (priv->pre_rx_handler && priv->shrd->ucode_owner == IWL_OWNERSHIP_TM) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index e191d394cfa0..9d955fa387e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -60,9 +60,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, u8 old_dev_type = send->dev_type; int ret; - iwl_init_notification_wait(priv->shrd, &disable_wait, - REPLY_WIPAN_DEACTIVATION_COMPLETE, - NULL, NULL); + iwl_init_notification_wait(&priv->notif_wait, &disable_wait, + REPLY_WIPAN_DEACTIVATION_COMPLETE, + NULL, NULL); send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->dev_type = RXON_DEV_TYPE_P2P; @@ -74,9 +74,10 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, if (ret) { IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); - iwl_remove_notification(priv->shrd, &disable_wait); + iwl_remove_notification(&priv->notif_wait, &disable_wait); } else { - ret = iwl_wait_notification(priv->shrd, &disable_wait, HZ); + ret = iwl_wait_notification(&priv->notif_wait, + &disable_wait, HZ); if (ret) IWL_ERR(priv, "Timed out waiting for PAN disable\n"); } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2422eef6d15f..5f0e07c0b50c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -845,7 +845,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) /* Cancel currently queued command. */ clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); - iwl_abort_notification_waits(priv->shrd); + iwl_abort_notification_waits(&priv->notif_wait); /* 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 0c397fd635a3..c57e605b26b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -51,6 +51,7 @@ #include "iwl-trans.h" #include "iwl-shared.h" #include "iwl-op-mode.h" +#include "iwl-notif-wait.h" struct iwl_tx_queue; @@ -739,6 +740,8 @@ struct iwl_priv { struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); + struct iwl_notif_wait_data notif_wait; + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; /* spectrum measurement report caching */ diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c new file mode 100644 index 000000000000..88dc4a0f96b4 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c @@ -0,0 +1,157 @@ +/****************************************************************************** + * + * 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) 2007 - 2012 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include + +#include "iwl-notif-wait.h" + + +void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait) +{ + spin_lock_init(¬if_wait->notif_wait_lock); + INIT_LIST_HEAD(¬if_wait->notif_waits); + init_waitqueue_head(¬if_wait->notif_waitq); +} + +void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, + struct iwl_rx_packet *pkt) +{ + if (!list_empty(¬if_wait->notif_waits)) { + struct iwl_notification_wait *w; + + spin_lock(¬if_wait->notif_wait_lock); + list_for_each_entry(w, ¬if_wait->notif_waits, list) { + if (w->cmd != pkt->hdr.cmd) + continue; + w->triggered = true; + if (w->fn) + w->fn(notif_wait, pkt, w->fn_data); + } + spin_unlock(¬if_wait->notif_wait_lock); + + wake_up_all(¬if_wait->notif_waitq); + } +} + +void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) +{ + unsigned long flags; + struct iwl_notification_wait *wait_entry; + + spin_lock_irqsave(¬if_wait->notif_wait_lock, flags); + list_for_each_entry(wait_entry, ¬if_wait->notif_waits, list) + wait_entry->aborted = true; + spin_unlock_irqrestore(¬if_wait->notif_wait_lock, flags); + + wake_up_all(¬if_wait->notif_waitq); +} + + +void +iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, + struct iwl_notification_wait *wait_entry, + u8 cmd, + void (*fn)(struct iwl_notif_wait_data *notif_wait, + 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(¬if_wait->notif_wait_lock); + list_add(&wait_entry->list, ¬if_wait->notif_waits); + spin_unlock_bh(¬if_wait->notif_wait_lock); +} + +int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait, + struct iwl_notification_wait *wait_entry, + unsigned long timeout) +{ + int ret; + + ret = wait_event_timeout(notif_wait->notif_waitq, + wait_entry->triggered || wait_entry->aborted, + timeout); + + spin_lock_bh(¬if_wait->notif_wait_lock); + list_del(&wait_entry->list); + spin_unlock_bh(¬if_wait->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_notif_wait_data *notif_wait, + struct iwl_notification_wait *wait_entry) +{ + spin_lock_bh(¬if_wait->notif_wait_lock); + list_del(&wait_entry->list); + spin_unlock_bh(¬if_wait->notif_wait_lock); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h new file mode 100644 index 000000000000..419f1ad65441 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h @@ -0,0 +1,130 @@ +/****************************************************************************** + * + * 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) 2007 - 2012 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef __iwl_notif_wait_h__ +#define __iwl_notif_wait_h__ + +#include + +/* TODO: remove later */ +#include "iwl-commands.h" + +struct iwl_notif_wait_data { + struct list_head notif_waits; + spinlock_t notif_wait_lock; + wait_queue_head_t notif_waitq; +}; + +/** + * 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_notif_wait_data *notif_data, + struct iwl_rx_packet *pkt, void *data); + void *fn_data; + + u8 cmd; + bool triggered, aborted; +}; + + +/* caller functions */ +void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_data); +void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_data, + struct iwl_rx_packet *pkt); +void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_data); + +/* user functions */ +void __acquires(wait_entry) +iwl_init_notification_wait(struct iwl_notif_wait_data *notif_data, + struct iwl_notification_wait *wait_entry, + u8 cmd, + void (*fn)(struct iwl_notif_wait_data *notif_data, + struct iwl_rx_packet *pkt, void *data), + void *fn_data); + +int __must_check __releases(wait_entry) +iwl_wait_notification(struct iwl_notif_wait_data *notif_data, + struct iwl_notification_wait *wait_entry, + unsigned long timeout); + +void __releases(wait_entry) +iwl_remove_notification(struct iwl_notif_wait_data *notif_data, + struct iwl_notification_wait *wait_entry); + +#endif /* __iwl_notif_wait_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 5a67fa141744..8ffc76079121 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -211,35 +211,6 @@ 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; -}; - /** * enum iwl_pa_type - Power Amplifier type * @IWL_PA_SYSTEM: based on uCode configuration @@ -400,9 +371,6 @@ struct iwl_cfg { * @wait_command_queue: the wait_queue for SYNC host command nad uCode load * @eeprom: pointer to the eeprom/OTP image * @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 * @device_pointers: pointers to ucode event tables */ struct iwl_shared { @@ -428,11 +396,6 @@ 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; - struct { u32 error_event_table; u32 log_event_table; @@ -462,24 +425,6 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr); void iwl_nic_config(struct iwl_priv *priv); const char *get_cmd_string(u8 cmd); -/* 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); - #define IWL_CMD(x) case x: return #x /***************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 095d71dc99c4..cc049d22151f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -418,23 +418,23 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) struct iwl_notification_wait calib_wait; int ret; - iwl_init_notification_wait(priv->shrd, &calib_wait, - CALIBRATION_COMPLETE_NOTIFICATION, - NULL, NULL); + iwl_init_notification_wait(&priv->notif_wait, &calib_wait, + CALIBRATION_COMPLETE_NOTIFICATION, + NULL, NULL); ret = iwl_init_alive_start(priv); if (ret) { IWL_ERR(priv, "Fail init calibration: %d\n", ret); goto cfg_init_calib_error; } - ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ); + ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ); if (ret) IWL_ERR(priv, "Error detecting" " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); return ret; cfg_init_calib_error: - iwl_remove_notification(priv->shrd, &calib_wait); + iwl_remove_notification(&priv->notif_wait, &calib_wait); return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 686d456d226e..4d34327f9425 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -29,7 +29,6 @@ #include #include -#include #include "iwl-dev.h" #include "iwl-core.h" @@ -434,10 +433,12 @@ struct iwl_alive_data { u8 subtype; }; -static void iwl_alive_fn(struct iwl_priv *priv, +static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, struct iwl_rx_packet *pkt, void *data) { + struct iwl_priv *priv = + container_of(notif_wait, struct iwl_priv, notif_wait); struct iwl_alive_data *alive_data = data; struct iwl_alive_resp *palive; @@ -457,70 +458,6 @@ 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) @@ -540,13 +477,13 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, if (!fw) return -EINVAL; - iwl_init_notification_wait(priv->shrd, &alive_wait, REPLY_ALIVE, + iwl_init_notification_wait(&priv->notif_wait, &alive_wait, REPLY_ALIVE, iwl_alive_fn, &alive_data); ret = iwl_trans_start_fw(trans(priv), fw); if (ret) { priv->shrd->ucode_type = old_type; - iwl_remove_notification(priv->shrd, &alive_wait); + iwl_remove_notification(&priv->notif_wait, &alive_wait); return ret; } @@ -554,7 +491,7 @@ int iwl_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 = iwl_wait_notification(priv->shrd, &alive_wait, + ret = iwl_wait_notification(&priv->notif_wait, &alive_wait, UCODE_ALIVE_TIMEOUT); if (ret) { priv->shrd->ucode_type = old_type; @@ -608,7 +545,7 @@ int iwl_run_init_ucode(struct iwl_priv *priv) if (priv->shrd->ucode_type != IWL_UCODE_NONE) return 0; - iwl_init_notification_wait(priv->shrd, &calib_wait, + iwl_init_notification_wait(&priv->notif_wait, &calib_wait, CALIBRATION_COMPLETE_NOTIFICATION, NULL, NULL); @@ -625,13 +562,13 @@ int iwl_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 = iwl_wait_notification(priv->shrd, &calib_wait, + ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, UCODE_CALIB_TIMEOUT); goto out; error: - iwl_remove_notification(priv->shrd, &calib_wait); + iwl_remove_notification(&priv->notif_wait, &calib_wait); out: /* Whatever happened, stop the device */ iwl_trans_stop_device(trans(priv)); -- cgit v1.2.3-70-g09d2 From 947a9407e34e7c8d44a0f4d95bbb1e5eae5459c0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:30:59 -0800 Subject: iwlwifi: move ucode_owner to priv The transport doesn't really need to know as we can enforce it in the command wrapper. Move the ucode_owner variable into priv and do all enforcing there. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ++++ drivers/net/wireless/iwlwifi/iwl-shared.h | 4 ---- drivers/net/wireless/iwlwifi/iwl-testmode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 1 - 8 files changed, 14 insertions(+), 13 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 90f1f8a506f2..dec2693c8cba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1306,6 +1306,12 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (cmd->flags & CMD_SYNC) lockdep_assert_held(&priv->mutex); + if (priv->ucode_owner == IWL_OWNERSHIP_TM && + !(cmd->flags & CMD_ON_DEMAND)) { + IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n"); + return -EIO; + } + return iwl_trans_send_cmd(trans(priv), cmd); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index f17142bb5df1..08de306c4c22 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -1165,7 +1165,7 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, iwl_notification_wait_notify(&priv->notif_wait, pkt); if (priv->pre_rx_handler && - priv->shrd->ucode_owner == IWL_OWNERSHIP_TM) + priv->ucode_owner == IWL_OWNERSHIP_TM) priv->pre_rx_handler(priv, rxb); else { /* Based on type of command response or notification, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ce62a2fcd67f..afded2947edd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1053,6 +1053,8 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; priv->agg_tids_count = 0; + priv->ucode_owner = IWL_OWNERSHIP_DRIVER; + /* initialize force reset */ priv->force_reset[IWL_RF_RESET].reset_duration = IWL_DELAY_NEXT_FORCE_RF_RESET; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c57e605b26b7..a301daf18fbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -748,6 +748,10 @@ struct iwl_priv { struct iwl_spectrum_notification measure_report; u8 measurement_status; +#define IWL_OWNERSHIP_DRIVER 0 +#define IWL_OWNERSHIP_TM 1 + u8 ucode_owner; + /* ucode beacon time */ u32 ucode_beacon_time; int missed_beacon_threshold; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 8ffc76079121..a648a2b4934a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -356,7 +356,6 @@ struct iwl_cfg { /** * struct iwl_shared - shared fields for all the layers of the driver * - * @ucode_owner: IWL_OWNERSHIP_* * @cmd_queue: command queue number * @status: STATUS_* * @wowlan: are we running wowlan uCode @@ -374,9 +373,6 @@ struct iwl_cfg { * @device_pointers: pointers to ucode event tables */ struct iwl_shared { -#define IWL_OWNERSHIP_DRIVER 0 -#define IWL_OWNERSHIP_TM 1 - u8 ucode_owner; u8 cmd_queue; unsigned long status; u8 valid_contexts; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index cc049d22151f..63868df32263 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -770,7 +770,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM)) - priv->shrd->ucode_owner = owner; + priv->ucode_owner = owner; else { IWL_ERR(priv, "Invalid owner\n"); return -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 7feeb2d52146..73febc9726cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -685,12 +685,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) return -EIO; } - if ((trans->shrd->ucode_owner == IWL_OWNERSHIP_TM) && - !(cmd->flags & CMD_ON_DEMAND)) { - IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n"); - return -EIO; - } - copy_size = sizeof(out_cmd->hdr); cmd_size = sizeof(out_cmd->hdr); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 6090e9800ce4..598a92d50895 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1022,7 +1022,6 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, IWL_TRANS_GET_PCIE_TRANS(trans); bool hw_rfkill; - trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue; trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue; -- cgit v1.2.3-70-g09d2 From 13df1aab4aa3cd99693c0cdeb7177e5359218431 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:31:00 -0800 Subject: iwlwifi: move all uCode load variables All variables related to uCode loading (the waitqueue and done indication) should be in the PCI-E transport's private data as this is transport specific. Move them there. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-shared.h | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 8 +++++--- drivers/net/wireless/iwlwifi/iwl-trans.h | 3 --- 5 files changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index a648a2b4934a..6b1c29b9bae8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -367,7 +367,7 @@ struct iwl_cfg { * @nic: pointer to the nic data * @hw_params: see struct iwl_hw_params * @lock: protect general shared data - * @wait_command_queue: the wait_queue for SYNC host command nad uCode load + * @wait_command_queue: the wait_queue for SYNC host commands * @eeprom: pointer to the eeprom/OTP image * @ucode_type: indicator of loaded ucode image * @device_pointers: pointers to ucode event tables diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 44952c371d33..93f49acac31b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "iwl-fh.h" @@ -243,6 +244,8 @@ struct iwl_tx_queue { * queue_stop_count: tracks what SW queue is stopped * @pci_dev: basic pci-network driver stuff * @hw_base: pci hardware address support + * @ucode_write_complete: indicates that the ucode has been copied. + * @ucode_write_waitq: wait queue for uCode load */ struct iwl_trans_pcie { struct iwl_rx_queue rxq; @@ -279,6 +282,9 @@ struct iwl_trans_pcie { /* PCI bus related data */ struct pci_dev *pci_dev; void __iomem *hw_base; + + bool ucode_write_complete; + wait_queue_head_t ucode_write_waitq; }; #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index f1456211c294..83cc60e8f607 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1114,8 +1114,8 @@ void iwl_irq_tasklet(struct iwl_trans *trans) isr_stats->tx++; handled |= CSR_INT_BIT_FH_TX; /* Wake up uCode load routine, now that load is complete */ - trans->ucode_write_complete = 1; - wake_up(&trans->shrd->wait_command_queue); + trans_pcie->ucode_write_complete = true; + wake_up(&trans_pcie->ucode_write_waitq); } if (inta & ~handled) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 598a92d50895..6ee46cba2c21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -947,11 +947,12 @@ static const u8 iwlagn_pan_ac_to_queue[] = { static int iwl_load_section(struct iwl_trans *trans, const char *name, const struct fw_desc *image, u32 dst_addr) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); dma_addr_t phy_addr = image->p_addr; u32 byte_cnt = image->len; int ret; - trans->ucode_write_complete = 0; + trans_pcie->ucode_write_complete = false; iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), @@ -982,8 +983,8 @@ static int iwl_load_section(struct iwl_trans *trans, const char *name, FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); IWL_DEBUG_FW(trans, "%s uCode section being loaded...\n", name); - ret = wait_event_timeout(trans->shrd->wait_command_queue, - trans->ucode_write_complete, 5 * HZ); + ret = wait_event_timeout(trans_pcie->ucode_write_waitq, + trans_pcie->ucode_write_complete, 5 * HZ); if (!ret) { IWL_ERR(trans, "Could not load the %s uCode section\n", name); @@ -2255,6 +2256,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, trans->shrd = shrd; trans_pcie->trans = trans; spin_lock_init(&trans_pcie->irq_lock); + init_waitqueue_head(&trans_pcie->ucode_write_waitq); /* W/A - seems to solve weird behavior. We need to remove this if we * don't want to stay in L1 all the time. This wastes a lot of power */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index a8d476a44c58..dcad69491786 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -338,7 +338,6 @@ enum iwl_trans_state { * @hw_id: a u32 with the ID of the device / subdevice. * Set during transport allocation. * @hw_id_str: a string with info about HW ID. Set during transport allocation. - * @ucode_write_complete: indicates that the ucode has been copied. * @nvm_device_type: indicates OTP or eeprom * @pm_support: set to true in start_hw if link pm is supported */ @@ -355,8 +354,6 @@ struct iwl_trans { u32 hw_id; char hw_id_str[52]; - u8 ucode_write_complete; - int nvm_device_type; bool pm_support; -- cgit v1.2.3-70-g09d2 From 7559553660da6cda3aa798c4e8eb681b63402819 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:31:01 -0800 Subject: iwlwifi: move irq to PCIe Even if the variable might also be used by other transports, there's no need for anything outside of the transport itself to access it, so move it into the private area. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 12 ++++++------ drivers/net/wireless/iwlwifi/iwl-trans.h | 2 -- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 93f49acac31b..d13b8d1f08fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -231,6 +231,7 @@ struct iwl_tx_queue { * @rxq: all the RX queue data * @rx_replenish: work that will be called when buffers need to be allocated * @trans: pointer to the generic transport area + * @irq - the irq number for the device * @irq_requested: true when the irq has been requested * @scd_base_addr: scheduler sram base address in SRAM * @scd_bc_tbls: pointer to the byte count table of the scheduler @@ -262,6 +263,7 @@ struct iwl_trans_pcie { struct tasklet_struct irq_tasklet; struct isr_statistics isr_stats; + unsigned int irq; spinlock_t irq_lock; u32 inta_mask; u32 scd_base_addr; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 6ee46cba2c21..16cb4a3511e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1294,7 +1294,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); /* wait to make sure we flush pending tasklet*/ - synchronize_irq(trans->irq); + synchronize_irq(trans_pcie->irq); tasklet_kill(&trans_pcie->irq_tasklet); cancel_work_sync(&trans_pcie->rx_replenish); @@ -1513,11 +1513,11 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) iwl_alloc_isr_ict(trans); - err = request_irq(trans->irq, iwl_isr_ict, IRQF_SHARED, + err = request_irq(trans_pcie->irq, iwl_isr_ict, IRQF_SHARED, DRV_NAME, trans); if (err) { IWL_ERR(trans, "Error allocating IRQ %d\n", - trans->irq); + trans_pcie->irq); goto error; } @@ -1540,7 +1540,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) return err; err_free_irq: - free_irq(trans->irq, trans); + free_irq(trans_pcie->irq, trans); error: iwl_free_isr_ict(trans); tasklet_kill(&trans_pcie->irq_tasklet); @@ -1629,7 +1629,7 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans) iwl_trans_pcie_rx_free(trans); #endif if (trans_pcie->irq_requested == true) { - free_irq(trans->irq, trans); + free_irq(trans_pcie->irq, trans); iwl_free_isr_ict(trans); } @@ -2318,7 +2318,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, "pci_enable_msi failed(0X%x)", err); trans->dev = &pdev->dev; - trans->irq = pdev->irq; + trans_pcie->irq = pdev->irq; trans_pcie->pci_dev = pdev; trans->hw_rev = iwl_read32(trans, CSR_HW_REV); trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index dcad69491786..a4a9efce7a7c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -334,7 +334,6 @@ enum iwl_trans_state { * @shrd - pointer to iwl_shared which holds shared data from the upper layer * @reg_lock - protect hw register access * @dev - pointer to struct device * that represents the device - * @irq - the irq number for the device * @hw_id: a u32 with the ID of the device / subdevice. * Set during transport allocation. * @hw_id_str: a string with info about HW ID. Set during transport allocation. @@ -349,7 +348,6 @@ struct iwl_trans { spinlock_t reg_lock; struct device *dev; - unsigned int irq; u32 hw_rev; u32 hw_id; char hw_id_str[52]; -- cgit v1.2.3-70-g09d2 From f8d7c1a18d5e77b17b5cc1ebefa21eaea7f2d0fa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:31:02 -0800 Subject: iwlwifi: move packet to transport The base packet structure will (hopefully) be the same for all transports, but what is in it differs. Remove the union of all the possible contents and move the packet itself into the transport header file. This requires changing all users of the union to just use pkt->data. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 50 ++++++++-------- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 8 ++- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 4 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 84 --------------------------- drivers/net/wireless/iwlwifi/iwl-notif-wait.h | 3 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 21 ++++--- drivers/net/wireless/iwlwifi/iwl-trans.h | 56 ++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-ucode.c | 4 +- 9 files changed, 103 insertions(+), 129 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 dec2693c8cba..b2ee1f9373c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -710,7 +710,7 @@ int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; + struct iwl_bt_coex_profile_notif *coex = (void *)pkt->data; struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg; if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 08de306c4c22..521c820ea10a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -135,14 +135,15 @@ static int iwlagn_rx_reply_error(struct iwl_priv *priv, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_error_resp *err_resp = (void *)pkt->data; IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " "seq 0x%04X ser 0x%08X\n", - le32_to_cpu(pkt->u.err_resp.error_type), - get_cmd_string(pkt->u.err_resp.cmd_id), - pkt->u.err_resp.cmd_id, - le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), - le32_to_cpu(pkt->u.err_resp.error_info)); + le32_to_cpu(err_resp->error_type), + get_cmd_string(err_resp->cmd_id), + err_resp->cmd_id, + le16_to_cpu(err_resp->bad_cmd_seq_num), + le32_to_cpu(err_resp->error_info)); return 0; } @@ -150,7 +151,7 @@ static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_csa_notification *csa = &(pkt->u.csa_notif); + struct iwl_csa_notification *csa = (void *)pkt->data; /* * MULTI-FIXME * See iwlagn_mac_channel_switch. @@ -181,7 +182,7 @@ static int iwlagn_rx_spectrum_measure_notif(struct iwl_priv *priv, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); + struct iwl_spectrum_notification *report = (void *)pkt->data; if (!report->state) { IWL_DEBUG_11H(priv, @@ -200,7 +201,7 @@ static int iwlagn_rx_pm_sleep_notif(struct iwl_priv *priv, { #ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); + struct iwl_sleep_notification *sleep = (void *)pkt->data; IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", sleep->pm_sleep_mode, sleep->pm_wakeup_src); #endif @@ -217,7 +218,7 @@ static int iwlagn_rx_pm_debug_statistics_notif(struct iwl_priv *priv, IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " "notification for %s:\n", len, get_cmd_string(pkt->hdr.cmd)); - iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); + iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->data, len); return 0; } @@ -226,7 +227,7 @@ static int iwlagn_rx_beacon_notif(struct iwl_priv *priv, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw; + struct iwlagn_beacon_notif *beacon = (void *)pkt->data; #ifdef CONFIG_IWLWIFI_DEBUG u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status); u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); @@ -515,7 +516,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, if (len == sizeof(struct iwl_bt_notif_statistics)) { struct iwl_bt_notif_statistics *stats; - stats = &pkt->u.stats_bt; + stats = (void *)&pkt->data; flag = &stats->flag; common = &stats->general.common; rx_non_phy = &stats->rx.general.common; @@ -533,7 +534,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, #endif } else if (len == sizeof(struct iwl_notif_statistics)) { struct iwl_notif_statistics *stats; - stats = &pkt->u.stats; + stats = (void *)&pkt->data; flag = &stats->flag; common = &stats->general.common; rx_non_phy = &stats->rx.general; @@ -601,8 +602,9 @@ static int iwlagn_rx_reply_statistics(struct iwl_priv *priv, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_notif_statistics *stats = (void *)pkt->data; - if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { + if (le32_to_cpu(stats->flag) & UCODE_STATISTICS_CLEAR_MSK) { #ifdef CONFIG_IWLWIFI_DEBUGFS memset(&priv->accum_stats, 0, sizeof(priv->accum_stats)); @@ -624,7 +626,8 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); + struct iwl_card_state_notif *card_state_notif = (void *)pkt->data; + u32 flags = le32_to_cpu(card_state_notif->flags); unsigned long status = priv->shrd->status; IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", @@ -678,9 +681,8 @@ static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_missed_beacon_notif *missed_beacon; + struct iwl_missed_beacon_notif *missed_beacon = (void *)pkt->data; - missed_beacon = &pkt->u.missed_beacon; if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) > priv->missed_beacon_threshold) { IWL_DEBUG_CALIB(priv, @@ -704,7 +706,7 @@ static int iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, struct iwl_rx_packet *pkt = rxb_addr(rxb); priv->last_phy_res_valid = true; - memcpy(&priv->last_phy_res, pkt->u.raw, + memcpy(&priv->last_phy_res, pkt->data, sizeof(struct iwl_rx_phy_res)); return 0; } @@ -949,12 +951,12 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, * received. */ if (pkt->hdr.cmd == REPLY_RX) { - phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; - header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) + phy_res = (struct iwl_rx_phy_res *)pkt->data; + header = (struct ieee80211_hdr *)(pkt->data + sizeof(*phy_res) + phy_res->cfg_phy_cnt); len = le16_to_cpu(phy_res->byte_count); - rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + + rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*phy_res) + phy_res->cfg_phy_cnt + len); ampdu_status = le32_to_cpu(rx_pkt_status); } else { @@ -963,10 +965,10 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, return 0; } phy_res = &priv->last_phy_res; - amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; - header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); + amsdu = (struct iwl_rx_mpdu_res_start *)pkt->data; + header = (struct ieee80211_hdr *)(pkt->data + sizeof(*amsdu)); len = le16_to_cpu(amsdu->byte_count); - rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); + rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*amsdu) + len); ampdu_status = iwlagn_translate_rx_status(priv, le32_to_cpu(rx_pkt_status)); } @@ -1051,7 +1053,7 @@ static int iwlagn_rx_noa_notification(struct iwl_priv *priv, { struct iwl_wipan_noa_data *new_data, *old_data; struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_wipan_noa_notification *noa_notif = (void *)pkt->u.raw; + struct iwl_wipan_noa_notification *noa_notif = (void *)pkt->data; /* no condition -- we're in softirq */ old_data = rcu_dereference_protected(priv->noa_data, true); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 14fbdecccd26..cb6c2300cf44 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -64,6 +64,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, struct iwl_addsta_cmd *addsta, struct iwl_rx_packet *pkt) { + struct iwl_add_sta_resp *add_sta_resp = (void *)pkt->data; u8 sta_id = addsta->sta.sta_id; int ret = -EIO; @@ -78,7 +79,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, spin_lock(&priv->sta_lock); - switch (pkt->u.add_sta.status) { + switch (add_sta_resp->status) { case ADD_STA_SUCCESS_MSK: IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); ret = iwl_sta_ucode_activate(priv, sta_id); @@ -97,7 +98,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, break; default: IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", - pkt->u.add_sta.status); + add_sta_resp->status); break; } @@ -460,7 +461,8 @@ static int iwl_send_remove_station(struct iwl_priv *priv, } if (!ret) { - switch (pkt->u.rem_sta.status) { + struct iwl_rem_sta_resp *rem_sta_resp = (void *)pkt->data; + switch (rem_sta_resp->status) { case REM_STA_SUCCESS_MSK: if (!temporary) { spin_lock_bh(&priv->sta_lock); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 151400cf51e0..0ef59d9a99ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -983,7 +983,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, u16 sequence = le16_to_cpu(pkt->hdr.sequence); int txq_id = SEQ_TO_QUEUE(sequence); int cmd_index __maybe_unused = SEQ_TO_INDEX(sequence); - struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; + struct iwlagn_tx_resp *tx_resp = (void *)pkt->data; struct ieee80211_hdr *hdr; u32 status = le16_to_cpu(tx_resp->status.status); u16 ssn = iwlagn_get_scd_ssn(tx_resp); @@ -1111,7 +1111,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; + struct iwl_compressed_ba_resp *ba_resp = (void *)pkt->data; struct iwl_ht_agg *agg; struct sk_buff_head reclaimed_skbs; struct ieee80211_tx_info *info; diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index aa8993065cdf..70ba962732f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -206,48 +206,6 @@ enum { /* iwl_cmd_header flags value */ #define IWL_CMD_FAILED_MSK 0x40 -#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f) -#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) -#define SEQ_TO_INDEX(s) ((s) & 0xff) -#define INDEX_TO_SEQ(i) ((i) & 0xff) -#define SEQ_RX_FRAME cpu_to_le16(0x8000) - -/** - * struct iwl_cmd_header - * - * This header format appears in the beginning of each command sent from the - * driver, and each response/notification received from uCode. - */ -struct iwl_cmd_header { - u8 cmd; /* Command ID: REPLY_RXON, etc. */ - u8 flags; /* 0:5 reserved, 6 abort, 7 internal */ - /* - * The driver sets up the sequence number to values of its choosing. - * uCode does not use this value, but passes it back to the driver - * when sending the response to each driver-originated command, so - * the driver can match the response to the command. Since the values - * don't get used by uCode, the driver may set up an arbitrary format. - * - * There is one exception: uCode sets bit 15 when it originates - * the response/notification, i.e. when the response/notification - * is not a direct response to a command sent by the driver. For - * example, uCode issues REPLY_RX when it sends a received frame - * to the driver; it is not a direct response to any driver command. - * - * The Linux driver uses the following format: - * - * 0:7 tfd index - position within TX queue - * 8:12 TX queue id - * 13:14 reserved - * 15 unsolicited RX or uCode-originated notification - */ - __le16 sequence; - - /* command or response/notification data follows immediately */ - u8 data[0]; -} __packed; - - /** * iwlagn rate_n_flags bit fields * @@ -3893,48 +3851,6 @@ struct iwlagn_wowlan_kek_kck_material_cmd { __le64 replay_ctr; } __packed; -/****************************************************************************** - * (13) - * Union of all expected notifications/responses: - * - *****************************************************************************/ -#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */ - -struct iwl_rx_packet { - /* - * The first 4 bytes of the RX frame header contain both the RX frame - * size and some flags. - * Bit fields: - * 31: flag flush RB request - * 30: flag ignore TC (terminal counter) request - * 29: flag fast IRQ request - * 28-14: Reserved - * 13-00: RX frame size - */ - __le32 len_n_flags; - struct iwl_cmd_header hdr; - union { - struct iwl_alive_resp alive_frame; - struct iwl_spectrum_notification spectrum_notif; - struct iwl_csa_notification csa_notif; - struct iwl_error_resp err_resp; - struct iwl_card_state_notif card_state_notif; - struct iwl_add_sta_resp add_sta; - struct iwl_rem_sta_resp rem_sta; - struct iwl_sleep_notification sleep_notif; - struct iwl_spectrum_resp spectrum; - struct iwl_notif_statistics stats; - struct iwl_bt_notif_statistics stats_bt; - struct iwl_compressed_ba_resp compressed_ba; - struct iwl_missed_beacon_notif missed_beacon; - struct iwl_coex_medium_notification coex_medium_notif; - struct iwl_coex_event_resp coex_event; - struct iwl_bt_coex_profile_notif bt_coex_profile_notif; - __le32 status; - u8 raw[0]; - } u; -} __packed; - int iwl_agn_check_rxon_cmd(struct iwl_priv *priv); /* diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h index 419f1ad65441..5e8af957aa7b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h @@ -64,8 +64,7 @@ #include -/* TODO: remove later */ -#include "iwl-commands.h" +#include "iwl-trans.h" struct iwl_notif_wait_data { struct list_head notif_waits; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 6cf2cb318882..91a14577b8a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -57,11 +57,11 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) { int ret; - struct iwl_rx_packet *pkt; struct iwl_host_cmd cmd = { .id = REPLY_SCAN_ABORT_CMD, .flags = CMD_SYNC | CMD_WANT_SKB, }; + __le32 *status; /* Exit instantly with error when device is not ready * to receive scan abort command or it does not perform @@ -76,15 +76,16 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) if (ret) return ret; - pkt = cmd.resp_pkt; - if (pkt->u.status != CAN_ABORT_STATUS) { + status = (void *)cmd.resp_pkt->data; + if (*status != CAN_ABORT_STATUS) { /* The scan abort will return 1 for success or * 2 for "failure". A failure condition can be * due to simply not being in an active scan which * can occur if we send the scan abort before we * the microcode has notified us that a scan is * completed. */ - IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status); + IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", + le32_to_cpu(*status)); ret = -EIO; } @@ -265,8 +266,7 @@ static int iwl_rx_reply_scan(struct iwl_priv *priv, { #ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_scanreq_notification *notif = - (struct iwl_scanreq_notification *)pkt->u.raw; + struct iwl_scanreq_notification *notif = (void *)pkt->data; IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status); #endif @@ -279,8 +279,8 @@ static int iwl_rx_scan_start_notif(struct iwl_priv *priv, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_scanstart_notification *notif = - (struct iwl_scanstart_notification *)pkt->u.raw; + struct iwl_scanstart_notification *notif = (void *)pkt->data; + priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); IWL_DEBUG_SCAN(priv, "Scan start: " "%d [802.11%s] " @@ -307,8 +307,7 @@ static int iwl_rx_scan_results_notif(struct iwl_priv *priv, { #ifdef CONFIG_IWLWIFI_DEBUG struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_scanresults_notification *notif = - (struct iwl_scanresults_notification *)pkt->u.raw; + struct iwl_scanresults_notification *notif = (void *)pkt->data; IWL_DEBUG_SCAN(priv, "Scan ch.res: " "%d [802.11%s] " @@ -332,7 +331,7 @@ static int iwl_rx_scan_complete_notif(struct iwl_priv *priv, struct iwl_device_cmd *cmd) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; + struct iwl_scancomplete_notification *scan_notif = (void *)pkt->data; IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", scan_notif->scanned_channels, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index a4a9efce7a7c..15bb208ab347 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -122,6 +122,62 @@ struct dentry; #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) +#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f) +#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) +#define SEQ_TO_INDEX(s) ((s) & 0xff) +#define INDEX_TO_SEQ(i) ((i) & 0xff) +#define SEQ_RX_FRAME cpu_to_le16(0x8000) + +/** + * struct iwl_cmd_header + * + * This header format appears in the beginning of each command sent from the + * driver, and each response/notification received from uCode. + */ +struct iwl_cmd_header { + u8 cmd; /* Command ID: REPLY_RXON, etc. */ + u8 flags; /* 0:5 reserved, 6 abort, 7 internal */ + /* + * The driver sets up the sequence number to values of its choosing. + * uCode does not use this value, but passes it back to the driver + * when sending the response to each driver-originated command, so + * the driver can match the response to the command. Since the values + * don't get used by uCode, the driver may set up an arbitrary format. + * + * There is one exception: uCode sets bit 15 when it originates + * the response/notification, i.e. when the response/notification + * is not a direct response to a command sent by the driver. For + * example, uCode issues REPLY_RX when it sends a received frame + * to the driver; it is not a direct response to any driver command. + * + * The Linux driver uses the following format: + * + * 0:7 tfd index - position within TX queue + * 8:12 TX queue id + * 13:14 reserved + * 15 unsolicited RX or uCode-originated notification + */ + __le16 sequence; +} __packed; + + +#define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */ + +struct iwl_rx_packet { + /* + * The first 4 bytes of the RX frame header contain both the RX frame + * size and some flags. + * Bit fields: + * 31: flag flush RB request + * 30: flag ignore TC (terminal counter) request + * 29: flag fast IRQ request + * 28-14: Reserved + * 13-00: RX frame size + */ + __le32 len_n_flags; + struct iwl_cmd_header hdr; + u8 data[]; +} __packed; /** * enum CMD_MODE - how to send the host commands ? diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 4d34327f9425..8267dbe869d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -186,7 +186,7 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv, 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; + struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->data; int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; /* reduce the size of the length field itself */ @@ -442,7 +442,7 @@ static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, struct iwl_alive_data *alive_data = data; struct iwl_alive_resp *palive; - palive = &pkt->u.alive_frame; + palive = (void *)pkt->data; IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision " "0x%01X 0x%01X\n", -- cgit v1.2.3-70-g09d2 From ecdb975c92c6ff63673f6380b87ab1e696dfae38 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:31:03 -0800 Subject: iwlwifi: virtualize nic_config The nic_config sets uCode dependent register bits, so it must be virtual in the op_mode. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 ++++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 5 ----- drivers/net/wireless/iwlwifi/iwl-op-mode.h | 9 +++++++++ drivers/net/wireless/iwlwifi/iwl-shared.h | 1 - drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 2 +- 5 files changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index afded2947edd..98f32e57f7f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1422,6 +1422,13 @@ static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) } } +static void iwl_nic_config(struct iwl_op_mode *op_mode) +{ + struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); + + cfg(priv)->lib->nic_config(priv); +} + const struct iwl_op_mode_ops iwl_dvm_ops = { .start = iwl_op_mode_dvm_start, .stop = iwl_op_mode_dvm_stop, @@ -1432,6 +1439,7 @@ const struct iwl_op_mode_ops iwl_dvm_ops = { .free_skb = iwl_free_skb, .nic_error = iwl_nic_error, .cmd_queue_full = iwl_cmd_queue_full, + .nic_config = iwl_nic_config, }; /***************************************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5f0e07c0b50c..f43f51d1570e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1468,11 +1468,6 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); } -void iwl_nic_config(struct iwl_priv *priv) -{ - cfg(priv)->lib->nic_config(priv); -} - void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) { struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index a4a4907803ca..6ea4163ff56a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h @@ -123,6 +123,8 @@ struct iwl_fw; * Must be atomic * @nic_error: error notification. Must be atomic * @cmd_queue_full: Called when the command queue gets full. Must be atomic. + * @nic_config: configure NIC, called before firmware is started. + * May sleep */ struct iwl_op_mode_ops { struct iwl_op_mode *(*start)(struct iwl_trans *trans, @@ -136,6 +138,7 @@ struct iwl_op_mode_ops { void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb); void (*nic_error)(struct iwl_op_mode *op_mode); void (*cmd_queue_full)(struct iwl_op_mode *op_mode); + void (*nic_config)(struct iwl_op_mode *op_mode); }; /** @@ -199,6 +202,12 @@ static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode) op_mode->ops->cmd_queue_full(op_mode); } +static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode) +{ + might_sleep(); + op_mode->ops->nic_config(op_mode); +} + /***************************************************** * Op mode layers implementations ******************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 6b1c29b9bae8..26894dbadef2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -418,7 +418,6 @@ enum iwl_rxon_context_id { }; int iwlagn_hw_valid_rtc_data_addr(u32 addr); -void iwl_nic_config(struct iwl_priv *priv); const char *get_cmd_string(u8 cmd); #define IWL_CMD(x) case x: return #x diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 16cb4a3511e1..26bb44242090 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -816,7 +816,7 @@ static int iwl_nic_init(struct iwl_trans *trans) iwl_set_pwr_vmain(trans); - iwl_nic_config(priv(trans)); + iwl_op_mode_nic_config(trans->op_mode); #ifndef CONFIG_IWLWIFI_IDI /* Allocate the RX queue, or reset if it is already allocated */ -- cgit v1.2.3-70-g09d2 From ef0ef9c8de7e7a069bc2c80a8687c4ab9fa9aff2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:31:04 -0800 Subject: iwlwifi: remove priv from shared Finally nothing needs to access priv from shared any more, 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-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl-shared.h | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 98f32e57f7f0..4cd375c811e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1205,7 +1205,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, op_mode->ops = &iwl_dvm_ops; priv = IWL_OP_MODE_GET_DVM(op_mode); priv->shrd = trans->shrd; - priv->shrd->priv = priv; priv->fw = fw; /* TODO: remove fw from shared data later */ priv->shrd->fw = fw; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 26894dbadef2..f8bef163dea3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -378,7 +378,6 @@ struct iwl_shared { u8 valid_contexts; const struct iwl_cfg *cfg; - struct iwl_priv *priv; struct iwl_trans *trans; void *drv; struct iwl_hw_params hw_params; @@ -400,7 +399,6 @@ struct iwl_shared { }; /*Whatever _m is (iwl_trans, iwl_priv, these macros will work */ -#define priv(_m) ((_m)->shrd->priv) #define cfg(_m) ((_m)->shrd->cfg) #define trans(_m) ((_m)->shrd->trans) #define hw_params(_m) ((_m)->shrd->hw_params) -- cgit v1.2.3-70-g09d2 From 55bba9eafbaa1d63df8158967fbe69c1a4aa71b1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:31:05 -0800 Subject: iwlwifi: remove PA type configuration No need to have a special config variable for the PA type, we can just use the additional NIC config function to config the hardware correctly. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 17 +++++++++-------- drivers/net/wireless/iwlwifi/iwl-shared.h | 12 ------------ 2 files changed, 9 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index d2e24824fc08..d299f05dfc9b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -96,20 +96,21 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv) CSR_GP_DRIVER_REG_BIT_6050_1x2); } +static void iwl6000i_additional_nic_config(struct iwl_priv *priv) +{ + /* 2x2 IPA phy type */ + iwl_write32(trans(priv), CSR_GP_DRIVER_REG, + CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); +} + /* NIC configuration for 6000 series */ static void iwl6000_nic_config(struct iwl_priv *priv) { iwl_rf_config(priv); - /* no locking required for register write */ - if (cfg(priv)->pa_type == IWL_PA_INTERNAL) { - /* 2x2 IPA phy type */ - iwl_write32(trans(priv), CSR_GP_DRIVER_REG, - CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); - } /* do additional nic configuration if needed */ if (cfg(priv)->additional_nic_config) - cfg(priv)->additional_nic_config(priv); + cfg(priv)->additional_nic_config(priv); } static struct iwl_sensitivity_ranges iwl6000_sensitivity = { @@ -473,8 +474,8 @@ const struct iwl_cfg iwl130_bg_cfg = { .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ .lib = &iwl6000_lib, \ + .additional_nic_config = iwl6000i_additional_nic_config,\ .base_params = &iwl6000_base_params, \ - .pa_type = IWL_PA_INTERNAL, \ .led_mode = IWL_LED_BLINK const struct iwl_cfg iwl6000i_2agn_cfg = { diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index f8bef163dea3..ff3394c47635 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -211,16 +211,6 @@ enum iwl_ucode_type { IWL_UCODE_WOWLAN, }; -/** - * enum iwl_pa_type - Power Amplifier type - * @IWL_PA_SYSTEM: based on uCode configuration - * @IWL_PA_INTERNAL: use Internal only - */ -enum iwl_pa_type { - IWL_PA_SYSTEM = 0, - IWL_PA_INTERNAL = 1, -}; - /* * LED mode * IWL_LED_DEFAULT: use device default @@ -301,7 +291,6 @@ struct iwl_base_params { * @base_params: pointer to basic parameters * @ht_params: point to ht patameters * @bt_params: pointer to bt parameters - * @pa_type: used by 6000 series only to identify the type of Power Amplifier * @need_temp_offset_calib: need to perform temperature offset calibration * @no_xtal_calib: some devices do not need crystal calibration data, * don't send it to those @@ -341,7 +330,6 @@ struct iwl_cfg { /* params likely to change within a device family */ const struct iwl_ht_params *ht_params; const struct iwl_bt_params *bt_params; - enum iwl_pa_type pa_type; /* if used set to IWL_PA_SYSTEM */ const bool need_temp_offset_calib; /* if used set to true */ const bool no_xtal_calib; u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; -- cgit v1.2.3-70-g09d2 From eae63b858f9a238a8868846dc5f27fc5e1865659 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:31:06 -0800 Subject: iwlwifi: don't include iwl-prph.h everywhere It's only needed in a few places. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-dev.h | 2 -- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 1 + drivers/net/wireless/iwlwifi/iwl-testmode.c | 1 + 5 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 5abebc355f7f..f6e6f57aade5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -43,6 +43,7 @@ #include "iwl-agn-hw.h" #include "iwl-shared.h" #include "iwl-cfg.h" +#include "iwl-prph.h" /* Highest firmware API version supported */ #define IWL1000_UCODE_API_MAX 6 diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 821ed3a36e52..907a0b22f7b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -45,6 +45,7 @@ #include "iwl-trans.h" #include "iwl-shared.h" #include "iwl-cfg.h" +#include "iwl-prph.h" /* Highest firmware API version supported */ #define IWL5000_UCODE_API_MAX 5 diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index a301daf18fbc..d1e722bd9f5b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -37,11 +37,9 @@ #include #include #include -#include #include "iwl-eeprom.h" #include "iwl-csr.h" -#include "iwl-prph.h" #include "iwl-debug.h" #include "iwl-agn-hw.h" #include "iwl-led.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index f965ee333920..e2d80849001f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -75,6 +75,7 @@ #include "iwl-agn.h" #include "iwl-eeprom.h" #include "iwl-io.h" +#include "iwl-prph.h" /************************** EEPROM BANDS **************************** * diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 63868df32263..5b06916be610 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -78,6 +78,7 @@ #include "iwl-testmode.h" #include "iwl-trans.h" #include "iwl-fh.h" +#include "iwl-prph.h" /* Periphery registers absolute lower bound. This is used in order to -- cgit v1.2.3-70-g09d2 From e7a0d0c4499c4dadec752459c6b15b240db4c3a8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:31:07 -0800 Subject: iwlwifi: clean up iwl-commands.h Do some cleanups here: * remove an unused prototype * remove some unused constants * clean up includes Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index cb6c2300cf44..cf5cc1060cf4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -26,7 +26,7 @@ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * *****************************************************************************/ - +#include #include #include "iwl-dev.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 70ba962732f7..9ed73e5154be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -69,15 +69,9 @@ #ifndef __iwl_commands_h__ #define __iwl_commands_h__ -#include #include +#include -struct iwl_priv; - -/* Tx rates */ -#define IWL_CCK_RATES 4 -#define IWL_OFDM_RATES 8 -#define IWL_MAX_RATES (IWL_CCK_RATES + IWL_OFDM_RATES) enum { REPLY_ALIVE = 0x1, @@ -3851,8 +3845,6 @@ struct iwlagn_wowlan_kek_kck_material_cmd { __le64 replay_ctr; } __packed; -int iwl_agn_check_rxon_cmd(struct iwl_priv *priv); - /* * REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification) */ -- cgit v1.2.3-70-g09d2 From b443d8d8a2b4c3def4b47c17a44bb17ea0a3202f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2012 13:31:08 -0800 Subject: iwlwifi: make iwl_fill_probe_req static This function is only used in iwl-scan.c, so if we move it up a little in the file it can be made static. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.h | 2 - drivers/net/wireless/iwlwifi/iwl-scan.c | 98 ++++++++++++++++----------------- 2 files changed, 49 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7259cbf77da4..e0423c4c01c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -202,8 +202,6 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); void iwl_force_scan_end(struct iwl_priv *priv); void iwl_internal_short_hw_scan(struct iwl_priv *priv); int iwl_force_reset(struct iwl_priv *priv, int mode, bool external); -u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, - const u8 *ta, const u8 *ie, int ie_len, int left); void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); void iwl_setup_scan_deferred_work(struct iwl_priv *priv); void iwl_cancel_scan_deferred_work(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 91a14577b8a8..8c3fb3233d9f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -572,6 +572,53 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, return added; } +/** + * iwl_fill_probe_req - fill in all required fields and IE for probe request + */ + +static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, + const u8 *ies, int ie_len, int left) +{ + int len = 0; + u8 *pos = NULL; + + /* Make sure there is enough space for the probe request, + * two mandatory IEs and the data */ + left -= 24; + if (left < 0) + return 0; + + frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); + memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); + memcpy(frame->sa, ta, ETH_ALEN); + memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); + frame->seq_ctrl = 0; + + len += 24; + + /* ...next IE... */ + pos = &frame->u.probe_req.variable[0]; + + /* fill in our indirect SSID IE */ + left -= 2; + if (left < 0) + return 0; + *pos++ = WLAN_EID_SSID; + *pos++ = 0; + + len += 2; + + if (WARN_ON(left < ie_len)) + return len; + + if (ies && ie_len) { + memcpy(pos, ies, ie_len); + len += ie_len; + } + + return (u16)len; +} + static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) { struct iwl_host_cmd cmd = { @@ -791,7 +838,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->rx_chain = cpu_to_le16(rx_chain); switch (priv->scan_type) { case IWL_SCAN_NORMAL: - cmd_len = iwl_fill_probe_req(priv, + cmd_len = iwl_fill_probe_req( (struct ieee80211_mgmt *)scan->data, vif->addr, priv->scan_request->ie, @@ -801,7 +848,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) case IWL_SCAN_RADIO_RESET: case IWL_SCAN_ROC: /* use bcast addr, will not be transmitted but must be valid */ - cmd_len = iwl_fill_probe_req(priv, + cmd_len = iwl_fill_probe_req( (struct ieee80211_mgmt *)scan->data, iwl_bcast_addr, NULL, 0, IWL_MAX_SCAN_SIZE - sizeof(*scan)); @@ -1004,53 +1051,6 @@ static void iwl_bg_scan_check(struct work_struct *data) mutex_unlock(&priv->mutex); } -/** - * iwl_fill_probe_req - fill in all required fields and IE for probe request - */ - -u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, - const u8 *ta, const u8 *ies, int ie_len, int left) -{ - int len = 0; - u8 *pos = NULL; - - /* Make sure there is enough space for the probe request, - * two mandatory IEs and the data */ - left -= 24; - if (left < 0) - return 0; - - frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); - memcpy(frame->sa, ta, ETH_ALEN); - memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); - frame->seq_ctrl = 0; - - len += 24; - - /* ...next IE... */ - pos = &frame->u.probe_req.variable[0]; - - /* fill in our indirect SSID IE */ - left -= 2; - if (left < 0) - return 0; - *pos++ = WLAN_EID_SSID; - *pos++ = 0; - - len += 2; - - if (WARN_ON(left < ie_len)) - return len; - - if (ies && ie_len) { - memcpy(pos, ies, ie_len); - len += ie_len; - } - - return (u16)len; -} - static void iwl_bg_abort_scan(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); -- cgit v1.2.3-70-g09d2 From 0d33cd782990b13d992109d16e11205e1ac547bb Mon Sep 17 00:00:00 2001 From: RafaÅ‚ MiÅ‚ecki Date: Wed, 7 Mar 2012 09:11:22 +0100 Subject: bcma: silence PMU warning for BCM4331 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: John W. Linville --- drivers/bcma/driver_chipcommon_pmu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 800163c8c2e7..a058842f14fd 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -80,6 +80,7 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) min_msk = 0x200D; max_msk = 0xFFFF; break; + case 0x4331: case 43224: case 43225: break; -- cgit v1.2.3-70-g09d2 From 41b58f189ada1a12d3c9417c3eedd5b910d8d09f Mon Sep 17 00:00:00 2001 From: Attila Fazekas Date: Thu, 23 Feb 2012 19:50:35 +0100 Subject: rtl8187: Add AD-HOC support Add AD-HOC support to the rtl8187 based on the rtl8180 source Signed-off-by: Attila Fazekas Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187/dev.c | 110 ++++++++++++++++++++----- drivers/net/wireless/rtl818x/rtl8187/rtl8187.h | 9 ++ 2 files changed, 100 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 638fbef693e6..cf53ac9d6f23 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -8,7 +8,7 @@ * Copyright 2005 Andrea Merello , et al. * * The driver was extended to the RTL8187B in 2008 by: - * Herton Ronaldo Krzesinski + * Herton Ronaldo Krzesinski * Hin-Tak Leung * Larry Finger * @@ -232,6 +232,7 @@ static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) { struct rtl8187_priv *priv = dev->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *tx_hdr = (struct ieee80211_hdr *)(skb->data); unsigned int ep; void *buf; struct urb *urb; @@ -249,7 +250,7 @@ static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) flags |= RTL818X_TX_DESC_FLAG_NO_ENC; flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24; - if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control)) + if (ieee80211_has_morefrags(tx_hdr->frame_control)) flags |= RTL818X_TX_DESC_FLAG_MOREFRAG; if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { flags |= RTL818X_TX_DESC_FLAG_RTS; @@ -261,6 +262,13 @@ static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; } + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + priv->seqno += 0x10; + tx_hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + tx_hdr->seq_ctrl |= cpu_to_le16(priv->seqno); + } + if (!priv->is_rtl8187b) { struct rtl8187_tx_hdr *hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); @@ -274,8 +282,6 @@ static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) } else { /* fc needs to be calculated before skb_push() */ unsigned int epmap[4] = { 6, 7, 5, 4 }; - struct ieee80211_hdr *tx_hdr = - (struct ieee80211_hdr *)(skb->data); u16 fc = le16_to_cpu(tx_hdr->frame_control); struct rtl8187b_tx_hdr *hdr = @@ -1031,10 +1037,61 @@ static void rtl8187_stop(struct ieee80211_hw *dev) cancel_delayed_work_sync(&priv->work); } +static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif) +{ + struct rtl8187_priv *priv = dev->priv; + + return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | + (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; +} + + +static void rtl8187_beacon_work(struct work_struct *work) +{ + struct rtl8187_vif *vif_priv = + container_of(work, struct rtl8187_vif, beacon_work.work); + struct ieee80211_vif *vif = + container_of((void *)vif_priv, struct ieee80211_vif, drv_priv); + struct ieee80211_hw *dev = vif_priv->dev; + struct ieee80211_mgmt *mgmt; + struct sk_buff *skb; + + /* don't overflow the tx ring */ + if (ieee80211_queue_stopped(dev, 0)) + goto resched; + + /* grab a fresh beacon */ + skb = ieee80211_beacon_get(dev, vif); + if (!skb) + goto resched; + + /* + * update beacon timestamp w/ TSF value + * TODO: make hardware update beacon timestamp + */ + mgmt = (struct ieee80211_mgmt *)skb->data; + mgmt->u.beacon.timestamp = cpu_to_le64(rtl8187_get_tsf(dev, vif)); + + /* TODO: use actual beacon queue */ + skb_set_queue_mapping(skb, 0); + + rtl8187_tx(dev, skb); + +resched: + /* + * schedule next beacon + * TODO: use hardware support for beacon timing + */ + schedule_delayed_work(&vif_priv->beacon_work, + usecs_to_jiffies(1024 * vif->bss_conf.beacon_int)); +} + + static int rtl8187_add_interface(struct ieee80211_hw *dev, struct ieee80211_vif *vif) { struct rtl8187_priv *priv = dev->priv; + struct rtl8187_vif *vif_priv; int i; int ret = -EOPNOTSUPP; @@ -1044,6 +1101,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, switch (vif->type) { case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: break; default: goto exit; @@ -1052,6 +1110,13 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, ret = 0; priv->vif = vif; + /* Initialize driver private area */ + vif_priv = (struct rtl8187_vif *)&vif->drv_priv; + vif_priv->dev = dev; + INIT_DELAYED_WORK(&vif_priv->beacon_work, rtl8187_beacon_work); + vif_priv->enable_beacon = false; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); for (i = 0; i < ETH_ALEN; i++) rtl818x_iowrite8(priv, &priv->map->MAC[i], @@ -1175,9 +1240,12 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, u32 changed) { struct rtl8187_priv *priv = dev->priv; + struct rtl8187_vif *vif_priv; int i; u8 reg; + vif_priv = (struct rtl8187_vif *)&vif->drv_priv; + if (changed & BSS_CHANGED_BSSID) { mutex_lock(&priv->conf_mutex); for (i = 0; i < ETH_ALEN; i++) @@ -1189,8 +1257,12 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, else reg = 0; - if (is_valid_ether_addr(info->bssid)) - reg |= RTL818X_MSR_INFRA; + if (is_valid_ether_addr(info->bssid)) { + if (vif->type == NL80211_IFTYPE_ADHOC) + reg |= RTL818X_MSR_ADHOC; + else + reg |= RTL818X_MSR_INFRA; + } else reg |= RTL818X_MSR_NO_LINK; @@ -1202,6 +1274,16 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE)) rtl8187_conf_erp(priv, info->use_short_slot, info->use_short_preamble); + + if (changed & BSS_CHANGED_BEACON_ENABLED) + vif_priv->enable_beacon = info->enable_beacon; + + if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON)) { + cancel_delayed_work_sync(&vif_priv->beacon_work); + if (vif_priv->enable_beacon) + schedule_work(&vif_priv->beacon_work.work); + } + } static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev, @@ -1279,13 +1361,6 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev, return 0; } -static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif) -{ - struct rtl8187_priv *priv = dev->priv; - - return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | - (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; -} static const struct ieee80211_ops rtl8187_ops = { .tx = rtl8187_tx, @@ -1514,12 +1589,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, if (reg & 0xFF00) priv->rfkill_mask = RFKILL_MASK_8198; } - - /* - * XXX: Once this driver supports anything that requires - * beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ. - */ - dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + dev->vif_data_size = sizeof(struct rtl8187_vif); + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) ; if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) printk(KERN_INFO "rtl8187: inconsistency between id with OEM" diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h index f1cc90751dbf..e19a20a8e955 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h @@ -89,6 +89,14 @@ enum { DEVICE_RTL8187B }; +struct rtl8187_vif { + struct ieee80211_hw *dev; + + /* beaconing */ + struct delayed_work beacon_work; + bool enable_beacon; +}; + struct rtl8187_priv { /* common between rtl818x drivers */ struct rtl818x_csr *map; @@ -141,6 +149,7 @@ struct rtl8187_priv { __le32 bits32; } *io_dmabuf; bool rfkill_off; + u16 seqno; }; void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); -- cgit v1.2.3-70-g09d2 From 55df5afb13718cda49128fa5985556df91d07765 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sat, 3 Mar 2012 22:18:00 +0200 Subject: wl12xx: implement SW Tx watchdog Track freed FW blocks during Tx. If no blocks were freed during a predefined timeout, initiate a HW recovery. This helps in situations when the FW watchdog fails. Don't trigger recovery during activities that can temporarily stop Tx. This includes: - scanning - buffering packets for sleeping stations (AP role) - ROC on any role Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/cmd.c | 8 +++ drivers/net/wireless/wl12xx/conf.h | 3 + drivers/net/wireless/wl12xx/main.c | 110 +++++++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/scan.c | 6 ++ drivers/net/wireless/wl12xx/tx.c | 4 ++ drivers/net/wireless/wl12xx/tx.h | 1 + drivers/net/wireless/wl12xx/wl12xx.h | 3 + 7 files changed, 135 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 1ef212f6440f..3414fc11e9ba 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -1818,6 +1818,14 @@ int wl12xx_croc(struct wl1271 *wl, u8 role_id) goto out; __clear_bit(role_id, wl->roc_map); + + /* + * Rearm the tx watchdog when removing the last ROC. This prevents + * recoveries due to just finished ROCs - when Tx hasn't yet had + * a chance to get out. + */ + if (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) >= WL12XX_MAX_ROLES) + wl12xx_rearm_tx_watchdog_locked(wl); out: return ret; } diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index cc50faaf03d1..3e581e19424c 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -690,6 +690,9 @@ struct conf_tx_settings { */ u8 tmpl_short_retry_limit; u8 tmpl_long_retry_limit; + + /* Time in ms for Tx watchdog timer to expire */ + u32 tx_watchdog_timeout; }; enum { diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 95a76a5f9eeb..39002363611e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -217,6 +217,7 @@ static struct conf_drv_settings default_conf = { .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, .tmpl_short_retry_limit = 10, .tmpl_long_retry_limit = 10, + .tx_watchdog_timeout = 5000, }, .conn = { .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, @@ -553,6 +554,80 @@ static void wl1271_rx_streaming_timer(unsigned long data) ieee80211_queue_work(wl->hw, &wlvif->rx_streaming_disable_work); } +/* wl->mutex must be taken */ +void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl) +{ + /* if the watchdog is not armed, don't do anything */ + if (wl->tx_allocated_blocks == 0) + return; + + cancel_delayed_work(&wl->tx_watchdog_work); + ieee80211_queue_delayed_work(wl->hw, &wl->tx_watchdog_work, + msecs_to_jiffies(wl->conf.tx.tx_watchdog_timeout)); +} + +static void wl12xx_tx_watchdog_work(struct work_struct *work) +{ + struct delayed_work *dwork; + struct wl1271 *wl; + + dwork = container_of(work, struct delayed_work, work); + wl = container_of(dwork, struct wl1271, tx_watchdog_work); + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + + /* Tx went out in the meantime - everything is ok */ + if (unlikely(wl->tx_allocated_blocks == 0)) + goto out; + + /* + * if a ROC is in progress, we might not have any Tx for a long + * time (e.g. pending Tx on the non-ROC channels) + */ + if (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) < WL12XX_MAX_ROLES) { + wl1271_debug(DEBUG_TX, "No Tx (in FW) for %d ms due to ROC", + wl->conf.tx.tx_watchdog_timeout); + wl12xx_rearm_tx_watchdog_locked(wl); + goto out; + } + + /* + * if a scan is in progress, we might not have any Tx for a long + * time + */ + if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { + wl1271_debug(DEBUG_TX, "No Tx (in FW) for %d ms due to scan", + wl->conf.tx.tx_watchdog_timeout); + wl12xx_rearm_tx_watchdog_locked(wl); + goto out; + } + + /* + * AP might cache a frame for a long time for a sleeping station, + * so rearm the timer if there's an AP interface with stations. If + * Tx is genuinely stuck we will most hopefully discover it when all + * stations are removed due to inactivity. + */ + if (wl->active_sta_count) { + wl1271_debug(DEBUG_TX, "No Tx (in FW) for %d ms. AP has " + " %d stations", + wl->conf.tx.tx_watchdog_timeout, + wl->active_sta_count); + wl12xx_rearm_tx_watchdog_locked(wl); + goto out; + } + + wl1271_error("Tx stuck (in FW) for %d ms. Starting recovery", + wl->conf.tx.tx_watchdog_timeout); + wl12xx_queue_recovery_work(wl); + +out: + mutex_unlock(&wl->mutex); +} + static void wl1271_conf_init(struct wl1271 *wl) { @@ -745,6 +820,18 @@ static void wl12xx_fw_status(struct wl1271 *wl, wl->tx_allocated_blocks -= freed_blocks; + /* + * If the FW freed some blocks: + * If we still have allocated blocks - re-arm the timer, Tx is + * not stuck. Otherwise, cancel the timer (no Tx currently). + */ + if (freed_blocks) { + if (wl->tx_allocated_blocks) + wl12xx_rearm_tx_watchdog_locked(wl); + else + cancel_delayed_work(&wl->tx_watchdog_work); + } + avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks; /* @@ -1418,6 +1505,7 @@ int wl1271_plt_stop(struct wl1271 *wl) cancel_work_sync(&wl->netstack_work); cancel_work_sync(&wl->recovery_work); cancel_delayed_work_sync(&wl->elp_work); + cancel_delayed_work_sync(&wl->tx_watchdog_work); mutex_lock(&wl->mutex); wl1271_power_off(wl); @@ -1789,6 +1877,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) cancel_work_sync(&wl->netstack_work); cancel_work_sync(&wl->tx_work); cancel_delayed_work_sync(&wl->elp_work); + cancel_delayed_work_sync(&wl->tx_watchdog_work); /* let's notify MAC80211 about the remaining pending TX frames */ wl12xx_tx_reset(wl, true); @@ -2218,6 +2307,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, if (wl->scan.state != WL1271_SCAN_STATE_IDLE && wl->scan_vif == vif) { + /* + * Rearm the tx watchdog just before idling scan. This + * prevents just-finished scans from triggering the watchdog + */ + wl12xx_rearm_tx_watchdog_locked(wl); + wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan_vif = NULL; @@ -3129,6 +3224,13 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; } + + /* + * Rearm the tx watchdog just before idling scan. This + * prevents just-finished scans from triggering the watchdog + */ + wl12xx_rearm_tx_watchdog_locked(wl); + wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan_vif = NULL; @@ -4138,6 +4240,13 @@ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); wl12xx_free_link(wl, wlvif, &hlid); wl->active_sta_count--; + + /* + * rearm the tx watchdog when the last STA is freed - give the FW a + * chance to return STA-buffered packets before complaining. + */ + if (wl->active_sta_count == 0) + wl12xx_rearm_tx_watchdog_locked(wl); } static int wl12xx_sta_add(struct wl1271 *wl, @@ -5212,6 +5321,7 @@ static 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_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work); wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); if (!wl->freezable_wq) { diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index e43a6b2c1d91..fcba055ef196 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -55,6 +55,12 @@ void wl1271_scan_complete_work(struct work_struct *work) vif = wl->scan_vif; wlvif = wl12xx_vif_to_data(vif); + /* + * Rearm the tx watchdog just before idling scan. This + * prevents just-finished scans from triggering the watchdog + */ + wl12xx_rearm_tx_watchdog_locked(wl); + wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan.req = NULL; diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 8f78fddcb723..43ae49143d68 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -226,6 +226,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl->tx_blocks_available -= total_blocks; wl->tx_allocated_blocks += total_blocks; + /* If the FW was empty before, arm the Tx watchdog */ + if (wl->tx_allocated_blocks == total_blocks) + wl12xx_rearm_tx_watchdog_locked(wl); + ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); wl->tx_allocated_pkts[ac]++; diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index e3977b55a710..5cf8c32d40d1 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -227,5 +227,6 @@ 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); +void wl12xx_rearm_tx_watchdog_locked(struct wl1271 *wl); #endif diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 6e13a3073e9f..749a15a75d38 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -495,6 +495,9 @@ struct wl1271 { /* last wlvif we transmitted from */ struct wl12xx_vif *last_wlvif; + + /* work to fire when Tx is stuck */ + struct delayed_work tx_watchdog_work; }; struct wl1271_station { -- cgit v1.2.3-70-g09d2 From fdeff46586e01c4b8ceb461a72a46fc6ef00a771 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:10 -0800 Subject: iwlwifi: remove unused arguments from iwlagn_gain_computation The function has two arguments it never uses, remove them. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 579679edd5f1..84cbe7bb504c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -879,10 +879,8 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, } static void iwlagn_gain_computation(struct iwl_priv *priv, - u32 average_noise[NUM_RX_CHAINS], - u16 min_average_noise_antenna_i, - u32 min_average_noise, - u8 default_chain) + u32 average_noise[NUM_RX_CHAINS], + u8 default_chain) { int i; s32 delta_g; @@ -1087,7 +1085,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) min_average_noise, min_average_noise_antenna_i); iwlagn_gain_computation(priv, average_noise, - min_average_noise_antenna_i, min_average_noise, find_first_chain(hw_params(priv).valid_rx_ant)); /* Some power changes may have been made during the calibration. -- cgit v1.2.3-70-g09d2 From 9b6ca44823a1414a26054fd0b5cd94f31c105ac8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:11 -0800 Subject: iwlwifi: remove unused argument from rs_initialize_lq The function never uses its conf argument, 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-agn-rs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 9895b807246b..53f8c51cfcdb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2677,7 +2677,6 @@ out: * which requires station table entry to exist). */ static void rs_initialize_lq(struct iwl_priv *priv, - struct ieee80211_conf *conf, struct ieee80211_sta *sta, struct iwl_lq_sta *lq_sta) { @@ -2912,7 +2911,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i lq_sta->dbg_fixed_rate = 0; #endif - rs_initialize_lq(priv, conf, sta, lq_sta); + rs_initialize_lq(priv, sta, lq_sta); } static void rs_fill_link_cmd(struct iwl_priv *priv, -- cgit v1.2.3-70-g09d2 From 955570fc662194c6a1128028a579d7e9014c30aa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:12 -0800 Subject: iwlwifi: move iwl_sta_id_or_broadcast to user There's only one user, so the function can be moved into the correct file. It also loses an argument along the way. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 31 ++++++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-agn.h | 31 ------------------------------- 2 files changed, 30 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 0ef59d9a99ee..c454c6782395 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -248,6 +248,35 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, } } +/** + * iwl_sta_id_or_broadcast - return sta_id or broadcast sta + * @context: the current context + * @sta: mac80211 station + * + * In certain circumstances mac80211 passes a station pointer + * that may be %NULL, for example during TX or key setup. In + * that case, we need to use the broadcast station, so this + * inline wraps that pattern. + */ +static int iwl_sta_id_or_broadcast(struct iwl_rxon_context *context, + struct ieee80211_sta *sta) +{ + int sta_id; + + if (!sta) + return context->bcast_sta_id; + + sta_id = iwl_sta_id(sta); + + /* + * mac80211 should not be passing a partially + * initialised station! + */ + WARN_ON(sta_id == IWL_INVALID_STATION); + + return sta_id; +} + /* * start REPLY_TX command process */ @@ -304,7 +333,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) sta_id = ctx->bcast_sta_id; else { /* Find index into station table for destination station */ - sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta); + sta_id = iwl_sta_id_or_broadcast(ctx, info->control.sta); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index ec3a90c42efb..8384c057babb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -258,37 +258,6 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta) return ((struct iwl_station_priv *)sta->drv_priv)->sta_id; } -/** - * iwl_sta_id_or_broadcast - return sta_id or broadcast sta - * @priv: iwl priv - * @context: the current context - * @sta: mac80211 station - * - * In certain circumstances mac80211 passes a station pointer - * that may be %NULL, for example during TX or key setup. In - * that case, we need to use the broadcast station, so this - * inline wraps that pattern. - */ -static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv, - struct iwl_rxon_context *context, - struct ieee80211_sta *sta) -{ - int sta_id; - - if (!sta) - return context->bcast_sta_id; - - sta_id = iwl_sta_id(sta); - - /* - * mac80211 should not be passing a partially - * initialised station! - */ - WARN_ON(sta_id == IWL_INVALID_STATION); - - return sta_id; -} - int iwlagn_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, -- cgit v1.2.3-70-g09d2 From 03dadf96aa48acbd2501f21d1c1b5740b93b7c72 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:13 -0800 Subject: iwlwifi: remove unused argument from iwl_init_hw_rates The function never uses the priv argument as it only fills in the passed data, so remove the argument. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4cd375c811e2..397faf9023e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1010,8 +1010,7 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv) del_timer_sync(&priv->ucode_trace); } -static void iwl_init_hw_rates(struct iwl_priv *priv, - struct ieee80211_rate *rates) +static void iwl_init_hw_rates(struct ieee80211_rate *rates) { int i; @@ -1090,7 +1089,7 @@ static int iwl_init_drv(struct iwl_priv *priv) IWL_ERR(priv, "initializing geos failed: %d\n", ret); goto err_free_channel_map; } - iwl_init_hw_rates(priv, priv->ieee_rates); + iwl_init_hw_rates(priv->ieee_rates); return 0; -- cgit v1.2.3-70-g09d2 From c1803c9459a9cd751eb46da9e60e49728aae7a5a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:14 -0800 Subject: iwlwifi: remove two unused arguments in testmode The dump functions never access the incoming attributes, so don't pass them. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-testmode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 5b06916be610..1d732092ebe7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -713,7 +713,7 @@ nla_put_failure: return -EMSGSIZE; } -static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb, +static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct sk_buff *skb, struct netlink_callback *cb) { @@ -905,9 +905,9 @@ static int iwl_testmode_indirect_mem(struct ieee80211_hw *hw, } } -static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, struct nlattr **tb, - struct sk_buff *skb, - struct netlink_callback *cb) +static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct netlink_callback *cb) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); int idx, length; @@ -1067,11 +1067,11 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, 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); + result = iwl_testmode_trace_dump(hw, skb, cb); break; case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP: IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n"); - result = iwl_testmode_buffer_dump(hw, tb, skb, cb); + result = iwl_testmode_buffer_dump(hw, skb, cb); break; default: result = -EINVAL; -- cgit v1.2.3-70-g09d2 From ea886a6014024d027fa207b8765e46d746cd2a18 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:15 -0800 Subject: iwlwifi: remove unused argument from iwlagn_suspend There's not much point in passing priv and hw pointers since they can be derived from each other, and the function doesn't use the hw pointer anyway. Remove it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-agn.h | 3 +-- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 2 +- 3 files changed, 3 insertions(+), 5 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 b2ee1f9373c0..6d8a8578778c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1120,8 +1120,7 @@ int iwlagn_send_patterns(struct iwl_priv *priv, return err; } -int iwlagn_suspend(struct iwl_priv *priv, - struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) +int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan) { struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd; struct iwl_rxon_cmd rxon; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 8384c057babb..82930ef86ad1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -141,8 +141,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv); #ifdef CONFIG_PM_SLEEP int iwlagn_send_patterns(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan); -int iwlagn_suspend(struct iwl_priv *priv, - struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); +int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan); #endif /* rx */ diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index d2c1d714c89c..bdcbbd0d3467 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -405,7 +405,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, goto out; } - ret = iwlagn_suspend(priv, hw, wowlan); + ret = iwlagn_suspend(priv, wowlan); if (ret) goto error; -- cgit v1.2.3-70-g09d2 From e755f882b7e72c48da820acc24196532977cfd07 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:16 -0800 Subject: iwlwifi: redesign PASSIVE_NO_RX workaround The PASSIVE_NO_RX workaround currently crosses through the op_mode and transport layers, which is a bit odd. This also isn't necessary, if the transport simply reports when queues are full (or no longer full) the op_mode can keep track of this state, and report to mac80211 only what *it* thinks is appropriate. What is appropriate can then be based on whether queues should be stopped to wait for RX or not. This significantly simplifies the transport API, it no longer needs to expose anything to stop a queue, nor to wake "any" queue, this can all be handled in the upper layer completely. Also simplify the handling to not be dependent on the context, that makes little sense as the queues are shared and both contexts have to be on the same channel anyway. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 8 ++--- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 8 ++--- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 12 ++++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 33 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 5 ++-- drivers/net/wireless/iwlwifi/iwl-core.c | 14 --------- drivers/net/wireless/iwlwifi/iwl-dev.h | 5 ++-- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 12 -------- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 36 ++--------------------- drivers/net/wireless/iwlwifi/iwl-trans.h | 36 ++--------------------- drivers/net/wireless/iwlwifi/iwl-ucode.c | 6 ++-- 11 files changed, 56 insertions(+), 119 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 521c820ea10a..a9bdbad6663e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -807,16 +807,12 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, * sometimes even after already having transmitted frames for the * association because the new RXON may reset the information. */ - if (unlikely(ieee80211_is_beacon(fc))) { + if (unlikely(ieee80211_is_beacon(fc) && priv->passive_no_rx)) { for_each_context(priv, ctx) { - if (!ctx->last_tx_rejected) - continue; if (compare_ether_addr(hdr->addr3, ctx->active.bssid_addr)) continue; - ctx->last_tx_rejected = false; - iwl_trans_wake_any_queue(trans(priv), ctx->ctxid, - "channel got active"); + iwlagn_lift_passive_no_rx(priv); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 9d955fa387e5..66e9a71aaac6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -833,12 +833,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, * not get stuck in this case either since it * can happen if userspace gets confused. */ - if (ctx->last_tx_rejected) { - ctx->last_tx_rejected = false; - iwl_trans_wake_any_queue(trans(priv), - ctx->ctxid, - "Disassoc: flush queue"); - } + iwlagn_lift_passive_no_rx(priv); + ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; if (ctx->ctxid == IWL_RXON_CTX_BSS) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index c454c6782395..a19db4c0c9fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1064,8 +1064,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, } /*we can free until ssn % q.n_bd not inclusive */ - WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, - ssn, status, &skbs)); + WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, + txq_id, ssn, &skbs)); iwlagn_check_ratid_empty(priv, sta_id, tid); freed = 0; @@ -1086,9 +1086,9 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && iwl_is_associated_ctx(ctx) && ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) { - ctx->last_tx_rejected = true; - iwl_trans_stop_queue(trans(priv), txq_id, - "Tx on passive channel"); + /* block and stop all queues */ + priv->passive_no_rx = true; + ieee80211_stop_queues(priv->hw); IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) " @@ -1182,7 +1182,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, * block-ack window (we assume that they've been successfully * transmitted ... if not, it's too late anyway). */ if (iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, - ba_resp_scd_ssn, 0, &reclaimed_skbs)) { + ba_resp_scd_ssn, &reclaimed_skbs)) { spin_unlock(&priv->sta_lock); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 397faf9023e4..29f40eab9715 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1427,6 +1427,39 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode) cfg(priv)->lib->nic_config(priv); } +static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac) +{ + struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); + + set_bit(ac, &priv->transport_queue_stop); + ieee80211_stop_queue(priv->hw, ac); +} + +static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac) +{ + struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); + + clear_bit(ac, &priv->transport_queue_stop); + + if (!priv->passive_no_rx) + ieee80211_wake_queue(priv->hw, ac); +} + +void iwlagn_lift_passive_no_rx(struct iwl_priv *priv) +{ + int ac; + + if (!priv->passive_no_rx) + return; + + for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) { + if (!test_bit(ac, &priv->transport_queue_stop)) + ieee80211_wake_queue(priv->hw, ac); + } + + priv->passive_no_rx = false; +} + const struct iwl_op_mode_ops iwl_dvm_ops = { .start = iwl_op_mode_dvm_start, .stop = iwl_op_mode_dvm_stop, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 82930ef86ad1..b56498b796c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -84,14 +84,13 @@ void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb); int __must_check iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); -void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac); -void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac); void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state); -void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac); void iwl_nic_error(struct iwl_op_mode *op_mode); bool iwl_check_for_ct_kill(struct iwl_priv *priv); +void iwlagn_lift_passive_no_rx(struct iwl_priv *priv); + /* MAC80211 */ struct ieee80211_hw *iwl_alloc_all(void); int iwlagn_mac_setup_register(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f43f51d1570e..f50bd4263b88 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1477,17 +1477,3 @@ void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1])); dev_kfree_skb_any(skb); } - -void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac) -{ - struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); - - ieee80211_stop_queue(priv->hw, ac); -} - -void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac) -{ - struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); - - ieee80211_wake_queue(priv->hw, ac); -} diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d1e722bd9f5b..74429702b130 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -670,8 +670,6 @@ struct iwl_rxon_context { bool enabled, is_40mhz; u8 extension_chan_offset; } ht; - - bool last_tx_rejected; }; enum iwl_scan_type { @@ -720,6 +718,9 @@ struct iwl_priv { spinlock_t sta_lock; struct mutex mutex; + unsigned long transport_queue_stop; + bool passive_no_rx; + /* ieee device used by generic ieee processing code */ struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index d13b8d1f08fa..4f73a6d06509 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -451,18 +451,6 @@ static inline void iwl_stop_queue(struct iwl_trans *trans, } } -#ifdef ieee80211_stop_queue -#undef ieee80211_stop_queue -#endif - -#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue - -#ifdef ieee80211_wake_queue -#undef ieee80211_wake_queue -#endif - -#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue - static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie, int txq_id) { diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 26bb44242090..1c4fbcd348a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1559,8 +1559,7 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans) } static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, - int txq_id, int ssn, u32 status, - struct sk_buff_head *skbs) + int txq_id, int ssn, struct sk_buff_head *skbs) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; @@ -1593,9 +1592,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, txq_id, iwl_get_queue_ac(txq), txq->q.read_ptr, tfd_num, ssn); freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); - if (iwl_queue_space(&txq->q) > txq->q.low_mark && - (!txq->sched_retry || - status != TX_STATUS_FAIL_PASSIVE_NO_RX)) + if (iwl_queue_space(&txq->q) > txq->q.low_mark) iwl_wake_queue(trans, txq, "Packets reclaimed"); } @@ -1662,32 +1659,6 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) } #endif /* CONFIG_PM_SLEEP */ -static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, - const char *msg) -{ - u8 ac, txq_id; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - for (ac = 0; ac < AC_NUM; ac++) { - txq_id = trans_pcie->ac_to_queue[ctx][ac]; - IWL_DEBUG_TX_QUEUES(trans, "Queue Status: Q[%d] %s\n", - ac, - (atomic_read(&trans_pcie->queue_stop_count[ac]) > 0) - ? "stopped" : "awake"); - iwl_wake_queue(trans, &trans_pcie->txq[txq_id], msg); - } -} - -static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id, - const char *msg) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - iwl_stop_queue(trans, &trans_pcie->txq[txq_id], msg); -} - #define IWL_FLUSH_WAIT_MS 2000 static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) @@ -2207,8 +2178,6 @@ const struct iwl_trans_ops trans_ops_pcie = { .wowlan_suspend = iwl_trans_pcie_wowlan_suspend, - .wake_any_queue = iwl_trans_pcie_wake_any_queue, - .send_cmd = iwl_trans_pcie_send_cmd, .tx = iwl_trans_pcie_tx, @@ -2219,7 +2188,6 @@ const struct iwl_trans_ops trans_ops_pcie = { .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, .free = iwl_trans_pcie_free, - .stop_queue = iwl_trans_pcie_stop_queue, .dbgfs_register = iwl_trans_pcie_dbgfs_register, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 15bb208ab347..609949f0299c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -289,7 +289,6 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) * May sleep * @fw_alive: called when the fw sends alive notification * May sleep - * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* * @stop_device:stops the whole device (embedded CPU put to reset) * May sleep * @wowlan_suspend: put the device into the correct mode for WoWLAN during @@ -312,7 +311,6 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) * irq, tasklet etc... From this point on, the device may not issue * any interrupt (incl. RFKILL). * May sleep - * @stop_queue: stop a specific queue * @check_stuck_queue: check if a specific queue is stuck * @wait_tx_queue_empty: wait until all tx queues are empty * May sleep @@ -334,18 +332,13 @@ struct iwl_trans_ops { void (*wowlan_suspend)(struct iwl_trans *trans); - void (*wake_any_queue)(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, - const char *msg); - int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx, u8 sta_id, u8 tid); int (*reclaim)(struct iwl_trans *trans, int sta_id, int tid, - int txq_id, int ssn, u32 status, - struct sk_buff_head *skbs); + int txq_id, int ssn, struct sk_buff_head *skbs); int (*tx_agg_disable)(struct iwl_trans *trans, int sta_id, int tid); @@ -357,8 +350,6 @@ struct iwl_trans_ops { void (*free)(struct iwl_trans *trans); - void (*stop_queue)(struct iwl_trans *trans, int q, const char *msg); - int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); int (*check_stuck_queue)(struct iwl_trans *trans, int q); int (*wait_tx_queue_empty)(struct iwl_trans *trans); @@ -474,17 +465,6 @@ static inline void iwl_trans_wowlan_suspend(struct iwl_trans *trans) trans->ops->wowlan_suspend(trans); } -static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, - const char *msg) -{ - if (trans->state != IWL_TRANS_FW_ALIVE) - IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); - - trans->ops->wake_any_queue(trans, ctx, msg); -} - - static inline int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { @@ -505,14 +485,13 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, } static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id, - int tid, int txq_id, int ssn, u32 status, + int tid, int txq_id, int ssn, struct sk_buff_head *skbs) { if (trans->state != IWL_TRANS_FW_ALIVE) IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); - return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, - status, skbs); + return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, skbs); } static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans, @@ -554,15 +533,6 @@ static inline void iwl_trans_free(struct iwl_trans *trans) trans->ops->free(trans); } -static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q, - const char *msg) -{ - if (trans->state != IWL_TRANS_FW_ALIVE) - IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); - - trans->ops->stop_queue(trans, q, msg); -} - static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) { if (trans->state != IWL_TRANS_FW_ALIVE) diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 8267dbe869d5..404fd8e7958b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -316,7 +316,6 @@ int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) static int iwl_alive_notify(struct iwl_priv *priv) { - struct iwl_rxon_context *ctx; int ret; if (!priv->tx_cmd_pool) @@ -329,8 +328,9 @@ static int iwl_alive_notify(struct iwl_priv *priv) return -ENOMEM; iwl_trans_fw_alive(trans(priv)); - for_each_context(priv, ctx) - ctx->last_tx_rejected = false; + + priv->passive_no_rx = false; + priv->transport_queue_stop = 0; ret = iwl_send_wimax_coex(priv); if (ret) -- cgit v1.2.3-70-g09d2 From b0b4619273dd8b9414a4632f8f229e4f2897ff45 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:17 -0800 Subject: iwlwifi: transport's tx_agg_disable must be atomic At least as long as it is called from the reclaim flow (iwlagn_check_ratid_empty) it must be atomic. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 609949f0299c..ed6ab449e439 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -306,7 +306,7 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) * ready and a successful ADDBA response has been received. * May sleep * @tx_agg_disable: de-configure a Tx queue to send AMPDUs - * May sleep + * Must be atomic * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... From this point on, the device may not issue * any interrupt (incl. RFKILL). @@ -497,8 +497,6 @@ static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id, static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid) { - might_sleep(); - if (trans->state != IWL_TRANS_FW_ALIVE) IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); -- cgit v1.2.3-70-g09d2 From 562f08eb8020cf3672c3743752f82d962ecb7788 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:18 -0800 Subject: iwlwifi: remove BT handlers from lib_ops There's no need to have operations for these as they simply depend on whether the device has built-in bluetooth, so just duplicate the information already there (whether bt_params is present or not). Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-2000.c | 3 --- drivers/net/wireless/iwlwifi/iwl-6000.c | 3 --- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 5 ++--- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-core.h | 6 ------ 5 files changed, 6 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 446d010dfe84..d6ba8419c940 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -156,9 +156,6 @@ static struct iwl_lib_ops iwl2000_lib = { static struct iwl_lib_ops iwl2030_lib = { .set_hw_params = iwl2000_hw_set_hw_params, - .bt_rx_handler_setup = iwlagn_bt_rx_handler_setup, - .bt_setup_deferred_work = iwlagn_bt_setup_deferred_work, - .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, .nic_config = iwl2000_nic_config, .eeprom_ops = { .regulatory_bands = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index d299f05dfc9b..904c50af92fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -252,9 +252,6 @@ static struct iwl_lib_ops iwl6000_lib = { static struct iwl_lib_ops iwl6030_lib = { .set_hw_params = iwl6000_hw_set_hw_params, - .bt_rx_handler_setup = iwlagn_bt_rx_handler_setup, - .bt_setup_deferred_work = iwlagn_bt_setup_deferred_work, - .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, .set_channel_switch = iwl6000_hw_channel_switch, .nic_config = iwl6000_nic_config, .eeprom_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index a9bdbad6663e..e504675f2637 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -1143,9 +1143,8 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) iwl_notification_wait_init(&priv->notif_wait); /* Set up BT Rx handlers */ - if (cfg(priv)->lib->bt_rx_handler_setup) - cfg(priv)->lib->bt_rx_handler_setup(priv); - + if (cfg(priv)->bt_params) + iwlagn_bt_rx_handler_setup(priv); } int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 29f40eab9715..5f390f8d3b8b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -976,8 +976,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) iwl_setup_scan_deferred_work(priv); - if (cfg(priv)->lib->bt_setup_deferred_work) - cfg(priv)->lib->bt_setup_deferred_work(priv); + if (cfg(priv)->bt_params) + iwlagn_bt_setup_deferred_work(priv); init_timer(&priv->statistics_periodic); priv->statistics_periodic.data = (unsigned long)priv; @@ -994,8 +994,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) void iwl_cancel_deferred_work(struct iwl_priv *priv) { - if (cfg(priv)->lib->cancel_deferred_work) - cfg(priv)->lib->cancel_deferred_work(priv); + if (cfg(priv)->bt_params) + iwlagn_bt_cancel_deferred_work(priv); cancel_work_sync(&priv->run_time_calib_work); cancel_work_sync(&priv->beacon_update); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e0423c4c01c7..95f6b7b0abf7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -77,12 +77,6 @@ struct iwl_cmd; struct iwl_lib_ops { /* set hw dependent parameters */ void (*set_hw_params)(struct iwl_priv *priv); - /* setup BT Rx handler */ - void (*bt_rx_handler_setup)(struct iwl_priv *priv); - /* setup BT related deferred work */ - void (*bt_setup_deferred_work)(struct iwl_priv *priv); - /* cancel deferred work */ - void (*cancel_deferred_work)(struct iwl_priv *priv); int (*set_channel_switch)(struct iwl_priv *priv, struct ieee80211_channel_switch *ch_switch); /* device specific configuration */ -- cgit v1.2.3-70-g09d2 From a75a79a84ffd7fea9e10f327d1e2f2fa25770375 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:19 -0800 Subject: iwlwifi: move BT/HT params to shared Hardware parameters will be shared, so move the definitions into the shared header file. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.h | 24 ------------------------ drivers/net/wireless/iwlwifi/iwl-shared.h | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 95f6b7b0abf7..635eb685edeb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -89,30 +89,6 @@ struct iwl_lib_ops { void (*temperature)(struct iwl_priv *priv); }; -/* - * @advanced_bt_coexist: support advanced bt coexist - * @bt_init_traffic_load: specify initial bt traffic load - * @bt_prio_boost: default bt priority boost value - * @agg_time_limit: maximum number of uSec in aggregation - * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode - */ -struct iwl_bt_params { - bool advanced_bt_coexist; - u8 bt_init_traffic_load; - u8 bt_prio_boost; - u16 agg_time_limit; - bool bt_sco_disable; - bool bt_session_2; -}; -/* - * @use_rts_for_aggregation: use rts/cts protection for HT traffic - */ -struct iwl_ht_params { - const bool ht_greenfield_support; /* if used set to true */ - bool use_rts_for_aggregation; - enum ieee80211_smps_mode smps_mode; -}; - /*************************** * L i b * ***************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index ff3394c47635..45409fcfbbd7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -270,6 +270,30 @@ struct iwl_base_params { const bool wd_disable; }; +/* + * @advanced_bt_coexist: support advanced bt coexist + * @bt_init_traffic_load: specify initial bt traffic load + * @bt_prio_boost: default bt priority boost value + * @agg_time_limit: maximum number of uSec in aggregation + * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode + */ +struct iwl_bt_params { + bool advanced_bt_coexist; + u8 bt_init_traffic_load; + u8 bt_prio_boost; + u16 agg_time_limit; + bool bt_sco_disable; + bool bt_session_2; +}; +/* + * @use_rts_for_aggregation: use rts/cts protection for HT traffic + */ +struct iwl_ht_params { + const bool ht_greenfield_support; /* if used set to true */ + bool use_rts_for_aggregation; + enum ieee80211_smps_mode smps_mode; +}; + /** * struct iwl_cfg * @name: Offical name of the device -- cgit v1.2.3-70-g09d2 From 51dc51d12bd609644bbe9877825a1a25a6016639 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:20 -0800 Subject: iwlwifi: make EEPROM enhanced TX power a bool There's no need to carry around the function pointer when a boolean indicating that the EEPROM stores enhanced TX power information is sufficient. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-2000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-6000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn.h | 1 - drivers/net/wireless/iwlwifi/iwl-eeprom.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index d6ba8419c940..14ce83bc71a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -149,7 +149,7 @@ static struct iwl_lib_ops iwl2000_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REGULATORY_BAND_NO_HT40, }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .enhanced_txpower = true, }, .temperature = iwlagn_temperature, }; @@ -167,7 +167,7 @@ static struct iwl_lib_ops iwl2030_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REGULATORY_BAND_NO_HT40, }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .enhanced_txpower = true, }, .temperature = iwlagn_temperature, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 904c50af92fd..0f89e45da1a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -245,7 +245,7 @@ static struct iwl_lib_ops iwl6000_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .enhanced_txpower = true, }, .temperature = iwlagn_temperature, }; @@ -264,7 +264,7 @@ static struct iwl_lib_ops iwl6030_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .enhanced_txpower = true, }, .temperature = iwlagn_temperature, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index b56498b796c2..6345ab0f2a96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -305,7 +305,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) } /* eeprom */ -void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac); extern int iwl_alive_start(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index e2d80849001f..23cea42b9495 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -589,7 +589,7 @@ iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \ ? # x " " : "") -void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) +static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) { struct iwl_shared *shrd = priv->shrd; struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; @@ -1025,8 +1025,8 @@ int iwl_init_channel_map(struct iwl_priv *priv) * driver need to process addition information * to determine the max channel tx power limits */ - if (cfg(priv)->lib->eeprom_ops.update_enhanced_txpower) - cfg(priv)->lib->eeprom_ops.update_enhanced_txpower(priv); + if (cfg(priv)->lib->eeprom_ops.enhanced_txpower) + iwl_eeprom_enhanced_txpower(priv); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 3b17056d5675..e4a758340996 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -302,7 +302,7 @@ extern const u8 iwl_eeprom_band_1[14]; struct iwl_eeprom_ops { const u32 regulatory_bands[7]; - void (*update_enhanced_txpower) (struct iwl_priv *priv); + bool enhanced_txpower; }; -- cgit v1.2.3-70-g09d2 From 9563fe1696fa0ced8cfa3f935736d4662a81c1c3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:21 -0800 Subject: iwlwifi: remove unused max_nrg_cck from sensitivity and constify The sensitivity parameters are never modified, so they should be const. Also remove the unused max_nrg_cck value to save some space. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-2000.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 +--- drivers/net/wireless/iwlwifi/iwl-6000.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - 5 files changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index f6e6f57aade5..450250332e4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -96,9 +96,8 @@ static void iwl1000_nic_config(struct iwl_priv *priv) ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); } -static struct iwl_sensitivity_ranges iwl1000_sensitivity = { +static const struct iwl_sensitivity_ranges iwl1000_sensitivity = { .min_nrg_cck = 95, - .max_nrg_cck = 0, /* not used, set to 0 */ .auto_corr_min_ofdm = 90, .auto_corr_min_ofdm_mrc = 170, .auto_corr_min_ofdm_x1 = 120, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 14ce83bc71a5..abfd901e81a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -91,9 +91,8 @@ static void iwl2000_nic_config(struct iwl_priv *priv) CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); } -static struct iwl_sensitivity_ranges iwl2000_sensitivity = { +static const struct iwl_sensitivity_ranges iwl2000_sensitivity = { .min_nrg_cck = 97, - .max_nrg_cck = 0, /* not used, set to 0 */ .auto_corr_min_ofdm = 80, .auto_corr_min_ofdm_mrc = 128, .auto_corr_min_ofdm_x1 = 105, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 907a0b22f7b2..9e187f8f5ae4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -75,9 +75,8 @@ static void iwl5000_nic_config(struct iwl_priv *priv) ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); } -static struct iwl_sensitivity_ranges iwl5000_sensitivity = { +static const struct iwl_sensitivity_ranges iwl5000_sensitivity = { .min_nrg_cck = 100, - .max_nrg_cck = 0, /* not used, set to 0 */ .auto_corr_min_ofdm = 90, .auto_corr_min_ofdm_mrc = 170, .auto_corr_min_ofdm_x1 = 105, @@ -102,7 +101,6 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = { static struct iwl_sensitivity_ranges iwl5150_sensitivity = { .min_nrg_cck = 95, - .max_nrg_cck = 0, /* not used, set to 0 */ .auto_corr_min_ofdm = 90, .auto_corr_min_ofdm_mrc = 170, .auto_corr_min_ofdm_x1 = 105, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 0f89e45da1a2..e64bc6b7bcbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -113,9 +113,8 @@ static void iwl6000_nic_config(struct iwl_priv *priv) cfg(priv)->additional_nic_config(priv); } -static struct iwl_sensitivity_ranges iwl6000_sensitivity = { +static const struct iwl_sensitivity_ranges iwl6000_sensitivity = { .min_nrg_cck = 110, - .max_nrg_cck = 0, /* not used, set to 0 */ .auto_corr_min_ofdm = 80, .auto_corr_min_ofdm_mrc = 128, .auto_corr_min_ofdm_x1 = 105, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 74429702b130..c3f372e2c142 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -294,7 +294,6 @@ struct iwl_vif_priv { struct iwl_sensitivity_ranges { u16 min_nrg_cck; - u16 max_nrg_cck; u16 nrg_th_cck; u16 nrg_th_ofdm; -- cgit v1.2.3-70-g09d2 From 9441b85d59ec9d06cbe749e12a59a06c09e601fa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:22 -0800 Subject: iwlwifi: return error if loading uCode failed In "iwlwifi: consolidate the start_device flow" the code flow changed and the firmware is now loaded by the transport layer, but the change unfortunately lost error checking -- restore. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 1c4fbcd348a8..ef76a3916189 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1070,9 +1070,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); /* Load the given image to the HW */ - iwl_load_given_ucode(trans, fw); - - return 0; + return iwl_load_given_ucode(trans, fw); } /* -- cgit v1.2.3-70-g09d2 From aa5affbacb24cb5d8fd6f7c66e57d62164ed6d34 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 7 Mar 2012 09:52:23 -0800 Subject: iwlwifi: dump stack when fail to gain access to the device Print dump stack when the device is not responding. This should give some more clue about the reason of failure. Also change the message we print, since "MAC in deep sleep" is kinda confusing. On the way add unlikely(), as fail to gain NIC access is hmm ... unlikely. Signed-off-by: Stanislaw Gruszka Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-io.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index e2e3b5c9cf7f..fc365350a3e7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -121,10 +121,10 @@ int iwl_grab_nic_access_silent(struct iwl_trans *trans) int iwl_grab_nic_access(struct iwl_trans *trans) { int ret = iwl_grab_nic_access_silent(trans); - if (ret) { + if (unlikely(ret)) { u32 val = iwl_read32(trans, CSR_GP_CNTRL); - IWL_ERR(trans, - "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); + WARN_ONCE(1, "Timeout waiting for hardware access " + "(CSR_GP_CNTRL 0x%08x)\n", val); } return ret; -- cgit v1.2.3-70-g09d2 From bfe4b80e9f7385f34986736cdc094be56782109a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 7 Mar 2012 09:52:24 -0800 Subject: iwlwifi: always check if got h/w access before write Before we write to the device registers always check if iwl_grap_nic_access() was successful. On the way change return type of grab_nic_access() to bool, and add likely()/unlikely() statement. Signed-off-by: Stanislaw Gruszka Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-io.c | 53 +++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-io.h | 2 +- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 4 +- 6 files changed, 35 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 7712c5537370..9a12b70c7d4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -189,7 +189,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) } iwl_read32(trans(priv), CSR_UCODE_DRV_GP1); spin_lock_irqsave(&trans(priv)->reg_lock, flags); - if (!iwl_grab_nic_access(trans(priv))) + if (likely(iwl_grab_nic_access(trans(priv)))) iwl_release_nic_access(trans(priv)); spin_unlock_irqrestore(&trans(priv)->reg_lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 5f390f8d3b8b..ce9ebeb89e4c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -327,7 +327,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, /* Make sure device is powered up for SRAM reads */ spin_lock_irqsave(&trans(priv)->reg_lock, reg_flags); - if (iwl_grab_nic_access(trans(priv))) { + if (unlikely(!iwl_grab_nic_access(trans(priv)))) { spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index fc365350a3e7..fa69845954cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -118,16 +118,17 @@ int iwl_grab_nic_access_silent(struct iwl_trans *trans) return 0; } -int iwl_grab_nic_access(struct iwl_trans *trans) +bool iwl_grab_nic_access(struct iwl_trans *trans) { int ret = iwl_grab_nic_access_silent(trans); if (unlikely(ret)) { u32 val = iwl_read32(trans, CSR_GP_CNTRL); WARN_ONCE(1, "Timeout waiting for hardware access " "(CSR_GP_CNTRL 0x%08x)\n", val); + return false; } - return ret; + return true; } void iwl_release_nic_access(struct iwl_trans *trans) @@ -156,7 +157,7 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) unsigned long flags; spin_lock_irqsave(&trans->reg_lock, flags); - if (!iwl_grab_nic_access(trans)) { + if (likely(iwl_grab_nic_access(trans))) { iwl_write32(trans, reg, value); iwl_release_nic_access(trans); } @@ -211,7 +212,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val) unsigned long flags; spin_lock_irqsave(&trans->reg_lock, flags); - if (!iwl_grab_nic_access(trans)) { + if (likely(iwl_grab_nic_access(trans))) { __iwl_write_prph(trans, addr, val); iwl_release_nic_access(trans); } @@ -223,9 +224,11 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) unsigned long flags; spin_lock_irqsave(&trans->reg_lock, flags); - iwl_grab_nic_access(trans); - __iwl_write_prph(trans, reg, __iwl_read_prph(trans, reg) | mask); - iwl_release_nic_access(trans); + if (likely(iwl_grab_nic_access(trans))) { + __iwl_write_prph(trans, reg, + __iwl_read_prph(trans, reg) | mask); + iwl_release_nic_access(trans); + } spin_unlock_irqrestore(&trans->reg_lock, flags); } @@ -235,10 +238,11 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg, unsigned long flags; spin_lock_irqsave(&trans->reg_lock, flags); - iwl_grab_nic_access(trans); - __iwl_write_prph(trans, reg, - (__iwl_read_prph(trans, reg) & mask) | bits); - iwl_release_nic_access(trans); + if (likely(iwl_grab_nic_access(trans))) { + __iwl_write_prph(trans, reg, + (__iwl_read_prph(trans, reg) & mask) | bits); + iwl_release_nic_access(trans); + } spin_unlock_irqrestore(&trans->reg_lock, flags); } @@ -248,10 +252,11 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask) u32 val; spin_lock_irqsave(&trans->reg_lock, flags); - iwl_grab_nic_access(trans); - val = __iwl_read_prph(trans, reg); - __iwl_write_prph(trans, reg, (val & ~mask)); - iwl_release_nic_access(trans); + if (likely(iwl_grab_nic_access(trans))) { + val = __iwl_read_prph(trans, reg); + __iwl_write_prph(trans, reg, (val & ~mask)); + iwl_release_nic_access(trans); + } spin_unlock_irqrestore(&trans->reg_lock, flags); } @@ -263,15 +268,13 @@ void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, u32 *vals = buf; spin_lock_irqsave(&trans->reg_lock, flags); - iwl_grab_nic_access(trans); - - iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); - rmb(); - - for (offs = 0; offs < words; offs++) - vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); - - iwl_release_nic_access(trans); + if (likely(iwl_grab_nic_access(trans))) { + iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); + rmb(); + for (offs = 0; offs < words; offs++) + vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); + iwl_release_nic_access(trans); + } spin_unlock_irqrestore(&trans->reg_lock, flags); } @@ -292,7 +295,7 @@ int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, u32 *vals = buf; spin_lock_irqsave(&trans->reg_lock, flags); - if (!iwl_grab_nic_access(trans)) { + if (likely(iwl_grab_nic_access(trans))) { iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); wmb(); diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 1136dc19936a..09b856768f62 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -61,7 +61,7 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, int timeout); int iwl_grab_nic_access_silent(struct iwl_trans *trans); -int iwl_grab_nic_access(struct iwl_trans *trans); +bool iwl_grab_nic_access(struct iwl_trans *trans); void iwl_release_nic_access(struct iwl_trans *trans); u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg); diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index bdcbbd0d3467..91a42c3261aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -445,7 +445,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) if (iwlagn_hw_valid_rtc_data_addr(base)) { spin_lock_irqsave(&trans(priv)->reg_lock, flags); ret = iwl_grab_nic_access_silent(trans(priv)); - if (ret == 0) { + if (likely(ret == 0)) { iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, base); status = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); iwl_release_nic_access(trans(priv)); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 83cc60e8f607..5d1fc7b1b0a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -745,7 +745,8 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, /* Make sure device is powered up for SRAM reads */ spin_lock_irqsave(&trans->reg_lock, reg_flags); - iwl_grab_nic_access(trans); + if (unlikely(!iwl_grab_nic_access(trans))) + goto out_unlock; /* Set starting address; reads will auto-increment */ iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr); @@ -785,6 +786,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, /* Allow device to power down */ iwl_release_nic_access(trans); +out_unlock: spin_unlock_irqrestore(&trans->reg_lock, reg_flags); return pos; } -- cgit v1.2.3-70-g09d2 From 3a73a30049f20a0ff3ef1c5c10170a9c5539e042 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 7 Mar 2012 09:52:25 -0800 Subject: iwlwifi: cleanup/fix memory barriers wmb(), rmb() are not needed when writel(), readl() are used as accessors for MMIO. We use them indirectly via iowrite32(), ioread32(). What is needed mmiowb(), for synchronizing writes coming from different CPUs on PCIe bridge (see in patch comments). This fortunately is not needed on x86, where mmiowb() is just defined as compiler barrier. As iwlwifi devices are most likely not used on anything other than x86, this is not so important fix. Signed-off-by: Stanislaw Gruszka Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl-io.c | 12 +++++++----- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 1 - 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ce9ebeb89e4c..64bc2859dd1b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -334,7 +334,6 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, /* Set starting address; reads will auto-increment */ iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, ptr); - rmb(); /* * Refuse to read more than would have fit into the log from diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index fa69845954cf..081dd34d2387 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -136,6 +136,13 @@ void iwl_release_nic_access(struct iwl_trans *trans) lockdep_assert_held(&trans->reg_lock); __iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + /* + * Above we read the CSR_GP_CNTRL register, which will flush + * any previous writes, but we need the write that clears the + * MAC_ACCESS_REQ bit to be performed before any other writes + * scheduled on different CPUs (after we drop reg_lock). + */ + mmiowb(); } u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) @@ -182,7 +189,6 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg) { iwl_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); - rmb(); return iwl_read32(trans, HBUS_TARG_PRPH_RDAT); } @@ -190,7 +196,6 @@ static inline void __iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val) { iwl_write32(trans, HBUS_TARG_PRPH_WADDR, ((addr & 0x0000FFFF) | (3 << 24))); - wmb(); iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); } @@ -270,7 +275,6 @@ void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr, spin_lock_irqsave(&trans->reg_lock, flags); if (likely(iwl_grab_nic_access(trans))) { iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); - rmb(); for (offs = 0; offs < words; offs++) vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); iwl_release_nic_access(trans); @@ -297,8 +301,6 @@ int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr, spin_lock_irqsave(&trans->reg_lock, flags); if (likely(iwl_grab_nic_access(trans))) { iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); - wmb(); - for (offs = 0; offs < words; offs++) iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]); iwl_release_nic_access(trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 5d1fc7b1b0a3..787229b352f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -750,7 +750,6 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, /* Set starting address; reads will auto-increment */ iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr); - rmb(); /* "time" is actually "data" for mode 0 (no timestamp). * place event id # at far right for easier visual parsing. */ -- cgit v1.2.3-70-g09d2 From 05f5b97ee0013fefbd9139cf8c3eda5f2a88c04a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 7 Mar 2012 09:52:26 -0800 Subject: iwlwifi: use writeb,writel,readl directly That change will save us some CPU cycles at run time. Having port-based I/O seems to be not possible for PCIe devices. Signed-off-by: Stanislaw Gruszka Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index ae08498dfcad..5afd06ef0d8b 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -1,6 +1,6 @@ config IWLWIFI tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) " - depends on PCI && MAC80211 + depends on PCI && MAC80211 && HAS_IOMEM select FW_LOADER select NEW_LEDS select LEDS_CLASS diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index ef76a3916189..389f99e6a8eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1600,18 +1600,17 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) { - iowrite8(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); + writeb(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); } static void iwl_trans_pcie_write32(struct iwl_trans *trans, u32 ofs, u32 val) { - iowrite32(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); + writel(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); } static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs) { - u32 val = ioread32(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); - return val; + return readl(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); } static void iwl_trans_pcie_free(struct iwl_trans *trans) @@ -1629,7 +1628,7 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans) } pci_disable_msi(trans_pcie->pci_dev); - pci_iounmap(trans_pcie->pci_dev, trans_pcie->hw_base); + iounmap(trans_pcie->hw_base); pci_release_regions(trans_pcie->pci_dev); pci_disable_device(trans_pcie->pci_dev); @@ -2258,9 +2257,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, goto out_pci_disable_device; } - trans_pcie->hw_base = pci_iomap(pdev, 0, 0); + trans_pcie->hw_base = pci_ioremap_bar(pdev, 0); if (!trans_pcie->hw_base) { - dev_printk(KERN_ERR, &pdev->dev, "pci_iomap failed"); + dev_printk(KERN_ERR, &pdev->dev, "pci_ioremap_bar failed"); err = -ENODEV; goto out_pci_release_regions; } -- cgit v1.2.3-70-g09d2 From c2945f390dbc725f3c3ef044a6a3f4e3909a7758 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 7 Mar 2012 09:52:27 -0800 Subject: iwlwifi: print DMA stop timeout error only if it happened iwl_poll_direct_bit() return negative error value on timeout, positive values do not indicate an error. Signed-off-by: Stanislaw Gruszka Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 389f99e6a8eb..aced6f8ae1e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1211,7 +1211,7 @@ static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans) */ static int iwl_trans_tx_stop(struct iwl_trans *trans) { - int ch, txq_id; + int ch, txq_id, ret; unsigned long flags; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1224,9 +1224,10 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); - if (iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG, + ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG, FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), - 1000)) + 1000); + if (ret < 0) IWL_ERR(trans, "Failing on timeout while stopping" " DMA channel %d [0x%08x]", ch, iwl_read_direct32(trans, -- cgit v1.2.3-70-g09d2 From 8722c899a07f45457464803142bd1c2d2a2c3bd8 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 7 Mar 2012 09:52:28 -0800 Subject: iwlwifi: reintroduce iwl_enable_rfkill_int If device is disabled by rfkill switch, do not enable all interrupts, but only CSR_INT_BIT_RF_KILL to receive rfkill state change. Unblocking other interrupts might cause problems, since driver can not be prepared for receive them. Signed-off-by: Stanislaw Gruszka Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 6 ++---- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 13 ++++++++----- 3 files changed, 16 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 4f73a6d06509..93d89a375a1c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -376,6 +376,12 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans) iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); } +static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) +{ + IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); + iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); +} + /* * we have 8 bits used like this: * diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 787229b352f6..2d6ea42b0d8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1134,10 +1134,8 @@ void iwl_irq_tasklet(struct iwl_trans *trans) if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status)) iwl_enable_interrupts(trans); /* Re-enable RF_KILL if it occurred */ - else if (handled & CSR_INT_BIT_RF_KILL) { - IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); - iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); - } + else if (handled & CSR_INT_BIT_RF_KILL) + iwl_enable_rfkill_int(trans); } /****************************************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index aced6f8ae1e9..88e1c427f8f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1044,7 +1044,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); if (hw_rfkill) { - iwl_enable_interrupts(trans); + iwl_enable_rfkill_int(trans); return -ERFKILL; } @@ -1553,8 +1553,7 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans) iwl_write32(trans, CSR_INT, 0xFFFFFFFF); /* Even if we stop the HW, we still want the RF kill interrupt */ - IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); - iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); + iwl_enable_rfkill_int(trans); } static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, @@ -1647,10 +1646,14 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) { bool hw_rfkill; - iwl_enable_interrupts(trans); - hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); + + if (hw_rfkill) + iwl_enable_rfkill_int(trans); + else + iwl_enable_interrupts(trans); + iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); return 0; -- cgit v1.2.3-70-g09d2 From 0aef8ddc8bedac1db4c96fddc9fb1b44b730cf4f Mon Sep 17 00:00:00 2001 From: Amit Beka Date: Wed, 7 Mar 2012 09:52:29 -0800 Subject: iwlwifi: add testmode command for rx forwarding Added a testmode command which tells iwl_rx_dispatch to send the RX both as a notification to nl80211 and with the registered RX handlers. This is used for monitoring RX from userspace while preserving the regular flows in the driver. Signed-off-by: Amit Beka Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 20 ++++++++++++++---- drivers/net/wireless/iwlwifi/iwl-testmode.c | 32 ++++++++++++++++++++++++++--- drivers/net/wireless/iwlwifi/iwl-testmode.h | 13 ++++++++++-- 3 files changed, 56 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index e504675f2637..8e7cdfaf10cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -1152,6 +1152,8 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); + void (*pre_rx_handler)(struct iwl_priv *, + struct iwl_rx_cmd_buffer *); int err = 0; /* @@ -1161,10 +1163,20 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, */ iwl_notification_wait_notify(&priv->notif_wait, pkt); - if (priv->pre_rx_handler && - priv->ucode_owner == IWL_OWNERSHIP_TM) - priv->pre_rx_handler(priv, rxb); - else { + /* RX data may be forwarded to userspace (using pre_rx_handler) in one + * of two cases: the first, that the user owns the uCode through + * testmode - in such case the pre_rx_handler is set and no further + * processing takes place. The other case is when the user want to + * monitor the rx w/o affecting the regular flow - the pre_rx_handler + * will be set but the ownership flag != IWL_OWNERSHIP_TM and the flow + * continues. + * We need to use ACCESS_ONCE to prevent a case where the handler + * changes between the check and the call. + */ + pre_rx_handler = ACCESS_ONCE(priv->pre_rx_handler); + if (pre_rx_handler) + pre_rx_handler(priv, rxb); + if (priv->ucode_owner != IWL_OWNERSHIP_TM) { /* Based on type of command response or notification, * handle those that need handling via function in * rx_handlers table. See iwl_setup_rx_handlers() */ diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 1d732092ebe7..b8044bcd5044 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -125,6 +125,8 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { [IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, }, [IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, }, [IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, }, + + [IWL_TM_ATTR_ENABLE_NOTIFICATION] = {.type = NLA_FLAG, }, }; /* @@ -194,7 +196,7 @@ nla_put_failure: void iwl_testmode_init(struct iwl_priv *priv) { - priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; + priv->pre_rx_handler = NULL; priv->testmode_trace.trace_enabled = false; priv->testmode_mem.read_in_progress = false; } @@ -770,9 +772,13 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) } owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); - if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM)) + if (owner == IWL_OWNERSHIP_DRIVER) { priv->ucode_owner = owner; - else { + priv->pre_rx_handler = NULL; + } else if (owner == IWL_OWNERSHIP_TM) { + priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; + priv->ucode_owner = owner; + } else { IWL_ERR(priv, "Invalid owner\n"); return -EINVAL; } @@ -937,6 +943,20 @@ static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, return -ENOBUFS; } +static int iwl_testmode_notifications(struct ieee80211_hw *hw, + struct nlattr **tb) +{ + struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); + bool enable; + + enable = nla_get_flag(tb[IWL_TM_ATTR_ENABLE_NOTIFICATION]); + if (enable) + priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; + else + priv->pre_rx_handler = NULL; + return 0; +} + /* 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 @@ -1022,6 +1042,12 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) result = iwl_testmode_indirect_mem(hw, tb); break; + case IWL_TM_CMD_APP2DEV_NOTIFICATIONS: + IWL_DEBUG_INFO(priv, "testmode notifications cmd " + "to driver\n"); + result = iwl_testmode_notifications(hw, tb); + break; + default: IWL_ERR(priv, "Unknown testmode command\n"); result = -ENOSYS; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 69b2e80f4071..6ba211b09426 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -122,6 +122,9 @@ * Fore reading, a READ command is sent from the userspace and the data * is returned when the user calls a DUMP command. * For writing, only a WRITE command is used. + * @IWL_TM_CMD_APP2DEV_NOTIFICATIONS: + * Command to enable/disable notifications (currently RX packets) from the + * driver to userspace. */ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_UCODE = 1, @@ -152,7 +155,8 @@ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ = 26, IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP = 27, IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE = 28, - IWL_TM_CMD_MAX = 29, + IWL_TM_CMD_APP2DEV_NOTIFICATIONS = 29, + IWL_TM_CMD_MAX = 30, }; /* @@ -256,6 +260,10 @@ enum iwl_tm_cmd_t { * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE this flag * indicates that the user wants to receive the response of the command * in a reply SKB. If it's not present, the response is not returned. + * @IWL_TM_ATTR_ENABLE_NOTIFICATIONS: + * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_NOTIFICATIONS, this + * flag enables (if present) or disables (if not) the forwarding + * to userspace. */ enum iwl_tm_attr_t { IWL_TM_ATTR_NOT_APPLICABLE = 0, @@ -282,7 +290,8 @@ enum iwl_tm_attr_t { IWL_TM_ATTR_FW_INST_SIZE = 21, IWL_TM_ATTR_FW_DATA_SIZE = 22, IWL_TM_ATTR_UCODE_CMD_SKB = 23, - IWL_TM_ATTR_MAX = 24, + IWL_TM_ATTR_ENABLE_NOTIFICATION = 24, + IWL_TM_ATTR_MAX = 25, }; /* uCode trace buffer */ -- cgit v1.2.3-70-g09d2 From 8e81f65fdc7f5d292bb3c115b748767d921823c1 Mon Sep 17 00:00:00 2001 From: Amit Beka Date: Wed, 7 Mar 2012 09:52:30 -0800 Subject: iwlwifi: fixed testmode notifications length The length of iwl_rx_packet doesn't include the dword for the length itself, so add it manually. Signed-off-by: Amit Beka Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-testmode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index b8044bcd5044..b06c6763cb7a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -185,7 +185,8 @@ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv, 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); + /* the length doesn't include len_n_flags field, so add it manually */ + NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length + sizeof(__le32), data); cfg80211_testmode_event(skb, GFP_ATOMIC); return; -- cgit v1.2.3-70-g09d2 From 18c57d3c1e31a91a5925da001c19d521178d00bd Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Wed, 7 Mar 2012 09:52:31 -0800 Subject: iwlwifi: add option to test MFP Add a Kconfig symbol to enable MFP for testing even if the firmware file doesn't advertise it. Signed-off-by: David Spinadel Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 9 +++++++++ drivers/net/wireless/iwlwifi/iwl-mac80211.c | 3 +++ 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 5afd06ef0d8b..2fe62730dddd 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -127,3 +127,12 @@ config IWLWIFI_P2P support when it is loaded. Say Y only if you want to experiment with P2P. + +config IWLWIFI_EXPERIMENTAL_MFP + bool "support MFP (802.11w) even if uCode doesn't advertise" + depends on IWLWIFI + help + This option enables experimental MFP (802.11W) support + even if the microcode doesn't advertise it. + + Say Y only if you want to experiment with MFP. diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 91a42c3261aa..dcf39f84f239 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -163,7 +163,10 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | IEEE80211_HW_SUPPORTS_STATIC_SMPS; +#ifndef CONFIG_IWLWIFI_EXPERIMENTAL_MFP + /* enable 11w if the uCode advertise */ if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP) +#endif /* !CONFIG_IWLWIFI_EXPERIMENTAL_MFP */ hw->flags |= IEEE80211_HW_MFP_CAPABLE; hw->sta_data_size = sizeof(struct iwl_station_priv); -- cgit v1.2.3-70-g09d2 From 9a716863ae4a2f039bc4d0b2b2bb4b24a1dc7a91 Mon Sep 17 00:00:00 2001 From: Don Fry Date: Wed, 7 Mar 2012 09:52:32 -0800 Subject: iwlwifi: separate status to priv and trans The shared status bits are a mixture of transport and op mode bits. Some are used just by one or the other, some are shared. Begin the de-tangling of these bits. 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 | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 16 +++++++--------- drivers/net/wireless/iwlwifi/iwl-agn.h | 9 ++------- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 6 +----- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 2 -- 7 files changed, 14 insertions(+), 24 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 6d8a8578778c..3fed4bbb7e82 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1291,7 +1291,7 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan) int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { - if (iwl_is_rfkill(priv->shrd) || iwl_is_ctkill(priv->shrd)) { + if (iwl_is_rfkill(priv->shrd) || iwl_is_ctkill(priv)) { IWL_WARN(priv, "Not sending command - %s KILL\n", iwl_is_rfkill(priv->shrd) ? "RF" : "CT"); return -EIO; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 9a12b70c7d4f..fa9415309cd6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -233,7 +233,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data) IWL_DEBUG_TEMP(priv, "entering CT_KILL state when " "temperature timer expired\n"); tt->state = IWL_TI_CT_KILL; - set_bit(STATUS_CT_KILL, &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); iwl_perform_ct_kill_task(priv, true); } } @@ -313,22 +313,21 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) } mutex_lock(&priv->mutex); if (old_state == IWL_TI_CT_KILL) - clear_bit(STATUS_CT_KILL, &priv->shrd->status); + clear_bit(STATUS_CT_KILL, &priv->status); if (tt->state != IWL_TI_CT_KILL && iwl_power_update_mode(priv, true)) { /* TT state not updated * try again during next temperature read */ if (old_state == IWL_TI_CT_KILL) - set_bit(STATUS_CT_KILL, &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); tt->state = old_state; IWL_ERR(priv, "Cannot update power mode, " "TT state not updated\n"); } else { if (tt->state == IWL_TI_CT_KILL) { if (force) { - set_bit(STATUS_CT_KILL, - &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); iwl_perform_ct_kill_task(priv, true); } else { iwl_prepare_ct_kill_task(priv); @@ -454,7 +453,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) } mutex_lock(&priv->mutex); if (old_state == IWL_TI_CT_KILL) - clear_bit(STATUS_CT_KILL, &priv->shrd->status); + clear_bit(STATUS_CT_KILL, &priv->status); if (tt->state != IWL_TI_CT_KILL && iwl_power_update_mode(priv, true)) { /* TT state not updated @@ -463,7 +462,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) IWL_ERR(priv, "Cannot update power mode, " "TT state not updated\n"); if (old_state == IWL_TI_CT_KILL) - set_bit(STATUS_CT_KILL, &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); tt->state = old_state; } else { IWL_DEBUG_TEMP(priv, @@ -474,8 +473,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) if (force) { IWL_DEBUG_TEMP(priv, "Enter IWL_TI_CT_KILL\n"); - set_bit(STATUS_CT_KILL, - &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); iwl_perform_ct_kill_task(priv, true); } else { iwl_prepare_ct_kill_task(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 6345ab0f2a96..ede1852b1d7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -367,11 +367,6 @@ static inline int iwl_is_alive(struct iwl_shared *shrd) return test_bit(STATUS_ALIVE, &shrd->status); } -static inline int iwl_is_init(struct iwl_shared *shrd) -{ - return test_bit(STATUS_INIT, &shrd->status); -} - static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd) { return test_bit(STATUS_RF_KILL_HW, &shrd->status); @@ -382,9 +377,9 @@ static inline int iwl_is_rfkill(struct iwl_shared *shrd) return iwl_is_rfkill_hw(shrd); } -static inline int iwl_is_ctkill(struct iwl_shared *shrd) +static inline int iwl_is_ctkill(struct iwl_priv *priv) { - return test_bit(STATUS_CT_KILL, &shrd->status); + return test_bit(STATUS_CT_KILL, &priv->status); } static inline int iwl_is_ready_rf(struct iwl_shared *shrd) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 0a898c54c733..1c235d685ae6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -530,15 +530,11 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", - test_bit(STATUS_CT_KILL, &priv->shrd->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", - test_bit(STATUS_INIT, &priv->shrd->status)); + test_bit(STATUS_CT_KILL, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", test_bit(STATUS_ALIVE, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", test_bit(STATUS_READY, &priv->shrd->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n", - test_bit(STATUS_TEMPERATURE, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c3f372e2c142..1b05faea7965 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -713,6 +713,7 @@ struct iwl_priv { /*data shared among all the driver's layers */ struct iwl_shared *shrd; const struct iwl_fw *fw; + unsigned long status; spinlock_t sta_lock; struct mutex mutex; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 93d89a375a1c..16a32ae4046e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -247,6 +247,7 @@ struct iwl_tx_queue { * @hw_base: pci hardware address support * @ucode_write_complete: indicates that the ucode has been copied. * @ucode_write_waitq: wait queue for uCode load + * @status - transport specific status flags */ struct iwl_trans_pcie { struct iwl_rx_queue rxq; @@ -287,6 +288,7 @@ struct iwl_trans_pcie { bool ucode_write_complete; wait_queue_head_t ucode_write_waitq; + unsigned long status; }; #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 88e1c427f8f5..e78098e79ee1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -833,8 +833,6 @@ static int iwl_nic_init(struct iwl_trans *trans) 0x800FFFFF); } - set_bit(STATUS_INIT, &trans->shrd->status); - return 0; } -- cgit v1.2.3-70-g09d2 From 354928dd00d0437149991fad7637c411ba1c62f0 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 7 Mar 2012 09:52:33 -0800 Subject: iwlwifi: make tx_cmd_pool kmem cache global Otherwise we are not able to run more than one device per driver: [ 24.743045] kmem_cache_create: duplicate cache iwl_dev_cmd [ 24.743051] Pid: 3165, comm: NetworkManager Not tainted 3.3.0-rc2-wl+ #5 [ 24.743054] Call Trace: [ 24.743066] [] kmem_cache_create+0x655/0x700 [ 24.743101] [] iwl_alive_notify+0x1cb/0x1f0 [iwlwifi] [ 24.743111] [] iwl_load_ucode_wait_alive+0x1b2/0x220 [iwlwifi] [ 24.743142] [] iwl_run_init_ucode+0x73/0x100 [iwlwifi] [ 24.743152] [] __iwl_up+0x81/0x220 [iwlwifi] [ 24.743161] [] iwlagn_mac_start+0x80/0x190 [iwlwifi] [ 24.743188] [] ieee80211_do_open+0x293/0x770 [mac80211] Signed-off-by: Stanislaw Gruszka Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 21 +++++++++++++++------ drivers/net/wireless/iwlwifi/iwl-core.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-ucode.c | 9 --------- 5 files changed, 21 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index a19db4c0c9fa..97ebfd26212e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -367,7 +367,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (info->flags & IEEE80211_TX_CTL_AMPDU) is_agg = true; - dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC); + dev_cmd = kmem_cache_alloc(iwl_tx_cmd_pool, GFP_ATOMIC); if (unlikely(!dev_cmd)) goto drop_unlock_priv; @@ -458,7 +458,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) drop_unlock_sta: if (dev_cmd) - kmem_cache_free(priv->tx_cmd_pool, dev_cmd); + kmem_cache_free(iwl_tx_cmd_pool, dev_cmd); spin_unlock(&priv->sta_lock); drop_unlock_priv: return -1; @@ -1078,7 +1078,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, info = IEEE80211_SKB_CB(skb); ctx = info->driver_data[0]; - kmem_cache_free(priv->tx_cmd_pool, + kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); memset(&info->status, 0, sizeof(info->status)); @@ -1229,7 +1229,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, WARN_ON_ONCE(1); info = IEEE80211_SKB_CB(skb); - kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1])); + kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); if (freed == 1) { /* this is the first skb we deliver in this batch */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 64bc2859dd1b..7927e3e11097 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1102,8 +1102,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv) { iwl_free_geos(priv); iwl_free_channel_map(priv); - if (priv->tx_cmd_pool) - kmem_cache_destroy(priv->tx_cmd_pool); kfree(priv->scan_cmd); kfree(priv->beacon_cmd); kfree(rcu_dereference_raw(priv->noa_data)); @@ -1477,6 +1475,9 @@ const struct iwl_op_mode_ops iwl_dvm_ops = { * driver and module entry point * *****************************************************************************/ + +struct kmem_cache *iwl_tx_cmd_pool; + static int __init iwl_init(void) { @@ -1484,20 +1485,27 @@ static int __init iwl_init(void) pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); pr_info(DRV_COPYRIGHT "\n"); + iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd", + sizeof(struct iwl_device_cmd), + sizeof(void *), 0, NULL); + if (!iwl_tx_cmd_pool) + return -ENOMEM; + ret = iwlagn_rate_control_register(); if (ret) { pr_err("Unable to register rate control algorithm: %d\n", ret); - return ret; + goto error_rc_register; } ret = iwl_pci_register_driver(); - if (ret) - goto error_register; + goto error_pci_register; return ret; -error_register: +error_pci_register: iwlagn_rate_control_unregister(); +error_rc_register: + kmem_cache_destroy(iwl_tx_cmd_pool); return ret; } @@ -1505,6 +1513,7 @@ static void __exit iwl_exit(void) { iwl_pci_unregister_driver(); iwlagn_rate_control_unregister(); + kmem_cache_destroy(iwl_tx_cmd_pool); } module_exit(iwl_exit); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f50bd4263b88..df7b165b290c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1470,10 +1470,9 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) { - struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); struct ieee80211_tx_info *info; info = IEEE80211_SKB_CB(skb); - kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1])); + kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); dev_kfree_skb_any(skb); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 1b05faea7965..aa4b3b122da4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -725,7 +725,6 @@ struct iwl_priv { struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; struct ieee80211_rate *ieee_rates; - struct kmem_cache *tx_cmd_pool; struct list_head calib_results; @@ -983,6 +982,7 @@ struct iwl_priv { bool have_rekey_data; }; /*iwl_priv */ +extern struct kmem_cache *iwl_tx_cmd_pool; extern struct iwl_mod_params iwlagn_mod_params; static inline struct iwl_rxon_context * diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 404fd8e7958b..d97cf44b75ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -318,15 +318,6 @@ static int iwl_alive_notify(struct iwl_priv *priv) { int ret; - if (!priv->tx_cmd_pool) - priv->tx_cmd_pool = - kmem_cache_create("iwl_dev_cmd", - sizeof(struct iwl_device_cmd), - sizeof(void *), 0, NULL); - - if (!priv->tx_cmd_pool) - return -ENOMEM; - iwl_trans_fw_alive(trans(priv)); priv->passive_no_rx = false; -- cgit v1.2.3-70-g09d2 From 3251715dc51a8cbd2cd030ff94fe36f37b4b9e74 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 7 Mar 2012 09:52:34 -0800 Subject: iwlwifi: log stop / wake queues There were a few missing occurences when we get PASSIVE_NO_RX notification. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 97ebfd26212e..ac5c1311ef33 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1088,6 +1088,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, ctx->vif->type == NL80211_IFTYPE_STATION) { /* block and stop all queues */ priv->passive_no_rx = true; + IWL_DEBUG_TX_QUEUES(priv, "stop all queues: " + "passive channel"); ieee80211_stop_queues(priv->hw); IWL_DEBUG_TX_REPLY(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7927e3e11097..6ed2f782177b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1450,8 +1450,12 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv) return; for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) { - if (!test_bit(ac, &priv->transport_queue_stop)) + if (!test_bit(ac, &priv->transport_queue_stop)) { + IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d"); ieee80211_wake_queue(priv->hw, ac); + } else { + IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d"); + } } priv->passive_no_rx = false; -- cgit v1.2.3-70-g09d2 From 92d743ae105314a865b3fca9128da11525d22203 Mon Sep 17 00:00:00 2001 From: Meenakshi Venkataraman Date: Wed, 7 Mar 2012 09:52:35 -0800 Subject: iwlwifi: configure transport layer from dvm op mode Introduce the iwl_trans_config struct which contains state variables that only the op mode can determine, but which the transport layer needs to know. Signed-off-by: Meenakshi Venkataraman Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 +++++++++- drivers/net/wireless/iwlwifi/iwl-trans.h | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6ed2f782177b..83018ec11bc7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1185,6 +1185,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, struct iwl_op_mode *op_mode; u16 num_mac; u32 ucode_flags; + struct iwl_trans_config trans_cfg; /************************ * 1. Allocating HW data @@ -1205,7 +1206,14 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, /* TODO: remove fw from shared data later */ priv->shrd->fw = fw; - iwl_trans_configure(trans(priv), op_mode); + /* + * Populate the state variables that the transport layer needs + * to know about. + */ + trans_cfg.op_mode = op_mode; + + /* Configure transport layer */ + iwl_trans_configure(trans(priv), &trans_cfg); /* At this point both hw and priv are allocated. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index ed6ab449e439..b6fd42779624 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -274,6 +274,16 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) return p; } +/** + * struct iwl_trans_config - transport configuration + * + * @op_mode: pointer to the upper layer. + * Must be set before any other call. + */ +struct iwl_trans_config { + struct iwl_op_mode *op_mode; +}; + /** * struct iwl_trans_ops - transport specific operations * @@ -408,13 +418,13 @@ struct iwl_trans { }; static inline void iwl_trans_configure(struct iwl_trans *trans, - struct iwl_op_mode *op_mode) + const struct iwl_trans_config *trans_cfg) { /* * only set the op_mode for the moment. Later on, this function will do * more */ - trans->op_mode = op_mode; + trans->op_mode = trans_cfg->op_mode; } static inline int iwl_trans_start_hw(struct iwl_trans *trans) -- cgit v1.2.3-70-g09d2 From 9bdfbfadc4f0b3a756b54e7ec7cfaf92c22ce258 Mon Sep 17 00:00:00 2001 From: Meenakshi Venkataraman Date: Wed, 7 Mar 2012 09:52:36 -0800 Subject: iwlwifi: move setting up fw parameters Gather parameters required to configure the transport layer before invoking the transport configuration API. Change-Id: I5b39da284af6d9b5432a08911b4e1173a4d7207d Signed-off-by: Meenakshi Venkataraman Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 45 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 83018ec11bc7..397342402d1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1206,6 +1206,30 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, /* TODO: remove fw from shared data later */ priv->shrd->fw = fw; + /************************ + * 2. Setup HW constants + ************************/ + iwl_set_hw_params(priv); + + ucode_flags = fw->ucode_capa.flags; + +#ifndef CONFIG_IWLWIFI_P2P + ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; +#endif + if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE)) + ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; + + /* + * if not PAN, then don't support P2P -- might be a uCode + * packaging bug or due to the eeprom check above + */ + if (!(ucode_flags & IWL_UCODE_TLV_FLAGS_PAN)) + ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; + + + /***************************** + * Configure transport layer + *****************************/ /* * Populate the state variables that the transport layer needs * to know about. @@ -1286,27 +1310,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, priv->hw->wiphy->n_addresses++; } - /************************ - * 5. Setup HW constants - ************************/ - iwl_set_hw_params(priv); - - ucode_flags = fw->ucode_capa.flags; - -#ifndef CONFIG_IWLWIFI_P2P - ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; -#endif - if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE)) - ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; - - /* - * if not PAN, then don't support P2P -- might be a uCode - * packaging bug or due to the eeprom check above - */ - if (!(ucode_flags & IWL_UCODE_TLV_FLAGS_PAN)) - ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; - - /******************* * 6. Setup priv *******************/ -- cgit v1.2.3-70-g09d2 From 83626404a70da74c67f32f119e53c0ba032ba2d8 Mon Sep 17 00:00:00 2001 From: Don Fry Date: Wed, 7 Mar 2012 09:52:37 -0800 Subject: iwlwifi: more status bit factoring Continue splitting the status bits between transport and op_mode. All but a few are separated. 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 | 8 ++-- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 18 ++++---- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 14 +++---- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 6 +-- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 20 ++++----- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 4 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 40 +++++++++--------- drivers/net/wireless/iwlwifi/iwl-agn.h | 31 ++++++-------- drivers/net/wireless/iwlwifi/iwl-core.c | 31 +++++++------- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 38 ++++++++--------- drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 34 +++++++-------- drivers/net/wireless/iwlwifi/iwl-power.c | 4 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 50 +++++++++++------------ drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 8 ++-- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 10 ++--- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 8 ++-- 17 files changed, 160 insertions(+), 166 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 3fed4bbb7e82..915183a3a873 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -51,7 +51,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) struct iwlagn_tx_power_dbm_cmd tx_power_cmd; u8 tx_ant_cfg_cmd; - if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->shrd->status), + if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), "TX Power requested while scanning!\n")) return -EAGAIN; @@ -575,7 +575,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) * STATUS_SCANNING to avoid race when queue_work two times from * different notifications, but quit and not perform any work at all. */ - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) + if (test_bit(STATUS_SCAN_HW, &priv->status)) goto out; iwl_update_chain_flags(priv); @@ -1291,9 +1291,9 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan) int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { - if (iwl_is_rfkill(priv->shrd) || iwl_is_ctkill(priv)) { + if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { IWL_WARN(priv, "Not sending command - %s KILL\n", - iwl_is_rfkill(priv->shrd) ? "RF" : "CT"); + iwl_is_rfkill(priv) ? "RF" : "CT"); return -EIO; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 8e7cdfaf10cc..3ad43330f6a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -159,7 +159,7 @@ static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_cmd *rxon = (void *)&ctx->active; - if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) + if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) return 0; if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { @@ -355,7 +355,7 @@ static void iwlagn_recover_from_statistics(struct iwl_priv *priv, { unsigned int msecs; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies); @@ -575,7 +575,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, priv->rx_statistics_jiffies = stamp; - set_bit(STATUS_STATISTICS, &priv->shrd->status); + set_bit(STATUS_STATISTICS, &priv->status); /* Reschedule the statistics timer to occur in * reg_recalib_period seconds to ensure we get a @@ -584,7 +584,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv, mod_timer(&priv->statistics_periodic, jiffies + msecs_to_jiffies(reg_recalib_period * 1000)); - if (unlikely(!test_bit(STATUS_SCANNING, &priv->shrd->status)) && + if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { iwlagn_rx_calc_noise(priv); queue_work(priv->workqueue, &priv->run_time_calib_work); @@ -658,18 +658,18 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv, iwl_tt_exit_ct_kill(priv); if (flags & HW_CARD_DISABLED) - set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + set_bit(STATUS_RF_KILL_HW, &priv->status); else - clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + clear_bit(STATUS_RF_KILL_HW, &priv->status); if (!(flags & RXON_CARD_DISABLED)) iwl_scan_cancel(priv); if ((test_bit(STATUS_RF_KILL_HW, &status) != - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status))) + test_bit(STATUS_RF_KILL_HW, &priv->status))) wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); + test_bit(STATUS_RF_KILL_HW, &priv->status)); else wake_up(&priv->shrd->wait_command_queue); return 0; @@ -691,7 +691,7 @@ static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv, le32_to_cpu(missed_beacon->total_missed_becons), le32_to_cpu(missed_beacon->num_recvd_beacons), le32_to_cpu(missed_beacon->num_expected_beacons)); - if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) + if (!test_bit(STATUS_SCANNING, &priv->status)) iwl_init_sensitivity(priv); } return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 66e9a71aaac6..36909077f994 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -361,7 +361,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) slot0 = bcnint / 2; slot1 = bcnint - slot0; - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status) || + if (test_bit(STATUS_SCAN_HW, &priv->status) || (!ctx_bss->vif->bss_conf.idle && !ctx_bss->vif->bss_conf.assoc)) { slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; @@ -377,7 +377,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) ctx_pan->beacon_int; slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->status)) { slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME; slot1 = IWL_MIN_SLOT_TIME; } @@ -421,7 +421,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) lockdep_assert_held(&priv->mutex); - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EBUSY; /* This function hardcodes a bunch of dual-mode assumptions */ @@ -457,7 +457,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * receive commit_rxon request * abort any previous channel switch if still in process */ - if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status) && + if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) && (priv->switch_channel != ctx->staging.channel)) { IWL_DEBUG_11H(priv, "abort channel switch on %d\n", le16_to_cpu(priv->switch_channel)); @@ -551,12 +551,12 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&priv->mutex); - if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) { + if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); goto out; } - if (!iwl_is_ready(priv->shrd)) { + if (!iwl_is_ready(priv)) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); goto out; } @@ -794,7 +794,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - if (unlikely(!iwl_is_ready(priv->shrd))) { + if (unlikely(!iwl_is_ready(priv))) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); mutex_unlock(&priv->mutex); return; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index cf5cc1060cf4..23e9eab477bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -490,7 +490,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, { u8 tid; - if (!iwl_is_ready(priv->shrd)) { + if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, "Unable to remove station %pM, device not ready.\n", addr); @@ -598,7 +598,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) int ret; bool send_lq; - if (!iwl_is_ready(priv->shrd)) { + if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); return; @@ -997,7 +997,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, keyconf->keyidx); memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); - if (iwl_is_rfkill(priv->shrd)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); /* but keys in device are clear anyway so return success */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index fa9415309cd6..baaf5ba2fc38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -174,7 +174,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) struct iwl_tt_mgmt *tt = &priv->thermal_throttle; unsigned long flags; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (tt->state == IWL_TI_CT_KILL) { @@ -225,7 +225,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data) struct iwl_priv *priv = (struct iwl_priv *)data; struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* temperature timer expired, ready to go into CT_KILL state */ @@ -504,10 +504,10 @@ static void iwl_bg_ct_enter(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (!iwl_is_ready(priv->shrd)) + if (!iwl_is_ready(priv)) return; if (tt->state != IWL_TI_CT_KILL) { @@ -533,10 +533,10 @@ static void iwl_bg_ct_exit(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (!iwl_is_ready(priv->shrd)) + if (!iwl_is_ready(priv)) return; /* stop ct_kill_exit_tm timer */ @@ -563,7 +563,7 @@ static void iwl_bg_ct_exit(struct work_struct *work) void iwl_tt_enter_ct_kill(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n"); @@ -572,7 +572,7 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv) void iwl_tt_exit_ct_kill(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n"); @@ -584,7 +584,7 @@ static void iwl_bg_tt_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); s32 temp = priv->temperature; /* degrees CELSIUS except specified */ - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (!priv->thermal_throttle.advanced_tt) @@ -595,7 +595,7 @@ static void iwl_bg_tt_work(struct work_struct *work) void iwl_tt_handler(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index ac5c1311ef33..9f224548b636 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -297,7 +297,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (info->control.vif) ctx = iwl_rxon_ctx_from_vif(info->control.vif); - if (iwl_is_rfkill(priv->shrd)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); goto drop_unlock_priv; } @@ -1000,7 +1000,7 @@ static void iwl_check_abort_status(struct iwl_priv *priv, { if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { IWL_ERR(priv, "Tx flush command to flush out all frames\n"); - if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) queue_work(priv->workqueue, &priv->tx_flush); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 397342402d1e..d45def33d0f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -244,11 +244,11 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, bt_runtime_config); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return; iwlagn_send_advance_bt_config(priv); } @@ -261,11 +261,11 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) goto out; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) goto out; IWL_DEBUG_INFO(priv, "BT coex in %s mode\n", @@ -300,11 +300,11 @@ static void iwl_bg_statistics_periodic(unsigned long data) { struct iwl_priv *priv = (struct iwl_priv *)data; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return; iwl_send_statistics_request(priv, CMD_ASYNC, false); @@ -461,7 +461,7 @@ static void iwl_bg_ucode_trace(unsigned long data) { struct iwl_priv *priv = (struct iwl_priv *)data; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (priv->event_log.ucode_trace) { @@ -477,11 +477,11 @@ static void iwl_bg_tx_flush(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, tx_flush); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* do nothing if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return; IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n"); @@ -640,12 +640,12 @@ int iwl_alive_start(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); /* After the ALIVE response, we can send host commands to the uCode */ - set_bit(STATUS_ALIVE, &priv->shrd->status); + set_bit(STATUS_ALIVE, &priv->status); /* Enable watchdog to monitor the driver tx queues */ iwl_setup_watchdog(priv); - if (iwl_is_rfkill(priv->shrd)) + if (iwl_is_rfkill(priv)) return -ERFKILL; if (priv->event_log.ucode_trace) { @@ -719,7 +719,7 @@ int iwl_alive_start(struct iwl_priv *priv) iwl_reset_run_time_calib(priv); } - set_bit(STATUS_READY, &priv->shrd->status); + set_bit(STATUS_READY, &priv->status); /* Configure the adapter for unassociated operation */ ret = iwlagn_commit_rxon(priv, ctx); @@ -786,7 +786,7 @@ void iwl_down(struct iwl_priv *priv) ieee80211_remain_on_channel_expired(priv->hw); exit_pending = - test_and_set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set * to prevent rearm timer */ @@ -811,7 +811,7 @@ void iwl_down(struct iwl_priv *priv) /* Wipe out the EXIT_PENDING status bit if we are not actually * exiting the module */ if (!exit_pending) - clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + clear_bit(STATUS_EXIT_PENDING, &priv->status); if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); @@ -820,13 +820,13 @@ void iwl_down(struct iwl_priv *priv) /* Clear out all status bits but a few that are stable across reset */ priv->shrd->status &= - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) << + test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | - test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) << + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | test_bit(STATUS_FW_ERROR, &priv->shrd->status) << STATUS_FW_ERROR | - test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) << + test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; dev_kfree_skb(priv->beacon_skb); @@ -846,8 +846,8 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || - test_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || + test_bit(STATUS_SCANNING, &priv->status)) { mutex_unlock(&priv->mutex); return; } @@ -903,7 +903,7 @@ static void iwl_bg_restart(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index ede1852b1d7e..eb96855ddf8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -353,28 +353,23 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, /* status checks */ -static inline int iwl_is_ready(struct iwl_shared *shrd) +static inline int iwl_is_ready(struct iwl_priv *priv) { /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are * set but EXIT_PENDING is not */ - return test_bit(STATUS_READY, &shrd->status) && - test_bit(STATUS_GEO_CONFIGURED, &shrd->status) && - !test_bit(STATUS_EXIT_PENDING, &shrd->status); + return test_bit(STATUS_READY, &priv->status) && + test_bit(STATUS_GEO_CONFIGURED, &priv->status) && + !test_bit(STATUS_EXIT_PENDING, &priv->status); } -static inline int iwl_is_alive(struct iwl_shared *shrd) +static inline int iwl_is_alive(struct iwl_priv *priv) { - return test_bit(STATUS_ALIVE, &shrd->status); + return test_bit(STATUS_ALIVE, &priv->status); } -static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd) +static inline int iwl_is_rfkill(struct iwl_priv *priv) { - return test_bit(STATUS_RF_KILL_HW, &shrd->status); -} - -static inline int iwl_is_rfkill(struct iwl_shared *shrd) -{ - return iwl_is_rfkill_hw(shrd); + return test_bit(STATUS_RF_KILL_HW, &priv->status); } static inline int iwl_is_ctkill(struct iwl_priv *priv) @@ -382,18 +377,18 @@ static inline int iwl_is_ctkill(struct iwl_priv *priv) return test_bit(STATUS_CT_KILL, &priv->status); } -static inline int iwl_is_ready_rf(struct iwl_shared *shrd) +static inline int iwl_is_ready_rf(struct iwl_priv *priv) { - if (iwl_is_rfkill(shrd)) + if (iwl_is_rfkill(priv)) return 0; - return iwl_is_ready(shrd); + return iwl_is_ready(priv); } #ifdef CONFIG_IWLWIFI_DEBUG #define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \ do { \ - if (!iwl_is_rfkill((m)->shrd)) \ + if (!iwl_is_rfkill((m))) \ IWL_ERR(m, fmt, ##args); \ else \ __iwl_err(trans(m)->dev, true, \ @@ -403,7 +398,7 @@ do { \ #else #define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \ do { \ - if (!iwl_is_rfkill((m)->shrd)) \ + if (!iwl_is_rfkill((m))) \ IWL_ERR(m, fmt, ##args); \ else \ __iwl_err(trans(m)->dev, true, true, fmt, ##args); \ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index df7b165b290c..8b85940731f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -113,7 +113,7 @@ int iwl_init_geos(struct iwl_priv *priv) if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); - set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); + set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } @@ -212,7 +212,7 @@ int iwl_init_geos(struct iwl_priv *priv) priv->bands[IEEE80211_BAND_2GHZ].n_channels, priv->bands[IEEE80211_BAND_5GHZ].n_channels); - set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); + set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } @@ -224,7 +224,7 @@ void iwl_free_geos(struct iwl_priv *priv) { kfree(priv->ieee_channels); kfree(priv->ieee_rates); - clear_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); + clear_bit(STATUS_GEO_CONFIGURED, &priv->status); } static bool iwl_is_channel_extension(struct iwl_priv *priv, @@ -798,11 +798,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) */ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, - &priv->shrd->status)) + if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) ieee80211_chswitch_done(ctx->vif, is_success); } @@ -849,7 +848,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) /* Keep the restart process from trying to send host * commands by clearing the ready bit */ - clear_bit(STATUS_READY, &priv->shrd->status); + clear_bit(STATUS_READY, &priv->status); wake_up(&priv->shrd->wait_command_queue); @@ -874,7 +873,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) priv->reload_count = 0; } - if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { if (iwlagn_mod_params.restart_fw) { IWL_DEBUG_FW_ERRORS(priv, "Restarting adapter due to uCode error.\n"); @@ -912,7 +911,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) return -EINVAL; } - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return -EIO; /* scan complete and commit_rxon use tx_power_next value, @@ -920,7 +919,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) priv->tx_power_next = tx_power; /* do not set tx power when scanning or channel changing */ - defer = test_bit(STATUS_SCANNING, &priv->shrd->status) || + defer = test_bit(STATUS_SCANNING, &priv->status) || memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); if (defer && !force) { IWL_DEBUG_INFO(priv, "Deferring tx power set\n"); @@ -1219,7 +1218,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) static void iwl_force_rf_reset(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (!iwl_is_any_associated(priv)) { @@ -1244,7 +1243,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) { struct iwl_force_reset *force_reset; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EINVAL; if (mode >= IWL_MAX_FORCE_RESET) { @@ -1334,10 +1333,10 @@ void iwl_bg_watchdog(unsigned long data) int cnt; unsigned long timeout; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (iwl_is_rfkill(priv->shrd)) + if (iwl_is_rfkill(priv)) return; timeout = hw_params(priv).wd_timeout; @@ -1461,9 +1460,9 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); if (state) - set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + set_bit(STATUS_RF_KILL_HW, &priv->status); else - clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + clear_bit(STATUS_RF_KILL_HW, &priv->status); wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); } diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 1c235d685ae6..7a1334e8c358 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -454,7 +454,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, char *buf; ssize_t ret; - if (!test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status)) + if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -525,28 +525,26 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", - test_bit(STATUS_INT_ENABLED, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); + test_bit(STATUS_RF_KILL_HW, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", test_bit(STATUS_CT_KILL, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", - test_bit(STATUS_ALIVE, &priv->shrd->status)); + test_bit(STATUS_ALIVE, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", - test_bit(STATUS_READY, &priv->shrd->status)); + test_bit(STATUS_READY, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", - test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status)); + test_bit(STATUS_GEO_CONFIGURED, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", - test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)); + test_bit(STATUS_EXIT_PENDING, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", - test_bit(STATUS_STATISTICS, &priv->shrd->status)); + test_bit(STATUS_STATISTICS, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", - test_bit(STATUS_SCANNING, &priv->shrd->status)); + test_bit(STATUS_SCANNING, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n", - test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)); + test_bit(STATUS_SCAN_ABORTING, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", - test_bit(STATUS_SCAN_HW, &priv->shrd->status)); + test_bit(STATUS_SCAN_HW, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", test_bit(STATUS_POWER_PMI, &priv->shrd->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", @@ -752,7 +750,7 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) return -EINVAL; - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return -EAGAIN; priv->power_data.debug_sleep_level_override = value; @@ -947,7 +945,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, struct statistics_rx_non_phy *delta_general, *max_general; struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1376,7 +1374,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, ssize_t ret; struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1578,7 +1576,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; struct statistics_div *div, *accum_div, *delta_div, *max_div; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1697,7 +1695,7 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, ssize_t ret; struct statistics_bt_activity *bt, *accum_bt; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; if (!priv->bt_enable_flag) @@ -1790,7 +1788,7 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200; ssize_t ret; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -2148,7 +2146,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, if (trace) { priv->event_log.ucode_trace = true; - if (iwl_is_alive(priv->shrd)) { + if (iwl_is_alive(priv)) { /* start collecting data now */ mod_timer(&priv->ucode_trace, jiffies); } @@ -2338,7 +2336,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, if (sscanf(buf, "%d", &flush) != 1) return -EINVAL; - if (iwl_is_rfkill(priv->shrd)) + if (iwl_is_rfkill(priv)) return -EFAULT; iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index f2f706f084a5..1993a2b7ae63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -126,7 +126,7 @@ static int iwl_led_cmd(struct iwl_priv *priv, }; int ret; - if (!test_bit(STATUS_READY, &priv->shrd->status)) + if (!test_bit(STATUS_READY, &priv->status)) return -EBUSY; if (priv->blink_on == on && priv->blink_off == off) diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index dcf39f84f239..54d3709c0a6c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -266,7 +266,7 @@ static int __iwl_up(struct iwl_priv *priv) lockdep_assert_held(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); return -EIO; } @@ -297,9 +297,9 @@ static int __iwl_up(struct iwl_priv *priv) return 0; error: - set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + set_bit(STATUS_EXIT_PENDING, &priv->status); iwl_down(priv); - clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + clear_bit(STATUS_EXIT_PENDING, &priv->status); IWL_ERR(priv, "Unable to initialize device.\n"); return ret; @@ -322,7 +322,7 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_INFO(priv, "Start UP work done.\n"); /* Now we should be done, and the READY bit should be set. */ - if (WARN_ON(!test_bit(STATUS_READY, &priv->shrd->status))) + if (WARN_ON(!test_bit(STATUS_READY, &priv->status))) ret = -EIO; iwlagn_led_enable(priv); @@ -807,7 +807,7 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, * mac80211 might WARN if we fail, but due the way we * (badly) handle hard rfkill, we might fail here */ - if (iwl_is_rfkill(priv->shrd)) + if (iwl_is_rfkill(priv)) ret = 0; mutex_unlock(&priv->mutex); @@ -839,12 +839,12 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - if (iwl_is_rfkill(priv->shrd)) + if (iwl_is_rfkill(priv)) goto out; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || - test_bit(STATUS_SCANNING, &priv->shrd->status) || - test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || + test_bit(STATUS_SCANNING, &priv->status) || + test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) goto out; if (!iwl_is_associated_ctx(ctx)) @@ -884,10 +884,10 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, * at this point, staging_rxon has the * configuration for channel switch */ - set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); + set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); priv->switch_channel = cpu_to_le16(ch); if (cfg(priv)->lib->set_channel_switch(priv, ch_switch)) { - clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); + clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); priv->switch_channel = 0; ieee80211_chswitch_done(ctx->vif, false); } @@ -954,11 +954,11 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "enter\n"); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n"); goto done; } - if (iwl_is_rfkill(priv->shrd)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n"); goto done; } @@ -999,7 +999,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); mutex_lock(&priv->mutex); - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->status)) { err = -EBUSY; goto out; } @@ -1140,7 +1140,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); - if (!iwl_is_ready_rf(priv->shrd)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; } @@ -1241,7 +1241,7 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, iwlagn_disable_roc(priv); - if (!iwl_is_ready_rf(priv->shrd)) { + if (!iwl_is_ready_rf(priv)) { IWL_WARN(priv, "Try to add interface when device not ready\n"); err = -EINVAL; goto out; @@ -1365,7 +1365,7 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) { + if (!ctx->vif || !iwl_is_ready_rf(priv)) { /* * Huh? But wait ... this can maybe happen when * we're in the middle of a firmware restart! diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index f79ff16e29f4..958d9d09aee3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -392,12 +392,12 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force) return 0; - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return -EIO; /* scan complete use sleep_power_next, need to be updated */ memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd)); - if (test_bit(STATUS_SCANNING, &priv->shrd->status) && !force) { + if (test_bit(STATUS_SCANNING, &priv->status) && !force) { IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n"); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 8c3fb3233d9f..902efe4bc898 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -66,9 +66,9 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) /* Exit instantly with error when device is not ready * to receive scan abort command or it does not perform * hardware scan currently */ - if (!test_bit(STATUS_READY, &priv->shrd->status) || - !test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) || - !test_bit(STATUS_SCAN_HW, &priv->shrd->status) || + if (!test_bit(STATUS_READY, &priv->status) || + !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || + !test_bit(STATUS_SCAN_HW, &priv->status) || test_bit(STATUS_FW_ERROR, &priv->shrd->status)) return -EIO; @@ -118,18 +118,18 @@ static void iwl_process_scan_complete(struct iwl_priv *priv) lockdep_assert_held(&priv->mutex); - if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status)) + if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->status)) return; IWL_DEBUG_SCAN(priv, "Completed scan.\n"); cancel_delayed_work(&priv->scan_check); - aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); + aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status); if (aborted) IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); - if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); goto out_settings; } @@ -165,7 +165,7 @@ out_complete: out_settings: /* Can we still talk to firmware ? */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return; iwlagn_post_scan(priv); @@ -175,16 +175,16 @@ void iwl_force_scan_end(struct iwl_priv *priv) { lockdep_assert_held(&priv->mutex); - if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (!test_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n"); return; } IWL_DEBUG_SCAN(priv, "Forcing scan end\n"); - clear_bit(STATUS_SCANNING, &priv->shrd->status); - clear_bit(STATUS_SCAN_HW, &priv->shrd->status); - clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); - clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status); + clear_bit(STATUS_SCANNING, &priv->status); + clear_bit(STATUS_SCAN_HW, &priv->status); + clear_bit(STATUS_SCAN_ABORTING, &priv->status); + clear_bit(STATUS_SCAN_COMPLETE, &priv->status); iwl_complete_scan(priv, true); } @@ -194,12 +194,12 @@ static void iwl_do_scan_abort(struct iwl_priv *priv) lockdep_assert_held(&priv->mutex); - if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (!test_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n"); return; } - if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) { + if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan abort in progress\n"); return; } @@ -238,7 +238,7 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) iwl_do_scan_abort(priv); while (time_before_eq(jiffies, timeout)) { - if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status)) + if (!test_bit(STATUS_SCAN_HW, &priv->status)) goto finished; msleep(20); } @@ -350,8 +350,8 @@ static int iwl_rx_scan_complete_notif(struct iwl_priv *priv, * to clear, we need to set SCAN_COMPLETE before clearing SCAN_HW * to avoid a race there. */ - set_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status); - clear_bit(STATUS_SCAN_HW, &priv->shrd->status); + set_bit(STATUS_SCAN_COMPLETE, &priv->status); + clear_bit(STATUS_SCAN_HW, &priv->status); queue_work(priv->workqueue, &priv->scan_completed); if (priv->iw_mode != NL80211_IFTYPE_ADHOC && @@ -927,7 +927,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->len = cpu_to_le16(cmd.len[0]); /* set scan bit here for PAN params */ - set_bit(STATUS_SCAN_HW, &priv->shrd->status); + set_bit(STATUS_SCAN_HW, &priv->status); ret = iwlagn_set_pan_params(priv); if (ret) @@ -935,7 +935,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) ret = iwl_dvm_send_cmd(priv, &cmd); if (ret) { - clear_bit(STATUS_SCAN_HW, &priv->shrd->status); + clear_bit(STATUS_SCAN_HW, &priv->status); iwlagn_set_pan_params(priv); } @@ -962,18 +962,18 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, cancel_delayed_work(&priv->scan_check); - if (!iwl_is_ready_rf(priv->shrd)) { + if (!iwl_is_ready_rf(priv)) { IWL_WARN(priv, "Request scan called when driver not ready.\n"); return -EIO; } - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->status)) { IWL_DEBUG_SCAN(priv, "Multiple concurrent scan requests in parallel.\n"); return -EBUSY; } - if (test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n"); return -EBUSY; } @@ -983,14 +983,14 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, scan_type == IWL_SCAN_ROC ? "remain-on-channel " : "internal short "); - set_bit(STATUS_SCANNING, &priv->shrd->status); + set_bit(STATUS_SCANNING, &priv->status); priv->scan_type = scan_type; priv->scan_start = jiffies; priv->scan_band = band; ret = iwlagn_request_scan(priv, vif); if (ret) { - clear_bit(STATUS_SCANNING, &priv->shrd->status); + clear_bit(STATUS_SCANNING, &priv->status); priv->scan_type = IWL_SCAN_NORMAL; return ret; } @@ -1025,7 +1025,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) goto unlock; } - if (test_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (test_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); goto unlock; } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 16a32ae4046e..dd64e69b1569 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -356,7 +356,8 @@ void iwl_dump_csr(struct iwl_trans *trans); ******************************************************/ static inline void iwl_disable_interrupts(struct iwl_trans *trans) { - clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + clear_bit(STATUS_INT_ENABLED, &trans_pcie->status); /* disable interrupts from uCode/NIC to host */ iwl_write32(trans, CSR_INT_MASK, 0x00000000); @@ -370,11 +371,10 @@ static inline void iwl_disable_interrupts(struct iwl_trans *trans) static inline void iwl_enable_interrupts(struct iwl_trans *trans) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); - set_bit(STATUS_INT_ENABLED, &trans->shrd->status); + set_bit(STATUS_INT_ENABLED, &trans_pcie->status); iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 2d6ea42b0d8e..32820913a2fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1131,7 +1131,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* Re-enable all interrupts */ /* only Re-enable if disabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status)) + if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status)) iwl_enable_interrupts(trans); /* Re-enable RF_KILL if it occurred */ else if (handled & CSR_INT_BIT_RF_KILL) @@ -1303,7 +1303,7 @@ static irqreturn_t iwl_isr(int irq, void *data) /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) tasklet_schedule(&trans_pcie->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && + else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && !trans_pcie->inta) iwl_enable_interrupts(trans); @@ -1314,7 +1314,7 @@ static irqreturn_t iwl_isr(int irq, void *data) none: /* re-enable interrupts here since we don't have anything to service. */ /* only Re-enable if disabled by irq and no schedules tasklet. */ - if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && + if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && !trans_pcie->inta) iwl_enable_interrupts(trans); @@ -1414,7 +1414,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) tasklet_schedule(&trans_pcie->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && + else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && !trans_pcie->inta) { /* Allow interrupt if was disabled by this handler and * no tasklet was schedules, We should not enable interrupt, @@ -1430,7 +1430,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) /* re-enable interrupts here since we don't have anything to service. * only Re-enable if disabled by irq. */ - if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && + if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && !trans_pcie->inta) iwl_enable_interrupts(trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index e78098e79ee1..3b8a5fb771f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -684,6 +684,7 @@ static void iwl_apm_config(struct iwl_trans *trans) */ static int iwl_apm_init(struct iwl_trans *trans) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int ret = 0; IWL_DEBUG_INFO(trans, "Init card's basic functions\n"); @@ -753,7 +754,7 @@ static int iwl_apm_init(struct iwl_trans *trans) iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - set_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status); + set_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); out: return ret; @@ -779,9 +780,10 @@ static int iwl_apm_stop_master(struct iwl_trans *trans) static void iwl_apm_stop(struct iwl_trans *trans) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n"); - clear_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status); + clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status); /* Stop device's DMA activity */ iwl_apm_stop_master(trans); @@ -1265,7 +1267,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) * restart. So don't process again if the device is * already dead. */ - if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) { + if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) { iwl_trans_tx_stop(trans); #ifndef CONFIG_IWLWIFI_IDI iwl_trans_rx_stop(trans); -- cgit v1.2.3-70-g09d2 From bada991b4590122c847520ed2b651b679c16afd3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:39 -0800 Subject: iwlwifi: remove messages from queue wake/stop The only reason we ever stop/wake queues at the transport level is now that they become full (or non-full), so the messages aren't useful any more -- remove them. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 36 +++++++++++------------ drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 4 +-- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index dd64e69b1569..c0e68097fcb5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -409,7 +409,7 @@ static inline u8 iwl_get_queue_ac(struct iwl_tx_queue *txq) } static inline void iwl_wake_queue(struct iwl_trans *trans, - struct iwl_tx_queue *txq, const char *msg) + struct iwl_tx_queue *txq) { u8 queue = txq->swq_id; u8 ac = queue & 3; @@ -420,19 +420,19 @@ static inline void iwl_wake_queue(struct iwl_trans *trans, if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) { if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) { iwl_op_mode_queue_not_full(trans->op_mode, ac); - IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d ac %d. %s", - hwq, ac, msg); + IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d ac %d", + hwq, ac); } else { - IWL_DEBUG_TX_QUEUES(trans, "Don't wake hwq %d ac %d" - " stop count %d. %s", - hwq, ac, atomic_read(&trans_pcie-> - queue_stop_count[ac]), msg); + IWL_DEBUG_TX_QUEUES(trans, + "Don't wake hwq %d ac %d stop count %d", + hwq, ac, + atomic_read(&trans_pcie->queue_stop_count[ac])); } } } static inline void iwl_stop_queue(struct iwl_trans *trans, - struct iwl_tx_queue *txq, const char *msg) + struct iwl_tx_queue *txq) { u8 queue = txq->swq_id; u8 ac = queue & 3; @@ -443,19 +443,19 @@ static inline void iwl_stop_queue(struct iwl_trans *trans, if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) { if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) { iwl_op_mode_queue_full(trans->op_mode, ac); - IWL_DEBUG_TX_QUEUES(trans, "Stop hwq %d ac %d" - " stop count %d. %s", - hwq, ac, atomic_read(&trans_pcie-> - queue_stop_count[ac]), msg); + IWL_DEBUG_TX_QUEUES(trans, + "Stop hwq %d ac %d stop count %d", + hwq, ac, + atomic_read(&trans_pcie->queue_stop_count[ac])); } else { - IWL_DEBUG_TX_QUEUES(trans, "Don't stop hwq %d ac %d" - " stop count %d. %s", - hwq, ac, atomic_read(&trans_pcie-> - queue_stop_count[ac]), msg); + IWL_DEBUG_TX_QUEUES(trans, + "Don't stop hwq %d ac %d stop count %d", + hwq, ac, + atomic_read(&trans_pcie->queue_stop_count[ac])); } } else { - IWL_DEBUG_TX_QUEUES(trans, "stop hwq %d, but it is stopped/ %s", - hwq, msg); + IWL_DEBUG_TX_QUEUES(trans, "stop hwq %d, but it is stopped", + hwq); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 3b8a5fb771f6..6172651d7e25 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1487,7 +1487,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, txq->need_update = 1; iwl_txq_update_write_ptr(trans, txq); } else { - iwl_stop_queue(trans, txq, "Queue is full"); + iwl_stop_queue(trans, txq); } } spin_unlock(&txq->lock); @@ -1591,7 +1591,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, tfd_num, ssn); freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); if (iwl_queue_space(&txq->q) > txq->q.low_mark) - iwl_wake_queue(trans, txq, "Packets reclaimed"); + iwl_wake_queue(trans, txq); } spin_unlock(&txq->lock); -- cgit v1.2.3-70-g09d2 From e6dd5838acf312516fcc4eb34516de5bc45e2980 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:40 -0800 Subject: iwlwifi: make iwl_init_context static It's not needed anywhere but during init. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d45def33d0f6..8c21db81ba5f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -488,7 +488,7 @@ static void iwl_bg_tx_flush(struct work_struct *work) iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); } -void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) +static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) { int i; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index eb96855ddf8d..5410dfd40694 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -118,7 +118,6 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf, int iwlagn_rx_calib_result(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); -void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); void iwl_send_prio_tbl(struct iwl_priv *priv); int iwl_init_alive_start(struct iwl_priv *priv); -- cgit v1.2.3-70-g09d2 From 974205153be8944539890084a170e3ad407164bc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 7 Mar 2012 09:52:42 -0800 Subject: iwlwifi: don't delete AP station directly With the mac80211 deauth sequence changes, the station is deleted before the device is set unassociated. This can cause the device to get confused as it expects the station to be there while the associated bit is set. To fix this, do not delete the AP station from the device when mac80211 asks for deletion, instead just mark it as unused and rely on the unassociated RXON to drop it from the station database in the device. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 35 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-mac80211.c | 22 +++++++++++++----- 3 files changed, 53 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 23e9eab477bb..c4175603864b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -546,6 +546,41 @@ out_err: return -EINVAL; } +void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id, + const u8 *addr) +{ + u8 tid; + + if (!iwl_is_ready(priv)) { + IWL_DEBUG_INFO(priv, + "Unable to remove station %pM, device not ready.\n", + addr); + return; + } + + IWL_DEBUG_ASSOC(priv, "Deactivating STA: %pM (%d)\n", addr, sta_id); + + if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION)) + return; + + spin_lock_bh(&priv->sta_lock); + + WARN_ON_ONCE(!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)); + + for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) + memset(&priv->tid_data[sta_id][tid], 0, + sizeof(priv->tid_data[sta_id][tid])); + + priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; + + priv->num_stations--; + + if (WARN_ON_ONCE(priv->num_stations < 0)) + priv->num_stations = 0; + + spin_unlock_bh(&priv->sta_lock); +} + /** * iwl_clear_ucode_stations - clear ucode station table bits * diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 5410dfd40694..3780a03f2716 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -234,6 +234,8 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct ieee80211_sta *sta, u8 *sta_id_r); int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, const u8 *addr); +void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id, + const u8 *addr); u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, const u8 *addr, bool is_ap, struct ieee80211_sta *sta); diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 54d3709c0a6c..9212ee3bef9b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -724,12 +724,22 @@ static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw, struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; int ret; - IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", - sta->addr); - ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr); - if (ret) - IWL_DEBUG_QUIET_RFKILL(priv, "Error removing station %pM\n", - sta->addr); + IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", sta->addr); + + if (vif->type == NL80211_IFTYPE_STATION) { + /* + * Station will be removed from device when the RXON + * is set to unassociated -- just deactivate it here + * to avoid re-programming it. + */ + ret = 0; + iwl_deactivate_station(priv, sta_priv->sta_id, sta->addr); + } else { + ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr); + if (ret) + IWL_DEBUG_QUIET_RFKILL(priv, + "Error removing station %pM\n", sta->addr); + } return ret; } -- cgit v1.2.3-70-g09d2 From 1353a7ba7ebe62dedc60a5ba75c434cfad960ede Mon Sep 17 00:00:00 2001 From: Don Fry Date: Wed, 7 Mar 2012 09:52:43 -0800 Subject: iwlwifi: correct status bit refactoring errors I missed a couple of status bits in my refactoring changes. This fixes the ones I missed. Signed-off-by: Don Fry Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 3ad43330f6a1..cc0227c1f352 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -628,7 +628,7 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv, struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_card_state_notif *card_state_notif = (void *)pkt->data; u32 flags = le32_to_cpu(card_state_notif->flags); - unsigned long status = priv->shrd->status; + unsigned long status = priv->status; IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", (flags & HW_CARD_DISABLED) ? "Kill" : "On", diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8c21db81ba5f..60f1dc640c94 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -819,15 +819,15 @@ void iwl_down(struct iwl_priv *priv) iwl_trans_stop_device(trans(priv)); /* Clear out all status bits but a few that are stable across reset */ - priv->shrd->status &= - test_bit(STATUS_RF_KILL_HW, &priv->status) << + priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_FW_ERROR, &priv->shrd->status) << - STATUS_FW_ERROR | test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; + priv->shrd->status &= + test_bit(STATUS_FW_ERROR, &priv->shrd->status) << + STATUS_FW_ERROR; dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; -- cgit v1.2.3-70-g09d2 From d11f0ca0121996461b17e93941e9dfa0a9eebbd1 Mon Sep 17 00:00:00 2001 From: Stanislav Yakovlev Date: Wed, 7 Mar 2012 19:32:40 -0500 Subject: net/wireless: ipw2x00: remove WEXT_USECHANNELS define Driver does not use it any more. Signed-off-by: Stanislav Yakovlev Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 2 -- drivers/net/wireless/ipw2x00/ipw2200.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 5d7e97e63def..ddf340f914da 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -298,8 +298,6 @@ static const char *command_types[] = { }; #endif -#define WEXT_USECHANNELS 1 - static const long ipw2100_frequencies[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h index ecb561d7a7a0..66e84ec0eb55 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.h +++ b/drivers/net/wireless/ipw2x00/ipw2200.h @@ -27,8 +27,6 @@ #ifndef __ipw2200_h__ #define __ipw2200_h__ -#define WEXT_USECHANNELS 1 - #include #include #include -- cgit v1.2.3-70-g09d2 From 8763848e03a9098e5b6f81428a98738dc960a436 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 7 Mar 2012 19:36:07 -0800 Subject: mwifiex: correction in number of bitrates In recent commit "mwifiex: correct bitrates advertised..", we have removed 22Mbps and 72Mbps bitrates from supported bitrate array. It means number of bitrates has reduced from 14 to 12. Initialize ".n_bitrates" to array size instead of hardcoding it. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index b4890a01ba92..84508b065265 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -646,7 +646,7 @@ static struct ieee80211_supported_band mwifiex_band_2ghz = { .channels = mwifiex_channels_2ghz, .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz), .bitrates = mwifiex_rates, - .n_bitrates = 14, + .n_bitrates = ARRAY_SIZE(mwifiex_rates), }; static struct ieee80211_channel mwifiex_channels_5ghz[] = { -- cgit v1.2.3-70-g09d2 From c6f600fcfe8a7e4f594fc4c80b2c7b66f248958b Mon Sep 17 00:00:00 2001 From: Meenakshi Venkataraman Date: Thu, 8 Mar 2012 11:29:12 -0800 Subject: iwlwifi: move command queue number out of the iwl_shared struct The command queue number is required by the transport layer, but it can be determined only by the op mode. Move this parameter to the dvm op mode, and configure the transport layer using an API. Signed-off-by: Meenakshi Venkataraman Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 16 +++++------ drivers/net/wireless/iwlwifi/iwl-shared.h | 2 -- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 24 ++++++++-------- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 34 ++++++++++++++++------- drivers/net/wireless/iwlwifi/iwl-trans.h | 9 ++++++ 7 files changed, 56 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 60f1dc640c94..1e6b5e41a72b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1236,6 +1236,14 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, */ trans_cfg.op_mode = op_mode; + if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { + priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; + trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; + } else { + priv->sta_key_max_num = STA_KEY_MAX_NUM; + trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + } + /* Configure transport layer */ iwl_trans_configure(trans(priv), &trans_cfg); @@ -1336,14 +1344,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, priv->new_scan_threshold_behaviour = !!(ucode_flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); - if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { - priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; - priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; - } else { - priv->sta_key_max_num = STA_KEY_MAX_NUM; - priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; - } - priv->phy_calib_chain_noise_reset_cmd = fw->ucode_capa.standard_phy_calibration_size; priv->phy_calib_chain_noise_gain_cmd = diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 45409fcfbbd7..0d957ca3d6c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -368,7 +368,6 @@ struct iwl_cfg { /** * struct iwl_shared - shared fields for all the layers of the driver * - * @cmd_queue: command queue number * @status: STATUS_* * @wowlan: are we running wowlan uCode * @valid_contexts: microcode/device supports multiple contexts @@ -385,7 +384,6 @@ struct iwl_cfg { * @device_pointers: pointers to ucode event tables */ struct iwl_shared { - u8 cmd_queue; unsigned long status; u8 valid_contexts; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index c0e68097fcb5..67965599bb30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -248,6 +248,7 @@ struct iwl_tx_queue { * @ucode_write_complete: indicates that the ucode has been copied. * @ucode_write_waitq: wait queue for uCode load * @status - transport specific status flags + * @cmd_queue - command queue number */ struct iwl_trans_pcie { struct iwl_rx_queue rxq; @@ -289,6 +290,7 @@ struct iwl_trans_pcie { bool ucode_write_complete; wait_queue_head_t ucode_write_waitq; unsigned long status; + u8 cmd_queue; }; #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 32820913a2fd..a5547a155b95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -361,7 +361,7 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_queue *rxq = &trans_pcie->rxq; - struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; + struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; struct iwl_device_cmd *cmd; unsigned long flags; int len, err; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 73febc9726cb..2b1df0092aee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -397,7 +397,7 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - if (txq_id != trans->shrd->cmd_queue) + if (txq_id != trans_pcie->cmd_queue) sta_id = tx_cmd->sta_id; bc_ent = cpu_to_le16(1 | (sta_id << 12)); @@ -664,7 +664,7 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid) static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; + struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; struct iwl_queue *q = &txq->q; struct iwl_device_cmd *out_cmd; struct iwl_cmd_meta *out_meta; @@ -737,7 +737,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) out_cmd->hdr.cmd = cmd->id; out_cmd->hdr.flags = 0; out_cmd->hdr.sequence = - cpu_to_le16(QUEUE_TO_SEQ(trans->shrd->cmd_queue) | + cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->cmd_queue) | INDEX_TO_SEQ(q->write_ptr)); /* and copy the data that needs to be copied */ @@ -757,7 +757,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) get_cmd_string(out_cmd->hdr.cmd), out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), cmd_size, - q->write_ptr, idx, trans->shrd->cmd_queue); + q->write_ptr, idx, trans_pcie->cmd_queue); phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, DMA_BIDIRECTIONAL); @@ -881,16 +881,16 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; + struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ - if (WARN(txq_id != trans->shrd->cmd_queue, + if (WARN(txq_id != trans_pcie->cmd_queue, "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", - txq_id, trans->shrd->cmd_queue, sequence, - trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr, - trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) { + txq_id, trans_pcie->cmd_queue, sequence, + trans_pcie->txq[trans_pcie->cmd_queue].q.read_ptr, + trans_pcie->txq[trans_pcie->cmd_queue].q.write_ptr)) { iwl_print_hex_error(trans, pkt, 32); return; } @@ -997,7 +997,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) if (!ret) { if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) { struct iwl_tx_queue *txq = - &trans_pcie->txq[trans->shrd->cmd_queue]; + &trans_pcie->txq[trans_pcie->cmd_queue]; struct iwl_queue *q = &txq->q; IWL_ERR(trans, @@ -1034,7 +1034,7 @@ cancel: * in later, it will possibly set an invalid * address (cmd->meta.source). */ - trans_pcie->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &= + trans_pcie->txq[trans_pcie->cmd_queue].meta[cmd_idx].flags &= ~CMD_WANT_SKB; } @@ -1065,7 +1065,7 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, int freed = 0; /* This function is not meant to release cmd queue*/ - if (WARN_ON(txq_id == trans->shrd->cmd_queue)) + if (WARN_ON(txq_id == trans_pcie->cmd_queue)) return 0; lockdep_assert_held(&txq->lock); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 6172651d7e25..8170133d8173 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -78,6 +78,10 @@ #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) +#define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie) \ + (((1<base_params->num_of_queues) - 1) &\ + (~(1<<(trans_pcie)->cmd_queue))) + static int iwl_trans_rx_alloc(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = @@ -301,6 +305,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, { size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; int i; + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds)) return -EINVAL; @@ -313,7 +318,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, if (!txq->meta || !txq->cmd) goto error; - if (txq_id == trans->shrd->cmd_queue) + if (txq_id == trans_pcie->cmd_queue) for (i = 0; i < slots_num; i++) { txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd), GFP_KERNEL); @@ -324,7 +329,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, /* Alloc driver data array and TFD circular buffer */ /* Driver private data, only for Tx (not command) queues, * not shared with device. */ - if (txq_id != trans->shrd->cmd_queue) { + if (txq_id != trans_pcie->cmd_queue) { txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->skbs[0]), GFP_KERNEL); if (!txq->skbs) { @@ -352,7 +357,7 @@ error: txq->skbs = NULL; /* since txq->cmd has been zeroed, * all non allocated cmd[i] will be NULL */ - if (txq->cmd && txq_id == trans->shrd->cmd_queue) + if (txq->cmd && txq_id == trans_pcie->cmd_queue) for (i = 0; i < slots_num; i++) kfree(txq->cmd[i]); kfree(txq->meta); @@ -418,7 +423,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) /* In the command queue, all the TBs are mapped as BIDI * so unmap them as such. */ - if (txq_id == trans->shrd->cmd_queue) + if (txq_id == trans_pcie->cmd_queue) dma_dir = DMA_BIDIRECTIONAL; else dma_dir = DMA_TO_DEVICE; @@ -454,7 +459,7 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) /* De-alloc array of command/tx buffers */ - if (txq_id == trans->shrd->cmd_queue) + if (txq_id == trans_pcie->cmd_queue) for (i = 0; i < txq->q.n_window; i++) kfree(txq->cmd[i]); @@ -551,7 +556,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) /* Alloc and init all Tx queues, including the command queue (#4/#9) */ for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { - slots_num = (txq_id == trans->shrd->cmd_queue) ? + slots_num = (txq_id == trans->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id], slots_num, txq_id); @@ -596,7 +601,7 @@ static int iwl_tx_init(struct iwl_trans *trans) /* Alloc and init all Tx queues, including the command queue (#4/#9) */ for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { - slots_num = (txq_id == trans->shrd->cmd_queue) ? + slots_num = (txq_id == trans->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id], slots_num, txq_id); @@ -1130,7 +1135,7 @@ static void iwl_tx_start(struct iwl_trans *trans) reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); iwl_write_prph(trans, SCD_QUEUECHAIN_SEL, - SCD_QUEUECHAIN_SEL_ALL(trans)); + SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie)); iwl_write_prph(trans, SCD_AGGR_SEL, 0); /* initiate the queues */ @@ -1162,7 +1167,7 @@ static void iwl_tx_start(struct iwl_trans *trans) else queue_to_fifo = iwlagn_default_queue_to_tx_fifo; - iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0); + iwl_trans_set_wr_ptrs(trans, trans_pcie->cmd_queue, 0); /* make sure all queue are not stopped */ memset(&trans_pcie->queue_stopped[0], 0, @@ -1613,6 +1618,14 @@ static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs) return readl(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); } +static void iwl_trans_pcie_configure(struct iwl_trans *trans, + const struct iwl_trans_config *trans_cfg) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + trans_pcie->cmd_queue = trans_cfg->cmd_queue; +} + static void iwl_trans_pcie_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = @@ -1673,7 +1686,7 @@ static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) /* waiting for all the tx frames complete might take a while */ for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { - if (cnt == trans->shrd->cmd_queue) + if (cnt == trans->cmd_queue) continue; txq = &trans_pcie->txq[cnt]; q = &txq->q; @@ -2202,6 +2215,7 @@ const struct iwl_trans_ops trans_ops_pcie = { .write8 = iwl_trans_pcie_write8, .write32 = iwl_trans_pcie_write32, .read32 = iwl_trans_pcie_read32, + .configure = iwl_trans_pcie_configure, }; struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index b6fd42779624..a40c2726c190 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -279,9 +279,12 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) * * @op_mode: pointer to the upper layer. * Must be set before any other call. + * @cmd_queue: the index of the command queue. + * Must be set before start_fw. */ struct iwl_trans_config { struct iwl_op_mode *op_mode; + u8 cmd_queue; }; /** @@ -331,6 +334,8 @@ struct iwl_trans_config { * @write8: write a u8 to a register at offset ofs from the BAR * @write32: write a u32 to a register at offset ofs from the BAR * @read32: read a u32 register at offset ofs from the BAR + * @configure: configure parameters required by the transport layer from + * the op_mode. */ struct iwl_trans_ops { @@ -370,6 +375,8 @@ struct iwl_trans_ops { void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val); void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val); u32 (*read32)(struct iwl_trans *trans, u32 ofs); + void (*configure)(struct iwl_trans *trans, + const struct iwl_trans_config *trans_cfg); }; /** @@ -425,6 +432,8 @@ static inline void iwl_trans_configure(struct iwl_trans *trans, * more */ trans->op_mode = trans_cfg->op_mode; + + trans->ops->configure(trans, trans_cfg); } static inline int iwl_trans_start_hw(struct iwl_trans *trans) -- cgit v1.2.3-70-g09d2 From 3dc420be8ce72688bd333afdab6d911e3ceb94e7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 7 Mar 2012 09:52:41 -0800 Subject: iwlwifi: restore PAN support in iwlwifi: move setting up fw parameters Meenakshi moved code up to configure the transport layer, but this code read the sku before it was set (from the EEPROM). This killed P2P. Only the ucode_flags are needed to configure the transport layer, not the sku which _must_ be set after the EEPROM is read. We need to reconfigure the transport in case the EEPROM disabled PAN support. This is not the nicest thing to do, but we have no choice. Document that we are allowed to configure the transport several times before start_fw, but not after. Signed-off-by: Emmanuel Grumbach Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 59 ++++++++++++++++---------------- drivers/net/wireless/iwlwifi/iwl-trans.h | 3 +- 2 files changed, 32 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1e6b5e41a72b..28422c03d673 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1206,35 +1206,17 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, /* TODO: remove fw from shared data later */ priv->shrd->fw = fw; - /************************ - * 2. Setup HW constants - ************************/ - iwl_set_hw_params(priv); + /* + * Populate the state variables that the transport layer needs + * to know about. + */ + trans_cfg.op_mode = op_mode; ucode_flags = fw->ucode_capa.flags; #ifndef CONFIG_IWLWIFI_P2P ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; #endif - if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE)) - ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; - - /* - * if not PAN, then don't support P2P -- might be a uCode - * packaging bug or due to the eeprom check above - */ - if (!(ucode_flags & IWL_UCODE_TLV_FLAGS_PAN)) - ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; - - - /***************************** - * Configure transport layer - *****************************/ - /* - * Populate the state variables that the transport layer needs - * to know about. - */ - trans_cfg.op_mode = op_mode; if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; @@ -1277,7 +1259,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, spin_lock_init(&priv->statistics.lock); /*********************** - * 3. Read REV register + * 2. Read REV register ***********************/ IWL_INFO(priv, "Detected %s, REV=0x%X\n", cfg(priv)->name, trans(priv)->hw_rev); @@ -1287,9 +1269,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, goto out_free_traffic_mem; /***************** - * 4. Read EEPROM + * 3. Read EEPROM *****************/ - /* Read the EEPROM */ err = iwl_eeprom_init(trans(priv), trans(priv)->hw_rev); /* Reset chip to save power until we load uCode during "up". */ iwl_trans_stop_hw(trans(priv)); @@ -1318,8 +1299,28 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, priv->hw->wiphy->n_addresses++; } + /************************ + * 4. Setup HW constants + ************************/ + iwl_set_hw_params(priv); + + if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE)) { + IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN"); + ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; + /* + * if not PAN, then don't support P2P -- might be a uCode + * packaging bug or due to the eeprom check above + */ + ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; + priv->sta_key_max_num = STA_KEY_MAX_NUM; + trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + + /* Configure transport layer again*/ + iwl_trans_configure(trans(priv), &trans_cfg); + } + /******************* - * 6. Setup priv + * 5. Setup priv *******************/ err = iwl_init_drv(priv); @@ -1328,7 +1329,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, /* At this point both hw and priv are initialized. */ /******************** - * 7. Setup services + * 6. Setup services ********************/ iwl_setup_deferred_work(priv); iwl_setup_rx_handlers(priv); @@ -1355,7 +1356,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, /************************************************** * This is still part of probe() in a sense... * - * 9. Setup and register with mac80211 and debugfs + * 7. Setup and register with mac80211 and debugfs **************************************************/ err = iwlagn_mac_setup_register(priv, &fw->ucode_capa); if (err) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index a40c2726c190..7d1990c7f658 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -335,7 +335,8 @@ struct iwl_trans_config { * @write32: write a u32 to a register at offset ofs from the BAR * @read32: read a u32 register at offset ofs from the BAR * @configure: configure parameters required by the transport layer from - * the op_mode. + * the op_mode. May be called several times before start_fw, can't be + * called after that. */ struct iwl_trans_ops { -- cgit v1.2.3-70-g09d2 From 9ba1947a89938ee83e7c16709ee4095ae3e36c44 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 9 Mar 2012 10:12:42 -0800 Subject: iwlwifi: fix cmd_queue number merge iwlwifi: move command queue number out of the iwl_shared struct move the cmd_queue out of iwl_shared struct, but for some reason the patch is half done and fail compile Here is the fix John, could you apply this patch to wireless-next to address the issue Thanks Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-prph.h | 4 ---- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index a4d11016c3b4..75dc20bd965b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -216,10 +216,6 @@ #define SCD_TRANS_TBL_OFFSET_QUEUE(x) \ ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) -#define SCD_QUEUECHAIN_SEL_ALL(priv) \ - (((1<shrd->cmd_queue))) - #define SCD_BASE (PRPH_BASE + 0xa02c00) #define SCD_SRAM_BASE_ADDR (SCD_BASE + 0x0) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 8170133d8173..a3ac6d814637 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -556,7 +556,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) /* Alloc and init all Tx queues, including the command queue (#4/#9) */ for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { - slots_num = (txq_id == trans->cmd_queue) ? + slots_num = (txq_id == trans_pcie->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id], slots_num, txq_id); @@ -601,7 +601,7 @@ static int iwl_tx_init(struct iwl_trans *trans) /* Alloc and init all Tx queues, including the command queue (#4/#9) */ for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { - slots_num = (txq_id == trans->cmd_queue) ? + slots_num = (txq_id == trans_pcie->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id], slots_num, txq_id); @@ -1686,7 +1686,7 @@ static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) /* waiting for all the tx frames complete might take a while */ for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { - if (cnt == trans->cmd_queue) + if (cnt == trans_pcie->cmd_queue) continue; txq = &trans_pcie->txq[cnt]; q = &txq->q; -- cgit v1.2.3-70-g09d2 From 1745e4405b2c0da6db2ec4b6bc0ad930612d8295 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 9 Mar 2012 11:13:40 -0800 Subject: iwlwifi: fix the delta for remove max_txq_num patch BIg portion of "iwlwifi: remove max_txq_num from hw_params" was missing during merge, here is the fix for it. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-2000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 2 -- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 3 ++- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 30 ++++++++++++++---------- 10 files changed, 23 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 450250332e4b..5b0d888f746b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -122,8 +122,6 @@ static const struct iwl_sensitivity_ranges iwl1000_sensitivity = { static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) { - hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); hw_params(priv).tx_chains_num = diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index abfd901e81a2..5635b9e2c69e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -117,8 +117,6 @@ static const struct iwl_sensitivity_ranges iwl2000_sensitivity = { static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) { - hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); hw_params(priv).tx_chains_num = diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 9e187f8f5ae4..a805e97b89af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -156,8 +156,6 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) { - hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); @@ -174,8 +172,6 @@ static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) static void iwl5150_hw_set_hw_params(struct iwl_priv *priv) { - hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index e64bc6b7bcbf..64060cd738b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -139,8 +139,6 @@ static const struct iwl_sensitivity_ranges iwl6000_sensitivity = { static void iwl6000_hw_set_hw_params(struct iwl_priv *priv) { - hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 9f224548b636..34adedc74d35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1159,7 +1159,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, * (in Tx queue's circular buffer) of first TFD/frame in window */ u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); - if (scd_flow >= hw_params(priv).max_txq_num) { + if (scd_flow >= cfg(priv)->base_params->num_of_queues) { IWL_ERR(priv, "BUG_ON scd_flow is bigger than number of queues\n"); return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 7a1334e8c358..9b71c87847c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -828,7 +828,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, char *buf; int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + - (hw_params(priv).max_txq_num * 32 * 8) + 400; + (cfg(priv)->base_params->num_of_queues * 32 * 8) + 400; const u8 *ptr; ssize_t ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index 0d957ca3d6c6..cf34087aa2fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -160,7 +160,6 @@ struct iwl_mod_params { * * Holds the module parameters * - * @max_txq_num: Max # Tx queues supported * @num_ampdu_queues: num of ampdu queues * @tx_chains_num: Number of TX chains * @rx_chains_num: Number of RX chains @@ -177,7 +176,6 @@ struct iwl_mod_params { * @use_rts_for_aggregation: use rts/cts protection for HT traffic */ struct iwl_hw_params { - u8 max_txq_num; u8 num_ampdu_queues; u8 tx_chains_num; u8 rx_chains_num; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index a5547a155b95..9bc3c73af5e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1050,7 +1050,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) if (inta & CSR_INT_BIT_WAKEUP) { IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq); - for (i = 0; i < hw_params(trans).max_txq_num; i++) + for (i = 0; i < cfg(trans)->base_params->num_of_queues; i++) iwl_txq_update_write_ptr(trans, &trans_pcie->txq[i]); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index 2b1df0092aee..565c664f6dce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -595,7 +595,8 @@ static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int txq_id; - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) + for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues; + txq_id++) if (!test_and_set_bit(txq_id, &trans_pcie->txq_ctx_active_msk)) return txq_id; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index a3ac6d814637..91628565409f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -497,7 +497,7 @@ static void iwl_trans_pcie_tx_free(struct iwl_trans *trans) /* Tx queues */ if (trans_pcie->txq) { for (txq_id = 0; - txq_id < hw_params(trans).max_txq_num; txq_id++) + txq_id < cfg(trans)->base_params->num_of_queues; txq_id++) iwl_tx_queue_free(trans, txq_id); } @@ -522,7 +522,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) int txq_id, slots_num; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u16 scd_bc_tbls_size = hw_params(trans).max_txq_num * + u16 scd_bc_tbls_size = cfg(trans)->base_params->num_of_queues * sizeof(struct iwlagn_scd_bc_tbl); /*It is not allowed to alloc twice, so warn when this happens. @@ -546,7 +546,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) goto error; } - trans_pcie->txq = kcalloc(hw_params(trans).max_txq_num, + trans_pcie->txq = kcalloc(cfg(trans)->base_params->num_of_queues, sizeof(struct iwl_tx_queue), GFP_KERNEL); if (!trans_pcie->txq) { IWL_ERR(trans, "Not enough memory for txq\n"); @@ -555,7 +555,8 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) } /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { + for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues; + txq_id++) { slots_num = (txq_id == trans_pcie->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id], @@ -600,7 +601,8 @@ static int iwl_tx_init(struct iwl_trans *trans) spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { + for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues; + txq_id++) { slots_num = (txq_id == trans_pcie->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id], @@ -1116,7 +1118,8 @@ static void iwl_tx_start(struct iwl_trans *trans) a += 4) iwl_write_targ_mem(trans, a, 0); for (; a < trans_pcie->scd_base_addr + - SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num); + SCD_TRANS_TBL_OFFSET_QUEUE( + cfg(trans)->base_params->num_of_queues); a += 4) iwl_write_targ_mem(trans, a, 0); @@ -1139,7 +1142,7 @@ static void iwl_tx_start(struct iwl_trans *trans) iwl_write_prph(trans, SCD_AGGR_SEL, 0); /* initiate the queues */ - for (i = 0; i < hw_params(trans).max_txq_num; i++) { + for (i = 0; i < cfg(trans)->base_params->num_of_queues; i++) { iwl_write_prph(trans, SCD_QUEUE_RDPTR(i), 0); iwl_write_direct32(trans, HBUS_TARG_WRPTR, 0 | (i << 8)); iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + @@ -1156,7 +1159,7 @@ static void iwl_tx_start(struct iwl_trans *trans) } iwl_write_prph(trans, SCD_INTERRUPT_MASK, - IWL_MASK(0, hw_params(trans).max_txq_num)); + IWL_MASK(0, cfg(trans)->base_params->num_of_queues)); /* Activate all Tx DMA/FIFO channels */ iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); @@ -1246,7 +1249,8 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans) } /* Unmap DMA from host system and free skb's */ - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) + for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues; + txq_id++) iwl_tx_queue_unmap(trans, txq_id); return 0; @@ -1685,7 +1689,7 @@ static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) int ret = 0; /* waiting for all the tx frames complete might take a while */ - for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { + for (cnt = 0; cnt < cfg(trans)->base_params->num_of_queues; cnt++) { if (cnt == trans_pcie->cmd_queue) continue; txq = &trans_pcie->txq[cnt]; @@ -1931,7 +1935,9 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, int pos = 0; int cnt; int ret; - const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num; + size_t bufsz; + + bufsz = sizeof(char) * 64 * cfg(trans)->base_params->num_of_queues; if (!trans_pcie->txq) { IWL_ERR(trans, "txq not ready\n"); @@ -1941,7 +1947,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, if (!buf) return -ENOMEM; - for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { + for (cnt = 0; cnt < cfg(trans)->base_params->num_of_queues; cnt++) { txq = &trans_pcie->txq[cnt]; q = &txq->q; pos += scnprintf(buf + pos, bufsz - pos, -- cgit v1.2.3-70-g09d2