aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54/p54common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/p54/p54common.c')
-rw-r--r--drivers/net/wireless/p54/p54common.c60
1 files changed, 50 insertions, 10 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 82354b974a04..34561e6e816b 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -138,6 +138,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
138 u8 *fw_version = NULL; 138 u8 *fw_version = NULL;
139 size_t len; 139 size_t len;
140 int i; 140 int i;
141 int maxlen;
141 142
142 if (priv->rx_start) 143 if (priv->rx_start)
143 return 0; 144 return 0;
@@ -195,6 +196,16 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
195 else 196 else
196 priv->rx_mtu = (size_t) 197 priv->rx_mtu = (size_t)
197 0x620 - priv->tx_hdr_len; 198 0x620 - priv->tx_hdr_len;
199 maxlen = priv->tx_hdr_len + /* USB devices */
200 sizeof(struct p54_rx_data) +
201 4 + /* rx alignment */
202 IEEE80211_MAX_FRAG_THRESHOLD;
203 if (priv->rx_mtu > maxlen && PAGE_SIZE == 4096) {
204 printk(KERN_INFO "p54: rx_mtu reduced from %d "
205 "to %d\n", priv->rx_mtu,
206 maxlen);
207 priv->rx_mtu = maxlen;
208 }
198 break; 209 break;
199 } 210 }
200 case BR_CODE_EXPOSED_IF: 211 case BR_CODE_EXPOSED_IF:
@@ -440,8 +451,8 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
440 } 451 }
441 if (err) 452 if (err)
442 goto err; 453 goto err;
443 454 }
444 } 455 break;
445 case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: 456 case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
446 priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); 457 priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
447 if (!priv->iq_autocal) { 458 if (!priv->iq_autocal) {
@@ -575,6 +586,7 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
575 u16 freq = le16_to_cpu(hdr->freq); 586 u16 freq = le16_to_cpu(hdr->freq);
576 size_t header_len = sizeof(*hdr); 587 size_t header_len = sizeof(*hdr);
577 u32 tsf32; 588 u32 tsf32;
589 u8 rate = hdr->rate & 0xf;
578 590
579 /* 591 /*
580 * If the device is in a unspecified state we have to 592 * If the device is in a unspecified state we have to
@@ -603,8 +615,11 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
603 rx_status.qual = (100 * hdr->rssi) / 127; 615 rx_status.qual = (100 * hdr->rssi) / 127;
604 if (hdr->rate & 0x10) 616 if (hdr->rate & 0x10)
605 rx_status.flag |= RX_FLAG_SHORTPRE; 617 rx_status.flag |= RX_FLAG_SHORTPRE;
606 rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ? 618 if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
607 hdr->rate : (hdr->rate - 4)) & 0xf; 619 rx_status.rate_idx = (rate < 4) ? 0 : rate - 4;
620 else
621 rx_status.rate_idx = rate;
622
608 rx_status.freq = freq; 623 rx_status.freq = freq;
609 rx_status.band = dev->conf.channel->band; 624 rx_status.band = dev->conf.channel->band;
610 rx_status.antenna = hdr->antenna; 625 rx_status.antenna = hdr->antenna;
@@ -730,7 +745,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
730 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); 745 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
731 struct p54_hdr *entry_hdr; 746 struct p54_hdr *entry_hdr;
732 struct p54_tx_data *entry_data; 747 struct p54_tx_data *entry_data;
733 int pad = 0; 748 unsigned int pad = 0, frame_len;
734 749
735 range = (void *)info->rate_driver_data; 750 range = (void *)info->rate_driver_data;
736 if (range->start_addr != addr) { 751 if (range->start_addr != addr) {
@@ -753,6 +768,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
753 __skb_unlink(entry, &priv->tx_queue); 768 __skb_unlink(entry, &priv->tx_queue);
754 spin_unlock_irqrestore(&priv->tx_queue.lock, flags); 769 spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
755 770
771 frame_len = entry->len;
756 entry_hdr = (struct p54_hdr *) entry->data; 772 entry_hdr = (struct p54_hdr *) entry->data;
757 entry_data = (struct p54_tx_data *) entry_hdr->data; 773 entry_data = (struct p54_tx_data *) entry_hdr->data;
758 priv->tx_stats[entry_data->hw_queue].len--; 774 priv->tx_stats[entry_data->hw_queue].len--;
@@ -798,6 +814,29 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
798 info->flags |= IEEE80211_TX_STAT_TX_FILTERED; 814 info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
799 info->status.ack_signal = p54_rssi_to_dbm(dev, 815 info->status.ack_signal = p54_rssi_to_dbm(dev,
800 (int)payload->ack_rssi); 816 (int)payload->ack_rssi);
817
818 /* Undo all changes to the frame. */
819 switch (entry_data->key_type) {
820 case P54_CRYPTO_TKIPMICHAEL: {
821 u8 *iv = (u8 *)(entry_data->align + pad +
822 entry_data->crypt_offset);
823
824 /* Restore the original TKIP IV. */
825 iv[2] = iv[0];
826 iv[0] = iv[1];
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;
838 }
839 skb_trim(entry, frame_len);
801 skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); 840 skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
802 ieee80211_tx_status_irqsafe(dev, entry); 841 ieee80211_tx_status_irqsafe(dev, entry);
803 goto out; 842 goto out;
@@ -1122,7 +1161,7 @@ static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
1122 1161
1123 skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, 1162 skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET,
1124 sizeof(struct p54_hdr) + sizeof(*tim), 1163 sizeof(struct p54_hdr) + sizeof(*tim),
1125 P54_CONTROL_TYPE_TIM, GFP_KERNEL); 1164 P54_CONTROL_TYPE_TIM, GFP_ATOMIC);
1126 if (!skb) 1165 if (!skb)
1127 return -ENOMEM; 1166 return -ENOMEM;
1128 1167
@@ -1383,7 +1422,6 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
1383 hdr->tries = ridx; 1422 hdr->tries = ridx;
1384 txhdr->rts_rate_idx = 0; 1423 txhdr->rts_rate_idx = 0;
1385 if (info->control.hw_key) { 1424 if (info->control.hw_key) {
1386 crypt_offset += info->control.hw_key->iv_len;
1387 txhdr->key_type = p54_convert_algo(info->control.hw_key->alg); 1425 txhdr->key_type = p54_convert_algo(info->control.hw_key->alg);
1388 txhdr->key_len = min((u8)16, info->control.hw_key->keylen); 1426 txhdr->key_len = min((u8)16, info->control.hw_key->keylen);
1389 memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len); 1427 memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len);
@@ -1397,6 +1435,8 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
1397 } 1435 }
1398 /* reserve some space for ICV */ 1436 /* reserve some space for ICV */
1399 len += info->control.hw_key->icv_len; 1437 len += info->control.hw_key->icv_len;
1438 memset(skb_put(skb, info->control.hw_key->icv_len), 0,
1439 info->control.hw_key->icv_len);
1400 } else { 1440 } else {
1401 txhdr->key_type = 0; 1441 txhdr->key_type = 0;
1402 txhdr->key_len = 0; 1442 txhdr->key_len = 0;
@@ -1584,7 +1624,7 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell)
1584 1624
1585 err: 1625 err:
1586 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));
1587 kfree_skb(skb); 1627 p54_free_skb(dev, skb);
1588 return -EINVAL; 1628 return -EINVAL;
1589} 1629}
1590 1630
@@ -1824,7 +1864,7 @@ static void p54_remove_interface(struct ieee80211_hw *dev,
1824 1864
1825static int p54_config(struct ieee80211_hw *dev, u32 changed) 1865static int p54_config(struct ieee80211_hw *dev, u32 changed)
1826{ 1866{
1827 int ret; 1867 int ret = 0;
1828 struct p54_common *priv = dev->priv; 1868 struct p54_common *priv = dev->priv;
1829 struct ieee80211_conf *conf = &dev->conf; 1869 struct ieee80211_conf *conf = &dev->conf;
1830 1870
@@ -2051,7 +2091,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
2051 algo = P54_CRYPTO_AESCCMP; 2091 algo = P54_CRYPTO_AESCCMP;
2052 break; 2092 break;
2053 default: 2093 default:
2054 return -EINVAL; 2094 return -EOPNOTSUPP;
2055 } 2095 }
2056 } 2096 }
2057 2097