linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH v4 11/16] mt76: sdio: extend sdio module to support CONNAC2
       [not found] <YWcuGcFPGCtaPh+2@lore-desk--annotate>
@ 2021-10-13 21:22 ` sean.wang
  2021-11-22 17:10 ` [PATCH 2/2] mt76: mt7921s: fix the device cannot sleep deeply in suspend sean.wang
  1 sibling, 0 replies; 7+ messages in thread
From: sean.wang @ 2021-10-13 21:22 UTC (permalink / raw)
  To: lorenzo.bianconi
  Cc: nbd, sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Mark-YW.Chen, Deren.Wu, km.lin, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Eric.Liang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, jemele, abhishekpandit, shawnku,
	linux-wireless, linux-mediatek

From: Sean Wang <sean.wang@mediatek.com>

>[...]
>>
>> In the current driver, we can see we only created one Rx queue
>> (dev->q_rx with qid = 0) in mt76s_alloc_queues for processing all incoming packets including MCU events and wifi packets.
>>
>> And from the point of view of the device, mt7663s use the hardware
>> queue 0 for all MCU events and wifi packets; mt7921s use the hardware
>> queue 1 for all MCU events and wifi packets.
>>
>> So if we don't remap from hardware queue 1 to dev->q_rx[0] for mt7921s
>> to handle incoming packets, we will get the kernel panic on accessing the invalid pointer on dev->q_rx[1].
>>
>>	Sean
>>
>> >Regards,
>> >Lorenzo
>> >
>>
>> <snip>
>
>ok, what about doing something like the patch below?
>If it works for you, I will post a formal patch.

go ahead. that looks fine to me.

>
>Regards,
>Lorenzo
>

<snip>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] mt76: mt7921s: fix the device cannot sleep deeply in suspend
       [not found] <YWcuGcFPGCtaPh+2@lore-desk--annotate>
  2021-10-13 21:22 ` [PATCH v4 11/16] mt76: sdio: extend sdio module to support CONNAC2 sean.wang
@ 2021-11-22 17:10 ` sean.wang
  2021-11-22 18:10   ` Lorenzo Bianconi
  1 sibling, 1 reply; 7+ messages in thread
From: sean.wang @ 2021-11-22 17:10 UTC (permalink / raw)
  To: lorenzo.bianconi
  Cc: nbd, sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Mark-YW.Chen, Deren.Wu, km.lin, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Eric.Liang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, jemele, abhishekpandit, shawnku,
	linux-wireless, linux-mediatek

From: Sean Wang <sean.wang@mediatek.com>

>> From: Sean Wang <sean.wang@mediatek.com>
>>
>>
>> <snip>
>>
>> >> >>
>> >> >> -		if (test_bit(MT76_MCU_RESET, &dev->phy.state)) {
>> >> >> -			if (!mt76s_txqs_empty(dev))
>> >> >> -				continue;
>> >> >> -			else
>> >> >> -				wake_up(&sdio->wait);
>> >> >> -		}
>> >> >>	} while (nframes > 0);
>> >> >>
>> >> >> +	if (test_bit(MT76_MCU_RESET, &dev->phy.state) &&
>> >> >> +	    mt76s_txqs_empty(dev))
>> >> >> +		wake_up(&sdio->wait);
>> >> >> +
>> >>
>> >> If doing so, mt76s_txqs_empty may not always be true because
>> >> enqueuing packets to q_tx or MCU command to q_mcu simultanenously
>> >> from the other contexts in different cpu is possible.
>> >>
>> >> It seemed to me we should check it for each iteration to guarantee
>> >> that we can wake up the one that is waiting for the all the queues are empty at some time.
>> >
>> >IIUC what we are interested here is there are no queued frames into the hw queues during suspend or reset, right?
>>
>> That is not completely true. Take the suspend procedure on mt7921s as an example.
>>
>> That should be "There are no queued frames into the hw queues right after mt76_connac_mcu_set_hif_suspend."
>>
>> The MCU data and WiFi are all handled in mt76s_txrx_worker so we
>> should synchronize all of the Tx queues are all empty and then handle
>> mt76_connac_mcu_set_hif_suspend to guarantee mt76_connac_mcu_set_hif_suspend is the last one to access the SDIO bus and there is no frame that accesses SDIO bus afterhand.
>
>ack, correct, "there are no queued frames into the hw queues right after mt76_connac_mcu_set_hif_suspend."
>What I mean is we are not really checking there are no frames in the hw queue here, but mt76 sdio has processed all the frames, got my point? maybe it is what we are looking for..

It seemed to me there is no a way to check if no frames in the hw queue for mt7921s

I think we can discuss the topic "it is ok move the check out of the loop" with another patch in the future

because it seemed not related to the patch.

>
>Regards,
>Lorenzo
>
>>
>> >
>> >>
>> >> >>	/* enable interrupt */
>> >> >>	sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);
>> >> >>	sdio_release_host(sdio->func);
>> >> >>
>> >> >> Regards,
>> >> >> Lorenzo
>> >> >>
>> >> >> > --
>> >> >> > 2.25.1
>> >> >> >
>> >> >
>> >> >
>> >> >
>> >>
>> >

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] mt76: mt7921s: fix the device cannot sleep deeply in suspend
  2021-11-22 17:10 ` [PATCH 2/2] mt76: mt7921s: fix the device cannot sleep deeply in suspend sean.wang
