Exemple #1
0
int ieee80211_register_hw(struct ieee80211_hw *hw)
{
    struct ieee80211_local *local = hw_to_local(hw);
    int result, i;
    enum ieee80211_band band;
    int channels, max_bitrates;
    bool supp_ht;
    static const u32 cipher_suites[] = {
        /* keep WEP first, it may be removed below */
        WLAN_CIPHER_SUITE_WEP40,
        WLAN_CIPHER_SUITE_WEP104,
        WLAN_CIPHER_SUITE_TKIP,
        WLAN_CIPHER_SUITE_CCMP,

        /* keep last -- depends on hw flags! */
        WLAN_CIPHER_SUITE_AES_CMAC
    };

    if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns)
#ifdef CONFIG_PM
            && (!local->ops->suspend || !local->ops->resume)
#endif
       )
        return -EINVAL;

    if (hw->max_report_rates == 0)
        hw->max_report_rates = hw->max_rates;

    /*
     * generic code guarantees at least one band,
     * set this very early because much code assumes
     * that hw.conf.channel is assigned
     */
    channels = 0;
    max_bitrates = 0;
    supp_ht = false;
    for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
        struct ieee80211_supported_band *sband;

        sband = local->hw.wiphy->bands[band];
        if (!sband)
            continue;
        if (!local->oper_channel) {
            /* init channel we're on */
            local->hw.conf.channel =
                local->oper_channel = &sband->channels[0];
            local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
        }
        channels += sband->n_channels;

        if (max_bitrates < sband->n_bitrates)
            max_bitrates = sband->n_bitrates;
        supp_ht = supp_ht || sband->ht_cap.ht_supported;
    }

    local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
                                  sizeof(void *) * channels, GFP_KERNEL);
    if (!local->int_scan_req)
        return -ENOMEM;

    /* if low-level driver supports AP, we also support VLAN */
    if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) {
        hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);
        hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN);
    }

    /* mac80211 always supports monitor */
    hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
    hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);

    /*
     * mac80211 doesn't support more than 1 channel, and also not more
     * than one IBSS interface
     */
    for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
        const struct ieee80211_iface_combination *c;
        int j;

        c = &hw->wiphy->iface_combinations[i];

        if (c->num_different_channels > 1)
            return -EINVAL;

        for (j = 0; j < c->n_limits; j++)
            if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
                    c->limits[j].max > 1)
                return -EINVAL;
    }

#ifndef CONFIG_MAC80211_MESH
    /* mesh depends on Kconfig, but drivers should set it if they want */
    local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
