diff options
author | Christian Lamparter <chunkeey@web.de> | 2008-09-03 16:25:25 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-09-08 14:00:18 -0400 |
commit | 19c19d54b6bfa57746f3ec805d1d7951eefa353b (patch) | |
tree | 1a48522cd59e6ef492d99ebe212beb819c2526a8 /drivers/net/wireless/p54/p54common.c | |
parent | e0a58eacf540c65763288c81caa74013f62d7234 (diff) |
p54: better firmware support
This patch hopefully contains all necessary changes to support
firmwares for all devices up to atleast 2.13.3.0.
(or: LowerMAC Protocol Rev: 5.5 )
And this is a big win, since:
* newer firmwares are more stable and reliable than the old ones.
* no problems anymore with packages > 1399 octets (without lowering the MTU).
* monitor mode finally works on USB for more than just a few seconds.
Signed-off-by: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54/p54common.c')
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 85 |
1 files changed, 50 insertions, 35 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index f742abab7594..f96f7c7e6af5 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -424,11 +424,12 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
424 | } | 424 | } |
425 | EXPORT_SYMBOL_GPL(p54_parse_eeprom); | 425 | EXPORT_SYMBOL_GPL(p54_parse_eeprom); |
426 | 426 | ||
427 | static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) | 427 | static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) |
428 | { | 428 | { |
429 | struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data; | 429 | struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data; |
430 | struct ieee80211_rx_status rx_status = {0}; | 430 | struct ieee80211_rx_status rx_status = {0}; |
431 | u16 freq = le16_to_cpu(hdr->freq); | 431 | u16 freq = le16_to_cpu(hdr->freq); |
432 | size_t header_len = sizeof(*hdr); | ||
432 | 433 | ||
433 | rx_status.signal = hdr->rssi; | 434 | rx_status.signal = hdr->rssi; |
434 | /* XX correct? */ | 435 | /* XX correct? */ |
@@ -440,10 +441,15 @@ static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
440 | rx_status.mactime = le64_to_cpu(hdr->timestamp); | 441 | rx_status.mactime = le64_to_cpu(hdr->timestamp); |
441 | rx_status.flag |= RX_FLAG_TSFT; | 442 | rx_status.flag |= RX_FLAG_TSFT; |
442 | 443 | ||
443 | skb_pull(skb, sizeof(*hdr)); | 444 | if (hdr->magic & cpu_to_le16(0x4000)) |
445 | header_len += hdr->align[0]; | ||
446 | |||
447 | skb_pull(skb, header_len); | ||
444 | skb_trim(skb, le16_to_cpu(hdr->len)); | 448 | skb_trim(skb, le16_to_cpu(hdr->len)); |
445 | 449 | ||
446 | ieee80211_rx_irqsafe(dev, skb, &rx_status); | 450 | ieee80211_rx_irqsafe(dev, skb, &rx_status); |
451 | |||
452 | return -1; | ||
447 | } | 453 | } |
448 | 454 | ||
449 | static void inline p54_wake_free_queues(struct ieee80211_hw *dev) | 455 | static void inline p54_wake_free_queues(struct ieee80211_hw *dev) |
@@ -536,7 +542,7 @@ static void p54_rx_eeprom_readback(struct ieee80211_hw *dev, | |||
536 | complete(&priv->eeprom_comp); | 542 | complete(&priv->eeprom_comp); |
537 | } | 543 | } |
538 | 544 | ||
539 | static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb) | 545 | static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb) |
540 | { | 546 | { |
541 | struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data; | 547 | struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data; |
542 | 548 | ||
@@ -554,31 +560,19 @@ static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
554 | wiphy_name(dev->wiphy), le16_to_cpu(hdr->type)); | 560 | wiphy_name(dev->wiphy), le16_to_cpu(hdr->type)); |
555 | break; | 561 | break; |
556 | } | 562 | } |
563 | |||
564 | return 0; | ||
557 | } | 565 | } |
558 | 566 | ||
559 | /* returns zero if skb can be reused */ | 567 | /* returns zero if skb can be reused */ |
560 | int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb) | 568 | int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb) |
561 | { | 569 | { |
562 | u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8; | 570 | u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8; |
563 | switch (type) { | 571 | |
564 | case 0x00: | 572 | if (type == 0x80) |
565 | case 0x01: | 573 | return p54_rx_control(dev, skb); |
566 | p54_rx_data(dev, skb); | 574 | else |
567 | return -1; | 575 | return p54_rx_data(dev, skb); |
568 | case 0x4d: | ||
569 | /* TODO: do something better... but then again, I've never seen this happen */ | ||
570 | printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n", | ||
571 | wiphy_name(dev->wiphy)); | ||
572 | break; | ||
573 | case 0x80: | ||
574 | p54_rx_control(dev, skb); | ||
575 | break; | ||
576 | default: | ||
577 | printk(KERN_ERR "%s: unknown frame RXed (0x%02x)\n", | ||
578 | wiphy_name(dev->wiphy), type); | ||
579 | break; | ||
580 | } | ||
581 | return 0; | ||
582 | } | 576 | } |
583 | EXPORT_SYMBOL_GPL(p54_rx); | 577 | EXPORT_SYMBOL_GPL(p54_rx); |
584 | 578 | ||
@@ -791,6 +785,7 @@ static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type, | |||
791 | struct p54_common *priv = dev->priv; | 785 | struct p54_common *priv = dev->priv; |
792 | struct p54_control_hdr *hdr; | 786 | struct p54_control_hdr *hdr; |
793 | struct p54_tx_control_filter *filter; | 787 | struct p54_tx_control_filter *filter; |
788 | size_t data_len; | ||
794 | 789 | ||
795 | hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) + | 790 | hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) + |
796 | priv->tx_hdr_len, GFP_ATOMIC); | 791 | priv->tx_hdr_len, GFP_ATOMIC); |
@@ -801,8 +796,6 @@ static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type, | |||
801 | 796 | ||
802 | filter = (struct p54_tx_control_filter *) hdr->data; | 797 | filter = (struct p54_tx_control_filter *) hdr->data; |
803 | hdr->magic1 = cpu_to_le16(0x8001); | 798 | hdr->magic1 = cpu_to_le16(0x8001); |
804 | hdr->len = cpu_to_le16(sizeof(*filter)); | ||
805 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter)); | ||
806 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET); | 799 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET); |
807 | 800 | ||
808 | priv->filter_type = filter->filter_type = cpu_to_le16(filter_type); | 801 | priv->filter_type = filter->filter_type = cpu_to_le16(filter_type); |
@@ -813,13 +806,25 @@ static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type, | |||
813 | memcpy(filter->bssid, bssid, ETH_ALEN); | 806 | memcpy(filter->bssid, bssid, ETH_ALEN); |
814 | 807 | ||
815 | filter->rx_antenna = priv->rx_antenna; | 808 | filter->rx_antenna = priv->rx_antenna; |
816 | filter->basic_rate_mask = cpu_to_le32(0x15F); | ||
817 | filter->rx_addr = cpu_to_le32(priv->rx_end); | ||
818 | filter->max_rx = cpu_to_le16(priv->rx_mtu); | ||
819 | filter->rxhw = cpu_to_le16(priv->rxhw); | ||
820 | filter->wakeup_timer = cpu_to_le16(500); | ||
821 | 809 | ||
822 | priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*filter), 1); | 810 | if (priv->fw_var < 0x500) { |
811 | data_len = P54_TX_CONTROL_FILTER_V1_LEN; | ||
812 | filter->v1.basic_rate_mask = cpu_to_le32(0x15F); | ||
813 | filter->v1.rx_addr = cpu_to_le32(priv->rx_end); | ||
814 | filter->v1.max_rx = cpu_to_le16(priv->rx_mtu); | ||
815 | filter->v1.rxhw = cpu_to_le16(priv->rxhw); | ||
816 | filter->v1.wakeup_timer = cpu_to_le16(500); | ||
817 | } else { | ||
818 | data_len = P54_TX_CONTROL_FILTER_V2_LEN; | ||
819 | filter->v2.rx_addr = cpu_to_le32(priv->rx_end); | ||
820 | filter->v2.max_rx = cpu_to_le16(priv->rx_mtu); | ||
821 | filter->v2.rxhw = cpu_to_le16(priv->rxhw); | ||
822 | filter->v2.timer = cpu_to_le16(1000); | ||
823 | } | ||
824 | |||
825 | hdr->len = cpu_to_le16(data_len); | ||
826 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + data_len); | ||
827 | priv->tx(dev, hdr, sizeof(*hdr) + data_len, 1); | ||
823 | return 0; | 828 | return 0; |
824 | } | 829 | } |
825 | 830 | ||
@@ -829,6 +834,7 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) | |||
829 | struct p54_control_hdr *hdr; | 834 | struct p54_control_hdr *hdr; |
830 | struct p54_tx_control_channel *chan; | 835 | struct p54_tx_control_channel *chan; |
831 | unsigned int i; | 836 | unsigned int i; |
837 | size_t data_len; | ||
832 | void *entry; | 838 | void *entry; |
833 | 839 | ||
834 | hdr = kzalloc(sizeof(*hdr) + sizeof(*chan) + | 840 | hdr = kzalloc(sizeof(*hdr) + sizeof(*chan) + |
@@ -841,9 +847,8 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) | |||
841 | chan = (struct p54_tx_control_channel *) hdr->data; | 847 | chan = (struct p54_tx_control_channel *) hdr->data; |
842 | 848 | ||
843 | hdr->magic1 = cpu_to_le16(0x8001); | 849 | hdr->magic1 = cpu_to_le16(0x8001); |
844 | hdr->len = cpu_to_le16(sizeof(*chan)); | 850 | |
845 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE); | 851 | hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE); |
846 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*chan)); | ||
847 | 852 | ||
848 | chan->flags = cpu_to_le16(0x1); | 853 | chan->flags = cpu_to_le16(0x1); |
849 | chan->dwell = cpu_to_le16(0x0); | 854 | chan->dwell = cpu_to_le16(0x0); |
@@ -895,10 +900,20 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) | |||
895 | break; | 900 | break; |
896 | } | 901 | } |
897 | 902 | ||
898 | chan->rssical_mul = cpu_to_le16(130); | 903 | if (priv->fw_var < 0x500) { |
899 | chan->rssical_add = cpu_to_le16(0xfe70); /* -400 */ | 904 | data_len = P54_TX_CONTROL_CHANNEL_V1_LEN; |
905 | chan->v1.rssical_mul = cpu_to_le16(130); | ||
906 | chan->v1.rssical_add = cpu_to_le16(0xfe70); | ||
907 | } else { | ||
908 | data_len = P54_TX_CONTROL_CHANNEL_V2_LEN; | ||
909 | chan->v2.rssical_mul = cpu_to_le16(130); | ||
910 | chan->v2.rssical_add = cpu_to_le16(0xfe70); | ||
911 | chan->v2.basic_rate_mask = cpu_to_le32(0x15f); | ||
912 | } | ||
900 | 913 | ||
901 | priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*chan), 1); | 914 | hdr->len = cpu_to_le16(data_len); |
915 | p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + data_len); | ||
916 | priv->tx(dev, hdr, sizeof(*hdr) + data_len, 1); | ||
902 | return 0; | 917 | return 0; |
903 | 918 | ||
904 | err: | 919 | err: |