aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/p54')
-rw-r--r--drivers/net/wireless/p54/Kconfig2
-rw-r--r--drivers/net/wireless/p54/eeprom.c32
-rw-r--r--drivers/net/wireless/p54/fwio.c1
-rw-r--r--drivers/net/wireless/p54/main.c54
-rw-r--r--drivers/net/wireless/p54/p54.h8
-rw-r--r--drivers/net/wireless/p54/p54pci.c89
-rw-r--r--drivers/net/wireless/p54/p54pci.h6
-rw-r--r--drivers/net/wireless/p54/p54spi.c1
-rw-r--r--drivers/net/wireless/p54/p54usb.c4
-rw-r--r--drivers/net/wireless/p54/txrx.c4
10 files changed, 119 insertions, 82 deletions
diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig
index b45d6a4ed1e8..b0342a520bf1 100644
--- a/drivers/net/wireless/p54/Kconfig
+++ b/drivers/net/wireless/p54/Kconfig
@@ -1,6 +1,6 @@
1config P54_COMMON 1config P54_COMMON
2 tristate "Softmac Prism54 support" 2 tristate "Softmac Prism54 support"
3 depends on MAC80211 && WLAN_80211 && EXPERIMENTAL 3 depends on MAC80211 && EXPERIMENTAL
4 select FW_LOADER 4 select FW_LOADER
5 ---help--- 5 ---help---
6 This is common code for isl38xx/stlc45xx based modules. 6 This is common code for isl38xx/stlc45xx based modules.
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index 0efe67deedee..187e263b045a 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -20,6 +20,7 @@
20#include <linux/firmware.h> 20#include <linux/firmware.h>
21#include <linux/etherdevice.h> 21#include <linux/etherdevice.h>
22#include <linux/sort.h> 22#include <linux/sort.h>
23#include <linux/slab.h>
23 24
24#include <net/mac80211.h> 25#include <net/mac80211.h>
25 26
@@ -126,7 +127,7 @@ static int p54_generate_band(struct ieee80211_hw *dev,
126 int ret = -ENOMEM; 127 int ret = -ENOMEM;
127 128
128 if ((!list->entries) || (!list->band_channel_num[band])) 129 if ((!list->entries) || (!list->band_channel_num[band]))
129 return 0; 130 return -EINVAL;
130 131
131 tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); 132 tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
132 if (!tmp) 133 if (!tmp)
@@ -158,6 +159,7 @@ static int p54_generate_band(struct ieee80211_hw *dev,
158 (list->channels[i].data & CHAN_HAS_CURVE ? "" : 159 (list->channels[i].data & CHAN_HAS_CURVE ? "" :
159 " [curve data]"), 160 " [curve data]"),
160 list->channels[i].index, list->channels[i].freq); 161 list->channels[i].index, list->channels[i].freq);
162 continue;
161 } 163 }
162 164
163 tmp->channels[j].band = list->channels[i].band; 165 tmp->channels[j].band = list->channels[i].band;
@@ -165,7 +167,16 @@ static int p54_generate_band(struct ieee80211_hw *dev,
165 j++; 167 j++;
166 } 168 }
167 169
168 tmp->n_channels = list->band_channel_num[band]; 170 if (j == 0) {
171 printk(KERN_ERR "%s: Disabling totally damaged %s band.\n",
172 wiphy_name(dev->wiphy), (band == IEEE80211_BAND_2GHZ) ?
173 "2 GHz" : "5 GHz");
174
175 ret = -ENODATA;
176 goto err_out;
177 }
178
179 tmp->n_channels = j;
169 old = priv->band_table[band]; 180 old = priv->band_table[band];
170 priv->band_table[band] = tmp; 181 priv->band_table[band] = tmp;
171 if (old) { 182 if (old) {
@@ -228,13 +239,13 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
228 struct p54_common *priv = dev->priv; 239 struct p54_common *priv = dev->priv;
229 struct p54_channel_list *list; 240 struct p54_channel_list *list;
230 unsigned int i, j, max_channel_num; 241 unsigned int i, j, max_channel_num;
231 int ret = -ENOMEM; 242 int ret = 0;
232 u16 freq; 243 u16 freq;
233 244
234 if ((priv->iq_autocal_len != priv->curve_data->entries) || 245 if ((priv->iq_autocal_len != priv->curve_data->entries) ||
235 (priv->iq_autocal_len != priv->output_limit->entries)) 246 (priv->iq_autocal_len != priv->output_limit->entries))
236 printk(KERN_ERR "%s: EEPROM is damaged... you may not be able" 247 printk(KERN_ERR "%s: Unsupported or damaged EEPROM detected. "
237 "to use all channels with this device.\n", 248 "You may not be able to use all channels.\n",
238 wiphy_name(dev->wiphy)); 249 wiphy_name(dev->wiphy));
239 250
240 max_channel_num = max_t(unsigned int, priv->output_limit->entries, 251 max_channel_num = max_t(unsigned int, priv->output_limit->entries,
@@ -243,8 +254,10 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
243 priv->curve_data->entries); 254 priv->curve_data->entries);
244 255
245 list = kzalloc(sizeof(*list), GFP_KERNEL); 256 list = kzalloc(sizeof(*list), GFP_KERNEL);
246 if (!list) 257 if (!list) {
258 ret = -ENOMEM;
247 goto free; 259 goto free;
260 }
248 261
249 list->max_entries = max_channel_num; 262 list->max_entries = max_channel_num;
250 list->channels = kzalloc(sizeof(struct p54_channel_entry) * 263 list->channels = kzalloc(sizeof(struct p54_channel_entry) *
@@ -282,13 +295,8 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
282 p54_compare_channels, NULL); 295 p54_compare_channels, NULL);
283 296
284 for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) { 297 for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) {
285 if (list->band_channel_num[i]) { 298 if (p54_generate_band(dev, list, i) == 0)
286 ret = p54_generate_band(dev, list, i);
287 if (ret)
288 goto free;
289
290 j++; 299 j++;
291 }
292 } 300 }
293 if (j == 0) { 301 if (j == 0) {
294 /* no useable band available. */ 302 /* no useable band available. */
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index e7b9e9cb39f5..c43a5d461ab2 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -17,6 +17,7 @@
17 */ 17 */
18 18
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/slab.h>
20#include <linux/firmware.h> 21#include <linux/firmware.h>
21#include <linux/etherdevice.h> 22#include <linux/etherdevice.h>
22 23
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index 4d486bf9f725..a7cb9eb759a1 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -17,6 +17,7 @@
17 */ 17 */
18 18
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/slab.h>
20#include <linux/firmware.h> 21#include <linux/firmware.h>
21#include <linux/etherdevice.h> 22#include <linux/etherdevice.h>
22 23
@@ -33,21 +34,29 @@ MODULE_DESCRIPTION("Softmac Prism54 common code");
33MODULE_LICENSE("GPL"); 34MODULE_LICENSE("GPL");
34MODULE_ALIAS("prism54common"); 35MODULE_ALIAS("prism54common");
35 36
37static int p54_sta_add_remove(struct ieee80211_hw *hw,
38 struct ieee80211_vif *vif,
39 struct ieee80211_sta *sta)
40{
41 struct p54_common *priv = hw->priv;
42
43 /*
44 * Notify the firmware that we don't want or we don't
45 * need to buffer frames for this station anymore.
46 */
47
48 p54_sta_unlock(priv, sta->addr);
49
50 return 0;
51}
52
36static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, 53static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
37 enum sta_notify_cmd notify_cmd, 54 enum sta_notify_cmd notify_cmd,
38 struct ieee80211_sta *sta) 55 struct ieee80211_sta *sta)
39{ 56{
40 struct p54_common *priv = dev->priv; 57 struct p54_common *priv = dev->priv;
41 switch (notify_cmd) {
42 case STA_NOTIFY_ADD:
43 case STA_NOTIFY_REMOVE:
44 /*
45 * Notify the firmware that we don't want or we don't
46 * need to buffer frames for this station anymore.
47 */
48 58
49 p54_sta_unlock(priv, sta->addr); 59 switch (notify_cmd) {
50 break;
51 case STA_NOTIFY_AWAKE: 60 case STA_NOTIFY_AWAKE:
52 /* update the firmware's filter table */ 61 /* update the firmware's filter table */
53 p54_sta_unlock(priv, sta->addr); 62 p54_sta_unlock(priv, sta->addr);
@@ -216,7 +225,7 @@ static void p54_stop(struct ieee80211_hw *dev)
216} 225}
217 226
218static int p54_add_interface(struct ieee80211_hw *dev, 227static int p54_add_interface(struct ieee80211_hw *dev,
219 struct ieee80211_if_init_conf *conf) 228 struct ieee80211_vif *vif)
220{ 229{
221 struct p54_common *priv = dev->priv; 230 struct p54_common *priv = dev->priv;
222 231
@@ -226,28 +235,28 @@ static int p54_add_interface(struct ieee80211_hw *dev,
226 return -EOPNOTSUPP; 235 return -EOPNOTSUPP;
227 } 236 }
228 237
229 priv->vif = conf->vif; 238 priv->vif = vif;
230 239
231 switch (conf->type) { 240 switch (vif->type) {
232 case NL80211_IFTYPE_STATION: 241 case NL80211_IFTYPE_STATION:
233 case NL80211_IFTYPE_ADHOC: 242 case NL80211_IFTYPE_ADHOC:
234 case NL80211_IFTYPE_AP: 243 case NL80211_IFTYPE_AP:
235 case NL80211_IFTYPE_MESH_POINT: 244 case NL80211_IFTYPE_MESH_POINT:
236 priv->mode = conf->type; 245 priv->mode = vif->type;
237 break; 246 break;
238 default: 247 default:
239 mutex_unlock(&priv->conf_mutex); 248 mutex_unlock(&priv->conf_mutex);
240 return -EOPNOTSUPP; 249 return -EOPNOTSUPP;
241 } 250 }
242 251
243 memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); 252 memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
244 p54_setup_mac(priv); 253 p54_setup_mac(priv);
245 mutex_unlock(&priv->conf_mutex); 254 mutex_unlock(&priv->conf_mutex);
246 return 0; 255 return 0;
247} 256}
248 257
249static void p54_remove_interface(struct ieee80211_hw *dev, 258static void p54_remove_interface(struct ieee80211_hw *dev,
250 struct ieee80211_if_init_conf *conf) 259 struct ieee80211_vif *vif)
251{ 260{
252 struct p54_common *priv = dev->priv; 261 struct p54_common *priv = dev->priv;
253 262
@@ -358,16 +367,6 @@ static int p54_get_stats(struct ieee80211_hw *dev,
358 return 0; 367 return 0;
359} 368}
360 369
361static int p54_get_tx_stats(struct ieee80211_hw *dev,
362 struct ieee80211_tx_queue_stats *stats)
363{
364 struct p54_common *priv = dev->priv;
365
366 memcpy(stats, &priv->tx_stats[P54_QUEUE_DATA],
367 sizeof(stats[0]) * dev->queues);
368 return 0;
369}
370
371static void p54_bss_info_changed(struct ieee80211_hw *dev, 370static void p54_bss_info_changed(struct ieee80211_hw *dev,
372 struct ieee80211_vif *vif, 371 struct ieee80211_vif *vif,
373 struct ieee80211_bss_conf *info, 372 struct ieee80211_bss_conf *info,
@@ -516,13 +515,14 @@ static const struct ieee80211_ops p54_ops = {
516 .remove_interface = p54_remove_interface, 515 .remove_interface = p54_remove_interface,
517 .set_tim = p54_set_tim, 516 .set_tim = p54_set_tim,
518 .sta_notify = p54_sta_notify, 517 .sta_notify = p54_sta_notify,
518 .sta_add = p54_sta_add_remove,
519 .sta_remove = p54_sta_add_remove,
519 .set_key = p54_set_key, 520 .set_key = p54_set_key,
520 .config = p54_config, 521 .config = p54_config,
521 .bss_info_changed = p54_bss_info_changed, 522 .bss_info_changed = p54_bss_info_changed,
522 .configure_filter = p54_configure_filter, 523 .configure_filter = p54_configure_filter,
523 .conf_tx = p54_conf_tx, 524 .conf_tx = p54_conf_tx,
524 .get_stats = p54_get_stats, 525 .get_stats = p54_get_stats,
525 .get_tx_stats = p54_get_tx_stats
526}; 526};
527 527
528struct ieee80211_hw *p54_init_common(size_t priv_data_len) 528struct ieee80211_hw *p54_init_common(size_t priv_data_len)
@@ -579,7 +579,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
579 * For now, disable PS by default because it affects 579 * For now, disable PS by default because it affects
580 * link stability significantly. 580 * link stability significantly.
581 */ 581 */
582 dev->wiphy->ps_default = false; 582 dev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
583 583
584 mutex_init(&priv->conf_mutex); 584 mutex_init(&priv->conf_mutex);
585 mutex_init(&priv->eeprom_mutex); 585 mutex_init(&priv->eeprom_mutex);
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index 1afc39410e85..43a3b2ead81a 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -157,6 +157,12 @@ struct p54_led_dev {
157 157
158#endif /* CONFIG_P54_LEDS */ 158#endif /* CONFIG_P54_LEDS */
159 159
160struct p54_tx_queue_stats {
161 unsigned int len;
162 unsigned int limit;
163 unsigned int count;
164};
165
160struct p54_common { 166struct p54_common {
161 struct ieee80211_hw *hw; 167 struct ieee80211_hw *hw;
162 struct ieee80211_vif *vif; 168 struct ieee80211_vif *vif;
@@ -183,7 +189,7 @@ struct p54_common {
183 /* (e)DCF / QOS state */ 189 /* (e)DCF / QOS state */
184 bool use_short_slot; 190 bool use_short_slot;
185 spinlock_t tx_stats_lock; 191 spinlock_t tx_stats_lock;
186 struct ieee80211_tx_queue_stats tx_stats[8]; 192 struct p54_tx_queue_stats tx_stats[8];
187 struct p54_edcf_queue_param qos_params[8]; 193 struct p54_edcf_queue_param qos_params[8];
188 194
189 /* Radio data */ 195 /* Radio data */
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index d348c265e867..c24067f1a0cb 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -15,6 +15,7 @@
15 15
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/pci.h> 17#include <linux/pci.h>
18#include <linux/slab.h>
18#include <linux/firmware.h> 19#include <linux/firmware.h>
19#include <linux/etherdevice.h> 20#include <linux/etherdevice.h>
20#include <linux/delay.h> 21#include <linux/delay.h>
@@ -31,7 +32,7 @@ MODULE_LICENSE("GPL");
31MODULE_ALIAS("prism54pci"); 32MODULE_ALIAS("prism54pci");
32MODULE_FIRMWARE("isl3886pci"); 33MODULE_FIRMWARE("isl3886pci");
33 34
34static struct pci_device_id p54p_table[] __devinitdata = { 35static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
35 /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ 36 /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
36 { PCI_DEVICE(0x1260, 0x3890) }, 37 { PCI_DEVICE(0x1260, 0x3890) },
37 /* 3COM 3CRWE154G72 Wireless LAN adapter */ 38 /* 3COM 3CRWE154G72 Wireless LAN adapter */
@@ -157,6 +158,14 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev,
157 skb_tail_pointer(skb), 158 skb_tail_pointer(skb),
158 priv->common.rx_mtu + 32, 159 priv->common.rx_mtu + 32,
159 PCI_DMA_FROMDEVICE); 160 PCI_DMA_FROMDEVICE);
161
162 if (pci_dma_mapping_error(priv->pdev, mapping)) {
163 dev_kfree_skb_any(skb);
164 dev_err(&priv->pdev->dev,
165 "RX DMA Mapping error\n");
166 break;
167 }
168
160 desc->host_addr = cpu_to_le32(mapping); 169 desc->host_addr = cpu_to_le32(mapping);
161 desc->device_addr = 0; // FIXME: necessary? 170 desc->device_addr = 0; // FIXME: necessary?
162 desc->len = cpu_to_le16(priv->common.rx_mtu + 32); 171 desc->len = cpu_to_le16(priv->common.rx_mtu + 32);
@@ -197,6 +206,14 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
197 i %= ring_limit; 206 i %= ring_limit;
198 continue; 207 continue;
199 } 208 }
209
210 if (unlikely(len > priv->common.rx_mtu)) {
211 if (net_ratelimit())
212 dev_err(&priv->pdev->dev, "rx'd frame size "
213 "exceeds length threshold.\n");
214
215 len = priv->common.rx_mtu;
216 }
200 skb_put(skb, len); 217 skb_put(skb, len);
201 218
202 if (p54_rx(dev, skb)) { 219 if (p54_rx(dev, skb)) {
@@ -218,25 +235,24 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
218 p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf); 235 p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf);
219} 236}
220 237
221/* caller must hold priv->lock */
222static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, 238static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
223 int ring_index, struct p54p_desc *ring, u32 ring_limit, 239 int ring_index, struct p54p_desc *ring, u32 ring_limit,
224 void **tx_buf) 240 struct sk_buff **tx_buf)
225{ 241{
226 struct p54p_priv *priv = dev->priv; 242 struct p54p_priv *priv = dev->priv;
227 struct p54p_ring_control *ring_control = priv->ring_control; 243 struct p54p_ring_control *ring_control = priv->ring_control;
228 struct p54p_desc *desc; 244 struct p54p_desc *desc;
245 struct sk_buff *skb;
229 u32 idx, i; 246 u32 idx, i;
230 247
231 i = (*index) % ring_limit; 248 i = (*index) % ring_limit;
232 (*index) = idx = le32_to_cpu(ring_control->device_idx[1]); 249 (*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]);
233 idx %= ring_limit; 250 idx %= ring_limit;
234 251
235 while (i != idx) { 252 while (i != idx) {
236 desc = &ring[i]; 253 desc = &ring[i];
237 if (tx_buf[i]) 254
238 if (FREE_AFTER_TX((struct sk_buff *) tx_buf[i])) 255 skb = tx_buf[i];
239 p54_free_skb(dev, tx_buf[i]);
240 tx_buf[i] = NULL; 256 tx_buf[i] = NULL;
241 257
242 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), 258 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
@@ -247,17 +263,28 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
247 desc->len = 0; 263 desc->len = 0;
248 desc->flags = 0; 264 desc->flags = 0;
249 265
266 if (skb && FREE_AFTER_TX(skb))
267 p54_free_skb(dev, skb);
268
250 i++; 269 i++;
251 i %= ring_limit; 270 i %= ring_limit;
252 } 271 }
253} 272}
254 273
255static void p54p_rx_tasklet(unsigned long dev_id) 274static void p54p_tasklet(unsigned long dev_id)
256{ 275{
257 struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id; 276 struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id;
258 struct p54p_priv *priv = dev->priv; 277 struct p54p_priv *priv = dev->priv;
259 struct p54p_ring_control *ring_control = priv->ring_control; 278 struct p54p_ring_control *ring_control = priv->ring_control;
260 279
280 p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt,
281 ARRAY_SIZE(ring_control->tx_mgmt),
282 priv->tx_buf_mgmt);
283
284 p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data,
285 ARRAY_SIZE(ring_control->tx_data),
286 priv->tx_buf_data);
287
261 p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, 288 p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,
262 ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); 289 ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt);
263 290
@@ -272,59 +299,49 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
272{ 299{
273 struct ieee80211_hw *dev = dev_id; 300 struct ieee80211_hw *dev = dev_id;
274 struct p54p_priv *priv = dev->priv; 301 struct p54p_priv *priv = dev->priv;
275 struct p54p_ring_control *ring_control = priv->ring_control;
276 __le32 reg; 302 __le32 reg;
277 303
278 spin_lock(&priv->lock);
279 reg = P54P_READ(int_ident); 304 reg = P54P_READ(int_ident);
280 if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { 305 if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
281 spin_unlock(&priv->lock); 306 goto out;
282 return IRQ_HANDLED;
283 } 307 }
284
285 P54P_WRITE(int_ack, reg); 308 P54P_WRITE(int_ack, reg);
286 309
287 reg &= P54P_READ(int_enable); 310 reg &= P54P_READ(int_enable);
288 311
289 if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) { 312 if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE))
290 p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 313 tasklet_schedule(&priv->tasklet);
291 3, ring_control->tx_mgmt, 314 else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
292 ARRAY_SIZE(ring_control->tx_mgmt),
293 priv->tx_buf_mgmt);
294
295 p54p_check_tx_ring(dev, &priv->tx_idx_data,
296 1, ring_control->tx_data,
297 ARRAY_SIZE(ring_control->tx_data),
298 priv->tx_buf_data);
299
300 tasklet_schedule(&priv->rx_tasklet);
301
302 } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
303 complete(&priv->boot_comp); 315 complete(&priv->boot_comp);
304 316
305 spin_unlock(&priv->lock); 317out:
306
307 return reg ? IRQ_HANDLED : IRQ_NONE; 318 return reg ? IRQ_HANDLED : IRQ_NONE;
308} 319}
309 320
310static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) 321static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
311{ 322{
323 unsigned long flags;
312 struct p54p_priv *priv = dev->priv; 324 struct p54p_priv *priv = dev->priv;
313 struct p54p_ring_control *ring_control = priv->ring_control; 325 struct p54p_ring_control *ring_control = priv->ring_control;
314 unsigned long flags;
315 struct p54p_desc *desc; 326 struct p54p_desc *desc;
316 dma_addr_t mapping; 327 dma_addr_t mapping;
317 u32 device_idx, idx, i; 328 u32 device_idx, idx, i;
318 329
319 spin_lock_irqsave(&priv->lock, flags); 330 spin_lock_irqsave(&priv->lock, flags);
320
321 device_idx = le32_to_cpu(ring_control->device_idx[1]); 331 device_idx = le32_to_cpu(ring_control->device_idx[1]);
322 idx = le32_to_cpu(ring_control->host_idx[1]); 332 idx = le32_to_cpu(ring_control->host_idx[1]);
323 i = idx % ARRAY_SIZE(ring_control->tx_data); 333 i = idx % ARRAY_SIZE(ring_control->tx_data);
324 334
325 priv->tx_buf_data[i] = skb;
326 mapping = pci_map_single(priv->pdev, skb->data, skb->len, 335 mapping = pci_map_single(priv->pdev, skb->data, skb->len,
327 PCI_DMA_TODEVICE); 336 PCI_DMA_TODEVICE);
337 if (pci_dma_mapping_error(priv->pdev, mapping)) {
338 spin_unlock_irqrestore(&priv->lock, flags);
339 p54_free_skb(dev, skb);
340 dev_err(&priv->pdev->dev, "TX DMA mapping error\n");
341 return ;
342 }
343 priv->tx_buf_data[i] = skb;
344
328 desc = &ring_control->tx_data[i]; 345 desc = &ring_control->tx_data[i];
329 desc->host_addr = cpu_to_le32(mapping); 346 desc->host_addr = cpu_to_le32(mapping);
330 desc->device_addr = ((struct p54_hdr *)skb->data)->req_id; 347 desc->device_addr = ((struct p54_hdr *)skb->data)->req_id;
@@ -346,14 +363,14 @@ static void p54p_stop(struct ieee80211_hw *dev)
346 unsigned int i; 363 unsigned int i;
347 struct p54p_desc *desc; 364 struct p54p_desc *desc;
348 365
349 tasklet_kill(&priv->rx_tasklet);
350
351 P54P_WRITE(int_enable, cpu_to_le32(0)); 366 P54P_WRITE(int_enable, cpu_to_le32(0));
352 P54P_READ(int_enable); 367 P54P_READ(int_enable);
353 udelay(10); 368 udelay(10);
354 369
355 free_irq(priv->pdev->irq, dev); 370 free_irq(priv->pdev->irq, dev);
356 371
372 tasklet_kill(&priv->tasklet);
373
357 P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); 374 P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
358 375
359 for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) { 376 for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) {
@@ -411,7 +428,7 @@ static int p54p_open(struct ieee80211_hw *dev)
411 int err; 428 int err;
412 429
413 init_completion(&priv->boot_comp); 430 init_completion(&priv->boot_comp);
414 err = request_irq(priv->pdev->irq, &p54p_interrupt, 431 err = request_irq(priv->pdev->irq, p54p_interrupt,
415 IRQF_SHARED, "p54pci", dev); 432 IRQF_SHARED, "p54pci", dev);
416 if (err) { 433 if (err) {
417 dev_err(&priv->pdev->dev, "failed to register IRQ handler\n"); 434 dev_err(&priv->pdev->dev, "failed to register IRQ handler\n");
@@ -537,7 +554,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
537 priv->common.tx = p54p_tx; 554 priv->common.tx = p54p_tx;
538 555
539 spin_lock_init(&priv->lock); 556 spin_lock_init(&priv->lock);
540 tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev); 557 tasklet_init(&priv->tasklet, p54p_tasklet, (unsigned long)dev);
541 558
542 err = request_firmware(&priv->firmware, "isl3886pci", 559 err = request_firmware(&priv->firmware, "isl3886pci",
543 &priv->pdev->dev); 560 &priv->pdev->dev);
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h
index fbb683953fb2..2feead617a3b 100644
--- a/drivers/net/wireless/p54/p54pci.h
+++ b/drivers/net/wireless/p54/p54pci.h
@@ -92,7 +92,7 @@ struct p54p_priv {
92 struct p54_common common; 92 struct p54_common common;
93 struct pci_dev *pdev; 93 struct pci_dev *pdev;
94 struct p54p_csr __iomem *map; 94 struct p54p_csr __iomem *map;
95 struct tasklet_struct rx_tasklet; 95 struct tasklet_struct tasklet;
96 const struct firmware *firmware; 96 const struct firmware *firmware;
97 spinlock_t lock; 97 spinlock_t lock;
98 struct p54p_ring_control *ring_control; 98 struct p54p_ring_control *ring_control;
@@ -101,8 +101,8 @@ struct p54p_priv {
101 u32 rx_idx_mgmt, tx_idx_mgmt; 101 u32 rx_idx_mgmt, tx_idx_mgmt;
102 struct sk_buff *rx_buf_data[8]; 102 struct sk_buff *rx_buf_data[8];
103 struct sk_buff *rx_buf_mgmt[4]; 103 struct sk_buff *rx_buf_mgmt[4];
104 void *tx_buf_data[32]; 104 struct sk_buff *tx_buf_data[32];
105 void *tx_buf_mgmt[4]; 105 struct sk_buff *tx_buf_mgmt[4];
106 struct completion boot_comp; 106 struct completion boot_comp;
107}; 107};
108 108
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index afd26bf06649..c8f09da1f84d 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -29,6 +29,7 @@
29#include <linux/spi/spi.h> 29#include <linux/spi/spi.h>
30#include <linux/etherdevice.h> 30#include <linux/etherdevice.h>
31#include <linux/gpio.h> 31#include <linux/gpio.h>
32#include <linux/slab.h>
32 33
33#include "p54spi.h" 34#include "p54spi.h"
34#include "p54spi_eeprom.h" 35#include "p54spi_eeprom.h"
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 92af9b96bb7a..743a6c68b29d 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -15,6 +15,7 @@
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/usb.h> 16#include <linux/usb.h>
17#include <linux/pci.h> 17#include <linux/pci.h>
18#include <linux/slab.h>
18#include <linux/firmware.h> 19#include <linux/firmware.h>
19#include <linux/etherdevice.h> 20#include <linux/etherdevice.h>
20#include <linux/delay.h> 21#include <linux/delay.h>
@@ -35,7 +36,9 @@ MODULE_FIRMWARE("isl3887usb");
35static struct usb_device_id p54u_table[] __devinitdata = { 36static struct usb_device_id p54u_table[] __devinitdata = {
36 /* Version 1 devices (pci chip + net2280) */ 37 /* Version 1 devices (pci chip + net2280) */
37 {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ 38 {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
39 {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */
38 {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ 40 {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
41 {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */
39 {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */ 42 {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
40 {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */ 43 {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
41 {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */ 44 {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
@@ -60,6 +63,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
60 {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ 63 {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
61 {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ 64 {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
62 {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ 65 {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
66 {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */
63 {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ 67 {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
64 {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ 68 {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
65 {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ 69 {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index b6dda2b27fb5..66057999a93c 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -183,10 +183,10 @@ static int p54_tx_qos_accounting_alloc(struct p54_common *priv,
183 struct sk_buff *skb, 183 struct sk_buff *skb,
184 const u16 p54_queue) 184 const u16 p54_queue)
185{ 185{
186 struct ieee80211_tx_queue_stats *queue; 186 struct p54_tx_queue_stats *queue;
187 unsigned long flags; 187 unsigned long flags;
188 188
189 if (WARN_ON(p54_queue > P54_QUEUE_NUM)) 189 if (WARN_ON(p54_queue >= P54_QUEUE_NUM))
190 return -EINVAL; 190 return -EINVAL;
191 191
192 queue = &priv->tx_stats[p54_queue]; 192 queue = &priv->tx_stats[p54_queue];