#endif

    /* if the underlying driver supports mesh, mac80211 will (at least)
     * provide routing of mesh authentication frames to userspace */
    if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT))
        local->hw.wiphy->flags |= WIPHY_FLAG_MESH_AUTH;

    /* mac80211 supports control port protocol changing */
    local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;

    if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
        local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
    else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
        local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;

    WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
         && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
         "U-APSD not supported with HW_PS_NULLFUNC_STACK\n");

    /*
     * Calculate scan IE length -- we need this to alloc
     * memory and to subtract from the driver limit. It
     * includes the DS Params, (extended) supported rates, and HT
     * information -- SSID is the driver's responsibility.
     */
    local->scan_ies_len = 4 + max_bitrates /* (ext) supp rates */ +
                          3 /* DS Params */;
    if (supp_ht)
        local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);

    if (!local->ops->hw_scan) {
        /* For hw_scan, driver needs to set these up. */
        local->hw.wiphy->max_scan_ssids = 4;
        local->hw.wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
    }

    /*
     * If the driver supports any scan IEs, then assume the
     * limit includes the IEs mac80211 will add, otherwise
     * leave it at zero and let the driver sort it out; we
     * still pass our IEs to the driver but userspace will
     * not be allowed to in that case.
     */
    if (local->hw.wiphy->max_scan_ie_len)
        local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;

    /* Set up cipher suites unless driver already did */
    if (!local->hw.wiphy->cipher_suites) {
        local->hw.wiphy->cipher_suites = cipher_suites;
        local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
        if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
            local->hw.wiphy->n_cipher_suites--;
    }
    if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) {
        if (local->hw.wiphy->cipher_suites == cipher_suites) {
            local->hw.wiphy->cipher_suites += 2;
            local->hw.wiphy->n_cipher_suites -= 2;
        } else {
            u32 *suites;
            int r, w = 0;

            /* Filter out WEP */

            suites = kmemdup(
                         local->hw.wiphy->cipher_suites,
                         sizeof(u32) * local->hw.wiphy->n_cipher_suites,
                         GFP_KERNEL);
            if (!suites)
                return -ENOMEM;
            for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
                u32 suite = local->hw.wiphy->cipher_suites[r];
                if (suite == WLAN_CIPHER_SUITE_WEP40 ||
                        suite == WLAN_CIPHER_SUITE_WEP104)
                    continue;
                suites[w++] = suite;
            }
            local->hw.wiphy->cipher_suites = suites;
            local->hw.wiphy->n_cipher_suites = w;
            local->wiphy_ciphers_allocated = true;
        }
    }

    if (!local->ops->remain_on_channel)
        local->hw.wiphy->max_remain_on_channel_duration = 5000;

    if (local->ops->sched_scan_start)
        local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;

    result = wiphy_register(local->hw.wiphy);
    if (result < 0)
        goto fail_wiphy_register;

    /*
     * We use the number of queues for feature tests (QoS, HT) internally
     * so restrict them appropriately.
     */
    if (hw->queues > IEEE80211_MAX_QUEUES)
        hw->queues = IEEE80211_MAX_QUEUES;

    local->workqueue =
        alloc_ordered_workqueue(wiphy_name(local->hw.wiphy), 0);
    if (!local->workqueue) {
        result = -ENOMEM;
        goto fail_workqueue;
    }

    /*
     * The hardware needs headroom for sending the frame,
     * and we need some headroom for passing the frame to monitor
     * interfaces, but never both at the same time.
     */
#ifndef __CHECKER__
    BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM !=
                 sizeof(struct ieee80211_tx_status_rtap_hdr));
#endif
    local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
                               sizeof(struct ieee80211_tx_status_rtap_hdr));

    debugfs_hw_add(local);

    /*
     * if the driver doesn't specify a max listen interval we
     * use 5 which should be a safe default
     */
    if (local->hw.max_listen_interval == 0)
        local->hw.max_listen_interval = 5;

    local->hw.conf.listen_interval = local->hw.max_listen_interval;

    local->dynamic_ps_forced_timeout = -1;

    result = ieee80211_wep_init(local);
    if (result < 0)
        wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
                    result);

    ieee80211_led_init(local);

    rtnl_lock();

    result = ieee80211_init_rate_ctrl_alg(local,
                                          hw->rate_control_algorithm);
    if (result < 0) {
        wiphy_debug(local->hw.wiphy,
                    "Failed to initialize rate control algorithm\n");
        goto fail_rate;
    }

    /* add one default STA interface if supported */
    if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
        result = ieee80211_if_add(local, "wlan%d", NULL,
                                  NL80211_IFTYPE_STATION, NULL);
        if (result)
            wiphy_warn(local->hw.wiphy,
                       "Failed to add default virtual iface\n");
    }

    rtnl_unlock();

    local->network_latency_notifier.notifier_call =
        ieee80211_max_network_latency;
    result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
                                 &local->network_latency_notifier);
    if (result) {
        rtnl_lock();
        goto fail_pm_qos;
    }

#ifdef CONFIG_INET
    local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
    result = register_inetaddr_notifier(&local->ifa_notifier);
    if (result)
        goto fail_ifa;
#endif

    netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll,
                   local->hw.napi_weight);

    return 0;

#ifdef CONFIG_INET
fail_ifa:
    pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
                           &local->network_latency_notifier);
    rtnl_lock();
