diff options
Diffstat (limited to 'drivers/net/wireless/p54')
-rw-r--r-- | drivers/net/wireless/p54/p54.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 170 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54common.h | 23 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54pci.c | 242 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54pci.h | 10 |
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 | ||
72 | int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); | 72 | int 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 | } |
156 | EXPORT_SYMBOL_GPL(p54_parse_firmware); | 156 | EXPORT_SYMBOL_GPL(p54_parse_firmware); |
157 | 157 | ||
158 | static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev, | 158 | static 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 | ||
204 | static 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 | |||
204 | int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | 240 | int 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 | ||
484 | out: | ||
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 | |||
94 | struct 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 | ||
214 | struct p54_tx_control_channel { | 224 | struct 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 | ||
229 | struct p54_tx_control_led { | 244 | struct 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 | ||
240 | static void p54p_refill_rx_ring(struct ieee80211_hw *dev) | 241 | static 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 | |||
285 | static 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 */ | ||
328 | static 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 | |||
359 | static 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 | ||
282 | static irqreturn_t p54p_interrupt(int irq, void *dev_id) | 375 | static 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 | ||
498 | static int __devinit p54p_probe(struct pci_dev *pdev, | 577 | static 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 | ||