@ 2021-11-22 18:10   ` Lorenzo Bianconi
  0 siblings, 0 replies; 7+ messages in thread
From: Lorenzo Bianconi @ 2021-11-22 18:10 UTC (permalink / raw)
  To: sean.wang
  Cc: lorenzo.bianconi, nbd, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Mark-YW.Chen, Deren.Wu, km.lin, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Eric.Liang,
	Stella.Chang, Tom.Chou, steve.lee, jsiuda, frankgor, jemele,
	abhishekpandit, shawnku, linux-wireless, linux-mediatek

[-- Attachment #1: Type: text/plain, Size: 2610 bytes --]

> From: Sean Wang <sean.wang@mediatek.com>
> 
> >> From: Sean Wang <sean.wang@mediatek.com>
> >>
> >>
> >> <snip>
> >>
> >> >> >>
> >> >> >> -		if (test_bit(MT76_MCU_RESET, &dev->phy.state)) {
> >> >> >> -			if (!mt76s_txqs_empty(dev))
> >> >> >> -				continue;
> >> >> >> -			else
> >> >> >> -				wake_up(&sdio->wait);
> >> >> >> -		}
> >> >> >>	} while (nframes > 0);
> >> >> >>
> >> >> >> +	if (test_bit(MT76_MCU_RESET, &dev->phy.state) &&
> >> >> >> +	    mt76s_txqs_empty(dev))
> >> >> >> +		wake_up(&sdio->wait);
> >> >> >> +
> >> >>
> >> >> If doing so, mt76s_txqs_empty may not always be true because
> >> >> enqueuing packets to q_tx or MCU command to q_mcu simultanenously
> >> >> from the other contexts in different cpu is possible.
> >> >>
> >> >> It seemed to me we should check it for each iteration to guarantee
> >> >> that we can wake up the one that is waiting for the all the queues are empty at some time.
> >> >
> >> >IIUC what we are interested here is there are no queued frames into the hw queues during suspend or reset, right?
> >>
> >> That is not completely true. Take the suspend procedure on mt7921s as an example.
> >>
> >> That should be "There are no queued frames into the hw queues right after mt76_connac_mcu_set_hif_suspend."
> >>
> >> The MCU data and WiFi are all handled in mt76s_txrx_worker so we
> >> should synchronize all of the Tx queues are all empty and then handle
> >> mt76_connac_mcu_set_hif_suspend to guarantee mt76_connac_mcu_set_hif_suspend is the last one to access the SDIO bus and there is no frame that accesses SDIO bus afterhand.
> >
> >ack, correct, "there are no queued frames into the hw queues right after mt76_connac_mcu_set_hif_suspend."
> >What I mean is we are not really checking there are no frames in the hw queue here, but mt76 sdio has processed all the frames, got my point? maybe it is what we are looking for..
> 
> It seemed to me there is no a way to check if no frames in the hw queue for mt7921s
> 
> I think we can discuss the topic "it is ok move the check out of the loop" with another patch in the future
> 
> because it seemed not related to the patch.

sure, fine to me.

Regards,
Lorenzo

> 
> >
> >Regards,
> >Lorenzo
> >
> >>
> >> >
> >> >>
> >> >> >>	/* enable interrupt */
> >> >> >>	sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);
> >> >> >>	sdio_release_host(sdio->func);
> >> >> >>
> >> >> >> Regards,
> >> >> >> Lorenzo
> >> >> >>
> >> >> >> > --
> >> >> >> > 2.25.1
> >> >> >> >
> >> >> >
> >> >> >
> >> >> >
> >> >>
> >> >

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 11/16] mt76: sdio: extend sdio module to support CONNAC2
  2021-10-13 17:56 ` [PATCH v4 11/16] mt76: sdio: extend sdio module to support CONNAC2 sean.wang
