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/p54.h2
-rw-r--r--drivers/net/wireless/p54/p54common.c170
-rw-r--r--drivers/net/wireless/p54/p54common.h23
-rw-r--r--drivers/net/wireless/p54/p54pci.c242
-rw-r--r--drivers/net/wireless/p54/p54pci.h10
5 files changed, 300 insertions, 147 deletions
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index 10df07de9e52..fca8762fa069 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -66,7 +66,7 @@ struct p54_common {
66 unsigned int tx_hdr_len; 66 unsigned int tx_hdr_len;
67 void *cached_vdcf; 67 void *cached_vdcf;
68 unsigned int fw_var; 68 unsigned int fw_var;
69 struct ieee80211_tx_queue_stats tx_stats[4]; 69 struct ieee80211_tx_queue_stats tx_stats[8];
70}; 70};
71 71
72int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); 72int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 29be3dc8ee09..17e06bbc996a 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -146,23 +146,23 @@ void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
146 146
147 if (priv->fw_var >= 0x300) { 147 if (priv->fw_var >= 0x300) {
148 /* Firmware supports QoS, use it! */ 148 /* Firmware supports QoS, use it! */
149 priv->tx_stats[0].limit = 3; 149 priv->tx_stats[4].limit = 3;
150 priv->tx_stats[1].limit = 4; 150 priv->tx_stats[5].limit = 4;
151 priv->tx_stats[2].limit = 3; 151 priv->tx_stats[6].limit = 3;
152 priv->tx_stats[3].limit = 1; 152 priv->tx_stats[7].limit = 1;
153 dev->queues = 4; 153 dev->queues = 4;
154 } 154 }
155} 155}
156EXPORT_SYMBOL_GPL(p54_parse_firmware); 156EXPORT_SYMBOL_GPL(p54_parse_firmware);
157 157
158static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev, 158static int p54_convert_rev0(struct ieee80211_hw *dev,
159 struct pda_pa_curve_data *curve_data) 159 struct pda_pa_curve_data *curve_data)
160{ 160{
161 struct p54_common *priv = dev->priv; 161 struct p54_common *priv = dev->priv;
162 struct pda_pa_curve_data_sample_rev1 *rev1; 162 struct p54_pa_curve_data_sample *dst;
163 struct pda_pa_curve_data_sample_rev0 *rev0; 163 struct pda_pa_curve_data_sample_rev0 *src;
164 size_t cd_len = sizeof(*curve_data) + 164 size_t cd_len = sizeof(*curve_data) +
165 (curve_data->points_per_channel*sizeof(*rev1) + 2) * 165 (curve_data->points_per_channel*sizeof(*dst) + 2) *
166 curve_data->channels; 166 curve_data->channels;
167 unsigned int i, j; 167 unsigned int i, j;
168 void *source, *target; 168 void *source, *target;
@@ -180,27 +180,63 @@ static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
180 *((__le16 *)target) = *freq; 180 *((__le16 *)target) = *freq;
181 target += sizeof(__le16); 181 target += sizeof(__le16);
182 for (j = 0; j < curve_data->points_per_channel; j++) { 182 for (j = 0; j < curve_data->points_per_channel; j++) {
183 rev1 = target; 183 dst = target;
184 rev0 = source; 184 src = source;
185 185
186 rev1->rf_power = rev0->rf_power; 186 dst->rf_power = src->rf_power;
187 rev1->pa_detector = rev0->pa_detector; 187 dst->pa_detector = src->pa_detector;
188 rev1->data_64qam = rev0->pcv; 188 dst->data_64qam = src->pcv;
189 /* "invent" the points for the other modulations */ 189 /* "invent" the points for the other modulations */
190#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y) 190#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
191 rev1->data_16qam = SUB(rev0->pcv, 12); 191 dst->data_16qam = SUB(src->pcv, 12);
192 rev1->data_qpsk = SUB(rev1->data_16qam, 12); 192 dst->data_qpsk = SUB(dst->data_16qam, 12);
193 rev1->data_bpsk = SUB(rev1->data_qpsk, 12); 193 dst->data_bpsk = SUB(dst->data_qpsk, 12);
194 rev1->data_barker= SUB(rev1->data_bpsk, 14); 194 dst->data_barker = SUB(dst->data_bpsk, 14);
195#undef SUB 195#undef SUB
196 target += sizeof(*rev1); 196 target += sizeof(*dst);
197 source += sizeof(*rev0); 197 source += sizeof(*src);
198 } 198 }
199 } 199 }
200 200
201 return 0; 201 return 0;
202} 202}
203 203
204static int p54_convert_rev1(struct ieee80211_hw *dev,
205 struct pda_pa_curve_data *curve_data)
206{
207 struct p54_common *priv = dev->priv;
208 struct p54_pa_curve_data_sample *dst;
209 struct pda_pa_curve_data_sample_rev1 *src;
210 size_t cd_len = sizeof(*curve_data) +
211 (curve_data->points_per_channel*sizeof(*dst) + 2) *
212 curve_data->channels;
213 unsigned int i, j;
214 void *source, *target;
215
216 priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
217 if (!priv->curve_data)
218 return -ENOMEM;
219
220 memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
221 source = curve_data->data;
222 target = priv->curve_data->data;
223 for (i = 0; i < curve_data->channels; i++) {
224 __le16 *freq = source;
225 source += sizeof(__le16);
226 *((__le16 *)target) = *freq;
227 target += sizeof(__le16);
228 for (j = 0; j < curve_data->points_per_channel; j++) {
229 memcpy(target, source, sizeof(*src));
230
231 target += sizeof(*dst);
232 source += sizeof(*src);
233 }
234 source++;
235 }
236
237 return 0;
238}
239
204int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) 240int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
205{ 241{
206 struct p54_common *priv = dev->priv; 242 struct p54_common *priv = dev->priv;
@@ -250,27 +286,32 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
250 entry->data[1]*sizeof(*priv->output_limit)); 286 entry->data[1]*sizeof(*priv->output_limit));
251 priv->output_limit_len = entry->data[1]; 287 priv->output_limit_len = entry->data[1];
252 break; 288 break;
253 case PDR_PRISM_PA_CAL_CURVE_DATA: 289 case PDR_PRISM_PA_CAL_CURVE_DATA: {
254 if (data_len < sizeof(struct pda_pa_curve_data)) { 290 struct pda_pa_curve_data *curve_data =
291 (struct pda_pa_curve_data *)entry->data;
292 if (data_len < sizeof(*curve_data)) {
255 err = -EINVAL; 293 err = -EINVAL;
256 goto err; 294 goto err;
257 } 295 }
258 296
259 if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) { 297 switch (curve_data->cal_method_rev) {
260 priv->curve_data = kmalloc(data_len, GFP_KERNEL); 298 case 0:
261 if (!priv->curve_data) { 299 err = p54_convert_rev0(dev, curve_data);
262 err = -ENOMEM; 300 break;
263 goto err; 301 case 1:
264 } 302 err = p54_convert_rev1(dev, curve_data);
265 303 break;
266 memcpy(priv->curve_data, entry->data, data_len); 304 default:
267 } else { 305 printk(KERN_ERR "p54: unknown curve data "
268 err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data); 306 "revision %d\n",
269 if (err) 307 curve_data->cal_method_rev);
270 goto err; 308 err = -ENODEV;
309 break;
271 } 310 }
311 if (err)
312 goto err;
272 313
273 break; 314 }
274 case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: 315 case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
275 priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); 316 priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
276 if (!priv->iq_autocal) { 317 if (!priv->iq_autocal) {
@@ -377,7 +418,7 @@ static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
377 int i; 418 int i;
378 419
379 for (i = 0; i < dev->queues; i++) 420 for (i = 0; i < dev->queues; i++)
380 if (priv->tx_stats[i].len < priv->tx_stats[i].limit) 421 if (priv->tx_stats[i + 4].len < priv->tx_stats[i + 4].limit)
381 ieee80211_wake_queue(dev, i); 422 ieee80211_wake_queue(dev, i);
382} 423}
383 424
@@ -391,7 +432,9 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
391 struct memrecord *range = NULL; 432 struct memrecord *range = NULL;
392 u32 freed = 0; 433 u32 freed = 0;
393 u32 last_addr = priv->rx_start; 434 u32 last_addr = priv->rx_start;
435 unsigned long flags;
394 436
437 spin_lock_irqsave(&priv->tx_queue.lock, flags);
395 while (entry != (struct sk_buff *)&priv->tx_queue) { 438 while (entry != (struct sk_buff *)&priv->tx_queue) {
396 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); 439 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
397 range = (void *)info->driver_data; 440 range = (void *)info->driver_data;
@@ -412,13 +455,15 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
412 455
413 last_addr = range->end_addr; 456 last_addr = range->end_addr;
414 __skb_unlink(entry, &priv->tx_queue); 457 __skb_unlink(entry, &priv->tx_queue);
458 spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
459
415 memset(&info->status, 0, sizeof(info->status)); 460 memset(&info->status, 0, sizeof(info->status));
416 entry_hdr = (struct p54_control_hdr *) entry->data; 461 entry_hdr = (struct p54_control_hdr *) entry->data;
417 entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; 462 entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
418 if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) 463 if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
419 pad = entry_data->align[0]; 464 pad = entry_data->align[0];
420 465
421 priv->tx_stats[entry_data->hw_queue - 4].len--; 466 priv->tx_stats[entry_data->hw_queue].len--;
422 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { 467 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
423 if (!(payload->status & 0x01)) 468 if (!(payload->status & 0x01))
424 info->flags |= IEEE80211_TX_STAT_ACK; 469 info->flags |= IEEE80211_TX_STAT_ACK;
@@ -429,12 +474,14 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
429 info->status.ack_signal = le16_to_cpu(payload->ack_rssi); 474 info->status.ack_signal = le16_to_cpu(payload->ack_rssi);
430 skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); 475 skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
431 ieee80211_tx_status_irqsafe(dev, entry); 476 ieee80211_tx_status_irqsafe(dev, entry);
432 break; 477 goto out;
433 } else 478 } else
434 last_addr = range->end_addr; 479 last_addr = range->end_addr;
435 entry = entry->next; 480 entry = entry->next;
436 } 481 }
482 spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
437 483
484out:
438 if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 + 485 if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
439 sizeof(struct p54_control_hdr)) 486 sizeof(struct p54_control_hdr))
440 p54_wake_free_queues(dev); 487 p54_wake_free_queues(dev);
@@ -559,7 +606,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
559 u8 rate; 606 u8 rate;
560 u8 cts_rate = 0x20; 607 u8 cts_rate = 0x20;
561 608
562 current_queue = &priv->tx_stats[skb_get_queue_mapping(skb)]; 609 current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4];
563 if (unlikely(current_queue->len > current_queue->limit)) 610 if (unlikely(current_queue->len > current_queue->limit))
564 return NETDEV_TX_BUSY; 611 return NETDEV_TX_BUSY;
565 current_queue->len++; 612 current_queue->len++;
@@ -672,12 +719,9 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
672 struct p54_control_hdr *hdr; 719 struct p54_control_hdr *hdr;
673 struct p54_tx_control_channel *chan; 720 struct p54_tx_control_channel *chan;
674 unsigned int i; 721 unsigned int i;
675 size_t payload_len = sizeof(*chan) + sizeof(u32)*2 +
676 sizeof(*chan->curve_data) *
677 priv->curve_data->points_per_channel;
678 void *entry; 722 void *entry;
679 723
680 hdr = kzalloc(sizeof(*hdr) + payload_len + 724 hdr = kzalloc(sizeof(*hdr) + sizeof(*chan) +
681 priv->tx_hdr_len, GFP_KERNEL); 725 priv->tx_hdr_len, GFP_KERNEL);
682 if (!hdr) 726 if (!hdr)
683 return -ENOMEM; 727 return -ENOMEM;
@@ -689,10 +733,10 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
689 hdr->magic1 = cpu_to_le16(0x8001); 733 hdr->magic1 = cpu_to_le16(0x8001);
690 hdr->len = cpu_to_le16(sizeof(*chan)); 734 hdr->len = cpu_to_le16(sizeof(*chan));
691 hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE); 735 hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
692 p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len); 736 p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*chan));
693 737
694 chan->magic1 = cpu_to_le16(0x1); 738 chan->flags = cpu_to_le16(0x1);
695 chan->magic2 = cpu_to_le16(0x0); 739 chan->dwell = cpu_to_le16(0x0);
696 740
697 for (i = 0; i < priv->iq_autocal_len; i++) { 741 for (i = 0; i < priv->iq_autocal_len; i++) {
698 if (priv->iq_autocal[i].freq != freq) 742 if (priv->iq_autocal[i].freq != freq)
@@ -710,35 +754,41 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
710 continue; 754 continue;
711 755
712 chan->val_barker = 0x38; 756 chan->val_barker = 0x38;
713 chan->val_bpsk = priv->output_limit[i].val_bpsk; 757 chan->val_bpsk = chan->dup_bpsk =
714 chan->val_qpsk = priv->output_limit[i].val_qpsk; 758 priv->output_limit[i].val_bpsk;
715 chan->val_16qam = priv->output_limit[i].val_16qam; 759 chan->val_qpsk = chan->dup_qpsk =
716 chan->val_64qam = priv->output_limit[i].val_64qam; 760 priv->output_limit[i].val_qpsk;
761 chan->val_16qam = chan->dup_16qam =
762 priv->output_limit[i].val_16qam;
763 chan->val_64qam = chan->dup_64qam =
764 priv->output_limit[i].val_64qam;
717 break; 765 break;
718 } 766 }
719 if (i == priv->output_limit_len) 767 if (i == priv->output_limit_len)
720 goto err; 768 goto err;
721 769
722 chan->pa_points_per_curve = priv->curve_data->points_per_channel;
723
724 entry = priv->curve_data->data; 770 entry = priv->curve_data->data;
725 for (i = 0; i < priv->curve_data->channels; i++) { 771 for (i = 0; i < priv->curve_data->channels; i++) {
726 if (*((__le16 *)entry) != freq) { 772 if (*((__le16 *)entry) != freq) {
727 entry += sizeof(__le16); 773 entry += sizeof(__le16);
728 entry += sizeof(struct pda_pa_curve_data_sample_rev1) * 774 entry += sizeof(struct p54_pa_curve_data_sample) *
729 chan->pa_points_per_curve; 775 priv->curve_data->points_per_channel;
730 continue; 776 continue;
731 } 777 }
732 778
733 entry += sizeof(__le16); 779 entry += sizeof(__le16);
780 chan->pa_points_per_curve =
781 min(priv->curve_data->points_per_channel, (u8) 8);
782
734 memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) * 783 memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
735 chan->pa_points_per_curve); 784 chan->pa_points_per_curve);
736 break; 785 break;
737 } 786 }
738 787
739 memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4); 788 chan->rssical_mul = cpu_to_le16(130);
789 chan->rssical_add = cpu_to_le16(0xfe70); /* -400 */
740 790
741 priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1); 791 priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*chan), 1);
742 return 0; 792 return 0;
743 793
744 err: 794 err:
@@ -987,7 +1037,7 @@ static int p54_get_tx_stats(struct ieee80211_hw *dev,
987{ 1037{
988 struct p54_common *priv = dev->priv; 1038 struct p54_common *priv = dev->priv;
989 1039
990 memcpy(stats, &priv->tx_stats, sizeof(stats[0]) * dev->queues); 1040 memcpy(stats, &priv->tx_stats[4], sizeof(stats[0]) * dev->queues);
991 1041
992 return 0; 1042 return 0;
993} 1043}
@@ -1025,7 +1075,11 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
1025 dev->channel_change_time = 1000; /* TODO: find actual value */ 1075 dev->channel_change_time = 1000; /* TODO: find actual value */
1026 dev->max_signal = 127; 1076 dev->max_signal = 127;
1027 1077
1028 priv->tx_stats[0].limit = 5; 1078 priv->tx_stats[0].limit = 1;
1079 priv->tx_stats[1].limit = 1;
1080 priv->tx_stats[2].limit = 1;
1081 priv->tx_stats[3].limit = 1;
1082 priv->tx_stats[4].limit = 5;
1029 dev->queues = 1; 1083 dev->queues = 1;
1030 1084
1031 dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 + 1085 dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h
index 9bc2a1cf4b57..a79c1a146917 100644
--- a/drivers/net/wireless/p54/p54common.h
+++ b/drivers/net/wireless/p54/p54common.h
@@ -89,6 +89,16 @@ struct pda_pa_curve_data_sample_rev1 {
89 u8 data_qpsk; 89 u8 data_qpsk;
90 u8 data_16qam; 90 u8 data_16qam;
91 u8 data_64qam; 91 u8 data_64qam;
92} __attribute__ ((packed));
93
94struct p54_pa_curve_data_sample {
95 u8 rf_power;
96 u8 pa_detector;
97 u8 data_barker;
98 u8 data_bpsk;
99 u8 data_qpsk;
100 u8 data_16qam;
101 u8 data_64qam;
92 u8 padding; 102 u8 padding;
93} __attribute__ ((packed)); 103} __attribute__ ((packed));
94 104
@@ -212,8 +222,8 @@ struct p54_tx_control_filter {
212} __attribute__ ((packed)); 222} __attribute__ ((packed));
213 223
214struct p54_tx_control_channel { 224struct p54_tx_control_channel {
215 __le16 magic1; 225 __le16 flags;
216 __le16 magic2; 226 __le16 dwell;
217 u8 padding1[20]; 227 u8 padding1[20];
218 struct pda_iq_autocal_entry iq_autocal; 228 struct pda_iq_autocal_entry iq_autocal;
219 u8 pa_points_per_curve; 229 u8 pa_points_per_curve;
@@ -222,8 +232,13 @@ struct p54_tx_control_channel {
222 u8 val_qpsk; 232 u8 val_qpsk;
223 u8 val_16qam; 233 u8 val_16qam;
224 u8 val_64qam; 234 u8 val_64qam;
225 struct pda_pa_curve_data_sample_rev1 curve_data[0]; 235 struct pda_pa_curve_data_sample_rev1 curve_data[8];
226 /* additional padding/data after curve_data */ 236 u8 dup_bpsk;
237 u8 dup_qpsk;
238 u8 dup_16qam;
239 u8 dup_64qam;
240 __le16 rssical_mul;
241 __le16 rssical_add;
227} __attribute__ ((packed)); 242} __attribute__ ((packed));
228 243
229struct p54_tx_control_led { 244struct p54_tx_control_led {
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index ea2dc3d93c4d..e9db4495c626 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -3,6 +3,7 @@
3 * Linux device driver for PCI based Prism54 3 * Linux device driver for PCI based Prism54
4 * 4 *
5 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> 5 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
6 * Copyright (c) 2008, Christian Lamparter <chunkeey@web.de>
6 * 7 *
7 * Based on the islsm (softmac prism54) driver, which is: 8 * Based on the islsm (softmac prism54) driver, which is:
8 * Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note@m4x.org>, et al. 9 * Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note@m4x.org>, et al.
@@ -237,20 +238,22 @@ static int p54p_read_eeprom(struct ieee80211_hw *dev)
237 return err; 238 return err;
238} 239}
239 240
240static void p54p_refill_rx_ring(struct ieee80211_hw *dev) 241static void p54p_refill_rx_ring(struct ieee80211_hw *dev,
242 int ring_index, struct p54p_desc *ring, u32 ring_limit,
243 struct sk_buff **rx_buf)
241{ 244{
242 struct p54p_priv *priv = dev->priv; 245 struct p54p_priv *priv = dev->priv;
243 struct p54p_ring_control *ring_control = priv->ring_control; 246 struct p54p_ring_control *ring_control = priv->ring_control;
244 u32 limit, host_idx, idx; 247 u32 limit, idx, i;
245 248
246 host_idx = le32_to_cpu(ring_control->host_idx[0]); 249 idx = le32_to_cpu(ring_control->host_idx[ring_index]);
247 limit = host_idx; 250 limit = idx;
248 limit -= le32_to_cpu(ring_control->device_idx[0]); 251 limit -= le32_to_cpu(ring_control->device_idx[ring_index]);
249 limit = ARRAY_SIZE(ring_control->rx_data) - limit; 252 limit = ring_limit - limit;
250 253
251 idx = host_idx % ARRAY_SIZE(ring_control->rx_data); 254 i = idx % ring_limit;
252 while (limit-- > 1) { 255 while (limit-- > 1) {
253 struct p54p_desc *desc = &ring_control->rx_data[idx]; 256 struct p54p_desc *desc = &ring[i];
254 257
255 if (!desc->host_addr) { 258 if (!desc->host_addr) {
256 struct sk_buff *skb; 259 struct sk_buff *skb;
@@ -267,16 +270,106 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
267 desc->device_addr = 0; // FIXME: necessary? 270 desc->device_addr = 0; // FIXME: necessary?
268 desc->len = cpu_to_le16(MAX_RX_SIZE); 271 desc->len = cpu_to_le16(MAX_RX_SIZE);
269 desc->flags = 0; 272 desc->flags = 0;
270 priv->rx_buf[idx] = skb; 273 rx_buf[i] = skb;
271 } 274 }
272 275
276 i++;
273 idx++; 277 idx++;
274 host_idx++; 278 i %= ring_limit;
275 idx %= ARRAY_SIZE(ring_control->rx_data);
276 } 279 }
277 280
278 wmb(); 281 wmb();
279 ring_control->host_idx[0] = cpu_to_le32(host_idx); 282 ring_control->host_idx[ring_index] = cpu_to_le32(idx);
283}
284
285static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
286 int ring_index, struct p54p_desc *ring, u32 ring_limit,
287 struct sk_buff **rx_buf)
288{
289 struct p54p_priv *priv = dev->priv;
290 struct p54p_ring_control *ring_control = priv->ring_control;
291 struct p54p_desc *desc;
292 u32 idx, i;
293
294 i = (*index) % ring_limit;
295 (*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]);
296 idx %= ring_limit;
297 while (i != idx) {
298 u16 len;
299 struct sk_buff *skb;
300 desc = &ring[i];
301 len = le16_to_cpu(desc->len);
302 skb = rx_buf[i];
303
304 if (!skb)
305 continue;
306
307 skb_put(skb, len);
308
309 if (p54_rx(dev, skb)) {
310 pci_unmap_single(priv->pdev,
311 le32_to_cpu(desc->host_addr),
312 MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
313 rx_buf[i] = NULL;
314 desc->host_addr = 0;
315 } else {
316 skb_trim(skb, 0);
317 desc->len = cpu_to_le16(MAX_RX_SIZE);
318 }
319
320 i++;
321 i %= ring_limit;
322 }
323
324 p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf);
325}
326
327/* caller must hold priv->lock */
328static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
329 int ring_index, struct p54p_desc *ring, u32 ring_limit,
330 void **tx_buf)
331{
332 struct p54p_priv *priv = dev->priv;
333 struct p54p_ring_control *ring_control = priv->ring_control;
334 struct p54p_desc *desc;
335 u32 idx, i;
336
337 i = (*index) % ring_limit;
338 (*index) = idx = le32_to_cpu(ring_control->device_idx[1]);
339 idx %= ring_limit;
340
341 while (i != idx) {
342 desc = &ring[i];
343 kfree(tx_buf[i]);
344 tx_buf[i] = NULL;
345
346 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
347 le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
348
349 desc->host_addr = 0;
350 desc->device_addr = 0;
351 desc->len = 0;
352 desc->flags = 0;
353
354 i++;
355 i %= ring_limit;
356 }
357}
358
359static void p54p_rx_tasklet(unsigned long dev_id)
360{
361 struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id;
362 struct p54p_priv *priv = dev->priv;
363 struct p54p_ring_control *ring_control = priv->ring_control;
364
365 p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,
366 ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt);
367
368 p54p_check_rx_ring(dev, &priv->rx_idx_data, 0, ring_control->rx_data,
369 ARRAY_SIZE(ring_control->rx_data), priv->rx_buf_data);
370
371 wmb();
372 P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
280} 373}
281 374
282static irqreturn_t p54p_interrupt(int irq, void *dev_id) 375static irqreturn_t p54p_interrupt(int irq, void *dev_id)
@@ -298,65 +391,18 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
298 reg &= P54P_READ(int_enable); 391 reg &= P54P_READ(int_enable);
299 392
300 if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) { 393 if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) {
301 struct p54p_desc *desc; 394 p54p_check_tx_ring(dev, &priv->tx_idx_mgmt,
302 u32 idx, i; 395 3, ring_control->tx_mgmt,
303 i = priv->tx_idx; 396 ARRAY_SIZE(ring_control->tx_mgmt),
304 i %= ARRAY_SIZE(ring_control->tx_data); 397 priv->tx_buf_mgmt);
305 priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]);
306 idx %= ARRAY_SIZE(ring_control->tx_data);
307
308 while (i != idx) {
309 desc = &ring_control->tx_data[i];
310 if (priv->tx_buf[i]) {
311 kfree(priv->tx_buf[i]);
312 priv->tx_buf[i] = NULL;
313 }
314
315 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
316 le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
317 398
318 desc->host_addr = 0; 399 p54p_check_tx_ring(dev, &priv->tx_idx_data,
319 desc->device_addr = 0; 400 1, ring_control->tx_data,
320 desc->len = 0; 401 ARRAY_SIZE(ring_control->tx_data),
321 desc->flags = 0; 402 priv->tx_buf_data);
322 403
323 i++; 404 tasklet_schedule(&priv->rx_tasklet);
324 i %= ARRAY_SIZE(ring_control->tx_data);
325 }
326
327 i = priv->rx_idx;
328 i %= ARRAY_SIZE(ring_control->rx_data);
329 priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]);
330 idx %= ARRAY_SIZE(ring_control->rx_data);
331 while (i != idx) {
332 u16 len;
333 struct sk_buff *skb;
334 desc = &ring_control->rx_data[i];
335 len = le16_to_cpu(desc->len);
336 skb = priv->rx_buf[i];
337
338 skb_put(skb, len);
339
340 if (p54_rx(dev, skb)) {
341 pci_unmap_single(priv->pdev,
342 le32_to_cpu(desc->host_addr),
343 MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
344
345 priv->rx_buf[i] = NULL;
346 desc->host_addr = 0;
347 } else {
348 skb_trim(skb, 0);
349 desc->len = cpu_to_le16(MAX_RX_SIZE);
350 }
351
352 i++;
353 i %= ARRAY_SIZE(ring_control->rx_data);
354 }
355 405
356 p54p_refill_rx_ring(dev);
357
358 wmb();
359 P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
360 } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)) 406 } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
361 complete(&priv->boot_comp); 407 complete(&priv->boot_comp);
362 408
@@ -392,7 +438,7 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
392 ring_control->host_idx[1] = cpu_to_le32(idx + 1); 438 ring_control->host_idx[1] = cpu_to_le32(idx + 1);
393 439
394 if (free_on_tx) 440 if (free_on_tx)
395 priv->tx_buf[i] = data; 441 priv->tx_buf_data[i] = data;
396 442
397 spin_unlock_irqrestore(&priv->lock, flags); 443 spin_unlock_irqrestore(&priv->lock, flags);
398 444
@@ -420,8 +466,14 @@ static int p54p_open(struct ieee80211_hw *dev)
420 } 466 }
421 467
422 memset(priv->ring_control, 0, sizeof(*priv->ring_control)); 468 memset(priv->ring_control, 0, sizeof(*priv->ring_control));
423 priv->rx_idx = priv->tx_idx = 0; 469 priv->rx_idx_data = priv->tx_idx_data = 0;
424 p54p_refill_rx_ring(dev); 470 priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0;
471
472 p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data,
473 ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data);
474
475 p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt,
476 ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt);
425 477
426 p54p_upload_firmware(dev); 478 p54p_upload_firmware(dev);
427 479
@@ -465,6 +517,8 @@ static void p54p_stop(struct ieee80211_hw *dev)
465 unsigned int i; 517 unsigned int i;
466 struct p54p_desc *desc; 518 struct p54p_desc *desc;
467 519
520 tasklet_kill(&priv->rx_tasklet);
521
468 P54P_WRITE(int_enable, cpu_to_le32(0)); 522 P54P_WRITE(int_enable, cpu_to_le32(0));
469 P54P_READ(int_enable); 523 P54P_READ(int_enable);
470 udelay(10); 524 udelay(10);
@@ -473,26 +527,51 @@ static void p54p_stop(struct ieee80211_hw *dev)
473 527
474 P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); 528 P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
475 529
476 for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) { 530 for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) {
477 desc = &ring_control->rx_data[i]; 531 desc = &ring_control->rx_data[i];
478 if (desc->host_addr) 532 if (desc->host_addr)
479 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), 533 pci_unmap_single(priv->pdev,
534 le32_to_cpu(desc->host_addr),
480 MAX_RX_SIZE, PCI_DMA_FROMDEVICE); 535 MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
481 kfree_skb(priv->rx_buf[i]); 536 kfree_skb(priv->rx_buf_data[i]);
482 priv->rx_buf[i] = NULL; 537 priv->rx_buf_data[i] = NULL;
483 } 538 }
484 539
485 for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) { 540 for (i = 0; i < ARRAY_SIZE(priv->rx_buf_mgmt); i++) {
541 desc = &ring_control->rx_mgmt[i];
542 if (desc->host_addr)
543 pci_unmap_single(priv->pdev,
544 le32_to_cpu(desc->host_addr),
545 MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
546 kfree_skb(priv->rx_buf_mgmt[i]);
547 priv->rx_buf_mgmt[i] = NULL;
548 }
549
550 for (i = 0; i < ARRAY_SIZE(priv->tx_buf_data); i++) {
486 desc = &ring_control->tx_data[i]; 551 desc = &ring_control->tx_data[i];
487 if (desc->host_addr) 552 if (desc->host_addr)
488 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), 553 pci_unmap_single(priv->pdev,
489 le16_to_cpu(desc->len), PCI_DMA_TODEVICE); 554 le32_to_cpu(desc->host_addr),
555 le16_to_cpu(desc->len),
556 PCI_DMA_TODEVICE);
557
558 kfree(priv->tx_buf_data[i]);
559 priv->tx_buf_data[i] = NULL;
560 }
561
562 for (i = 0; i < ARRAY_SIZE(priv->tx_buf_mgmt); i++) {
563 desc = &ring_control->tx_mgmt[i];
564 if (desc->host_addr)
565 pci_unmap_single(priv->pdev,
566 le32_to_cpu(desc->host_addr),
567 le16_to_cpu(desc->len),
568 PCI_DMA_TODEVICE);
490 569
491 kfree(priv->tx_buf[i]); 570 kfree(priv->tx_buf_mgmt[i]);
492 priv->tx_buf[i] = NULL; 571 priv->tx_buf_mgmt[i] = NULL;
493 } 572 }
494 573
495 memset(ring_control, 0, sizeof(ring_control)); 574 memset(ring_control, 0, sizeof(*ring_control));
496} 575}
497 576
498static int __devinit p54p_probe(struct pci_dev *pdev, 577static int __devinit p54p_probe(struct pci_dev *pdev,
@@ -585,6 +664,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
585 priv->common.tx = p54p_tx; 664 priv->common.tx = p54p_tx;
586 665
587 spin_lock_init(&priv->lock); 666 spin_lock_init(&priv->lock);
667 tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev);
588 668
589 err = ieee80211_register_hw(dev); 669 err = ieee80211_register_hw(dev);
590 if (err) { 670 if (err) {
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h
index 07678ef5ddc8..4a6778070afc 100644
--- a/drivers/net/wireless/p54/p54pci.h
+++ b/drivers/net/wireless/p54/p54pci.h
@@ -92,13 +92,17 @@ 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 96
96 spinlock_t lock; 97 spinlock_t lock;
97 struct p54p_ring_control *ring_control; 98 struct p54p_ring_control *ring_control;
98 dma_addr_t ring_control_dma; 99 dma_addr_t ring_control_dma;
99 u32 rx_idx, tx_idx; 100 u32 rx_idx_data, tx_idx_data;
100 struct sk_buff *rx_buf[8]; 101 u32 rx_idx_mgmt, tx_idx_mgmt;
101 void *tx_buf[32]; 102 struct sk_buff *rx_buf_data[8];
103 struct sk_buff *rx_buf_mgmt[4];
104 void *tx_buf_data[32];
105 void *tx_buf_mgmt[4];
102 struct completion boot_comp; 106 struct completion boot_comp;
103}; 107};
104 108