diff options
Diffstat (limited to 'drivers/net/wireless/p54/p54common.c')
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index c6a370fa9bcb..34561e6e816b 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -451,8 +451,8 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
451 | } | 451 | } |
452 | if (err) | 452 | if (err) |
453 | goto err; | 453 | goto err; |
454 | 454 | } | |
455 | } | 455 | break; |
456 | case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: | 456 | case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: |
457 | priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); | 457 | priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); |
458 | if (!priv->iq_autocal) { | 458 | if (!priv->iq_autocal) { |
@@ -745,7 +745,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
745 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); | 745 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); |
746 | struct p54_hdr *entry_hdr; | 746 | struct p54_hdr *entry_hdr; |
747 | struct p54_tx_data *entry_data; | 747 | struct p54_tx_data *entry_data; |
748 | int pad = 0; | 748 | unsigned int pad = 0, frame_len; |
749 | 749 | ||
750 | range = (void *)info->rate_driver_data; | 750 | range = (void *)info->rate_driver_data; |
751 | if (range->start_addr != addr) { | 751 | if (range->start_addr != addr) { |
@@ -768,6 +768,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
768 | __skb_unlink(entry, &priv->tx_queue); | 768 | __skb_unlink(entry, &priv->tx_queue); |
769 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | 769 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); |
770 | 770 | ||
771 | frame_len = entry->len; | ||
771 | entry_hdr = (struct p54_hdr *) entry->data; | 772 | entry_hdr = (struct p54_hdr *) entry->data; |
772 | entry_data = (struct p54_tx_data *) entry_hdr->data; | 773 | entry_data = (struct p54_tx_data *) entry_hdr->data; |
773 | priv->tx_stats[entry_data->hw_queue].len--; | 774 | priv->tx_stats[entry_data->hw_queue].len--; |
@@ -814,15 +815,28 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
814 | info->status.ack_signal = p54_rssi_to_dbm(dev, | 815 | info->status.ack_signal = p54_rssi_to_dbm(dev, |
815 | (int)payload->ack_rssi); | 816 | (int)payload->ack_rssi); |
816 | 817 | ||
817 | if (entry_data->key_type == P54_CRYPTO_TKIPMICHAEL) { | 818 | /* Undo all changes to the frame. */ |
819 | switch (entry_data->key_type) { | ||
820 | case P54_CRYPTO_TKIPMICHAEL: { | ||
818 | u8 *iv = (u8 *)(entry_data->align + pad + | 821 | u8 *iv = (u8 *)(entry_data->align + pad + |
819 | entry_data->crypt_offset); | 822 | entry_data->crypt_offset); |
820 | 823 | ||
821 | /* Restore the original TKIP IV. */ | 824 | /* Restore the original TKIP IV. */ |
822 | iv[2] = iv[0]; | 825 | iv[2] = iv[0]; |
823 | iv[0] = iv[1]; | 826 | iv[0] = iv[1]; |
824 | iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */ | 827 | iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */ |
828 | |||
829 | frame_len -= 12; /* remove TKIP_MMIC + TKIP_ICV */ | ||
830 | break; | ||
831 | } | ||
832 | case P54_CRYPTO_AESCCMP: | ||
833 | frame_len -= 8; /* remove CCMP_MIC */ | ||
834 | break; | ||
835 | case P54_CRYPTO_WEP: | ||
836 | frame_len -= 4; /* remove WEP_ICV */ | ||
837 | break; | ||
825 | } | 838 | } |
839 | skb_trim(entry, frame_len); | ||
826 | skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); | 840 | skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); |
827 | ieee80211_tx_status_irqsafe(dev, entry); | 841 | ieee80211_tx_status_irqsafe(dev, entry); |
828 | goto out; | 842 | goto out; |
@@ -1147,7 +1161,7 @@ static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, | |||
1147 | 1161 | ||
1148 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, | 1162 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, |
1149 | sizeof(struct p54_hdr) + sizeof(*tim), | 1163 | sizeof(struct p54_hdr) + sizeof(*tim), |
1150 | P54_CONTROL_TYPE_TIM, GFP_KERNEL); | 1164 | P54_CONTROL_TYPE_TIM, GFP_ATOMIC); |
1151 | if (!skb) | 1165 | if (!skb) |
1152 | return -ENOMEM; | 1166 | return -ENOMEM; |
1153 | 1167 | ||
@@ -1610,7 +1624,7 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) | |||
1610 | 1624 | ||
1611 | err: | 1625 | err: |
1612 | printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy)); | 1626 | printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy)); |
1613 | kfree_skb(skb); | 1627 | p54_free_skb(dev, skb); |
1614 | return -EINVAL; | 1628 | return -EINVAL; |
1615 | } | 1629 | } |
1616 | 1630 | ||
@@ -2077,7 +2091,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
2077 | algo = P54_CRYPTO_AESCCMP; | 2091 | algo = P54_CRYPTO_AESCCMP; |
2078 | break; | 2092 | break; |
2079 | default: | 2093 | default: |
2080 | return -EINVAL; | 2094 | return -EOPNOTSUPP; |
2081 | } | 2095 | } |
2082 | } | 2096 | } |
2083 | 2097 | ||