@ 2021-10-13 19:06   ` Lorenzo Bianconi
  0 siblings, 0 replies; 7+ messages in thread
From: Lorenzo Bianconi @ 2021-10-13 19:06 UTC (permalink / raw)
  To: sean.wang
  Cc: lorenzo.bianconi, nbd, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Mark-YW.Chen, Deren.Wu, km.lin, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Eric.Liang,
	Stella.Chang, Tom.Chou, steve.lee, jsiuda, frankgor, jemele,
	abhishekpandit, shawnku, linux-wireless, linux-mediatek

[-- Attachment #1: Type: text/plain, Size: 3533 bytes --]

[...]
> 
> In the current driver, we can see we only created one Rx queue (dev->q_rx with qid = 0)
> in mt76s_alloc_queues for processing all incoming packets including MCU events and wifi packets.
> 
> And from the point of view of the device,
> mt7663s use the hardware queue 0 for all MCU events and wifi packets;
> mt7921s use the hardware queue 1 for all MCU events and wifi packets.
> 
> So if we don't remap from hardware queue 1 to dev->q_rx[0] for mt7921s to handle incoming packets,
> we will get the kernel panic on accessing the invalid pointer on dev->q_rx[1].
> 
> 	Sean
> 
> >Regards,
> >Lorenzo
> >
> 
> <snip>

ok, what about doing something like the patch below?
If it works for you, I will post a formal patch.

Regards,
Lorenzo

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 792573dad2e1..25524a21dffa 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -1254,7 +1254,8 @@ void mt76u_queues_deinit(struct mt76_dev *dev);
 
 int mt76s_init(struct mt76_dev *dev, struct sdio_func *func,
 	       const struct mt76_bus_ops *bus_ops);
-int mt76s_alloc_queues(struct mt76_dev *dev);
+int mt76s_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid);
+int mt76s_alloc_tx(struct mt76_dev *dev);
 void mt76s_deinit(struct mt76_dev *dev);
 void mt76s_sdio_irq(struct sdio_func *func);
 void mt76s_txrx_worker(struct mt76_sdio *sdio);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
index c3bd163e0278..577561aaee31 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
@@ -147,7 +147,11 @@ static int mt7663s_probe(struct sdio_func *func,
 		}
 	}
 
-	ret = mt76s_alloc_queues(&dev->mt76);
+	ret = mt76s_alloc_rx_queue(mdev, MT_RXQ_MAIN);
+	if (ret < 0)
+		goto error;
+
+	ret = mt76s_alloc_tx(mdev);
 	if (ret)
 		goto error;
 
diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c
index bb40cc3e9c2b..c99acc21225e 100644
--- a/drivers/net/wireless/mediatek/mt76/sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/sdio.c
@@ -299,8 +299,7 @@ int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func, int hw_ver)
 }
 EXPORT_SYMBOL_GPL(mt76s_hw_init);
 
-static int
-mt76s_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid)
+int mt76s_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid)
 {
 	struct mt76_queue *q = &dev->q_rx[qid];
 
@@ -317,6 +316,7 @@ mt76s_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(mt76s_alloc_rx_queue);
 
 static struct mt76_queue *mt76s_alloc_tx_queue(struct mt76_dev *dev)
 {
@@ -338,7 +338,7 @@ static struct mt76_queue *mt76s_alloc_tx_queue(struct mt76_dev *dev)
 	return q;
 }
 
-static int mt76s_alloc_tx(struct mt76_dev *dev)
+int mt76s_alloc_tx(struct mt76_dev *dev)
 {
 	struct mt76_queue *q;
 	int i;
@@ -361,18 +361,7 @@ static int mt76s_alloc_tx(struct mt76_dev *dev)
 
 	return 0;
 }
-
-int mt76s_alloc_queues(struct mt76_dev *dev)
-{
-	int err;
-
-	err = mt76s_alloc_rx_queue(dev, MT_RXQ_MAIN);
-	if (err < 0)
-		return err;
-
-	return mt76s_alloc_tx(dev);
-}
-EXPORT_SYMBOL_GPL(mt76s_alloc_queues);
+EXPORT_SYMBOL_GPL(mt76s_alloc_tx);
 
 static struct mt76_queue_entry *
 mt76s_get_next_rx_entry(struct mt76_queue *q)

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 11/16] mt76: sdio: extend sdio module to support CONNAC2
       [not found] <YWcJe27HQMS7B85j@lore-desk--annotate>
@ 2021-10-13 17:56 ` sean.wang
  2021-10-13 19:06   ` Lorenzo Bianconi
  0 siblings, 1 reply; 7+ messages in thread
From: sean.wang @ 2021-10-13 17:56 UTC (permalink / raw)
  To: lorenzo.bianconi
  Cc: nbd, sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Mark-YW.Chen, Deren.Wu, km.lin, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Eric.Liang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, jemele, abhishekpandit, shawnku,
	linux-wireless, linux-mediatek

From: Sean Wang <sean.wang@mediatek.com>

>> From: Sean Wang <sean.wang@mediatek.com>
>>
>> Extend sdio module to support CONNAC2 hw that mt7921s rely on.
>>
>> Tested-by: Deren Wu <deren.wu@mediatek.com>
>> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
>> Co-developed-by: Deren Wu <deren.wu@mediatek.com>
>> Signed-off-by: Deren Wu <deren.wu@mediatek.com>
>> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
>> ---
>>  drivers/net/wireless/mediatek/mt76/mt76.h     |  5 +-
>>  .../net/wireless/mediatek/mt76/mt7615/sdio.c  |  5 +-
>>  drivers/net/wireless/mediatek/mt76/sdio.c     | 23 ++++++-
>>  drivers/net/wireless/mediatek/mt76/sdio.h     | 50 ++++++++++++++-
>>  .../net/wireless/mediatek/mt76/sdio_txrx.c    | 62 ++++++++++++++++---
>>  5 files changed, 128 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h
>> b/drivers/net/wireless/mediatek/mt76/mt76.h
>> index e2f33956a122..06f0d1348d52 100644
>> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
>> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
>> @@ -505,6 +505,8 @@ struct mt76_sdio {
>>
>>	struct sdio_func *func;
>>	void *intr_data;
>> +	int intr_size;
>> +	u8 hw_ver;
>>
>>	struct {
>>		int pse_data_quota;
>> @@ -1249,7 +1251,8 @@ int mt76s_alloc_queues(struct mt76_dev *dev);
>> void mt76s_deinit(struct mt76_dev *dev);  void mt76s_sdio_irq(struct
>> sdio_func *func);  void mt76s_txrx_worker(struct mt76_sdio *sdio);
>> -int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func);
>> +int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func,
>> +		  int hw_ver);
>>  u32 mt76s_rr(struct mt76_dev *dev, u32 offset);  void mt76s_wr(struct
>> mt76_dev *dev, u32 offset, u32 val);
>>  u32 mt76s_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val);
>> diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
>> b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
>> index f47e25f6dedb..a6b5d536d962 100644
>> --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
>> +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
>> @@ -100,7 +100,7 @@ static int mt7663s_probe(struct sdio_func *func,
>>	if (ret < 0)
>>		goto error;
>>
>> -	ret = mt76s_hw_init(mdev, func);
>> +	ret = mt76s_hw_init(mdev, func, MT76_CONNAC_SDIO);
>>	if (ret)
>>		goto error;
>>
>> @@ -108,8 +108,9 @@ static int mt7663s_probe(struct sdio_func *func,
>>		    (mt76_rr(dev, MT_HW_REV) & 0xff);
>>	dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
>>
>> +	mdev->sdio.intr_size = sizeof(struct mt76_connac_sdio_intr);
>>	mdev->sdio.intr_data = devm_kmalloc(mdev->dev,
>> -					    sizeof(struct mt76s_intr),
>> +					    mdev->sdio.intr_size,
>>					    GFP_KERNEL);
>>	if (!mdev->sdio.intr_data) {
>>		ret = -ENOMEM;
>> diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c
>> b/drivers/net/wireless/mediatek/mt76/sdio.c
>> index 82fb4c110b90..bb40cc3e9c2b 100644
>> --- a/drivers/net/wireless/mediatek/mt76/sdio.c
>> +++ b/drivers/net/wireless/mediatek/mt76/sdio.c
>> @@ -221,11 +221,13 @@ int mt76s_rd_rp(struct mt76_dev *dev, u32 base,
>> }  EXPORT_SYMBOL_GPL(mt76s_rd_rp);
>>
>> -int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func)
>> +int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func, int
>> +hw_ver)
>>  {
>>	u32 status, ctrl;
>>	int ret;
>>
>> +	dev->sdio.hw_ver = hw_ver;
>> +
>>	sdio_claim_host(func);
>>
>>	ret = sdio_enable_func(func);
>> @@ -255,12 +257,27 @@ int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func)
>>		goto disable_func;
>>
>>	ctrl = WHIER_RX0_DONE_INT_EN | WHIER_TX_DONE_INT_EN;
>> +	if (hw_ver == MT76_CONNAC2_SDIO)
>> +		ctrl |= WHIER_RX1_DONE_INT_EN;
>>	sdio_writel(func, ctrl, MCR_WHIER, &ret);
>>	if (ret < 0)
>>		goto disable_func;
>>
>> -	/* set WHISR as read clear and Rx aggregation number as 16 */
>> -	ctrl = FIELD_PREP(MAX_HIF_RX_LEN_NUM, 16);
>> +	switch (hw_ver) {
>> +	case MT76_CONNAC_SDIO:
>> +		/* set WHISR as read clear and Rx aggregation number as 16 */
>> +		ctrl = FIELD_PREP(MAX_HIF_RX_LEN_NUM, 16);
>> +		break;
>> +	default:
>> +		ctrl = sdio_readl(func, MCR_WHCR, &ret);
>> +		if (ret < 0)
>> +			goto disable_func;
>> +		ctrl &= ~MAX_HIF_RX_LEN_NUM_CONNAC2;
>> +		ctrl &= ~W_INT_CLR_CTRL; /* read clear */
>> +		ctrl |= FIELD_PREP(MAX_HIF_RX_LEN_NUM_CONNAC2, 0);
>> +		break;
>> +	}
>> +
>>	sdio_writel(func, ctrl, MCR_WHCR, &ret);
>>	if (ret < 0)
>>		goto disable_func;
>> diff --git a/drivers/net/wireless/mediatek/mt76/sdio.h
>> b/drivers/net/wireless/mediatek/mt76/sdio.h
>> index 03877d89e152..7d2ec044dcb1 100644
>> --- a/drivers/net/wireless/mediatek/mt76/sdio.h
>> +++ b/drivers/net/wireless/mediatek/mt76/sdio.h
>> @@ -21,7 +21,12 @@
>>  #define MCR_WHCR			0x000C
>>  #define W_INT_CLR_CTRL			BIT(1)
>>  #define RECV_MAILBOX_RD_CLR_EN		BIT(2)
>> +#define WF_SYS_RSTB			BIT(4) /* supported in CONNAC2 */
>> +#define WF_WHOLE_PATH_RSTB		BIT(5) /* supported in CONNAC2 */
>> +#define WF_SDIO_WF_PATH_RSTB		BIT(6) /* supported in CONNAC2 */
>>  #define MAX_HIF_RX_LEN_NUM		GENMASK(13, 8)
>> +#define MAX_HIF_RX_LEN_NUM_CONNAC2	GENMASK(14, 8) /* supported in CONNAC2 */
>> +#define WF_RST_DONE			BIT(15) /* supported in CONNAC2 */
>>  #define RX_ENHANCE_MODE			BIT(16)
>>
>>  #define MCR_WHISR			0x0010
>> @@ -29,6 +34,7 @@
>>  #define WHIER_D2H_SW_INT		GENMASK(31, 8)
>>  #define WHIER_FW_OWN_BACK_INT_EN	BIT(7)
>>  #define WHIER_ABNORMAL_INT_EN		BIT(6)
>> +#define WHIER_WDT_INT_EN		BIT(5) /* supported in CONNAC2 */
>>  #define WHIER_RX1_DONE_INT_EN		BIT(2)
>>  #define WHIER_RX0_DONE_INT_EN		BIT(1)
>>  #define WHIER_TX_DONE_INT_EN		BIT(0)
>> @@ -100,7 +106,37 @@
>>
>>  #define MCR_SWPCDBGR			0x0154
>>
>> -struct mt76s_intr {
>> +#define MCR_H2DSM2R			0x0160 /* supported in CONNAC2 */
>> +#define MCR_H2DSM3R			0x0164 /* supported in CONNAC2 */
>> +#define MCR_D2HRM3R			0x0174 /* supported in CONNAC2 */
>> +#define MCR_WTQCR8			0x0190 /* supported in CONNAC2 */
>> +#define MCR_WTQCR9			0x0194 /* supported in CONNAC2 */
>> +#define MCR_WTQCR10			0x0198 /* supported in CONNAC2 */
>> +#define MCR_WTQCR11			0x019C /* supported in CONNAC2 */
>> +#define MCR_WTQCR12			0x01A0 /* supported in CONNAC2 */
>> +#define MCR_WTQCR13			0x01A4 /* supported in CONNAC2 */
>> +#define MCR_WTQCR14			0x01A8 /* supported in CONNAC2 */
>> +#define MCR_WTQCR15			0x01AC /* supported in CONNAC2 */
>> +
>> +enum mt76_connac_sdio_ver {
>> +	MT76_CONNAC_SDIO,
>> +	MT76_CONNAC2_SDIO,
>> +};
>> +
>> +struct mt76_connac2_sdio_intr {
>> +	u32 isr;
>> +	struct {
>> +		u32 wtqcr[16];
>> +	} tx;
>> +	struct {
>> +		u16 num[2];
>> +		u16 len0[16];
>> +		u16 len1[128];
>> +	} rx;
>> +	u32 rec_mb[2];
>> +} __packed;
>> +
>> +struct mt76_connac_sdio_intr {
>>	u32 isr;
>>	struct {
>>		u32 wtqcr[8];
>> @@ -112,4 +148,16 @@ struct mt76s_intr {
>>	u32 rec_mb[2];
>>  } __packed;
>>
>> +struct mt76s_intr {
>> +	u32 isr;
>> +	struct {
>> +		u32 *wtqcr;
>> +	} tx;
>> +	struct {
>> +		u16 num[2];
>> +		u16 *len[2];
>> +	} rx;
>> +	u32 rec_mb[2];
>> +};
>> +
>>  #endif
>> diff --git a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
>> b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
>> index ceb3dc0613d6..73289a9845d7 100644
>> --- a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
>> +++ b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
>> @@ -81,7 +81,7 @@ static int
>>  mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
>>		   struct mt76s_intr *intr)
>>  {
>> -	struct mt76_queue *q = &dev->q_rx[qid];
>> +	struct mt76_queue *q = &dev->q_rx[0];
>
>why qid is always 0 here?
>

In the current driver, we can see we only created one Rx queue (dev->q_rx with qid = 0)
in mt76s_alloc_queues for processing all incoming packets including MCU events and wifi packets.

And from the point of view of the device,
mt7663s use the hardware queue 0 for all MCU events and wifi packets;
mt7921s use the hardware queue 1 for all MCU events and wifi packets.

So if we don't remap from hardware queue 1 to dev->q_rx[0] for mt7921s to handle incoming packets,
we will get the kernel panic on accessing the invalid pointer on dev->q_rx[1].

	Sean

>Regards,
>Lorenzo
>

<snip>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 11/16] mt76: sdio: extend sdio module to support CONNAC2
  2021-10-12 22:52 ` [PATCH v4 11/16] mt76: sdio: extend sdio module to support CONNAC2 sean.wang
@ 2021-10-13 16:29   ` Lorenzo Bianconi
  0 siblings, 0 replies; 7+ messages in thread
From: Lorenzo Bianconi @ 2021-10-13 16:29 UTC (permalink / raw)
  To: sean.wang
  Cc: nbd, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Mark-YW.Chen, Deren.Wu, km.lin, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Eric.Liang,
	Stella.Chang, Tom.Chou, steve.lee, jsiuda, frankgor, jemele,
	abhishekpandit, shawnku, linux-wireless, linux-mediatek

[-- Attachment #1: Type: text/plain, Size: 10895 bytes --]

> From: Sean Wang <sean.wang@mediatek.com>
> 
> Extend sdio module to support CONNAC2 hw that mt7921s rely on.
> 
> Tested-by: Deren Wu <deren.wu@mediatek.com>
> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Co-developed-by: Deren Wu <deren.wu@mediatek.com>
> Signed-off-by: Deren Wu <deren.wu@mediatek.com>
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> ---
>  drivers/net/wireless/mediatek/mt76/mt76.h     |  5 +-
>  .../net/wireless/mediatek/mt76/mt7615/sdio.c  |  5 +-
>  drivers/net/wireless/mediatek/mt76/sdio.c     | 23 ++++++-
>  drivers/net/wireless/mediatek/mt76/sdio.h     | 50 ++++++++++++++-
>  .../net/wireless/mediatek/mt76/sdio_txrx.c    | 62 ++++++++++++++++---
>  5 files changed, 128 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index e2f33956a122..06f0d1348d52 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -505,6 +505,8 @@ struct mt76_sdio {
>  
>  	struct sdio_func *func;
>  	void *intr_data;
> +	int intr_size;
> +	u8 hw_ver;
>  
>  	struct {
>  		int pse_data_quota;
> @@ -1249,7 +1251,8 @@ int mt76s_alloc_queues(struct mt76_dev *dev);
>  void mt76s_deinit(struct mt76_dev *dev);
>  void mt76s_sdio_irq(struct sdio_func *func);
>  void mt76s_txrx_worker(struct mt76_sdio *sdio);
> -int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func);
> +int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func,
> +		  int hw_ver);
>  u32 mt76s_rr(struct mt76_dev *dev, u32 offset);
>  void mt76s_wr(struct mt76_dev *dev, u32 offset, u32 val);
>  u32 mt76s_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
> index f47e25f6dedb..a6b5d536d962 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
> @@ -100,7 +100,7 @@ static int mt7663s_probe(struct sdio_func *func,
>  	if (ret < 0)
>  		goto error;
>  
> -	ret = mt76s_hw_init(mdev, func);
> +	ret = mt76s_hw_init(mdev, func, MT76_CONNAC_SDIO);
>  	if (ret)
>  		goto error;
>  
> @@ -108,8 +108,9 @@ static int mt7663s_probe(struct sdio_func *func,
>  		    (mt76_rr(dev, MT_HW_REV) & 0xff);
>  	dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
>  
> +	mdev->sdio.intr_size = sizeof(struct mt76_connac_sdio_intr);
>  	mdev->sdio.intr_data = devm_kmalloc(mdev->dev,
> -					    sizeof(struct mt76s_intr),
> +					    mdev->sdio.intr_size,
>  					    GFP_KERNEL);
>  	if (!mdev->sdio.intr_data) {
>  		ret = -ENOMEM;
> diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c
> index 82fb4c110b90..bb40cc3e9c2b 100644
> --- a/drivers/net/wireless/mediatek/mt76/sdio.c
> +++ b/drivers/net/wireless/mediatek/mt76/sdio.c
> @@ -221,11 +221,13 @@ int mt76s_rd_rp(struct mt76_dev *dev, u32 base,
>  }
>  EXPORT_SYMBOL_GPL(mt76s_rd_rp);
>  
> -int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func)
> +int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func, int hw_ver)
>  {
>  	u32 status, ctrl;
>  	int ret;
>  
> +	dev->sdio.hw_ver = hw_ver;
> +
>  	sdio_claim_host(func);
>  
>  	ret = sdio_enable_func(func);
> @@ -255,12 +257,27 @@ int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func)
>  		goto disable_func;
>  
>  	ctrl = WHIER_RX0_DONE_INT_EN | WHIER_TX_DONE_INT_EN;
> +	if (hw_ver == MT76_CONNAC2_SDIO)
> +		ctrl |= WHIER_RX1_DONE_INT_EN;
>  	sdio_writel(func, ctrl, MCR_WHIER, &ret);
>  	if (ret < 0)
>  		goto disable_func;
>  
> -	/* set WHISR as read clear and Rx aggregation number as 16 */
> -	ctrl = FIELD_PREP(MAX_HIF_RX_LEN_NUM, 16);
> +	switch (hw_ver) {
> +	case MT76_CONNAC_SDIO:
> +		/* set WHISR as read clear and Rx aggregation number as 16 */
> +		ctrl = FIELD_PREP(MAX_HIF_RX_LEN_NUM, 16);
> +		break;
> +	default:
> +		ctrl = sdio_readl(func, MCR_WHCR, &ret);
> +		if (ret < 0)
> +			goto disable_func;
> +		ctrl &= ~MAX_HIF_RX_LEN_NUM_CONNAC2;
> +		ctrl &= ~W_INT_CLR_CTRL; /* read clear */
> +		ctrl |= FIELD_PREP(MAX_HIF_RX_LEN_NUM_CONNAC2, 0);
> +		break;
> +	}
> +
>  	sdio_writel(func, ctrl, MCR_WHCR, &ret);
>  	if (ret < 0)
>  		goto disable_func;
> diff --git a/drivers/net/wireless/mediatek/mt76/sdio.h b/drivers/net/wireless/mediatek/mt76/sdio.h
> index 03877d89e152..7d2ec044dcb1 100644
> --- a/drivers/net/wireless/mediatek/mt76/sdio.h
> +++ b/drivers/net/wireless/mediatek/mt76/sdio.h
> @@ -21,7 +21,12 @@
>  #define MCR_WHCR			0x000C
>  #define W_INT_CLR_CTRL			BIT(1)
>  #define RECV_MAILBOX_RD_CLR_EN		BIT(2)
> +#define WF_SYS_RSTB			BIT(4) /* supported in CONNAC2 */
> +#define WF_WHOLE_PATH_RSTB		BIT(5) /* supported in CONNAC2 */
> +#define WF_SDIO_WF_PATH_RSTB		BIT(6) /* supported in CONNAC2 */
>  #define MAX_HIF_RX_LEN_NUM		GENMASK(13, 8)
> +#define MAX_HIF_RX_LEN_NUM_CONNAC2	GENMASK(14, 8) /* supported in CONNAC2 */
> +#define WF_RST_DONE			BIT(15) /* supported in CONNAC2 */
>  #define RX_ENHANCE_MODE			BIT(16)
>  
>  #define MCR_WHISR			0x0010
> @@ -29,6 +34,7 @@
>  #define WHIER_D2H_SW_INT		GENMASK(31, 8)
>  #define WHIER_FW_OWN_BACK_INT_EN	BIT(7)
>  #define WHIER_ABNORMAL_INT_EN		BIT(6)
> +#define WHIER_WDT_INT_EN		BIT(5) /* supported in CONNAC2 */
>  #define WHIER_RX1_DONE_INT_EN		BIT(2)
>  #define WHIER_RX0_DONE_INT_EN		BIT(1)
>  #define WHIER_TX_DONE_INT_EN		BIT(0)
> @@ -100,7 +106,37 @@
>  
>  #define MCR_SWPCDBGR			0x0154
>  
> -struct mt76s_intr {
> +#define MCR_H2DSM2R			0x0160 /* supported in CONNAC2 */
> +#define MCR_H2DSM3R			0x0164 /* supported in CONNAC2 */
> +#define MCR_D2HRM3R			0x0174 /* supported in CONNAC2 */
> +#define MCR_WTQCR8			0x0190 /* supported in CONNAC2 */
> +#define MCR_WTQCR9			0x0194 /* supported in CONNAC2 */
> +#define MCR_WTQCR10			0x0198 /* supported in CONNAC2 */
> +#define MCR_WTQCR11			0x019C /* supported in CONNAC2 */
> +#define MCR_WTQCR12			0x01A0 /* supported in CONNAC2 */
> +#define MCR_WTQCR13			0x01A4 /* supported in CONNAC2 */
> +#define MCR_WTQCR14			0x01A8 /* supported in CONNAC2 */
> +#define MCR_WTQCR15			0x01AC /* supported in CONNAC2 */
> +
> +enum mt76_connac_sdio_ver {
> +	MT76_CONNAC_SDIO,
> +	MT76_CONNAC2_SDIO,
> +};
> +
> +struct mt76_connac2_sdio_intr {
> +	u32 isr;
> +	struct {
> +		u32 wtqcr[16];
> +	} tx;
> +	struct {
> +		u16 num[2];
> +		u16 len0[16];
> +		u16 len1[128];
> +	} rx;
> +	u32 rec_mb[2];
> +} __packed;
> +
> +struct mt76_connac_sdio_intr {
>  	u32 isr;
>  	struct {
>  		u32 wtqcr[8];
> @@ -112,4 +148,16 @@ struct mt76s_intr {
>  	u32 rec_mb[2];
>  } __packed;
>  
> +struct mt76s_intr {
> +	u32 isr;
> +	struct {
> +		u32 *wtqcr;
> +	} tx;
> +	struct {
> +		u16 num[2];
> +		u16 *len[2];
> +	} rx;
> +	u32 rec_mb[2];
> +};
> +
>  #endif
> diff --git a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
> index ceb3dc0613d6..73289a9845d7 100644
> --- a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
> +++ b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
> @@ -81,7 +81,7 @@ static int
>  mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
>  		   struct mt76s_intr *intr)
>  {
> -	struct mt76_queue *q = &dev->q_rx[qid];
> +	struct mt76_queue *q = &dev->q_rx[0];

why qid is always 0 here?

Regards,
Lorenzo

>  	struct mt76_sdio *sdio = &dev->sdio;
>  	int len = 0, err, i;
>  	struct page *page;
> @@ -112,8 +112,10 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
>  	for (i = 0; i < intr->rx.num[qid]; i++) {
>  		int index = (q->head + i) % q->ndesc;
>  		struct mt76_queue_entry *e = &q->entry[index];
> +		__le32 *rxd = (__le32 *)buf;
>  
> -		len = intr->rx.len[qid][i];
> +		/* parse rxd to get the actual packet length */
> +		len = FIELD_GET(GENMASK(15, 0), le32_to_cpu(rxd[0]));
>  		e->skb = mt76s_build_rx_skb(buf, len, round_up(len + 4, 4));
>  		if (!e->skb)
>  			break;
> @@ -132,35 +134,72 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
>  	return i;
>  }
>  
> +static void mt76s_intr_parse(struct mt76_dev *dev, void *data,
> +			     struct mt76s_intr *intr)
> +{
> +	struct mt76_connac_sdio_intr *intr_v1;
> +	struct mt76_connac2_sdio_intr *intr_v2;
> +	int i;
> +
> +	switch (dev->sdio.hw_ver) {
> +	case MT76_CONNAC_SDIO:
> +		intr_v1 = data;
> +		intr->isr =  intr_v1->isr;
> +		intr->tx.wtqcr = intr_v1->tx.wtqcr;
> +		for (i = 0; i < 2 ; i++) {
> +			intr->rx.num[i] = intr_v1->rx.num[i];
> +			intr->rx.len[i] = intr_v1->rx.len[i];
> +			intr->rec_mb[i] = intr_v1->rec_mb[i];
> +		}
> +		break;
> +	default:
> +		intr_v2 = data;
> +		intr->isr =  intr_v2->isr;
> +		intr->tx.wtqcr = intr_v2->tx.wtqcr;
> +		for (i = 0; i < 2 ; i++) {
> +			intr->rx.num[i] = intr_v2->rx.num[i];
> +			if (!i)
> +				intr->rx.len[0] = intr_v2->rx.len0;
> +			else
> +				intr->rx.len[1] = intr_v2->rx.len1;
> +			intr->rec_mb[i] = intr_v2->rec_mb[i];
> +		}
> +		break;
> +	}
> +}
> +
>  static int mt76s_rx_handler(struct mt76_dev *dev)
>  {
>  	struct mt76_sdio *sdio = &dev->sdio;
> -	struct mt76s_intr *intr = sdio->intr_data;
> +	void *data = sdio->intr_data;
> +	struct mt76s_intr intr;
>  	int nframes = 0, ret;
>  
> -	ret = sdio_readsb(sdio->func, intr, MCR_WHISR, sizeof(*intr));
> +	ret = sdio_readsb(sdio->func, data, MCR_WHISR, sdio->intr_size);
>  	if (ret < 0)
>  		return ret;
>  
> -	trace_dev_irq(dev, intr->isr, 0);
> +	mt76s_intr_parse(dev, data, &intr);
>  
> -	if (intr->isr & WHIER_RX0_DONE_INT_EN) {
> -		ret = mt76s_rx_run_queue(dev, 0, intr);
> +	trace_dev_irq(dev, intr.isr, 0);
> +
> +	if (intr.isr & WHIER_RX0_DONE_INT_EN) {
> +		ret = mt76s_rx_run_queue(dev, 0, &intr);
>  		if (ret > 0) {
>  			mt76_worker_schedule(&sdio->net_worker);
>  			nframes += ret;
>  		}
>  	}
>  
> -	if (intr->isr & WHIER_RX1_DONE_INT_EN) {
> -		ret = mt76s_rx_run_queue(dev, 1, intr);
> +	if (intr.isr & WHIER_RX1_DONE_INT_EN) {
> +		ret = mt76s_rx_run_queue(dev, 1, &intr);
>  		if (ret > 0) {
>  			mt76_worker_schedule(&sdio->net_worker);
>  			nframes += ret;
>  		}
>  	}
>  
> -	nframes += !!mt76s_refill_sched_quota(dev, intr->tx.wtqcr);
> +	nframes += !!mt76s_refill_sched_quota(dev, intr.tx.wtqcr);
>  
>  	return nframes;
>  }
> @@ -173,6 +212,9 @@ mt76s_tx_pick_quota(struct mt76_sdio *sdio, bool mcu, int buf_sz,
>  
>  	pse_sz = DIV_ROUND_UP(buf_sz + sdio->sched.deficit, MT_PSE_PAGE_SZ);
>  
> +	if (mcu && sdio->hw_ver == MT76_CONNAC2_SDIO)
> +		pse_sz = 1;
> +
>  	if (mcu) {
>  		if (sdio->sched.pse_mcu_quota < *pse_size + pse_sz)
>  			return -EBUSY;
> -- 
> 2.25.1
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v4 11/16] mt76: sdio: extend sdio module to support CONNAC2
  2021-10-12 22:51 [PATCH v4 00/16] Add MT7921 SDIO WiFi support sean.wang
@ 2021-10-12 22:52 ` sean.wang
  2021-10-13 16:29   ` Lorenzo Bianconi
  0 siblings, 1 reply; 7+ messages in thread
From: sean.wang @ 2021-10-12 22:52 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Mark-YW.Chen, Deren.Wu, km.lin, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Eric.Liang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, jemele, abhishekpandit, shawnku,
	linux-wireless, linux-mediatek, Deren Wu

From: Sean Wang <sean.wang@mediatek.com>

Extend sdio module to support CONNAC2 hw that mt7921s rely on.

Tested-by: Deren Wu <deren.wu@mediatek.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Co-developed-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt76.h     |  5 +-
 .../net/wireless/mediatek/mt76/mt7615/sdio.c  |  5 +-
 drivers/net/wireless/mediatek/mt76/sdio.c     | 23 ++++++-
 drivers/net/wireless/mediatek/mt76/sdio.h     | 50 ++++++++++++++-
 .../net/wireless/mediatek/mt76/sdio_txrx.c    | 62 ++++++++++++++++---
 5 files changed, 128 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index e2f33956a122..06f0d1348d52 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -505,6 +505,8 @@ struct mt76_sdio {
 
 	struct sdio_func *func;
 	void *intr_data;
+	int intr_size;
+	u8 hw_ver;
 
 	struct {
 		int pse_data_quota;
@@ -1249,7 +1251,8 @@ int mt76s_alloc_queues(struct mt76_dev *dev);
 void mt76s_deinit(struct mt76_dev *dev);
 void mt76s_sdio_irq(struct sdio_func *func);
 void mt76s_txrx_worker(struct mt76_sdio *sdio);
-int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func);
+int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func,
+		  int hw_ver);
 u32 mt76s_rr(struct mt76_dev *dev, u32 offset);
 void mt76s_wr(struct mt76_dev *dev, u32 offset, u32 val);
 u32 mt76s_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
index f47e25f6dedb..a6b5d536d962 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
@@ -100,7 +100,7 @@ static int mt7663s_probe(struct sdio_func *func,
 	if (ret < 0)
 		goto error;
 
-	ret = mt76s_hw_init(mdev, func);
+	ret = mt76s_hw_init(mdev, func, MT76_CONNAC_SDIO);
 	if (ret)
 		goto error;
 
@@ -108,8 +108,9 @@ static int mt7663s_probe(struct sdio_func *func,
 		    (mt76_rr(dev, MT_HW_REV) & 0xff);
 	dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
 
+	mdev->sdio.intr_size = sizeof(struct mt76_connac_sdio_intr);
 	mdev->sdio.intr_data = devm_kmalloc(mdev->dev,
-					    sizeof(struct mt76s_intr),
+					    mdev->sdio.intr_size,
 					    GFP_KERNEL);
 	if (!mdev->sdio.intr_data) {
 		ret = -ENOMEM;
diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c
index 82fb4c110b90..bb40cc3e9c2b 100644
--- a/drivers/net/wireless/mediatek/mt76/sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/sdio.c
@@ -221,11 +221,13 @@ int mt76s_rd_rp(struct mt76_dev *dev, u32 base,
 }
 EXPORT_SYMBOL_GPL(mt76s_rd_rp);
 
-int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func)
+int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func, int hw_ver)
 {
 	u32 status, ctrl;
 	int ret;
 
+	dev->sdio.hw_ver = hw_ver;
+
 	sdio_claim_host(func);
 
 	ret = sdio_enable_func(func);
@@ -255,12 +257,27 @@ int mt76s_hw_init(struct mt76_dev *dev, struct sdio_func *func)
 		goto disable_func;
 
 	ctrl = WHIER_RX0_DONE_INT_EN | WHIER_TX_DONE_INT_EN;
+	if (hw_ver == MT76_CONNAC2_SDIO)
+		ctrl |= WHIER_RX1_DONE_INT_EN;
 	sdio_writel(func, ctrl, MCR_WHIER, &ret);
 	if (ret < 0)
 		goto disable_func;
 
-	/* set WHISR as read clear and Rx aggregation number as 16 */
-	ctrl = FIELD_PREP(MAX_HIF_RX_LEN_NUM, 16);
+	switch (hw_ver) {
+	case MT76_CONNAC_SDIO:
+		/* set WHISR as read clear and Rx aggregation number as 16 */
+		ctrl = FIELD_PREP(MAX_HIF_RX_LEN_NUM, 16);
+		break;
+	default:
+		ctrl = sdio_readl(func, MCR_WHCR, &ret);
+		if (ret < 0)
+			goto disable_func;
+		ctrl &= ~MAX_HIF_RX_LEN_NUM_CONNAC2;
+		ctrl &= ~W_INT_CLR_CTRL; /* read clear */
+		ctrl |= FIELD_PREP(MAX_HIF_RX_LEN_NUM_CONNAC2, 0);
+		break;
+	}
+
 	sdio_writel(func, ctrl, MCR_WHCR, &ret);
 	if (ret < 0)
 		goto disable_func;
diff --git a/drivers/net/wireless/mediatek/mt76/sdio.h b/drivers/net/wireless/mediatek/mt76/sdio.h
index 03877d89e152..7d2ec044dcb1 100644
--- a/drivers/net/wireless/mediatek/mt76/sdio.h
+++ b/drivers/net/wireless/mediatek/mt76/sdio.h
@@ -21,7 +21,12 @@
 #define MCR_WHCR			0x000C
 #define W_INT_CLR_CTRL			BIT(1)
 #define RECV_MAILBOX_RD_CLR_EN		BIT(2)
+#define WF_SYS_RSTB			BIT(4) /* supported in CONNAC2 */
+#define WF_WHOLE_PATH_RSTB		BIT(5) /* supported in CONNAC2 */
+#define WF_SDIO_WF_PATH_RSTB		BIT(6) /* supported in CONNAC2 */
 #define MAX_HIF_RX_LEN_NUM		GENMASK(13, 8)
+#define MAX_HIF_RX_LEN_NUM_CONNAC2	GENMASK(14, 8) /* supported in CONNAC2 */
+#define WF_RST_DONE			BIT(15) /* supported in CONNAC2 */
 #define RX_ENHANCE_MODE			BIT(16)
 
 #define MCR_WHISR			0x0010
@@ -29,6 +34,7 @@
 #define WHIER_D2H_SW_INT		GENMASK(31, 8)
 #define WHIER_FW_OWN_BACK_INT_EN	BIT(7)
 #define WHIER_ABNORMAL_INT_EN		BIT(6)
+#define WHIER_WDT_INT_EN		BIT(5) /* supported in CONNAC2 */
 #define WHIER_RX1_DONE_INT_EN		BIT(2)
 #define WHIER_RX0_DONE_INT_EN		BIT(1)
 #define WHIER_TX_DONE_INT_EN		BIT(0)
@@ -100,7 +106,37 @@
 
 #define MCR_SWPCDBGR			0x0154
 
-struct mt76s_intr {
+#define MCR_H2DSM2R			0x0160 /* supported in CONNAC2 */
+#define MCR_H2DSM3R			0x0164 /* supported in CONNAC2 */
+#define MCR_D2HRM3R			0x0174 /* supported in CONNAC2 */
+#define MCR_WTQCR8			0x0190 /* supported in CONNAC2 */
+#define MCR_WTQCR9			0x0194 /* supported in CONNAC2 */
+#define MCR_WTQCR10			0x0198 /* supported in CONNAC2 */
+#define MCR_WTQCR11			0x019C /* supported in CONNAC2 */
+#define MCR_WTQCR12			0x01A0 /* supported in CONNAC2 */
+#define MCR_WTQCR13			0x01A4 /* supported in CONNAC2 */
+#define MCR_WTQCR14			0x01A8 /* supported in CONNAC2 */
+#define MCR_WTQCR15			0x01AC /* supported in CONNAC2 */
+
+enum mt76_connac_sdio_ver {
+	MT76_CONNAC_SDIO,
+	MT76_CONNAC2_SDIO,
+};
+
+struct mt76_connac2_sdio_intr {
+	u32 isr;
+	struct {
+		u32 wtqcr[16];
+	} tx;
+	struct {
+		u16 num[2];
+		u16 len0[16];
+		u16 len1[128];
+	} rx;
+	u32 rec_mb[2];
+} __packed;
+
+struct mt76_connac_sdio_intr {
 	u32 isr;
 	struct {
 		u32 wtqcr[8];
@@ -112,4 +148,16 @@ struct mt76s_intr {
 	u32 rec_mb[2];
 } __packed;
 
+struct mt76s_intr {
+	u32 isr;
+	struct {
+		u32 *wtqcr;
+	} tx;
+	struct {
+		u16 num[2];
+		u16 *len[2];
+	} rx;
+	u32 rec_mb[2];
+};
+
 #endif
diff --git a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
index ceb3dc0613d6..73289a9845d7 100644
--- a/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/sdio_txrx.c
@@ -81,7 +81,7 @@ static int
 mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
 		   struct mt76s_intr *intr)
 {
-	struct mt76_queue *q = &dev->q_rx[qid];
+	struct mt76_queue *q = &dev->q_rx[0];
 	struct mt76_sdio *sdio = &dev->sdio;
 	int len = 0, err, i;
 	struct page *page;
@@ -112,8 +112,10 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
 	for (i = 0; i < intr->rx.num[qid]; i++) {
 		int index = (q->head + i) % q->ndesc;
 		struct mt76_queue_entry *e = &q->entry[index];
+		__le32 *rxd = (__le32 *)buf;
 
-		len = intr->rx.len[qid][i];
+		/* parse rxd to get the actual packet length */
+		len = FIELD_GET(GENMASK(15, 0), le32_to_cpu(rxd[0]));
 		e->skb = mt76s_build_rx_skb(buf, len, round_up(len + 4, 4));
 		if (!e->skb)
 			break;
@@ -132,35 +134,72 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
 	return i;
 }
 
+static void mt76s_intr_parse(struct mt76_dev *dev, void *data,
+			     struct mt76s_intr *intr)
+{
+	struct mt76_connac_sdio_intr *intr_v1;
+	struct mt76_connac2_sdio_intr *intr_v2;
+	int i;
+
+	switch (dev->sdio.hw_ver) {
+	case MT76_CONNAC_SDIO:
+		intr_v1 = data;
+		intr->isr =  intr_v1->isr;
+		intr->tx.wtqcr = intr_v1->tx.wtqcr;
+		for (i = 0; i < 2 ; i++) {
+			intr->rx.num[i] = intr_v1->rx.num[i];
+			intr->rx.len[i] = intr_v1->rx.len[i];
+			intr->rec_mb[i] = intr_v1->rec_mb[i];
+		}
+		break;
+	default:
+		intr_v2 = data;
+		intr->isr =  intr_v2->isr;
+		intr->tx.wtqcr = intr_v2->tx.wtqcr;
+		for (i = 0; i < 2 ; i++) {
+			intr->rx.num[i] = intr_v2->rx.num[i];
+			if (!i)
+				intr->rx.len[0] = intr_v2->rx.len0;
+			else
+				intr->rx.len[1] = intr_v2->rx.len1;
+			intr->rec_mb[i] = intr_v2->rec_mb[i];
+		}
+		break;
+	}
+}
+
 static int mt76s_rx_handler(struct mt76_dev *dev)
 {
 	struct mt76_sdio *sdio = &dev->sdio;
-	struct mt76s_intr *intr = sdio->intr_data;
+	void *data = sdio->intr_data;
+	struct mt76s_intr intr;
 	int nframes = 0, ret;
 
-	ret = sdio_readsb(sdio->func, intr, MCR_WHISR, sizeof(*intr));
+	ret = sdio_readsb(sdio->func, data, MCR_WHISR, sdio->intr_size);
 	if (ret < 0)
 		return ret;
 
-	trace_dev_irq(dev, intr->isr, 0);
+	mt76s_intr_parse(dev, data, &intr);
 
-	if (intr->isr & WHIER_RX0_DONE_INT_EN) {
-		ret = mt76s_rx_run_queue(dev, 0, intr);
+	trace_dev_irq(dev, intr.isr, 0);
+
+	if (intr.isr & WHIER_RX0_DONE_INT_EN) {
+		ret = mt76s_rx_run_queue(dev, 0, &intr);
 		if (ret > 0) {
 			mt76_worker_schedule(&sdio->net_worker);
 			nframes += ret;
 		}
 	}
 
-	if (intr->isr & WHIER_RX1_DONE_INT_EN) {
-		ret = mt76s_rx_run_queue(dev, 1, intr);
+	if (intr.isr & WHIER_RX1_DONE_INT_EN) {
+		ret = mt76s_rx_run_queue(dev, 1, &intr);
 		if (ret > 0) {
 			mt76_worker_schedule(&sdio->net_worker);
 			nframes += ret;
 		}
 	}
 
-	nframes += !!mt76s_refill_sched_quota(dev, intr->tx.wtqcr);
+	nframes += !!mt76s_refill_sched_quota(dev, intr.tx.wtqcr);
 
 	return nframes;
 }
@@ -173,6 +212,9 @@ mt76s_tx_pick_quota(struct mt76_sdio *sdio, bool mcu, int buf_sz,
 
 	pse_sz = DIV_ROUND_UP(buf_sz + sdio->sched.deficit, MT_PSE_PAGE_SZ);
 
+	if (mcu && sdio->hw_ver == MT76_CONNAC2_SDIO)
+		pse_sz = 1;
+
 	if (mcu) {
 		if (sdio->sched.pse_mcu_quota < *pse_size + pse_sz)
 			return -EBUSY;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-11-22 18:10 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <YWcuGcFPGCtaPh+2@lore-desk--annotate>
2021-10-13 21:22 ` [PATCH v4 11/16] mt76: sdio: extend sdio module to support CONNAC2 sean.wang
2021-11-22 17:10 ` [PATCH 2/2] mt76: mt7921s: fix the device cannot sleep deeply in suspend sean.wang
2021-11-22 18:10   ` Lorenzo Bianconi
     [not found] <YWcJe27HQMS7B85j@lore-desk--annotate>
2021-10-13 17:56 ` [PATCH v4 11/16] mt76: sdio: extend sdio module to support CONNAC2 sean.wang
2021-10-13 19:06   ` Lorenzo Bianconi
2021-10-12 22:51 [PATCH v4 00/16] Add MT7921 SDIO WiFi support sean.wang
2021-10-12 22:52 ` [PATCH v4 11/16] mt76: sdio: extend sdio module to support CONNAC2 sean.wang
2021-10-13 16:29   ` Lorenzo Bianconi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).