diff options
Diffstat (limited to 'drivers/net/wireless/orinoco')
-rw-r--r-- | drivers/net/wireless/orinoco/cfg.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/main.c | 172 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/orinoco.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/orinoco_cs.c | 27 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/orinoco_usb.c | 91 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/spectrum_cs.c | 27 |
6 files changed, 162 insertions, 162 deletions
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c index 81d228de9e5d..8c4169c227ae 100644 --- a/drivers/net/wireless/orinoco/cfg.c +++ b/drivers/net/wireless/orinoco/cfg.c @@ -159,6 +159,7 @@ static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev, } static int orinoco_set_channel(struct wiphy *wiphy, + struct net_device *netdev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) { diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 1d60c7e4392a..ca71f08709bc 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -340,18 +340,109 @@ EXPORT_SYMBOL(orinoco_change_mtu); /* Tx path */ /********************************************************************/ +/* Add encapsulation and MIC to the existing SKB. + * The main xmit routine will then send the whole lot to the card. + * Need 8 bytes headroom + * Need 8 bytes tailroom + * + * With encapsulated ethernet II frame + * -------- + * 803.3 header (14 bytes) + * dst[6] + * -------- src[6] + * 803.3 header (14 bytes) len[2] + * dst[6] 803.2 header (8 bytes) + * src[6] encaps[6] + * len[2] <- leave alone -> len[2] + * -------- -------- <-- 0 + * Payload Payload + * ... ... + * + * -------- -------- + * MIC (8 bytes) + * -------- + * + * returns 0 on success, -ENOMEM on error. + */ +int orinoco_process_xmit_skb(struct sk_buff *skb, + struct net_device *dev, + struct orinoco_private *priv, + int *tx_control, + u8 *mic_buf) +{ + struct orinoco_tkip_key *key; + struct ethhdr *eh; + int do_mic; + + key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key; + + do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) && + (key != NULL)); + + if (do_mic) + *tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) | + HERMES_TXCTRL_MIC; + + eh = (struct ethhdr *)skb->data; + + /* Encapsulate Ethernet-II frames */ + if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ + struct header_struct { + struct ethhdr eth; /* 802.3 header */ + u8 encap[6]; /* 802.2 header */ + } __attribute__ ((packed)) hdr; + int len = skb->len + sizeof(encaps_hdr) - (2 * ETH_ALEN); + + if (skb_headroom(skb) < ENCAPS_OVERHEAD) { + if (net_ratelimit()) + printk(KERN_ERR + "%s: Not enough headroom for 802.2 headers %d\n", + dev->name, skb_headroom(skb)); + return -ENOMEM; + } + + /* Fill in new header */ + memcpy(&hdr.eth, eh, 2 * ETH_ALEN); + hdr.eth.h_proto = htons(len); + memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); + + /* Make room for the new header, and copy it in */ + eh = (struct ethhdr *) skb_push(skb, ENCAPS_OVERHEAD); + memcpy(eh, &hdr, sizeof(hdr)); + } + + /* Calculate Michael MIC */ + if (do_mic) { + size_t len = skb->len - ETH_HLEN; + u8 *mic = &mic_buf[0]; + + /* Have to write to an even address, so copy the spare + * byte across */ + if (skb->len % 2) { + *mic = skb->data[skb->len - 1]; + mic++; + } + + orinoco_mic(priv->tx_tfm_mic, key->tx_mic, + eh->h_dest, eh->h_source, 0 /* priority */, + skb->data + ETH_HLEN, + len, mic); + } + + return 0; +} +EXPORT_SYMBOL(orinoco_process_xmit_skb); + static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; - struct orinoco_tkip_key *key; hermes_t *hw = &priv->hw; int err = 0; u16 txfid = priv->txfid; - struct ethhdr *eh; int tx_control; unsigned long flags; - int do_mic; + u8 mic_buf[MICHAEL_MIC_LEN+1]; if (!netif_running(dev)) { printk(KERN_ERR "%s: Tx on stopped device!\n", @@ -383,16 +474,12 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) if (skb->len < ETH_HLEN) goto drop; - key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key; - - do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) && - (key != NULL)); - tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX; - if (do_mic) - tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) | - HERMES_TXCTRL_MIC; + err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control, + &mic_buf[0]); + if (err) + goto drop; if (priv->has_alt_txcntl) { /* WPA enabled firmwares have tx_cntl at the end of @@ -435,34 +522,6 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); } - eh = (struct ethhdr *)skb->data; - - /* Encapsulate Ethernet-II frames */ - if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ - struct header_struct { - struct ethhdr eth; /* 802.3 header */ - u8 encap[6]; /* 802.2 header */ - } __attribute__ ((packed)) hdr; - - /* Strip destination and source from the data */ - skb_pull(skb, 2 * ETH_ALEN); - - /* And move them to a separate header */ - memcpy(&hdr.eth, eh, 2 * ETH_ALEN); - hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len); - memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); - - /* Insert the SNAP header */ - if (skb_headroom(skb) < sizeof(hdr)) { - printk(KERN_ERR - "%s: Not enough headroom for 802.2 headers %d\n", - dev->name, skb_headroom(skb)); - goto drop; - } - eh = (struct ethhdr *) skb_push(skb, sizeof(hdr)); - memcpy(eh, &hdr, sizeof(hdr)); - } - err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len, txfid, HERMES_802_3_OFFSET); if (err) { @@ -471,32 +530,16 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) goto busy; } - /* Calculate Michael MIC */ - if (do_mic) { - u8 mic_buf[MICHAEL_MIC_LEN + 1]; - u8 *mic; - size_t offset; - size_t len; + if (tx_control & HERMES_TXCTRL_MIC) { + size_t offset = HERMES_802_3_OFFSET + skb->len; + size_t len = MICHAEL_MIC_LEN; - if (skb->len % 2) { - /* MIC start is on an odd boundary */ - mic_buf[0] = skb->data[skb->len - 1]; - mic = &mic_buf[1]; - offset = skb->len - 1; - len = MICHAEL_MIC_LEN + 1; - } else { - mic = &mic_buf[0]; - offset = skb->len; - len = MICHAEL_MIC_LEN; + if (offset % 2) { + offset--; + len++; } - - orinoco_mic(priv->tx_tfm_mic, key->tx_mic, - eh->h_dest, eh->h_source, 0 /* priority */, - skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic); - - /* Write the MIC */ err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len, - txfid, HERMES_802_3_OFFSET + offset); + txfid, offset); if (err) { printk(KERN_ERR "%s: Error %d writing MIC to BAP\n", dev->name, err); @@ -517,7 +560,6 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) goto busy; } - dev->trans_start = jiffies; stats->tx_bytes += HERMES_802_3_OFFSET + skb->len; goto ok; @@ -1576,8 +1618,6 @@ void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) /* We don't actually do anything about it */ break; } - - return; } EXPORT_SYMBOL(__orinoco_ev_info); @@ -2235,7 +2275,7 @@ int orinoco_if_add(struct orinoco_private *priv, /* we use the default eth_mac_addr for setting the MAC addr */ /* Reserve space in skb for the SNAP header */ - dev->hard_header_len += ENCAPS_OVERHEAD; + dev->needed_headroom = ENCAPS_OVERHEAD; netif_carrier_off(dev); diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index e9f415a56d4d..a6da86e0a70f 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -200,6 +200,12 @@ extern irqreturn_t orinoco_interrupt(int irq, void *dev_id); extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw); extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw); +int orinoco_process_xmit_skb(struct sk_buff *skb, + struct net_device *dev, + struct orinoco_private *priv, + int *tx_control, + u8 *mic); + /* Common ndo functions exported for reuse by orinoco_usb */ int orinoco_open(struct net_device *dev); int orinoco_stop(struct net_device *dev); diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index f99b13ba92b3..b16d5db52a4d 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -50,7 +50,6 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket * struct orinoco_private */ struct orinoco_pccard { struct pcmcia_device *p_dev; - dev_node_t node; /* Used to handle hard reset */ /* yuck, we need this hack to work around the insanity of the @@ -119,10 +118,6 @@ orinoco_cs_probe(struct pcmcia_device *link) card->p_dev = link; link->priv = priv; - /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; - link->irq.Handler = orinoco_interrupt; - /* General socket configuration defaults can go here. In this * client, we assume very little, and rely on the CIS for * almost everything. In most clients, many details (i.e., @@ -144,8 +139,7 @@ static void orinoco_cs_detach(struct pcmcia_device *link) { struct orinoco_private *priv = link->priv; - if (link->dev_node) - orinoco_if_del(priv); + orinoco_if_del(priv); orinoco_cs_release(link); @@ -230,7 +224,6 @@ static int orinoco_cs_config(struct pcmcia_device *link) { struct orinoco_private *priv = link->priv; - struct orinoco_pccard *card = priv->card; hermes_t *hw = &priv->hw; int ret; void __iomem *mem; @@ -258,12 +251,7 @@ orinoco_cs_config(struct pcmcia_device *link) goto failed; } - /* - * Allocate an interrupt line. Note that this does not assign - * a handler to the interrupt, unless the 'Handler' member of - * the irq structure is initialized. - */ - ret = pcmcia_request_irq(link, &link->irq); + ret = pcmcia_request_irq(link, orinoco_interrupt); if (ret) goto failed; @@ -285,9 +273,6 @@ orinoco_cs_config(struct pcmcia_device *link) if (ret) goto failed; - /* Ok, we have the configuration, prepare to register the netdev */ - card->node.major = card->node.minor = 0; - /* Initialise the main driver */ if (orinoco_init(priv) != 0) { printk(KERN_ERR PFX "orinoco_init() failed\n"); @@ -296,17 +281,11 @@ orinoco_cs_config(struct pcmcia_device *link) /* Register an interface with the stack */ if (orinoco_if_add(priv, link->io.BasePort1, - link->irq.AssignedIRQ, NULL) != 0) { + link->irq, NULL) != 0) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto failed; } - /* At this point, the dev_node_t structure(s) needs to be - * initialized and arranged in a linked list at link->dev_node. */ - strcpy(card->node.dev_name, priv->ndev->name); - link->dev_node = &card->node; /* link->dev_node being non-NULL is also - * used to indicate that the - * net_device has been registered */ return 0; failed: diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index e22093359f3e..78f089baa8c9 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -67,6 +67,7 @@ #include <linux/wireless.h> #include <linux/firmware.h> +#include "mic.h" #include "orinoco.h" #ifndef URB_ASYNC_UNLINK @@ -1198,11 +1199,9 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; struct ezusb_priv *upriv = priv->card; + u8 mic[MICHAEL_MIC_LEN+1]; int err = 0; - char *p; - struct ethhdr *eh; - int len, data_len, data_off; - __le16 tx_control; + int tx_control; unsigned long flags; struct request_context *ctx; u8 *buf; @@ -1222,7 +1221,7 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) if (orinoco_lock(priv, &flags) != 0) { printk(KERN_ERR - "%s: orinoco_xmit() called while hw_unavailable\n", + "%s: ezusb_xmit() called while hw_unavailable\n", dev->name); return NETDEV_TX_BUSY; } @@ -1232,53 +1231,46 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) /* Oops, the firmware hasn't established a connection, silently drop the packet (this seems to be the safest approach). */ - stats->tx_errors++; - orinoco_unlock(priv, &flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; + goto drop; } + /* Check packet length */ + if (skb->len < ETH_HLEN) + goto drop; + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0); if (!ctx) - goto fail; + goto busy; memset(ctx->buf, 0, BULK_BUF_SIZE); buf = ctx->buf->data; - /* Length of the packet body */ - /* FIXME: what if the skb is smaller than this? */ - len = max_t(int, skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN); - - eh = (struct ethhdr *) skb->data; - - tx_control = cpu_to_le16(0); - memcpy(buf, &tx_control, sizeof(tx_control)); - buf += sizeof(tx_control); - /* Encapsulate Ethernet-II frames */ - if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ - struct header_struct *hdr = (void *) buf; - buf += sizeof(*hdr); - data_len = len; - data_off = sizeof(tx_control) + sizeof(*hdr); - p = skb->data + ETH_HLEN; - - /* 802.3 header */ - memcpy(hdr->dest, eh->h_dest, ETH_ALEN); - memcpy(hdr->src, eh->h_source, ETH_ALEN); - hdr->len = htons(data_len + ENCAPS_OVERHEAD); - - /* 802.2 header */ - memcpy(&hdr->dsap, &encaps_hdr, sizeof(encaps_hdr)); - - hdr->ethertype = eh->h_proto; - } else { /* IEEE 802.3 frame */ - data_len = len + ETH_HLEN; - data_off = sizeof(tx_control); - p = skb->data; + tx_control = 0; + + err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control, + &mic[0]); + if (err) + goto drop; + + { + __le16 *tx_cntl = (__le16 *)buf; + *tx_cntl = cpu_to_le16(tx_control); + buf += sizeof(*tx_cntl); } - memcpy(buf, p, data_len); - buf += data_len; + memcpy(buf, skb->data, skb->len); + buf += skb->len; + + if (tx_control & HERMES_TXCTRL_MIC) { + u8 *m = mic; + /* Mic has been offset so it can be copied to an even + * address. We're copying eveything anyway, so we + * don't need to copy that first byte. */ + if (skb->len % 2) + m++; + memcpy(buf, m, MICHAEL_MIC_LEN); + buf += MICHAEL_MIC_LEN; + } /* Finally, we actually initiate the send */ netif_stop_queue(dev); @@ -1294,20 +1286,23 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) if (net_ratelimit()) printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err); - stats->tx_errors++; - goto fail; + goto busy; } dev->trans_start = jiffies; - stats->tx_bytes += data_off + data_len; + stats->tx_bytes += skb->len; + goto ok; - orinoco_unlock(priv, &flags); + drop: + stats->tx_errors++; + stats->tx_dropped++; + ok: + orinoco_unlock(priv, &flags); dev_kfree_skb(skb); - return NETDEV_TX_OK; - fail: + busy: orinoco_unlock(priv, &flags); return NETDEV_TX_BUSY; } diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index 9b1af4976bf5..b51a9adc80f6 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -57,7 +57,6 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket * struct orinoco_private */ struct orinoco_pccard { struct pcmcia_device *p_dev; - dev_node_t node; }; /********************************************************************/ @@ -193,10 +192,6 @@ spectrum_cs_probe(struct pcmcia_device *link) card->p_dev = link; link->priv = priv; - /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; - link->irq.Handler = orinoco_interrupt; - /* General socket configuration defaults can go here. In this * client, we assume very little, and rely on the CIS for * almost everything. In most clients, many details (i.e., @@ -218,8 +213,7 @@ static void spectrum_cs_detach(struct pcmcia_device *link) { struct orinoco_private *priv = link->priv; - if (link->dev_node) - orinoco_if_del(priv); + orinoco_if_del(priv); spectrum_cs_release(link); @@ -304,7 +298,6 @@ static int spectrum_cs_config(struct pcmcia_device *link) { struct orinoco_private *priv = link->priv; - struct orinoco_pccard *card = priv->card; hermes_t *hw = &priv->hw; int ret; void __iomem *mem; @@ -332,12 +325,7 @@ spectrum_cs_config(struct pcmcia_device *link) goto failed; } - /* - * Allocate an interrupt line. Note that this does not assign - * a handler to the interrupt, unless the 'Handler' member of - * the irq structure is initialized. - */ - ret = pcmcia_request_irq(link, &link->irq); + ret = pcmcia_request_irq(link, orinoco_interrupt); if (ret) goto failed; @@ -360,9 +348,6 @@ spectrum_cs_config(struct pcmcia_device *link) if (ret) goto failed; - /* Ok, we have the configuration, prepare to register the netdev */ - card->node.major = card->node.minor = 0; - /* Reset card */ if (spectrum_cs_hard_reset(priv) != 0) goto failed; @@ -375,17 +360,11 @@ spectrum_cs_config(struct pcmcia_device *link) /* Register an interface with the stack */ if (orinoco_if_add(priv, link->io.BasePort1, - link->irq.AssignedIRQ, NULL) != 0) { + link->irq, NULL) != 0) { printk(KERN_ERR PFX "orinoco_if_add() failed\n"); goto failed; } - /* At this point, the dev_node_t structure(s) needs to be - * initialized and arranged in a linked list at link->dev_node. */ - strcpy(card->node.dev_name, priv->ndev->name); - link->dev_node = &card->node; /* link->dev_node being non-NULL is also - * used to indicate that the - * net_device has been registered */ return 0; failed: |