/** @brief This function handles client driver shutdown * * @param dev A pointer to device structure * @return N/A */ void woal_sdio_shutdown(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); moal_handle *handle = NULL; struct sdio_mmc_card *cardp; mlan_ds_hs_cfg hscfg; int timeout = 0; int i; ENTER(); PRINTM(MCMND, "<--- Enter woal_sdio_shutdown --->\n"); cardp = sdio_get_drvdata(func); if (!cardp || !cardp->handle) { PRINTM(MERROR, "Card or moal_handle structure is not valid\n"); LEAVE(); return; } handle = cardp->handle; for (i = 0; i < handle->priv_num; i++) netif_device_detach(handle->priv[i]->netdev); if (shutdown_hs) { memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg)); hscfg.is_invoke_hostcmd = MFALSE; hscfg.conditions = SHUTDOWN_HOST_SLEEP_DEF_COND; hscfg.gap = SHUTDOWN_HOST_SLEEP_DEF_GAP; hscfg.gpio = SHUTDOWN_HOST_SLEEP_DEF_GPIO; if (woal_set_get_hs_params (woal_get_priv(handle, MLAN_BSS_ROLE_ANY), MLAN_ACT_SET, MOAL_IOCTL_WAIT, &hscfg) == MLAN_STATUS_FAILURE) { PRINTM(MERROR, "Fail to set HS parameter in shutdown: 0x%x 0x%x 0x%x\n", hscfg.conditions, hscfg.gap, hscfg.gpio); goto done; } /* Enable Host Sleep */ handle->hs_activate_wait_q_woken = MFALSE; memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg)); hscfg.is_invoke_hostcmd = MTRUE; if (woal_set_get_hs_params (woal_get_priv(handle, MLAN_BSS_ROLE_ANY), MLAN_ACT_SET, MOAL_NO_WAIT, &hscfg) == MLAN_STATUS_FAILURE) { PRINTM(MERROR, "Request HS enable failed in shutdown\n"); goto done; } timeout = wait_event_interruptible_timeout (handle->hs_activate_wait_q, handle->hs_activate_wait_q_woken, HS_ACTIVE_TIMEOUT); if (handle->hs_activated == MTRUE) PRINTM(MMSG, "HS actived in shutdown\n"); else PRINTM(MMSG, "Fail to enable HS in shutdown\n"); } done: PRINTM(MCMND, "<--- Leave woal_sdio_shutdown --->\n"); LEAVE(); return; }
/** * @brief uap hs_cfg ioctl handler * * @param dev A pointer to net_device structure * @param req A pointer to ifreq structure * @return 0 --success, otherwise fail */ static int woal_uap_hs_cfg(struct net_device *dev, struct ifreq *req) { moal_private *priv = (moal_private *) netdev_priv(dev); mlan_ds_hs_cfg hscfg; ds_hs_cfg hs_cfg; t_u16 action; int ret = 0; ENTER(); memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg)); memset(&hs_cfg, 0, sizeof(ds_hs_cfg)); /* Sanity check */ if (req->ifr_data == NULL) { PRINTM(MERROR, "uap_hs_cfg() corrupt data\n"); ret = -EFAULT; goto done; } if (copy_from_user(&hs_cfg, req->ifr_data, sizeof(ds_hs_cfg))) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; } PRINTM(MIOCTL, "ioctl hscfg: flags=0x%lx condition=0x%lx gpio=%d gap=0x%lx\n", hs_cfg.flags, hs_cfg.conditions, (int) hs_cfg.gpio, hs_cfg.gap); if (hs_cfg.flags & HS_CFG_FLAG_SET) { action = MLAN_ACT_SET; if (hs_cfg.flags != HS_CFG_FLAG_ALL) { woal_set_get_hs_params(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &hscfg); } if (hs_cfg.flags & HS_CFG_FLAG_CONDITION) hscfg.conditions = hs_cfg.conditions; if (hs_cfg.flags & HS_CFG_FLAG_GPIO) hscfg.gpio = hs_cfg.gpio; if (hs_cfg.flags & HS_CFG_FLAG_GAP) hscfg.gap = hs_cfg.gap; /* Issue IOCTL to set up parameters */ hscfg.is_invoke_hostcmd = MFALSE; if (MLAN_STATUS_SUCCESS != woal_set_get_hs_params(priv, action, MOAL_IOCTL_WAIT, &hscfg)) { ret = -EFAULT; goto done; } } else { action = MLAN_ACT_GET; } /* Issue IOCTL to invoke hostcmd */ hscfg.is_invoke_hostcmd = MTRUE; if (MLAN_STATUS_SUCCESS != woal_set_get_hs_params(priv, action, MOAL_IOCTL_WAIT, &hscfg)) { ret = -EFAULT; goto done; } if (!(hs_cfg.flags & HS_CFG_FLAG_SET)) { hs_cfg.flags = HS_CFG_FLAG_CONDITION | HS_CFG_FLAG_GPIO | HS_CFG_FLAG_GAP; hs_cfg.conditions = hscfg.conditions; hs_cfg.gpio = hscfg.gpio; hs_cfg.gap = hscfg.gap; /* Copy to user */ if (copy_to_user(req->ifr_data, &hs_cfg, sizeof(ds_hs_cfg))) { PRINTM(MERROR, "Copy to user failed!\n"); ret = -EFAULT; goto done; } } done: LEAVE(); return ret; }