Commit 6892555d authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Felix Fietkau
Browse files

mt76: mt7622: fix fw hang on mt7622



Set poll timeout to 3s for mt7622 devices in order to avoid fw hangs.
Swap mt7622_trigger_hif_int and doorbell configuration order in
mt7615_mcu_drv_pmctrl routine.
Introduce mt7615_mcu_lp_drv_pmctrl routine to take care of drv_own
configuration for runtime-pm.

Fixes: 08523a2a ("mt76: mt7615: add mt7615_pm_wake utility routine")
Fixes: 894b7767 ("mt76: mt7615: improve mt7615_driver_own reliability")
Fixes: 757b0e7f ("mt76: mt7615: avoid polling in fw_own for mt7663")
Co-developed-by: default avatarShayne Chen <shayne.chen@mediatek.com>
Signed-off-by: default avatarShayne Chen <shayne.chen@mediatek.com>
Co-developed-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent b1b7ee2f
Loading
Loading
Loading
Loading
+32 −14
Original line number Diff line number Diff line
@@ -338,28 +338,46 @@ static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev)
{
	struct mt76_phy *mphy = &dev->mt76.phy;
	struct mt76_dev *mdev = &dev->mt76;
	int i;

	if (!test_and_clear_bit(MT76_STATE_PM, &mphy->state))
		goto out;

	mt7622_trigger_hif_int(dev, true);

	for (i = 0; i < MT7615_DRV_OWN_RETRY_COUNT; i++) {
	u32 addr;
	int err;

	addr = is_mt7663(mdev) ? MT_PCIE_DOORBELL_PUSH : MT_CFG_LPCR_HOST;
	mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN);

	mt7622_trigger_hif_int(dev, true);

	addr = is_mt7663(mdev) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST;
		if (mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 50))
			break;
	}
	err = !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000);

	mt7622_trigger_hif_int(dev, false);

	if (i == MT7615_DRV_OWN_RETRY_COUNT) {
	if (err) {
		dev_err(mdev->dev, "driver own failed\n");
		return -ETIMEDOUT;
	}

	clear_bit(MT76_STATE_PM, &mphy->state);

	return 0;
}

static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev)
{
	struct mt76_phy *mphy = &dev->mt76.phy;
	int i;

	if (!test_and_clear_bit(MT76_STATE_PM, &mphy->state))
		goto out;

	for (i = 0; i < MT7615_DRV_OWN_RETRY_COUNT; i++) {
		mt76_wr(dev, MT_PCIE_DOORBELL_PUSH, MT_CFG_LPCR_HOST_DRV_OWN);
		if (mt76_poll_msec(dev, MT_CONN_HIF_ON_LPCTL,
				   MT_CFG_LPCR_HOST_FW_OWN, 0, 50))
			break;
	}

	if (i == MT7615_DRV_OWN_RETRY_COUNT) {
		dev_err(dev->mt76.dev, "driver own failed\n");
		set_bit(MT76_STATE_PM, &mphy->state);
		return -EIO;
	}
@@ -386,7 +404,7 @@ static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev)

	if (is_mt7622(&dev->mt76) &&
	    !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN,
			    MT_CFG_LPCR_HOST_FW_OWN, 300)) {
			    MT_CFG_LPCR_HOST_FW_OWN, 3000)) {
		dev_err(dev->mt76.dev, "Timeout for firmware own\n");
		clear_bit(MT76_STATE_PM, &mphy->state);
		err = -EIO;
@@ -1900,7 +1918,7 @@ static const struct mt7615_mcu_ops uni_update_ops = {
	.add_tx_ba = mt7615_mcu_uni_tx_ba,
	.add_rx_ba = mt7615_mcu_uni_rx_ba,
	.sta_add = mt7615_mcu_uni_add_sta,
	.set_drv_ctrl = mt7615_mcu_drv_pmctrl,
	.set_drv_ctrl = mt7615_mcu_lp_drv_pmctrl,
	.set_fw_ctrl = mt7615_mcu_fw_pmctrl,
};