diff options
Diffstat (limited to 'drivers/net/wireless/orinoco/orinoco_usb.c')
-rw-r--r-- | drivers/net/wireless/orinoco/orinoco_usb.c | 91 |
1 files changed, 43 insertions, 48 deletions
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 @@ | |||
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 | } |