wifi: wilc1000: Fill in missing error handling

Add error handling to chip_wakeup() and propagate the errors throughout
the entire driver. Add error handling to acquire_bus()/release_bus() and
host_sleep_notify()/host_wakeup_notify() functions as a result as well.
Fill the error handling to all call sites.

Reviewed-by: Alexis Lothoré <alexis.lothore@bootlin.com>
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://patch.msgid.link/20241004114551.40236-4-marex@denx.de
This commit is contained in:
Marek Vasut 2024-10-04 13:44:13 +02:00 committed by Kalle Valo
parent 0a6ea2e235
commit 1241c5650f
3 changed files with 118 additions and 51 deletions

View File

@ -960,6 +960,7 @@ static int wilc_sdio_suspend(struct device *dev)
{ {
struct sdio_func *func = dev_to_sdio_func(dev); struct sdio_func *func = dev_to_sdio_func(dev);
struct wilc *wilc = sdio_get_drvdata(func); struct wilc *wilc = sdio_get_drvdata(func);
int ret;
dev_info(dev, "sdio suspend\n"); dev_info(dev, "sdio suspend\n");
@ -969,7 +970,11 @@ static int wilc_sdio_suspend(struct device *dev)
if (!IS_ERR(wilc->rtc_clk)) if (!IS_ERR(wilc->rtc_clk))
clk_disable_unprepare(wilc->rtc_clk); clk_disable_unprepare(wilc->rtc_clk);
host_sleep_notify(wilc); ret = host_sleep_notify(wilc);
if (ret) {
clk_prepare_enable(wilc->rtc_clk);
return ret;
}
wilc_sdio_disable_interrupt(wilc); wilc_sdio_disable_interrupt(wilc);
@ -992,9 +997,7 @@ static int wilc_sdio_resume(struct device *dev)
wilc_sdio_init(wilc, true); wilc_sdio_init(wilc, true);
wilc_sdio_enable_interrupt(wilc); wilc_sdio_enable_interrupt(wilc);
host_wakeup_notify(wilc); return host_wakeup_notify(wilc);
return 0;
} }
static const struct of_device_id wilc_of_match[] = { static const struct of_device_id wilc_of_match[] = {

View File

@ -601,7 +601,7 @@ static int chip_allow_sleep(struct wilc *wilc)
return 0; return 0;
} }
static void chip_wakeup(struct wilc *wilc) static int chip_wakeup(struct wilc *wilc)
{ {
u32 ret = 0; u32 ret = 0;
u32 clk_status_val = 0, trials = 0; u32 clk_status_val = 0, trials = 0;
@ -630,20 +630,20 @@ static void chip_wakeup(struct wilc *wilc)
ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg, ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg,
from_host_to_fw_bit); from_host_to_fw_bit);
if (ret) if (ret)
return; return ret;
/* Set wake-up bit */ /* Set wake-up bit */
ret = hif_func->hif_write_reg(wilc, wakeup_reg, ret = hif_func->hif_write_reg(wilc, wakeup_reg,
wakeup_bit); wakeup_bit);
if (ret) if (ret)
return; return ret;
while (trials < WAKE_UP_TRIAL_RETRY) { while (trials < WAKE_UP_TRIAL_RETRY) {
ret = hif_func->hif_read_reg(wilc, clk_status_reg, ret = hif_func->hif_read_reg(wilc, clk_status_reg,
&clk_status_val); &clk_status_val);
if (ret) { if (ret) {
pr_err("Bus error %d %x\n", ret, clk_status_val); pr_err("Bus error %d %x\n", ret, clk_status_val);
return; return ret;
} }
if (clk_status_val & clk_status_bit) if (clk_status_val & clk_status_bit)
break; break;
@ -652,42 +652,63 @@ static void chip_wakeup(struct wilc *wilc)
} }
if (trials >= WAKE_UP_TRIAL_RETRY) { if (trials >= WAKE_UP_TRIAL_RETRY) {
pr_err("Failed to wake-up the chip\n"); pr_err("Failed to wake-up the chip\n");
return; return -ETIMEDOUT;
} }
/* Sometimes spi fail to read clock regs after reading /* Sometimes spi fail to read clock regs after reading
* writing clockless registers * writing clockless registers
*/ */
if (wilc->io_type == WILC_HIF_SPI) if (wilc->io_type == WILC_HIF_SPI)
wilc->hif_func->hif_reset(wilc); wilc->hif_func->hif_reset(wilc);
return 0;
} }
static inline void acquire_bus(struct wilc *wilc, enum bus_acquire acquire) static inline int acquire_bus(struct wilc *wilc, enum bus_acquire acquire)
{ {
int ret = 0;
mutex_lock(&wilc->hif_cs); mutex_lock(&wilc->hif_cs);
if (acquire == WILC_BUS_ACQUIRE_AND_WAKEUP && wilc->power_save_mode) if (acquire == WILC_BUS_ACQUIRE_AND_WAKEUP && wilc->power_save_mode) {
chip_wakeup(wilc); ret = chip_wakeup(wilc);
if (ret)
mutex_unlock(&wilc->hif_cs);
}
return ret;
} }
static inline void release_bus(struct wilc *wilc, enum bus_release release) static inline int release_bus(struct wilc *wilc, enum bus_release release)
{ {
int ret = 0;
if (release == WILC_BUS_RELEASE_ALLOW_SLEEP && wilc->power_save_mode) if (release == WILC_BUS_RELEASE_ALLOW_SLEEP && wilc->power_save_mode)
chip_allow_sleep(wilc); ret = chip_allow_sleep(wilc);
mutex_unlock(&wilc->hif_cs); mutex_unlock(&wilc->hif_cs);
return ret;
} }
void host_wakeup_notify(struct wilc *wilc) int host_wakeup_notify(struct wilc *wilc)
{ {
acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); int ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
if (ret)
return ret;
wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_2, 1); wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_2, 1);
release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); return release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
} }
EXPORT_SYMBOL_GPL(host_wakeup_notify); EXPORT_SYMBOL_GPL(host_wakeup_notify);
void host_sleep_notify(struct wilc *wilc) int host_sleep_notify(struct wilc *wilc)
{ {
acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); int ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
if (ret)
return ret;
wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_1, 1); wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_1, 1);
release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); return release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
} }
EXPORT_SYMBOL_GPL(host_sleep_notify); EXPORT_SYMBOL_GPL(host_sleep_notify);
@ -714,6 +735,7 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
int srcu_idx; int srcu_idx;
u8 *txb = wilc->tx_buffer; u8 *txb = wilc->tx_buffer;
struct wilc_vif *vif; struct wilc_vif *vif;
int rv;
if (wilc->quit) if (wilc->quit)
goto out_update_cnt; goto out_update_cnt;
@ -784,7 +806,10 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
goto out_unlock; goto out_unlock;
vmm_table[i] = 0x0; vmm_table[i] = 0x0;
acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
if (ret)
goto out_unlock;
counter = 0; counter = 0;
func = wilc->hif_func; func = wilc->hif_func;
do { do {
@ -859,7 +884,9 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
goto out_release_bus; goto out_release_bus;
} }
release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); ret = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
if (ret)
goto out_unlock;
offset = 0; offset = 0;
i = 0; i = 0;
@ -921,7 +948,9 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
for (i = 0; i < NQUEUES; i++) for (i = 0; i < NQUEUES; i++)
wilc->txq[i].fw.count += ac_pkt_num_to_chip[i]; wilc->txq[i].fw.count += ac_pkt_num_to_chip[i];
acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
if (ret)
goto out_unlock;
ret = func->hif_clear_int_ext(wilc, ENABLE_TX_VMM); ret = func->hif_clear_int_ext(wilc, ENABLE_TX_VMM);
if (ret) if (ret)
@ -930,7 +959,9 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
ret = func->hif_block_tx_ext(wilc, 0, txb, offset); ret = func->hif_block_tx_ext(wilc, 0, txb, offset);
out_release_bus: out_release_bus:
release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); rv = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
if (!ret && rv)
ret = rv;
out_unlock: out_unlock:
mutex_unlock(&wilc->txq_add_to_head_cs); mutex_unlock(&wilc->txq_add_to_head_cs);
@ -1059,8 +1090,14 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
void wilc_handle_isr(struct wilc *wilc) void wilc_handle_isr(struct wilc *wilc)
{ {
u32 int_status; u32 int_status;
int ret;
ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
if (ret) {
dev_err_ratelimited(wilc->dev, "Cannot acquire bus\n");
return;
}
acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
wilc->hif_func->hif_read_int(wilc, &int_status); wilc->hif_func->hif_read_int(wilc, &int_status);
if (int_status & DATA_INT_EXT) if (int_status & DATA_INT_EXT)
@ -1069,7 +1106,9 @@ void wilc_handle_isr(struct wilc *wilc)
if (!(int_status & (ALL_INT_EXT))) if (!(int_status & (ALL_INT_EXT)))
wilc_unknown_isr_ext(wilc); wilc_unknown_isr_ext(wilc);
release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); ret = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
if (ret)
dev_err_ratelimited(wilc->dev, "Cannot release bus\n");
} }
EXPORT_SYMBOL_GPL(wilc_handle_isr); EXPORT_SYMBOL_GPL(wilc_handle_isr);
@ -1081,6 +1120,7 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
u8 *dma_buffer; u8 *dma_buffer;
int ret = 0; int ret = 0;
u32 reg = 0; u32 reg = 0;
int rv;
blksz = BIT(12); blksz = BIT(12);
@ -1091,7 +1131,9 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
offset = 0; offset = 0;
pr_debug("%s: Downloading firmware size = %d\n", __func__, buffer_size); pr_debug("%s: Downloading firmware size = %d\n", __func__, buffer_size);
acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
if (ret)
return ret;
wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg); wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
reg &= ~BIT(10); reg &= ~BIT(10);
@ -1100,11 +1142,17 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
if (reg & BIT(10)) if (reg & BIT(10))
pr_err("%s: Failed to reset\n", __func__); pr_err("%s: Failed to reset\n", __func__);
release_bus(wilc, WILC_BUS_RELEASE_ONLY); ret = release_bus(wilc, WILC_BUS_RELEASE_ONLY);
if (ret)
goto fail;
do { do {
addr = get_unaligned_le32(&buffer[offset]); addr = get_unaligned_le32(&buffer[offset]);
size = get_unaligned_le32(&buffer[offset + 4]); size = get_unaligned_le32(&buffer[offset + 4]);
acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
if (ret)
goto fail;
offset += 8; offset += 8;
while (((int)size) && (offset < buffer_size)) { while (((int)size) && (offset < buffer_size)) {
if (size <= blksz) if (size <= blksz)
@ -1122,7 +1170,9 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
offset += size2; offset += size2;
size -= size2; size -= size2;
} }
release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); rv = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
if (!ret && rv)
ret = rv;
if (ret) { if (ret) {
pr_err("%s Bus error\n", __func__); pr_err("%s Bus error\n", __func__);
@ -1141,7 +1191,7 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
int wilc_wlan_start(struct wilc *wilc) int wilc_wlan_start(struct wilc *wilc)
{ {
u32 reg = 0; u32 reg = 0;
int ret; int ret, rv;
u32 chipid; u32 chipid;
if (wilc->io_type == WILC_HIF_SDIO) { if (wilc->io_type == WILC_HIF_SDIO) {
@ -1150,7 +1200,10 @@ int wilc_wlan_start(struct wilc *wilc)
} else if (wilc->io_type == WILC_HIF_SPI) { } else if (wilc->io_type == WILC_HIF_SPI) {
reg = 1; reg = 1;
} }
acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
if (ret)
return ret;
ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg); ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg);
if (ret) if (ret)
goto release; goto release;
@ -1181,16 +1234,18 @@ int wilc_wlan_start(struct wilc *wilc)
wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg); wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, &reg);
release: release:
release_bus(wilc, WILC_BUS_RELEASE_ONLY); rv = release_bus(wilc, WILC_BUS_RELEASE_ONLY);
return ret; return ret ? ret : rv;
} }
int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)
{ {
u32 reg = 0; u32 reg = 0;
int ret; int ret, rv;
acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
if (ret)
return ret;
ret = wilc->hif_func->hif_read_reg(wilc, GLOBAL_MODE_CONTROL, &reg); ret = wilc->hif_func->hif_read_reg(wilc, GLOBAL_MODE_CONTROL, &reg);
if (ret) if (ret)
@ -1226,9 +1281,9 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif)
ret = 0; ret = 0;
release: release:
/* host comm is disabled - we can't issue sleep command anymore: */ /* host comm is disabled - we can't issue sleep command anymore: */
release_bus(wilc, WILC_BUS_RELEASE_ONLY); rv = release_bus(wilc, WILC_BUS_RELEASE_ONLY);
return ret; return ret ? ret : rv;
} }
void wilc_wlan_cleanup(struct net_device *dev) void wilc_wlan_cleanup(struct net_device *dev)
@ -1434,11 +1489,13 @@ EXPORT_SYMBOL_GPL(wilc_get_chipid);
static int init_chip(struct net_device *dev) static int init_chip(struct net_device *dev)
{ {
u32 reg; u32 reg;
int ret = 0; int ret, rv;
struct wilc_vif *vif = netdev_priv(dev); struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc = vif->wilc; struct wilc *wilc = vif->wilc;
acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP);
if (ret)
return ret;
ret = wilc_get_chipid(wilc); ret = wilc_get_chipid(wilc);
if (ret) if (ret)
@ -1470,17 +1527,19 @@ static int init_chip(struct net_device *dev)
} }
release: release:
release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); rv = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP);
return ret; return ret ? ret : rv;
} }
int wilc_load_mac_from_nv(struct wilc *wl) int wilc_load_mac_from_nv(struct wilc *wl)
{ {
int ret = -EINVAL; int ret, rv;
unsigned int i; unsigned int i;
acquire_bus(wl, WILC_BUS_ACQUIRE_AND_WAKEUP); ret = acquire_bus(wl, WILC_BUS_ACQUIRE_AND_WAKEUP);
if (ret)
return ret;
for (i = 0; i < WILC_NVMEM_MAX_NUM_BANK; i++) { for (i = 0; i < WILC_NVMEM_MAX_NUM_BANK; i++) {
int bank_offset = get_bank_offset_from_bank_index(i); int bank_offset = get_bank_offset_from_bank_index(i);
@ -1519,14 +1578,14 @@ int wilc_load_mac_from_nv(struct wilc *wl)
break; break;
} }
release_bus(wl, WILC_BUS_RELEASE_ALLOW_SLEEP); rv = release_bus(wl, WILC_BUS_RELEASE_ALLOW_SLEEP);
return ret; return ret ? ret : rv;
} }
EXPORT_SYMBOL_GPL(wilc_load_mac_from_nv); EXPORT_SYMBOL_GPL(wilc_load_mac_from_nv);
int wilc_wlan_init(struct net_device *dev) int wilc_wlan_init(struct net_device *dev)
{ {
int ret = 0; int ret = 0, rv;
struct wilc_vif *vif = netdev_priv(dev); struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc; struct wilc *wilc;
@ -1535,11 +1594,16 @@ int wilc_wlan_init(struct net_device *dev)
wilc->quit = 0; wilc->quit = 0;
if (!wilc->hif_func->hif_is_init(wilc)) { if (!wilc->hif_func->hif_is_init(wilc)) {
acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY);
if (ret)
return ret;
ret = wilc->hif_func->hif_init(wilc, false); ret = wilc->hif_func->hif_init(wilc, false);
if (!ret) if (!ret)
ret = wilc_get_chipid(wilc); ret = wilc_get_chipid(wilc);
release_bus(wilc, WILC_BUS_RELEASE_ONLY); rv = release_bus(wilc, WILC_BUS_RELEASE_ONLY);
if (!ret && rv)
ret = rv;
if (ret) if (ret)
goto fail; goto fail;

View File

@ -436,8 +436,8 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev);
void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size); void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size);
bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size); bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size);
void host_wakeup_notify(struct wilc *wilc); int host_wakeup_notify(struct wilc *wilc);
void host_sleep_notify(struct wilc *wilc); int host_sleep_notify(struct wilc *wilc);
int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
u32 count); u32 count);
int wilc_wlan_init(struct net_device *dev); int wilc_wlan_init(struct net_device *dev);