aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@googlemail.com>2010-05-04 17:54:41 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-05-07 14:55:49 -0400
commitbac6fafd4d6a0af26aeb37277a39607f7ce0be77 (patch)
tree4535874fa3b58249cf4936bb1656fb5759ed28a2 /drivers/net/wireless/orinoco
parent3ef83d745bf5220bef3a0fd11b96eb9ac64c8e8e (diff)
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 <kilroyd@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco')
-rw-r--r--drivers/net/wireless/orinoco/main.c169
-rw-r--r--drivers/net/wireless/orinoco/orinoco.h6
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c91
3 files changed, 155 insertions, 111 deletions
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index 7c9faa4c079..86f268cd89e 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -339,18 +339,109 @@ EXPORT_SYMBOL(orinoco_change_mtu);
339/* Tx path */ 339/* Tx path */
340/********************************************************************/ 340/********************************************************************/
341 341
342/* Add encapsulation and MIC to the existing SKB.
343 * The main xmit routine will then send the whole lot to the card.
344 * Need 8 bytes headroom
345 * Need 8 bytes tailroom
346 *
347 * With encapsulated ethernet II frame
348 * --------
349 * 803.3 header (14 bytes)
350 * dst[6]
351 * -------- src[6]
352 * 803.3 header (14 bytes) len[2]
353 * dst[6] 803.2 header (8 bytes)
354 * src[6] encaps[6]
355 * len[2] <- leave alone -> len[2]
356 * -------- -------- <-- 0
357 * Payload Payload
358 * ... ...
359 *
360 * -------- --------
361 * MIC (8 bytes)
362 * --------
363 *
364 * returns 0 on success, -ENOMEM on error.
365 */
366int orinoco_process_xmit_skb(struct sk_buff *skb,
367 struct net_device *dev,
368 struct orinoco_private *priv,
369 int *tx_control,
370 u8 *mic_buf)
371{
372 struct orinoco_tkip_key *key;
373 struct ethhdr *eh;
374 int do_mic;
375
376 key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key;
377
378 do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) &&
379 (key != NULL));
380
381 if (do_mic)
382 *tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
383 HERMES_TXCTRL_MIC;
384
385 eh = (struct ethhdr *)skb->data;
386
387 /* Encapsulate Ethernet-II frames */
388 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
389 struct header_struct {
390 struct ethhdr eth; /* 802.3 header */
391 u8 encap[6]; /* 802.2 header */
392 } __attribute__ ((packed)) hdr;
393 int len = skb->len + sizeof(encaps_hdr) - (2 * ETH_ALEN);
394
395 if (skb_headroom(skb) < ENCAPS_OVERHEAD) {
396 if (net_ratelimit())
397 printk(KERN_ERR
398 "%s: Not enough headroom for 802.2 headers %d\n",
399 dev->name, skb_headroom(skb));
400 return -ENOMEM;
401 }
402
403 /* Fill in new header */
404 memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
405 hdr.eth.h_proto = htons(len);
406 memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
407
408 /* Make room for the new header, and copy it in */
409 eh = (struct ethhdr *) skb_push(skb, ENCAPS_OVERHEAD);
410 memcpy(eh, &hdr, sizeof(hdr));
411 }
412
413 /* Calculate Michael MIC */
414 if (do_mic) {
415 size_t len = skb->len - ETH_HLEN;
416 u8 *mic = &mic_buf[0];
417
418 /* Have to write to an even address, so copy the spare
419 * byte across */
420 if (skb->len % 2) {
421 *mic = skb->data[skb->len - 1];
422 mic++;
423 }
424
425 orinoco_mic(priv->tx_tfm_mic, key->tx_mic,
426 eh->h_dest, eh->h_source, 0 /* priority */,
427 skb->data + ETH_HLEN,
428 len, mic);
429 }
430
431 return 0;
432}
433EXPORT_SYMBOL(orinoco_process_xmit_skb);
434
342static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) 435static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
343{ 436{
344 struct orinoco_private *priv = ndev_priv(dev); 437 struct orinoco_private *priv = ndev_priv(dev);
345 struct net_device_stats *stats = &priv->stats; 438 struct net_device_stats *stats = &priv->stats;
346 struct orinoco_tkip_key *key;
347 hermes_t *hw = &priv->hw; 439 hermes_t *hw = &priv->hw;
348 int err = 0; 440 int err = 0;
349 u16 txfid = priv->txfid; 441 u16 txfid = priv->txfid;
350 struct ethhdr *eh;
351 int tx_control; 442 int tx_control;
352 unsigned long flags; 443 unsigned long flags;
353 int do_mic; 444 u8 mic_buf[MICHAEL_MIC_LEN+1];
354 445
355 if (!netif_running(dev)) { 446 if (!netif_running(dev)) {
356 printk(KERN_ERR "%s: Tx on stopped device!\n", 447 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)
382 if (skb->len < ETH_HLEN) 473 if (skb->len < ETH_HLEN)
383 goto drop; 474 goto drop;
384 475
385 key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key;
386
387 do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) &&
388 (key != NULL));
389
390 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX; 476 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
391 477
392 if (do_mic) 478 err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control,
393 tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) | 479 &mic_buf[0]);
394 HERMES_TXCTRL_MIC; 480 if (err)
481 goto drop;
395 482
396 if (priv->has_alt_txcntl) { 483 if (priv->has_alt_txcntl) {
397 /* WPA enabled firmwares have tx_cntl at the end of 484 /* 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)
434 HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); 521 HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
435 } 522 }
436 523
437 eh = (struct ethhdr *)skb->data;
438
439 /* Encapsulate Ethernet-II frames */
440 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
441 struct header_struct {
442 struct ethhdr eth; /* 802.3 header */
443 u8 encap[6]; /* 802.2 header */
444 } __attribute__ ((packed)) hdr;
445
446 /* Strip destination and source from the data */
447 skb_pull(skb, 2 * ETH_ALEN);
448
449 /* And move them to a separate header */
450 memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
451 hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);
452 memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
453
454 /* Insert the SNAP header */
455 if (skb_headroom(skb) < sizeof(hdr)) {
456 printk(KERN_ERR
457 "%s: Not enough headroom for 802.2 headers %d\n",
458 dev->name, skb_headroom(skb));
459 goto drop;
460 }
461 eh = (struct ethhdr *) skb_push(skb, sizeof(hdr));
462 memcpy(eh, &hdr, sizeof(hdr));
463 }
464
465 err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len, 524 err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len,
466 txfid, HERMES_802_3_OFFSET); 525 txfid, HERMES_802_3_OFFSET);
467 if (err) { 526 if (err) {
@@ -470,32 +529,16 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
470 goto busy; 529 goto busy;
471 } 530 }
472 531
473 /* Calculate Michael MIC */ 532 if (tx_control & HERMES_TXCTRL_MIC) {
474 if (do_mic) { 533 size_t offset = HERMES_802_3_OFFSET + skb->len;
475 u8 mic_buf[MICHAEL_MIC_LEN + 1]; 534 size_t len = MICHAEL_MIC_LEN;
476 u8 *mic;
477 size_t offset;
478 size_t len;
479 535
480 if (skb->len % 2) { 536 if (offset % 2) {
481 /* MIC start is on an odd boundary */ 537 offset--;
482 mic_buf[0] = skb->data[skb->len - 1]; 538 len++;
483 mic = &mic_buf[1];
484 offset = skb->len - 1;
485 len = MICHAEL_MIC_LEN + 1;
486 } else {
487 mic = &mic_buf[0];
488 offset = skb->len;
489 len = MICHAEL_MIC_LEN;
490 } 539 }
491
492 orinoco_mic(priv->tx_tfm_mic, key->tx_mic,
493 eh->h_dest, eh->h_source, 0 /* priority */,
494 skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
495
496 /* Write the MIC */
497 err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len, 540 err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
498 txfid, HERMES_802_3_OFFSET + offset); 541 txfid, offset);
499 if (err) { 542 if (err) {
500 printk(KERN_ERR "%s: Error %d writing MIC to BAP\n", 543 printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
501 dev->name, err); 544 dev->name, err);
@@ -2234,7 +2277,7 @@ int orinoco_if_add(struct orinoco_private *priv,
2234 /* we use the default eth_mac_addr for setting the MAC addr */ 2277 /* we use the default eth_mac_addr for setting the MAC addr */
2235 2278
2236 /* Reserve space in skb for the SNAP header */ 2279 /* Reserve space in skb for the SNAP header */
2237 dev->hard_header_len += ENCAPS_OVERHEAD; 2280 dev->needed_headroom = ENCAPS_OVERHEAD;
2238 2281
2239 netif_carrier_off(dev); 2282 netif_carrier_off(dev);
2240 2283
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index e9f415a56d4..a6da86e0a70 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);
200extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw); 200extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);
201extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw); 201extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);
202 202
203int orinoco_process_xmit_skb(struct sk_buff *skb,
204 struct net_device *dev,
205 struct orinoco_private *priv,
206 int *tx_control,
207 u8 *mic);
208
203/* Common ndo functions exported for reuse by orinoco_usb */ 209/* Common ndo functions exported for reuse by orinoco_usb */
204int orinoco_open(struct net_device *dev); 210int orinoco_open(struct net_device *dev);
205int orinoco_stop(struct net_device *dev); 211int orinoco_stop(struct net_device *dev);
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index e22093359f3..78f089baa8c 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -67,6 +67,7 @@
67#include <linux/wireless.h> 67#include <linux/wireless.h>
68#include <linux/firmware.h> 68#include <linux/firmware.h>
69 69
70#include "mic.h"
70#include "orinoco.h" 71#include "orinoco.h"
71 72
72#ifndef URB_ASYNC_UNLINK 73#ifndef URB_ASYNC_UNLINK
@@ -1198,11 +1199,9 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
1198 struct orinoco_private *priv = ndev_priv(dev); 1199 struct orinoco_private *priv = ndev_priv(dev);
1199 struct net_device_stats *stats = &priv->stats; 1200 struct net_device_stats *stats = &priv->stats;
1200 struct ezusb_priv *upriv = priv->card; 1201 struct ezusb_priv *upriv = priv->card;
1202 u8 mic[MICHAEL_MIC_LEN+1];
1201 int err = 0; 1203 int err = 0;
1202 char *p; 1204 int tx_control;
1203 struct ethhdr *eh;
1204 int len, data_len, data_off;
1205 __le16 tx_control;
1206 unsigned long flags; 1205 unsigned long flags;
1207 struct request_context *ctx; 1206 struct request_context *ctx;
1208 u8 *buf; 1207 u8 *buf;
@@ -1222,7 +1221,7 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
1222 1221
1223 if (orinoco_lock(priv, &flags) != 0) { 1222 if (orinoco_lock(priv, &flags) != 0) {
1224 printk(KERN_ERR 1223 printk(KERN_ERR
1225 "%s: orinoco_xmit() called while hw_unavailable\n", 1224 "%s: ezusb_xmit() called while hw_unavailable\n",
1226 dev->name); 1225 dev->name);
1227 return NETDEV_TX_BUSY; 1226 return NETDEV_TX_BUSY;
1228 } 1227 }
@@ -1232,53 +1231,46 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
1232 /* Oops, the firmware hasn't established a connection, 1231 /* Oops, the firmware hasn't established a connection,
1233 silently drop the packet (this seems to be the 1232 silently drop the packet (this seems to be the
1234 safest approach). */ 1233 safest approach). */
1235 stats->tx_errors++; 1234 goto drop;
1236 orinoco_unlock(priv, &flags);
1237 dev_kfree_skb(skb);
1238 return NETDEV_TX_OK;
1239 } 1235 }
1240 1236
1237 /* Check packet length */
1238 if (skb->len < ETH_HLEN)
1239 goto drop;
1240
1241 ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0); 1241 ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0);
1242 if (!ctx) 1242 if (!ctx)
1243 goto fail; 1243 goto busy;
1244 1244
1245 memset(ctx->buf, 0, BULK_BUF_SIZE); 1245 memset(ctx->buf, 0, BULK_BUF_SIZE);
1246 buf = ctx->buf->data; 1246 buf = ctx->buf->data;
1247 1247
1248 /* Length of the packet body */ 1248 tx_control = 0;
1249 /* FIXME: what if the skb is smaller than this? */ 1249
1250 len = max_t(int, skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN); 1250 err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control,
1251 1251 &mic[0]);
1252 eh = (struct ethhdr *) skb->data; 1252 if (err)
1253 1253 goto drop;
1254 tx_control = cpu_to_le16(0); 1254
1255 memcpy(buf, &tx_control, sizeof(tx_control)); 1255 {
1256 buf += sizeof(tx_control); 1256 __le16 *tx_cntl = (__le16 *)buf;
1257 /* Encapsulate Ethernet-II frames */ 1257 *tx_cntl = cpu_to_le16(tx_control);
1258 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ 1258 buf += sizeof(*tx_cntl);
1259 struct header_struct *hdr = (void *) buf;
1260 buf += sizeof(*hdr);
1261 data_len = len;
1262 data_off = sizeof(tx_control) + sizeof(*hdr);
1263 p = skb->data + ETH_HLEN;
1264
1265 /* 802.3 header */
1266 memcpy(hdr->dest, eh->h_dest, ETH_ALEN);
1267 memcpy(hdr->src, eh->h_source, ETH_ALEN);
1268 hdr->len = htons(data_len + ENCAPS_OVERHEAD);
1269
1270 /* 802.2 header */
1271 memcpy(&hdr->dsap, &encaps_hdr, sizeof(encaps_hdr));
1272
1273 hdr->ethertype = eh->h_proto;
1274 } else { /* IEEE 802.3 frame */
1275 data_len = len + ETH_HLEN;
1276 data_off = sizeof(tx_control);
1277 p = skb->data;
1278 } 1259 }
1279 1260
1280 memcpy(buf, p, data_len); 1261 memcpy(buf, skb->data, skb->len);
1281 buf += data_len; 1262 buf += skb->len;
1263
1264 if (tx_control & HERMES_TXCTRL_MIC) {
1265 u8 *m = mic;
1266 /* Mic has been offset so it can be copied to an even
1267 * address. We're copying eveything anyway, so we
1268 * don't need to copy that first byte. */
1269 if (skb->len % 2)
1270 m++;
1271 memcpy(buf, m, MICHAEL_MIC_LEN);
1272 buf += MICHAEL_MIC_LEN;
1273 }
1282 1274
1283 /* Finally, we actually initiate the send */ 1275 /* Finally, we actually initiate the send */
1284 netif_stop_queue(dev); 1276 netif_stop_queue(dev);
@@ -1294,20 +1286,23 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
1294 if (net_ratelimit()) 1286 if (net_ratelimit())
1295 printk(KERN_ERR "%s: Error %d transmitting packet\n", 1287 printk(KERN_ERR "%s: Error %d transmitting packet\n",
1296 dev->name, err); 1288 dev->name, err);
1297 stats->tx_errors++; 1289 goto busy;
1298 goto fail;
1299 } 1290 }
1300 1291
1301 dev->trans_start = jiffies; 1292 dev->trans_start = jiffies;
1302 stats->tx_bytes += data_off + data_len; 1293 stats->tx_bytes += skb->len;
1294 goto ok;
1303 1295
1304 orinoco_unlock(priv, &flags); 1296 drop:
1297 stats->tx_errors++;
1298 stats->tx_dropped++;
1305 1299
1300 ok:
1301 orinoco_unlock(priv, &flags);
1306 dev_kfree_skb(skb); 1302 dev_kfree_skb(skb);
1307
1308 return NETDEV_TX_OK; 1303 return NETDEV_TX_OK;
1309 1304
1310 fail: 1305 busy:
1311 orinoco_unlock(priv, &flags); 1306 orinoco_unlock(priv, &flags);
1312 return NETDEV_TX_BUSY; 1307 return NETDEV_TX_BUSY;
1313} 1308}