/**  @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;
}
Beispiel #2
0
/**
 *  @brief Handle suspend 
 *
 *  @param intf		  Pointer to usb_interface
 *  @param message	  Pointer to pm_message_t structure 			
 *
 *  @return 	   	  MLAN_STATUS_SUCCESS
 */
static int
woal_usb_suspend(struct usb_interface *intf, pm_message_t message)
{
    struct usb_card_rec *cardp = usb_get_intfdata(intf);
    moal_handle *handle = NULL;
    int i;

    ENTER();

    if (!cardp || !cardp->phandle) {
        PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
        LEAVE();
        return MLAN_STATUS_SUCCESS;
    }
    handle = cardp->phandle;

    /* Enable Host Sleep */
    woal_enable_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY));

    /* Indicate device suspended */
    /* The flag must be set here before the usb_kill_urb() calls. Reason: In
       the complete handlers, urb->status(= -ENOENT) and 'is_suspended' flag is 
       used in combination to distinguish between a suspended state and a
       'disconnect' one. */
    handle->is_suspended = MTRUE;
    for (i = 0; i < handle->priv_num; i++)
        netif_carrier_off(handle->priv[i]->netdev);

    /* Unlink Rx cmd URB */
    if (atomic_read(&cardp->rx_cmd_urb_pending) && cardp->rx_cmd.urb) {
        usb_kill_urb(cardp->rx_cmd.urb);
    }
    /* Unlink Rx data URBs */
    if (atomic_read(&cardp->rx_data_urb_pending)) {
        for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
            if (cardp->rx_data_list[i].urb)
                usb_kill_urb(cardp->rx_data_list[i].urb);
        }
    }

    /* Unlink Tx data URBs */
    for (i = 0; i < MVUSB_TX_HIGH_WMARK; i++) {
        if (cardp->tx_data_list[i].urb) {
            usb_kill_urb(cardp->tx_data_list[i].urb);
        }
    }
    /* Unlink Tx cmd URB */
    if (cardp->tx_cmd.urb) {
        usb_kill_urb(cardp->tx_cmd.urb);
    }

    handle->suspend_wait_q_woken = MTRUE;
    wake_up_interruptible(&handle->suspend_wait_q);

    LEAVE();
    return MLAN_STATUS_SUCCESS;
}
/**  @brief This function handles client driver suspend
 *  
 *  @param dev	   A pointer to device structure
 *  @return 	   MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
int
woal_sdio_suspend(struct device *dev)
{
    struct sdio_func *func = dev_to_sdio_func(dev);
    mmc_pm_flag_t pm_flags = 0;
    moal_handle *handle = NULL;
    struct sdio_mmc_card *cardp;
    int i;
    int ret = MLAN_STATUS_SUCCESS;
    int hs_actived = 0;

    ENTER();

    if (func) {
        pm_flags = sdio_get_host_pm_caps(func);
        PRINTM(MCMND, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
               pm_flags);
        if (!(pm_flags & MMC_PM_KEEP_POWER)) {
            PRINTM(MERROR, "%s: cannot remain alive while host is suspended\n",
                   sdio_func_id(func));
            LEAVE();
            return -ENOSYS;
        }
        cardp = sdio_get_drvdata(func);
        if (!cardp || !cardp->handle) {
            PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
            LEAVE();
            return MLAN_STATUS_SUCCESS;
        }
    } else {
        PRINTM(MERROR, "sdio_func is not specified\n");
        LEAVE();
        return MLAN_STATUS_SUCCESS;
    }
    handle = cardp->handle;

    if (pm_keep_power) {
        /* Enable the Host Sleep */
        hs_actived = woal_enable_hs(woal_get_priv(handle, MLAN_BSS_TYPE_ANY));
        if (hs_actived) {
            PRINTM(MCMND, "suspend with MMC_PM_KEEP_POWER\n");
            ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
        }
    }

    /* Indicate device suspended */
    handle->is_suspended = MTRUE;
    for (i = 0; i < handle->priv_num; i++)
        netif_carrier_off(handle->priv[i]->netdev);

    LEAVE();
    return ret;
}
/**
 * @brief reset AP or GO parameters
 *
 * @param wiphy           A pointer to wiphy structure
 * @param dev             A pointer to net_device structure
 *
 * @return                0 -- success, otherwise fail
 */
