aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@gmail.com>2008-08-21 18:27:56 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-22 19:28:05 -0400
commit6eecad77861b193bcfc109de12835ca0bddf7c58 (patch)
treecacb4f7513571c6992adebb00c21bc8e5a14e663 /drivers/net/wireless
parent3994d502017a2239e30152d1231843ad05d04a7b (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/net/wireless')
-rw-r--r--drivers/net/wireless/hermes.h1
-rw-r--r--drivers/net/wireless/orinoco.c59
-rw-r--r--drivers/net/wireless/orinoco.h1
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;