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; }
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; }
/* * 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; }
/* 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); }