diff options
author | Christian Lamparter <chunkeey@web.de> | 2009-07-16 14:03:47 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-24 15:05:21 -0400 |
commit | 46df10ae44b4488176bae16da0b31541eb0f8f48 (patch) | |
tree | 0f562347c429808ee8ba0ec151ea77189d5be744 /drivers/net/wireless/p54/main.c | |
parent | 12f49a79cd32d97a11f864a7b67660438ee3e6c8 (diff) |
p54: fix beaconing related firmware crash
This patch fixes a firmware crash which can be provoked by changing
operation mode.
Acked-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Christian Lamparter <chunkeey@web.de>
Tested-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54/main.c')
-rw-r--r-- | drivers/net/wireless/p54/main.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index f19add2c3cac..955f6d7ec16a 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -130,7 +130,6 @@ static int p54_beacon_update(struct p54_common *priv, | |||
130 | struct ieee80211_vif *vif) | 130 | struct ieee80211_vif *vif) |
131 | { | 131 | { |
132 | struct sk_buff *beacon; | 132 | struct sk_buff *beacon; |
133 | __le32 old_beacon_req_id; | ||
134 | int ret; | 133 | int ret; |
135 | 134 | ||
136 | beacon = ieee80211_beacon_get(priv->hw, vif); | 135 | beacon = ieee80211_beacon_get(priv->hw, vif); |
@@ -140,15 +139,16 @@ static int p54_beacon_update(struct p54_common *priv, | |||
140 | if (ret) | 139 | if (ret) |
141 | return ret; | 140 | return ret; |
142 | 141 | ||
143 | old_beacon_req_id = priv->beacon_req_id; | 142 | /* |
144 | priv->beacon_req_id = GET_REQ_ID(beacon); | 143 | * During operation, the firmware takes care of beaconing. |
145 | 144 | * The driver only needs to upload a new beacon template, once | |
146 | ret = p54_tx_80211(priv->hw, beacon); | 145 | * the template was changed by the stack or userspace. |
147 | if (ret) { | 146 | * |
148 | priv->beacon_req_id = old_beacon_req_id; | 147 | * LMAC API 3.2.2 also specifies that the driver does not need |
149 | return -ENOSPC; | 148 | * to cancel the old beacon template by hand, instead the firmware |
150 | } | 149 | * will release the previous one through the feedback mechanism. |
151 | 150 | */ | |
151 | WARN_ON(p54_tx_80211(priv->hw, beacon)); | ||
152 | priv->tsf_high32 = 0; | 152 | priv->tsf_high32 = 0; |
153 | priv->tsf_low32 = 0; | 153 | priv->tsf_low32 = 0; |
154 | 154 | ||
@@ -253,9 +253,14 @@ static void p54_remove_interface(struct ieee80211_hw *dev, | |||
253 | 253 | ||
254 | mutex_lock(&priv->conf_mutex); | 254 | mutex_lock(&priv->conf_mutex); |
255 | priv->vif = NULL; | 255 | priv->vif = NULL; |
256 | if (priv->beacon_req_id) { | 256 | |
257 | /* | ||
258 | * LMAC API 3.2.2 states that any active beacon template must be | ||
259 | * canceled by the driver before attempting a mode transition. | ||
260 | */ | ||
261 | if (le32_to_cpu(priv->beacon_req_id) != 0) { | ||
257 | p54_tx_cancel(priv, priv->beacon_req_id); | 262 | p54_tx_cancel(priv, priv->beacon_req_id); |
258 | priv->beacon_req_id = cpu_to_le32(0); | 263 | wait_for_completion_interruptible_timeout(&priv->beacon_comp, HZ); |
259 | } | 264 | } |
260 | priv->mode = NL80211_IFTYPE_MONITOR; | 265 | priv->mode = NL80211_IFTYPE_MONITOR; |
261 | memset(priv->mac_addr, 0, ETH_ALEN); | 266 | memset(priv->mac_addr, 0, ETH_ALEN); |
@@ -544,6 +549,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
544 | BIT(NL80211_IFTYPE_MESH_POINT); | 549 | BIT(NL80211_IFTYPE_MESH_POINT); |
545 | 550 | ||
546 | dev->channel_change_time = 1000; /* TODO: find actual value */ | 551 | dev->channel_change_time = 1000; /* TODO: find actual value */ |
552 | priv->beacon_req_id = cpu_to_le32(0); | ||
547 | priv->tx_stats[P54_QUEUE_BEACON].limit = 1; | 553 | priv->tx_stats[P54_QUEUE_BEACON].limit = 1; |
548 | priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1; | 554 | priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1; |
549 | priv->tx_stats[P54_QUEUE_MGMT].limit = 3; | 555 | priv->tx_stats[P54_QUEUE_MGMT].limit = 3; |
@@ -567,6 +573,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
567 | mutex_init(&priv->conf_mutex); | 573 | mutex_init(&priv->conf_mutex); |
568 | mutex_init(&priv->eeprom_mutex); | 574 | mutex_init(&priv->eeprom_mutex); |
569 | init_completion(&priv->eeprom_comp); | 575 | init_completion(&priv->eeprom_comp); |
576 | init_completion(&priv->beacon_comp); | ||
570 | INIT_DELAYED_WORK(&priv->work, p54_work); | 577 | INIT_DELAYED_WORK(&priv->work, p54_work); |
571 | 578 | ||
572 | return dev; | 579 | return dev; |