diff options
author | David Kilroy <kilroyd@gmail.com> | 2008-08-21 18:27:56 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-08-22 19:28:05 -0400 |
commit | 6eecad77861b193bcfc109de12835ca0bddf7c58 (patch) | |
tree | cacb4f7513571c6992adebb00c21bc8e5a14e663 /drivers | |
parent | 3994d502017a2239e30152d1231843ad05d04a7b (diff) |
orinoco: Fix transmit for Agere/Lucent with fw 9.x
The tx control word has moved into the 802.11 header area on these
firmwares.
Signed-off-by: David Kilroy <kilroyd@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/hermes.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco.c | 59 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco.h | 1 |
3 files changed, 46 insertions, 15 deletions
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h index 287f5363fda2..1d0c5840f825 100644 --- a/drivers/net/wireless/hermes.h +++ b/drivers/net/wireless/hermes.h | |||
@@ -179,6 +179,7 @@ | |||
179 | #define HERMES_802_11_OFFSET (14) | 179 | #define HERMES_802_11_OFFSET (14) |
180 | #define HERMES_802_3_OFFSET (14+32) | 180 | #define HERMES_802_3_OFFSET (14+32) |
181 | #define HERMES_802_2_OFFSET (14+32+14) | 181 | #define HERMES_802_2_OFFSET (14+32+14) |
182 | #define HERMES_TXCNTL2_OFFSET (HERMES_802_3_OFFSET - 2) | ||
182 | 183 | ||
183 | #define HERMES_RXSTAT_ERR (0x0003) | 184 | #define HERMES_RXSTAT_ERR (0x0003) |
184 | #define HERMES_RXSTAT_BADCRC (0x0001) | 185 | #define HERMES_RXSTAT_BADCRC (0x0001) |
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 306697aa3330..b83415daa723 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
@@ -722,7 +722,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) | |||
722 | u16 txfid = priv->txfid; | 722 | u16 txfid = priv->txfid; |
723 | struct ethhdr *eh; | 723 | struct ethhdr *eh; |
724 | int data_off; | 724 | int data_off; |
725 | struct hermes_tx_descriptor desc; | 725 | int tx_control; |
726 | unsigned long flags; | 726 | unsigned long flags; |
727 | 727 | ||
728 | if (! netif_running(dev)) { | 728 | if (! netif_running(dev)) { |
@@ -756,21 +756,48 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) | |||
756 | 756 | ||
757 | eh = (struct ethhdr *)skb->data; | 757 | eh = (struct ethhdr *)skb->data; |
758 | 758 | ||
759 | memset(&desc, 0, sizeof(desc)); | 759 | tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX; |
760 | desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX); | ||
761 | err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0); | ||
762 | if (err) { | ||
763 | if (net_ratelimit()) | ||
764 | printk(KERN_ERR "%s: Error %d writing Tx descriptor " | ||
765 | "to BAP\n", dev->name, err); | ||
766 | goto busy; | ||
767 | } | ||
768 | 760 | ||
769 | /* Clear the 802.11 header and data length fields - some | 761 | if (priv->has_alt_txcntl) { |
770 | * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused | 762 | /* WPA enabled firmwares have tx_cntl at the end of |
771 | * if this isn't done. */ | 763 | * the 802.11 header. So write zeroed descriptor and |
772 | hermes_clear_words(hw, HERMES_DATA0, | 764 | * 802.11 header at the same time |
773 | HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); | 765 | */ |
766 | char desc[HERMES_802_3_OFFSET]; | ||
767 | __le16 *txcntl = (__le16 *) &desc[HERMES_TXCNTL2_OFFSET]; | ||
768 | |||
769 | memset(&desc, 0, sizeof(desc)); | ||
770 | |||
771 | *txcntl = cpu_to_le16(tx_control); | ||
772 | err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), | ||
773 | txfid, 0); | ||
774 | if (err) { | ||
775 | if (net_ratelimit()) | ||
776 | printk(KERN_ERR "%s: Error %d writing Tx " | ||
777 | "descriptor to BAP\n", dev->name, err); | ||
778 | goto busy; | ||
779 | } | ||
780 | } else { | ||
781 | struct hermes_tx_descriptor desc; | ||
782 | |||
783 | memset(&desc, 0, sizeof(desc)); | ||
784 | |||
785 | desc.tx_control = cpu_to_le16(tx_control); | ||
786 | err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), | ||
787 | txfid, 0); | ||
788 | if (err) { | ||
789 | if (net_ratelimit()) | ||
790 | printk(KERN_ERR "%s: Error %d writing Tx " | ||
791 | "descriptor to BAP\n", dev->name, err); | ||
792 | goto busy; | ||
793 | } | ||
794 | |||
795 | /* Clear the 802.11 header and data length fields - some | ||
796 | * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused | ||
797 | * if this isn't done. */ | ||
798 | hermes_clear_words(hw, HERMES_DATA0, | ||
799 | HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); | ||
800 | } | ||
774 | 801 | ||
775 | /* Encapsulate Ethernet-II frames */ | 802 | /* Encapsulate Ethernet-II frames */ |
776 | if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ | 803 | if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ |
@@ -2528,6 +2555,7 @@ static int determine_firmware(struct net_device *dev) | |||
2528 | priv->has_ibss = 1; | 2555 | priv->has_ibss = 1; |
2529 | priv->has_wep = 0; | 2556 | priv->has_wep = 0; |
2530 | priv->has_big_wep = 0; | 2557 | priv->has_big_wep = 0; |
2558 | priv->has_alt_txcntl = 0; | ||
2531 | priv->do_fw_download = 0; | 2559 | priv->do_fw_download = 0; |
2532 | 2560 | ||
2533 | /* Determine capabilities from the firmware version */ | 2561 | /* Determine capabilities from the firmware version */ |
@@ -2550,6 +2578,7 @@ static int determine_firmware(struct net_device *dev) | |||
2550 | priv->has_hostscan = (firmver >= 0x8000a); | 2578 | priv->has_hostscan = (firmver >= 0x8000a); |
2551 | priv->do_fw_download = 1; | 2579 | priv->do_fw_download = 1; |
2552 | priv->broken_monitor = (firmver >= 0x80000); | 2580 | priv->broken_monitor = (firmver >= 0x80000); |
2581 | priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */ | ||
2553 | 2582 | ||
2554 | /* Tested with Agere firmware : | 2583 | /* Tested with Agere firmware : |
2555 | * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II | 2584 | * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II |
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h index e0acb633e9d5..f93752ffb07c 100644 --- a/drivers/net/wireless/orinoco.h +++ b/drivers/net/wireless/orinoco.h | |||
@@ -85,6 +85,7 @@ struct orinoco_private { | |||
85 | unsigned int has_preamble:1; | 85 | unsigned int has_preamble:1; |
86 | unsigned int has_sensitivity:1; | 86 | unsigned int has_sensitivity:1; |
87 | unsigned int has_hostscan:1; | 87 | unsigned int has_hostscan:1; |
88 | unsigned int has_alt_txcntl:1; | ||
88 | unsigned int do_fw_download:1; | 89 | unsigned int do_fw_download:1; |
89 | unsigned int broken_disableport:1; | 90 | unsigned int broken_disableport:1; |
90 | unsigned int broken_monitor:1; | 91 | unsigned int broken_monitor:1; |