Commit af5399b2 authored by Kalle Valo's avatar Kalle Valo

Merge tag 'mt76-for-kvalo-2019-02-18' of https://github.com/nbd168/wireless

mt76 patches for 5.1

* beacon support for USB devices (mesh+ad-hoc only)
* mt76x0 tx power fixes
* fixes for encryption, calibration and ED/CCA
* more code unification
* USB fixes
* fix for using the correct hweight8 function
parents f77ecde5 9f688473
...@@ -4,7 +4,8 @@ obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o ...@@ -4,7 +4,8 @@ obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o
obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o
mt76-y := \ mt76-y := \
mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o tx.o agg-rx.o mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \
tx.o agg-rx.o mcu.o
mt76-usb-y := usb.o usb_trace.o usb_mcu.o mt76-usb-y := usb.o usb_trace.o usb_mcu.o
......
...@@ -242,6 +242,30 @@ mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) ...@@ -242,6 +242,30 @@ mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
iowrite32(q->head, &q->regs->cpu_idx); iowrite32(q->head, &q->regs->cpu_idx);
} }
static int
mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid,
struct sk_buff *skb, u32 tx_info)
{
struct mt76_queue *q = &dev->q_tx[qid];
struct mt76_queue_buf buf;
dma_addr_t addr;
addr = dma_map_single(dev->dev, skb->data, skb->len,
DMA_TO_DEVICE);
if (dma_mapping_error(dev->dev, addr))
return -ENOMEM;
buf.addr = addr;
buf.len = skb->len;
spin_lock_bh(&q->lock);
mt76_dma_add_buf(dev, q, &buf, 1, tx_info, skb, NULL);
mt76_dma_kick_queue(dev, q);
spin_unlock_bh(&q->lock);
return 0;
}
int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
struct sk_buff *skb, struct mt76_wcid *wcid, struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
...@@ -522,17 +546,16 @@ mt76_dma_init(struct mt76_dev *dev) ...@@ -522,17 +546,16 @@ mt76_dma_init(struct mt76_dev *dev)
static const struct mt76_queue_ops mt76_dma_ops = { static const struct mt76_queue_ops mt76_dma_ops = {
.init = mt76_dma_init, .init = mt76_dma_init,
.alloc = mt76_dma_alloc_queue, .alloc = mt76_dma_alloc_queue,
.add_buf = mt76_dma_add_buf, .tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw,
.tx_queue_skb = mt76_dma_tx_queue_skb, .tx_queue_skb = mt76_dma_tx_queue_skb,
.tx_cleanup = mt76_dma_tx_cleanup, .tx_cleanup = mt76_dma_tx_cleanup,
.rx_reset = mt76_dma_rx_reset, .rx_reset = mt76_dma_rx_reset,
.kick = mt76_dma_kick_queue, .kick = mt76_dma_kick_queue,
}; };
int mt76_dma_attach(struct mt76_dev *dev) void mt76_dma_attach(struct mt76_dev *dev)
{ {
dev->queue_ops = &mt76_dma_ops; dev->queue_ops = &mt76_dma_ops;
return 0;
} }
EXPORT_SYMBOL_GPL(mt76_dma_attach); EXPORT_SYMBOL_GPL(mt76_dma_attach);
......
...@@ -54,7 +54,7 @@ enum mt76_mcu_evt_type { ...@@ -54,7 +54,7 @@ enum mt76_mcu_evt_type {
EVT_EVENT_DFS_DETECT_RSP, EVT_EVENT_DFS_DETECT_RSP,
}; };
int mt76_dma_attach(struct mt76_dev *dev); void mt76_dma_attach(struct mt76_dev *dev);
void mt76_dma_cleanup(struct mt76_dev *dev); void mt76_dma_cleanup(struct mt76_dev *dev);
#endif #endif
...@@ -124,7 +124,7 @@ static void mt76_init_stream_cap(struct mt76_dev *dev, ...@@ -124,7 +124,7 @@ static void mt76_init_stream_cap(struct mt76_dev *dev,
bool vht) bool vht)
{ {
struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
int i, nstream = __sw_hweight8(dev->antenna_mask); int i, nstream = hweight8(dev->antenna_mask);
struct ieee80211_sta_vht_cap *vht_cap; struct ieee80211_sta_vht_cap *vht_cap;
u16 mcs_map = 0; u16 mcs_map = 0;
...@@ -269,7 +269,9 @@ mt76_check_sband(struct mt76_dev *dev, int band) ...@@ -269,7 +269,9 @@ mt76_check_sband(struct mt76_dev *dev, int band)
} }
struct mt76_dev * struct mt76_dev *
mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops) mt76_alloc_device(struct device *pdev, unsigned int size,
const struct ieee80211_ops *ops,
const struct mt76_driver_ops *drv_ops)
{ {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct mt76_dev *dev; struct mt76_dev *dev;
...@@ -280,6 +282,9 @@ mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops) ...@@ -280,6 +282,9 @@ mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops)
dev = hw->priv; dev = hw->priv;
dev->hw = hw; dev->hw = hw;
dev->dev = pdev;
dev->drv = drv_ops;
spin_lock_init(&dev->rx_lock); spin_lock_init(&dev->rx_lock);
spin_lock_init(&dev->lock); spin_lock_init(&dev->lock);
spin_lock_init(&dev->cc_lock); spin_lock_init(&dev->cc_lock);
...@@ -721,7 +726,7 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -721,7 +726,7 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int *dbm) int *dbm)
{ {
struct mt76_dev *dev = hw->priv; struct mt76_dev *dev = hw->priv;
int n_chains = __sw_hweight8(dev->antenna_mask); int n_chains = hweight8(dev->antenna_mask);
*dbm = dev->txpower_cur / 2; *dbm = dev->txpower_cur / 2;
......
/*
* Copyright (C) 2019 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "mt76.h"
struct sk_buff *
mt76_mcu_msg_alloc(const void *data, int head_len,
int data_len, int tail_len)
{
struct sk_buff *skb;
skb = alloc_skb(head_len + data_len + tail_len,
GFP_KERNEL);
if (!skb)
return NULL;
skb_reserve(skb, head_len);
if (data && data_len)
skb_put_data(skb, data, data_len);
return skb;
}
EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc);
/* mmio */
struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
unsigned long expires)
{
unsigned long timeout;
if (!time_is_after_jiffies(expires))
return NULL;
timeout = expires - jiffies;
wait_event_timeout(dev->mmio.mcu.wait,
!skb_queue_empty(&dev->mmio.mcu.res_q),
timeout);
return skb_dequeue(&dev->mmio.mcu.res_q);
}
EXPORT_SYMBOL_GPL(mt76_mcu_get_response);
void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb)
{
skb_queue_tail(&dev->mmio.mcu.res_q, skb);
wake_up(&dev->mmio.mcu.wait);
}
EXPORT_SYMBOL_GPL(mt76_mcu_rx_event);
...@@ -87,6 +87,7 @@ struct mt76u_buf { ...@@ -87,6 +87,7 @@ struct mt76u_buf {
struct mt76_dev *dev; struct mt76_dev *dev;
struct urb *urb; struct urb *urb;
size_t len; size_t len;
void *buf;
bool done; bool done;
}; };
...@@ -157,6 +158,9 @@ struct mt76_queue_ops { ...@@ -157,6 +158,9 @@ struct mt76_queue_ops {
struct sk_buff *skb, struct mt76_wcid *wcid, struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
int (*tx_queue_skb_raw)(struct mt76_dev *dev, enum mt76_txq_id qid,
struct sk_buff *skb, u32 tx_info);
void *(*dequeue)(struct mt76_dev *dev, struct mt76_queue *q, bool flush, void *(*dequeue)(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
int *len, u32 *info, bool *more); int *len, u32 *info, bool *more);
...@@ -376,6 +380,7 @@ struct mt76_usb { ...@@ -376,6 +380,7 @@ struct mt76_usb {
u16 out_max_packet; u16 out_max_packet;
u8 in_ep[__MT_EP_IN_MAX]; u8 in_ep[__MT_EP_IN_MAX];
u16 in_max_packet; u16 in_max_packet;
bool sg_en;
struct mt76u_mcu { struct mt76u_mcu {
struct mutex mutex; struct mutex mutex;
...@@ -562,7 +567,7 @@ static inline u16 mt76_rev(struct mt76_dev *dev) ...@@ -562,7 +567,7 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
#define mt76_init_queues(dev) (dev)->mt76.queue_ops->init(&((dev)->mt76)) #define mt76_init_queues(dev) (dev)->mt76.queue_ops->init(&((dev)->mt76))
#define mt76_queue_alloc(dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_alloc(dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_add_buf(dev, ...) (dev)->mt76.queue_ops->add_buf(&((dev)->mt76), __VA_ARGS__) #define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)
...@@ -582,8 +587,9 @@ mt76_channel_state(struct mt76_dev *dev, struct ieee80211_channel *c) ...@@ -582,8 +587,9 @@ mt76_channel_state(struct mt76_dev *dev, struct ieee80211_channel *c)
return &msband->chan[idx]; return &msband->chan[idx];
} }
struct mt76_dev *mt76_alloc_device(unsigned int size, struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size,
const struct ieee80211_ops *ops); const struct ieee80211_ops *ops,
const struct mt76_driver_ops *drv_ops);
int mt76_register_device(struct mt76_dev *dev, bool vht, int mt76_register_device(struct mt76_dev *dev, bool vht,
struct ieee80211_rate *rates, int n_rates); struct ieee80211_rate *rates, int n_rates);
void mt76_unregister_device(struct mt76_dev *dev); void mt76_unregister_device(struct mt76_dev *dev);
...@@ -722,14 +728,17 @@ static inline u8 q2ep(u8 qid) ...@@ -722,14 +728,17 @@ static inline u8 q2ep(u8 qid)
return qid + 1; return qid + 1;
} }
static inline bool mt76u_check_sg(struct mt76_dev *dev) static inline int
mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int timeout)
{ {
struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_interface *intf = to_usb_interface(dev->dev);
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
struct mt76_usb *usb = &dev->usb;
unsigned int pipe;
int sent;
return (udev->bus->sg_tablesize > 0 && pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]);
(udev->bus->no_sg_constraint || return usb_bulk_msg(udev, pipe, data, len, &sent, timeout);
udev->speed == USB_SPEED_WIRELESS));
} }
int mt76u_vendor_request(struct mt76_dev *dev, u8 req, int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
...@@ -740,7 +749,7 @@ void mt76u_single_wr(struct mt76_dev *dev, const u8 req, ...@@ -740,7 +749,7 @@ void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf);
void mt76u_deinit(struct mt76_dev *dev); void mt76u_deinit(struct mt76_dev *dev);
int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
int nsgs, int len, int sglen, gfp_t gfp); int len, int data_len, gfp_t gfp);
void mt76u_buf_free(struct mt76u_buf *buf); void mt76u_buf_free(struct mt76u_buf *buf);
int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
struct mt76u_buf *buf, gfp_t gfp, struct mt76u_buf *buf, gfp_t gfp,
...@@ -751,6 +760,13 @@ void mt76u_stop_queues(struct mt76_dev *dev); ...@@ -751,6 +760,13 @@ void mt76u_stop_queues(struct mt76_dev *dev);
void mt76u_stop_stat_wk(struct mt76_dev *dev); void mt76u_stop_stat_wk(struct mt76_dev *dev);
void mt76u_queues_deinit(struct mt76_dev *dev); void mt76u_queues_deinit(struct mt76_dev *dev);
struct sk_buff *
mt76_mcu_msg_alloc(const void *data, int head_len,
int data_len, int tail_len);
void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb);
struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
unsigned long expires);
void mt76u_mcu_complete_urb(struct urb *urb); void mt76u_mcu_complete_urb(struct urb *urb);
int mt76u_mcu_init_rx(struct mt76_dev *dev); int mt76u_mcu_init_rx(struct mt76_dev *dev);
void mt76u_mcu_deinit(struct mt76_dev *dev); void mt76u_mcu_deinit(struct mt76_dev *dev);
......
...@@ -152,11 +152,11 @@ static s8 mt76x0_get_delta(struct mt76x02_dev *dev) ...@@ -152,11 +152,11 @@ static s8 mt76x0_get_delta(struct mt76x02_dev *dev)
return mt76x02_rate_power_val(val); return mt76x02_rate_power_val(val);
} }
void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev,
struct ieee80211_channel *chan,
struct mt76_rate_power *t)
{ {
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
bool is_2ghz = chan->band == NL80211_BAND_2GHZ; bool is_2ghz = chan->band == NL80211_BAND_2GHZ;
struct mt76_rate_power *t = &dev->mt76.rate_power;
u16 val, addr; u16 val, addr;
s8 delta; s8 delta;
...@@ -189,7 +189,7 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) ...@@ -189,7 +189,7 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 8 : 0x126; addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 8 : 0x126;
val = mt76x02_eeprom_get(dev, addr); val = mt76x02_eeprom_get(dev, addr);
t->ht[4] = t->ht[5] = t->vht[4] = t->vht[5] = s6_to_s8(val); t->ht[4] = t->ht[5] = t->vht[4] = t->vht[5] = s6_to_s8(val);
t->ht[6] = t->vht[6] = s6_to_s8(val >> 8); t->ht[6] = t->ht[7] = t->vht[6] = t->vht[7] = s6_to_s8(val >> 8);
/* ht-vht mcs 1ss 0, 1, 2, 3 stbc */ /* ht-vht mcs 1ss 0, 1, 2, 3 stbc */
addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 14 : 0xec; addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 14 : 0xec;
...@@ -205,14 +205,15 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) ...@@ -205,14 +205,15 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
/* vht mcs 8, 9 5GHz */ /* vht mcs 8, 9 5GHz */
val = mt76x02_eeprom_get(dev, 0x132); val = mt76x02_eeprom_get(dev, 0x132);
t->vht[7] = s6_to_s8(val); t->vht[8] = s6_to_s8(val);
t->vht[8] = s6_to_s8(val >> 8); t->vht[9] = s6_to_s8(val >> 8);
delta = mt76x0_tssi_enabled(dev) ? 0 : mt76x0_get_delta(dev); delta = mt76x0_tssi_enabled(dev) ? 0 : mt76x0_get_delta(dev);
mt76x02_add_rate_power_offset(t, delta); mt76x02_add_rate_power_offset(t, delta);
} }
void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp) void mt76x0_get_power_info(struct mt76x02_dev *dev,
struct ieee80211_channel *chan, s8 *tp)
{ {
struct mt76x0_chan_map { struct mt76x0_chan_map {
u8 chan; u8 chan;
...@@ -226,7 +227,6 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp) ...@@ -226,7 +227,6 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp)
{ 140, 26 }, { 151, 28 }, { 157, 30 }, { 161, 32 }, { 140, 26 }, { 151, 28 }, { 157, 30 }, { 161, 32 },
{ 167, 34 }, { 171, 36 }, { 175, 38 }, { 167, 34 }, { 171, 36 }, { 175, 38 },
}; };
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
u8 offset, addr; u8 offset, addr;
int i, idx = 0; int i, idx = 0;
u16 data; u16 data;
......
...@@ -25,8 +25,11 @@ struct mt76x02_dev; ...@@ -25,8 +25,11 @@ struct mt76x02_dev;
int mt76x0_eeprom_init(struct mt76x02_dev *dev); int mt76x0_eeprom_init(struct mt76x02_dev *dev);
void mt76x0_read_rx_gain(struct mt76x02_dev *dev); void mt76x0_read_rx_gain(struct mt76x02_dev *dev);
void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev); void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev,
void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp); struct ieee80211_channel *chan,
struct mt76_rate_power *t);
void mt76x0_get_power_info(struct mt76x02_dev *dev,
struct ieee80211_channel *chan, s8 *tp);
static inline s8 s6_to_s8(u32 val) static inline s8 s6_to_s8(u32 val)
{ {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "eeprom.h" #include "eeprom.h"
#include "mcu.h" #include "mcu.h"
#include "initvals.h" #include "initvals.h"
#include "../mt76x02_phy.h"
static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband) static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband)
{ {
...@@ -262,27 +263,24 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev) ...@@ -262,27 +263,24 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev)
} }
EXPORT_SYMBOL_GPL(mt76x0_init_hardware); EXPORT_SYMBOL_GPL(mt76x0_init_hardware);
struct mt76x02_dev * static void
mt76x0_alloc_device(struct device *pdev, mt76x0_init_txpower(struct mt76x02_dev *dev,
const struct mt76_driver_ops *drv_ops, struct ieee80211_supported_band *sband)
const struct ieee80211_ops *ops)
{ {
struct mt76x02_dev *dev; struct ieee80211_channel *chan;
struct mt76_dev *mdev; struct mt76_rate_power t;
s8 tp;
mdev = mt76_alloc_device(sizeof(*dev), ops); int i;
if (!mdev)
return NULL;
mdev->dev = pdev; for (i = 0; i < sband->n_channels; i++) {
mdev->drv = drv_ops; chan = &sband->channels[i];
dev = container_of(mdev, struct mt76x02_dev, mt76); mt76x0_get_tx_power_per_rate(dev, chan, &t);
mutex_init(&dev->phy_mutex); mt76x0_get_power_info(dev, chan, &tp);
return dev; chan->max_power = (mt76x02_get_max_rate_power(&t) + tp) / 2;
}
} }
EXPORT_SYMBOL_GPL(mt76x0_alloc_device);
int mt76x0_register_device(struct mt76x02_dev *dev) int mt76x0_register_device(struct mt76x02_dev *dev)
{ {
...@@ -296,9 +294,14 @@ int mt76x0_register_device(struct mt76x02_dev *dev) ...@@ -296,9 +294,14 @@ int mt76x0_register_device(struct mt76x02_dev *dev)
if (ret) if (ret)
return ret; return ret;
if (dev->mt76.cap.has_5ghz) {
/* overwrite unsupported features */ /* overwrite unsupported features */
if (dev->mt76.cap.has_5ghz)
mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband); mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband);
mt76x0_init_txpower(dev, &dev->mt76.sband_5g.sband);
}
if (dev->mt76.cap.has_2ghz)
mt76x0_init_txpower(dev, &dev->mt76.sband_2g.sband);
mt76x02_init_debugfs(dev); mt76x02_init_debugfs(dev);
......
...@@ -50,10 +50,6 @@ static inline bool is_mt7630(struct mt76x02_dev *dev) ...@@ -50,10 +50,6 @@ static inline bool is_mt7630(struct mt76x02_dev *dev)
} }
/* Init */ /* Init */
struct mt76x02_dev *
mt76x0_alloc_device(struct device *pdev,
const struct mt76_driver_ops *drv_ops,
const struct ieee80211_ops *ops);
int mt76x0_init_hardware(struct mt76x02_dev *dev); int mt76x0_init_hardware(struct mt76x02_dev *dev);
int mt76x0_register_device(struct mt76x02_dev *dev); int mt76x0_register_device(struct mt76x02_dev *dev);
void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset); void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset);
......
...@@ -30,7 +30,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw) ...@@ -30,7 +30,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw)
mt76x02_mac_start(dev); mt76x02_mac_start(dev);
mt76x0_phy_calibrate(dev, true); mt76x0_phy_calibrate(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
MT_CALIBRATE_INTERVAL); MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL); MT_CALIBRATE_INTERVAL);
set_bit(MT76_STATE_RUNNING, &dev->mt76.state); set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
...@@ -174,6 +174,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -174,6 +174,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
.sta_remove = mt76x02_sta_remove, .sta_remove = mt76x02_sta_remove,
}; };
struct mt76x02_dev *dev; struct mt76x02_dev *dev;
struct mt76_dev *mdev;
int ret; int ret;
ret = pcim_enable_device(pdev); ret = pcim_enable_device(pdev);
...@@ -190,16 +191,20 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -190,16 +191,20 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret) if (ret)
return ret; return ret;
dev = mt76x0_alloc_device(&pdev->dev, &drv_ops, &mt76x0e_ops); mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x0e_ops,
if (!dev) &drv_ops);
if (!mdev)
return -ENOMEM; return -ENOMEM;
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); dev = container_of(mdev, struct mt76x02_dev, mt76);
mutex_init(&dev->phy_mutex);
mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]);
dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler, ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev); IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret) if (ret)
goto error; goto error;
......
...@@ -847,14 +847,15 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) ...@@ -847,14 +847,15 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
struct mt76_rate_power *t = &dev->mt76.rate_power; struct mt76_rate_power *t = &dev->mt76.rate_power;
s8 info; s8 info;
mt76x0_get_tx_power_per_rate(dev); mt76x0_get_tx_power_per_rate(dev, dev->mt76.chandef.chan, t);
mt76x0_get_power_info(dev, &info); mt76x0_get_power_info(dev, dev->mt76.chandef.chan, &info);
mt76x02_add_rate_power_offset(t, info); mt76x02_add_rate_power_offset(t, info);
mt76x02_limit_rate_power(t, dev->mt76.txpower_conf); mt76x02_limit_rate_power(t, dev->mt76.txpower_conf);
dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t); dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t);
mt76x02_add_rate_power_offset(t, -info); mt76x02_add_rate_power_offset(t, -info);
dev->target_power = info;
mt76x02_phy_set_txpower(dev, info, info); mt76x02_phy_set_txpower(dev, info, info);
} }
...@@ -1006,14 +1007,16 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev, ...@@ -1006,14 +1007,16 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
/* enable vco */ /* enable vco */
mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7)); mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7));
if (scan) if (scan) {
mt76x02_edcca_init(dev, false);
return 0; return 0;
}
mt76x02_init_agc_gain(dev); mt76x02_init_agc_gain(dev);
mt76x0_phy_calibrate(dev, false); mt76x0_phy_calibrate(dev, false);
mt76x0_phy_set_txpower(dev); mt76x0_phy_set_txpower(dev);
mt76x02_edcca_init(dev); mt76x02_edcca_init(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL); MT_CALIBRATE_INTERVAL);
......
...@@ -118,7 +118,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw) ...@@ -118,7 +118,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw)
mt76x0_phy_calibrate(dev, true); mt76x0_phy_calibrate(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
MT_CALIBRATE_INTERVAL); MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL); MT_CALIBRATE_INTERVAL);
set_bit(MT76_STATE_RUNNING, &dev->mt76.state); set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
...@@ -206,7 +206,7 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev) ...@@ -206,7 +206,7 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev)
goto out_err; goto out_err;
/* check hw sg support in order to enable AMSDU */ /* check hw sg support in order to enable AMSDU */
if (mt76u_check_sg(&dev->mt76)) if (dev->mt76.usb.sg_en)
hw->max_tx_fragments = MT_SG_MAX_SIZE; hw->max_tx_fragments = MT_SG_MAX_SIZE;
else else
hw->max_tx_fragments = 1; hw->max_tx_fragments = 1;
...@@ -233,14 +233,18 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, ...@@ -233,14 +233,18 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
}; };
struct usb_device *usb_dev = interface_to_usbdev(usb_intf); struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
struct mt76x02_dev *dev; struct mt76x02_dev *dev;
struct mt76_dev *mdev;
u32 asic_rev, mac_rev; u32 asic_rev, mac_rev;
int ret; int ret;
dev = mt76x0_alloc_device(&usb_intf->dev, &drv_ops, mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), &mt76x0u_ops,
&mt76x0u_ops); &drv_ops);
if (!dev) if (!mdev)
return -ENOMEM; return -ENOMEM;
dev = container_of(mdev, struct mt76x02_dev, mt76);
mutex_init(&dev->phy_mutex);
/* Quirk for Archer T1U */ /* Quirk for Archer T1U */
if (id->driver_info) if (id->driver_info)
dev->no_2ghz = true; dev->no_2ghz = true;
...@@ -250,27 +254,27 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, ...@@ -250,27 +254,27 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
usb_set_intfdata(usb_intf, dev); usb_set_intfdata(usb_intf, dev);
mt76x02u_init_mcu(&dev->mt76); mt76x02u_init_mcu(mdev);
ret = mt76u_init(&dev->mt76, usb_intf); ret = mt76u_init(mdev, usb_intf);
if (ret) if (ret)
goto err; goto err;
/* Disable the HW, otherwise MCU fail to initalize on hot reboot */ /* Disable the HW, otherwise MCU fail to initalize on hot reboot */
mt76x0_chip_onoff(dev, false, false); mt76x0_chip_onoff(dev, false, false);
if (!mt76x02_wait_for_mac(&dev->mt76)) { if (!mt76x02_wait_for_mac(mdev)) {
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
goto err; goto err;
} }
asic_rev = mt76_rr(dev, MT_ASIC_VERSION); asic_rev = mt76_rr(dev, MT_ASIC_VERSION);
mac_rev = mt76_rr(dev, MT_MAC_CSR0); mac_rev = mt76_rr(dev, MT_MAC_CSR0);
dev_info(dev->mt76.dev, "ASIC revision: %08x MAC revision: %08x\n", dev_info(mdev->dev, "ASIC revision: %08x MAC revision: %08x\n",
asic_rev, mac_rev); asic_rev, mac_rev);
/* Note: vendor driver skips this check for MT76X0U */ /* Note: vendor driver skips this check for MT76X0U */
if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL)) if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
dev_warn(dev->mt76.dev, "Warning: eFUSE not present\n"); dev_warn(mdev->dev, "Warning: eFUSE not present\n");
ret = mt76x0u_register_device(dev); ret = mt76x0u_register_device(dev);
if (ret < 0) if (ret < 0)
...@@ -282,7 +286,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, ...@@ -282,7 +286,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
usb_set_intfdata(usb_intf, NULL); usb_set_intfdata(usb_intf, NULL);
usb_put_dev(interface_to_usbdev(usb_intf)); usb_put_dev(interface_to_usbdev(usb_intf));
ieee80211_free_hw(dev->mt76.hw); ieee80211_free_hw(mdev->hw);
return ret; return ret;
} }
......
...@@ -140,12 +140,6 @@ static int mt76x0u_load_firmware(struct mt76x02_dev *dev) ...@@ -140,12 +140,6 @@ static int mt76x0u_load_firmware(struct mt76x02_dev *dev)
FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20)); FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20));
mt76x02u_mcu_fw_reset(dev); mt76x02u_mcu_fw_reset(dev);
usleep_range(5000, 6000); usleep_range(5000, 6000);
/*
mt76x0_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN |
MT_PBF_CFG_TX1Q_EN |
MT_PBF_CFG_TX2Q_EN |
MT_PBF_CFG_TX3Q_EN));
*/
mt76_wr(dev, MT_FCE_PSE_CTRL, 1); mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "mt76x02_dma.h" #include "mt76x02_dma.h"
#define MT_CALIBRATE_INTERVAL HZ #define MT_CALIBRATE_INTERVAL HZ
#define MT_MAC_WORK_INTERVAL (HZ / 10)
#define MT_WATCHDOG_TIME (HZ / 10) #define MT_WATCHDOG_TIME (HZ / 10)
#define MT_TX_HANG_TH 10 #define MT_TX_HANG_TH 10
...@@ -73,6 +74,8 @@ struct mt76x02_dev { ...@@ -73,6 +74,8 @@ struct mt76x02_dev {
struct mutex phy_mutex; struct mutex phy_mutex;
u16 vif_mask;
u8 txdone_seq; u8 txdone_seq;
DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status); DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);
...@@ -114,6 +117,7 @@ struct mt76x02_dev { ...@@ -114,6 +117,7 @@ struct mt76x02_dev {
bool ed_monitor; bool ed_monitor;
u8 ed_trigger; u8 ed_trigger;
u8 ed_silent; u8 ed_silent;
ktime_t ed_time;
}; };
extern struct ieee80211_rate mt76x02_rates[12]; extern struct ieee80211_rate mt76x02_rates[12];
...@@ -128,8 +132,7 @@ void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, ...@@ -128,8 +132,7 @@ void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev); void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev);
void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
unsigned int idx);
int mt76x02_add_interface(struct ieee80211_hw *hw, int mt76x02_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
void mt76x02_remove_interface(struct ieee80211_hw *hw, void mt76x02_remove_interface(struct ieee80211_hw *hw,
......
...@@ -886,7 +886,7 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev, ...@@ -886,7 +886,7 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev,
tasklet_disable(&dfs_pd->dfs_tasklet); tasklet_disable(&dfs_pd->dfs_tasklet);
dev->ed_monitor = region == NL80211_DFS_ETSI; dev->ed_monitor = region == NL80211_DFS_ETSI;
mt76x02_edcca_init(dev); mt76x02_edcca_init(dev, true);
dfs_pd->region = region; dfs_pd->region = region;
mt76x02_dfs_init_params(dev); mt76x02_dfs_init_params(dev);
......
...@@ -291,6 +291,13 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, ...@@ -291,6 +291,13 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
memset(txwi, 0, sizeof(*txwi)); memset(txwi, 0, sizeof(*txwi));
if (!info->control.hw_key && wcid && wcid->hw_key_idx != 0xff &&
ieee80211_has_protected(hdr->frame_control)) {
wcid = NULL;
ieee80211_get_tx_rates(info->control.vif, sta, skb,
info->control.rates, 1);
}
if (wcid) if (wcid)
txwi->wcid = wcid->idx; txwi->wcid = wcid->idx;
else else
...@@ -307,7 +314,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, ...@@ -307,7 +314,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
ccmp_pn[6] = pn >> 32; ccmp_pn[6] = pn >> 32;
ccmp_pn[7] = pn >> 40; ccmp_pn[7] = pn >> 40;
txwi->iv = *((__le32 *)&ccmp_pn[0]); txwi->iv = *((__le32 *)&ccmp_pn[0]);
txwi->eiv = *((__le32 *)&ccmp_pn[1]); txwi->eiv = *((__le32 *)&ccmp_pn[4]);
} }
spin_lock_bh(&dev->mt76.lock); spin_lock_bh(&dev->mt76.lock);
...@@ -548,8 +555,11 @@ mt76x02_mac_process_rate(struct mt76x02_dev *dev, ...@@ -548,8 +555,11 @@ mt76x02_mac_process_rate(struct mt76x02_dev *dev,
return 0; return 0;
} }
void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr) void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr)
{ {
static const u8 null_addr[ETH_ALEN] = {};
int i;
ether_addr_copy(dev->mt76.macaddr, addr); ether_addr_copy(dev->mt76.macaddr, addr);
if (!is_valid_ether_addr(dev->mt76.macaddr)) { if (!is_valid_ether_addr(dev->mt76.macaddr)) {
...@@ -563,6 +573,16 @@ void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr) ...@@ -563,6 +573,16 @@ void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr)
mt76_wr(dev, MT_MAC_ADDR_DW1, mt76_wr(dev, MT_MAC_ADDR_DW1,
get_unaligned_le16(dev->mt76.macaddr + 4) | get_unaligned_le16(dev->mt76.macaddr + 4) |
FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff)); FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
mt76_wr(dev, MT_MAC_BSSID_DW0,
get_unaligned_le32(dev->mt76.macaddr));
mt76_wr(dev, MT_MAC_BSSID_DW1,
get_unaligned_le16(dev->mt76.macaddr + 4) |
FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 APs + 8 STAs */
MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT);
for (i = 0; i < 16; i++)
mt76x02_mac_set_bssid(dev, i, null_addr);
} }
EXPORT_SYMBOL_GPL(mt76x02_mac_setaddr); EXPORT_SYMBOL_GPL(mt76x02_mac_setaddr);
...@@ -588,7 +608,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, ...@@ -588,7 +608,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
u16 rate = le16_to_cpu(rxwi->rate); u16 rate = le16_to_cpu(rxwi->rate);
u16 tid_sn = le16_to_cpu(rxwi->tid_sn); u16 tid_sn = le16_to_cpu(rxwi->tid_sn);
bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST); bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST);
int i, pad_len = 0, nstreams = dev->mt76.chainmask & 0xf; int pad_len = 0, nstreams = dev->mt76.chainmask & 0xf;
s8 signal; s8 signal;
u8 pn_len; u8 pn_len;
u8 wcid; u8 wcid;
...@@ -648,12 +668,13 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, ...@@ -648,12 +668,13 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
status->chains = BIT(0); status->chains = BIT(0);
signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0); signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0);
for (i = 0; i < nstreams; i++) { status->chain_signal[0] = signal;
status->chains |= BIT(i); if (nstreams > 1) {
status->chain_signal[i] = mt76x02_mac_get_rssi(dev, status->chains |= BIT(1);
rxwi->rssi[i], status->chain_signal[1] = mt76x02_mac_get_rssi(dev,
i); rxwi->rssi[1],
signal = max_t(s8, signal, status->chain_signal[i]); 1);
signal = max_t(s8, signal, status->chain_signal[1]);
} }
status->signal = signal; status->signal = signal;
status->freq = dev->mt76.chandef.chan->center_freq; status->freq = dev->mt76.chandef.chan->center_freq;
...@@ -871,12 +892,12 @@ mt76x02_edcca_tx_enable(struct mt76x02_dev *dev, bool enable) ...@@ -871,12 +892,12 @@ mt76x02_edcca_tx_enable(struct mt76x02_dev *dev, bool enable)
dev->ed_tx_blocked = !enable; dev->ed_tx_blocked = !enable;
} }
void mt76x02_edcca_init(struct mt76x02_dev *dev) void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable)
{ {
dev->ed_trigger = 0; dev->ed_trigger = 0;
dev->ed_silent = 0; dev->ed_silent = 0;
if (dev->ed_monitor) { if (dev->ed_monitor && enable) {
struct ieee80211_channel *chan = dev->mt76.chandef.chan; struct ieee80211_channel *chan = dev->mt76.chandef.chan;
u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20; u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20;
...@@ -899,17 +920,27 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev) ...@@ -899,17 +920,27 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev)
} }
} }
mt76x02_edcca_tx_enable(dev, true); mt76x02_edcca_tx_enable(dev, true);
/* clear previous CCA timer value */
mt76_rr(dev, MT_ED_CCA_TIMER);
dev->ed_time = ktime_get_boottime();
} }
EXPORT_SYMBOL_GPL(mt76x02_edcca_init); EXPORT_SYMBOL_GPL(mt76x02_edcca_init);
#define MT_EDCCA_TH 90 #define MT_EDCCA_TH 92
#define MT_EDCCA_BLOCK_TH 2 #define MT_EDCCA_BLOCK_TH 2
static void mt76x02_edcca_check(struct mt76x02_dev *dev) static void mt76x02_edcca_check(struct mt76x02_dev *dev)
{ {
u32 val, busy; ktime_t cur_time;
u32 active, val, busy;
cur_time = ktime_get_boottime();
val = mt76_rr(dev, MT_ED_CCA_TIMER); val = mt76_rr(dev, MT_ED_CCA_TIMER);
busy = (val * 100) / jiffies_to_usecs(MT_CALIBRATE_INTERVAL);
active = ktime_to_us(ktime_sub(cur_time, dev->ed_time));
dev->ed_time = cur_time;
busy = (val * 100) / active;
busy = min_t(u32, busy, 100); busy = min_t(u32, busy, 100);
if (busy > MT_EDCCA_TH) { if (busy > MT_EDCCA_TH) {
...@@ -955,7 +986,7 @@ void mt76x02_mac_work(struct work_struct *work) ...@@ -955,7 +986,7 @@ void mt76x02_mac_work(struct work_struct *work)
mt76_tx_status_check(&dev->mt76, NULL, false); mt76_tx_status_check(&dev->mt76, NULL, false);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
MT_CALIBRATE_INTERVAL); MT_MAC_WORK_INTERVAL);
} }
void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr) void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr)
...@@ -1047,8 +1078,9 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, ...@@ -1047,8 +1078,9 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
return 0; return 0;
} }
void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, static void
u8 vif_idx, bool val) __mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx,
bool val, struct sk_buff *skb)
{ {
u8 old_mask = dev->beacon_mask; u8 old_mask = dev->beacon_mask;
bool en; bool en;
...@@ -1056,6 +1088,8 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, ...@@ -1056,6 +1088,8 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
if (val) { if (val) {
dev->beacon_mask |= BIT(vif_idx); dev->beacon_mask |= BIT(vif_idx);
if (skb)
mt76x02_mac_set_beacon(dev, vif_idx, skb);
} else { } else {
dev->beacon_mask &= ~BIT(vif_idx); dev->beacon_mask &= ~BIT(vif_idx);
mt76x02_mac_set_beacon(dev, vif_idx, NULL); mt76x02_mac_set_beacon(dev, vif_idx, NULL);
...@@ -1066,14 +1100,34 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, ...@@ -1066,14 +1100,34 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
en = dev->beacon_mask; en = dev->beacon_mask;
mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en);
reg = MT_BEACON_TIME_CFG_BEACON_TX | reg = MT_BEACON_TIME_CFG_BEACON_TX |
MT_BEACON_TIME_CFG_TBTT_EN | MT_BEACON_TIME_CFG_TBTT_EN |
MT_BEACON_TIME_CFG_TIMER_EN; MT_BEACON_TIME_CFG_TIMER_EN;
mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en); mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en);
if (mt76_is_usb(dev))
return;
mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en);
if (en) if (en)
mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
else else
mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
} }
void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
struct ieee80211_vif *vif, bool val)
{
u8 vif_idx = ((struct mt76x02_vif *)vif->drv_priv)->idx;
struct sk_buff *skb = NULL;
if (mt76_is_mmio(dev))
tasklet_disable(&dev->pre_tbtt_tasklet);
else if (val)
skb = ieee80211_beacon_get(mt76_hw(dev), vif);
__mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb);
if (mt76_is_mmio(dev))
tasklet_enable(&dev->pre_tbtt_tasklet);
}
...@@ -191,7 +191,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, ...@@ -191,7 +191,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot, void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot,
int ht_mode); int ht_mode);
void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val); void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val);
void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr); void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr);
void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid, struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_sta *sta, int len); struct ieee80211_sta *sta, int len);
...@@ -204,8 +204,8 @@ void mt76x02_mac_work(struct work_struct *work); ...@@ -204,8 +204,8 @@ void mt76x02_mac_work(struct work_struct *work);
void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr); void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr);
int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
struct sk_buff *skb); struct sk_buff *skb);
void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
bool val); struct ieee80211_vif *vif, bool val);
void mt76x02_edcca_init(struct mt76x02_dev *dev); void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable);
#endif #endif
...@@ -21,70 +21,13 @@ ...@@ -21,70 +21,13 @@
#include "mt76x02_mcu.h" #include "mt76x02_mcu.h"
static struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len)
{
struct sk_buff *skb;
skb = alloc_skb(len, GFP_KERNEL);
if (!skb)
return NULL;
memcpy(skb_put(skb, len), data, len);
return skb;
}
static struct sk_buff *
mt76x02_mcu_get_response(struct mt76x02_dev *dev, unsigned long expires)
{
unsigned long timeout;
if (!time_is_after_jiffies(expires))
return NULL;
timeout = expires - jiffies;
wait_event_timeout(dev->mt76.mmio.mcu.wait,
!skb_queue_empty(&dev->mt76.mmio.mcu.res_q),
timeout);
return skb_dequeue(&dev->mt76.mmio.mcu.res_q);
}
static int
mt76x02_tx_queue_mcu(struct mt76x02_dev *dev, enum mt76_txq_id qid,
struct sk_buff *skb, int cmd, int seq)
{
struct mt76_queue *q = &dev->mt76.q_tx[qid];
struct mt76_queue_buf buf;
dma_addr_t addr;
u32 tx_info;
tx_info = MT_MCU_MSG_TYPE_CMD |
FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) |
FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) |
FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) |
FIELD_PREP(MT_MCU_MSG_LEN, skb->len);
addr = dma_map_single(dev->mt76.dev, skb->data, skb->len,
DMA_TO_DEVICE);
if (dma_mapping_error(dev->mt76.dev, addr))
return -ENOMEM;
buf.addr = addr;
buf.len = skb->len;
spin_lock_bh(&q->lock);
mt76_queue_add_buf(dev, q, &buf, 1, tx_info, skb, NULL);
mt76_queue_kick(dev, q);
spin_unlock_bh(&q->lock);
return 0;
}
int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
int len, bool wait_resp) int len, bool wait_resp)
{ {
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
unsigned long expires = jiffies + HZ; unsigned long expires = jiffies + HZ;
struct sk_buff *skb; struct sk_buff *skb;
u32 tx_info;
int ret; int ret;
u8 seq; u8 seq;
...@@ -98,7 +41,13 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, ...@@ -98,7 +41,13 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
if (!seq) if (!seq)
seq = ++mdev->mmio.mcu.msg_seq & 0xf; seq = ++mdev->mmio.mcu.msg_seq & 0xf;
ret = mt76x02_tx_queue_mcu(dev, MT_TXQ_MCU, skb, cmd, seq); tx_info = MT_MCU_MSG_TYPE_CMD |
FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) |
FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) |
FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) |
FIELD_PREP(MT_MCU_MSG_LEN, skb->len);
ret = mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, tx_info);
if (ret) if (ret)
goto out; goto out;
...@@ -106,7 +55,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, ...@@ -106,7 +55,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
u32 *rxfce; u32 *rxfce;
bool check_seq = false; bool check_seq = false;
skb = mt76x02_mcu_get_response(dev, expires); skb = mt76_mcu_get_response(&dev->mt76, expires);
if (!skb) { if (!skb) {
dev_err(mdev->dev, dev_err(mdev->dev,
"MCU message %d (seq %d) timed out\n", cmd, "MCU message %d (seq %d) timed out\n", cmd,
......
...@@ -96,6 +96,12 @@ struct mt76x02_patch_header { ...@@ -96,6 +96,12 @@ struct mt76x02_patch_header {
u8 pad[2]; u8 pad[2];
}; };
static inline struct sk_buff *
mt76x02_mcu_msg_alloc(const void *data, int len)
{
return mt76_mcu_msg_alloc(data, 0, len, 0);
}
int mt76x02_mcu_cleanup(struct mt76x02_dev *dev); int mt76x02_mcu_cleanup(struct mt76x02_dev *dev);
int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param); int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param);
int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct mt76x02_dev *dev = hw->priv; struct mt76x02_dev *dev = hw->priv;
struct ieee80211_vif *vif = info->control.vif; struct ieee80211_vif *vif = info->control.vif;
...@@ -33,13 +32,7 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, ...@@ -33,13 +32,7 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
msta = (struct mt76x02_sta *)control->sta->drv_priv; msta = (struct mt76x02_sta *)control->sta->drv_priv;
wcid = &msta->wcid; wcid = &msta->wcid;
/* sw encrypted frames */ } else if (vif) {
if (!info->control.hw_key && wcid->hw_key_idx != 0xff &&
ieee80211_has_protected(hdr->frame_control))
control->sta = NULL;
}
if (vif && !control->sta) {
struct mt76x02_vif *mvif; struct mt76x02_vif *mvif;
mvif = (struct mt76x02_vif *)vif->drv_priv; mvif = (struct mt76x02_vif *)vif->drv_priv;
...@@ -58,8 +51,7 @@ void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, ...@@ -58,8 +51,7 @@ void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
if (q == MT_RXQ_MCU) { if (q == MT_RXQ_MCU) {
/* this is used just by mmio code */ /* this is used just by mmio code */
skb_queue_tail(&mdev->mmio.mcu.res_q, skb); mt76_mcu_rx_event(&dev->mt76, skb);
wake_up(&mdev->mmio.mcu.wait);
return; return;
} }
......
...@@ -49,7 +49,12 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) ...@@ -49,7 +49,12 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
FIELD_PREP(MT_TXD_INFO_DPORT, port) | flags; FIELD_PREP(MT_TXD_INFO_DPORT, port) | flags;
put_unaligned_le32(info, skb_push(skb, sizeof(info))); put_unaligned_le32(info, skb_push(skb, sizeof(info)));
/* Add zero pad of 4 - 7 bytes */
pad = round_up(skb->len, 4) + 4 - skb->len; pad = round_up(skb->len, 4) + 4 - skb->len;
/* First packet of a A-MSDU burst keeps track of the whole burst
* length, need to update lenght of it and the last packet.
*/
skb_walk_frags(skb, iter) { skb_walk_frags(skb, iter) {
last = iter; last = iter;
if (!iter->next) { if (!iter->next) {
...@@ -59,11 +64,10 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) ...@@ -59,11 +64,10 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
} }
} }
if (unlikely(pad)) {
if (skb_pad(last, pad)) if (skb_pad(last, pad))
return -ENOMEM; return -ENOMEM;
__skb_put(last, pad); __skb_put(last, pad);
}
return 0; return 0;
} }
......
...@@ -28,21 +28,6 @@ ...@@ -28,21 +28,6 @@
#define MT_TX_CPU_FROM_FCE_CPU_DESC_IDX 0x09a8 #define MT_TX_CPU_FROM_FCE_CPU_DESC_IDX 0x09a8
static struct sk_buff *
mt76x02u_mcu_msg_alloc(const void *data, int len)
{
struct sk_buff *skb;
skb = alloc_skb(MT_CMD_HDR_LEN + len + 8, GFP_KERNEL);
if (!skb)
return NULL;
skb_reserve(skb, MT_CMD_HDR_LEN);
skb_put_data(skb, data, len);
return skb;
}
static void static void
mt76x02u_multiple_mcu_reads(struct mt76_dev *dev, u8 *data, int len) mt76x02u_multiple_mcu_reads(struct mt76_dev *dev, u8 *data, int len)
{ {
...@@ -78,9 +63,9 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) ...@@ -78,9 +63,9 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq)
struct mt76_usb *usb = &dev->usb; struct mt76_usb *usb = &dev->usb;
struct mt76u_buf *buf = &usb->mcu.res; struct mt76u_buf *buf = &usb->mcu.res;
struct urb *urb = buf->urb; struct urb *urb = buf->urb;
u8 *data = buf->buf;
int i, ret; int i, ret;
u32 rxfce; u32 rxfce;
u8 *data;
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
if (!wait_for_completion_timeout(&usb->mcu.cmpl, if (!wait_for_completion_timeout(&usb->mcu.cmpl,
...@@ -90,7 +75,6 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) ...@@ -90,7 +75,6 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq)
if (urb->status) if (urb->status)
return -EIO; return -EIO;
data = sg_virt(&urb->sg[0]);
if (usb->mcu.rp) if (usb->mcu.rp)
mt76x02u_multiple_mcu_reads(dev, data + 4, mt76x02u_multiple_mcu_reads(dev, data + 4,
urb->actual_length - 8); urb->actual_length - 8);
...@@ -121,18 +105,14 @@ static int ...@@ -121,18 +105,14 @@ static int
__mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb,
int cmd, bool wait_resp) int cmd, bool wait_resp)
{ {
struct usb_interface *intf = to_usb_interface(dev->dev);
struct usb_device *udev = interface_to_usbdev(intf);
struct mt76_usb *usb = &dev->usb; struct mt76_usb *usb = &dev->usb;
unsigned int pipe; int ret;
int ret, sent;
u8 seq = 0; u8 seq = 0;
u32 info; u32 info;
if (test_bit(MT76_REMOVED, &dev->state)) if (test_bit(MT76_REMOVED, &dev->state))
return 0; return 0;
pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]);
if (wait_resp) { if (wait_resp) {
seq = ++usb->mcu.msg_seq & 0xf; seq = ++usb->mcu.msg_seq & 0xf;
if (!seq) if (!seq)
...@@ -146,7 +126,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, ...@@ -146,7 +126,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb,
if (ret) if (ret)
return ret; return ret;
ret = usb_bulk_msg(udev, pipe, skb->data, skb->len, &sent, 500); ret = mt76u_bulk_msg(dev, skb->data, skb->len, 500);
if (ret) if (ret)
return ret; return ret;
...@@ -166,7 +146,7 @@ mt76x02u_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data, ...@@ -166,7 +146,7 @@ mt76x02u_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data,
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
skb = mt76x02u_mcu_msg_alloc(data, len); skb = mt76_mcu_msg_alloc(data, MT_CMD_HDR_LEN, len, 8);
if (!skb) if (!skb)
return -ENOMEM; return -ENOMEM;
...@@ -268,14 +248,12 @@ void mt76x02u_mcu_fw_reset(struct mt76x02_dev *dev) ...@@ -268,14 +248,12 @@ void mt76x02u_mcu_fw_reset(struct mt76x02_dev *dev)
EXPORT_SYMBOL_GPL(mt76x02u_mcu_fw_reset); EXPORT_SYMBOL_GPL(mt76x02u_mcu_fw_reset);
static int static int
__mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf, __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, u8 *data,
const void *fw_data, int len, u32 dst_addr) const void *fw_data, int len, u32 dst_addr)
{ {
u8 *data = sg_virt(&buf->urb->sg[0]);
DECLARE_COMPLETION_ONSTACK(cmpl);
__le32 info; __le32 info;
u32 val; u32 val;
int err; int err, data_len;
info = cpu_to_le32(FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) | info = cpu_to_le32(FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) |
FIELD_PREP(MT_MCU_MSG_LEN, len) | FIELD_PREP(MT_MCU_MSG_LEN, len) |
...@@ -291,25 +269,12 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf, ...@@ -291,25 +269,12 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf,
mt76u_single_wr(&dev->mt76, MT_VEND_WRITE_FCE, mt76u_single_wr(&dev->mt76, MT_VEND_WRITE_FCE,
MT_FCE_DMA_LEN, len << 16); MT_FCE_DMA_LEN, len << 16);
buf->len = MT_CMD_HDR_LEN + len + sizeof(info); data_len = MT_CMD_HDR_LEN + len + sizeof(info);
err = mt76u_submit_buf(&dev->mt76, USB_DIR_OUT,
MT_EP_OUT_INBAND_CMD,
buf, GFP_KERNEL,
mt76u_mcu_complete_urb, &cmpl);
if (err < 0)
return err;
if (!wait_for_completion_timeout(&cmpl,
msecs_to_jiffies(1000))) {
dev_err(dev->mt76.dev, "firmware upload timed out\n");
usb_kill_urb(buf->urb);
return -ETIMEDOUT;
}
if (mt76u_urb_error(buf->urb)) { err = mt76u_bulk_msg(&dev->mt76, data, data_len, 1000);
dev_err(dev->mt76.dev, "firmware upload failed: %d\n", if (err) {
buf->urb->status); dev_err(dev->mt76.dev, "firmware upload failed: %d\n", err);
return buf->urb->status; return err;
} }
val = mt76_rr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX); val = mt76_rr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX);
...@@ -322,17 +287,16 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf, ...@@ -322,17 +287,16 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf,
int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data, int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data,
int data_len, u32 max_payload, u32 offset) int data_len, u32 max_payload, u32 offset)
{ {
int err, len, pos = 0, max_len = max_payload - 8; int len, err = 0, pos = 0, max_len = max_payload - 8;
struct mt76u_buf buf; u8 *buf;
err = mt76u_buf_alloc(&dev->mt76, &buf, 1, max_payload, max_payload, buf = kmalloc(max_payload, GFP_KERNEL);
GFP_KERNEL); if (!buf)
if (err < 0) return -ENOMEM;
return err;
while (data_len > 0) { while (data_len > 0) {
len = min_t(int, data_len, max_len); len = min_t(int, data_len, max_len);
err = __mt76x02u_mcu_fw_send_data(dev, &buf, data + pos, err = __mt76x02u_mcu_fw_send_data(dev, buf, data + pos,
len, offset + pos); len, offset + pos);
if (err < 0) if (err < 0)
break; break;
...@@ -341,7 +305,7 @@ int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data, ...@@ -341,7 +305,7 @@ int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data,
pos += len; pos += len;
usleep_range(5000, 10000); usleep_range(5000, 10000);
} }
mt76u_buf_free(&buf); kfree(buf);
return err; return err;
} }
......
...@@ -140,10 +140,16 @@ void mt76x02_init_device(struct mt76x02_dev *dev) ...@@ -140,10 +140,16 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
hw->max_rate_tries = 1; hw->max_rate_tries = 1;
hw->extra_tx_headroom = 2; hw->extra_tx_headroom = 2;
wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
#ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) |
#endif
BIT(NL80211_IFTYPE_ADHOC);
if (mt76_is_usb(dev)) { if (mt76_is_usb(dev)) {
hw->extra_tx_headroom += sizeof(struct mt76x02_txwi) + hw->extra_tx_headroom += sizeof(struct mt76x02_txwi) +
MT_DMA_HDR_LEN; MT_DMA_HDR_LEN;
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
} else { } else {
INIT_DELAYED_WORK(&dev->wdt_work, mt76x02_wdt_work); INIT_DELAYED_WORK(&dev->wdt_work, mt76x02_wdt_work);
...@@ -152,18 +158,9 @@ void mt76x02_init_device(struct mt76x02_dev *dev) ...@@ -152,18 +158,9 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
wiphy->reg_notifier = mt76x02_regd_notifier; wiphy->reg_notifier = mt76x02_regd_notifier;
wiphy->iface_combinations = mt76x02_if_comb; wiphy->iface_combinations = mt76x02_if_comb;
wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb); wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb);
wiphy->interface_modes = wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
#ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) |
#endif
BIT(NL80211_IFTYPE_ADHOC);
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
/* init led callbacks */ /* init led callbacks */
if (IS_ENABLED(CONFIG_MT76_LEDS)) { if (IS_ENABLED(CONFIG_MT76_LEDS)) {
dev->mt76.led_cdev.brightness_set = dev->mt76.led_cdev.brightness_set =
...@@ -172,6 +169,8 @@ void mt76x02_init_device(struct mt76x02_dev *dev) ...@@ -172,6 +169,8 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
} }
} }
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
hw->sta_data_size = sizeof(struct mt76x02_sta); hw->sta_data_size = sizeof(struct mt76x02_sta);
hw->vif_data_size = sizeof(struct mt76x02_vif); hw->vif_data_size = sizeof(struct mt76x02_vif);
...@@ -268,7 +267,8 @@ void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, ...@@ -268,7 +267,8 @@ void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
} }
EXPORT_SYMBOL_GPL(mt76x02_sta_remove); EXPORT_SYMBOL_GPL(mt76x02_sta_remove);
void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, static void
mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
unsigned int idx) unsigned int idx)
{ {
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
...@@ -282,7 +282,6 @@ void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, ...@@ -282,7 +282,6 @@ void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
mt76_txq_init(&dev->mt76, vif->txq); mt76_txq_init(&dev->mt76, vif->txq);
} }
EXPORT_SYMBOL_GPL(mt76x02_vif_init);
int int
mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
...@@ -309,6 +308,15 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ...@@ -309,6 +308,15 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
if (vif->type == NL80211_IFTYPE_STATION) if (vif->type == NL80211_IFTYPE_STATION)
idx += 8; idx += 8;
if (dev->vif_mask & BIT(idx))
return -EBUSY;
/* Allow to change address in HW if we create first interface. */
if (!dev->vif_mask && !ether_addr_equal(dev->mt76.macaddr, vif->addr))
mt76x02_mac_setaddr(dev, vif->addr);
dev->vif_mask |= BIT(idx);
mt76x02_vif_init(dev, vif, idx); mt76x02_vif_init(dev, vif, idx);
return 0; return 0;
} }
...@@ -318,8 +326,10 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw, ...@@ -318,8 +326,10 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
struct mt76x02_dev *dev = hw->priv; struct mt76x02_dev *dev = hw->priv;
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
mt76_txq_remove(&dev->mt76, vif->txq); mt76_txq_remove(&dev->mt76, vif->txq);
dev->vif_mask &= ~BIT(mvif->idx);
} }
EXPORT_SYMBOL_GPL(mt76x02_remove_interface); EXPORT_SYMBOL_GPL(mt76x02_remove_interface);
...@@ -421,7 +431,7 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ...@@ -421,7 +431,7 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
} else { } else {
if (idx == wcid->hw_key_idx) { if (idx == wcid->hw_key_idx) {
wcid->hw_key_idx = -1; wcid->hw_key_idx = -1;
wcid->sw_iv = true; wcid->sw_iv = false;
} }
key = NULL; key = NULL;
...@@ -657,29 +667,26 @@ static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev) ...@@ -657,29 +667,26 @@ static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev)
void mt76x02_init_beacon_config(struct mt76x02_dev *dev) void mt76x02_init_beacon_config(struct mt76x02_dev *dev)
{ {
static const u8 null_addr[ETH_ALEN] = {};
int i; int i;
mt76_wr(dev, MT_MAC_BSSID_DW0, if (mt76_is_mmio(dev)) {
get_unaligned_le32(dev->mt76.macaddr));
mt76_wr(dev, MT_MAC_BSSID_DW1,
get_unaligned_le16(dev->mt76.macaddr + 4) |
FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 beacons */
MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT);
/* Fire a pre-TBTT interrupt 8 ms before TBTT */ /* Fire a pre-TBTT interrupt 8 ms before TBTT */
mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT,
8 << 4); 8 << 4);
mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER, mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER,
MT_DFS_GP_INTERVAL); MT_DFS_GP_INTERVAL);
mt76_wr(dev, MT_INT_TIMER_EN, 0); mt76_wr(dev, MT_INT_TIMER_EN, 0);
}
mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN |
MT_BEACON_TIME_CFG_SYNC_MODE |
MT_BEACON_TIME_CFG_TBTT_EN |
MT_BEACON_TIME_CFG_BEACON_TX));
mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++)
mt76x02_mac_set_bssid(dev, i, null_addr);
mt76x02_mac_set_beacon(dev, i, NULL); mt76x02_mac_set_beacon(dev, i, NULL);
}
mt76x02_set_beacon_offsets(dev); mt76x02_set_beacon_offsets(dev);
} }
EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config); EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config);
...@@ -697,12 +704,8 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw, ...@@ -697,12 +704,8 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BSSID) if (changed & BSS_CHANGED_BSSID)
mt76x02_mac_set_bssid(dev, mvif->idx, info->bssid); mt76x02_mac_set_bssid(dev, mvif->idx, info->bssid);
if (changed & BSS_CHANGED_BEACON_ENABLED) { if (changed & BSS_CHANGED_BEACON_ENABLED)
tasklet_disable(&dev->pre_tbtt_tasklet); mt76x02_mac_set_beacon_enable(dev, vif, info->enable_beacon);
mt76x02_mac_set_beacon_enable(dev, mvif->idx,
info->enable_beacon);
tasklet_enable(&dev->pre_tbtt_tasklet);
}
if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT) if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
mt76x02_mac_set_tx_protection(dev, info->use_cts_prot, mt76x02_mac_set_tx_protection(dev, info->use_cts_prot,
......
...@@ -49,7 +49,6 @@ static inline bool mt76x2_channel_silent(struct mt76x02_dev *dev) ...@@ -49,7 +49,6 @@ static inline bool mt76x2_channel_silent(struct mt76x02_dev *dev)
extern const struct ieee80211_ops mt76x2_ops; extern const struct ieee80211_ops mt76x2_ops;
struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev);
int mt76x2_register_device(struct mt76x02_dev *dev); int mt76x2_register_device(struct mt76x02_dev *dev);
void mt76x2_phy_power_on(struct mt76x02_dev *dev); void mt76x2_phy_power_on(struct mt76x02_dev *dev);
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
extern const struct ieee80211_ops mt76x2u_ops; extern const struct ieee80211_ops mt76x2u_ops;
struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev);
int mt76x2u_register_device(struct mt76x02_dev *dev); int mt76x2u_register_device(struct mt76x02_dev *dev);
int mt76x2u_init_hardware(struct mt76x02_dev *dev); int mt76x2u_init_hardware(struct mt76x02_dev *dev);
void mt76x2u_cleanup(struct mt76x02_dev *dev); void mt76x2u_cleanup(struct mt76x02_dev *dev);
......
...@@ -30,7 +30,19 @@ static const struct pci_device_id mt76pci_device_table[] = { ...@@ -30,7 +30,19 @@ static const struct pci_device_id mt76pci_device_table[] = {
static int static int
mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
static const struct mt76_driver_ops drv_ops = {
.txwi_size = sizeof(struct mt76x02_txwi),
.update_survey = mt76x02_update_channel,
.tx_prepare_skb = mt76x02_tx_prepare_skb,
.tx_complete_skb = mt76x02_tx_complete_skb,
.rx_skb = mt76x02_queue_rx_skb,
.rx_poll_complete = mt76x02_rx_poll_complete,
.sta_ps = mt76x02_sta_ps,
.sta_add = mt76x02_sta_add,
.sta_remove = mt76x02_sta_remove,
};
struct mt76x02_dev *dev; struct mt76x02_dev *dev;
struct mt76_dev *mdev;
int ret; int ret;
ret = pcim_enable_device(pdev); ret = pcim_enable_device(pdev);
...@@ -47,17 +59,19 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -47,17 +59,19 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret) if (ret)
return ret; return ret;
dev = mt76x2_alloc_device(&pdev->dev); mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x2_ops,
if (!dev) &drv_ops);
if (!mdev)
return -ENOMEM; return -ENOMEM;
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); dev = container_of(mdev, struct mt76x02_dev, mt76);
mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]);
mt76x2_reset_wlan(dev, false); mt76x2_reset_wlan(dev, false);
dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler, ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev); IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret) if (ret)
goto error; goto error;
......
...@@ -119,9 +119,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) ...@@ -119,9 +119,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
mt76_wr(dev, MT_MCU_CLOCK_CTL, 0x1401); mt76_wr(dev, MT_MCU_CLOCK_CTL, 0x1401);
mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN); mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);
mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(macaddr)); mt76x02_mac_setaddr(dev, macaddr);
mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(macaddr + 4));
mt76x02_init_beacon_config(dev); mt76x02_init_beacon_config(dev);
if (!hard) if (!hard)
return 0; return 0;
...@@ -315,33 +313,6 @@ void mt76x2_cleanup(struct mt76x02_dev *dev) ...@@ -315,33 +313,6 @@ void mt76x2_cleanup(struct mt76x02_dev *dev)
mt76x02_mcu_cleanup(dev); mt76x02_mcu_cleanup(dev);
} }
struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev)
{
static const struct mt76_driver_ops drv_ops = {
.txwi_size = sizeof(struct mt76x02_txwi),
.update_survey = mt76x02_update_channel,
.tx_prepare_skb = mt76x02_tx_prepare_skb,
.tx_complete_skb = mt76x02_tx_complete_skb,
.rx_skb = mt76x02_queue_rx_skb,
.rx_poll_complete = mt76x02_rx_poll_complete,
.sta_ps = mt76x02_sta_ps,
.sta_add = mt76x02_sta_add,
.sta_remove = mt76x02_sta_remove,
};
struct mt76x02_dev *dev;
struct mt76_dev *mdev;
mdev = mt76_alloc_device(sizeof(*dev), &mt76x2_ops);
if (!mdev)
return NULL;
dev = container_of(mdev, struct mt76x02_dev, mt76);
mdev->dev = pdev;
mdev->drv = &drv_ops;
return dev;
}
int mt76x2_register_device(struct mt76x02_dev *dev) int mt76x2_register_device(struct mt76x02_dev *dev)
{ {
int ret; int ret;
......
...@@ -33,7 +33,7 @@ mt76x2_start(struct ieee80211_hw *hw) ...@@ -33,7 +33,7 @@ mt76x2_start(struct ieee80211_hw *hw)
goto out; goto out;
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
MT_CALIBRATE_INTERVAL); MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work, ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work,
MT_WATCHDOG_TIME); MT_WATCHDOG_TIME);
......
...@@ -240,8 +240,10 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, ...@@ -240,8 +240,10 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev,
mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070);
mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x04101B3F); mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x04101B3F);
if (scan) if (scan) {
mt76x02_edcca_init(dev, false);
return 0; return 0;
}
mt76x2_phy_channel_calibrate(dev, true); mt76x2_phy_channel_calibrate(dev, true);
mt76x02_init_agc_gain(dev); mt76x02_init_agc_gain(dev);
...@@ -254,7 +256,7 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, ...@@ -254,7 +256,7 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev,
0x38); 0x38);
} }
mt76x02_edcca_init(dev); mt76x02_edcca_init(dev, true);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work,
MT_CALIBRATE_INTERVAL); MT_CALIBRATE_INTERVAL);
......
...@@ -241,7 +241,7 @@ void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev) ...@@ -241,7 +241,7 @@ void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev)
t.offset1 = txp.chain[1].tssi_offset; t.offset1 = txp.chain[1].tssi_offset;
mt76x2_mcu_tssi_comp(dev, &t); mt76x2_mcu_tssi_comp(dev, &t);
if (t.pa_mode || dev->cal.dpd_cal_done) if (t.pa_mode || dev->cal.dpd_cal_done || dev->ed_tx_blocked)
return; return;
usleep_range(10000, 20000); usleep_range(10000, 20000);
......
...@@ -36,24 +36,36 @@ static const struct usb_device_id mt76x2u_device_table[] = { ...@@ -36,24 +36,36 @@ static const struct usb_device_id mt76x2u_device_table[] = {
static int mt76x2u_probe(struct usb_interface *intf, static int mt76x2u_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
static const struct mt76_driver_ops drv_ops = {
.tx_prepare_skb = mt76x02u_tx_prepare_skb,
.tx_complete_skb = mt76x02u_tx_complete_skb,
.tx_status_data = mt76x02_tx_status_data,
.rx_skb = mt76x02_queue_rx_skb,
.sta_add = mt76x02_sta_add,
.sta_remove = mt76x02_sta_remove,
};
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
struct mt76x02_dev *dev; struct mt76x02_dev *dev;
struct mt76_dev *mdev;
int err; int err;
dev = mt76x2u_alloc_device(&intf->dev); mdev = mt76_alloc_device(&intf->dev, sizeof(*dev), &mt76x2u_ops,
if (!dev) &drv_ops);
if (!mdev)
return -ENOMEM; return -ENOMEM;
dev = container_of(mdev, struct mt76x02_dev, mt76);
udev = usb_get_dev(udev); udev = usb_get_dev(udev);
usb_reset_device(udev); usb_reset_device(udev);
mt76x02u_init_mcu(&dev->mt76); mt76x02u_init_mcu(mdev);
err = mt76u_init(&dev->mt76, intf); err = mt76u_init(mdev, intf);
if (err < 0) if (err < 0)
goto err; goto err;
dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); mdev->rev = mt76_rr(dev, MT_ASIC_VERSION);
dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev);
err = mt76x2u_register_device(dev); err = mt76x2u_register_device(dev);
if (err < 0) if (err < 0)
......
...@@ -134,30 +134,6 @@ static int mt76x2u_init_eeprom(struct mt76x02_dev *dev) ...@@ -134,30 +134,6 @@ static int mt76x2u_init_eeprom(struct mt76x02_dev *dev)
return 0; return 0;
} }
struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev)
{
static const struct mt76_driver_ops drv_ops = {
.tx_prepare_skb = mt76x02u_tx_prepare_skb,
.tx_complete_skb = mt76x02u_tx_complete_skb,
.tx_status_data = mt76x02_tx_status_data,
.rx_skb = mt76x02_queue_rx_skb,
.sta_add = mt76x02_sta_add,
.sta_remove = mt76x02_sta_remove,
};
struct mt76x02_dev *dev;
struct mt76_dev *mdev;
mdev = mt76_alloc_device(sizeof(*dev), &mt76x2u_ops);
if (!mdev)
return NULL;
dev = container_of(mdev, struct mt76x02_dev, mt76);
mdev->dev = pdev;
mdev->drv = &drv_ops;
return dev;
}
int mt76x2u_init_hardware(struct mt76x02_dev *dev) int mt76x2u_init_hardware(struct mt76x02_dev *dev)
{ {
int i, k, err; int i, k, err;
...@@ -207,11 +183,7 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev) ...@@ -207,11 +183,7 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev)
mt76x02_mac_shared_key_setup(dev, i, k, NULL); mt76x02_mac_shared_key_setup(dev, i, k, NULL);
} }
mt76_clear(dev, MT_BEACON_TIME_CFG, mt76x02_init_beacon_config(dev);
MT_BEACON_TIME_CFG_TIMER_EN |
MT_BEACON_TIME_CFG_SYNC_MODE |
MT_BEACON_TIME_CFG_TBTT_EN |
MT_BEACON_TIME_CFG_BEACON_TX);
mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e); mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x583f); mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x583f);
...@@ -256,7 +228,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) ...@@ -256,7 +228,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)
goto fail; goto fail;
/* check hw sg support in order to enable AMSDU */ /* check hw sg support in order to enable AMSDU */
if (mt76u_check_sg(&dev->mt76)) if (dev->mt76.usb.sg_en)
hw->max_tx_fragments = MT_SG_MAX_SIZE; hw->max_tx_fragments = MT_SG_MAX_SIZE;
else else
hw->max_tx_fragments = 1; hw->max_tx_fragments = 1;
......
...@@ -28,7 +28,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw) ...@@ -28,7 +28,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw)
goto out; goto out;
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
MT_CALIBRATE_INTERVAL); MT_MAC_WORK_INTERVAL);
set_bit(MT76_STATE_RUNNING, &dev->mt76.state); set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
out: out:
...@@ -46,19 +46,6 @@ static void mt76x2u_stop(struct ieee80211_hw *hw) ...@@ -46,19 +46,6 @@ static void mt76x2u_stop(struct ieee80211_hw *hw)
mutex_unlock(&dev->mt76.mutex); mutex_unlock(&dev->mt76.mutex);
} }
static int mt76x2u_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct mt76x02_dev *dev = hw->priv;
unsigned int idx = 8;
if (!ether_addr_equal(dev->mt76.macaddr, vif->addr))
mt76x02_mac_setaddr(dev, vif->addr);
mt76x02_vif_init(dev, vif, idx);
return 0;
}
static int static int
mt76x2u_set_channel(struct mt76x02_dev *dev, mt76x2u_set_channel(struct mt76x02_dev *dev,
struct cfg80211_chan_def *chandef) struct cfg80211_chan_def *chandef)
...@@ -125,7 +112,7 @@ const struct ieee80211_ops mt76x2u_ops = { ...@@ -125,7 +112,7 @@ const struct ieee80211_ops mt76x2u_ops = {
.tx = mt76x02_tx, .tx = mt76x02_tx,
.start = mt76x2u_start, .start = mt76x2u_start,
.stop = mt76x2u_stop, .stop = mt76x2u_stop,
.add_interface = mt76x2u_add_interface, .add_interface = mt76x02_add_interface,
.remove_interface = mt76x02_remove_interface, .remove_interface = mt76x02_remove_interface,
.sta_state = mt76_sta_state, .sta_state = mt76_sta_state,
.set_key = mt76x02_set_key, .set_key = mt76x02_set_key,
......
...@@ -205,9 +205,6 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid, ...@@ -205,9 +205,6 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid,
{ {
struct sk_buff *skb, *tmp; struct sk_buff *skb, *tmp;
if (pktid == MT_PACKET_ID_NO_ACK)
return NULL;
skb_queue_walk_safe(&dev->status_list, skb, tmp) { skb_queue_walk_safe(&dev->status_list, skb, tmp) {
struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb); struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
...@@ -217,7 +214,7 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid, ...@@ -217,7 +214,7 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid,
if (cb->pktid == pktid) if (cb->pktid == pktid)
return skb; return skb;
if (!pktid && if (pktid >= 0 &&
!time_after(jiffies, cb->jiffies + MT_TX_STATUS_SKB_TIMEOUT)) !time_after(jiffies, cb->jiffies + MT_TX_STATUS_SKB_TIMEOUT))
continue; continue;
......
...@@ -22,6 +22,10 @@ ...@@ -22,6 +22,10 @@
#define MT_VEND_REQ_MAX_RETRY 10 #define MT_VEND_REQ_MAX_RETRY 10
#define MT_VEND_REQ_TOUT_MS 300 #define MT_VEND_REQ_TOUT_MS 300
static bool disable_usb_sg;
module_param_named(disable_usb_sg, disable_usb_sg, bool, 0644);
MODULE_PARM_DESC(disable_usb_sg, "Disable usb scatter-gather support");
/* should be called with usb_ctrl_mtx locked */ /* should be called with usb_ctrl_mtx locked */
static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req,
u8 req_type, u16 val, u16 offset, u8 req_type, u16 val, u16 offset,
...@@ -241,6 +245,16 @@ mt76u_rd_rp(struct mt76_dev *dev, u32 base, ...@@ -241,6 +245,16 @@ mt76u_rd_rp(struct mt76_dev *dev, u32 base,
return mt76u_req_rd_rp(dev, base, data, n); return mt76u_req_rd_rp(dev, base, data, n);
} }
static bool mt76u_check_sg(struct mt76_dev *dev)
{
struct usb_interface *intf = to_usb_interface(dev->dev);
struct usb_device *udev = interface_to_usbdev(intf);
return (!disable_usb_sg && udev->bus->sg_tablesize > 0 &&
(udev->bus->no_sg_constraint ||
udev->speed == USB_SPEED_WIRELESS));
}
static int static int
mt76u_set_endpoints(struct usb_interface *intf, mt76u_set_endpoints(struct usb_interface *intf,
struct mt76_usb *usb) struct mt76_usb *usb)
...@@ -309,7 +323,8 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf, ...@@ -309,7 +323,8 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf,
return i ? : -ENOMEM; return i ? : -ENOMEM;
} }
int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, static int
mt76u_buf_alloc_sg(struct mt76_dev *dev, struct mt76u_buf *buf,
int nsgs, int len, int sglen, gfp_t gfp) int nsgs, int len, int sglen, gfp_t gfp)
{ {
buf->urb = usb_alloc_urb(0, gfp); buf->urb = usb_alloc_urb(0, gfp);
...@@ -326,15 +341,42 @@ int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, ...@@ -326,15 +341,42 @@ int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
return mt76u_fill_rx_sg(dev, buf, nsgs, len, sglen); return mt76u_fill_rx_sg(dev, buf, nsgs, len, sglen);
} }
EXPORT_SYMBOL_GPL(mt76u_buf_alloc);
int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
int len, int data_len, gfp_t gfp)
{
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
buf->urb = usb_alloc_urb(0, gfp);
if (!buf->urb)
return -ENOMEM;
buf->buf = page_frag_alloc(&q->rx_page, len, gfp);
if (!buf->buf)
return -ENOMEM;
buf->len = data_len;
buf->dev = dev;
return 0;
}
void mt76u_buf_free(struct mt76u_buf *buf) void mt76u_buf_free(struct mt76u_buf *buf)
{ {
struct urb *urb = buf->urb; struct urb *urb = buf->urb;
struct scatterlist *sg;
int i; int i;
for (i = 0; i < urb->num_sgs; i++) for (i = 0; i < urb->num_sgs; i++) {
skb_free_frag(sg_virt(&urb->sg[i])); sg = &urb->sg[i];
if (!sg)
continue;
skb_free_frag(sg_virt(sg));
}
if (buf->buf)
skb_free_frag(buf->buf);
usb_free_urb(buf->urb); usb_free_urb(buf->urb);
} }
EXPORT_SYMBOL_GPL(mt76u_buf_free); EXPORT_SYMBOL_GPL(mt76u_buf_free);
...@@ -345,6 +387,7 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, ...@@ -345,6 +387,7 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
{ {
struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_interface *intf = to_usb_interface(dev->dev);
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
u8 *data = buf->urb->num_sgs ? NULL : buf->buf;
unsigned int pipe; unsigned int pipe;
if (dir == USB_DIR_IN) if (dir == USB_DIR_IN)
...@@ -352,7 +395,7 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, ...@@ -352,7 +395,7 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
else else
pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[index]); pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[index]);
usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, buf->len, usb_fill_bulk_urb(buf->urb, udev, pipe, data, buf->len,
complete_fn, context); complete_fn, context);
trace_submit_urb(dev, buf->urb); trace_submit_urb(dev, buf->urb);
...@@ -393,10 +436,11 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len) ...@@ -393,10 +436,11 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
} }
static int static int
mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf)
{ {
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
u8 *data = sg_virt(&urb->sg[0]); struct urb *urb = buf->urb;
u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : buf->buf;
int data_len, len, nsgs = 1; int data_len, len, nsgs = 1;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -407,7 +451,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) ...@@ -407,7 +451,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
if (len < 0) if (len < 0)
return 0; return 0;
data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN); data_len = urb->num_sgs ? urb->sg[0].length : buf->len;
data_len = min_t(int, len, data_len - MT_DMA_HDR_LEN);
if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size)) if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size))
return 0; return 0;
...@@ -419,7 +464,7 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) ...@@ -419,7 +464,7 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
__skb_put(skb, data_len); __skb_put(skb, data_len);
len -= data_len; len -= data_len;
while (len > 0) { while (len > 0 && urb->num_sgs) {
data_len = min_t(int, len, urb->sg[nsgs].length); data_len = min_t(int, len, urb->sg[nsgs].length);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
sg_page(&urb->sg[nsgs]), sg_page(&urb->sg[nsgs]),
...@@ -447,7 +492,8 @@ static void mt76u_complete_rx(struct urb *urb) ...@@ -447,7 +492,8 @@ static void mt76u_complete_rx(struct urb *urb)
case -ENOENT: case -ENOENT:
return; return;
default: default:
dev_err(dev->dev, "rx urb failed: %d\n", urb->status); dev_err_ratelimited(dev->dev, "rx urb failed: %d\n",
urb->status);
/* fall through */ /* fall through */
case 0: case 0:
break; break;
...@@ -464,12 +510,26 @@ static void mt76u_complete_rx(struct urb *urb) ...@@ -464,12 +510,26 @@ static void mt76u_complete_rx(struct urb *urb)
spin_unlock_irqrestore(&q->lock, flags); spin_unlock_irqrestore(&q->lock, flags);
} }
static int
mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q,
struct mt76u_buf *buf, int nsgs)
{
if (dev->usb.sg_en) {
return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size,
SKB_WITH_OVERHEAD(q->buf_size));
} else {
buf->buf = page_frag_alloc(&q->rx_page, q->buf_size,
GFP_ATOMIC);
return buf->buf ? 0 : -ENOMEM;
}
}
static void mt76u_rx_tasklet(unsigned long data) static void mt76u_rx_tasklet(unsigned long data)
{ {
struct mt76_dev *dev = (struct mt76_dev *)data; struct mt76_dev *dev = (struct mt76_dev *)data;
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
int err, nsgs, buf_len = q->buf_size;
struct mt76u_buf *buf; struct mt76u_buf *buf;
int err, count;
rcu_read_lock(); rcu_read_lock();
...@@ -478,11 +538,9 @@ static void mt76u_rx_tasklet(unsigned long data) ...@@ -478,11 +538,9 @@ static void mt76u_rx_tasklet(unsigned long data)
if (!buf) if (!buf)
break; break;
nsgs = mt76u_process_rx_entry(dev, buf->urb); count = mt76u_process_rx_entry(dev, buf);
if (nsgs > 0) { if (count > 0) {
err = mt76u_fill_rx_sg(dev, buf, nsgs, err = mt76u_refill_rx(dev, q, buf, count);
buf_len,
SKB_WITH_OVERHEAD(buf_len));
if (err < 0) if (err < 0)
break; break;
} }
...@@ -520,7 +578,7 @@ EXPORT_SYMBOL_GPL(mt76u_submit_rx_buffers); ...@@ -520,7 +578,7 @@ EXPORT_SYMBOL_GPL(mt76u_submit_rx_buffers);
static int mt76u_alloc_rx(struct mt76_dev *dev) static int mt76u_alloc_rx(struct mt76_dev *dev)
{ {
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
int i, err, nsgs; int i, err;
spin_lock_init(&q->rx_page_lock); spin_lock_init(&q->rx_page_lock);
spin_lock_init(&q->lock); spin_lock_init(&q->lock);
...@@ -530,23 +588,22 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) ...@@ -530,23 +588,22 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
if (!q->entry) if (!q->entry)
return -ENOMEM; return -ENOMEM;
if (mt76u_check_sg(dev)) { q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
q->buf_size = MT_RX_BUF_SIZE; q->ndesc = MT_NUM_RX_ENTRIES;
nsgs = MT_SG_MAX_SIZE; for (i = 0; i < q->ndesc; i++) {
} else { if (dev->usb.sg_en)
q->buf_size = PAGE_SIZE; err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf,
nsgs = 1; MT_SG_MAX_SIZE, q->buf_size,
} SKB_WITH_OVERHEAD(q->buf_size),
GFP_KERNEL);
for (i = 0; i < MT_NUM_RX_ENTRIES; i++) { else
err = mt76u_buf_alloc(dev, &q->entry[i].ubuf, err = mt76u_buf_alloc(dev, &q->entry[i].ubuf,
nsgs, q->buf_size, q->buf_size,
SKB_WITH_OVERHEAD(q->buf_size), SKB_WITH_OVERHEAD(q->buf_size),
GFP_KERNEL); GFP_KERNEL);
if (err < 0) if (err < 0)
return err; return err;
} }
q->ndesc = MT_NUM_RX_ENTRIES;
return mt76u_submit_rx_buffers(dev); return mt76u_submit_rx_buffers(dev);
} }
...@@ -691,7 +748,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, ...@@ -691,7 +748,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
{ {
struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_interface *intf = to_usb_interface(dev->dev);
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
u8 ep = q2ep(q->hw_idx); u8 *data = NULL, ep = q2ep(q->hw_idx);
struct mt76u_buf *buf; struct mt76u_buf *buf;
u16 idx = q->tail; u16 idx = q->tail;
unsigned int pipe; unsigned int pipe;
...@@ -708,12 +765,16 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, ...@@ -708,12 +765,16 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
buf = &q->entry[idx].ubuf; buf = &q->entry[idx].ubuf;
buf->done = false; buf->done = false;
if (dev->usb.sg_en) {
err = mt76u_tx_build_sg(skb, buf->urb); err = mt76u_tx_build_sg(skb, buf->urb);
if (err < 0) if (err < 0)
return err; return err;
} else {
data = skb->data;
}
pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[ep]); pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[ep]);
usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, skb->len, usb_fill_bulk_urb(buf->urb, udev, pipe, data, skb->len,
mt76u_complete_tx, buf); mt76u_complete_tx, buf);
q->tail = (q->tail + 1) % q->ndesc; q->tail = (q->tail + 1) % q->ndesc;
...@@ -749,10 +810,8 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) ...@@ -749,10 +810,8 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
{ {
struct mt76u_buf *buf; struct mt76u_buf *buf;
struct mt76_queue *q; struct mt76_queue *q;
size_t size;
int i, j; int i, j;
size = MT_SG_MAX_SIZE * sizeof(struct scatterlist);
for (i = 0; i < IEEE80211_NUM_ACS; i++) { for (i = 0; i < IEEE80211_NUM_ACS; i++) {
q = &dev->q_tx[i]; q = &dev->q_tx[i];
spin_lock_init(&q->lock); spin_lock_init(&q->lock);
...@@ -774,11 +833,17 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) ...@@ -774,11 +833,17 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
if (!buf->urb) if (!buf->urb)
return -ENOMEM; return -ENOMEM;
buf->urb->sg = devm_kzalloc(dev->dev, size, GFP_KERNEL); if (dev->usb.sg_en) {
size_t size = MT_SG_MAX_SIZE *
sizeof(struct scatterlist);
buf->urb->sg = devm_kzalloc(dev->dev, size,
GFP_KERNEL);
if (!buf->urb->sg) if (!buf->urb->sg)
return -ENOMEM; return -ENOMEM;
} }
} }
}
return 0; return 0;
} }
...@@ -838,16 +903,9 @@ int mt76u_alloc_queues(struct mt76_dev *dev) ...@@ -838,16 +903,9 @@ int mt76u_alloc_queues(struct mt76_dev *dev)
err = mt76u_alloc_rx(dev); err = mt76u_alloc_rx(dev);
if (err < 0) if (err < 0)
goto err;
err = mt76u_alloc_tx(dev);
if (err < 0)
goto err;
return 0;
err:
mt76u_queues_deinit(dev);
return err; return err;
return mt76u_alloc_tx(dev);
} }
EXPORT_SYMBOL_GPL(mt76u_alloc_queues); EXPORT_SYMBOL_GPL(mt76u_alloc_queues);
...@@ -882,6 +940,8 @@ int mt76u_init(struct mt76_dev *dev, ...@@ -882,6 +940,8 @@ int mt76u_init(struct mt76_dev *dev,
dev->bus = &mt76u_ops; dev->bus = &mt76u_ops;
dev->queue_ops = &usb_queue_ops; dev->queue_ops = &usb_queue_ops;
usb->sg_en = mt76u_check_sg(dev);
return mt76u_set_endpoints(intf, usb); return mt76u_set_endpoints(intf, usb);
} }
EXPORT_SYMBOL_GPL(mt76u_init); EXPORT_SYMBOL_GPL(mt76u_init);
......
...@@ -29,9 +29,8 @@ int mt76u_mcu_init_rx(struct mt76_dev *dev) ...@@ -29,9 +29,8 @@ int mt76u_mcu_init_rx(struct mt76_dev *dev)
struct mt76_usb *usb = &dev->usb; struct mt76_usb *usb = &dev->usb;
int err; int err;
err = mt76u_buf_alloc(dev, &usb->mcu.res, 1, err = mt76u_buf_alloc(dev, &usb->mcu.res, MCU_RESP_URB_SIZE,
MCU_RESP_URB_SIZE, MCU_RESP_URB_SIZE, MCU_RESP_URB_SIZE, GFP_KERNEL);
GFP_KERNEL);
if (err < 0) if (err < 0)
return err; return err;
...@@ -48,9 +47,11 @@ EXPORT_SYMBOL_GPL(mt76u_mcu_init_rx); ...@@ -48,9 +47,11 @@ EXPORT_SYMBOL_GPL(mt76u_mcu_init_rx);
void mt76u_mcu_deinit(struct mt76_dev *dev) void mt76u_mcu_deinit(struct mt76_dev *dev)
{ {
struct mt76_usb *usb = &dev->usb; struct mt76u_buf *buf = &dev->usb.mcu.res;
usb_kill_urb(usb->mcu.res.urb); if (buf->urb) {
mt76u_buf_free(&usb->mcu.res); usb_kill_urb(buf->urb);
mt76u_buf_free(buf);
}
} }
EXPORT_SYMBOL_GPL(mt76u_mcu_deinit); EXPORT_SYMBOL_GPL(mt76u_mcu_deinit);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment