diff options
author | David S. Miller <davem@davemloft.net> | 2015-06-23 01:03:18 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-06-23 01:03:18 -0700 |
commit | fa433354f042105fc7a299253f904bb48dae0950 (patch) | |
tree | 7dc747d4f994713699a37080b0774f8315a1e1ef /drivers/net/wireless/mediatek | |
parent | 10ea5165e44ec8467e393a84ecfbf5732605d504 (diff) | |
parent | 40b503c76481aecf811a29a14a80c13b429b5e14 (diff) | |
download | lwn-fa433354f042105fc7a299253f904bb48dae0950.tar.gz lwn-fa433354f042105fc7a299253f904bb48dae0950.zip |
Merge tag 'wireless-drivers-next-for-davem-2015-06-18' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says:
====================
Major changes:
mwifiex:
* enhancements for AP mode: support verbose information in station
dump command and also information about AP link.
* enable power save by default
brcmfmac:
* fix module reload issue for PCIe
* improving msgbuf protocol for PCIe devices
* rework .get_station() cfg80211 callback operation
* determine interface combinations upon device feature support
ath9k:
* ath9k_htc: add support of channel switch
wil6210:
* add modparam for bcast ring size
* support hidden SSID
* add per-MCS Rx stats
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/mediatek')
-rw-r--r-- | drivers/net/wireless/mediatek/mt7601u/dma.c | 74 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt7601u/eeprom.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt7601u/init.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt7601u/mac.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt7601u/main.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt7601u/usb.c | 9 |
6 files changed, 45 insertions, 54 deletions
diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c index 9c9e1288644b..7217da4f1543 100644 --- a/drivers/net/wireless/mediatek/mt7601u/dma.c +++ b/drivers/net/wireless/mediatek/mt7601u/dma.c @@ -34,56 +34,32 @@ static unsigned int ieee80211_get_hdrlen_from_buf(const u8 *data, unsigned len) static struct sk_buff * mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi, - u8 *data, u32 seg_len) + void *data, u32 seg_len, u32 truesize, struct page *p) { struct sk_buff *skb; - u32 true_len; + u32 true_len, hdr_len = 0, copy, frag; - if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) - seg_len -= 2; - - skb = alloc_skb(seg_len, GFP_ATOMIC); - if (!skb) - return NULL; - - if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) { - int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len); - - memcpy(skb_put(skb, hdr_len), data, hdr_len); - data += hdr_len + 2; - seg_len -= hdr_len; - } - - memcpy(skb_put(skb, seg_len), data, seg_len); - - true_len = mt76_mac_process_rx(dev, skb, skb->data, rxwi); - skb_trim(skb, true_len); - - return skb; -} - -static struct sk_buff * -mt7601u_rx_skb_from_seg_paged(struct mt7601u_dev *dev, - struct mt7601u_rxwi *rxwi, void *data, - u32 seg_len, u32 truesize, struct page *p) -{ - unsigned int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len); - unsigned int true_len, copy, frag; - struct sk_buff *skb; - - skb = alloc_skb(128, GFP_ATOMIC); + skb = alloc_skb(p ? 128 : seg_len, GFP_ATOMIC); if (!skb) return NULL; true_len = mt76_mac_process_rx(dev, skb, data, rxwi); + if (!true_len || true_len > seg_len) + goto bad_frame; + + hdr_len = ieee80211_get_hdrlen_from_buf(data, true_len); + if (!hdr_len) + goto bad_frame; if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) { memcpy(skb_put(skb, hdr_len), data, hdr_len); + data += hdr_len + 2; true_len -= hdr_len; hdr_len = 0; } + /* If not doing paged RX allocated skb will always have enough space */ copy = (true_len <= skb_tailroom(skb)) ? true_len : hdr_len + 8; frag = true_len - copy; @@ -97,10 +73,16 @@ mt7601u_rx_skb_from_seg_paged(struct mt7601u_dev *dev, } return skb; + +bad_frame: + dev_err_ratelimited(dev->dev, "Error: incorrect frame len:%u hdr:%u\n", + true_len, hdr_len); + dev_kfree_skb(skb); + return NULL; } static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data, - u32 seg_len, struct page *p, bool paged) + u32 seg_len, struct page *p) { struct sk_buff *skb; struct mt7601u_rxwi *rxwi; @@ -126,11 +108,7 @@ static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data, trace_mt_rx(dev, rxwi, fce_info); - if (paged) - skb = mt7601u_rx_skb_from_seg_paged(dev, rxwi, data, seg_len, - truesize, p); - else - skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len); + skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len, truesize, p); if (!skb) return; @@ -158,23 +136,17 @@ mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e) u32 seg_len, data_len = e->urb->actual_length; u8 *data = page_address(e->p); struct page *new_p = NULL; - bool paged = true; int cnt = 0; if (!test_bit(MT7601U_STATE_INITIALIZED, &dev->state)) return; /* Copy if there is very little data in the buffer. */ - if (data_len < 512) { - paged = false; - } else { + if (data_len > 512) new_p = dev_alloc_pages(MT_RX_ORDER); - if (!new_p) - paged = false; - } while ((seg_len = mt7601u_rx_next_seg_len(data, data_len))) { - mt7601u_rx_process_seg(dev, data, seg_len, e->p, paged); + mt7601u_rx_process_seg(dev, data, seg_len, new_p ? e->p : NULL); data_len -= seg_len; data += seg_len; @@ -182,9 +154,9 @@ mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e) } if (cnt > 1) - trace_mt_rx_dma_aggr(dev, cnt, paged); + trace_mt_rx_dma_aggr(dev, cnt, !!new_p); - if (paged) { + if (new_p) { /* we have one extra ref from the allocator */ __free_pages(e->p, MT_RX_ORDER); diff --git a/drivers/net/wireless/mediatek/mt7601u/eeprom.c b/drivers/net/wireless/mediatek/mt7601u/eeprom.c index ce3837f270f0..8d8ee0344f7b 100644 --- a/drivers/net/wireless/mediatek/mt7601u/eeprom.c +++ b/drivers/net/wireless/mediatek/mt7601u/eeprom.c @@ -277,6 +277,10 @@ mt7601u_extra_power_over_mac(struct mt7601u_dev *dev) static void mt7601u_set_power_rate(struct power_per_rate *rate, s8 delta, u8 value) { + /* Invalid? Note: vendor driver does not handle this */ + if (value == 0xff) + return; + rate->raw = s6_validate(value); rate->bw20 = s6_to_int(value); /* Note: vendor driver does cap the value to s6 right away */ diff --git a/drivers/net/wireless/mediatek/mt7601u/init.c b/drivers/net/wireless/mediatek/mt7601u/init.c index ca1ea2e55ff4..df3dd56199a7 100644 --- a/drivers/net/wireless/mediatek/mt7601u/init.c +++ b/drivers/net/wireless/mediatek/mt7601u/init.c @@ -427,6 +427,9 @@ err: void mt7601u_cleanup(struct mt7601u_dev *dev) { + if (!test_and_clear_bit(MT7601U_STATE_INITIALIZED, &dev->state)) + return; + mt7601u_stop_hardware(dev); mt7601u_dma_cleanup(dev); mt7601u_mcu_cmd_deinit(dev); diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.c b/drivers/net/wireless/mediatek/mt7601u/mac.c index c161bcc6a7fa..7514bce1ac91 100644 --- a/drivers/net/wireless/mediatek/mt7601u/mac.c +++ b/drivers/net/wireless/mediatek/mt7601u/mac.c @@ -450,10 +450,14 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb, { struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct mt7601u_rxwi *rxwi = rxi; - u32 ctl = le32_to_cpu(rxwi->ctl); + u32 len, ctl = le32_to_cpu(rxwi->ctl); u16 rate = le16_to_cpu(rxwi->rate); int rssi; + len = MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl); + if (len < 10) + return 0; + if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) { status->flag |= RX_FLAG_DECRYPTED; status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; @@ -474,7 +478,7 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb, dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8); spin_unlock_bh(&dev->con_mon_lock); - return MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl); + return len; } static enum mt76_cipher_type diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c index ced82abb414f..169384b48b27 100644 --- a/drivers/net/wireless/mediatek/mt7601u/main.c +++ b/drivers/net/wireless/mediatek/mt7601u/main.c @@ -119,6 +119,7 @@ mt76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS; + MT76_FILTER(OTHER_BSS, MT_RX_FILTR_CFG_PROMISC); MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR); MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR); MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK | diff --git a/drivers/net/wireless/mediatek/mt7601u/usb.c b/drivers/net/wireless/mediatek/mt7601u/usb.c index 99e2b3997bfa..54dba4001865 100644 --- a/drivers/net/wireless/mediatek/mt7601u/usb.c +++ b/drivers/net/wireless/mediatek/mt7601u/usb.c @@ -338,8 +338,15 @@ static int mt7601u_suspend(struct usb_interface *usb_intf, pm_message_t state) static int mt7601u_resume(struct usb_interface *usb_intf) { struct mt7601u_dev *dev = usb_get_intfdata(usb_intf); + int ret; + + ret = mt7601u_init_hardware(dev); + if (ret) + return ret; + + set_bit(MT7601U_STATE_INITIALIZED, &dev->state); - return mt7601u_init_hardware(dev); + return 0; } MODULE_DEVICE_TABLE(usb, mt7601u_device_table); |