/* Proc hscfg file write handler * This function can be used to configure the host sleep parameters. */ static ssize_t mwifiex_hscfg_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct mwifiex_private *priv = (void *)file->private_data; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1); int ret, arg_num; struct mwifiex_ds_hs_cfg hscfg; int conditions = HS_CFG_COND_DEF; u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF; if (!buf) return -ENOMEM; if (copy_from_user(buf, ubuf, buf_size)) { ret = -EFAULT; goto done; } arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap); memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg)); if (arg_num > 3) { mwifiex_dbg(priv->adapter, ERROR, "Too many arguments\n"); ret = -EINVAL; goto done; } if (arg_num >= 1 && arg_num < 3) mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET, MWIFIEX_SYNC_CMD, &hscfg); if (arg_num) { if (conditions == HS_CFG_CANCEL) { mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD); ret = count; goto done; } hscfg.conditions = conditions; } if (arg_num >= 2) hscfg.gpio = gpio; if (arg_num == 3) hscfg.gap = gap; hscfg.is_invoke_hostcmd = false; mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, &hscfg); mwifiex_enable_hs(priv->adapter); priv->adapter->hs_enabling = false; ret = count; done: free_page(addr); return ret; }
/* * SDIO resume. * * Kernel needs to suspend all functions separately. Therefore all * registered functions must have drivers with suspend and resume * methods. Failing that the kernel simply removes the whole card. * * If already not resumed, this function turns on the traffic and * sends a host sleep cancel request to the firmware. */ static int mwifiex_sdio_resume(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; if (func) { pm_flag = sdio_get_host_pm_caps(func); card = sdio_get_drvdata(func); if (!card || !card->adapter) { pr_err("resume: invalid card or adapter\n"); return 0; } } else { pr_err("resume: sdio_func is not specified\n"); return 0; } adapter = card->adapter; if (!adapter->is_suspended) { dev_warn(adapter->dev, "device already resumed\n"); return 0; } adapter->is_suspended = false; /* Disable Host Sleep */ mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), MWIFIEX_ASYNC_CMD); return 0; }
static int mwifiex_pcie_resume(struct pci_dev *pdev) { struct mwifiex_adapter *adapter; struct pcie_service_card *card; int i; if (pdev) { card = (struct pcie_service_card *) pci_get_drvdata(pdev); if (!card || !card->adapter) { pr_err("Card or adapter structure is not valid\n"); return 0; } } else { pr_err("PCIE device is not specified\n"); return 0; } adapter = card->adapter; if (!adapter->is_suspended) { dev_warn(adapter->dev, "Device already resumed\n"); return 0; } adapter->is_suspended = false; for (i = 0; i < adapter->priv_num; i++) if (adapter->priv[i]->media_connected) netif_carrier_on(adapter->priv[i]->netdev); mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), MWIFIEX_ASYNC_CMD); return 0; }
/* Proc hscfg file write handler * This function can be used to configure the host sleep parameters. */ static ssize_t mwifiex_hscfg_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct mwifiex_private *priv = (void *)file->private_data; char *buf; int ret, arg_num; struct mwifiex_ds_hs_cfg hscfg; int conditions = HS_CFG_COND_DEF; u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF; buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); if (IS_ERR(buf)) return PTR_ERR(buf); arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap); memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg)); if (arg_num > 3) { mwifiex_dbg(priv->adapter, ERROR, "Too many arguments\n"); ret = -EINVAL; goto done; } if (arg_num >= 1 && arg_num < 3) mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET, MWIFIEX_SYNC_CMD, &hscfg); if (arg_num) { if (conditions == HS_CFG_CANCEL) { mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD); ret = count; goto done; } hscfg.conditions = conditions; } if (arg_num >= 2) hscfg.gpio = gpio; if (arg_num == 3) hscfg.gap = gap; hscfg.is_invoke_hostcmd = false; mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, &hscfg); mwifiex_enable_hs(priv->adapter); priv->adapter->hs_enabling = false; ret = count; done: kfree(buf); return ret; }
/* Kernel needs to suspend all functions separately. Therefore all * registered functions must have drivers with suspend and resume * methods. Failing that the kernel simply removes the whole card. * * If already not resumed, this function turns on the traffic and * sends a 'host sleep cancel' request to the firmware. */ static int mwifiex_usb_resume(struct usb_interface *intf) { struct usb_card_rec *card = usb_get_intfdata(intf); struct mwifiex_adapter *adapter; int i; if (!card || !card->adapter) { pr_err("%s: card or card->adapter is NULL\n", __func__); return 0; } adapter = card->adapter; if (unlikely(!adapter->is_suspended)) { dev_warn(adapter->dev, "Device already resumed\n"); return 0; } /* Indicate device resumed. The netdev queue will be resumed only * after the urbs have been re-submitted */ adapter->is_suspended = false; if (!atomic_read(&card->rx_data_urb_pending)) for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) mwifiex_usb_submit_rx_urb(&card->rx_data_list[i], MWIFIEX_RX_DATA_BUF_SIZE); if (!atomic_read(&card->rx_cmd_urb_pending)) { card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE); if (card->rx_cmd.skb) mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE); } for (i = 0; i < adapter->priv_num; i++) if (adapter->priv[i]->media_connected) netif_carrier_on(adapter->priv[i]->netdev); /* Disable Host Sleep */ if (adapter->hs_activated) mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY), MWIFIEX_ASYNC_CMD); #ifdef CONFIG_PM /* Resume handler may be called due to remote wakeup, * force to exit suspend anyway */ usb_disable_autosuspend(card->udev); #endif /* CONFIG_PM */ return 0; }
/* Kernel needs to suspend all functions separately. Therefore all * registered functions must have drivers with suspend and resume * methods. Failing that the kernel simply removes the whole card. * * If already not resumed, this function turns on the traffic and * sends a 'host sleep cancel' request to the firmware. */ static int mwifiex_usb_resume(struct usb_interface *intf) { struct usb_card_rec *card = usb_get_intfdata(intf); struct mwifiex_adapter *adapter; int i; if (!card->adapter) { dev_err(&intf->dev, "%s: card->adapter is NULL\n", __func__); return 0; } adapter = card->adapter; if (unlikely(!adapter->is_suspended)) { mwifiex_dbg(adapter, WARN, "Device already resumed\n"); return 0; } /* Indicate device resumed. The netdev queue will be resumed only * after the urbs have been re-submitted */ adapter->is_suspended = false; if (!atomic_read(&card->rx_data_urb_pending)) for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) mwifiex_usb_submit_rx_urb(&card->rx_data_list[i], MWIFIEX_RX_DATA_BUF_SIZE); if (!atomic_read(&card->rx_cmd_urb_pending)) { card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE); if (card->rx_cmd.skb) mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE); } /* Disable Host Sleep */ if (adapter->hs_activated) mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY), MWIFIEX_ASYNC_CMD); return 0; }
static int mwifiex_sdio_resume(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; int i; if (func) { pm_flag = sdio_get_host_pm_caps(func); card = sdio_get_drvdata(func); if (!card || !card->adapter) { pr_err("resume: invalid card or adapter\n"); return 0; } } else { pr_err("resume: sdio_func is not specified\n"); return 0; } adapter = card->adapter; if (!adapter->is_suspended) { dev_warn(adapter->dev, "device already resumed\n"); return 0; } adapter->is_suspended = false; for (i = 0; i < adapter->priv_num; i++) if (adapter->priv[i]->media_connected) netif_carrier_on(adapter->priv[i]->netdev); mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), MWIFIEX_ASYNC_CMD); return 0; }