#endif
fail_pm_qos:
    ieee80211_led_exit(local);
    ieee80211_remove_interfaces(local);
fail_rate:
    rtnl_unlock();
    ieee80211_wep_free(local);
    sta_info_stop(local);
    destroy_workqueue(local->workqueue);
fail_workqueue:
    wiphy_unregister(local->hw.wiphy);
fail_wiphy_register:
    if (local->wiphy_ciphers_allocated)
        kfree(local->hw.wiphy->cipher_suites);
    kfree(local->int_scan_req);
    return result;
}
/*
========================================================================
Routine Description:
	Allocate a wireless device.

Arguments:
	pAd				- WLAN control block pointer
	pDev			- Generic device interface

Return Value:
	wireless device

Note:
========================================================================
*/
static struct wireless_dev *CFG80211_WdevAlloc(
	IN CFG80211_CB					*pCfg80211_CB,
	IN CFG80211_BAND				*pBandInfo,
	IN VOID 						*pAd,
	IN struct device				*pDev)
{
	struct wireless_dev *pWdev;
	ULONG *pPriv;


	/*
	 * We're trying to have the following memory layout:
	 *
	 * +------------------------+
	 * | struct wiphy			|
	 * +------------------------+
	 * | pAd pointer			|
	 * +------------------------+
	 */

	pWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
	if (pWdev == NULL)
	{
		DBGPRINT(RT_DEBUG_ERROR, ("80211> Wireless device allocation fail!\n"));
		return NULL;
	} /* End of if */

	pWdev->wiphy = wiphy_new(&CFG80211_Ops, sizeof(ULONG *));
	if (pWdev->wiphy == NULL)
	{
		DBGPRINT(RT_DEBUG_ERROR, ("80211> Wiphy device allocation fail!\n"));
		goto LabelErrWiphyNew;
	} /* End of if */

	/* keep pAd pointer */
	pPriv = (ULONG *)(wiphy_priv(pWdev->wiphy));
	*pPriv = (ULONG)pAd;

	set_wiphy_dev(pWdev->wiphy, pDev);

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
	pWdev->wiphy->max_scan_ssids = pBandInfo->MaxBssTable;
#endif /* KERNEL_VERSION */


#ifdef CONFIG_STA_SUPPORT
	pWdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
							       BIT(NL80211_IFTYPE_ADHOC) |
							       BIT(NL80211_IFTYPE_MONITOR);
#endif /* CONFIG_STA_SUPPORT */
	pWdev->wiphy->reg_notifier = CFG80211_RegNotifier;

	/* init channel information */
	CFG80211_SupBandInit(pCfg80211_CB, pBandInfo, pWdev->wiphy, NULL, NULL);

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
	/* CFG80211_SIGNAL_TYPE_MBM: signal strength in mBm (100*dBm) */
	pWdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
#endif /* KERNEL_VERSION */

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32))
	pWdev->wiphy->cipher_suites = CipherSuites;
	pWdev->wiphy->n_cipher_suites = ARRAY_SIZE(CipherSuites);
#endif /* LINUX_VERSION_CODE */

	if (wiphy_register(pWdev->wiphy) < 0)
	{
		DBGPRINT(RT_DEBUG_ERROR, ("80211> Register wiphy device fail!\n"));
		goto LabelErrReg;
	} /* End of if */

	return pWdev;

 LabelErrReg:
	wiphy_free(pWdev->wiphy);

 LabelErrWiphyNew:
	os_free_mem(NULL, pWdev);

	return NULL;
} /* End of CFG80211_WdevAlloc */
/*
 * This function registers the device with CFG802.11 subsystem.
 *
 * The function creates the wireless device/wiphy, populates it with
 * default parameters and handler function pointers, and finally
 * registers the device.
 */