int
woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
{
	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
	int ret = 0;
#ifdef STA_SUPPORT
	moal_private *pmpriv = NULL;
#endif

	ENTER();

	PRINTM(MMSG, "wlan: Stoping AP\n");
	woal_deauth_all_station(priv);
	/* if the bss is still running, then stop it */
	if (priv->bss_started == MTRUE) {
		if (MLAN_STATUS_SUCCESS !=
		    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT_TIMEOUT, UAP_BSS_STOP)) {
			ret = -EFAULT;
			goto done;
		}
		if (MLAN_STATUS_SUCCESS !=
		    woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_RESET)) {
			ret = -EFAULT;
			goto done;
		}
		/* Set WLAN MAC addresses */
		if (MLAN_STATUS_SUCCESS != woal_request_set_mac_address(priv)) {
			PRINTM(MERROR, "Set MAC address failed\n");
			ret = -EFAULT;
			goto done;
		}
	}
	woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);

#ifdef STA_SUPPORT
	if (!woal_is_any_interface_active(priv->phandle)) {
		pmpriv = woal_get_priv((moal_handle *)priv->phandle,
				       MLAN_BSS_ROLE_STA);
		if (pmpriv)
			woal_set_scan_time(pmpriv, ACTIVE_SCAN_CHAN_TIME,
					   PASSIVE_SCAN_CHAN_TIME,
					   SPECIFIC_SCAN_CHAN_TIME);
	}
#endif

	priv->cipher = 0;
	memset(priv->uap_wep_key, 0, sizeof(priv->uap_wep_key));
	priv->channel = 0;
	PRINTM(MMSG, "wlan: AP stopped\n");
done:
	LEAVE();
	return ret;
}
/**  @brief This function handles client driver resume
 *  
 *  @param dev	   A pointer to device structure
 *  @return 	   MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
int
woal_sdio_resume(struct device *dev)
{
    struct sdio_func *func = dev_to_sdio_func(dev);
    mmc_pm_flag_t pm_flags = 0;
    moal_handle *handle = NULL;
    struct sdio_mmc_card *cardp;
    int i;

    ENTER();

    if (func) {
        pm_flags = sdio_get_host_pm_caps(func);
        PRINTM(MCMND, "%s: resume: PM flags = 0x%x\n", sdio_func_id(func),
               pm_flags);
        cardp = sdio_get_drvdata(func);
        if (!cardp || !cardp->handle) {
            PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
            LEAVE();
            return MLAN_STATUS_SUCCESS;
        }
    } else {
        PRINTM(MERROR, "sdio_func is not specified\n");
        LEAVE();
        return MLAN_STATUS_SUCCESS;
    }
    handle = cardp->handle;

    if (handle->is_suspended == MFALSE) {
        PRINTM(MWARN, "Device already resumed\n");
        LEAVE();
        return MLAN_STATUS_SUCCESS;
    }

    handle->is_suspended = MFALSE;
    for (i = 0; i < handle->priv_num; i++)
        netif_carrier_on(handle->priv[i]->netdev);

    /* Disable Host Sleep */
    woal_hs_cfg_cancel(woal_get_priv(handle, MLAN_BSS_TYPE_ANY), MOAL_NO_WAIT);

    LEAVE();
    return MLAN_STATUS_SUCCESS;

}
/**  @brief This function handles client driver resume
 *
 *  @param dev      A pointer to device structure
 *  @return         MLAN_STATUS_SUCCESS
 */
int
woal_sdio_resume(struct device *dev)
{
	struct sdio_func *func = dev_to_sdio_func(dev);
	mmc_pm_flag_t pm_flags = 0;
	moal_handle *handle = NULL;
	struct sdio_mmc_card *cardp;
	int i;

	ENTER();
	PRINTM(MCMND, "<--- Enter woal_sdio_resume --->\n");
	wifi_enable_hostwake_irq(MFALSE);
	pm_flags = sdio_get_host_pm_caps(func);
	PRINTM(MCMND, "%s: resume: PM flags = 0x%x\n", sdio_func_id(func),
	       pm_flags);
	cardp = sdio_get_drvdata(func);
	if (!cardp || !cardp->handle) {
		PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
		LEAVE();
		return MLAN_STATUS_SUCCESS;
	}
	handle = cardp->handle;

	if (handle->is_suspended == MFALSE) {
		PRINTM(MWARN, "Device already resumed\n");
		LEAVE();
		return MLAN_STATUS_SUCCESS;
	}
	handle->is_suspended = MFALSE;
	if (woal_check_driver_status(handle)) {
		PRINTM(MERROR, "Resuem, device is in hang state\n");
		LEAVE();
		return MLAN_STATUS_SUCCESS;
	}
	for (i = 0; i < handle->priv_num; i++)
		netif_device_attach(handle->priv[i]->netdev);

	/* Disable Host Sleep */
	woal_cancel_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), MOAL_NO_WAIT);
	PRINTM(MCMND, "<--- Leave woal_sdio_resume --->\n");
	LEAVE();
	return MLAN_STATUS_SUCCESS;
}
Beispiel #7
0
/**  @brief This function handles client driver suspend
 *
 *  @param dev      A pointer to device structure
 *  @return         MLAN_STATUS_SUCCESS or error code
 */
