diff options
Diffstat (limited to 'drivers/net/wireless/marvell')
-rw-r--r-- | drivers/net/wireless/marvell/libertas/cmd.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/libertas/if_usb.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/libertas/main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/libertas/mesh.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/libertas_tf/if_usb.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/11n.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/cfg80211.c | 384 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/cmdevt.c | 21 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/main.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/main.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/pcie.c | 36 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/sta_tx.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/uap_event.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/uap_txrx.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwifiex/usb.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/marvell/mwl8k.c | 2 |
17 files changed, 325 insertions, 210 deletions
diff --git a/drivers/net/wireless/marvell/libertas/cmd.c b/drivers/net/wireless/marvell/libertas/cmd.c index a4d9dd73b258..104d2b6dc9af 100644 --- a/drivers/net/wireless/marvell/libertas/cmd.c +++ b/drivers/net/wireless/marvell/libertas/cmd.c @@ -150,10 +150,9 @@ int lbs_update_hw_spec(struct lbs_private *priv) memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN); if (!priv->copied_hwaddr) { - memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN); + eth_hw_addr_set(priv->dev, priv->current_addr); if (priv->mesh_dev) - memcpy(priv->mesh_dev->dev_addr, - priv->current_addr, ETH_ALEN); + eth_hw_addr_set(priv->mesh_dev, priv->current_addr); priv->copied_hwaddr = 1; } diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c index 20436a289d5c..5d6dc1dd050d 100644 --- a/drivers/net/wireless/marvell/libertas/if_usb.c +++ b/drivers/net/wireless/marvell/libertas/if_usb.c @@ -292,6 +292,7 @@ err_add_card: if_usb_reset_device(cardp); dealloc: if_usb_free(cardp); + kfree(cardp); error: return r; @@ -316,6 +317,7 @@ static void if_usb_disconnect(struct usb_interface *intf) /* Unlink and free urb */ if_usb_free(cardp); + kfree(cardp); usb_set_intfdata(intf, NULL); usb_put_dev(interface_to_usbdev(intf)); diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c index 64fc5e410864..5c9f295536ea 100644 --- a/drivers/net/wireless/marvell/libertas/main.c +++ b/drivers/net/wireless/marvell/libertas/main.c @@ -302,9 +302,9 @@ int lbs_set_mac_address(struct net_device *dev, void *addr) dev = priv->dev; memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN); - memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN); + eth_hw_addr_set(dev, phwaddr->sa_data); if (priv->mesh_dev) - memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN); + eth_hw_addr_set(priv->mesh_dev, phwaddr->sa_data); return ret; } diff --git a/drivers/net/wireless/marvell/libertas/mesh.c b/drivers/net/wireless/marvell/libertas/mesh.c index 6cbba84989b8..a58c1e141f2c 100644 --- a/drivers/net/wireless/marvell/libertas/mesh.c +++ b/drivers/net/wireless/marvell/libertas/mesh.c @@ -169,7 +169,7 @@ static ssize_t anycast_mask_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0])); + return sysfs_emit(buf, "0x%X\n", le32_to_cpu(mesh_access.data[0])); } /** @@ -222,7 +222,7 @@ static ssize_t prb_rsp_limit_show(struct device *dev, return ret; retry_limit = le32_to_cpu(mesh_access.data[1]); - return snprintf(buf, 10, "%d\n", retry_limit); + return sysfs_emit(buf, "%d\n", retry_limit); } /** @@ -270,7 +270,7 @@ static ssize_t lbs_mesh_show(struct device *dev, struct device_attribute *attr, char *buf) { struct lbs_private *priv = to_net_dev(dev)->ml_priv; - return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); + return sysfs_emit(buf, "0x%X\n", !!priv->mesh_dev); } /** @@ -369,7 +369,7 @@ static ssize_t bootflag_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag)); + return sysfs_emit(buf, "%d\n", le32_to_cpu(defs.bootflag)); } /** @@ -419,7 +419,7 @@ static ssize_t boottime_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 12, "%d\n", defs.boottime); + return sysfs_emit(buf, "%d\n", defs.boottime); } /** @@ -479,7 +479,7 @@ static ssize_t channel_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel)); + return sysfs_emit(buf, "%d\n", le16_to_cpu(defs.channel)); } /** @@ -605,7 +605,7 @@ static ssize_t protocol_id_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id); + return sysfs_emit(buf, "%d\n", defs.meshie.val.active_protocol_id); } /** @@ -667,7 +667,7 @@ static ssize_t metric_id_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id); + return sysfs_emit(buf, "%d\n", defs.meshie.val.active_metric_id); } /** @@ -729,7 +729,7 @@ static ssize_t capability_show(struct device *dev, if (ret) return ret; - return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability); + return sysfs_emit(buf, "%d\n", defs.meshie.val.mesh_capability); } /** diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c index fe0a69e804d8..75b5319d033f 100644 --- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c +++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c @@ -230,6 +230,7 @@ static int if_usb_probe(struct usb_interface *intf, dealloc: if_usb_free(cardp); + kfree(cardp); error: lbtf_deb_leave(LBTF_DEB_MAIN); return -ENOMEM; @@ -254,6 +255,7 @@ static void if_usb_disconnect(struct usb_interface *intf) /* Unlink and free urb */ if_usb_free(cardp); + kfree(cardp); usb_set_intfdata(intf, NULL); usb_put_dev(interface_to_usbdev(intf)); diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c index 6696bce56178..9ff2058bcd7e 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n.c +++ b/drivers/net/wireless/marvell/mwifiex/11n.c @@ -125,7 +125,7 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv, tx_ba_tbl->ra); } else { /* * In case of failure, recreate the deleted stream in case - * we initiated the ADDBA + * we initiated the DELBA */ if (!INITIATOR_BIT(del_ba_param_set)) return 0; @@ -657,14 +657,15 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, uint16_t del_ba_param_set; memset(&delba, 0, sizeof(delba)); - delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS); - del_ba_param_set = le16_to_cpu(delba.del_ba_param_set); + del_ba_param_set = tid << DELBA_TID_POS; + if (initiator) del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK; else del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK; + delba.del_ba_param_set = cpu_to_le16(del_ba_param_set); memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN); /* We don't wait for the response of this command */ diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 0961f4a5e415..6f23ec34e2e2 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -519,8 +519,14 @@ mwifiex_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, encrypt_key.is_igtk_def_key = true; eth_broadcast_addr(encrypt_key.mac_addr); - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, true, &encrypt_key, true); + if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, true, &encrypt_key, true)) { + mwifiex_dbg(priv->adapter, ERROR, + "Sending KEY_MATERIAL command failed\n"); + return -1; + } + + return 0; } /* @@ -908,16 +914,20 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, switch (type) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: - priv->bss_role = MWIFIEX_BSS_ROLE_STA; + priv->bss_role = MWIFIEX_BSS_ROLE_STA; + priv->bss_type = MWIFIEX_BSS_TYPE_STA; break; case NL80211_IFTYPE_P2P_CLIENT: - priv->bss_role = MWIFIEX_BSS_ROLE_STA; + priv->bss_role = MWIFIEX_BSS_ROLE_STA; + priv->bss_type = MWIFIEX_BSS_TYPE_P2P; break; case NL80211_IFTYPE_P2P_GO: - priv->bss_role = MWIFIEX_BSS_ROLE_UAP; + priv->bss_role = MWIFIEX_BSS_ROLE_UAP; + priv->bss_type = MWIFIEX_BSS_TYPE_P2P; break; case NL80211_IFTYPE_AP: priv->bss_role = MWIFIEX_BSS_ROLE_UAP; + priv->bss_type = MWIFIEX_BSS_TYPE_UAP; break; default: mwifiex_dbg(adapter, ERROR, @@ -939,6 +949,117 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, return 0; } +static bool +is_vif_type_change_allowed(struct mwifiex_adapter *adapter, + enum nl80211_iftype old_iftype, + enum nl80211_iftype new_iftype) +{ + switch (old_iftype) { + case NL80211_IFTYPE_ADHOC: + switch (new_iftype) { + case NL80211_IFTYPE_STATION: + return true; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_P2P_GO: + return adapter->curr_iface_comb.p2p_intf != + adapter->iface_limit.p2p_intf; + case NL80211_IFTYPE_AP: + return adapter->curr_iface_comb.uap_intf != + adapter->iface_limit.uap_intf; + default: + return false; + } + + case NL80211_IFTYPE_STATION: + switch (new_iftype) { + case NL80211_IFTYPE_ADHOC: + return true; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_P2P_GO: + return adapter->curr_iface_comb.p2p_intf != + adapter->iface_limit.p2p_intf; + case NL80211_IFTYPE_AP: + return adapter->curr_iface_comb.uap_intf != + adapter->iface_limit.uap_intf; + default: + return false; + } + + case NL80211_IFTYPE_AP: + switch (new_iftype) { + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: + return adapter->curr_iface_comb.sta_intf != + adapter->iface_limit.sta_intf; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_P2P_GO: + return adapter->curr_iface_comb.p2p_intf != + adapter->iface_limit.p2p_intf; + default: + return false; + } + + case NL80211_IFTYPE_P2P_CLIENT: + switch (new_iftype) { + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: + return true; + case NL80211_IFTYPE_P2P_GO: + return true; + case NL80211_IFTYPE_AP: + return adapter->curr_iface_comb.uap_intf != + adapter->iface_limit.uap_intf; + default: + return false; + } + + case NL80211_IFTYPE_P2P_GO: + switch (new_iftype) { + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: + return true; + case NL80211_IFTYPE_P2P_CLIENT: + return true; + case NL80211_IFTYPE_AP: + return adapter->curr_iface_comb.uap_intf != + adapter->iface_limit.uap_intf; + default: + return false; + } + + default: + break; + } + + return false; +} + +static void +update_vif_type_counter(struct mwifiex_adapter *adapter, + enum nl80211_iftype iftype, + int change) +{ + switch (iftype) { + case NL80211_IFTYPE_UNSPECIFIED: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: + adapter->curr_iface_comb.sta_intf += change; + break; + case NL80211_IFTYPE_AP: + adapter->curr_iface_comb.uap_intf += change; + break; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_P2P_GO: + adapter->curr_iface_comb.p2p_intf += change; + break; + default: + mwifiex_dbg(adapter, ERROR, + "%s: Unsupported iftype passed: %d\n", + __func__, iftype); + break; + } +} + static int mwifiex_change_vif_to_p2p(struct net_device *dev, enum nl80211_iftype curr_iftype, @@ -955,13 +1076,6 @@ mwifiex_change_vif_to_p2p(struct net_device *dev, adapter = priv->adapter; - if (adapter->curr_iface_comb.p2p_intf == - adapter->iface_limit.p2p_intf) { - mwifiex_dbg(adapter, ERROR, - "cannot create multiple P2P ifaces\n"); - return -1; - } - mwifiex_dbg(adapter, INFO, "%s: changing role to p2p\n", dev->name); @@ -970,6 +1084,10 @@ mwifiex_change_vif_to_p2p(struct net_device *dev, if (mwifiex_init_new_priv_params(priv, dev, type)) return -1; + update_vif_type_counter(adapter, curr_iftype, -1); + update_vif_type_counter(adapter, type, +1); + dev->ieee80211_ptr->iftype = type; + switch (type) { case NL80211_IFTYPE_P2P_CLIENT: if (mwifiex_cfg80211_init_p2p_client(priv)) @@ -993,21 +1111,6 @@ mwifiex_change_vif_to_p2p(struct net_device *dev, if (mwifiex_sta_init_cmd(priv, false, false)) return -1; - switch (curr_iftype) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - adapter->curr_iface_comb.sta_intf--; - break; - case NL80211_IFTYPE_AP: - adapter->curr_iface_comb.uap_intf--; - break; - default: - break; - } - - adapter->curr_iface_comb.p2p_intf++; - dev->ieee80211_ptr->iftype = type; - return 0; } @@ -1027,15 +1130,6 @@ mwifiex_change_vif_to_sta_adhoc(struct net_device *dev, adapter = priv->adapter; - if ((curr_iftype != NL80211_IFTYPE_P2P_CLIENT && - curr_iftype != NL80211_IFTYPE_P2P_GO) && - (adapter->curr_iface_comb.sta_intf == - adapter->iface_limit.sta_intf)) { - mwifiex_dbg(adapter, ERROR, - "cannot create multiple station/adhoc ifaces\n"); - return -1; - } - if (type == NL80211_IFTYPE_STATION) mwifiex_dbg(adapter, INFO, "%s: changing role to station\n", dev->name); @@ -1047,26 +1141,17 @@ mwifiex_change_vif_to_sta_adhoc(struct net_device *dev, return -1; if (mwifiex_init_new_priv_params(priv, dev, type)) return -1; + + update_vif_type_counter(adapter, curr_iftype, -1); + update_vif_type_counter(adapter, type, +1); + dev->ieee80211_ptr->iftype = type; + if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, HostCmd_ACT_GEN_SET, 0, NULL, true)) return -1; if (mwifiex_sta_init_cmd(priv, false, false)) return -1; - switch (curr_iftype) { - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - adapter->curr_iface_comb.p2p_intf--; - break; - case NL80211_IFTYPE_AP: - adapter->curr_iface_comb.uap_intf--; - break; - default: - break; - } - - adapter->curr_iface_comb.sta_intf++; - dev->ieee80211_ptr->iftype = type; return 0; } @@ -1086,13 +1171,6 @@ mwifiex_change_vif_to_ap(struct net_device *dev, adapter = priv->adapter; - if (adapter->curr_iface_comb.uap_intf == - adapter->iface_limit.uap_intf) { - mwifiex_dbg(adapter, ERROR, - "cannot create multiple AP ifaces\n"); - return -1; - } - mwifiex_dbg(adapter, INFO, "%s: changing role to AP\n", dev->name); @@ -1100,27 +1178,17 @@ mwifiex_change_vif_to_ap(struct net_device *dev, return -1; if (mwifiex_init_new_priv_params(priv, dev, type)) return -1; + + update_vif_type_counter(adapter, curr_iftype, -1); + update_vif_type_counter(adapter, type, +1); + dev->ieee80211_ptr->iftype = type; + if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, HostCmd_ACT_GEN_SET, 0, NULL, true)) return -1; if (mwifiex_sta_init_cmd(priv, false, false)) return -1; - switch (curr_iftype) { - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - adapter->curr_iface_comb.p2p_intf--; - break; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - adapter->curr_iface_comb.sta_intf--; - break; - default: - break; - } - - adapter->curr_iface_comb.uap_intf++; - dev->ieee80211_ptr->iftype = type; return 0; } /* @@ -1141,6 +1209,27 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, return -EBUSY; } + if (type == NL80211_IFTYPE_UNSPECIFIED) { + mwifiex_dbg(priv->adapter, INFO, + "%s: no new type specified, keeping old type %d\n", + dev->name, curr_iftype); + return 0; + } + + if (curr_iftype == type) { + mwifiex_dbg(priv->adapter, INFO, + "%s: interface already is of type %d\n", + dev->name, curr_iftype); + return 0; + } + + if (!is_vif_type_change_allowed(priv->adapter, curr_iftype, type)) { + mwifiex_dbg(priv->adapter, ERROR, + "%s: change from type %d to %d is not allowed\n", + dev->name, curr_iftype, type); + return -EOPNOTSUPP; + } + switch (curr_iftype) { case NL80211_IFTYPE_ADHOC: switch (type) { @@ -1160,19 +1249,10 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, case NL80211_IFTYPE_AP: return mwifiex_change_vif_to_ap(dev, curr_iftype, type, params); - case NL80211_IFTYPE_UNSPECIFIED: - mwifiex_dbg(priv->adapter, INFO, - "%s: kept type as IBSS\n", dev->name); - fallthrough; - case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */ - return 0; default: - mwifiex_dbg(priv->adapter, ERROR, - "%s: changing to %d not supported\n", - dev->name, type); - return -EOPNOTSUPP; + goto errnotsupp; } - break; + case NL80211_IFTYPE_STATION: switch (type) { case NL80211_IFTYPE_ADHOC: @@ -1191,22 +1271,14 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, case NL80211_IFTYPE_AP: return mwifiex_change_vif_to_ap(dev, curr_iftype, type, params); - case NL80211_IFTYPE_UNSPECIFIED: - mwifiex_dbg(priv->adapter, INFO, - "%s: kept type as STA\n", dev->name); - fallthrough; - case NL80211_IFTYPE_STATION: /* This shouldn't happen */ - return 0; default: - mwifiex_dbg(priv->adapter, ERROR, - "%s: changing to %d not supported\n", - dev->name, type); - return -EOPNOTSUPP; + goto errnotsupp; } - break; + case NL80211_IFTYPE_AP: switch (type) { case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, type, params); break; @@ -1214,69 +1286,60 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, case NL80211_IFTYPE_P2P_GO: return mwifiex_change_vif_to_p2p(dev, curr_iftype, type, params); - case NL80211_IFTYPE_UNSPECIFIED: - mwifiex_dbg(priv->adapter, INFO, - "%s: kept type as AP\n", dev->name); - fallthrough; - case NL80211_IFTYPE_AP: /* This shouldn't happen */ - return 0; default: - mwifiex_dbg(priv->adapter, ERROR, - "%s: changing to %d not supported\n", - dev->name, type); - return -EOPNOTSUPP; + goto errnotsupp; } - break; + case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: + if (mwifiex_cfg80211_deinit_p2p(priv)) + return -EFAULT; + switch (type) { - case NL80211_IFTYPE_STATION: - if (mwifiex_cfg80211_deinit_p2p(priv)) - return -EFAULT; - priv->adapter->curr_iface_comb.p2p_intf--; - priv->adapter->curr_iface_comb.sta_intf++; - dev->ieee80211_ptr->iftype = type; - if (mwifiex_deinit_priv_params(priv)) - return -1; - if (mwifiex_init_new_priv_params(priv, dev, type)) - return -1; - if (mwifiex_sta_init_cmd(priv, false, false)) - return -1; - break; case NL80211_IFTYPE_ADHOC: - if (mwifiex_cfg80211_deinit_p2p(priv)) - return -EFAULT; + case NL80211_IFTYPE_STATION: return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, type, params); - break; + case NL80211_IFTYPE_P2P_GO: + return mwifiex_change_vif_to_p2p(dev, curr_iftype, + type, params); case NL80211_IFTYPE_AP: - if (mwifiex_cfg80211_deinit_p2p(priv)) - return -EFAULT; return mwifiex_change_vif_to_ap(dev, curr_iftype, type, params); - case NL80211_IFTYPE_UNSPECIFIED: - mwifiex_dbg(priv->adapter, INFO, - "%s: kept type as P2P\n", dev->name); - fallthrough; + default: + goto errnotsupp; + } + + case NL80211_IFTYPE_P2P_GO: + if (mwifiex_cfg80211_deinit_p2p(priv)) + return -EFAULT; + + switch (type) { + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: + return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, + type, params); case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - return 0; + return mwifiex_change_vif_to_p2p(dev, curr_iftype, + type, params); + case NL80211_IFTYPE_AP: + return mwifiex_change_vif_to_ap(dev, curr_iftype, type, + params); default: - mwifiex_dbg(priv->adapter, ERROR, - "%s: changing to %d not supported\n", - dev->name, type); - return -EOPNOTSUPP; + goto errnotsupp; } - break; + default: - mwifiex_dbg(priv->adapter, ERROR, - "%s: unknown iftype: %d\n", - dev->name, dev->ieee80211_ptr->iftype); - return -EOPNOTSUPP; + goto errnotsupp; } return 0; + +errnotsupp: + mwifiex_dbg(priv->adapter, ERROR, + "unsupported interface type transition: %d to %d\n", + curr_iftype, type); + return -EOPNOTSUPP; } static void @@ -2997,7 +3060,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->bss_type = MWIFIEX_BSS_TYPE_P2P; priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; - priv->bss_priority = MWIFIEX_BSS_ROLE_STA; + priv->bss_priority = 0; priv->bss_role = MWIFIEX_BSS_ROLE_STA; priv->bss_started = 0; @@ -3108,23 +3171,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, mwifiex_dev_debugfs_init(priv); #endif - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - adapter->curr_iface_comb.sta_intf++; - break; - case NL80211_IFTYPE_AP: - adapter->curr_iface_comb.uap_intf++; - break; - case NL80211_IFTYPE_P2P_CLIENT: - adapter->curr_iface_comb.p2p_intf++; - break; - default: - /* This should be dead code; checked above */ - mwifiex_dbg(adapter, ERROR, "type not supported\n"); - return ERR_PTR(-EINVAL); - } + update_vif_type_counter(adapter, type, +1); return &priv->wdev; @@ -3177,37 +3224,18 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) cfg80211_unregister_netdevice(wdev->netdev); if (priv->dfs_cac_workqueue) { - flush_workqueue(priv->dfs_cac_workqueue); destroy_workqueue(priv->dfs_cac_workqueue); priv->dfs_cac_workqueue = NULL; } if (priv->dfs_chan_sw_workqueue) { - flush_workqueue(priv->dfs_chan_sw_workqueue); destroy_workqueue(priv->dfs_chan_sw_workqueue); priv->dfs_chan_sw_workqueue = NULL; } /* Clear the priv in adapter */ priv->netdev = NULL; - switch (priv->bss_mode) { - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - adapter->curr_iface_comb.sta_intf--; - break; - case NL80211_IFTYPE_AP: - adapter->curr_iface_comb.uap_intf--; - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - adapter->curr_iface_comb.p2p_intf--; - break; - default: - mwifiex_dbg(adapter, ERROR, - "del_virtual_intf: type not supported\n"); - break; - } + update_vif_type_counter(adapter, priv->bss_mode, -1); priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; @@ -3470,7 +3498,7 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, } if (!wowlan) { - mwifiex_dbg(adapter, ERROR, + mwifiex_dbg(adapter, INFO, "None of the WOWLAN triggers enabled\n"); ret = 0; goto done; diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index 171a25742600..d6a61f850c6f 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -608,6 +608,11 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no, return -1; } + if (priv->adapter->hs_activated_manually && + cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) { + mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD); + priv->adapter->hs_activated_manually = false; + } /* Get a new command node */ cmd_node = mwifiex_get_cmd_node(adapter); @@ -714,6 +719,15 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, } } + /* Same with exit host sleep cmd, luckily that can't happen at the same time as EXIT_PS */ + if (command == HostCmd_CMD_802_11_HS_CFG_ENH) { + struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = + &host_cmd->params.opt_hs_cfg; + + if (le16_to_cpu(hs_cfg->action) == HS_ACTIVATE) + add_tail = false; + } + spin_lock_bh(&adapter->cmd_pending_q_lock); if (add_tail) list_add_tail(&cmd_node->list, &adapter->cmd_pending_q); @@ -1216,6 +1230,13 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter) __func__); adapter->if_ops.wakeup(adapter); + + if (adapter->hs_activated_manually) { + mwifiex_cancel_hs(mwifiex_get_priv (adapter, MWIFIEX_BSS_ROLE_ANY), + MWIFIEX_ASYNC_CMD); + adapter->hs_activated_manually = false; + } + adapter->hs_activated = false; clear_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags); clear_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags); diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 17399d4aa129..19b996c6a260 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -401,6 +401,12 @@ process_start: !adapter->scan_processing) && !adapter->data_sent && !skb_queue_empty(&adapter->tx_data_q)) { + if (adapter->hs_activated_manually) { + mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY), + MWIFIEX_ASYNC_CMD); + adapter->hs_activated_manually = false; + } + mwifiex_process_tx_queue(adapter); if (adapter->hs_activated) { clear_bit(MWIFIEX_IS_HS_CONFIGURED, @@ -418,6 +424,12 @@ process_start: !mwifiex_bypass_txlist_empty(adapter) && !mwifiex_is_tdls_chan_switching (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) { + if (adapter->hs_activated_manually) { + mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY), + MWIFIEX_ASYNC_CMD); + adapter->hs_activated_manually = false; + } + mwifiex_process_bypass_tx(adapter); if (adapter->hs_activated) { clear_bit(MWIFIEX_IS_HS_CONFIGURED, @@ -434,6 +446,12 @@ process_start: !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter) && !mwifiex_is_tdls_chan_switching (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) { + if (adapter->hs_activated_manually) { + mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY), + MWIFIEX_ASYNC_CMD); + adapter->hs_activated_manually = false; + } + mwifiex_wmm_process_tx(adapter); if (adapter->hs_activated) { clear_bit(MWIFIEX_IS_HS_CONFIGURED, @@ -498,13 +516,11 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter) static void mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter) { if (adapter->workqueue) { - flush_workqueue(adapter->workqueue); destroy_workqueue(adapter->workqueue); adapter->workqueue = NULL; } if (adapter->rx_workqueue) { - flush_workqueue(adapter->rx_workqueue); destroy_workqueue(adapter->rx_workqueue); adapter->rx_workqueue = NULL; } @@ -987,7 +1003,7 @@ int mwifiex_set_mac_address(struct mwifiex_private *priv, return ret; } - ether_addr_copy(dev->dev_addr, priv->curr_addr); + eth_hw_addr_set(dev, priv->curr_addr); return 0; } diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 5923c5c14c8d..90012cbcfd15 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -986,6 +986,7 @@ struct mwifiex_adapter { struct timer_list wakeup_timer; struct mwifiex_hs_config_param hs_cfg; u8 hs_activated; + u8 hs_activated_manually; u16 hs_activate_wait_q_woken; wait_queue_head_t hs_activate_wait_q; u8 event_body[MAX_EVENT_SIZE]; diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index c6ccce426b49..c3f5583ea70d 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -17,6 +17,7 @@ * this warranty disclaimer. */ +#include <linux/iopoll.h> #include <linux/firmware.h> #include "decl.h" @@ -647,11 +648,15 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, "max count reached while accessing sleep cookie\n"); } +#define N_WAKEUP_TRIES_SHORT_INTERVAL 15 +#define N_WAKEUP_TRIES_LONG_INTERVAL 35 + /* This function wakes up the card by reading fw_status register. */ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + int retval; mwifiex_dbg(adapter, EVENT, "event: Wakeup device...\n"); @@ -659,11 +664,24 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) if (reg->sleep_cookie) mwifiex_pcie_dev_wakeup_delay(adapter); - /* Accessing fw_status register will wakeup device */ - if (mwifiex_write_reg(adapter, reg->fw_status, FIRMWARE_READY_PCIE)) { - mwifiex_dbg(adapter, ERROR, - "Writing fw_status register failed\n"); - return -1; + /* The 88W8897 PCIe+USB firmware (latest version 15.68.19.p21) sometimes + * appears to ignore or miss our wakeup request, so we continue trying + * until we receive an interrupt from the card. + */ + if (read_poll_timeout(mwifiex_write_reg, retval, + READ_ONCE(adapter->int_status) != 0, + 500, 500 * N_WAKEUP_TRIES_SHORT_INTERVAL, + false, + adapter, reg->fw_status, FIRMWARE_READY_PCIE)) { + if (read_poll_timeout(mwifiex_write_reg, retval, + READ_ONCE(adapter->int_status) != 0, + 10000, 10000 * N_WAKEUP_TRIES_LONG_INTERVAL, + false, + adapter, reg->fw_status, FIRMWARE_READY_PCIE)) { + mwifiex_dbg(adapter, ERROR, + "Firmware didn't wake up\n"); + return -EIO; + } } if (reg->sleep_cookie) { @@ -1490,6 +1508,14 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, ret = -1; goto done_unmap; } + + /* The firmware (latest version 15.68.19.p21) of the 88W8897 PCIe+USB card + * seems to crash randomly after setting the TX ring write pointer when + * ASPM powersaving is enabled. A workaround seems to be keeping the bus + * busy by reading a random register afterwards. + */ + mwifiex_read_reg(adapter, PCI_VENDOR_ID, &rx_val); + if ((mwifiex_pcie_txbd_not_full(card)) && tx_param->next_pkt_len) { /* have more packets and TxBD still can hold more */ diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index 48ea00da1fc9..1e2798dce18f 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c @@ -396,6 +396,10 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, if (hs_activate) { hs_cfg->action = cpu_to_le16(HS_ACTIVATE); hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED); + + adapter->hs_activated_manually = true; + mwifiex_dbg(priv->adapter, CMD, + "cmd: Activating host sleep manually\n"); } else { hs_cfg->action = cpu_to_le16(HS_CONFIGURE); hs_cfg->params.hs_config.conditions = hscfg_param->conditions; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_tx.c b/drivers/net/wireless/marvell/mwifiex/sta_tx.c index 241305377e20..a9b5eb992220 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_tx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_tx.c @@ -62,8 +62,8 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; - pad = ((void *)skb->data - (sizeof(*local_tx_pd) + hroom)- - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1); + pad = ((uintptr_t)skb->data - (sizeof(*local_tx_pd) + hroom)) & + (MWIFIEX_DMA_ALIGN_SZ - 1); skb_push(skb, sizeof(*local_tx_pd) + pad); local_tx_pd = (struct txpd *) skb->data; diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c index 9121447e2701..2e25d72dcac5 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_event.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c @@ -197,8 +197,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) mwifiex_dbg(adapter, EVENT, "AP EVENT: event id: %#x\n", eventcause); priv->port_open = false; - memcpy(priv->netdev->dev_addr, adapter->event_body + 2, - ETH_ALEN); + eth_hw_addr_set(priv->netdev, adapter->event_body + 2); if (priv->hist_data) mwifiex_hist_data_reset(priv); mwifiex_check_uap_capabilities(priv, adapter->event_skb); diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index 9bbdb8dfce62..245ff644f81e 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -475,8 +475,8 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; - pad = ((void *)skb->data - (sizeof(*txpd) + hroom) - NULL) & - (MWIFIEX_DMA_ALIGN_SZ - 1); + pad = ((uintptr_t)skb->data - (sizeof(*txpd) + hroom)) & + (MWIFIEX_DMA_ALIGN_SZ - 1); skb_push(skb, sizeof(*txpd) + pad); diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c index 426e39d4ccf0..9736aa0ab7fd 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.c +++ b/drivers/net/wireless/marvell/mwifiex/usb.c @@ -505,6 +505,22 @@ static int mwifiex_usb_probe(struct usb_interface *intf, } } + switch (card->usb_boot_state) { + case USB8XXX_FW_DNLD: + /* Reject broken descriptors. */ + if (!card->rx_cmd_ep || !card->tx_cmd_ep) + return -ENODEV; + if (card->bulk_out_maxpktsize == 0) + return -ENODEV; + break; + case USB8XXX_FW_READY: + /* Assume the driver can handle missing endpoints for now. */ + break; + default: + WARN_ON(1); + return -ENODEV; + } + usb_set_intfdata(intf, card); ret = mwifiex_add_card(card, &card->fw_done, &usb_ops, diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c index 3bf6571f4149..529e325498cd 100644 --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c @@ -5800,8 +5800,8 @@ static void mwl8k_fw_state_machine(const struct firmware *fw, void *context) fail: priv->fw_state = FW_STATE_ERROR; complete(&priv->firmware_loading_complete); - device_release_driver(&priv->pdev->dev); mwl8k_release_firmware(priv); + device_release_driver(&priv->pdev->dev); } #define MAX_RESTART_ATTEMPTS 1 |