int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac,
			      struct mwifiex_private *priv)
{
	int ret;
	void *wdev_priv;
	struct wireless_dev *wdev;

	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
	if (!wdev) {
		dev_err(priv->adapter->dev, "%s: allocating wireless device\n",
						__func__);
		return -ENOMEM;
	}
	wdev->wiphy =
		wiphy_new(&mwifiex_cfg80211_ops,
			  sizeof(struct mwifiex_private *));
	if (!wdev->wiphy) {
		kfree(wdev);
		return -ENOMEM;
	}
	wdev->iftype = NL80211_IFTYPE_STATION;
	wdev->wiphy->max_scan_ssids = 10;
	wdev->wiphy->interface_modes =
		BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);

	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
	mwifiex_setup_ht_caps(
		&wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);

	if (priv->adapter->config_bands & BAND_A) {
		wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
		mwifiex_setup_ht_caps(
			&wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);
	} else {
		wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
	}

	/* Initialize cipher suits */
	wdev->wiphy->cipher_suites = mwifiex_cipher_suites;
	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);

	memcpy(wdev->wiphy->perm_addr, mac, 6);
	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;

	/* We are using custom domains */
	wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;

	wdev->wiphy->reg_notifier = mwifiex_reg_notifier;

	/* Set struct mwifiex_private pointer in wiphy_priv */
	wdev_priv = wiphy_priv(wdev->wiphy);

	*(unsigned long *) wdev_priv = (unsigned long) priv;

	ret = wiphy_register(wdev->wiphy);
	if (ret < 0) {
		dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n",
						__func__);
		wiphy_free(wdev->wiphy);
		kfree(wdev);
		return ret;
	} else {
		dev_dbg(priv->adapter->dev,
				"info: successfully registered wiphy device\n");
	}

	dev_net_set(dev, wiphy_net(wdev->wiphy));
	dev->ieee80211_ptr = wdev;
	memcpy(dev->dev_addr, wdev->wiphy->perm_addr, 6);
	memcpy(dev->perm_addr, wdev->wiphy->perm_addr, 6);
	SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
	priv->wdev = wdev;

	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
	dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
	dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;

	return ret;
}
Exemple #4
0
int ieee80211_register_hw(struct ieee80211_hw *hw)
{
	struct ieee80211_local *local = hw_to_local(hw);
	int result;
	enum ieee80211_band band;
	int channels, i, j, max_bitrates;
	bool supp_ht;
	static const u32 cipher_suites[] = {
		WLAN_CIPHER_SUITE_WEP40,
		WLAN_CIPHER_SUITE_WEP104,
		WLAN_CIPHER_SUITE_TKIP,
		WLAN_CIPHER_SUITE_CCMP,

		/* keep last -- depends on hw flags! */
		WLAN_CIPHER_SUITE_AES_CMAC
	};

	/*
	 * generic code guarantees at least one band,
	 * set this very early because much code assumes
	 * that hw.conf.channel is assigned
	 */
	channels = 0;
	max_bitrates = 0;
	supp_ht = false;
	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
		struct ieee80211_supported_band *sband;

		sband = local->hw.wiphy->bands[band];
		if (!sband)
			continue;
		if (!local->oper_channel) {
			/* init channel we're on */
			local->hw.conf.channel =
			local->oper_channel = &sband->channels[0];
			local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
		}
		channels += sband->n_channels;

		if (max_bitrates < sband->n_bitrates)
			max_bitrates = sband->n_bitrates;
		supp_ht = supp_ht || sband->ht_cap.ht_supported;
	}

	local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
				      sizeof(void *) * channels, GFP_KERNEL);
	if (!local->int_scan_req)
		return -ENOMEM;

	/* if low-level driver supports AP, we also support VLAN */
	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP))
		local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN);

	/* mac80211 always supports monitor */
	local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);

	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
	else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;

	/*
	 * Calculate scan IE length -- we need this to alloc
	 * memory and to subtract from the driver limit. It
	 * includes the (extended) supported rates and HT
	 * information -- SSID is the driver's responsibility.
	 */
	local->scan_ies_len = 4 + max_bitrates; /* (ext) supp rates */
	if (supp_ht)
		local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);

	if (!local->ops->hw_scan) {
		/* For hw_scan, driver needs to set these up. */
		local->hw.wiphy->max_scan_ssids = 4;
		local->hw.wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
	}

	/*
	 * If the driver supports any scan IEs, then assume the
	 * limit includes the IEs mac80211 will add, otherwise
	 * leave it at zero and let the driver sort it out; we
	 * still pass our IEs to the driver but userspace will
	 * not be allowed to in that case.
	 */
	if (local->hw.wiphy->max_scan_ie_len)
		local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;

	local->hw.wiphy->cipher_suites = cipher_suites;
	local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
	if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
		local->hw.wiphy->n_cipher_suites--;

	result = wiphy_register(local->hw.wiphy);
	if (result < 0)
		goto fail_wiphy_register;

	/*
	 * We use the number of queues for feature tests (QoS, HT) internally
	 * so restrict them appropriately.
	 */
	if (hw->queues > IEEE80211_MAX_QUEUES)
		hw->queues = IEEE80211_MAX_QUEUES;

	local->workqueue =
		create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
	if (!local->workqueue) {
		result = -ENOMEM;
		goto fail_workqueue;
	}

	/*
	 * The hardware needs headroom for sending the frame,
	 * and we need some headroom for passing the frame to monitor
	 * interfaces, but never both at the same time.
	 */
	BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM !=
			sizeof(struct ieee80211_tx_status_rtap_hdr));
	local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
				   sizeof(struct ieee80211_tx_status_rtap_hdr));

	debugfs_hw_add(local);

	if (local->hw.max_listen_interval == 0)
		local->hw.max_listen_interval = 1;

	local->hw.conf.listen_interval = local->hw.max_listen_interval;

	result = sta_info_start(local);
	if (result < 0)
		goto fail_sta_info;

	result = ieee80211_wep_init(local);
	if (result < 0) {
		printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
		       wiphy_name(local->hw.wiphy), result);
		goto fail_wep;
	}

	rtnl_lock();

	result = ieee80211_init_rate_ctrl_alg(local,
					      hw->rate_control_algorithm);
	if (result < 0) {
		printk(KERN_DEBUG "%s: Failed to initialize rate control "
		       "algorithm\n", wiphy_name(local->hw.wiphy));
		goto fail_rate;
	}

	/* add one default STA interface if supported */
	if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
		result = ieee80211_if_add(local, "wlan%d", NULL,
					  NL80211_IFTYPE_STATION, NULL);
		if (result)
			printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
			       wiphy_name(local->hw.wiphy));
	}

	rtnl_unlock();

	ieee80211_led_init(local);

	/* alloc internal scan request */
	i = 0;
	local->int_scan_req->ssids = &local->scan_ssid;
	local->int_scan_req->n_ssids = 1;
	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
		if (!hw->wiphy->bands[band])
			continue;
		for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) {
			local->int_scan_req->channels[i] =
				&hw->wiphy->bands[band]->channels[j];
			i++;
		}
	}
	local->int_scan_req->n_channels = i;

	local->network_latency_notifier.notifier_call =
		ieee80211_max_network_latency;
	result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
				     &local->network_latency_notifier);

	if (result) {
		rtnl_lock();
		goto fail_pm_qos;
	}

	return 0;

 fail_pm_qos:
	ieee80211_led_exit(local);
	ieee80211_remove_interfaces(local);
 fail_rate:
	rtnl_unlock();
	ieee80211_wep_free(local);
 fail_wep:
	sta_info_stop(local);
 fail_sta_info:
	destroy_workqueue(local->workqueue);
 fail_workqueue:
	wiphy_unregister(local->hw.wiphy);
 fail_wiphy_register:
	kfree(local->int_scan_req);
	return result;
}
Exemple #5
0
/*
 * This function registers the device with CFG802.11 subsystem.
 *
 * The function creates the wireless device/wiphy, populates it with
 * default parameters and handler function pointers, and finally
 * registers the device.
 */
int mwifiex_register_cfg80211(struct mwifiex_private *priv)
{
	int ret;
	void *wdev_priv;
	struct wireless_dev *wdev;
	struct ieee80211_sta_ht_cap *ht_info;

	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
	if (!wdev) {
		dev_err(priv->adapter->dev, "%s: allocating wireless device\n",
			__func__);
		return -ENOMEM;
	}
	wdev->wiphy =
		wiphy_new(&mwifiex_cfg80211_ops,
			  sizeof(struct mwifiex_private *));
	if (!wdev->wiphy) {
		kfree(wdev);
		return -ENOMEM;
	}
	wdev->iftype = NL80211_IFTYPE_STATION;
	wdev->wiphy->max_scan_ssids = 10;
	wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
				       BIT(NL80211_IFTYPE_ADHOC);

	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
	ht_info = &wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap;
	mwifiex_setup_ht_caps(ht_info, priv);

	if (priv->adapter->config_bands & BAND_A) {
		wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
		ht_info = &wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap;
		mwifiex_setup_ht_caps(ht_info, priv);
	} else {
		wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
	}

	/* Initialize cipher suits */
	wdev->wiphy->cipher_suites = mwifiex_cipher_suites;
	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);

	memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;

	/* Reserve space for bss band information */
	wdev->wiphy->bss_priv_size = sizeof(u8);

	wdev->wiphy->reg_notifier = mwifiex_reg_notifier;

	/* Set struct mwifiex_private pointer in wiphy_priv */
	wdev_priv = wiphy_priv(wdev->wiphy);

	*(unsigned long *) wdev_priv = (unsigned long) priv;

	set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev);

	ret = wiphy_register(wdev->wiphy);
	if (ret < 0) {
		dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n",
			__func__);
		wiphy_free(wdev->wiphy);
		kfree(wdev);
		return ret;
	} else {
		dev_dbg(priv->adapter->dev,
			"info: successfully registered wiphy device\n");
	}

	priv->wdev = wdev;

	return ret;
}
Exemple #6
0
/* Called after firmware is initialised */
int orinoco_wiphy_register(struct wiphy *wiphy)
{
	struct orinoco_private *priv = wiphy_priv(wiphy);
	int i, channels = 0;

	if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
		wiphy->max_scan_ssids = 1;
	else
		wiphy->max_scan_ssids = 0;

	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);

	/* TODO: should we set if we only have demo ad-hoc?
	 *       (priv->has_port3)
	 */
	if (priv->has_ibss)
		wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);

	if (!priv->broken_monitor || force_monitor)
		wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);

	priv->band.bitrates = orinoco_rates;
	priv->band.n_bitrates = ARRAY_SIZE(orinoco_rates);

	/* Only support channels allowed by the card EEPROM */
	for (i = 0; i < NUM_CHANNELS; i++) {
		if (priv->channel_mask & (1 << i)) {
			priv->channels[i].center_freq =
				ieee80211_dsss_chan_to_freq(i+1);
			channels++;
		}
	}
	priv->band.channels = priv->channels;
	priv->band.n_channels = channels;

	wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;

	i = 0;
	if (priv->has_wep) {
		priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40;
		i++;

		if (priv->has_big_wep) {
			priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104;
			i++;
		}
	}
	if (priv->has_wpa) {
		priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP;
		i++;
	}
	wiphy->cipher_suites = priv->cipher_suites;
	wiphy->n_cipher_suites = i;

	wiphy->rts_threshold = priv->rts_thresh;
	if (!priv->has_mwo)
		wiphy->frag_threshold = priv->frag_thresh + 1;
	wiphy->retry_short = priv->short_retry_limit;
	wiphy->retry_long = priv->long_retry_limit;

	return wiphy_register(wiphy);
}