int
woal_sdio_suspend(struct device *dev)
{
	struct sdio_func *func = dev_to_sdio_func(dev);
	mmc_pm_flag_t pm_flags = 0;
	moal_handle *handle = NULL;
	struct sdio_mmc_card *cardp;
	int i, retry_num = 8;
	int ret = MLAN_STATUS_SUCCESS;
	int hs_actived = 0;
	mlan_ds_ps_info pm_info;

	ENTER();
	PRINTM(MCMND, "<--- Enter woal_sdio_suspend --->\n");
	pm_flags = sdio_get_host_pm_caps(func);
	PRINTM(MCMND, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
	       pm_flags);
	if (!(pm_flags & MMC_PM_KEEP_POWER)) {
		PRINTM(MERROR,
		       "%s: cannot remain alive while host is suspended\n",
		       sdio_func_id(func));
		LEAVE();
		return -ENOSYS;
	}
	cardp = sdio_get_drvdata(func);
	if (!cardp || !cardp->handle) {
		PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
		LEAVE();
		return MLAN_STATUS_SUCCESS;
	}

	handle = cardp->handle;
	if (handle->is_suspended == MTRUE) {
		PRINTM(MWARN, "Device already suspended\n");
		LEAVE();
		return MLAN_STATUS_SUCCESS;
	}
	if (handle->fw_dump) {
		PRINTM(MMSG, "suspend not allowed while FW dump!");
		ret = -EBUSY;
		goto done;
	}
	handle->suspend_fail = MFALSE;
	memset(&pm_info, 0, sizeof(pm_info));
	for (i = 0; i < retry_num; i++) {
		if (MLAN_STATUS_SUCCESS ==
		    woal_get_pm_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
				     &pm_info)) {
			if (pm_info.is_suspend_allowed == MTRUE)
				break;
			else
				PRINTM(MMSG,
				       "Suspend not allowed and retry again\n");
		}
		woal_sched_timeout(100);
	}
	if (pm_info.is_suspend_allowed == MFALSE) {
		PRINTM(MMSG, "Suspend not allowed\n");
		ret = -EBUSY;
		goto done;
	}

	for (i = 0; i < handle->priv_num; i++)
		netif_device_detach(handle->priv[i]->netdev);

	if (pm_keep_power) {
		/* Enable the Host Sleep */
#ifdef MMC_PM_FUNC_SUSPENDED
		handle->suspend_notify_req = MTRUE;
#endif
		hs_actived =
			woal_enable_hs(woal_get_priv
				       (handle, MLAN_BSS_ROLE_ANY));
#ifdef MMC_PM_FUNC_SUSPENDED
		handle->suspend_notify_req = MFALSE;
#endif
		if (hs_actived) {
#ifdef MMC_PM_SKIP_RESUME_PROBE
			PRINTM(MCMND,
			       "suspend with MMC_PM_KEEP_POWER and MMC_PM_SKIP_RESUME_PROBE\n");
			ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER |
						     MMC_PM_SKIP_RESUME_PROBE);
#else
			PRINTM(MCMND, "suspend with MMC_PM_KEEP_POWER\n");
			ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
#endif
		} else {
			PRINTM(MMSG, "HS not actived, suspend fail!");
			handle->suspend_fail = MTRUE;
			for (i = 0; i < handle->priv_num; i++)
				netif_device_attach(handle->priv[i]->netdev);
			ret = -EBUSY;
			goto done;
		}
	}

	/* Indicate device suspended */
	handle->is_suspended = MTRUE;
done:
	PRINTM(MCMND, "<--- Leave woal_sdio_suspend --->\n");
	LEAVE();
	return ret;
}
Beispiel #8
0
/**
 *  @brief Handle resume
 *
 *  @param intf		  Pointer to usb_interface
 *  
 *  @return 	   	  MLAN_STATUS_SUCCESS
 */
