diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-10-11 15:35:42 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-10-11 15:35:42 -0400 |
commit | 094daf7db7c47861009899ce23f9177d761e20b0 (patch) | |
tree | a107065393720b80664157a035b206576e834793 /drivers/net/wireless/mwifiex | |
parent | 3ed6f6958c0ac21958285d8648f14d34da4bbcb3 (diff) | |
parent | 5f68a2b0a890d086e40fc7b55f4a0c32c28bc0d2 (diff) |
Merge branch 'master' of git://git.infradead.org/users/linville/wireless-next into for-davem
Conflicts:
Documentation/feature-removal-schedule.txt
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r-- | drivers/net/wireless/mwifiex/11n_aggr.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/11n_aggr.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 176 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/decl.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/init.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.c | 266 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 19 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_ioctl.c | 46 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.c | 32 |
10 files changed, 251 insertions, 304 deletions
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 1a453a605b3f..9e63d16365e3 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -193,7 +193,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, skb_src = skb_dequeue(&pra_list->skb_head); pra_list->total_pkts_size -= skb_src->len; - pra_list->total_pkts--; atomic_dec(&priv->wmm.tx_pkts_queued); @@ -269,7 +268,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, skb_queue_tail(&pra_list->skb_head, skb_aggr); pra_list->total_pkts_size += skb_aggr->len; - pra_list->total_pkts++; atomic_inc(&priv->wmm.tx_pkts_queued); diff --git a/drivers/net/wireless/mwifiex/11n_aggr.h b/drivers/net/wireless/mwifiex/11n_aggr.h index 9c6dca7ab02c..900e1c62a0cc 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.h +++ b/drivers/net/wireless/mwifiex/11n_aggr.h @@ -21,6 +21,7 @@ #define _MWIFIEX_11N_AGGR_H_ #define PKT_TYPE_AMSDU 0xE6 +#define MIN_NUM_AMSDU 2 int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, struct sk_buff *skb); diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 0ddcdca63cf7..462c71067bfb 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -543,12 +543,28 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, ret = -EFAULT; } + /* + * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid + * MCS index values for us are 0 to 7. + */ + if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 8)) { + sinfo->txrate.mcs = priv->tx_rate; + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + /* 40MHz rate */ + if (priv->tx_htinfo & BIT(1)) + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + /* SGI enabled */ + if (priv->tx_htinfo & BIT(2)) + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + } + sinfo->rx_bytes = priv->stats.rx_bytes; sinfo->tx_bytes = priv->stats.tx_bytes; sinfo->rx_packets = priv->stats.rx_packets; sinfo->tx_packets = priv->stats.tx_packets; sinfo->signal = priv->qual_level; - sinfo->txrate.legacy = rate.rate; + /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */ + sinfo->txrate.legacy = rate.rate * 5; return ret; } @@ -565,8 +581,6 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - mwifiex_dump_station_info(priv, sinfo); - if (!priv->media_connected) return -ENOENT; if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) @@ -1148,8 +1162,150 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; } +/* + * create a new virtual interface with the given name + */ +struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, + char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +{ + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + struct mwifiex_adapter *adapter; + struct net_device *dev; + void *mdev_priv; + + if (!priv) + return NULL; + + adapter = priv->adapter; + if (!adapter) + return NULL; + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + if (priv->bss_mode) { + wiphy_err(wiphy, "cannot create multiple" + " station/adhoc interfaces\n"); + return NULL; + } + + if (type == NL80211_IFTYPE_UNSPECIFIED) + priv->bss_mode = NL80211_IFTYPE_STATION; + else + priv->bss_mode = type; + + priv->bss_type = MWIFIEX_BSS_TYPE_STA; + priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; + priv->bss_priority = 0; + priv->bss_role = MWIFIEX_BSS_ROLE_STA; + priv->bss_index = 0; + priv->bss_num = 0; + + break; + default: + wiphy_err(wiphy, "type not supported\n"); + return NULL; + } + + dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name, + ether_setup, 1); + if (!dev) { + wiphy_err(wiphy, "no memory available for netdevice\n"); + goto error; + } + + dev_net_set(dev, wiphy_net(wiphy)); + dev->ieee80211_ptr = priv->wdev; + dev->ieee80211_ptr->iftype = priv->bss_mode; + memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN); + memcpy(dev->perm_addr, wiphy->perm_addr, ETH_ALEN); + SET_NETDEV_DEV(dev, wiphy_dev(wiphy)); + + dev->flags |= IFF_BROADCAST | IFF_MULTICAST; + dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; + dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; + + 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 */ + if (register_netdevice(dev)) { + wiphy_err(wiphy, "cannot register virtual network device\n"); + goto error; + } + + sema_init(&priv->async_sem, 1); + priv->scan_pending_on_block = false; + + dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); + +#ifdef CONFIG_DEBUG_FS + mwifiex_dev_debugfs_init(priv); +#endif + return dev; +error: + if (dev && (dev->reg_state == NETREG_UNREGISTERED)) + free_netdev(dev); + priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; + + return NULL; +} +EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); + +/* + * del_virtual_intf: remove the virtual interface determined by dev + */ +int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) +{ + struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); + + if (!priv || !dev) + return 0; + +#ifdef CONFIG_DEBUG_FS + mwifiex_dev_debugfs_remove(priv); +#endif + + if (!netif_queue_stopped(priv->netdev)) + netif_stop_queue(priv->netdev); + + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + + if (dev->reg_state == NETREG_REGISTERED) + unregister_netdevice(dev); + + if (dev->reg_state == NETREG_UNREGISTERED) + free_netdev(dev); + + /* Clear the priv in adapter */ + priv->netdev = NULL; + + priv->media_connected = false; + + cancel_work_sync(&priv->cfg_workqueue); + flush_workqueue(priv->workqueue); + destroy_workqueue(priv->workqueue); + + priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; + + return 0; +} +EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); + /* station cfg80211 operations */ static struct cfg80211_ops mwifiex_cfg80211_ops = { + .add_virtual_intf = mwifiex_add_virtual_intf, + .del_virtual_intf = mwifiex_del_virtual_intf, .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf, .scan = mwifiex_cfg80211_scan, .connect = mwifiex_cfg80211_connect, @@ -1174,8 +1330,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { * 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 mwifiex_register_cfg80211(struct mwifiex_private *priv) { int ret; void *wdev_priv; @@ -1215,7 +1370,7 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, wdev->wiphy->cipher_suites = mwifiex_cipher_suites; wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); - memcpy(wdev->wiphy->perm_addr, mac, 6); + memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN); wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; /* We are using custom domains */ @@ -1245,17 +1400,8 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, "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; } diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h index c4db8f36aa16..8d010f2500c5 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.h +++ b/drivers/net/wireless/mwifiex/cfg80211.h @@ -24,8 +24,7 @@ #include "main.h" -int mwifiex_register_cfg80211(struct net_device *, u8 *, - struct mwifiex_private *); +int mwifiex_register_cfg80211(struct mwifiex_private *); void mwifiex_cfg80211_results(struct work_struct *work); #endif diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 94ddc9038cb3..6ca62c809cb9 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -114,14 +114,6 @@ struct mwifiex_txinfo { u8 bss_index; }; -struct mwifiex_bss_attr { - u8 bss_type; - u8 frame_type; - u8 active; - u8 bss_priority; - u8 bss_num; -}; - enum mwifiex_wmm_ac_e { WMM_AC_BK, WMM_AC_BE, diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 26e685a31bc0..e1076b46401e 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -76,7 +76,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) memset(priv->curr_addr, 0xff, ETH_ALEN); priv->pkt_tx_ctrl = 0; - priv->bss_mode = NL80211_IFTYPE_STATION; + priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; priv->data_rate = 0; /* Initially indicate the rate as auto */ priv->is_data_rate_auto = true; priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 48b4d95219fb..4c7491ec3f2b 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -26,21 +26,6 @@ const char driver_version[] = "mwifiex " VERSION " (%s) "; -static struct mwifiex_bss_attr mwifiex_bss_sta[] = { - {MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0}, -}; - -static int drv_mode = DRV_MODE_STA; - -/* Supported drv_mode table */ -static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = { - { - .drv_mode = DRV_MODE_STA, - .intf_num = ARRAY_SIZE(mwifiex_bss_sta), - .bss_attr = mwifiex_bss_sta, - }, -}; - /* * This function registers the device and performs all the necessary * initializations. @@ -57,7 +42,6 @@ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = { * proper cleanup before exiting. */ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, - struct mwifiex_drv_mode *drv_mode_ptr, void **padapter) { struct mwifiex_adapter *adapter; @@ -78,44 +62,20 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, goto error; adapter->priv_num = 0; - for (i = 0; i < drv_mode_ptr->intf_num; i++) { - adapter->priv[i] = NULL; - - if (!drv_mode_ptr->bss_attr[i].active) - continue; - - /* Allocate memory for private structure */ - adapter->priv[i] = kzalloc(sizeof(struct mwifiex_private), - GFP_KERNEL); - if (!adapter->priv[i]) { - dev_err(adapter->dev, "%s: failed to alloc priv[%d]\n", - __func__, i); - goto error; - } - adapter->priv_num++; - adapter->priv[i]->adapter = adapter; - /* Save bss_type, frame_type & bss_priority */ - adapter->priv[i]->bss_type = drv_mode_ptr->bss_attr[i].bss_type; - adapter->priv[i]->frame_type = - drv_mode_ptr->bss_attr[i].frame_type; - adapter->priv[i]->bss_priority = - drv_mode_ptr->bss_attr[i].bss_priority; - - if (drv_mode_ptr->bss_attr[i].bss_type == MWIFIEX_BSS_TYPE_STA) - adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_STA; - else if (drv_mode_ptr->bss_attr[i].bss_type == - MWIFIEX_BSS_TYPE_UAP) - adapter->priv[i]->bss_role = MWIFIEX_BSS_ROLE_UAP; - - /* Save bss_index & bss_num */ - adapter->priv[i]->bss_index = i; - adapter->priv[i]->bss_num = drv_mode_ptr->bss_attr[i].bss_num; + /* Allocate memory for private structure */ + adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private), + GFP_KERNEL); + if (!adapter->priv[0]) { + dev_err(adapter->dev, "%s: failed to alloc priv[0]\n", + __func__); + goto error; } - adapter->drv_mode = drv_mode_ptr; - if (mwifiex_init_lock_list(adapter)) - goto error; + adapter->priv_num++; + + adapter->priv[0]->adapter = adapter; + mwifiex_init_lock_list(adapter); init_timer(&adapter->cmd_timer); adapter->cmd_timer.function = mwifiex_cmd_timeout_func; @@ -126,9 +86,9 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, error: dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n"); - mwifiex_free_lock_list(adapter); - for (i = 0; i < drv_mode_ptr->intf_num; i++) + for (i = 0; i < adapter->priv_num; i++) kfree(adapter->priv[i]); + kfree(adapter); return -1; @@ -316,38 +276,6 @@ exit_main_proc: } /* - * This function initializes the software. - * - * The main work includes allocating and initializing the adapter structure - * and initializing the private structures. - */ -static int -mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **padapter) -{ - int i; - struct mwifiex_drv_mode *drv_mode_ptr; - - /* find mwifiex_drv_mode entry from mwifiex_drv_mode_tbl */ - drv_mode_ptr = NULL; - for (i = 0; i < ARRAY_SIZE(mwifiex_drv_mode_tbl); i++) { - if (mwifiex_drv_mode_tbl[i].drv_mode == drv_mode) { - drv_mode_ptr = &mwifiex_drv_mode_tbl[i]; - break; - } - } - - if (!drv_mode_ptr) { - pr_err("invalid drv_mode=%d\n", drv_mode); - return -1; - } - - if (mwifiex_register(card, if_ops, drv_mode_ptr, padapter)) - return -1; - - return 0; -} - -/* * This function frees the adapter structure. * * Additionally, this closes the netlink socket, frees the timers @@ -649,8 +577,8 @@ static const struct net_device_ops mwifiex_netdev_ops = { * * In addition, the CFG80211 work queue is also created. */ -static void -mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev) +void mwifiex_init_priv_params(struct mwifiex_private *priv, + struct net_device *dev) { dev->netdev_ops = &mwifiex_netdev_ops; /* Initialize private structure */ @@ -664,118 +592,6 @@ mwifiex_init_priv_params(struct mwifiex_private *priv, struct net_device *dev) } /* - * This function adds a new logical interface. - * - * It allocates, initializes and registers the interface by performing - * the following opearations - - * - Allocate a new net device structure - * - Assign device name - * - Register the new device with CFG80211 subsystem - * - Initialize semaphore and private structure - * - Register the new device with kernel - * - Create the complete debug FS structure if configured - */ -static struct mwifiex_private *mwifiex_add_interface( - struct mwifiex_adapter *adapter, - u8 bss_index, u8 bss_type) -{ - struct net_device *dev; - struct mwifiex_private *priv; - void *mdev_priv; - - dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), "mlan%d", - ether_setup, 1); - if (!dev) { - dev_err(adapter->dev, "no memory available for netdevice\n"); - goto error; - } - - if (mwifiex_register_cfg80211(dev, adapter->priv[bss_index]->curr_addr, - adapter->priv[bss_index]) != 0) { - dev_err(adapter->dev, "cannot register netdevice with cfg80211\n"); - goto error; - } - /* Save the priv pointer in netdev */ - priv = adapter->priv[bss_index]; - mdev_priv = netdev_priv(dev); - *((unsigned long *) mdev_priv) = (unsigned long) priv; - - priv->netdev = dev; - - sema_init(&priv->async_sem, 1); - priv->scan_pending_on_block = false; - - mwifiex_init_priv_params(priv, dev); - - SET_NETDEV_DEV(dev, adapter->dev); - - /* Register network device */ - if (register_netdev(dev)) { - dev_err(adapter->dev, "cannot register virtual network device\n"); - goto error; - } - - dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); -#ifdef CONFIG_DEBUG_FS - mwifiex_dev_debugfs_init(priv); -#endif - return priv; -error: - if (dev) - free_netdev(dev); - return NULL; -} - -/* - * This function removes a logical interface. - * - * It deregisters, resets and frees the interface by performing - * the following operations - - * - Disconnect the device if connected, send wireless event to - * notify applications. - * - Remove the debug FS structure if configured - * - Unregister the device from kernel - * - Free the net device structure - * - Cancel all works and destroy work queue - * - Unregister and free the wireless device from CFG80211 subsystem - */ -static void -mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index) -{ - struct net_device *dev; - struct mwifiex_private *priv = adapter->priv[bss_index]; - - if (!priv) - return; - dev = priv->netdev; - - if (priv->media_connected) - priv->media_connected = false; - -#ifdef CONFIG_DEBUG_FS - mwifiex_dev_debugfs_remove(priv); -#endif - /* Last reference is our one */ - dev_dbg(adapter->dev, "info: %s: refcnt = %d\n", - dev->name, netdev_refcnt_read(dev)); - - if (dev->reg_state == NETREG_REGISTERED) - unregister_netdev(dev); - - /* Clear the priv in adapter */ - priv->netdev = NULL; - if (dev) - free_netdev(dev); - - cancel_work_sync(&priv->cfg_workqueue); - flush_workqueue(priv->workqueue); - destroy_workqueue(priv->workqueue); - wiphy_unregister(priv->wdev->wiphy); - wiphy_free(priv->wdev->wiphy); - kfree(priv->wdev); -} - -/* * This function check if command is pending. */ int is_command_pending(struct mwifiex_adapter *adapter) @@ -847,14 +663,14 @@ int mwifiex_add_card(void *card, struct semaphore *sem, struct mwifiex_if_ops *if_ops) { - int i; struct mwifiex_adapter *adapter; char fmt[64]; + struct mwifiex_private *priv; if (down_interruptible(sem)) goto exit_sem_err; - if (mwifiex_init_sw(card, if_ops, (void **)&adapter)) { + if (mwifiex_register(card, if_ops, (void **)&adapter)) { pr_err("%s: software init failed\n", __func__); goto err_init_sw; } @@ -888,14 +704,26 @@ mwifiex_add_card(void *card, struct semaphore *sem, goto err_init_fw; } - /* Add interfaces */ - for (i = 0; i < adapter->drv_mode->intf_num; i++) { - if (!mwifiex_add_interface(adapter, i, - adapter->drv_mode->bss_attr[i].bss_type)) { - goto err_add_intf; - } + priv = adapter->priv[0]; + + if (mwifiex_register_cfg80211(priv) != 0) { + dev_err(adapter->dev, "cannot register netdevice" + " with cfg80211\n"); + goto err_init_fw; + } + + rtnl_lock(); + /* Create station interface by default */ + if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d", + NL80211_IFTYPE_STATION, NULL, NULL)) { + rtnl_unlock(); + dev_err(adapter->dev, "cannot create default station" + " interface\n"); + goto err_add_intf; } + rtnl_unlock(); + up(sem); mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); @@ -904,8 +732,9 @@ mwifiex_add_card(void *card, struct semaphore *sem, return 0; err_add_intf: - for (i = 0; i < adapter->priv_num; i++) - mwifiex_remove_interface(adapter, i); + rtnl_lock(); + mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); + rtnl_unlock(); err_init_fw: pr_debug("info: %s: unregister device\n", __func__); adapter->if_ops.unregister_dev(adapter); @@ -960,7 +789,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) /* Stop data */ for (i = 0; i < adapter->priv_num; i++) { priv = adapter->priv[i]; - if (priv) { + if (priv && priv->netdev) { if (!netif_queue_stopped(priv->netdev)) netif_stop_queue(priv->netdev); if (netif_carrier_ok(priv->netdev)) @@ -985,9 +814,20 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) atomic_read(&adapter->cmd_pending)); } - /* Remove interface */ - for (i = 0; i < adapter->priv_num; i++) - mwifiex_remove_interface(adapter, i); + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + + if (!priv) + continue; + + rtnl_lock(); + mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); + rtnl_unlock(); + } + + wiphy_unregister(priv->wdev->wiphy); + wiphy_free(priv->wdev->wiphy); + kfree(priv->wdev); mwifiex_terminate_workqueue(adapter); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 1e801328a558..907ab746dc4b 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -45,15 +45,6 @@ enum { MWIFIEX_SYNC_CMD }; -#define DRV_MODE_STA 0x1 - -struct mwifiex_drv_mode { - u16 drv_mode; - u16 intf_num; - struct mwifiex_bss_attr *bss_attr; -}; - - #define MWIFIEX_MAX_AP 64 #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) @@ -182,7 +173,6 @@ struct mwifiex_ra_list_tbl { struct sk_buff_head skb_head; u8 ra[ETH_ALEN]; u32 total_pkts_size; - u32 total_pkts; u32 is_11n_enabled; }; @@ -546,7 +536,6 @@ struct mwifiex_if_ops { struct mwifiex_adapter { struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; u8 priv_num; - struct mwifiex_drv_mode *drv_mode; const struct firmware *firmware; char fw_name[32]; struct device *dev; @@ -792,6 +781,8 @@ int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); int is_command_pending(struct mwifiex_adapter *adapter); +void mwifiex_init_priv_params(struct mwifiex_private *priv, + struct net_device *dev); /* * This function checks if the queuing is RA based or not. @@ -966,6 +957,12 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, int mwifiex_check_network_compatibility(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc); +struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, + char *name, enum nl80211_iftype type, + u32 *flags, struct vif_params *params); +int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); + + #ifdef CONFIG_DEBUG_FS void mwifiex_debugfs_init(void); void mwifiex_debugfs_remove(void); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index a9dfeb1b4ace..520800b618e7 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -720,51 +720,9 @@ done: static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv, struct mwifiex_rate_cfg *rate_cfg) { - struct mwifiex_adapter *adapter = priv->adapter; - rate_cfg->is_rate_auto = priv->is_data_rate_auto; - if (!priv->media_connected) { - switch (adapter->config_bands) { - case BAND_B: - /* Return the lowest supported rate for B band */ - rate_cfg->rate = supported_rates_b[0] & 0x7f; - break; - case BAND_G: - case BAND_G | BAND_GN: - /* Return the lowest supported rate for G band */ - rate_cfg->rate = supported_rates_g[0] & 0x7f; - break; - case BAND_B | BAND_G: - case BAND_A | BAND_B | BAND_G: - case BAND_A | BAND_B: - case BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN: - case BAND_B | BAND_G | BAND_GN: - /* Return the lowest supported rate for BG band */ - rate_cfg->rate = supported_rates_bg[0] & 0x7f; - break; - case BAND_A: - case BAND_A | BAND_G: - case BAND_A | BAND_G | BAND_AN | BAND_GN: - case BAND_A | BAND_AN: - /* Return the lowest supported rate for A band */ - rate_cfg->rate = supported_rates_a[0] & 0x7f; - break; - case BAND_GN: - /* Return the lowest supported rate for N band */ - rate_cfg->rate = supported_rates_n[0] & 0x7f; - break; - default: - dev_warn(adapter->dev, "invalid band %#x\n", - adapter->config_bands); - break; - } - } else { - return mwifiex_send_cmd_sync(priv, - HostCmd_CMD_802_11_TX_RATE_QUERY, - HostCmd_ACT_GEN_GET, 0, NULL); - } - - return 0; + return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, + HostCmd_ACT_GEN_GET, 0, NULL); } /* diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 69e260b41711..eda24474c1fc 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -121,7 +121,6 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra) memcpy(ra_list->ra, ra, ETH_ALEN); ra_list->total_pkts_size = 0; - ra_list->total_pkts = 0; dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list); @@ -648,7 +647,6 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, skb_queue_tail(&ra_list->skb_head, skb); ra_list->total_pkts_size += skb->len; - ra_list->total_pkts++; atomic_inc(&priv->wmm.tx_pkts_queued); @@ -975,6 +973,28 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, } /* + * This function checks if 11n aggregation is possible. + */ +static int +mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv, + struct mwifiex_ra_list_tbl *ptr, + int max_buf_size) +{ + int count = 0, total_size = 0; + struct sk_buff *skb, *tmp; + + skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { + total_size += skb->len; + if (total_size >= max_buf_size) + break; + if (++count >= MIN_NUM_AMSDU) + return true; + } + + return false; +} + +/* * This function sends a single packet to firmware for transmission. */ static void @@ -1001,7 +1021,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb); ptr->total_pkts_size -= skb->len; - ptr->total_pkts--; if (!skb_queue_empty(&ptr->skb_head)) skb_next = skb_peek(&ptr->skb_head); @@ -1027,7 +1046,6 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, skb_queue_tail(&ptr->skb_head, skb); ptr->total_pkts_size += skb->len; - ptr->total_pkts++; tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); @@ -1213,11 +1231,9 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) mwifiex_send_delba(priv, tid_del, ra, 1); } } -/* Minimum number of AMSDU */ -#define MIN_NUM_AMSDU 2 - if (mwifiex_is_amsdu_allowed(priv, tid) && - (ptr->total_pkts >= MIN_NUM_AMSDU)) + mwifiex_is_11n_aggragation_possible(priv, ptr, + adapter->tx_buf_size)) mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, ptr_index, flags); /* ra_list_spinlock has been freed in |