Commit 6eecad77 authored by David Kilroy's avatar David Kilroy Committed by John W. Linville

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: default avatarDavid Kilroy <kilroyd@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 3994d502
...@@ -179,6 +179,7 @@ ...@@ -179,6 +179,7 @@
#define HERMES_802_11_OFFSET (14) #define HERMES_802_11_OFFSET (14)
#define HERMES_802_3_OFFSET (14+32) #define HERMES_802_3_OFFSET (14+32)
#define HERMES_802_2_OFFSET (14+32+14) #define HERMES_802_2_OFFSET (14+32+14)
#define HERMES_TXCNTL2_OFFSET (HERMES_802_3_OFFSET - 2)
#define HERMES_RXSTAT_ERR (0x0003) #define HERMES_RXSTAT_ERR (0x0003)
#define HERMES_RXSTAT_BADCRC (0x0001) #define HERMES_RXSTAT_BADCRC (0x0001)
......
...@@ -722,7 +722,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -722,7 +722,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
u16 txfid = priv->txfid; u16 txfid = priv->txfid;
struct ethhdr *eh; struct ethhdr *eh;
int data_off; int data_off;
struct hermes_tx_descriptor desc; int tx_control;
unsigned long flags; unsigned long flags;
if (! netif_running(dev)) { if (! netif_running(dev)) {
...@@ -756,21 +756,48 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -756,21 +756,48 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
eh = (struct ethhdr *)skb->data; eh = (struct ethhdr *)skb->data;
memset(&desc, 0, sizeof(desc)); tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
if (err) {
if (net_ratelimit())
printk(KERN_ERR "%s: Error %d writing Tx descriptor "
"to BAP\n", dev->name, err);
goto busy;
}
/* Clear the 802.11 header and data length fields - some if (priv->has_alt_txcntl) {
* firmwares (e.g. Lucent/Agere 8.xx) appear to get confused /* WPA enabled firmwares have tx_cntl at the end of
* if this isn't done. */ * the 802.11 header. So write zeroed descriptor and
hermes_clear_words(hw, HERMES_DATA0, * 802.11 header at the same time
HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); */
char desc[HERMES_802_3_OFFSET];
__le16 *txcntl = (__le16 *) &desc[HERMES_TXCNTL2_OFFSET];
memset(&desc, 0, sizeof(desc));
*txcntl = cpu_to_le16(tx_control);
err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
txfid, 0);
if (err) {
if (net_ratelimit())
printk(KERN_ERR "%s: Error %d writing Tx "
"descriptor to BAP\n", dev->name, err);
goto busy;
}
} else {
struct hermes_tx_descriptor desc;
memset(&desc, 0, sizeof(desc));
desc.tx_control = cpu_to_le16(tx_control);
err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
txfid, 0);
if (err) {
if (net_ratelimit())
printk(KERN_ERR "%s: Error %d writing Tx "
"descriptor to BAP\n", dev->name, err);
goto busy;
}
/* Clear the 802.11 header and data length fields - some
* firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
* if this isn't done. */
hermes_clear_words(hw, HERMES_DATA0,
HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
}
/* Encapsulate Ethernet-II frames */ /* Encapsulate Ethernet-II frames */
if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
...@@ -2528,6 +2555,7 @@ static int determine_firmware(struct net_device *dev) ...@@ -2528,6 +2555,7 @@ static int determine_firmware(struct net_device *dev)
priv->has_ibss = 1; priv->has_ibss = 1;
priv->has_wep = 0; priv->has_wep = 0;
priv->has_big_wep = 0; priv->has_big_wep = 0;
priv->has_alt_txcntl = 0;
priv->do_fw_download = 0; priv->do_fw_download = 0;
/* Determine capabilities from the firmware version */ /* Determine capabilities from the firmware version */
...@@ -2550,6 +2578,7 @@ static int determine_firmware(struct net_device *dev) ...@@ -2550,6 +2578,7 @@ static int determine_firmware(struct net_device *dev)
priv->has_hostscan = (firmver >= 0x8000a); priv->has_hostscan = (firmver >= 0x8000a);
priv->do_fw_download = 1; priv->do_fw_download = 1;
priv->broken_monitor = (firmver >= 0x80000); priv->broken_monitor = (firmver >= 0x80000);
priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
/* Tested with Agere firmware : /* Tested with Agere firmware :
* 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
......
...@@ -85,6 +85,7 @@ struct orinoco_private { ...@@ -85,6 +85,7 @@ struct orinoco_private {
unsigned int has_preamble:1; unsigned int has_preamble:1;
unsigned int has_sensitivity:1; unsigned int has_sensitivity:1;
unsigned int has_hostscan:1; unsigned int has_hostscan:1;
unsigned int has_alt_txcntl:1;
unsigned int do_fw_download:1; unsigned int do_fw_download:1;
unsigned int broken_disableport:1; unsigned int broken_disableport:1;
unsigned int broken_monitor:1; unsigned int broken_monitor:1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment