Commit 3ad08509 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Felix Fietkau
Browse files

mt76: sdio: introduce parse_irq callback



Add parse_irq to handle that interrupt status structure is
different between mt7663s and mt7921s.

This is a preliminary patch to introduce mt7921s driver

Tested-by: default avatarSean Wang <sean.wang@mediatek.com>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 764dee47
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
struct mt76_dev;
struct mt76_phy;
struct mt76_wcid;
struct mt76s_intr;

struct mt76_reg_pair {
	u32 reg;
@@ -512,6 +513,8 @@ struct mt76_sdio {
		int pse_mcu_quota;
		int deficit;
	} sched;

	int (*parse_irq)(struct mt76_dev *dev, struct mt76s_intr *intr);
};

struct mt76_mmio {
+12 −0
Original line number Diff line number Diff line
@@ -107,6 +107,18 @@ struct mt7615_wtbl_rate_desc {
	struct mt7615_sta *sta;
};

struct mt7663s_intr {
	u32 isr;
	struct {
		u32 wtqcr[8];
	} tx;
	struct {
		u16 num[2];
		u16 len[2][16];
	} rx;
	u32 rec_mb[2];
} __packed;

struct mt7615_sta {
	struct mt76_wcid wcid; /* must be first */

+22 −1
Original line number Diff line number Diff line
@@ -50,6 +50,26 @@ static void mt7663s_init_work(struct work_struct *work)
	mt7615_init_work(dev);
}

static int mt7663s_parse_intr(struct mt76_dev *dev, struct mt76s_intr *intr)
{
	struct mt76_sdio *sdio = &dev->sdio;
	struct mt7663s_intr *irq_data = sdio->intr_data;
	int i, err;

	err = sdio_readsb(sdio->func, irq_data, MCR_WHISR, sizeof(*irq_data));
	if (err)
		return err;

	intr->isr = irq_data->isr;
	intr->rec_mb = irq_data->rec_mb;
	intr->tx.wtqcr = irq_data->tx.wtqcr;
	intr->rx.num = irq_data->rx.num;
	for (i = 0; i < 2 ; i++)
		intr->rx.len[i] = irq_data->rx.len[i];

	return 0;
}

static int mt7663s_probe(struct sdio_func *func,
			 const struct sdio_device_id *id)
{
@@ -108,8 +128,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.parse_irq = mt7663s_parse_intr;
	mdev->sdio.intr_data = devm_kmalloc(mdev->dev,
					    sizeof(struct mt76s_intr),
					    sizeof(struct mt7663s_intr),
					    GFP_KERNEL);
	if (!mdev->sdio.intr_data) {
		ret = -ENOMEM;
+5 −5
Original line number Diff line number Diff line
@@ -102,14 +102,14 @@

struct mt76s_intr {
	u32 isr;
	u32 *rec_mb;
	struct {
		u32 wtqcr[8];
		u32 *wtqcr;
	} tx;
	struct {
		u16 num[2];
		u16 len[2][16];
		u16 *len[2];
		u16 *num;
	} rx;
	u32 rec_mb[2];
} __packed;
};

#endif
+9 −9
Original line number Diff line number Diff line
@@ -135,32 +135,32 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
static int mt76s_rx_handler(struct mt76_dev *dev)
{
	struct mt76_sdio *sdio = &dev->sdio;
	struct mt76s_intr *intr = sdio->intr_data;
	struct mt76s_intr intr;
	int nframes = 0, ret;

	ret = sdio_readsb(sdio->func, intr, MCR_WHISR, sizeof(*intr));
	if (ret < 0)
	ret = sdio->parse_irq(dev, &intr);
	if (ret)
		return ret;

	trace_dev_irq(dev, intr->isr, 0);
	trace_dev_irq(dev, intr.isr, 0);

	if (intr->isr & WHIER_RX0_DONE_INT_EN) {
		ret = mt76s_rx_run_queue(dev, 0, intr);
	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;
}