rework mt76u layer to support new devices
Subsystems (2)
Lorenzo Bianconi
maintainercover rework mt76u layer to support new devices
Rework mt76u layer to support new devices (e.g. 7663u).
The main difference between mt7663u and previous mt76u dongles (e.g. mt76x2u) is mt7663u reports fw events through a dedicated mcu hw queue. Moreover, mt7663u relies on full usb 32bit address space to configure the usb dongle.
This series is based on "mt76: channel switch support for USB devices"
https://patchwork.kernel.org/cover/11301193/
Lorenzo Bianconi (18):
mt76: mt76u: check tx_status_data pointer in mt76u_tx_tasklet
mt76: mt76u: add mt76u_process_rx_queue utility routine
mt76: mt76u: add mt76_queue to mt76u_get_next_rx_entry signature
mt76: mt76u: add mt76_queue to mt76u_refill_rx signature
mt76: mt76u: use mt76_queue as mt76u_complete_rx context
mt76: mt76u: add queue id parameter to mt76u_submit_rx_buffers
mt76: mt76u: move mcu buffer allocation in mt76x02u drivers
mt76: mt76u: introduce mt76u_free_rx_queue utility routine
mt76: mt76u: stop/free all possible rx queues
mt76: mt76u: add mt76u_alloc_rx_queue utility routine
mt76: mt76u: add queue parameter to mt76u_rx_urb_alloc
mt76: mt76u: resume all rx queue in mt76u_resume_rx
mt76: mt76u: introduce mt76u_alloc_mcu_queue utility routine
mt76: mt76u: add {read/write}_extended utility routines
mt76: mt76u: take into account different queue mapping for 7663
mt76: mt76u: introduce mt76u_skb_dma_info routine
mt76: mt76u: add endpoint to mt76u_bulk_msg signature
mt76: mt76u: introduce MT_DRV_RX_DMA_HDR flag
drivers/net/wireless/mediatek/mt76/mt76.h | 15 +- .../net/wireless/mediatek/mt76/mt76x0/usb.c | 8 +- .../wireless/mediatek/mt76/mt76x02_usb_core.c | 25 +- .../wireless/mediatek/mt76/mt76x02_usb_mcu.c | 9 +- .../net/wireless/mediatek/mt76/mt76x2/usb.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_init.c | 6 + drivers/net/wireless/mediatek/mt76/usb.c | 370 +++++++++++++----- 7 files changed, 309 insertions(+), 126 deletions(-)
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 1/18 mt76: mt76u: check tx_status_data pointer in mt76u_tx_tasklet
New devices (e.g. mt7663u) do not rely on stats workqueue to load tx statistics but will be reported by the firmware. Check tx_status_data pointer in mt76u_tx_tasklet in order to reuse tx tasklet for new devices
--- drivers/net/wireless/mediatek/mt76/usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/usb.c +2 -1
@@ -708,7 +708,8 @@ static void mt76u_tx_tasklet(unsigned long data)mt76_txq_schedule (&dev->phy, i); -if (!test_and_set_bit (MT76_READING_STATS , &dev->phy.state)) +if (dev->drv->tx_status_data && + !test_and_set_bit (MT76_READING_STATS , &dev->phy.state))queue_work (dev->usb.stat_wq, &dev->usb.stat_work);if (wake)ieee80211_wake_queue (dev->hw, i);
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 2/18 mt76: mt76u: add mt76u_process_rx_queue utility routine
In reply to Lorenzo BianconiIntroduce mt76u_process_rx_queue routine to process rx hw queue. This is a preliminary patch to support new devices (e.g. mt7663u) that rely on a hw queue for mcu messages
--- drivers/net/wireless/mediatek/mt76/usb.c | 30 +++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-)
drivers/net/wireless/mediatek/mt76/usb.c +19 -11
@@ -468,9 +468,9 @@ mt76u_build_rx_skb(void *data, int len, int buf_size) }static int -mt76u_process_rx_entry (struct mt76_dev *dev,struct urb *urb) +mt76u_process_rx_entry (struct mt76_dev *dev,struct urb *urb, +int buf_size) { -struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ];u8 *data = urb->num_sgs ?sg_virt (&urb->sg[0 ]) : urb->transfer_buffer;int data_len = urb->num_sgs ? urb->sg[0 ].length : urb->actual_length;int len, nsgs =1 ;
@@ -484,7 +484,7 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)return 0 ; data_len =min_t (int, len, data_len -MT_DMA_HDR_LEN ); - skb =mt76u_build_rx_skb (data, data_len, q->buf_size); + skb =mt76u_build_rx_skb (data, data_len, buf_size);if (!skb)return 0 ;
@@ -493,8 +493,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) data_len =min_t (int, len, urb->sg[nsgs].length);skb_add_rx_frag (skb,skb_shinfo (skb)->nr_frags,sg_page (&urb->sg[nsgs]), - urb->sg[nsgs].offset, - data_len, q->buf_size); + urb->sg[nsgs].offset, data_len, + buf_size); len -= data_len; nsgs++; }
@@ -545,20 +545,19 @@ mt76u_submit_rx_buf(struct mt76_dev *dev, struct urb *urb)return usb_submit_urb (urb,GFP_ATOMIC ); } -static void mt76u_rx_tasklet (unsigned long data) +static void +mt76u_process_rx_queue (struct mt76_dev *dev,struct mt76_queue *q) { -struct mt76_dev *dev = (struct mt76_dev *)data; +int qid = q - &dev->q_rx[MT_RXQ_MAIN ];struct urb *urb;int err, count; -rcu_read_lock (); -while (true) { urb =mt76u_get_next_rx_entry (dev);if (!urb)break ; - count =mt76u_process_rx_entry (dev, urb); + count =mt76u_process_rx_entry (dev, urb, q->buf_size);if (count >0 ) { err =mt76u_refill_rx (dev, urb, count,GFP_ATOMIC );if (err <0 )
@@ -566,8 +565,17 @@ static void mt76u_rx_tasklet(unsigned long data) }mt76u_submit_rx_buf (dev, urb); } -mt76_rx_poll_complete (dev,MT_RXQ_MAIN ,NULL ); +if (qid ==MT_RXQ_MAIN ) +mt76_rx_poll_complete (dev,MT_RXQ_MAIN ,NULL ); +} +static void mt76u_rx_tasklet (unsigned long data) +{ +struct mt76_dev *dev = (struct mt76_dev *)data; +struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ]; + +rcu_read_lock (); +mt76u_process_rx_queue (dev, q);rcu_read_unlock (); }
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 3/18 mt76: mt76u: add mt76_queue to mt76u_get_next_rx_entry signature
In reply to Lorenzo BianconiRely on mt76_queue pointer in mt76u_get_next_rx_entry in order to add support for new devices (e.g 7663u) that reports fw events through hw rx mcu queue
--- drivers/net/wireless/mediatek/mt76/usb.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/usb.c +3 -4
@@ -398,10 +398,9 @@ mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index, urb->context = context; } -static inline struct urb * -mt76u_get_next_rx_entry (struct mt76_dev *dev) +static struct urb * +mt76u_get_next_rx_entry (struct mt76_queue *q) { -struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ];struct urb *urb =NULL ;unsigned long flags;
@@ -553,7 +552,7 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)int err, count;while (true) { - urb =mt76u_get_next_rx_entry (dev); + urb =mt76u_get_next_rx_entry (q);if (!urb)break ;
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 4/18 mt76: mt76u: add mt76_queue to mt76u_refill_rx signature
In reply to Lorenzo BianconiIntroduce mt76_queue parameter to mt76u_refill_rx signature in order to reuse it for mcu hw rx queue
--- drivers/net/wireless/mediatek/mt76/usb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/usb.c +7 -5
@@ -318,11 +318,12 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb, }static int -mt76u_refill_rx (struct mt76_dev *dev,struct urb *urb,int nsgs,gfp_t gfp) +mt76u_refill_rx (struct mt76_dev *dev,struct mt76_queue *q, +struct urb *urb,int nsgs,gfp_t gfp) { -struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ]; +enum mt76_rxq_id qid = q - &dev->q_rx[MT_RXQ_MAIN ]; -if (dev->usb.sg_en) +if (qid ==MT_RXQ_MAIN && dev->usb.sg_en)return mt76u_fill_rx_sg (dev, q, urb, nsgs, gfp); urb->transfer_buffer_length = q->buf_size;
@@ -355,13 +356,14 @@ mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e,static int mt76u_rx_urb_alloc (struct mt76_dev *dev,struct mt76_queue_entry *e) { +struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ];int err; err =mt76u_urb_alloc (dev, e,MT_RX_SG_MAX_SIZE );if (err)return err; -return mt76u_refill_rx (dev, e->urb,MT_RX_SG_MAX_SIZE , +return mt76u_refill_rx (dev, q, e->urb,MT_RX_SG_MAX_SIZE ,GFP_KERNEL ); }
@@ -558,7 +560,7 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) count =mt76u_process_rx_entry (dev, urb, q->buf_size);if (count >0 ) { - err =mt76u_refill_rx (dev, urb, count,GFP_ATOMIC ); + err =mt76u_refill_rx (dev, q, urb, count,GFP_ATOMIC );if (err <0 )break ; }
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 5/18 mt76: mt76u: use mt76_queue as mt76u_complete_rx context
In reply to Lorenzo BianconiIn order to reuse mt76u_complete_rx for both data and mcu rx queue, rely on mt76_queue as urb context in mt76u_complete_rx. Moreover set usb rx endoint according to rx queue in mt76u_submit_rx_buf. This is a preliminary patch to add mt7663u support
--- drivers/net/wireless/mediatek/mt76/usb.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
drivers/net/wireless/mediatek/mt76/usb.c +10 -7
@@ -506,8 +506,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb,static void mt76u_complete_rx (struct urb *urb) { -struct mt76_dev *dev = urb->context; -struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ]; +struct mt76_dev *dev =dev_get_drvdata (&urb->dev->dev); +struct mt76_queue *q = urb->context;unsigned long flags;trace_rx_urb (dev, urb);
@@ -537,10 +537,13 @@ static void mt76u_complete_rx(struct urb *urb) }static int -mt76u_submit_rx_buf (struct mt76_dev *dev,struct urb *urb) +mt76u_submit_rx_buf (struct mt76_dev *dev,enum mt76_rxq_id qid, +struct urb *urb) { -mt76u_fill_bulk_urb (dev,USB_DIR_IN ,MT_EP_IN_PKT_RX , urb, - mt76u_complete_rx, dev); +int ep = qid ==MT_RXQ_MAIN ?MT_EP_IN_PKT_RX :MT_EP_IN_CMD_RESP ; + +mt76u_fill_bulk_urb (dev,USB_DIR_IN , ep, urb, + mt76u_complete_rx, &dev->q_rx[qid]);trace_submit_urb (dev, urb);return usb_submit_urb (urb,GFP_ATOMIC );
@@ -564,7 +567,7 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)if (err <0 )break ; } -mt76u_submit_rx_buf (dev, urb); +mt76u_submit_rx_buf (dev, qid, urb); }if (qid ==MT_RXQ_MAIN )mt76_rx_poll_complete (dev,MT_RXQ_MAIN ,NULL );
@@ -588,7 +591,7 @@ static int mt76u_submit_rx_buffers(struct mt76_dev *dev)spin_lock_irqsave (&q->lock, flags);for (i =0 ; i < q->ndesc; i++) { - err =mt76u_submit_rx_buf (dev, q->entry[i].urb); + err =mt76u_submit_rx_buf (dev,MT_RXQ_MAIN , q->entry[i].urb);if (err <0 )break ; }
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 6/18 mt76: mt76u: add queue id parameter to mt76u_submit_rx_buffers
In reply to Lorenzo BianconiAdd queue_id parameter to mt76u_submit_rx_buffers in order to reuse it adding mt7663u support
--- drivers/net/wireless/mediatek/mt76/usb.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/usb.c +6 -5
@@ -583,15 +583,16 @@ static void mt76u_rx_tasklet(unsigned long data)rcu_read_unlock (); } -static int mt76u_submit_rx_buffers (struct mt76_dev *dev) +static int +mt76u_submit_rx_buffers (struct mt76_dev *dev,enum mt76_rxq_id qid) { -struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ]; +struct mt76_queue *q = &dev->q_rx[qid];unsigned long flags;int i, err =0 ;spin_lock_irqsave (&q->lock, flags);for (i =0 ; i < q->ndesc; i++) { - err =mt76u_submit_rx_buf (dev,MT_RXQ_MAIN , q->entry[i].urb); + err =mt76u_submit_rx_buf (dev, qid, q->entry[i].urb);if (err <0 )break ; }
@@ -628,7 +629,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)return err; } -return mt76u_submit_rx_buffers (dev); +return mt76u_submit_rx_buffers (dev,MT_RXQ_MAIN ); }static void mt76u_free_rx (struct mt76_dev *dev)
@@ -668,7 +669,7 @@ int mt76u_resume_rx(struct mt76_dev *dev)for (i =0 ; i < q->ndesc; i++)usb_unpoison_urb (q->entry[i].urb); -return mt76u_submit_rx_buffers (dev); +return mt76u_submit_rx_buffers (dev,MT_RXQ_MAIN ); }EXPORT_SYMBOL_GPL (mt76u_resume_rx);
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 7/18 mt76: mt76u: move mcu buffer allocation in mt76x02u drivers
In reply to Lorenzo BianconiMove mcu buffer allocation in mt76x2u/mt76x0u drivers since newer chipsets (e.g. mt7763u) does not rely on synchronous mcu communication
--- drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 6 ++++++ drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c | 6 ++++++ drivers/net/wireless/mediatek/mt76/usb.c | 5 ----- 3 files changed, 12 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +6 -0
@@ -172,8 +172,14 @@ static int mt76x0u_init_hardware(struct mt76x02_dev *dev, bool reset)static int mt76x0u_register_device (struct mt76x02_dev *dev) {struct ieee80211_hw *hw = dev->mt76.hw; +struct mt76_usb *usb = &dev->mt76.usb;int err; + usb->mcu.data =devm_kmalloc (dev->mt76.dev,MCU_RESP_URB_SIZE , +GFP_KERNEL ); +if (!usb->mcu.data) +return -ENOMEM ; + err =mt76u_alloc_queues (&dev->mt76);if (err <0 ) goto out_err;
drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +6 -0
@@ -190,6 +190,7 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev)int mt76x2u_register_device (struct mt76x02_dev *dev) {struct ieee80211_hw *hw =mt76_hw (dev); +struct mt76_usb *usb = &dev->mt76.usb;int err;INIT_DELAYED_WORK (&dev->cal_work, mt76x2u_phy_calibrate);
@@ -199,6 +200,11 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)if (err <0 )return err; + usb->mcu.data =devm_kmalloc (dev->mt76.dev,MCU_RESP_URB_SIZE , +GFP_KERNEL ); +if (!usb->mcu.data) +return -ENOMEM ; + err =mt76u_alloc_queues (&dev->mt76);if (err <0 ) goto fail;
drivers/net/wireless/mediatek/mt76/usb.c +0 -5
@@ -605,14 +605,9 @@ mt76u_submit_rx_buffers(struct mt76_dev *dev, enum mt76_rxq_id qid)static int mt76u_alloc_rx (struct mt76_dev *dev) { -struct mt76_usb *usb = &dev->usb;struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ];int i, err; - usb->mcu.data =devm_kmalloc (dev->dev,MCU_RESP_URB_SIZE ,GFP_KERNEL ); -if (!usb->mcu.data) -return -ENOMEM ; -spin_lock_init (&q->lock); q->entry = devm_kcalloc(dev->dev, MT_NUM_RX_ENTRIES, sizeof(*q->entry),
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 8/18 mt76: mt76u: introduce mt76u_free_rx_queue utility routine
In reply to Lorenzo BianconiIntroduce mt76u_free_rx_queue utility routine to free rx hw queue. This is a preliminary patch to support new devices (e.g. mt7663u) that rely on a hw queue for mcu messages
--- drivers/net/wireless/mediatek/mt76/usb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/usb.c +9 -2
@@ -627,9 +627,9 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)return mt76u_submit_rx_buffers (dev,MT_RXQ_MAIN ); } -static void mt76u_free_rx (struct mt76_dev *dev) +static void +mt76u_free_rx_queue (struct mt76_dev *dev,struct mt76_queue *q) { -struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ];struct page *page;int i;
@@ -644,6 +644,13 @@ static void mt76u_free_rx(struct mt76_dev *dev)memset (&q->rx_page,0 ,sizeof (q->rx_page)); } +static void mt76u_free_rx (struct mt76_dev *dev) +{ +struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ]; + +mt76u_free_rx_queue (dev, q); +} +void mt76u_stop_rx (struct mt76_dev *dev) {struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ];
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 9/18 mt76: mt76u: stop/free all possible rx queues
In reply to Lorenzo BianconiStop/free all configured rx queues (data/mcu) in mt76u_stop_rx/mt76u_free_rx. This is a preliminary patch to support new devices (e.g. mt7663u) that rely on a hw queue for mcu messages
--- drivers/net/wireless/mediatek/mt76/usb.c | 25 ++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/usb.c +19 -6
@@ -646,18 +646,31 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)static void mt76u_free_rx (struct mt76_dev *dev) { -struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ]; +struct mt76_queue *q; +int i; + +for (i =0 ; i < __MT_RXQ_MAX; i++) { + q = &dev->q_rx[i]; +if (!q->ndesc) +continue ; -mt76u_free_rx_queue (dev, q); +mt76u_free_rx_queue (dev, q); + } }void mt76u_stop_rx (struct mt76_dev *dev) { -struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ]; -int i; +struct mt76_queue *q; +int i, j; -for (i =0 ; i < q->ndesc; i++) -usb_poison_urb (q->entry[i].urb); +for (i =0 ; i < __MT_RXQ_MAX; i++) { + q = &dev->q_rx[i]; +if (!q->ndesc) +continue ; + +for (j =0 ; j < q->ndesc; j++) +usb_poison_urb (q->entry[j].urb); + }tasklet_kill (&dev->usb.rx_tasklet); }
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 10/18 mt76: mt76u: add mt76u_alloc_rx_queue utility routine
In reply to Lorenzo BianconiIntroduce mt76u_alloc_rx_queue routine to allocate rx hw queue. This is a preliminary patch to support new devices (e.g. mt7663u) that rely on a hw queue for mcu messages
--- drivers/net/wireless/mediatek/mt76/usb.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/usb.c +5 -4
@@ -603,9 +603,10 @@ mt76u_submit_rx_buffers(struct mt76_dev *dev, enum mt76_rxq_id qid)return err; } -static int mt76u_alloc_rx (struct mt76_dev *dev) +static int +mt76u_alloc_rx_queue (struct mt76_dev *dev,enum mt76_rxq_id qid) { -struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ]; +struct mt76_queue *q = &dev->q_rx[qid];int i, err;spin_lock_init (&q->lock);
@@ -624,7 +625,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)return err; } -return mt76u_submit_rx_buffers (dev,MT_RXQ_MAIN ); +return mt76u_submit_rx_buffers (dev, qid); } static void
@@ -966,7 +967,7 @@ int mt76u_alloc_queues(struct mt76_dev *dev) {int err; - err =mt76u_alloc_rx (dev); + err =mt76u_alloc_rx_queue (dev,MT_RXQ_MAIN );if (err <0 )return err;
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 11/18 mt76: mt76u: add queue parameter to mt76u_rx_urb_alloc
In reply to Lorenzo BianconiAdd mt76_queue parameter to mt76u_rx_urb_alloc signature since this routine will be used to allocate urbs for mcu hw queue used by new chipset generation (e.g. mt7663u). Check sg_max_size in in mt76u_urb_alloc in order to use linear urb for mcu queue
--- drivers/net/wireless/mediatek/mt76/usb.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
drivers/net/wireless/mediatek/mt76/usb.c +9 -8
@@ -347,24 +347,25 @@ mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e,usb_init_urb (e->urb); -if (dev->usb.sg_en) +if (dev->usb.sg_en && sg_max_size >0 ) e->urb->sg = (struct scatterlist *)(e->urb +1 );return 0 ; }static int -mt76u_rx_urb_alloc (struct mt76_dev *dev,struct mt76_queue_entry *e) +mt76u_rx_urb_alloc (struct mt76_dev *dev,struct mt76_queue *q, +struct mt76_queue_entry *e) { -struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ]; -int err; +enum mt76_rxq_id qid = q - &dev->q_rx[MT_RXQ_MAIN ]; +int err, sg_size; - err =mt76u_urb_alloc (dev, e,MT_RX_SG_MAX_SIZE ); + sg_size = qid ==MT_RXQ_MAIN ?MT_RX_SG_MAX_SIZE :0 ; + err =mt76u_urb_alloc (dev, e, sg_size);if (err)return err; -return mt76u_refill_rx (dev, q, e->urb,MT_RX_SG_MAX_SIZE , -GFP_KERNEL ); +return mt76u_refill_rx (dev, q, e->urb, sg_size,GFP_KERNEL ); }static void mt76u_urb_free (struct urb *urb)
@@ -620,7 +621,7 @@ mt76u_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid) q->buf_size =PAGE_SIZE ;for (i =0 ; i < q->ndesc; i++) { - err =mt76u_rx_urb_alloc (dev, &q->entry[i]); + err =mt76u_rx_urb_alloc (dev, q, &q->entry[i]);if (err <0 )return err; }
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 12/18 mt76: mt76u: resume all rx queue in mt76u_resume_rx
In reply to Lorenzo BianconiResume all possible rx queues after suspend. This is a preliminary patch to support mt7663u devices
--- drivers/net/wireless/mediatek/mt76/usb.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/usb.c +16 -5
@@ -680,13 +680,24 @@ EXPORT_SYMBOL_GPL(mt76u_stop_rx);int mt76u_resume_rx (struct mt76_dev *dev) { -struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN ]; -int i; +struct mt76_queue *q; +int i, j, err; -for (i =0 ; i < q->ndesc; i++) -usb_unpoison_urb (q->entry[i].urb); +for (i =0 ; i < __MT_RXQ_MAX; i++) { + q = &dev->q_rx[i]; -return mt76u_submit_rx_buffers (dev,MT_RXQ_MAIN ); +if (!q->ndesc) +continue ; + +for (j =0 ; j < q->ndesc; j++) +usb_unpoison_urb (q->entry[j].urb); + + err =mt76u_submit_rx_buffers (dev, i); +if (err <0 ) +return err; + } + +return 0 ; }EXPORT_SYMBOL_GPL (mt76u_resume_rx);
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 13/18 mt76: mt76u: introduce mt76u_alloc_mcu_queue utility routine
In reply to Lorenzo BianconiAdd mt76u_alloc_mcu_queue utility routine to allocate mcu hw rx queue. This is a preliminary patch to support new devices (e.g. mt7663u) that rely on a hw queue for mcu messages
--- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/usb.c | 6 ++++++ 2 files changed, 7 insertions(+)
drivers/net/wireless/mediatek/mt76/mt76.h +1 -0
@@ -888,6 +888,7 @@ void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val);int mt76u_init (struct mt76_dev *dev,struct usb_interface *intf);void mt76u_deinit (struct mt76_dev *dev); +int mt76u_alloc_mcu_queue (struct mt76_dev *dev);int mt76u_alloc_queues (struct mt76_dev *dev);void mt76u_stop_tx (struct mt76_dev *dev);void mt76u_stop_rx (struct mt76_dev *dev);
drivers/net/wireless/mediatek/mt76/usb.c +6 -0
@@ -629,6 +629,12 @@ mt76u_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid)return mt76u_submit_rx_buffers (dev, qid); } +int mt76u_alloc_mcu_queue (struct mt76_dev *dev) +{ +return mt76u_alloc_rx_queue (dev,MT_RXQ_MCU ); +} +EXPORT_SYMBOL_GPL (mt76u_alloc_mcu_queue); +static void mt76u_free_rx_queue (struct mt76_dev *dev,struct mt76_queue *q) {
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 14/18 mt76: mt76u: add {read/write}_extended utility routines
In reply to Lorenzo BianconiIntroduce extended utility routines to read/write data o usb bus. New devices (e.g. mt7663u) will rely on both upper and lower part of the register address. Add ext parameter to mt76u_init signature in order to reuse the code adding mt7663u support.
--- drivers/net/wireless/mediatek/mt76/mt76.h | 6 +- .../net/wireless/mediatek/mt76/mt76x0/usb.c | 2 +- .../net/wireless/mediatek/mt76/mt76x2/usb.c | 2 +- drivers/net/wireless/mediatek/mt76/usb.c | 142 ++++++++++++++---- 4 files changed, 123 insertions(+), 29 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +5 -1
@@ -357,12 +357,15 @@ struct mt76_rate_power {enum mt_vendor_req {MT_VEND_DEV_MODE =0x1 ,MT_VEND_WRITE =0x2 , +MT_VEND_POWER_ON =0x4 ,MT_VEND_MULTI_WRITE =0x6 ,MT_VEND_MULTI_READ =0x7 ,MT_VEND_READ_EEPROM =0x9 ,MT_VEND_WRITE_FCE =0x42 ,MT_VEND_WRITE_CFG =0x46 ,MT_VEND_READ_CFG =0x47 , +MT_VEND_READ_EXT =0x63 , +MT_VEND_WRITE_EXT =0x66 , };enum mt76u_in_ep {
@@ -886,8 +889,9 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, void *buf, size_t len);void mt76u_single_wr (struct mt76_dev *dev,const u8 req,const u16 offset,const u32 val); -int mt76u_init (struct mt76_dev *dev,struct usb_interface *intf);void mt76u_deinit (struct mt76_dev *dev); +int mt76u_init (struct mt76_dev *dev,struct usb_interface *intf, +bool ext);int mt76u_alloc_mcu_queue (struct mt76_dev *dev);int mt76u_alloc_queues (struct mt76_dev *dev);void mt76u_stop_tx (struct mt76_dev *dev);
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +1 -1
@@ -246,7 +246,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,usb_set_intfdata (usb_intf, dev);mt76x02u_init_mcu (mdev); - ret =mt76u_init (mdev, usb_intf); + ret =mt76u_init (mdev, usb_intf, false);if (ret) goto err;
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +1 -1
@@ -54,7 +54,7 @@ static int mt76x2u_probe(struct usb_interface *intf,usb_set_intfdata (intf, dev);mt76x02u_init_mcu (mdev); - err =mt76u_init (mdev, intf); + err =mt76u_init (mdev, intf, false);if (err <0 ) goto err;
drivers/net/wireless/mediatek/mt76/usb.c +116 -26
204 lines not on this page · raw message
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 15/18 mt76: mt76u: take into account different queue mapping for 7663
In reply to Lorenzo Bianconi7663u devices rely on a different endpoint mapping. Take it into account in mt76u_alloc_tx routine
--- drivers/net/wireless/mediatek/mt76/usb.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/usb.c +9 -1
@@ -964,6 +964,14 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q) } } +static u8 mt76u_ac_to_hwq (struct mt76_dev *dev,u8 ac) +{ +if (mt76_chip (dev) ==0x7663 ) +return ac ^0x3 ; + +return mt76_ac_to_hwq (ac); +} +static int mt76u_alloc_tx (struct mt76_dev *dev) {struct mt76_queue *q;
@@ -982,7 +990,7 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)return -ENOMEM ;spin_lock_init (&q->lock); - q->hw_idx =mt76_ac_to_hwq (i); + q->hw_idx =mt76u_ac_to_hwq (dev, i); dev->q_tx[i].q = q; q->entry = devm_kcalloc(dev->dev,
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 16/18 mt76: mt76u: introduce mt76u_skb_dma_info routine
In reply to Lorenzo BianconiIntroduce mt76u_skb_dma_info utility routine in mt76-usb module in order to be reused adding mt7663u support
--- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../wireless/mediatek/mt76/mt76x02_usb_core.c | 25 ++-------------- drivers/net/wireless/mediatek/mt76/usb.c | 29 +++++++++++++++++++ 3 files changed, 32 insertions(+), 23 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +1 -0
@@ -884,6 +884,7 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,return usb_bulk_msg (udev, pipe, data, len, actual_len, timeout); } +int mt76u_skb_dma_info (struct sk_buff *skb,u32 info);int mt76u_vendor_request (struct mt76_dev *dev,u8 req,u8 req_type,u16 val,u16 offset,void *buf,size_t len);
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +2 -23
@@ -46,8 +46,7 @@ EXPORT_SYMBOL_GPL(mt76x02u_mac_start);int mt76x02u_skb_dma_info (struct sk_buff *skb,int port,u32 flags) { -struct sk_buff *iter, *last = skb; -u32 info, pad; +u32 info;/* Buffer layout: * | 4B | xfer len | pad | 4B |
@@ -57,28 +56,8 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)*/ info =FIELD_PREP (MT_TXD_INFO_LEN ,round_up (skb->len,4 )) |FIELD_PREP (MT_TXD_INFO_DPORT , port) | flags; -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; - -/* First packet of a A-MSDU burst keeps track of the whole burst -* length, need to update length of it and the last packet. -*/ - skb_walk_frags(skb, iter) { - last = iter; -if (!iter->next) { - skb->data_len += pad; - skb->len += pad; -break ; - } - } - -if (skb_pad (last, pad)) -return -ENOMEM ; -__skb_put (last, pad); - -return 0 ; +return mt76u_skb_dma_info (skb, info); } int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
drivers/net/wireless/mediatek/mt76/usb.c +29 -0
@@ -907,6 +907,35 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb,return urb->num_sgs; } +int mt76u_skb_dma_info (struct sk_buff *skb,u32 info) +{ +struct sk_buff *iter, *last = skb; +u32 pad; + +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; + +/* First packet of a A-MSDU burst keeps track of the whole burst +* length, need to update length of it and the last packet. +*/ + skb_walk_frags(skb, iter) { + last = iter; +if (!iter->next) { + skb->data_len += pad; + skb->len += pad; +break ; + } + } + +if (skb_pad (last, pad)) +return -ENOMEM ; +__skb_put (last, pad); + +return 0 ; +} +EXPORT_SYMBOL_GPL (mt76u_skb_dma_info); + static int mt76u_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb, struct mt76_wcid *wcid,
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 17/18 mt76: mt76u: add endpoint to mt76u_bulk_msg signature
In reply to Lorenzo BianconiThis is a preliminary patch to support mt7663u usb dongles
--- drivers/net/wireless/mediatek/mt76/mt76.h | 6 +++--- drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +3 -3
@@ -869,7 +869,7 @@ static inline u8 q2ep(u8 qid)static inline int mt76u_bulk_msg (struct mt76_dev *dev,void *data,int len,int *actual_len, -int timeout) +int timeout,int ep) {struct usb_interface *uintf =to_usb_interface (dev->dev);struct usb_device *udev =interface_to_usbdev (uintf);
@@ -877,9 +877,9 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,unsigned int pipe;if (actual_len) - pipe =usb_rcvbulkpipe (udev, usb->in_ep[MT_EP_IN_CMD_RESP ]); + pipe =usb_rcvbulkpipe (udev, usb->in_ep[ep]);else - pipe =usb_sndbulkpipe (udev, usb->out_ep[MT_EP_OUT_INBAND_CMD ]); + pipe =usb_sndbulkpipe (udev, usb->out_ep[ep]);return usb_bulk_msg (udev, pipe, data, len, actual_len, timeout); }
drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +6 -3
@@ -55,7 +55,8 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq)u32 rxfce;for (i =0 ; i <5 ; i++) { - ret =mt76u_bulk_msg (dev, data,MCU_RESP_URB_SIZE , &len,300 ); + ret =mt76u_bulk_msg (dev, data,MCU_RESP_URB_SIZE , &len, +300 ,MT_EP_IN_CMD_RESP );if (ret == -ETIMEDOUT )continue ;if (ret)
@@ -103,7 +104,8 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb,if (ret)return ret; - ret =mt76u_bulk_msg (dev, skb->data, skb->len,NULL ,500 ); + ret =mt76u_bulk_msg (dev, skb->data, skb->len,NULL ,500 , +MT_EP_OUT_INBAND_CMD );if (ret)return ret;
@@ -248,7 +250,8 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, u8 *data, data_len =MT_CMD_HDR_LEN + len +sizeof (info); - err =mt76u_bulk_msg (&dev->mt76, data, data_len,NULL ,1000 ); + err =mt76u_bulk_msg (&dev->mt76, data, data_len,NULL ,1000 , +MT_EP_OUT_INBAND_CMD );if (err) {dev_err (dev->mt76.dev,"firmware upload failed: %d\n" , err);return err;
Signature · 1 line
2.24.1
Lorenzo Bianconi
maintainerPATCH 18/18 mt76: mt76u: introduce MT_DRV_RX_DMA_HDR flag
In reply to Lorenzo BianconiDefine MT_DRV_RX_DMA_HDR flag in drv_flag in order to not skip rx frame dma header since new devices (e.g. mt7663u) reports rx frame info in the usb dma header
--- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/usb.c | 31 ++++++++++++++--------- 2 files changed, 20 insertions(+), 12 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76.h +1 -0
@@ -286,6 +286,7 @@ struct mt76_hw_cap {#define MT_DRV_TXWI_NO_FREE BIT(0)#define MT_DRV_TX_ALIGNED4_SKBS BIT(1)#define MT_DRV_SW_RX_AIRTIME BIT(2) +#define MT_DRV_RX_DMA_HDR BIT(3)struct mt76_driver_ops {u32 drv_flags;
drivers/net/wireless/mediatek/mt76/usb.c +19 -12
@@ -506,14 +506,17 @@ mt76u_get_next_rx_entry(struct mt76_queue *q)return urb; } -static int mt76u_get_rx_entry_len (u8 *data,u32 data_len) +static int +mt76u_get_rx_entry_len (struct mt76_dev *dev,u8 *data, +u32 data_len) {u16 dma_len, min_len; dma_len =get_unaligned_le16 (data); - min_len =MT_DMA_HDR_LEN +MT_RX_RXWI_LEN + -MT_FCE_INFO_LEN ; +if (dev->drv->drv_flags &MT_DRV_RX_DMA_HDR ) +return dma_len; + min_len =MT_DMA_HDR_LEN +MT_RX_RXWI_LEN +MT_FCE_INFO_LEN ;if (data_len < min_len || !dma_len || dma_len +MT_DMA_HDR_LEN > data_len || (dma_len &0x3 ))
@@ -522,11 +525,14 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len) }static struct sk_buff * -mt76u_build_rx_skb (void *data,int len,int buf_size) +mt76u_build_rx_skb (struct mt76_dev *dev,void *data, +int len,int buf_size) { +int head_room, drv_flags = dev->drv->drv_flags;struct sk_buff *skb; -if (SKB_WITH_OVERHEAD (buf_size) <MT_DMA_HDR_LEN + len) { + head_room = drv_flags &MT_DRV_RX_DMA_HDR ?0 :MT_DMA_HDR_LEN ; +if (SKB_WITH_OVERHEAD (buf_size) < head_room + len) {struct page *page;/* slow path, not enough space for data and
@@ -536,8 +542,8 @@ mt76u_build_rx_skb(void *data, int len, int buf_size)if (!skb)return NULL ; -skb_put_data (skb, data +MT_DMA_HDR_LEN ,MT_SKB_HEAD_LEN ); - data += (MT_DMA_HDR_LEN +MT_SKB_HEAD_LEN ); +skb_put_data (skb, data + head_room,MT_SKB_HEAD_LEN ); + data += head_room +MT_SKB_HEAD_LEN ; page =virt_to_head_page (data); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, data - page_address(page),
@@ -551,7 +557,7 @@ mt76u_build_rx_skb(void *data, int len, int buf_size)if (!skb)return NULL ; -skb_reserve (skb,MT_DMA_HDR_LEN ); +skb_reserve (skb, head_room);__skb_put (skb, len);return skb;
@@ -563,18 +569,19 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb, {u8 *data = urb->num_sgs ?sg_virt (&urb->sg[0 ]) : urb->transfer_buffer;int data_len = urb->num_sgs ? urb->sg[0 ].length : urb->actual_length; -int len, nsgs =1 ; +int len, nsgs =1 , head_room, drv_flags = dev->drv->drv_flags;struct sk_buff *skb;if (!test_bit (MT76_STATE_INITIALIZED , &dev->phy.state))return 0 ; - len =mt76u_get_rx_entry_len (data, urb->actual_length); + len =mt76u_get_rx_entry_len (dev, data, urb->actual_length);if (len <0 )return 0 ; - data_len =min_t (int, len, data_len -MT_DMA_HDR_LEN ); - skb =mt76u_build_rx_skb (data, data_len, buf_size); + head_room = drv_flags &MT_DRV_RX_DMA_HDR ?0 :MT_DMA_HDR_LEN ; + data_len =min_t (int, len, data_len - head_room); + skb =mt76u_build_rx_skb (dev, data, data_len, buf_size);if (!skb)return 0 ;
Signature · 1 line
2.24.1