Exemplo n.º 1
0
/*
 * This function gets firmware and initializes it.
 *
 * The main initialization steps followed are -
 *      - Download the correct firmware to card
 *      - Issue the init commands to firmware
 */
static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
{
	int ret;
	char fmt[64];
	struct mwifiex_private *priv;
	struct mwifiex_adapter *adapter = context;
	struct mwifiex_fw_image fw;

	if (!firmware) {
		dev_err(adapter->dev,
			"Failed to get firmware %s\n", adapter->fw_name);
		goto done;
	}

	memset(&fw, 0, sizeof(struct mwifiex_fw_image));
	adapter->firmware = firmware;
	fw.fw_buf = (u8 *) adapter->firmware->data;
	fw.fw_len = adapter->firmware->size;

	if (adapter->if_ops.dnld_fw)
		ret = adapter->if_ops.dnld_fw(adapter, &fw);
	else
		ret = mwifiex_dnld_fw(adapter, &fw);
	if (ret == -1)
		goto done;

	dev_notice(adapter->dev, "WLAN FW is active\n");

	adapter->init_wait_q_woken = false;
	ret = mwifiex_init_fw(adapter);
	if (ret == -1) {
		goto done;
	} else if (!ret) {
		adapter->hw_status = MWIFIEX_HW_STATUS_READY;
		goto done;
	}
	/* Wait for mwifiex_init to complete */
	wait_event_interruptible(adapter->init_wait_q,
				 adapter->init_wait_q_woken);
	if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
		goto done;

	priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
	if (mwifiex_register_cfg80211(adapter)) {
		dev_err(adapter->dev, "cannot register with cfg80211\n");
		goto err_init_fw;
	}

	rtnl_lock();
	/* Create station interface by default */
	if (!mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d",
				      NL80211_IFTYPE_STATION, NULL, NULL)) {
		dev_err(adapter->dev, "cannot create default STA interface\n");
		goto err_add_intf;
	}

	/* Create AP interface by default */
	if (!mwifiex_add_virtual_intf(adapter->wiphy, "uap%d",
				      NL80211_IFTYPE_AP, NULL, NULL)) {
		dev_err(adapter->dev, "cannot create default AP interface\n");
		goto err_add_intf;
	}

	/* Create P2P interface by default */
	if (!mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d",
				      NL80211_IFTYPE_P2P_CLIENT, NULL, NULL)) {
		dev_err(adapter->dev, "cannot create default P2P interface\n");
		goto err_add_intf;
	}
	rtnl_unlock();

	mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
	dev_notice(adapter->dev, "driver_version = %s\n", fmt);
	goto done;

err_add_intf:
	mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
	rtnl_unlock();
err_init_fw:
	pr_debug("info: %s: unregister device\n", __func__);
	adapter->if_ops.unregister_dev(adapter);
done:
	release_firmware(adapter->firmware);
	complete(&adapter->fw_load);
	return;
}
Exemplo n.º 2
0
void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter)
{
    void *p;
    char drv_version[64];
    struct usb_card_rec *cardp;
    struct sdio_mmc_card *sdio_card;
    struct mwifiex_private *priv;
    int i, idx;
    struct netdev_queue *txq;
    struct mwifiex_debug_info *debug_info;

    if (adapter->drv_info_dump) {
        vfree(adapter->drv_info_dump);
        adapter->drv_info_size = 0;
    }

    dev_info(adapter->dev, "=== DRIVER INFO DUMP START===\n");

    adapter->drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX);

    if (!adapter->drv_info_dump)
        return;

    p = (char *)(adapter->drv_info_dump);
    p += sprintf(p, "driver_name = " "\"mwifiex\"\n");

    mwifiex_drv_get_driver_version(adapter, drv_version,
                                   sizeof(drv_version) - 1);
    p += sprintf(p, "driver_version = %s\n", drv_version);

    if (adapter->iface_type == MWIFIEX_USB) {
        cardp = (struct usb_card_rec *)adapter->card;
        p += sprintf(p, "tx_cmd_urb_pending = %d\n",
                     atomic_read(&cardp->tx_cmd_urb_pending));
        p += sprintf(p, "tx_data_urb_pending = %d\n",
                     atomic_read(&cardp->tx_data_urb_pending));
        p += sprintf(p, "rx_cmd_urb_pending = %d\n",
                     atomic_read(&cardp->rx_cmd_urb_pending));
        p += sprintf(p, "rx_data_urb_pending = %d\n",
                     atomic_read(&cardp->rx_data_urb_pending));
    }

    p += sprintf(p, "tx_pending = %d\n",
                 atomic_read(&adapter->tx_pending));
    p += sprintf(p, "rx_pending = %d\n",
                 atomic_read(&adapter->rx_pending));

    if (adapter->iface_type == MWIFIEX_SDIO) {
        sdio_card = (struct sdio_mmc_card *)adapter->card;
        p += sprintf(p, "\nmp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
                     sdio_card->mp_rd_bitmap, sdio_card->curr_rd_port);
        p += sprintf(p, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
                     sdio_card->mp_wr_bitmap, sdio_card->curr_wr_port);
    }

    for (i = 0; i < adapter->priv_num; i++) {
        if (!adapter->priv[i] || !adapter->priv[i]->netdev)
            continue;
        priv = adapter->priv[i];
        p += sprintf(p, "\n[interface  : \"%s\"]\n",
                     priv->netdev->name);
        p += sprintf(p, "wmm_tx_pending[0] = %d\n",
                     atomic_read(&priv->wmm_tx_pending[0]));
        p += sprintf(p, "wmm_tx_pending[1] = %d\n",
                     atomic_read(&priv->wmm_tx_pending[1]));
        p += sprintf(p, "wmm_tx_pending[2] = %d\n",
                     atomic_read(&priv->wmm_tx_pending[2]));
        p += sprintf(p, "wmm_tx_pending[3] = %d\n",
                     atomic_read(&priv->wmm_tx_pending[3]));
        p += sprintf(p, "media_state=\"%s\"\n", !priv->media_connected ?
                     "Disconnected" : "Connected");
        p += sprintf(p, "carrier %s\n", (netif_carrier_ok(priv->netdev)
                                         ? "on" : "off"));
        for (idx = 0; idx < priv->netdev->num_tx_queues; idx++) {
            txq = netdev_get_tx_queue(priv->netdev, idx);
            p += sprintf(p, "tx queue %d:%s  ", idx,
                         netif_tx_queue_stopped(txq) ?
                         "stopped" : "started");
        }
        p += sprintf(p, "\n%s: num_tx_timeout = %d\n",
                     priv->netdev->name, priv->num_tx_timeout);
    }

    if (adapter->iface_type == MWIFIEX_SDIO) {
        p += sprintf(p, "\n=== SDIO register DUMP===\n");
        if (adapter->if_ops.reg_dump)
            p += adapter->if_ops.reg_dump(adapter, p);
    }

    p += sprintf(p, "\n=== MORE DEBUG INFORMATION\n");
    debug_info = kzalloc(sizeof(*debug_info), GFP_KERNEL);
    if (debug_info) {
        for (i = 0; i < adapter->priv_num; i++) {
            if (!adapter->priv[i] || !adapter->priv[i]->netdev)
                continue;
            priv = adapter->priv[i];
            mwifiex_get_debug_info(priv, debug_info);
            p += mwifiex_debug_info_to_buffer(priv, p, debug_info);
            break;
        }
        kfree(debug_info);
    }

    adapter->drv_info_size = p - adapter->drv_info_dump;
    dev_info(adapter->dev, "=== DRIVER INFO DUMP END===\n");
}
Exemplo n.º 3
0
/*
 * This function gets firmware and initializes it.
 *
 * The main initialization steps followed are -
 *      - Download the correct firmware to card
 *      - Issue the init commands to firmware
 */
static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
{
	int ret;
	char fmt[64];
	struct mwifiex_private *priv;
	struct mwifiex_adapter *adapter = context;
	struct mwifiex_fw_image fw;
	struct semaphore *sem = adapter->card_sem;
	bool init_failed = false;
	struct wireless_dev *wdev;

	if (!firmware) {
		dev_err(adapter->dev,
			"Failed to get firmware %s\n", adapter->fw_name);
		goto err_dnld_fw;
	}

	memset(&fw, 0, sizeof(struct mwifiex_fw_image));
	adapter->firmware = firmware;
	fw.fw_buf = (u8 *) adapter->firmware->data;
	fw.fw_len = adapter->firmware->size;

	if (adapter->if_ops.dnld_fw)
		ret = adapter->if_ops.dnld_fw(adapter, &fw);
	else
		ret = mwifiex_dnld_fw(adapter, &fw);
	if (ret == -1)
		goto err_dnld_fw;

	dev_notice(adapter->dev, "WLAN FW is active\n");

	if (cal_data_cfg) {
		if ((request_firmware(&adapter->cal_data, cal_data_cfg,
				      adapter->dev)) < 0)
			dev_err(adapter->dev,
				"Cal data request_firmware() failed\n");
	}

	/* enable host interrupt after fw dnld is successful */
	if (adapter->if_ops.enable_int) {
		if (adapter->if_ops.enable_int(adapter))
			goto err_dnld_fw;
	}

	adapter->init_wait_q_woken = false;
	ret = mwifiex_init_fw(adapter);
	if (ret == -1) {
		goto err_init_fw;
	} else if (!ret) {
		adapter->hw_status = MWIFIEX_HW_STATUS_READY;
		goto done;
	}
	/* Wait for mwifiex_init to complete */
	wait_event_interruptible(adapter->init_wait_q,
				 adapter->init_wait_q_woken);
	if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
		goto err_init_fw;

	priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
	if (mwifiex_register_cfg80211(adapter)) {
		dev_err(adapter->dev, "cannot register with cfg80211\n");
		goto err_init_fw;
	}

	if (mwifiex_init_channel_scan_gap(adapter)) {
		dev_err(adapter->dev, "could not init channel stats table\n");
		goto err_init_fw;
	}

	if (driver_mode) {
		driver_mode &= MWIFIEX_DRIVER_MODE_BITMASK;
		driver_mode |= MWIFIEX_DRIVER_MODE_STA;
	}

	rtnl_lock();
	/* Create station interface by default */
	wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d",
					NL80211_IFTYPE_STATION, NULL, NULL);
	if (IS_ERR(wdev)) {
		dev_err(adapter->dev, "cannot create default STA interface\n");
		rtnl_unlock();
		goto err_add_intf;
	}

	if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) {
		wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d",
						NL80211_IFTYPE_AP, NULL, NULL);
		if (IS_ERR(wdev)) {
			dev_err(adapter->dev, "cannot create AP interface\n");
			rtnl_unlock();
			goto err_add_intf;
		}
	}

	if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) {
		wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d",
						NL80211_IFTYPE_P2P_CLIENT, NULL,
						NULL);
		if (IS_ERR(wdev)) {
			dev_err(adapter->dev,
				"cannot create p2p client interface\n");
			rtnl_unlock();
			goto err_add_intf;
		}
	}
	rtnl_unlock();

	mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
	dev_notice(adapter->dev, "driver_version = %s\n", fmt);
	goto done;

err_add_intf:
	wiphy_unregister(adapter->wiphy);
	wiphy_free(adapter->wiphy);
err_init_fw:
	if (adapter->if_ops.disable_int)
		adapter->if_ops.disable_int(adapter);
err_dnld_fw:
	pr_debug("info: %s: unregister device\n", __func__);
	if (adapter->if_ops.unregister_dev)
		adapter->if_ops.unregister_dev(adapter);

	if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) ||
	    (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) {
		pr_debug("info: %s: shutdown mwifiex\n", __func__);
		adapter->init_wait_q_woken = false;

		if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
			wait_event_interruptible(adapter->init_wait_q,
						 adapter->init_wait_q_woken);
	}
	adapter->surprise_removed = true;
	mwifiex_terminate_workqueue(adapter);
	init_failed = true;
done:
	if (adapter->cal_data) {
		release_firmware(adapter->cal_data);
		adapter->cal_data = NULL;
	}
	if (adapter->firmware) {
		release_firmware(adapter->firmware);
		adapter->firmware = NULL;
	}
	if (init_failed)
		mwifiex_free_adapter(adapter);
	up(sem);
	return;
}
Exemplo n.º 4
0
/*
 * Proc info file read handler.
 *
 * This function is called when the 'info' file is opened for reading.
 * It prints the following driver related information -
 *      - Driver name
 *      - Driver version
 *      - Driver extended version
 *      - Interface name
 *      - BSS mode
 *      - Media state (connected or disconnected)
 *      - MAC address
 *      - Total number of Tx bytes
 *      - Total number of Rx bytes
 *      - Total number of Tx packets
 *      - Total number of Rx packets
 *      - Total number of dropped Tx packets
 *      - Total number of dropped Rx packets
 *      - Total number of corrupted Tx packets
 *      - Total number of corrupted Rx packets
 *      - Carrier status (on or off)
 *      - Tx queue status (started or stopped)
 *
 * For STA mode drivers, it also prints the following extra -
 *      - ESSID
 *      - BSSID
 *      - Channel
 *      - Region code
 *      - Multicast count
 *      - Multicast addresses
 */
static ssize_t
mwifiex_info_read(struct file *file, char __user *ubuf,
		  size_t count, loff_t *ppos)
{
	struct mwifiex_private *priv =
		(struct mwifiex_private *) file->private_data;
	struct net_device *netdev = priv->netdev;
	struct netdev_hw_addr *ha;
	struct netdev_queue *txq;
	unsigned long page = get_zeroed_page(GFP_KERNEL);
	char *p = (char *) page, fmt[64];
	struct mwifiex_bss_info info;
	ssize_t ret;
	int i = 0;

	if (!p)
		return -ENOMEM;

	memset(&info, 0, sizeof(info));
	ret = mwifiex_get_bss_info(priv, &info);
	if (ret)
		goto free_and_exit;

	mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1);

	if (!priv->version_str[0])
		mwifiex_get_ver_ext(priv);

	p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
	p += sprintf(p, "driver_version = %s", fmt);
	p += sprintf(p, "\nverext = %s", priv->version_str);
	p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name);

	if (info.bss_mode >= ARRAY_SIZE(bss_modes))
		p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode);
	else
		p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);

	p += sprintf(p, "media_state=\"%s\"\n",
		     (!priv->media_connected ? "Disconnected" : "Connected"));
	p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);

	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
		p += sprintf(p, "multicast_count=\"%d\"\n",
			     netdev_mc_count(netdev));
		p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
		p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
		p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
		p += sprintf(p, "country_code = \"%s\"\n", info.country_code);

		netdev_for_each_mc_addr(ha, netdev)
			p += sprintf(p, "multicast_address[%d]=\"%pM\"\n",
					i++, ha->addr);
	}

	p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
	p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
	p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
	p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
	p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
	p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
	p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
	p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
	p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev))
					 ? "on" : "off"));
	p += sprintf(p, "tx queue");
	for (i = 0; i < netdev->num_tx_queues; i++) {
		txq = netdev_get_tx_queue(netdev, i);
		p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ?
			     "stopped" : "started");
	}
	p += sprintf(p, "\n");

	ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
				      (unsigned long) p - page);

free_and_exit:
	free_page(page);
	return ret;
}