diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-24 11:54:29 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-24 11:54:29 -0700 |
commit | 28f3d717618156c0dcd2f497d791b578a7931d87 (patch) | |
tree | 37b11581b51929b5473541e53bd242b3e1a9f666 /drivers/net/wireless/mwifiex/cfg80211.c | |
parent | 654443e20dfc0617231f28a07c96a979ee1a0239 (diff) | |
parent | 1ca7ee30630e1022dbcf1b51be20580815ffab73 (diff) | |
download | blackbird-op-linux-28f3d717618156c0dcd2f497d791b578a7931d87.tar.gz blackbird-op-linux-28f3d717618156c0dcd2f497d791b578a7931d87.zip |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull more networking updates from David Miller:
"Ok, everything from here on out will be bug fixes."
1) One final sync of wireless and bluetooth stuff from John Linville.
These changes have all been in his tree for more than a week, and
therefore have had the necessary -next exposure. John was just away
on a trip and didn't have a change to send the pull request until a
day or two ago.
2) Put back some defines in user exposed header file areas that were
removed during the tokenring purge. From Stephen Hemminger and Paul
Gortmaker.
3) A bug fix for UDP hash table allocation got lost in the pile due to
one of those "you got it.. no I've got it.." situations. :-)
From Tim Bird.
4) SKB coalescing in TCP needs to have stricter checks, otherwise we'll
try to coalesce overlapping frags and crash. Fix from Eric Dumazet.
5) RCU routing table lookups can race with free_fib_info(), causing
crashes when we deref the device pointers in the route. Fix by
releasing the net device in the RCU callback. From Yanmin Zhang.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (293 commits)
tcp: take care of overlaps in tcp_try_coalesce()
ipv4: fix the rcu race between free_fib_info and ip_route_output_slow
mm: add a low limit to alloc_large_system_hash
ipx: restore token ring define to include/linux/ipx.h
if: restore token ring ARP type to header
xen: do not disable netfront in dom0
phy/micrel: Fix ID of KSZ9021
mISDN: Add X-Tensions USB ISDN TA XC-525
gianfar:don't add FCB length to hard_header_len
Bluetooth: Report proper error number in disconnection
Bluetooth: Create flags for bt_sk()
Bluetooth: report the right security level in getsockopt
Bluetooth: Lock the L2CAP channel when sending
Bluetooth: Restore locking semantics when looking up L2CAP channels
Bluetooth: Fix a redundant and problematic incoming MTU check
Bluetooth: Add support for Foxconn/Hon Hai AR5BBU22 0489:E03C
Bluetooth: Fix EIR data generation for mgmt_device_found
Bluetooth: Fix Inquiry with RSSI event mask
Bluetooth: improve readability of l2cap_seq_list code
Bluetooth: Fix skb length calculation
...
Diffstat (limited to 'drivers/net/wireless/mwifiex/cfg80211.c')
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 498 |
1 files changed, 351 insertions, 147 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index c78ea873a63a..87671446e24b 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -20,6 +20,23 @@ #include "cfg80211.h" #include "main.h" +static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = { + { + .max = 1, .types = BIT(NL80211_IFTYPE_STATION), + }, + { + .max = 1, .types = BIT(NL80211_IFTYPE_AP), + }, +}; + +static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = { + .limits = mwifiex_ap_sta_limits, + .num_different_channels = 1, + .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits), + .max_interfaces = MWIFIEX_MAX_BSS_NUM, + .beacon_int_infra_match = true, +}; + /* * This function maps the nl802.11 channel type into driver channel type. * @@ -67,7 +84,7 @@ mwifiex_is_alg_wep(u32 cipher) /* * This function retrieves the private structure from kernel wiphy structure. */ -static void *mwifiex_cfg80211_get_priv(struct wiphy *wiphy) +static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy) { return (void *) (*(unsigned long *) wiphy_priv(wiphy)); } @@ -80,8 +97,10 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); + const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + const u8 *peer_mac = pairwise ? mac_addr : bc_mac; - if (mwifiex_set_encode(priv, NULL, 0, key_index, 1)) { + if (mwifiex_set_encode(priv, NULL, 0, key_index, peer_mac, 1)) { wiphy_err(wiphy, "deleting the crypto keys\n"); return -EFAULT; } @@ -98,7 +117,8 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, int mbm) { - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); + struct mwifiex_private *priv; struct mwifiex_power_cfg power_cfg; int dbm = MBM_TO_DBM(mbm); @@ -109,6 +129,8 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, power_cfg.is_power_auto = 1; } + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + return mwifiex_set_tx_power(priv, &power_cfg); } @@ -148,7 +170,7 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, if (!priv->sec_info.wep_enabled) return 0; - if (mwifiex_set_encode(priv, NULL, 0, key_index, 0)) { + if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) { wiphy_err(wiphy, "set default Tx key index\n"); return -EFAULT; } @@ -165,9 +187,11 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, struct key_params *params) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); + const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + const u8 *peer_mac = pairwise ? mac_addr : bc_mac; if (mwifiex_set_encode(priv, params->key, params->key_len, - key_index, 0)) { + key_index, peer_mac, 0)) { wiphy_err(wiphy, "crypto keys added\n"); return -EFAULT; } @@ -192,13 +216,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) enum ieee80211_band band; struct ieee80211_supported_band *sband; struct ieee80211_channel *ch; - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); + struct mwifiex_private *priv; struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg; /* Set country code */ - domain_info->country_code[0] = priv->country_code[0]; - domain_info->country_code[1] = priv->country_code[1]; + domain_info->country_code[0] = adapter->country_code[0]; + domain_info->country_code[1] = adapter->country_code[1]; domain_info->country_code[2] = ' '; band = mwifiex_band_to_radio_type(adapter->config_bands); @@ -250,6 +274,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) domain_info->no_of_triplet = no_of_triplet; + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, HostCmd_ACT_GEN_SET, 0, NULL)) { wiphy_err(wiphy, "11D: setting domain info in FW\n"); @@ -272,12 +298,12 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) static int mwifiex_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) { - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for domain" - " %c%c\n", request->alpha2[0], request->alpha2[1]); + wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n", + request->alpha2[0], request->alpha2[1]); - memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2)); + memcpy(adapter->country_code, request->alpha2, sizeof(request->alpha2)); switch (request->initiator) { case NL80211_REGDOM_SET_BY_DRIVER: @@ -361,33 +387,10 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, if (mwifiex_bss_set_channel(priv, &cfp)) return -EFAULT; - return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); -} - -/* - * CFG802.11 operation handler to set channel. - * - * This function can only be used when station is not connected. - */ -static int -mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) -{ - struct mwifiex_private *priv; - - if (dev) - priv = mwifiex_netdev_get_priv(dev); + if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) + return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); else - priv = mwifiex_cfg80211_get_priv(wiphy); - - if (priv->media_connected) { - wiphy_err(wiphy, "This setting is valid only when station " - "is not connected\n"); - return -EINVAL; - } - - return mwifiex_set_rf_channel(priv, chan, channel_type); + return mwifiex_uap_set_channel(priv, cfp.channel); } /* @@ -399,18 +402,13 @@ mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, static int mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) { - int ret; - if (frag_thr < MWIFIEX_FRAG_MIN_VALUE || frag_thr > MWIFIEX_FRAG_MAX_VALUE) - return -EINVAL; - - /* Send request to firmware */ - ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, FRAG_THRESH_I, - &frag_thr); + frag_thr = MWIFIEX_FRAG_MAX_VALUE; - return ret; + return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_SET, FRAG_THRESH_I, + &frag_thr); } /* @@ -439,19 +437,85 @@ mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr) static int mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) { - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - int ret = 0; + struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); + struct mwifiex_private *priv; + struct mwifiex_uap_bss_param *bss_cfg; + int ret, bss_started, i; + + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + + switch (priv->bss_role) { + case MWIFIEX_BSS_ROLE_UAP: + bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), + GFP_KERNEL); + if (!bss_cfg) + return -ENOMEM; + + mwifiex_set_sys_config_invalid_data(bss_cfg); + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) + bss_cfg->rts_threshold = wiphy->rts_threshold; + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) + bss_cfg->frag_threshold = wiphy->frag_threshold; + if (changed & WIPHY_PARAM_RETRY_LONG) + bss_cfg->retry_limit = wiphy->retry_long; + + bss_started = priv->bss_started; + + ret = mwifiex_send_cmd_sync(priv, + HostCmd_CMD_UAP_BSS_STOP, + HostCmd_ACT_GEN_SET, 0, + NULL); + if (ret) { + wiphy_err(wiphy, "Failed to stop the BSS\n"); + kfree(bss_cfg); + return ret; + } - if (changed & WIPHY_PARAM_RTS_THRESHOLD) { - ret = mwifiex_set_rts(priv, wiphy->rts_threshold); - if (ret) - return ret; - } + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_UAP_SYS_CONFIG, + HostCmd_ACT_GEN_SET, + UAP_BSS_PARAMS_I, bss_cfg); - if (changed & WIPHY_PARAM_FRAG_THRESHOLD) - ret = mwifiex_set_frag(priv, wiphy->frag_threshold); + kfree(bss_cfg); - return ret; + if (ret) { + wiphy_err(wiphy, "Failed to set bss config\n"); + return ret; + } + + if (!bss_started) + break; + + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_UAP_BSS_START, + HostCmd_ACT_GEN_SET, 0, + NULL); + if (ret) { + wiphy_err(wiphy, "Failed to start BSS\n"); + return ret; + } + + break; + case MWIFIEX_BSS_ROLE_STA: + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + ret = mwifiex_set_rts(priv, + wiphy->rts_threshold); + if (ret) + return ret; + } + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { + ret = mwifiex_set_frag(priv, + wiphy->frag_threshold); + if (ret) + return ret; + } + break; + } + } + + return 0; } /* @@ -466,31 +530,59 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, int ret; struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - if (priv->bss_mode == type) { - wiphy_warn(wiphy, "already set to required type\n"); - return 0; - } - - priv->bss_mode = type; - - switch (type) { + switch (dev->ieee80211_ptr->iftype) { case NL80211_IFTYPE_ADHOC: - dev->ieee80211_ptr->iftype = NL80211_IFTYPE_ADHOC; - wiphy_dbg(wiphy, "info: setting interface type to adhoc\n"); + switch (type) { + case NL80211_IFTYPE_STATION: + break; + case NL80211_IFTYPE_UNSPECIFIED: + wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name); + case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */ + return 0; + case NL80211_IFTYPE_AP: + default: + wiphy_err(wiphy, "%s: changing to %d not supported\n", + dev->name, type); + return -EOPNOTSUPP; + } break; case NL80211_IFTYPE_STATION: - dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; - wiphy_dbg(wiphy, "info: setting interface type to managed\n"); + switch (type) { + case NL80211_IFTYPE_ADHOC: + break; + case NL80211_IFTYPE_UNSPECIFIED: + wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); + case NL80211_IFTYPE_STATION: /* This shouldn't happen */ + return 0; + case NL80211_IFTYPE_AP: + default: + wiphy_err(wiphy, "%s: changing to %d not supported\n", + dev->name, type); + return -EOPNOTSUPP; + } + break; + case NL80211_IFTYPE_AP: + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name); + case NL80211_IFTYPE_AP: /* This shouldn't happen */ + return 0; + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: + default: + wiphy_err(wiphy, "%s: changing to %d not supported\n", + dev->name, type); + return -EOPNOTSUPP; + } break; - case NL80211_IFTYPE_UNSPECIFIED: - dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; - wiphy_dbg(wiphy, "info: setting interface type to auto\n"); - return 0; default: - wiphy_err(wiphy, "unknown interface type: %d\n", type); - return -EINVAL; + wiphy_err(wiphy, "%s: unknown iftype: %d\n", + dev->name, dev->ieee80211_ptr->iftype); + return -EOPNOTSUPP; } + dev->ieee80211_ptr->iftype = type; + priv->bss_mode = type; mwifiex_deauthenticate(priv, NULL); priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; @@ -804,6 +896,90 @@ static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, return 0; } +/* cfg80211 operation handler for stop ap. + * Function stops BSS running at uAP interface. + */ +static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + if (mwifiex_del_mgmt_ies(priv)) + wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); + + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, + HostCmd_ACT_GEN_SET, 0, NULL)) { + wiphy_err(wiphy, "Failed to stop the BSS\n"); + return -1; + } + + return 0; +} + +/* cfg80211 operation handler for start_ap. + * Function sets beacon period, DTIM period, SSID and security into + * AP config structure. + * AP is configured with these settings and BSS is started. + */ +static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_ap_settings *params) +{ + struct mwifiex_uap_bss_param *bss_cfg; + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) + return -1; + if (mwifiex_set_mgmt_ies(priv, params)) + return -1; + + bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); + if (!bss_cfg) + return -ENOMEM; + + mwifiex_set_sys_config_invalid_data(bss_cfg); + + if (params->beacon_interval) + bss_cfg->beacon_period = params->beacon_interval; + if (params->dtim_period) + bss_cfg->dtim_period = params->dtim_period; + + if (params->ssid && params->ssid_len) { + memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len); + bss_cfg->ssid.ssid_len = params->ssid_len; + } + + if (mwifiex_set_secure_params(priv, bss_cfg, params)) { + kfree(bss_cfg); + wiphy_err(wiphy, "Failed to parse secuirty parameters!\n"); + return -1; + } + + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, + HostCmd_ACT_GEN_SET, 0, NULL)) { + wiphy_err(wiphy, "Failed to stop the BSS\n"); + kfree(bss_cfg); + return -1; + } + + if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, + HostCmd_ACT_GEN_SET, + UAP_BSS_PARAMS_I, bss_cfg)) { + wiphy_err(wiphy, "Failed to set the SSID\n"); + kfree(bss_cfg); + return -1; + } + + kfree(bss_cfg); + + if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_BSS_START, + HostCmd_ACT_GEN_SET, 0, NULL)) { + wiphy_err(wiphy, "Failed to start the BSS\n"); + return -1; + } + + return 0; +} + /* * CFG802.11 operation handler for disconnection request. * @@ -923,7 +1099,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, priv->wep_key_curr_index = 0; priv->sec_info.encryption_mode = 0; priv->sec_info.is_authtype_auto = 0; - ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); + ret = mwifiex_set_encode(priv, NULL, 0, 0, NULL, 1); if (mode == NL80211_IFTYPE_ADHOC) { /* "privacy" is set only for ad-hoc mode */ @@ -971,7 +1147,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, " with key len %d\n", sme->key_len); priv->wep_key_curr_index = sme->key_idx; ret = mwifiex_set_encode(priv, sme->key, sme->key_len, - sme->key_idx, 0); + sme->key_idx, NULL, 0); } } done: @@ -1050,6 +1226,11 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, goto done; } + if (priv->bss_mode == NL80211_IFTYPE_AP) { + wiphy_err(wiphy, "skip association request for AP interface\n"); + goto done; + } + wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", (char *) sme->ssid, sme->bssid); @@ -1283,15 +1464,12 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, u32 *flags, struct vif_params *params) { - struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); - struct mwifiex_adapter *adapter; + struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); + struct mwifiex_private *priv; struct net_device *dev; void *mdev_priv; + struct wireless_dev *wdev; - if (!priv) - return NULL; - - adapter = priv->adapter; if (!adapter) return NULL; @@ -1299,12 +1477,21 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: + priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; if (priv->bss_mode) { - wiphy_err(wiphy, "cannot create multiple" - " station/adhoc interfaces\n"); + wiphy_err(wiphy, + "cannot create multiple sta/adhoc ifaces\n"); return NULL; } + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!wdev) + return NULL; + + wdev->wiphy = wiphy; + priv->wdev = wdev; + wdev->iftype = NL80211_IFTYPE_STATION; + if (type == NL80211_IFTYPE_UNSPECIFIED) priv->bss_mode = NL80211_IFTYPE_STATION; else @@ -1312,11 +1499,36 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->bss_type = MWIFIEX_BSS_TYPE_STA; priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; - priv->bss_priority = 0; + priv->bss_priority = MWIFIEX_BSS_ROLE_STA; priv->bss_role = MWIFIEX_BSS_ROLE_STA; priv->bss_num = 0; break; + case NL80211_IFTYPE_AP: + priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP]; + + if (priv->bss_mode) { + wiphy_err(wiphy, "Can't create multiple AP interfaces"); + return NULL; + } + + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!wdev) + return NULL; + + priv->wdev = wdev; + wdev->wiphy = wiphy; + wdev->iftype = NL80211_IFTYPE_AP; + + priv->bss_type = MWIFIEX_BSS_TYPE_UAP; + priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; + priv->bss_priority = MWIFIEX_BSS_ROLE_UAP; + priv->bss_role = MWIFIEX_BSS_ROLE_UAP; + priv->bss_started = 0; + priv->bss_num = 0; + priv->bss_mode = type; + + break; default: wiphy_err(wiphy, "type not supported\n"); return NULL; @@ -1329,6 +1541,15 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, goto error; } + mwifiex_init_priv_params(priv, dev); + priv->netdev = dev; + + mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); + + if (adapter->config_bands & BAND_A) + mwifiex_setup_ht_caps( + &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); + dev_net_set(dev, wiphy_net(wiphy)); dev->ieee80211_ptr = priv->wdev; dev->ieee80211_ptr->iftype = priv->bss_mode; @@ -1343,9 +1564,6 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, mdev_priv = netdev_priv(dev); *((unsigned long *) mdev_priv) = (unsigned long) priv; - priv->netdev = dev; - mwifiex_init_priv_params(priv, dev); - SET_NETDEV_DEV(dev, adapter->dev); /* Register network device */ @@ -1417,7 +1635,6 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .get_station = mwifiex_cfg80211_get_station, .dump_station = mwifiex_cfg80211_dump_station, .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, - .set_channel = mwifiex_cfg80211_set_channel, .join_ibss = mwifiex_cfg80211_join_ibss, .leave_ibss = mwifiex_cfg80211_leave_ibss, .add_key = mwifiex_cfg80211_add_key, @@ -1426,6 +1643,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, .set_tx_power = mwifiex_cfg80211_set_tx_power, .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask, + .start_ap = mwifiex_cfg80211_start_ap, + .stop_ap = mwifiex_cfg80211_stop_ap, .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, }; @@ -1436,82 +1655,67 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { * default parameters and handler function pointers, and finally * registers the device. */ -int mwifiex_register_cfg80211(struct mwifiex_private *priv) + +int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) { int ret; void *wdev_priv; - struct wireless_dev *wdev; - struct ieee80211_sta_ht_cap *ht_info; + struct wiphy *wiphy; + struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; u8 *country_code; - 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); + /* create a new wiphy for use with cfg80211 */ + wiphy = wiphy_new(&mwifiex_cfg80211_ops, + sizeof(struct mwifiex_adapter *)); + if (!wiphy) { + dev_err(adapter->dev, "%s: creating new wiphy\n", __func__); return -ENOMEM; } - wdev->iftype = NL80211_IFTYPE_STATION; - wdev->wiphy->max_scan_ssids = 10; - wdev->wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; - 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; - } + wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; + wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_AP); + + wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; + if (adapter->config_bands & BAND_A) + wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; + else + wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + + wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta; + wiphy->n_iface_combinations = 1; /* Initialize cipher suits */ - wdev->wiphy->cipher_suites = mwifiex_cipher_suites; - wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); + wiphy->cipher_suites = mwifiex_cipher_suites; + 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; + memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN); + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_CUSTOM_REGULATORY; /* Reserve space for mwifiex specific private data for BSS */ - wdev->wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); - - wdev->wiphy->reg_notifier = mwifiex_reg_notifier; + wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); - /* Set struct mwifiex_private pointer in wiphy_priv */ - wdev_priv = wiphy_priv(wdev->wiphy); + wiphy->reg_notifier = mwifiex_reg_notifier; - *(unsigned long *) wdev_priv = (unsigned long) priv; + /* Set struct mwifiex_adapter pointer in wiphy_priv */ + wdev_priv = wiphy_priv(wiphy); + *(unsigned long *)wdev_priv = (unsigned long)adapter; - set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev); + set_wiphy_dev(wiphy, (struct device *)priv->adapter->dev); - ret = wiphy_register(wdev->wiphy); + ret = wiphy_register(wiphy); if (ret < 0) { - dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", - __func__); - wiphy_free(wdev->wiphy); - kfree(wdev); + dev_err(adapter->dev, + "%s: wiphy_register failed: %d\n", __func__, ret); + wiphy_free(wiphy); return ret; - } else { - dev_dbg(priv->adapter->dev, - "info: successfully registered wiphy device\n"); } - country_code = mwifiex_11d_code_2_region(priv->adapter->region_code); - if (country_code && regulatory_hint(wdev->wiphy, country_code)) - dev_err(priv->adapter->dev, - "%s: regulatory_hint failed\n", __func__); - - priv->wdev = wdev; + if (country_code && regulatory_hint(wiphy, country_code)) + dev_err(adapter->dev, "regulatory_hint() failed\n"); + adapter->wiphy = wiphy; return ret; } |