Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem

Conflicts:
	drivers/net/wireless/ath/ar9170/main.c
This commit is contained in:
John W. Linville
2010-05-11 14:24:55 -04:00
63 changed files with 1367 additions and 1510 deletions

View File

@@ -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);
@@ -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);