diff --git a/drivers/staging/wilc1000/bt.c b/drivers/staging/wilc1000/bt.c index 48a530250151fa..705ea17cb6626e 100644 --- a/drivers/staging/wilc1000/bt.c +++ b/drivers/staging/wilc1000/bt.c @@ -307,7 +307,7 @@ int wilc_bt_power_down(struct wilc *wilc, int source) mutex_lock(&wilc->cs); - pr_info("source: %s, current bus status Wifi: %d, BT: %d\n", + pr_info("POWERING DOWN: source: %s, current bus status Wifi: %d, BT: %d\n", (source == DEV_WIFI ? "Wifi" : "BT"), wilc->power.status[DEV_WIFI], wilc->power.status[DEV_BT]); @@ -327,6 +327,7 @@ int wilc_bt_power_down(struct wilc *wilc, int source) release_bus(wilc, WILC_BUS_RELEASE_ONLY, source); if (ret) { mutex_unlock(&wilc->cs); + pr_err("deinit failed ret: 0x%0x\n", ret); return ret; } } @@ -346,7 +347,7 @@ int wilc_bt_power_up(struct wilc *wilc, int source) mutex_lock(&wilc->cs); - pr_debug("source: %s, current bus status Wifi: %d, BT: %d\n", + pr_info("POWERING UP: source: %s, current bus status Wifi: %d, BT: %d\n", (source == DEV_WIFI ? "Wifi" : "BT"), wilc->power.status[DEV_WIFI], wilc->power.status[DEV_BT]); diff --git a/drivers/staging/wilc1000/hif.c b/drivers/staging/wilc1000/hif.c index 8d9cbc07af52b2..5389430a9ed291 100644 --- a/drivers/staging/wilc1000/hif.c +++ b/drivers/staging/wilc1000/hif.c @@ -1819,12 +1819,18 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) { struct wid wid; int result; + struct wilc *wilc = vif->wilc; if (!rssi_level) { PRINT_ER(vif->ndev, "RSS pointer value is null\n"); return -EFAULT; } + if (!wilc->initialized) { + netdev_info(vif->ndev, "Driver not initialized\n"); + return 0; + } + wid.id = WID_RSSI; wid.type = WID_CHAR; wid.size = sizeof(char); diff --git a/drivers/staging/wilc1000/netdev.c b/drivers/staging/wilc1000/netdev.c index 3e7aff7af36daf..e27be97224eb5d 100644 --- a/drivers/staging/wilc1000/netdev.c +++ b/drivers/staging/wilc1000/netdev.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "netdev.h" #include "cfg80211.h" @@ -744,13 +745,17 @@ static void wilc_wlan_deinitialize(struct net_device *dev) struct wilc_vif *vif = netdev_priv(dev); struct wilc *wl = vif->wilc; + if (!wl) { + PRINT_ER(dev, "wl is NULL\n"); + return; + } + if (wl->initialized) { PRINT_INFO(vif->ndev, INIT_DBG, "Deinitializing wilc ...\n"); - if (!wl) { - PRINT_ER(dev, "wl is NULL\n"); - return; - } + ret = wilc_wlan_stop(wl, vif); + if (ret != 0) + PRINT_ER(dev, "failed in wlan_stop\n"); PRINT_D(vif->ndev, INIT_DBG, "destroy aging timer\n"); @@ -765,21 +770,18 @@ static void wilc_wlan_deinitialize(struct net_device *dev) mutex_unlock(&wl->hif_cs); } } - complete(&wl->txq_event); + deinit_irq(dev); PRINT_INFO(vif->ndev, INIT_DBG, "Deinitializing Threads\n"); wlan_deinitialize_threads(dev); PRINT_INFO(vif->ndev, INIT_DBG, "Deinitializing IRQ\n"); - deinit_irq(dev); - - ret = wilc_wlan_stop(wl, vif); - if (ret != 0) - PRINT_ER(dev, "failed in wlan_stop\n"); PRINT_INFO(vif->ndev, INIT_DBG, "Deinitializing WILC Wlan\n"); wilc_wlan_cleanup(dev); wl->initialized = false; + wl->close = 0; + wl->quit = 0; PRINT_INFO(dev, INIT_DBG, "wilc deinitialization Done\n"); } else { @@ -828,8 +830,6 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) if (!wl->initialized) { wl->mac_status = WILC_MAC_STATUS_INIT; - wl->close = 0; - wl->initialized = 0; ret = wilc_wlan_init(dev); if (ret) { @@ -871,9 +871,11 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) ret = wilc_start_firmware(dev); if (ret) { PRINT_ER(dev, "Failed to start firmware\n"); - goto fail_irq_enable; + goto fail_fw_start; } + wl->initialized = true; + if (cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) { int size; char firmware_ver[50]; @@ -893,7 +895,6 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) goto fail_fw_start; } - wl->initialized = true; return 0; fail_fw_start: @@ -910,6 +911,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) fail_wilc_wlan: wilc_wlan_cleanup(dev); PRINT_ER(dev, "WLAN initialization FAILED\n"); + wl->initialized = false; } else { PRINT_WRN(vif->ndev, INIT_DBG, "wilc already initialized\n"); } @@ -928,7 +930,7 @@ static int wilc_mac_open(struct net_device *ndev) { struct wilc_vif *vif = netdev_priv(ndev); struct wilc *wl = vif->wilc; - unsigned char mac_add[ETH_ALEN] = {0}; + unsigned char mac_add[ETH_ALEN] __aligned(2) = { 0 }; int ret = 0; if (!wl || !wl->dev) { @@ -999,7 +1001,7 @@ static int wilc_set_mac_addr(struct net_device *dev, void *p) struct wilc_vif *vif = netdev_priv(dev); struct sockaddr *addr = (struct sockaddr *)p; struct wilc *wilc = vif->wilc; - unsigned char mac_addr[6] = {0}; + unsigned char mac_addr[6] __aligned(2) = { 0 }; struct wilc_vif *tmp_vif; int srcu_idx; @@ -1164,10 +1166,10 @@ static int wilc_mac_close(struct net_device *ndev) if (vif->ndev) { netif_stop_queue(vif->ndev); - handle_connect_cancel(vif); + handle_connect_cancel(vif); - if (!recovery_on) - wilc_deinit_host_int(vif->ndev); + if (!recovery_on) + wilc_deinit_host_int(vif->ndev); } if (wl->open_ifcs == 0) { @@ -1175,6 +1177,9 @@ static int wilc_mac_close(struct net_device *ndev) wl->close = 1; wilc_wlan_deinitialize(ndev); + + PRINT_INFO(ndev, GENERIC_DBG, "Powering down wilc\n"); + wilc_bt_power_down(wl, DEV_WIFI); } vif->mac_opened = 0; @@ -1266,7 +1271,6 @@ void wilc_netdev_cleanup(struct wilc *wilc) #endif wilc_sysfs_exit(); wlan_deinit_locks(wilc); - kfree(wilc->bus_data); wiphy_unregister(wilc->wiphy); pr_info("Freeing wiphy\n"); wiphy_free(wilc->wiphy); diff --git a/drivers/staging/wilc1000/sdio.c b/drivers/staging/wilc1000/sdio.c index 90be674a77d029..7debf403dc35bf 100644 --- a/drivers/staging/wilc1000/sdio.c +++ b/drivers/staging/wilc1000/sdio.c @@ -221,18 +221,22 @@ static int wilc_sdio_probe(struct sdio_func *func, wilc_netdev_cleanup(wilc); free: kfree(sdio_priv); + wilc->bus_data = NULL; return ret; } static void wilc_sdio_remove(struct sdio_func *func) { struct wilc *wilc = sdio_get_drvdata(func); + struct wilc_sdio *sdio_priv = wilc->bus_data; if (!IS_ERR(wilc->rtc_clk)) clk_disable_unprepare(wilc->rtc_clk); wilc_netdev_cleanup(wilc); wilc_bt_deinit(); + kfree(sdio_priv); + wilc->bus_data = NULL; } static int wilc_sdio_reset(struct wilc *wilc) @@ -257,6 +261,9 @@ static int wilc_sdio_reset(struct wilc *wilc) static bool wilc_sdio_is_init(struct wilc *wilc) { struct wilc_sdio *sdio_priv = wilc->bus_data; + if (!sdio_priv) { + return false; + } return sdio_priv->is_init; } @@ -410,6 +417,11 @@ static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data) struct wilc_sdio *sdio_priv = wilc->bus_data; int ret; + if (!sdio_priv) { + dev_err(&func->dev, "%s: 'bus_data' not initialized\n", __func__); + return -1; + } + cpu_to_le32s(&data); if (addr >= 0xf0 && addr <= 0xff) { /* only vendor specific registers */ @@ -459,6 +471,11 @@ static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; + if (!sdio_priv) { + dev_err(&func->dev, "%s: 'bus_data' not initialized\n", __func__); + return -1; + } + u32 block_size = sdio_priv->block_size; struct sdio_cmd53 cmd; int nblk, nleft, ret; @@ -533,6 +550,11 @@ static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data) struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; int ret; + + if (!sdio_priv) { + dev_err(&func->dev, "%s: 'bus_data' not initialized\n", __func__); + return -1; + } if (addr >= 0xf0 && addr <= 0xff) { /* only vendor specific registers */ struct sdio_cmd52 cmd; @@ -580,9 +602,15 @@ static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; - u32 block_size = sdio_priv->block_size; struct sdio_cmd53 cmd; int nblk, nleft, ret; + u32 block_size; + + if (!sdio_priv) { + dev_err(&func->dev, "%s: 'bus_data' not initialized\n", __func__); + return -1; + } + block_size = sdio_priv->block_size; cmd.read_write = 0; if (addr > 0) { @@ -660,7 +688,9 @@ static int wilc_sdio_deinit(struct wilc *wilc) struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; - sdio_priv->is_init = false; + if (sdio_priv) { + sdio_priv->is_init = false; + } pm_runtime_put_sync_autosuspend(mmc_dev(func->card->host)); wilc_wlan_power(wilc, false); @@ -672,6 +702,11 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; + if (!sdio_priv) { + dev_err(&func->dev, "%s: 'bus_data' not initialized\n", __func__); + return -1; + } + struct sdio_cmd52 cmd; int loop, ret; u32 chipid; @@ -830,6 +865,11 @@ static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; + if (!sdio_priv) { + dev_err(&func->dev, "%s: 'bus_data' not initialized\n", __func__); + return -1; + } + u32 tmp; struct sdio_cmd52 cmd; u32 irq_flags; @@ -881,6 +921,11 @@ static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) struct wilc_sdio *sdio_priv = wilc->bus_data; int ret; u32 reg = 0; + + if (!sdio_priv) { + dev_err(&func->dev, "%s: 'bus_data' not initialized\n", __func__); + return -1; + } if (wilc->chip == WILC_1000) { if (sdio_priv->irq_gpio) @@ -970,6 +1015,11 @@ static int wilc_sdio_sync_ext(struct wilc *wilc, int nint) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; + if (!sdio_priv) { + dev_err(&func->dev, "%s: 'bus_data' not initialized\n", __func__); + return -1; + } + u32 reg; int ret, i; diff --git a/drivers/staging/wilc1000/spi.c b/drivers/staging/wilc1000/spi.c index 634454a00a713e..737fe64a2b282a 100644 --- a/drivers/staging/wilc1000/spi.c +++ b/drivers/staging/wilc1000/spi.c @@ -162,18 +162,22 @@ static int wilc_bus_probe(struct spi_device *spi) wilc_netdev_cleanup(wilc); free: kfree(spi_priv); + wilc->bus_data = NULL; return ret; } static int wilc_bus_remove(struct spi_device *spi) { struct wilc *wilc = spi_get_drvdata(spi); + struct wilc_spi *spi_priv = wilc->bus_data; if (!IS_ERR(wilc->rtc_clk)) clk_disable_unprepare(wilc->rtc_clk); wilc_netdev_cleanup(wilc); wilc_bt_deinit(); + kfree(spi_priv); + wilc->bus_data = NULL; return 0; } diff --git a/drivers/staging/wilc1000/wlan.c b/drivers/staging/wilc1000/wlan.c index d603cd6cb6561c..5f007d9c04dd2f 100644 --- a/drivers/staging/wilc1000/wlan.c +++ b/drivers/staging/wilc1000/wlan.c @@ -885,9 +885,12 @@ static void chip_wakeup_wilc3000(struct wilc *wilc, int source) /* in case of failure, Reset the wakeup bit to introduce a new * edge on the next loop */ - if ((clk_status_reg_val & clk_status_bit) == 0) + if ((clk_status_reg_val & clk_status_bit) == 0) { hif_func->hif_write_reg(wilc, wakeup_reg, wakeup_reg_val & (~wakeup_bit)); + /* added wait before wakeup sequence retry */ + usleep_range(200, 300); + } } while (((clk_status_reg_val & clk_status_bit) == 0) && (wake_seq_trials-- > 0)); if (!wake_seq_trials) @@ -1261,10 +1264,10 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) out_release_bus: release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI); - schedule(); out_unlock: mutex_unlock(&wilc->txq_add_to_head_cs); + schedule(); out_update_cnt: *txq_count = wilc->txq_entries; @@ -1418,6 +1421,9 @@ void wilc_handle_isr(struct wilc *wilc) { u32 int_status; + if (wilc->close) + return; + acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_WIFI); wilc->hif_func->hif_read_int(wilc, &int_status); @@ -1544,10 +1550,6 @@ int wilc_wlan_start(struct wilc *wilc) ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); - if (!ret) - wilc->initialized = 1; - else - wilc->initialized = 0; release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI); return (ret < 0) ? ret : 0; @@ -1564,7 +1566,7 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) ret = wilc->hif_func->hif_read_reg(wilc, GLOBAL_MODE_CONTROL, ®); if (ret) { PRINT_ER(vif->ndev, "Error while reading reg\n"); - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI); + release_bus(wilc, WILC_BUS_RELEASE_ONLY, DEV_WIFI); return -EIO; } @@ -1572,7 +1574,7 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) ret = wilc->hif_func->hif_write_reg(wilc, GLOBAL_MODE_CONTROL, reg); if (ret) { PRINT_ER(vif->ndev, "Error while writing reg\n"); - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI); + release_bus(wilc, WILC_BUS_RELEASE_ONLY, DEV_WIFI); return -EIO; } @@ -1582,7 +1584,7 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) ret = wilc->hif_func->hif_read_reg(wilc, PWR_SEQ_MISC_CTRL, ®); if (ret) { PRINT_ER(vif->ndev, "Error while reading reg\n"); - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI); + release_bus(wilc, WILC_BUS_RELEASE_ONLY, DEV_WIFI); return ret; } @@ -1590,14 +1592,14 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) ret = wilc->hif_func->hif_write_reg(wilc, PWR_SEQ_MISC_CTRL, reg); if (ret) { PRINT_ER(vif->ndev, "Error while writing reg\n"); - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI); + release_bus(wilc, WILC_BUS_RELEASE_ONLY, DEV_WIFI); return ret; } ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); if (ret) { PRINT_ER(vif->ndev, "Error while reading reg\n"); - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI); + release_bus(wilc, WILC_BUS_RELEASE_ONLY, DEV_WIFI); return ret; } @@ -1605,11 +1607,11 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) (reg | WILC_ABORT_REQ_BIT)); if (ret) { PRINT_ER(vif->ndev, "Error while writing reg\n"); - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI); + release_bus(wilc, WILC_BUS_RELEASE_ONLY, DEV_WIFI); return ret; } - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_WIFI); + release_bus(wilc, WILC_BUS_RELEASE_ONLY, DEV_WIFI); return 0; } @@ -1883,6 +1885,7 @@ int wilc_wlan_init(struct net_device *dev) wilc = vif->wilc; wilc->quit = 0; + wilc->close = 0; PRINT_INFO(vif->ndev, INIT_DBG, "Initializing WILC_Wlan\n");