From b42f2074dedef559ecf72dce61a6501f9f9b273a Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 1 May 2010 14:05:38 +0100 Subject: orinoco: add hermes_ops Pave the way for introducing USB alternative functions. Force callers to dereference ops instead of providing wrappers. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/main.c | 83 +++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 41 deletions(-) (limited to 'drivers/net/wireless/orinoco/main.c') diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index b42634c614b5..d90951f731ef 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -399,8 +399,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) memset(&desc, 0, sizeof(desc)); *txcntl = cpu_to_le16(tx_control); - err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), - txfid, 0); + err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), + txfid, 0); if (err) { if (net_ratelimit()) printk(KERN_ERR "%s: Error %d writing Tx " @@ -413,8 +413,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) 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); + err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), + txfid, 0); if (err) { if (net_ratelimit()) printk(KERN_ERR "%s: Error %d writing Tx " @@ -457,8 +457,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) memcpy(eh, &hdr, sizeof(hdr)); } - err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len, - txfid, HERMES_802_3_OFFSET); + err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len, + txfid, HERMES_802_3_OFFSET); if (err) { printk(KERN_ERR "%s: Error %d writing packet to BAP\n", dev->name, err); @@ -489,8 +489,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic); /* Write the MIC */ - err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len, - txfid, HERMES_802_3_OFFSET + offset); + err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len, + txfid, HERMES_802_3_OFFSET + offset); if (err) { printk(KERN_ERR "%s: Error %d writing MIC to BAP\n", dev->name, err); @@ -501,7 +501,7 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) /* Finally, we actually initiate the send */ netif_stop_queue(dev); - err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, + err = hw->ops->cmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, NULL); if (err) { netif_start_queue(dev); @@ -571,9 +571,9 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) return; /* Nothing's really happened */ /* Read part of the frame header - we need status and addr1 */ - err = hermes_bap_pread(hw, IRQ_BAP, &hdr, - sizeof(struct hermes_txexc_data), - fid, 0); + err = hw->ops->bap_pread(hw, IRQ_BAP, &hdr, + sizeof(struct hermes_txexc_data), + fid, 0); hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); stats->tx_errors++; @@ -763,9 +763,9 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, /* If any, copy the data from the card to the skb */ if (datalen > 0) { - err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), - ALIGN(datalen, 2), rxfid, - HERMES_802_2_OFFSET); + err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), + ALIGN(datalen, 2), rxfid, + HERMES_802_2_OFFSET); if (err) { printk(KERN_ERR "%s: error %d reading monitor frame\n", dev->name, err); @@ -813,8 +813,8 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) rxfid = hermes_read_regn(hw, RXFID); - err = hermes_bap_pread(hw, IRQ_BAP, desc, sizeof(*desc), - rxfid, 0); + err = hw->ops->bap_pread(hw, IRQ_BAP, desc, sizeof(*desc), + rxfid, 0); if (err) { printk(KERN_ERR "%s: error %d reading Rx descriptor. " "Frame dropped.\n", dev->name, err); @@ -881,9 +881,9 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) nothing is removed. 2 is for aligning the IP header. */ skb_reserve(skb, ETH_HLEN + 2); - err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length), - ALIGN(length, 2), rxfid, - HERMES_802_2_OFFSET); + err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, length), + ALIGN(length, 2), rxfid, + HERMES_802_2_OFFSET); if (err) { printk(KERN_ERR "%s: error %d reading frame. " "Frame dropped.\n", dev->name, err); @@ -1144,9 +1144,9 @@ static void orinoco_join_ap(struct work_struct *work) goto out; /* Read scan results from the firmware */ - err = hermes_read_ltv(hw, USER_BAP, - HERMES_RID_SCANRESULTSTABLE, - MAX_SCAN_LEN, &len, buf); + err = hw->ops->read_ltv(hw, USER_BAP, + HERMES_RID_SCANRESULTSTABLE, + MAX_SCAN_LEN, &len, buf); if (err) { printk(KERN_ERR "%s: Cannot read scan results\n", dev->name); @@ -1193,8 +1193,8 @@ static void orinoco_send_bssid_wevent(struct orinoco_private *priv) union iwreq_data wrqu; int err; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, - ETH_ALEN, NULL, wrqu.ap_addr.sa_data); + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, + ETH_ALEN, NULL, wrqu.ap_addr.sa_data); if (err != 0) return; @@ -1216,8 +1216,8 @@ static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv) if (!priv->has_wpa) return; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO, - sizeof(buf), NULL, &buf); + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO, + sizeof(buf), NULL, &buf); if (err != 0) return; @@ -1246,8 +1246,9 @@ static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv) if (!priv->has_wpa) return; - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO, - sizeof(buf), NULL, &buf); + err = hw->ops->read_ltv(hw, USER_BAP, + HERMES_RID_CURRENT_ASSOC_RESP_INFO, + sizeof(buf), NULL, &buf); if (err != 0) return; @@ -1370,8 +1371,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) infofid = hermes_read_regn(hw, INFOFID); /* Read the info frame header - don't try too hard */ - err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info), - infofid, 0); + err = hw->ops->bap_pread(hw, IRQ_BAP, &info, sizeof(info), + infofid, 0); if (err) { printk(KERN_ERR "%s: error %d reading info frame. " "Frame dropped.\n", dev->name, err); @@ -1392,8 +1393,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) len = sizeof(tallies); } - err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len, - infofid, sizeof(info)); + err = hw->ops->bap_pread(hw, IRQ_BAP, &tallies, len, + infofid, sizeof(info)); if (err) break; @@ -1428,8 +1429,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) break; } - err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len, - infofid, sizeof(info)); + err = hw->ops->bap_pread(hw, IRQ_BAP, &linkstatus, len, + infofid, sizeof(info)); if (err) break; newstatus = le16_to_cpu(linkstatus.linkstatus); @@ -1493,8 +1494,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) } /* Read scan data */ - err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, - infofid, sizeof(info)); + err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) buf, len, + infofid, sizeof(info)); if (err) { kfree(buf); qabort_scan(priv); @@ -1546,8 +1547,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) break; /* Read scan data */ - err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len, - infofid, sizeof(info)); + err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) bss, len, + infofid, sizeof(info)); if (err) kfree(bss); else @@ -1646,7 +1647,7 @@ static int orinoco_reinit_firmware(struct orinoco_private *priv) struct hermes *hw = &priv->hw; int err; - err = hermes_init(hw); + err = hw->ops->init(hw); if (priv->do_fw_download && !err) { err = orinoco_download(priv); if (err) @@ -1983,7 +1984,7 @@ int orinoco_init(struct orinoco_private *priv) priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN; /* Initialize the firmware */ - err = hermes_init(hw); + err = hw->ops->init(hw); if (err != 0) { dev_err(dev, "Failed to initialize firmware (err = %d)\n", err); -- cgit v1.2.3 From 593ef09c9e70c92c0d76c67a1c03a5d44d3aec82 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 1 May 2010 14:05:39 +0100 Subject: orinoco: allow driver to specify netdev_ops Allow the main drivers to specify a custom version of the net_device_ops structure. This is required by orinoco_usb to supply a separate transmit function. Export existing net_device_ops callbacks so that the drivers can reuse some of the existing code. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/main.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless/orinoco/main.c') diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index d90951f731ef..7acb6bc3ebff 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -253,7 +253,7 @@ void set_port_type(struct orinoco_private *priv) /* Device methods */ /********************************************************************/ -static int orinoco_open(struct net_device *dev) +int orinoco_open(struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); unsigned long flags; @@ -271,8 +271,9 @@ static int orinoco_open(struct net_device *dev) return err; } +EXPORT_SYMBOL(orinoco_open); -static int orinoco_stop(struct net_device *dev) +int orinoco_stop(struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); int err = 0; @@ -290,15 +291,17 @@ static int orinoco_stop(struct net_device *dev) return err; } +EXPORT_SYMBOL(orinoco_stop); -static struct net_device_stats *orinoco_get_stats(struct net_device *dev) +struct net_device_stats *orinoco_get_stats(struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); return &priv->stats; } +EXPORT_SYMBOL(orinoco_get_stats); -static void orinoco_set_multicast_list(struct net_device *dev) +void orinoco_set_multicast_list(struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); unsigned long flags; @@ -312,8 +315,9 @@ static void orinoco_set_multicast_list(struct net_device *dev) __orinoco_set_multicast_list(dev); orinoco_unlock(priv, &flags); } +EXPORT_SYMBOL(orinoco_set_multicast_list); -static int orinoco_change_mtu(struct net_device *dev, int new_mtu) +int orinoco_change_mtu(struct net_device *dev, int new_mtu) { struct orinoco_private *priv = ndev_priv(dev); @@ -329,6 +333,7 @@ static int orinoco_change_mtu(struct net_device *dev, int new_mtu) return 0; } +EXPORT_SYMBOL(orinoco_change_mtu); /********************************************************************/ /* Tx path */ @@ -614,7 +619,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) netif_wake_queue(dev); } -static void orinoco_tx_timeout(struct net_device *dev) +void orinoco_tx_timeout(struct net_device *dev) { struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; @@ -629,6 +634,7 @@ static void orinoco_tx_timeout(struct net_device *dev) schedule_work(&priv->reset_work); } +EXPORT_SYMBOL(orinoco_tx_timeout); /********************************************************************/ /* Rx path (data frames) */ @@ -2192,7 +2198,8 @@ EXPORT_SYMBOL(alloc_orinocodev); */ int orinoco_if_add(struct orinoco_private *priv, unsigned long base_addr, - unsigned int irq) + unsigned int irq, + const struct net_device_ops *ops) { struct wiphy *wiphy = priv_to_wiphy(priv); struct wireless_dev *wdev; @@ -2211,12 +2218,17 @@ int orinoco_if_add(struct orinoco_private *priv, /* Setup / override net_device fields */ dev->ieee80211_ptr = wdev; - dev->netdev_ops = &orinoco_netdev_ops; dev->watchdog_timeo = HZ; /* 1 second timeout */ dev->wireless_handlers = &orinoco_handler_def; #ifdef WIRELESS_SPY dev->wireless_data = &priv->wireless_data; #endif + /* Default to standard ops if not set */ + if (ops) + dev->netdev_ops = ops; + else + dev->netdev_ops = &orinoco_netdev_ops; + /* we use the default eth_mac_addr for setting the MAC addr */ /* Reserve space in skb for the SNAP header */ -- cgit v1.2.3 From bcad6e80f3fb0d6724c3814cf32258bbcf1d67db Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 1 May 2010 14:05:40 +0100 Subject: orinoco: encapsulate driver locking Local bus and USB drivers will need to do locking differently. The original orinoco_usb patches had a boolean variable controlling whether spin_lock_bh was used, or irq based locking. This version provides wrappers for the lock functions and the drivers specify the functions pointers needed. This will introduce a performance penalty, but I'm not expecting it to be noticable. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless/orinoco/main.c') diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 7acb6bc3ebff..36c4ba865c7c 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -281,13 +281,13 @@ int orinoco_stop(struct net_device *dev) /* We mustn't use orinoco_lock() here, because we need to be able to close the interface even if hw_unavailable is set (e.g. as we're released after a PC Card removal) */ - spin_lock_irq(&priv->lock); + orinoco_lock_irq(priv); priv->open = 0; err = __orinoco_down(priv); - spin_unlock_irq(&priv->lock); + orinoco_unlock_irq(priv); return err; } @@ -1741,7 +1741,7 @@ void orinoco_reset(struct work_struct *work) } /* This has to be called from user context */ - spin_lock_irq(&priv->lock); + orinoco_lock_irq(priv); priv->hw_unavailable--; @@ -1756,7 +1756,7 @@ void orinoco_reset(struct work_struct *work) dev->trans_start = jiffies; } - spin_unlock_irq(&priv->lock); + orinoco_unlock_irq(priv); return; disable: @@ -2073,9 +2073,9 @@ int orinoco_init(struct orinoco_private *priv) /* Make the hardware available, as long as it hasn't been * removed elsewhere (e.g. by PCMCIA hot unplug) */ - spin_lock_irq(&priv->lock); + orinoco_lock_irq(priv); priv->hw_unavailable--; - spin_unlock_irq(&priv->lock); + orinoco_unlock_irq(priv); dev_dbg(dev, "Ready\n"); @@ -2317,7 +2317,7 @@ int orinoco_up(struct orinoco_private *priv) unsigned long flags; int err; - spin_lock_irqsave(&priv->lock, flags); + priv->hw.ops->lock_irqsave(&priv->lock, &flags); err = orinoco_reinit_firmware(priv); if (err) { @@ -2337,7 +2337,7 @@ int orinoco_up(struct orinoco_private *priv) } exit: - spin_unlock_irqrestore(&priv->lock, flags); + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags); return 0; } @@ -2349,7 +2349,7 @@ void orinoco_down(struct orinoco_private *priv) unsigned long flags; int err; - spin_lock_irqsave(&priv->lock, flags); + priv->hw.ops->lock_irqsave(&priv->lock, &flags); err = __orinoco_down(priv); if (err) printk(KERN_WARNING "%s: Error %d downing interface\n", @@ -2357,7 +2357,7 @@ void orinoco_down(struct orinoco_private *priv) netif_device_detach(dev); priv->hw_unavailable++; - spin_unlock_irqrestore(&priv->lock, flags); + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags); } EXPORT_SYMBOL(orinoco_down); -- cgit v1.2.3 From 9afac70a7305817b22327ac23cf2d0eb72388229 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Sat, 1 May 2010 14:05:41 +0100 Subject: orinoco: add orinoco_usb driver This driver uses the core orinoco modules for the bulk of the functionality. The low level hermes routines (for local bus cards) are replaced, the driver supplies its own ndo_xmit_start function, and locking is done with the _bh variant. Some recent functionality is not available to the USB cards yet (firmware loading and WPA). Out-of-tree driver originally written by Manuel Estrada Sainz. Thanks to Mark Davis for supplying hardware to test the updates. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/orinoco/main.c') diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 36c4ba865c7c..7c9faa4c079e 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -797,7 +797,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, stats->rx_dropped++; } -static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) +void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) { struct orinoco_private *priv = ndev_priv(dev); struct net_device_stats *stats = &priv->stats; @@ -918,6 +918,7 @@ update_stats: out: kfree(desc); } +EXPORT_SYMBOL(__orinoco_ev_rx); static void orinoco_rx(struct net_device *dev, struct hermes_rx_descriptor *desc, @@ -1359,7 +1360,7 @@ static void orinoco_process_scan_results(struct work_struct *work) spin_unlock_irqrestore(&priv->scan_lock, flags); } -static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) +void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) { struct orinoco_private *priv = ndev_priv(dev); u16 infofid; @@ -1577,6 +1578,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) return; } +EXPORT_SYMBOL(__orinoco_ev_info); static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw) { -- cgit v1.2.3 From bac6fafd4d6a0af26aeb37277a39607f7ce0be77 Mon Sep 17 00:00:00 2001 From: David Kilroy Date: Tue, 4 May 2010 22:54:41 +0100 Subject: orinoco: refactor xmit path ... so orinoco_usb can share some common functionality. Handle 802.2 encapsulation and MIC calculation in that function. The 802.3 header is prepended to the SKB. The calculated MIC is written to a specified buffer. Also modify the transmit control word that will be passed onto the hardware to specify whether the MIC is present, and the key used. Signed-off-by: David Kilroy Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/main.c | 169 ++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 63 deletions(-) (limited to 'drivers/net/wireless/orinoco/main.c') diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 7c9faa4c079e..86f268cd89e7 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -339,18 +339,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", @@ -382,16 +473,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 @@ -434,34 +521,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) { @@ -470,32 +529,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); @@ -2234,7 +2277,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); -- cgit v1.2.3 From 1ae5dc342ac78d7a42965fd1f323815f6f5ef2c1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 10 May 2010 05:01:31 -0700 Subject: net: trans_start cleanups Now that core network takes care of trans_start updates, dont do it in drivers themselves, if possible. Drivers can avoid one cache miss (on dev->trans_start) in their start_xmit() handler. Exceptions are NETIF_F_LLTX drivers Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/wireless/orinoco/main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless/orinoco/main.c') diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 1d60c7e4392a..884a7779fc5f 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -517,7 +517,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; -- cgit v1.2.3 From a4b770972b8f819e408d7cc3ae9637e15bff62f6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 14 May 2010 00:19:28 -0700 Subject: drivers/net: Remove unnecessary returns from void function()s This patch removes from drivers/net/ all the unnecessary return; statements that precede the last closing brace of void functions. It does not remove the returns that are immediately preceded by a label as gcc doesn't like that. It also does not remove null void functions with return. Done via: $ grep -rP --include=*.[ch] -l "return;\n}" net/ | \ xargs perl -i -e 'local $/ ; while (<>) { s/\n[ \t\n]+return;\n}/\n}/g; print; }' with some cleanups by hand. Compile tested x86 allmodconfig only. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/wireless/orinoco/main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/wireless/orinoco/main.c') diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 97e954ee17f8..ca71f08709bc 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -1618,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); -- cgit v1.2.3