static int
woal_usb_resume(struct usb_interface *intf)
{
    struct usb_card_rec *cardp = usb_get_intfdata(intf);
    moal_handle *handle = NULL;
    int i;

    ENTER();

    if (!cardp || !cardp->phandle) {
        PRINTM(MERROR, "Card or adapter structure is not valid\n");
        LEAVE();
        return MLAN_STATUS_SUCCESS;
    }
    handle = cardp->phandle;

    if (handle->is_suspended == MFALSE) {
        PRINTM(MWARN, "Device already resumed\n");
        LEAVE();
        return MLAN_STATUS_SUCCESS;
    }

    /* Indicate device resumed. The netdev queue will be resumed only after
       the urbs have been resubmitted */
    handle->is_suspended = MFALSE;

    if (!atomic_read(&cardp->rx_data_urb_pending)) {
        /* Submit multiple Rx data URBs */
        woal_usb_submit_rx_data_urbs(handle);
    }
    if (!atomic_read(&cardp->rx_cmd_urb_pending)) {
        if ((cardp->rx_cmd.pmbuf =
             woal_alloc_mlan_buffer(handle, MLAN_RX_CMD_BUF_SIZE)))
            woal_usb_submit_rx_urb(&cardp->rx_cmd, MLAN_RX_CMD_BUF_SIZE);
    }

    for (i = 0; i < handle->priv_num; i++)
        if (handle->priv[i]->media_connected == MTRUE)
            netif_carrier_on(handle->priv[i]->netdev);

    /* Disable Host Sleep */
    if (handle->hs_activated)
        woal_cancel_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), MOAL_NO_WAIT);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
#ifdef CONFIG_PM
    /* Resume handler may be called due to remote wakeup, force to exit suspend 
       anyway */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
    cardp->udev->autosuspend_disabled = 1;
#else
    cardp->udev->dev.power.runtime_auto = 0;
#endif /* < 2.6.35 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
    cardp->udev->autoresume_disabled = 0;
#endif /* < 2.6.33 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)
    atomic_inc(&(cardp->udev)->dev.power.usage_count);
#endif /* >= 2.6.34 */
#endif /* CONFIG_PM */
#endif /* >= 2.6.24 */

    LEAVE();
    return MLAN_STATUS_SUCCESS;
}
Beispiel #9
0
/** 
 *  @brief config proc write function
 *
 *  @param f	   file pointer
 *  @param buf     pointer to data buffer
 *  @param cnt     data number to write
 *  @param data    data to write
 *  @return 	   number of data
 */
static int
woal_config_write(struct file *f, const char *buf, unsigned long cnt,
                  void *data)
{
    char databuf[101];
    char *line;
    t_u32 config_data = 0;
    moal_handle *handle = (moal_handle *) data;
    int func, reg, val;
    int copy_len;
    moal_private *priv = NULL;

    ENTER();
    if (!MODULE_GET) {
        LEAVE();
        return 0;
    }

    if (cnt >= sizeof(databuf)) {
        MODULE_PUT;
        LEAVE();
        return (int) cnt;
    }
    memset(databuf, 0, sizeof(databuf));
    copy_len = MIN((sizeof(databuf) - 1), cnt);
    if (copy_from_user(databuf, buf, copy_len)) {
        MODULE_PUT;
        LEAVE();
        return 0;
    }
    line = databuf;
    if (!strncmp(databuf, "soft_reset", strlen("soft_reset"))) {
        line += strlen("soft_reset") + 1;
        config_data = (t_u32) woal_string_to_number(line);
        PRINTM(MINFO, "soft_reset: %d\n", (int) config_data);
        if (woal_request_soft_reset(handle) == MLAN_STATUS_SUCCESS) {
            handle->hardware_status = HardwareStatusReset;
        } else {
            PRINTM(MERROR, "Could not perform soft reset\n");
        }
    }
    if (!strncmp(databuf, "drv_mode", strlen("drv_mode"))) {
        line += strlen("drv_mode") + 1;
        config_data = (t_u32) woal_string_to_number(line);
        PRINTM(MINFO, "drv_mode: %d\n", (int) config_data);
        if (config_data != (t_u32) drv_mode)
            if (woal_switch_drv_mode(handle, config_data) !=
                MLAN_STATUS_SUCCESS) {
                PRINTM(MERROR, "Could not switch drv mode\n");
            }
    }
    if (!strncmp(databuf, "sdcmd52rw=", strlen("sdcmd52rw="))) {
        parse_cmd52_string(databuf, (size_t) cnt, &func, &reg, &val);
        woal_sdio_read_write_cmd52(handle, func, reg, val);
    }
    if (!strncmp(databuf, "debug_dump", strlen("debug_dump"))) {
        priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
        if (priv) {
            woal_mlan_debug_info(priv);
            woal_moal_debug_info(priv, NULL, MFALSE);
            woal_dump_firmware_info(priv);
        }
    }

    MODULE_PUT;
    LEAVE();
    return (int) cnt;
}