109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2f988d640SKalle Valo /* 3f988d640SKalle Valo * This file contains the major functions in WLAN 4f988d640SKalle Valo * driver. It includes init, exit, open, close and main 5f988d640SKalle Valo * thread etc.. 6f988d640SKalle Valo */ 7f988d640SKalle Valo 8f988d640SKalle Valo #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9f988d640SKalle Valo 10f988d640SKalle Valo #include <linux/module.h> 11f988d640SKalle Valo #include <linux/delay.h> 12f988d640SKalle Valo #include <linux/etherdevice.h> 13f988d640SKalle Valo #include <linux/hardirq.h> 14f988d640SKalle Valo #include <linux/netdevice.h> 15f988d640SKalle Valo #include <linux/if_arp.h> 16f988d640SKalle Valo #include <linux/kthread.h> 17f988d640SKalle Valo #include <linux/kfifo.h> 18f988d640SKalle Valo #include <linux/slab.h> 19f988d640SKalle Valo #include <net/cfg80211.h> 20f988d640SKalle Valo 21f988d640SKalle Valo #include "host.h" 22f988d640SKalle Valo #include "decl.h" 23f988d640SKalle Valo #include "dev.h" 24f988d640SKalle Valo #include "cfg.h" 25f988d640SKalle Valo #include "debugfs.h" 26f988d640SKalle Valo #include "cmd.h" 27f988d640SKalle Valo #include "mesh.h" 28f988d640SKalle Valo 29f988d640SKalle Valo #define DRIVER_RELEASE_VERSION "323.p0" 30f988d640SKalle Valo const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION 31f988d640SKalle Valo #ifdef DEBUG 32f988d640SKalle Valo "-dbg" 33f988d640SKalle Valo #endif 34f988d640SKalle Valo ""; 35f988d640SKalle Valo 36f988d640SKalle Valo 37f988d640SKalle Valo /* Module parameters */ 38f988d640SKalle Valo unsigned int lbs_debug; 39f988d640SKalle Valo EXPORT_SYMBOL_GPL(lbs_debug); 40f988d640SKalle Valo module_param_named(libertas_debug, lbs_debug, int, 0644); 41f988d640SKalle Valo 42f988d640SKalle Valo unsigned int lbs_disablemesh; 43f988d640SKalle Valo EXPORT_SYMBOL_GPL(lbs_disablemesh); 44f988d640SKalle Valo module_param_named(libertas_disablemesh, lbs_disablemesh, int, 0644); 45f988d640SKalle Valo 46f988d640SKalle Valo 47f988d640SKalle Valo /* 48f988d640SKalle Valo * This global structure is used to send the confirm_sleep command as 49f988d640SKalle Valo * fast as possible down to the firmware. 50f988d640SKalle Valo */ 51f988d640SKalle Valo struct cmd_confirm_sleep confirm_sleep; 52f988d640SKalle Valo 53f988d640SKalle Valo 54f988d640SKalle Valo /* 55f988d640SKalle Valo * the table to keep region code 56f988d640SKalle Valo */ 57f988d640SKalle Valo u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] = 58f988d640SKalle Valo { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; 59f988d640SKalle Valo 60f988d640SKalle Valo /* 61f988d640SKalle Valo * FW rate table. FW refers to rates by their index in this table, not by the 62f988d640SKalle Valo * rate value itself. Values of 0x00 are 63f988d640SKalle Valo * reserved positions. 64f988d640SKalle Valo */ 65f988d640SKalle Valo static u8 fw_data_rates[MAX_RATES] = 66f988d640SKalle Valo { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, 67f988d640SKalle Valo 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00 68f988d640SKalle Valo }; 69f988d640SKalle Valo 70f988d640SKalle Valo /** 71f988d640SKalle Valo * lbs_fw_index_to_data_rate - use index to get the data rate 72f988d640SKalle Valo * 73f988d640SKalle Valo * @idx: The index of data rate 74f988d640SKalle Valo * returns: data rate or 0 75f988d640SKalle Valo */ 76f988d640SKalle Valo u32 lbs_fw_index_to_data_rate(u8 idx) 77f988d640SKalle Valo { 78f988d640SKalle Valo if (idx >= sizeof(fw_data_rates)) 79f988d640SKalle Valo idx = 0; 80f988d640SKalle Valo return fw_data_rates[idx]; 81f988d640SKalle Valo } 82f988d640SKalle Valo 83f988d640SKalle Valo /** 84f988d640SKalle Valo * lbs_data_rate_to_fw_index - use rate to get the index 85f988d640SKalle Valo * 86f988d640SKalle Valo * @rate: data rate 87f988d640SKalle Valo * returns: index or 0 88f988d640SKalle Valo */ 89f988d640SKalle Valo u8 lbs_data_rate_to_fw_index(u32 rate) 90f988d640SKalle Valo { 91f988d640SKalle Valo u8 i; 92f988d640SKalle Valo 93f988d640SKalle Valo if (!rate) 94f988d640SKalle Valo return 0; 95f988d640SKalle Valo 96f988d640SKalle Valo for (i = 0; i < sizeof(fw_data_rates); i++) { 97f988d640SKalle Valo if (rate == fw_data_rates[i]) 98f988d640SKalle Valo return i; 99f988d640SKalle Valo } 100f988d640SKalle Valo return 0; 101f988d640SKalle Valo } 102f988d640SKalle Valo 103f988d640SKalle Valo int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type) 104f988d640SKalle Valo { 105f988d640SKalle Valo int ret = 0; 106f988d640SKalle Valo 107f988d640SKalle Valo switch (type) { 108f988d640SKalle Valo case NL80211_IFTYPE_MONITOR: 109f988d640SKalle Valo ret = lbs_set_monitor_mode(priv, 1); 110f988d640SKalle Valo break; 111f988d640SKalle Valo case NL80211_IFTYPE_STATION: 112f988d640SKalle Valo if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) 113f988d640SKalle Valo ret = lbs_set_monitor_mode(priv, 0); 114f988d640SKalle Valo if (!ret) 115f988d640SKalle Valo ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1); 116f988d640SKalle Valo break; 117f988d640SKalle Valo case NL80211_IFTYPE_ADHOC: 118f988d640SKalle Valo if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) 119f988d640SKalle Valo ret = lbs_set_monitor_mode(priv, 0); 120f988d640SKalle Valo if (!ret) 121f988d640SKalle Valo ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2); 122f988d640SKalle Valo break; 123f988d640SKalle Valo default: 124f988d640SKalle Valo ret = -ENOTSUPP; 125f988d640SKalle Valo } 126f988d640SKalle Valo return ret; 127f988d640SKalle Valo } 128f988d640SKalle Valo 129f988d640SKalle Valo int lbs_start_iface(struct lbs_private *priv) 130f988d640SKalle Valo { 131f988d640SKalle Valo struct cmd_ds_802_11_mac_address cmd; 132f988d640SKalle Valo int ret; 133f988d640SKalle Valo 134f988d640SKalle Valo if (priv->power_restore) { 135f988d640SKalle Valo ret = priv->power_restore(priv); 136f988d640SKalle Valo if (ret) 137f988d640SKalle Valo return ret; 138f988d640SKalle Valo } 139f988d640SKalle Valo 140f988d640SKalle Valo cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 141f988d640SKalle Valo cmd.action = cpu_to_le16(CMD_ACT_SET); 142f988d640SKalle Valo memcpy(cmd.macadd, priv->current_addr, ETH_ALEN); 143f988d640SKalle Valo 144f988d640SKalle Valo ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd); 145f988d640SKalle Valo if (ret) { 146f988d640SKalle Valo lbs_deb_net("set MAC address failed\n"); 147f988d640SKalle Valo goto err; 148f988d640SKalle Valo } 149f988d640SKalle Valo 150f988d640SKalle Valo ret = lbs_set_iface_type(priv, priv->wdev->iftype); 151f988d640SKalle Valo if (ret) { 152f988d640SKalle Valo lbs_deb_net("set iface type failed\n"); 153f988d640SKalle Valo goto err; 154f988d640SKalle Valo } 155f988d640SKalle Valo 156f988d640SKalle Valo ret = lbs_set_11d_domain_info(priv); 157f988d640SKalle Valo if (ret) { 158f988d640SKalle Valo lbs_deb_net("set 11d domain info failed\n"); 159f988d640SKalle Valo goto err; 160f988d640SKalle Valo } 161f988d640SKalle Valo 162f988d640SKalle Valo lbs_update_channel(priv); 163f988d640SKalle Valo 164f988d640SKalle Valo priv->iface_running = true; 165f988d640SKalle Valo return 0; 166f988d640SKalle Valo 167f988d640SKalle Valo err: 168f988d640SKalle Valo if (priv->power_save) 169f988d640SKalle Valo priv->power_save(priv); 170f988d640SKalle Valo return ret; 171f988d640SKalle Valo } 172f988d640SKalle Valo 173f988d640SKalle Valo /** 174f988d640SKalle Valo * lbs_dev_open - open the ethX interface 175f988d640SKalle Valo * 176f988d640SKalle Valo * @dev: A pointer to &net_device structure 177f988d640SKalle Valo * returns: 0 or -EBUSY if monitor mode active 178f988d640SKalle Valo */ 179f988d640SKalle Valo static int lbs_dev_open(struct net_device *dev) 180f988d640SKalle Valo { 181f988d640SKalle Valo struct lbs_private *priv = dev->ml_priv; 182f988d640SKalle Valo int ret = 0; 183f988d640SKalle Valo 184f988d640SKalle Valo if (!priv->iface_running) { 185f988d640SKalle Valo ret = lbs_start_iface(priv); 186f988d640SKalle Valo if (ret) 187f988d640SKalle Valo goto out; 188f988d640SKalle Valo } 189f988d640SKalle Valo 190f988d640SKalle Valo spin_lock_irq(&priv->driver_lock); 191f988d640SKalle Valo 192f988d640SKalle Valo netif_carrier_off(dev); 193f988d640SKalle Valo 194f988d640SKalle Valo if (!priv->tx_pending_len) 195f988d640SKalle Valo netif_wake_queue(dev); 196f988d640SKalle Valo 197f988d640SKalle Valo spin_unlock_irq(&priv->driver_lock); 198f988d640SKalle Valo 199f988d640SKalle Valo out: 200f988d640SKalle Valo return ret; 201f988d640SKalle Valo } 202f988d640SKalle Valo 203f988d640SKalle Valo static bool lbs_command_queue_empty(struct lbs_private *priv) 204f988d640SKalle Valo { 205f988d640SKalle Valo unsigned long flags; 206f988d640SKalle Valo bool ret; 207f988d640SKalle Valo spin_lock_irqsave(&priv->driver_lock, flags); 208f988d640SKalle Valo ret = priv->cur_cmd == NULL && list_empty(&priv->cmdpendingq); 209f988d640SKalle Valo spin_unlock_irqrestore(&priv->driver_lock, flags); 210f988d640SKalle Valo return ret; 211f988d640SKalle Valo } 212f988d640SKalle Valo 213f988d640SKalle Valo int lbs_stop_iface(struct lbs_private *priv) 214f988d640SKalle Valo { 215f988d640SKalle Valo unsigned long flags; 216f988d640SKalle Valo int ret = 0; 217f988d640SKalle Valo 218f988d640SKalle Valo spin_lock_irqsave(&priv->driver_lock, flags); 219f988d640SKalle Valo priv->iface_running = false; 220f988d640SKalle Valo kfree_skb(priv->currenttxskb); 221f988d640SKalle Valo priv->currenttxskb = NULL; 222f988d640SKalle Valo priv->tx_pending_len = 0; 223f988d640SKalle Valo spin_unlock_irqrestore(&priv->driver_lock, flags); 224f988d640SKalle Valo 225f988d640SKalle Valo cancel_work_sync(&priv->mcast_work); 226f988d640SKalle Valo del_timer_sync(&priv->tx_lockup_timer); 227f988d640SKalle Valo 228f988d640SKalle Valo /* Disable command processing, and wait for all commands to complete */ 229f988d640SKalle Valo lbs_deb_main("waiting for commands to complete\n"); 230f988d640SKalle Valo wait_event(priv->waitq, lbs_command_queue_empty(priv)); 231f988d640SKalle Valo lbs_deb_main("all commands completed\n"); 232f988d640SKalle Valo 233f988d640SKalle Valo if (priv->power_save) 234f988d640SKalle Valo ret = priv->power_save(priv); 235f988d640SKalle Valo 236f988d640SKalle Valo return ret; 237f988d640SKalle Valo } 238f988d640SKalle Valo 239f988d640SKalle Valo /** 240f988d640SKalle Valo * lbs_eth_stop - close the ethX interface 241f988d640SKalle Valo * 242f988d640SKalle Valo * @dev: A pointer to &net_device structure 243f988d640SKalle Valo * returns: 0 244f988d640SKalle Valo */ 245f988d640SKalle Valo static int lbs_eth_stop(struct net_device *dev) 246f988d640SKalle Valo { 247f988d640SKalle Valo struct lbs_private *priv = dev->ml_priv; 248f988d640SKalle Valo 249f988d640SKalle Valo if (priv->connect_status == LBS_CONNECTED) 250f988d640SKalle Valo lbs_disconnect(priv, WLAN_REASON_DEAUTH_LEAVING); 251f988d640SKalle Valo 252f988d640SKalle Valo spin_lock_irq(&priv->driver_lock); 253f988d640SKalle Valo netif_stop_queue(dev); 254f988d640SKalle Valo spin_unlock_irq(&priv->driver_lock); 255f988d640SKalle Valo 256f988d640SKalle Valo lbs_update_mcast(priv); 257f988d640SKalle Valo cancel_delayed_work_sync(&priv->scan_work); 258f988d640SKalle Valo if (priv->scan_req) 259f988d640SKalle Valo lbs_scan_done(priv); 260f988d640SKalle Valo 261f988d640SKalle Valo netif_carrier_off(priv->dev); 262f988d640SKalle Valo 263f988d640SKalle Valo if (!lbs_iface_active(priv)) 264f988d640SKalle Valo lbs_stop_iface(priv); 265f988d640SKalle Valo 266f988d640SKalle Valo return 0; 267f988d640SKalle Valo } 268f988d640SKalle Valo 269f988d640SKalle Valo void lbs_host_to_card_done(struct lbs_private *priv) 270f988d640SKalle Valo { 271f988d640SKalle Valo unsigned long flags; 272f988d640SKalle Valo 273f988d640SKalle Valo spin_lock_irqsave(&priv->driver_lock, flags); 274f988d640SKalle Valo del_timer(&priv->tx_lockup_timer); 275f988d640SKalle Valo 276f988d640SKalle Valo priv->dnld_sent = DNLD_RES_RECEIVED; 277f988d640SKalle Valo 278f988d640SKalle Valo /* Wake main thread if commands are pending */ 279f988d640SKalle Valo if (!priv->cur_cmd || priv->tx_pending_len > 0) { 280f988d640SKalle Valo if (!priv->wakeup_dev_required) 281f988d640SKalle Valo wake_up(&priv->waitq); 282f988d640SKalle Valo } 283f988d640SKalle Valo 284f988d640SKalle Valo spin_unlock_irqrestore(&priv->driver_lock, flags); 285f988d640SKalle Valo } 286f988d640SKalle Valo EXPORT_SYMBOL_GPL(lbs_host_to_card_done); 287f988d640SKalle Valo 288f988d640SKalle Valo int lbs_set_mac_address(struct net_device *dev, void *addr) 289f988d640SKalle Valo { 290f988d640SKalle Valo int ret = 0; 291f988d640SKalle Valo struct lbs_private *priv = dev->ml_priv; 292f988d640SKalle Valo struct sockaddr *phwaddr = addr; 293f988d640SKalle Valo 294f988d640SKalle Valo /* 295f988d640SKalle Valo * Can only set MAC address when all interfaces are down, to be written 296f988d640SKalle Valo * to the hardware when one of them is brought up. 297f988d640SKalle Valo */ 298f988d640SKalle Valo if (lbs_iface_active(priv)) 299f988d640SKalle Valo return -EBUSY; 300f988d640SKalle Valo 301f988d640SKalle Valo /* In case it was called from the mesh device */ 302f988d640SKalle Valo dev = priv->dev; 303f988d640SKalle Valo 304f988d640SKalle Valo memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN); 305*708884e7SJakub Kicinski eth_hw_addr_set(dev, phwaddr->sa_data); 306f988d640SKalle Valo if (priv->mesh_dev) 307*708884e7SJakub Kicinski eth_hw_addr_set(priv->mesh_dev, phwaddr->sa_data); 308f988d640SKalle Valo 309f988d640SKalle Valo return ret; 310f988d640SKalle Valo } 311f988d640SKalle Valo 312f988d640SKalle Valo 313f988d640SKalle Valo static inline int mac_in_list(unsigned char *list, int list_len, 314f988d640SKalle Valo unsigned char *mac) 315f988d640SKalle Valo { 316f988d640SKalle Valo while (list_len) { 317f988d640SKalle Valo if (!memcmp(list, mac, ETH_ALEN)) 318f988d640SKalle Valo return 1; 319f988d640SKalle Valo list += ETH_ALEN; 320f988d640SKalle Valo list_len--; 321f988d640SKalle Valo } 322f988d640SKalle Valo return 0; 323f988d640SKalle Valo } 324f988d640SKalle Valo 325f988d640SKalle Valo 326f988d640SKalle Valo static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, 327f988d640SKalle Valo struct net_device *dev, int nr_addrs) 328f988d640SKalle Valo { 329f988d640SKalle Valo int i = nr_addrs; 330f988d640SKalle Valo struct netdev_hw_addr *ha; 331f988d640SKalle Valo int cnt; 332f988d640SKalle Valo 333f988d640SKalle Valo if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST)) 334f988d640SKalle Valo return nr_addrs; 335f988d640SKalle Valo 336f988d640SKalle Valo netif_addr_lock_bh(dev); 337f988d640SKalle Valo cnt = netdev_mc_count(dev); 338f988d640SKalle Valo netdev_for_each_mc_addr(ha, dev) { 339f988d640SKalle Valo if (mac_in_list(cmd->maclist, nr_addrs, ha->addr)) { 340f988d640SKalle Valo lbs_deb_net("mcast address %s:%pM skipped\n", dev->name, 341f988d640SKalle Valo ha->addr); 342f988d640SKalle Valo cnt--; 343f988d640SKalle Valo continue; 344f988d640SKalle Valo } 345f988d640SKalle Valo 346f988d640SKalle Valo if (i == MRVDRV_MAX_MULTICAST_LIST_SIZE) 347f988d640SKalle Valo break; 348f988d640SKalle Valo memcpy(&cmd->maclist[6*i], ha->addr, ETH_ALEN); 349f988d640SKalle Valo lbs_deb_net("mcast address %s:%pM added to filter\n", dev->name, 350f988d640SKalle Valo ha->addr); 351f988d640SKalle Valo i++; 352f988d640SKalle Valo cnt--; 353f988d640SKalle Valo } 354f988d640SKalle Valo netif_addr_unlock_bh(dev); 355f988d640SKalle Valo if (cnt) 356f988d640SKalle Valo return -EOVERFLOW; 357f988d640SKalle Valo 358f988d640SKalle Valo return i; 359f988d640SKalle Valo } 360f988d640SKalle Valo 361f988d640SKalle Valo void lbs_update_mcast(struct lbs_private *priv) 362f988d640SKalle Valo { 363f988d640SKalle Valo struct cmd_ds_mac_multicast_adr mcast_cmd; 364f988d640SKalle Valo int dev_flags = 0; 365f988d640SKalle Valo int nr_addrs; 366f988d640SKalle Valo int old_mac_control = priv->mac_control; 367f988d640SKalle Valo 368f988d640SKalle Valo if (netif_running(priv->dev)) 369f988d640SKalle Valo dev_flags |= priv->dev->flags; 370f988d640SKalle Valo if (priv->mesh_dev && netif_running(priv->mesh_dev)) 371f988d640SKalle Valo dev_flags |= priv->mesh_dev->flags; 372f988d640SKalle Valo 373f988d640SKalle Valo if (dev_flags & IFF_PROMISC) { 374f988d640SKalle Valo priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE; 375f988d640SKalle Valo priv->mac_control &= ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | 376f988d640SKalle Valo CMD_ACT_MAC_MULTICAST_ENABLE); 377f988d640SKalle Valo goto out_set_mac_control; 378f988d640SKalle Valo } else if (dev_flags & IFF_ALLMULTI) { 379f988d640SKalle Valo do_allmulti: 380f988d640SKalle Valo priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; 381f988d640SKalle Valo priv->mac_control &= ~(CMD_ACT_MAC_PROMISCUOUS_ENABLE | 382f988d640SKalle Valo CMD_ACT_MAC_MULTICAST_ENABLE); 383f988d640SKalle Valo goto out_set_mac_control; 384f988d640SKalle Valo } 385f988d640SKalle Valo 386f988d640SKalle Valo /* Once for priv->dev, again for priv->mesh_dev if it exists */ 387f988d640SKalle Valo nr_addrs = lbs_add_mcast_addrs(&mcast_cmd, priv->dev, 0); 388f988d640SKalle Valo if (nr_addrs >= 0 && priv->mesh_dev) 389f988d640SKalle Valo nr_addrs = lbs_add_mcast_addrs(&mcast_cmd, priv->mesh_dev, nr_addrs); 390f988d640SKalle Valo if (nr_addrs < 0) 391f988d640SKalle Valo goto do_allmulti; 392f988d640SKalle Valo 393f988d640SKalle Valo if (nr_addrs) { 394f988d640SKalle Valo int size = offsetof(struct cmd_ds_mac_multicast_adr, 395f988d640SKalle Valo maclist[6*nr_addrs]); 396f988d640SKalle Valo 397f988d640SKalle Valo mcast_cmd.action = cpu_to_le16(CMD_ACT_SET); 398f988d640SKalle Valo mcast_cmd.hdr.size = cpu_to_le16(size); 399f988d640SKalle Valo mcast_cmd.nr_of_adrs = cpu_to_le16(nr_addrs); 400f988d640SKalle Valo 401f988d640SKalle Valo lbs_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &mcast_cmd.hdr, size); 402f988d640SKalle Valo 403f988d640SKalle Valo priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; 404f988d640SKalle Valo } else 405f988d640SKalle Valo priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; 406f988d640SKalle Valo 407f988d640SKalle Valo priv->mac_control &= ~(CMD_ACT_MAC_PROMISCUOUS_ENABLE | 408f988d640SKalle Valo CMD_ACT_MAC_ALL_MULTICAST_ENABLE); 409f988d640SKalle Valo out_set_mac_control: 410f988d640SKalle Valo if (priv->mac_control != old_mac_control) 411f988d640SKalle Valo lbs_set_mac_control(priv); 412f988d640SKalle Valo } 413f988d640SKalle Valo 414f988d640SKalle Valo static void lbs_set_mcast_worker(struct work_struct *work) 415f988d640SKalle Valo { 416f988d640SKalle Valo struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work); 417f988d640SKalle Valo lbs_update_mcast(priv); 418f988d640SKalle Valo } 419f988d640SKalle Valo 420f988d640SKalle Valo void lbs_set_multicast_list(struct net_device *dev) 421f988d640SKalle Valo { 422f988d640SKalle Valo struct lbs_private *priv = dev->ml_priv; 423f988d640SKalle Valo 424f988d640SKalle Valo schedule_work(&priv->mcast_work); 425f988d640SKalle Valo } 426f988d640SKalle Valo 427f988d640SKalle Valo /** 428f988d640SKalle Valo * lbs_thread - handles the major jobs in the LBS driver. 429f988d640SKalle Valo * It handles all events generated by firmware, RX data received 430f988d640SKalle Valo * from firmware and TX data sent from kernel. 431f988d640SKalle Valo * 432f988d640SKalle Valo * @data: A pointer to &lbs_thread structure 433f988d640SKalle Valo * returns: 0 434f988d640SKalle Valo */ 435f988d640SKalle Valo static int lbs_thread(void *data) 436f988d640SKalle Valo { 437f988d640SKalle Valo struct net_device *dev = data; 438f988d640SKalle Valo struct lbs_private *priv = dev->ml_priv; 439ac6424b9SIngo Molnar wait_queue_entry_t wait; 440f988d640SKalle Valo 441f988d640SKalle Valo init_waitqueue_entry(&wait, current); 442f988d640SKalle Valo 443f988d640SKalle Valo for (;;) { 444f988d640SKalle Valo int shouldsleep; 445f988d640SKalle Valo u8 resp_idx; 446f988d640SKalle Valo 447f988d640SKalle Valo lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n", 448f988d640SKalle Valo priv->currenttxskb, priv->dnld_sent); 449f988d640SKalle Valo 450f988d640SKalle Valo add_wait_queue(&priv->waitq, &wait); 451f988d640SKalle Valo set_current_state(TASK_INTERRUPTIBLE); 452f988d640SKalle Valo spin_lock_irq(&priv->driver_lock); 453f988d640SKalle Valo 454f988d640SKalle Valo if (kthread_should_stop()) 455f988d640SKalle Valo shouldsleep = 0; /* Bye */ 456f988d640SKalle Valo else if (priv->surpriseremoved) 457f988d640SKalle Valo shouldsleep = 1; /* We need to wait until we're _told_ to die */ 458f988d640SKalle Valo else if (priv->psstate == PS_STATE_SLEEP) 459f988d640SKalle Valo shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ 460f988d640SKalle Valo else if (priv->cmd_timed_out) 461f988d640SKalle Valo shouldsleep = 0; /* Command timed out. Recover */ 462f988d640SKalle Valo else if (!priv->fw_ready) 463f988d640SKalle Valo shouldsleep = 1; /* Firmware not ready. We're waiting for it */ 464f988d640SKalle Valo else if (priv->dnld_sent) 465f988d640SKalle Valo shouldsleep = 1; /* Something is en route to the device already */ 466f988d640SKalle Valo else if (priv->tx_pending_len > 0) 467f988d640SKalle Valo shouldsleep = 0; /* We've a packet to send */ 468f988d640SKalle Valo else if (priv->resp_len[priv->resp_idx]) 469f988d640SKalle Valo shouldsleep = 0; /* We have a command response */ 470f988d640SKalle Valo else if (priv->cur_cmd) 471f988d640SKalle Valo shouldsleep = 1; /* Can't send a command; one already running */ 472f988d640SKalle Valo else if (!list_empty(&priv->cmdpendingq) && 473f988d640SKalle Valo !(priv->wakeup_dev_required)) 474f988d640SKalle Valo shouldsleep = 0; /* We have a command to send */ 475f988d640SKalle Valo else if (kfifo_len(&priv->event_fifo)) 476f988d640SKalle Valo shouldsleep = 0; /* We have an event to process */ 477f988d640SKalle Valo else 478f988d640SKalle Valo shouldsleep = 1; /* No command */ 479f988d640SKalle Valo 480f988d640SKalle Valo if (shouldsleep) { 481f988d640SKalle Valo lbs_deb_thread("sleeping, connect_status %d, " 482f988d640SKalle Valo "psmode %d, psstate %d\n", 483f988d640SKalle Valo priv->connect_status, 484f988d640SKalle Valo priv->psmode, priv->psstate); 485f988d640SKalle Valo spin_unlock_irq(&priv->driver_lock); 486f988d640SKalle Valo schedule(); 487f988d640SKalle Valo } else 488f988d640SKalle Valo spin_unlock_irq(&priv->driver_lock); 489f988d640SKalle Valo 490f988d640SKalle Valo lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n", 491f988d640SKalle Valo priv->currenttxskb, priv->dnld_sent); 492f988d640SKalle Valo 493f988d640SKalle Valo set_current_state(TASK_RUNNING); 494f988d640SKalle Valo remove_wait_queue(&priv->waitq, &wait); 495f988d640SKalle Valo 496f988d640SKalle Valo lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n", 497f988d640SKalle Valo priv->currenttxskb, priv->dnld_sent); 498f988d640SKalle Valo 499f988d640SKalle Valo if (kthread_should_stop()) { 500f988d640SKalle Valo lbs_deb_thread("break from main thread\n"); 501f988d640SKalle Valo break; 502f988d640SKalle Valo } 503f988d640SKalle Valo 504f988d640SKalle Valo if (priv->surpriseremoved) { 505f988d640SKalle Valo lbs_deb_thread("adapter removed; waiting to die...\n"); 506f988d640SKalle Valo continue; 507f988d640SKalle Valo } 508f988d640SKalle Valo 509f988d640SKalle Valo lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n", 510f988d640SKalle Valo priv->currenttxskb, priv->dnld_sent); 511f988d640SKalle Valo 512f988d640SKalle Valo /* Process any pending command response */ 513f988d640SKalle Valo spin_lock_irq(&priv->driver_lock); 514f988d640SKalle Valo resp_idx = priv->resp_idx; 515f988d640SKalle Valo if (priv->resp_len[resp_idx]) { 516f988d640SKalle Valo spin_unlock_irq(&priv->driver_lock); 517f988d640SKalle Valo lbs_process_command_response(priv, 518f988d640SKalle Valo priv->resp_buf[resp_idx], 519f988d640SKalle Valo priv->resp_len[resp_idx]); 520f988d640SKalle Valo spin_lock_irq(&priv->driver_lock); 521f988d640SKalle Valo priv->resp_len[resp_idx] = 0; 522f988d640SKalle Valo } 523f988d640SKalle Valo spin_unlock_irq(&priv->driver_lock); 524f988d640SKalle Valo 525f988d640SKalle Valo /* Process hardware events, e.g. card removed, link lost */ 526f988d640SKalle Valo spin_lock_irq(&priv->driver_lock); 527f988d640SKalle Valo while (kfifo_len(&priv->event_fifo)) { 528f988d640SKalle Valo u32 event; 529f988d640SKalle Valo 530f988d640SKalle Valo if (kfifo_out(&priv->event_fifo, 531f988d640SKalle Valo (unsigned char *) &event, sizeof(event)) != 532f988d640SKalle Valo sizeof(event)) 533f988d640SKalle Valo break; 534f988d640SKalle Valo spin_unlock_irq(&priv->driver_lock); 535f988d640SKalle Valo lbs_process_event(priv, event); 536f988d640SKalle Valo spin_lock_irq(&priv->driver_lock); 537f988d640SKalle Valo } 538f988d640SKalle Valo spin_unlock_irq(&priv->driver_lock); 539f988d640SKalle Valo 540f988d640SKalle Valo if (priv->wakeup_dev_required) { 541f988d640SKalle Valo lbs_deb_thread("Waking up device...\n"); 542f988d640SKalle Valo /* Wake up device */ 543f988d640SKalle Valo if (priv->exit_deep_sleep(priv)) 544f988d640SKalle Valo lbs_deb_thread("Wakeup device failed\n"); 545f988d640SKalle Valo continue; 546f988d640SKalle Valo } 547f988d640SKalle Valo 548f988d640SKalle Valo /* command timeout stuff */ 549f988d640SKalle Valo if (priv->cmd_timed_out && priv->cur_cmd) { 550f988d640SKalle Valo struct cmd_ctrl_node *cmdnode = priv->cur_cmd; 551f988d640SKalle Valo 552f988d640SKalle Valo netdev_info(dev, "Timeout submitting command 0x%04x\n", 553f988d640SKalle Valo le16_to_cpu(cmdnode->cmdbuf->command)); 554f988d640SKalle Valo lbs_complete_command(priv, cmdnode, -ETIMEDOUT); 555f988d640SKalle Valo 556f988d640SKalle Valo /* Reset card, but only when it isn't in the process 557f988d640SKalle Valo * of being shutdown anyway. */ 558f988d640SKalle Valo if (!dev->dismantle && priv->reset_card) 559f988d640SKalle Valo priv->reset_card(priv); 560f988d640SKalle Valo } 561f988d640SKalle Valo priv->cmd_timed_out = 0; 562f988d640SKalle Valo 563f988d640SKalle Valo if (!priv->fw_ready) 564f988d640SKalle Valo continue; 565f988d640SKalle Valo 566f988d640SKalle Valo /* Check if we need to confirm Sleep Request received previously */ 567f988d640SKalle Valo if (priv->psstate == PS_STATE_PRE_SLEEP && 568f988d640SKalle Valo !priv->dnld_sent && !priv->cur_cmd) { 569f988d640SKalle Valo if (priv->connect_status == LBS_CONNECTED) { 570f988d640SKalle Valo lbs_deb_thread("pre-sleep, currenttxskb %p, " 571f988d640SKalle Valo "dnld_sent %d, cur_cmd %p\n", 572f988d640SKalle Valo priv->currenttxskb, priv->dnld_sent, 573f988d640SKalle Valo priv->cur_cmd); 574f988d640SKalle Valo 575f988d640SKalle Valo lbs_ps_confirm_sleep(priv); 576f988d640SKalle Valo } else { 577f988d640SKalle Valo /* workaround for firmware sending 578f988d640SKalle Valo * deauth/linkloss event immediately 579f988d640SKalle Valo * after sleep request; remove this 580f988d640SKalle Valo * after firmware fixes it 581f988d640SKalle Valo */ 582f988d640SKalle Valo priv->psstate = PS_STATE_AWAKE; 583f988d640SKalle Valo netdev_alert(dev, 584f988d640SKalle Valo "ignore PS_SleepConfirm in non-connected state\n"); 585f988d640SKalle Valo } 586f988d640SKalle Valo } 587f988d640SKalle Valo 588f988d640SKalle Valo /* The PS state is changed during processing of Sleep Request 589f988d640SKalle Valo * event above 590f988d640SKalle Valo */ 591f988d640SKalle Valo if ((priv->psstate == PS_STATE_SLEEP) || 592f988d640SKalle Valo (priv->psstate == PS_STATE_PRE_SLEEP)) 593f988d640SKalle Valo continue; 594f988d640SKalle Valo 595f988d640SKalle Valo if (priv->is_deep_sleep) 596f988d640SKalle Valo continue; 597f988d640SKalle Valo 598f988d640SKalle Valo /* Execute the next command */ 599f988d640SKalle Valo if (!priv->dnld_sent && !priv->cur_cmd) 600f988d640SKalle Valo lbs_execute_next_command(priv); 601f988d640SKalle Valo 602f988d640SKalle Valo spin_lock_irq(&priv->driver_lock); 603f988d640SKalle Valo if (!priv->dnld_sent && priv->tx_pending_len > 0) { 604f988d640SKalle Valo int ret = priv->hw_host_to_card(priv, MVMS_DAT, 605f988d640SKalle Valo priv->tx_pending_buf, 606f988d640SKalle Valo priv->tx_pending_len); 607f988d640SKalle Valo if (ret) { 608f988d640SKalle Valo lbs_deb_tx("host_to_card failed %d\n", ret); 609f988d640SKalle Valo priv->dnld_sent = DNLD_RES_RECEIVED; 610f988d640SKalle Valo } else { 611f988d640SKalle Valo mod_timer(&priv->tx_lockup_timer, 612f988d640SKalle Valo jiffies + (HZ * 5)); 613f988d640SKalle Valo } 614f988d640SKalle Valo priv->tx_pending_len = 0; 615f988d640SKalle Valo if (!priv->currenttxskb) { 616f988d640SKalle Valo /* We can wake the queues immediately if we aren't 617f988d640SKalle Valo waiting for TX feedback */ 618f988d640SKalle Valo if (priv->connect_status == LBS_CONNECTED) 619f988d640SKalle Valo netif_wake_queue(priv->dev); 620f988d640SKalle Valo if (priv->mesh_dev && 621f988d640SKalle Valo netif_running(priv->mesh_dev)) 622f988d640SKalle Valo netif_wake_queue(priv->mesh_dev); 623f988d640SKalle Valo } 624f988d640SKalle Valo } 625f988d640SKalle Valo spin_unlock_irq(&priv->driver_lock); 626f988d640SKalle Valo } 627f988d640SKalle Valo 628f988d640SKalle Valo del_timer(&priv->command_timer); 629f988d640SKalle Valo del_timer(&priv->tx_lockup_timer); 630f988d640SKalle Valo del_timer(&priv->auto_deepsleep_timer); 631f988d640SKalle Valo 632f988d640SKalle Valo return 0; 633f988d640SKalle Valo } 634f988d640SKalle Valo 635f988d640SKalle Valo /** 636f988d640SKalle Valo * lbs_setup_firmware - gets the HW spec from the firmware and sets 637f988d640SKalle Valo * some basic parameters 638f988d640SKalle Valo * 639f988d640SKalle Valo * @priv: A pointer to &struct lbs_private structure 640f988d640SKalle Valo * returns: 0 or -1 641f988d640SKalle Valo */ 642f988d640SKalle Valo static int lbs_setup_firmware(struct lbs_private *priv) 643f988d640SKalle Valo { 644f988d640SKalle Valo int ret = -1; 645f988d640SKalle Valo s16 curlevel = 0, minlevel = 0, maxlevel = 0; 646f988d640SKalle Valo 647f988d640SKalle Valo /* Read MAC address from firmware */ 648f988d640SKalle Valo eth_broadcast_addr(priv->current_addr); 649f988d640SKalle Valo ret = lbs_update_hw_spec(priv); 650f988d640SKalle Valo if (ret) 651f988d640SKalle Valo goto done; 652f988d640SKalle Valo 653f988d640SKalle Valo /* Read power levels if available */ 654f988d640SKalle Valo ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel); 655f988d640SKalle Valo if (ret == 0) { 656f988d640SKalle Valo priv->txpower_cur = curlevel; 657f988d640SKalle Valo priv->txpower_min = minlevel; 658f988d640SKalle Valo priv->txpower_max = maxlevel; 659f988d640SKalle Valo } 660f988d640SKalle Valo 661f988d640SKalle Valo /* Send cmd to FW to enable 11D function */ 662f988d640SKalle Valo ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1); 663f988d640SKalle Valo if (ret) 664f988d640SKalle Valo goto done; 665f988d640SKalle Valo 666f988d640SKalle Valo ret = lbs_set_mac_control_sync(priv); 667f988d640SKalle Valo done: 668f988d640SKalle Valo return ret; 669f988d640SKalle Valo } 670f988d640SKalle Valo 671f988d640SKalle Valo int lbs_suspend(struct lbs_private *priv) 672f988d640SKalle Valo { 673f988d640SKalle Valo int ret; 674f988d640SKalle Valo 675f988d640SKalle Valo if (priv->is_deep_sleep) { 676f988d640SKalle Valo ret = lbs_set_deep_sleep(priv, 0); 677f988d640SKalle Valo if (ret) { 678f988d640SKalle Valo netdev_err(priv->dev, 679f988d640SKalle Valo "deep sleep cancellation failed: %d\n", ret); 680f988d640SKalle Valo return ret; 681f988d640SKalle Valo } 682f988d640SKalle Valo priv->deep_sleep_required = 1; 683f988d640SKalle Valo } 684f988d640SKalle Valo 685f988d640SKalle Valo ret = lbs_set_host_sleep(priv, 1); 686f988d640SKalle Valo 687f988d640SKalle Valo netif_device_detach(priv->dev); 688f988d640SKalle Valo if (priv->mesh_dev) 689f988d640SKalle Valo netif_device_detach(priv->mesh_dev); 690f988d640SKalle Valo 691f988d640SKalle Valo return ret; 692f988d640SKalle Valo } 693f988d640SKalle Valo EXPORT_SYMBOL_GPL(lbs_suspend); 694f988d640SKalle Valo 695f988d640SKalle Valo int lbs_resume(struct lbs_private *priv) 696f988d640SKalle Valo { 697f988d640SKalle Valo int ret; 698f988d640SKalle Valo 699f988d640SKalle Valo ret = lbs_set_host_sleep(priv, 0); 700f988d640SKalle Valo 701f988d640SKalle Valo netif_device_attach(priv->dev); 702f988d640SKalle Valo if (priv->mesh_dev) 703f988d640SKalle Valo netif_device_attach(priv->mesh_dev); 704f988d640SKalle Valo 705f988d640SKalle Valo if (priv->deep_sleep_required) { 706f988d640SKalle Valo priv->deep_sleep_required = 0; 707f988d640SKalle Valo ret = lbs_set_deep_sleep(priv, 1); 708f988d640SKalle Valo if (ret) 709f988d640SKalle Valo netdev_err(priv->dev, 710f988d640SKalle Valo "deep sleep activation failed: %d\n", ret); 711f988d640SKalle Valo } 712f988d640SKalle Valo 713f988d640SKalle Valo if (priv->setup_fw_on_resume) 714f988d640SKalle Valo ret = lbs_setup_firmware(priv); 715f988d640SKalle Valo 716f988d640SKalle Valo return ret; 717f988d640SKalle Valo } 718f988d640SKalle Valo EXPORT_SYMBOL_GPL(lbs_resume); 719f988d640SKalle Valo 720f988d640SKalle Valo /** 721f988d640SKalle Valo * lbs_cmd_timeout_handler - handles the timeout of command sending. 722f988d640SKalle Valo * It will re-send the same command again. 723f988d640SKalle Valo * 724f696d724SLee Jones * @t: Context from which to retrieve a &struct lbs_private pointer 725f988d640SKalle Valo */ 72678ce6a90SKees Cook static void lbs_cmd_timeout_handler(struct timer_list *t) 727f988d640SKalle Valo { 72878ce6a90SKees Cook struct lbs_private *priv = from_timer(priv, t, command_timer); 729f988d640SKalle Valo unsigned long flags; 730f988d640SKalle Valo 731f988d640SKalle Valo spin_lock_irqsave(&priv->driver_lock, flags); 732f988d640SKalle Valo 733f988d640SKalle Valo if (!priv->cur_cmd) 734f988d640SKalle Valo goto out; 735f988d640SKalle Valo 736f988d640SKalle Valo netdev_info(priv->dev, "command 0x%04x timed out\n", 737f988d640SKalle Valo le16_to_cpu(priv->cur_cmd->cmdbuf->command)); 738f988d640SKalle Valo 739f988d640SKalle Valo priv->cmd_timed_out = 1; 740f988d640SKalle Valo 741f988d640SKalle Valo /* 742f988d640SKalle Valo * If the device didn't even acknowledge the command, reset the state 743f988d640SKalle Valo * so that we don't block all future commands due to this one timeout. 744f988d640SKalle Valo */ 745f988d640SKalle Valo if (priv->dnld_sent == DNLD_CMD_SENT) 746f988d640SKalle Valo priv->dnld_sent = DNLD_RES_RECEIVED; 747f988d640SKalle Valo 748f988d640SKalle Valo wake_up(&priv->waitq); 749f988d640SKalle Valo out: 750f988d640SKalle Valo spin_unlock_irqrestore(&priv->driver_lock, flags); 751f988d640SKalle Valo } 752f988d640SKalle Valo 753f988d640SKalle Valo /** 754f988d640SKalle Valo * lbs_tx_lockup_handler - handles the timeout of the passing of TX frames 755f988d640SKalle Valo * to the hardware. This is known to frequently happen with SD8686 when 756f988d640SKalle Valo * waking up after a Wake-on-WLAN-triggered resume. 757f988d640SKalle Valo * 758f696d724SLee Jones * @t: Context from which to retrieve a &struct lbs_private pointer 759f988d640SKalle Valo */ 76078ce6a90SKees Cook static void lbs_tx_lockup_handler(struct timer_list *t) 761f988d640SKalle Valo { 76278ce6a90SKees Cook struct lbs_private *priv = from_timer(priv, t, tx_lockup_timer); 763f988d640SKalle Valo unsigned long flags; 764f988d640SKalle Valo 765f988d640SKalle Valo spin_lock_irqsave(&priv->driver_lock, flags); 766f988d640SKalle Valo 767f988d640SKalle Valo netdev_info(priv->dev, "TX lockup detected\n"); 768f988d640SKalle Valo if (priv->reset_card) 769f988d640SKalle Valo priv->reset_card(priv); 770f988d640SKalle Valo 771f988d640SKalle Valo priv->dnld_sent = DNLD_RES_RECEIVED; 772f988d640SKalle Valo wake_up_interruptible(&priv->waitq); 773f988d640SKalle Valo 774f988d640SKalle Valo spin_unlock_irqrestore(&priv->driver_lock, flags); 775f988d640SKalle Valo } 776f988d640SKalle Valo 777f988d640SKalle Valo /** 778f988d640SKalle Valo * auto_deepsleep_timer_fn - put the device back to deep sleep mode when 779f988d640SKalle Valo * timer expires and no activity (command, event, data etc.) is detected. 780f696d724SLee Jones * @t: Context from which to retrieve a &struct lbs_private pointer 781f988d640SKalle Valo * returns: N/A 782f988d640SKalle Valo */ 78378ce6a90SKees Cook static void auto_deepsleep_timer_fn(struct timer_list *t) 784f988d640SKalle Valo { 78578ce6a90SKees Cook struct lbs_private *priv = from_timer(priv, t, auto_deepsleep_timer); 786f988d640SKalle Valo 787f988d640SKalle Valo if (priv->is_activity_detected) { 788f988d640SKalle Valo priv->is_activity_detected = 0; 789f988d640SKalle Valo } else { 790f988d640SKalle Valo if (priv->is_auto_deep_sleep_enabled && 791f988d640SKalle Valo (!priv->wakeup_dev_required) && 792f988d640SKalle Valo (priv->connect_status != LBS_CONNECTED)) { 793f988d640SKalle Valo struct cmd_header cmd; 794f988d640SKalle Valo 795f988d640SKalle Valo lbs_deb_main("Entering auto deep sleep mode...\n"); 796f988d640SKalle Valo memset(&cmd, 0, sizeof(cmd)); 797f988d640SKalle Valo cmd.size = cpu_to_le16(sizeof(cmd)); 798f988d640SKalle Valo lbs_cmd_async(priv, CMD_802_11_DEEP_SLEEP, &cmd, 799f988d640SKalle Valo sizeof(cmd)); 800f988d640SKalle Valo } 801f988d640SKalle Valo } 802f988d640SKalle Valo mod_timer(&priv->auto_deepsleep_timer , jiffies + 803f988d640SKalle Valo (priv->auto_deep_sleep_timeout * HZ)/1000); 804f988d640SKalle Valo } 805f988d640SKalle Valo 806f988d640SKalle Valo int lbs_enter_auto_deep_sleep(struct lbs_private *priv) 807f988d640SKalle Valo { 808f988d640SKalle Valo priv->is_auto_deep_sleep_enabled = 1; 809f988d640SKalle Valo if (priv->is_deep_sleep) 810f988d640SKalle Valo priv->wakeup_dev_required = 1; 811f988d640SKalle Valo mod_timer(&priv->auto_deepsleep_timer , 812f988d640SKalle Valo jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000); 813f988d640SKalle Valo 814f988d640SKalle Valo return 0; 815f988d640SKalle Valo } 816f988d640SKalle Valo 817f988d640SKalle Valo int lbs_exit_auto_deep_sleep(struct lbs_private *priv) 818f988d640SKalle Valo { 819f988d640SKalle Valo priv->is_auto_deep_sleep_enabled = 0; 820f988d640SKalle Valo priv->auto_deep_sleep_timeout = 0; 821f988d640SKalle Valo del_timer(&priv->auto_deepsleep_timer); 822f988d640SKalle Valo 823f988d640SKalle Valo return 0; 824f988d640SKalle Valo } 825f988d640SKalle Valo 826f988d640SKalle Valo static int lbs_init_adapter(struct lbs_private *priv) 827f988d640SKalle Valo { 828f988d640SKalle Valo int ret; 829f988d640SKalle Valo 830f988d640SKalle Valo eth_broadcast_addr(priv->current_addr); 831f988d640SKalle Valo 832f988d640SKalle Valo priv->connect_status = LBS_DISCONNECTED; 833f988d640SKalle Valo priv->channel = DEFAULT_AD_HOC_CHANNEL; 834f988d640SKalle Valo priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; 835f988d640SKalle Valo priv->radio_on = 1; 836f988d640SKalle Valo priv->psmode = LBS802_11POWERMODECAM; 837f988d640SKalle Valo priv->psstate = PS_STATE_FULL_POWER; 838f988d640SKalle Valo priv->is_deep_sleep = 0; 839f988d640SKalle Valo priv->is_auto_deep_sleep_enabled = 0; 840f988d640SKalle Valo priv->deep_sleep_required = 0; 841f988d640SKalle Valo priv->wakeup_dev_required = 0; 842f988d640SKalle Valo init_waitqueue_head(&priv->ds_awake_q); 843f988d640SKalle Valo init_waitqueue_head(&priv->scan_q); 844f988d640SKalle Valo priv->authtype_auto = 1; 845f988d640SKalle Valo priv->is_host_sleep_configured = 0; 846f988d640SKalle Valo priv->is_host_sleep_activated = 0; 847f988d640SKalle Valo init_waitqueue_head(&priv->host_sleep_q); 848f988d640SKalle Valo init_waitqueue_head(&priv->fw_waitq); 849f988d640SKalle Valo mutex_init(&priv->lock); 850f988d640SKalle Valo 85178ce6a90SKees Cook timer_setup(&priv->command_timer, lbs_cmd_timeout_handler, 0); 85278ce6a90SKees Cook timer_setup(&priv->tx_lockup_timer, lbs_tx_lockup_handler, 0); 85378ce6a90SKees Cook timer_setup(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn, 0); 854f988d640SKalle Valo 855f988d640SKalle Valo INIT_LIST_HEAD(&priv->cmdfreeq); 856f988d640SKalle Valo INIT_LIST_HEAD(&priv->cmdpendingq); 857f988d640SKalle Valo 858f988d640SKalle Valo spin_lock_init(&priv->driver_lock); 859f988d640SKalle Valo 860f988d640SKalle Valo /* Allocate the command buffers */ 861f988d640SKalle Valo if (lbs_allocate_cmd_buffer(priv)) { 862f988d640SKalle Valo pr_err("Out of memory allocating command buffers\n"); 863f988d640SKalle Valo ret = -ENOMEM; 864f988d640SKalle Valo goto out; 865f988d640SKalle Valo } 866f988d640SKalle Valo priv->resp_idx = 0; 867f988d640SKalle Valo priv->resp_len[0] = priv->resp_len[1] = 0; 868f988d640SKalle Valo 869f988d640SKalle Valo /* Create the event FIFO */ 870f988d640SKalle Valo ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL); 871f988d640SKalle Valo if (ret) { 872f988d640SKalle Valo pr_err("Out of memory allocating event FIFO buffer\n"); 873f988d640SKalle Valo goto out; 874f988d640SKalle Valo } 875f988d640SKalle Valo 876f988d640SKalle Valo out: 877f988d640SKalle Valo return ret; 878f988d640SKalle Valo } 879f988d640SKalle Valo 880f988d640SKalle Valo static void lbs_free_adapter(struct lbs_private *priv) 881f988d640SKalle Valo { 882f988d640SKalle Valo lbs_free_cmd_buffer(priv); 883f988d640SKalle Valo kfifo_free(&priv->event_fifo); 884f988d640SKalle Valo del_timer(&priv->command_timer); 885f988d640SKalle Valo del_timer(&priv->tx_lockup_timer); 886f988d640SKalle Valo del_timer(&priv->auto_deepsleep_timer); 887f988d640SKalle Valo } 888f988d640SKalle Valo 889f988d640SKalle Valo static const struct net_device_ops lbs_netdev_ops = { 890f988d640SKalle Valo .ndo_open = lbs_dev_open, 891f988d640SKalle Valo .ndo_stop = lbs_eth_stop, 892f988d640SKalle Valo .ndo_start_xmit = lbs_hard_start_xmit, 893f988d640SKalle Valo .ndo_set_mac_address = lbs_set_mac_address, 894f988d640SKalle Valo .ndo_set_rx_mode = lbs_set_multicast_list, 895f988d640SKalle Valo .ndo_validate_addr = eth_validate_addr, 896f988d640SKalle Valo }; 897f988d640SKalle Valo 898f988d640SKalle Valo /** 899f988d640SKalle Valo * lbs_add_card - adds the card. It will probe the 900f988d640SKalle Valo * card, allocate the lbs_priv and initialize the device. 901f988d640SKalle Valo * 902f988d640SKalle Valo * @card: A pointer to card 903f988d640SKalle Valo * @dmdev: A pointer to &struct device 904f988d640SKalle Valo * returns: A pointer to &struct lbs_private structure 905f988d640SKalle Valo */ 906f988d640SKalle Valo struct lbs_private *lbs_add_card(void *card, struct device *dmdev) 907f988d640SKalle Valo { 908f988d640SKalle Valo struct net_device *dev; 909f988d640SKalle Valo struct wireless_dev *wdev; 910f988d640SKalle Valo struct lbs_private *priv = NULL; 911bbc2a101SLubomir Rintel int err; 912f988d640SKalle Valo 913f988d640SKalle Valo /* Allocate an Ethernet device and register it */ 914f988d640SKalle Valo wdev = lbs_cfg_alloc(dmdev); 915f988d640SKalle Valo if (IS_ERR(wdev)) { 916bbc2a101SLubomir Rintel err = PTR_ERR(wdev); 917f988d640SKalle Valo pr_err("cfg80211 init failed\n"); 918bbc2a101SLubomir Rintel goto err_cfg; 919f988d640SKalle Valo } 920f988d640SKalle Valo 921f988d640SKalle Valo wdev->iftype = NL80211_IFTYPE_STATION; 922f988d640SKalle Valo priv = wdev_priv(wdev); 923f988d640SKalle Valo priv->wdev = wdev; 924f988d640SKalle Valo 925bbc2a101SLubomir Rintel err = lbs_init_adapter(priv); 926bbc2a101SLubomir Rintel if (err) { 927f988d640SKalle Valo pr_err("failed to initialize adapter structure\n"); 928f988d640SKalle Valo goto err_wdev; 929f988d640SKalle Valo } 930f988d640SKalle Valo 931f988d640SKalle Valo dev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, ether_setup); 932f988d640SKalle Valo if (!dev) { 933bbc2a101SLubomir Rintel err = -ENOMEM; 934f988d640SKalle Valo dev_err(dmdev, "no memory for network device instance\n"); 935f988d640SKalle Valo goto err_adapter; 936f988d640SKalle Valo } 937f988d640SKalle Valo 938f988d640SKalle Valo dev->ieee80211_ptr = wdev; 939f988d640SKalle Valo dev->ml_priv = priv; 940f988d640SKalle Valo SET_NETDEV_DEV(dev, dmdev); 941f988d640SKalle Valo wdev->netdev = dev; 942f988d640SKalle Valo priv->dev = dev; 943f988d640SKalle Valo 944f988d640SKalle Valo dev->netdev_ops = &lbs_netdev_ops; 945f988d640SKalle Valo dev->watchdog_timeo = 5 * HZ; 946f988d640SKalle Valo dev->ethtool_ops = &lbs_ethtool_ops; 947f988d640SKalle Valo dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 948f988d640SKalle Valo 949f988d640SKalle Valo priv->card = card; 950f988d640SKalle Valo 951f988d640SKalle Valo strcpy(dev->name, "wlan%d"); 952f988d640SKalle Valo 953f988d640SKalle Valo lbs_deb_thread("Starting main thread...\n"); 954f988d640SKalle Valo init_waitqueue_head(&priv->waitq); 955f988d640SKalle Valo priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main"); 956f988d640SKalle Valo if (IS_ERR(priv->main_thread)) { 957bbc2a101SLubomir Rintel err = PTR_ERR(priv->main_thread); 958f988d640SKalle Valo lbs_deb_thread("Error creating main thread.\n"); 959f988d640SKalle Valo goto err_ndev; 960f988d640SKalle Valo } 961f988d640SKalle Valo 962f988d640SKalle Valo priv->work_thread = create_singlethread_workqueue("lbs_worker"); 963f988d640SKalle Valo INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); 964f988d640SKalle Valo 965f988d640SKalle Valo priv->wol_criteria = EHS_REMOVE_WAKEUP; 966f988d640SKalle Valo priv->wol_gpio = 0xff; 967f988d640SKalle Valo priv->wol_gap = 20; 968f988d640SKalle Valo priv->ehs_remove_supported = true; 969f988d640SKalle Valo 970bbc2a101SLubomir Rintel return priv; 971f988d640SKalle Valo 972f988d640SKalle Valo err_ndev: 973f988d640SKalle Valo free_netdev(dev); 974f988d640SKalle Valo 975f988d640SKalle Valo err_adapter: 976f988d640SKalle Valo lbs_free_adapter(priv); 977f988d640SKalle Valo 978f988d640SKalle Valo err_wdev: 979f988d640SKalle Valo lbs_cfg_free(priv); 980f988d640SKalle Valo 981bbc2a101SLubomir Rintel err_cfg: 982bbc2a101SLubomir Rintel return ERR_PTR(err); 983f988d640SKalle Valo } 984f988d640SKalle Valo EXPORT_SYMBOL_GPL(lbs_add_card); 985f988d640SKalle Valo 986f988d640SKalle Valo 987f988d640SKalle Valo void lbs_remove_card(struct lbs_private *priv) 988f988d640SKalle Valo { 989f988d640SKalle Valo struct net_device *dev = priv->dev; 990f988d640SKalle Valo 991f988d640SKalle Valo lbs_remove_mesh(priv); 992f988d640SKalle Valo 993f988d640SKalle Valo if (priv->wiphy_registered) 994f988d640SKalle Valo lbs_scan_deinit(priv); 995f988d640SKalle Valo 996f988d640SKalle Valo lbs_wait_for_firmware_load(priv); 997f988d640SKalle Valo 998f988d640SKalle Valo /* worker thread destruction blocks on the in-flight command which 999f988d640SKalle Valo * should have been cleared already in lbs_stop_card(). 1000f988d640SKalle Valo */ 1001f988d640SKalle Valo lbs_deb_main("destroying worker thread\n"); 1002f988d640SKalle Valo destroy_workqueue(priv->work_thread); 1003f988d640SKalle Valo lbs_deb_main("done destroying worker thread\n"); 1004f988d640SKalle Valo 1005f988d640SKalle Valo if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { 1006f988d640SKalle Valo priv->psmode = LBS802_11POWERMODECAM; 10070b8802dcSAndreas Kemnade /* no need to wakeup if already woken up, 10080b8802dcSAndreas Kemnade * on suspend, this exit ps command is not processed 10090b8802dcSAndreas Kemnade * the driver hangs 10100b8802dcSAndreas Kemnade */ 10110b8802dcSAndreas Kemnade if (priv->psstate != PS_STATE_FULL_POWER) 1012f988d640SKalle Valo lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true); 1013f988d640SKalle Valo } 1014f988d640SKalle Valo 1015f988d640SKalle Valo if (priv->is_deep_sleep) { 1016f988d640SKalle Valo priv->is_deep_sleep = 0; 1017f988d640SKalle Valo wake_up_interruptible(&priv->ds_awake_q); 1018f988d640SKalle Valo } 1019f988d640SKalle Valo 1020f988d640SKalle Valo priv->is_host_sleep_configured = 0; 1021f988d640SKalle Valo priv->is_host_sleep_activated = 0; 1022f988d640SKalle Valo wake_up_interruptible(&priv->host_sleep_q); 1023f988d640SKalle Valo 1024f988d640SKalle Valo /* Stop the thread servicing the interrupts */ 1025f988d640SKalle Valo priv->surpriseremoved = 1; 1026f988d640SKalle Valo kthread_stop(priv->main_thread); 1027f988d640SKalle Valo 1028f988d640SKalle Valo lbs_free_adapter(priv); 1029f988d640SKalle Valo lbs_cfg_free(priv); 1030f988d640SKalle Valo free_netdev(dev); 1031f988d640SKalle Valo } 1032f988d640SKalle Valo EXPORT_SYMBOL_GPL(lbs_remove_card); 1033f988d640SKalle Valo 1034f988d640SKalle Valo 1035f988d640SKalle Valo int lbs_rtap_supported(struct lbs_private *priv) 1036f988d640SKalle Valo { 1037f988d640SKalle Valo if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) 1038f988d640SKalle Valo return 1; 1039f988d640SKalle Valo 1040f988d640SKalle Valo /* newer firmware use a capability mask */ 1041f988d640SKalle Valo return ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && 1042f988d640SKalle Valo (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)); 1043f988d640SKalle Valo } 1044f988d640SKalle Valo 1045f988d640SKalle Valo 1046f988d640SKalle Valo int lbs_start_card(struct lbs_private *priv) 1047f988d640SKalle Valo { 1048f988d640SKalle Valo struct net_device *dev = priv->dev; 10494c8a4685SColin Ian King int ret; 1050f988d640SKalle Valo 1051f988d640SKalle Valo /* poke the firmware */ 1052f988d640SKalle Valo ret = lbs_setup_firmware(priv); 1053f988d640SKalle Valo if (ret) 1054f988d640SKalle Valo goto done; 1055f988d640SKalle Valo 1056f988d640SKalle Valo if (!lbs_disablemesh) 1057f988d640SKalle Valo lbs_init_mesh(priv); 1058f988d640SKalle Valo else 1059f988d640SKalle Valo pr_info("%s: mesh disabled\n", dev->name); 1060f988d640SKalle Valo 10613691ac4aSDan Carpenter ret = lbs_cfg_register(priv); 10623691ac4aSDan Carpenter if (ret) { 1063f988d640SKalle Valo pr_err("cannot register device\n"); 1064f988d640SKalle Valo goto done; 1065f988d640SKalle Valo } 1066f988d640SKalle Valo 1067f988d640SKalle Valo if (lbs_mesh_activated(priv)) 1068f988d640SKalle Valo lbs_start_mesh(priv); 1069f988d640SKalle Valo 1070f988d640SKalle Valo lbs_debugfs_init_one(priv, dev); 1071f988d640SKalle Valo 1072f988d640SKalle Valo netdev_info(dev, "Marvell WLAN 802.11 adapter\n"); 1073f988d640SKalle Valo 1074f988d640SKalle Valo ret = 0; 1075f988d640SKalle Valo 1076f988d640SKalle Valo done: 1077f988d640SKalle Valo return ret; 1078f988d640SKalle Valo } 1079f988d640SKalle Valo EXPORT_SYMBOL_GPL(lbs_start_card); 1080f988d640SKalle Valo 1081f988d640SKalle Valo 1082f988d640SKalle Valo void lbs_stop_card(struct lbs_private *priv) 1083f988d640SKalle Valo { 1084f988d640SKalle Valo struct net_device *dev; 1085f988d640SKalle Valo 1086f988d640SKalle Valo if (!priv) 10874bc606afSKees Cook return; 1088f988d640SKalle Valo dev = priv->dev; 1089f988d640SKalle Valo 1090f988d640SKalle Valo /* If the netdev isn't registered, it means that lbs_start_card() was 1091f988d640SKalle Valo * never called so we have nothing to do here. */ 1092f988d640SKalle Valo if (dev->reg_state != NETREG_REGISTERED) 10934bc606afSKees Cook return; 1094f988d640SKalle Valo 1095f988d640SKalle Valo netif_stop_queue(dev); 1096f988d640SKalle Valo netif_carrier_off(dev); 1097f988d640SKalle Valo 1098f988d640SKalle Valo lbs_debugfs_remove_one(priv); 1099f988d640SKalle Valo lbs_deinit_mesh(priv); 1100f988d640SKalle Valo unregister_netdev(dev); 1101f988d640SKalle Valo } 1102f988d640SKalle Valo EXPORT_SYMBOL_GPL(lbs_stop_card); 1103f988d640SKalle Valo 1104f988d640SKalle Valo 1105f988d640SKalle Valo void lbs_queue_event(struct lbs_private *priv, u32 event) 1106f988d640SKalle Valo { 1107f988d640SKalle Valo unsigned long flags; 1108f988d640SKalle Valo 1109f988d640SKalle Valo spin_lock_irqsave(&priv->driver_lock, flags); 1110f988d640SKalle Valo 1111f988d640SKalle Valo if (priv->psstate == PS_STATE_SLEEP) 1112f988d640SKalle Valo priv->psstate = PS_STATE_AWAKE; 1113f988d640SKalle Valo 1114f988d640SKalle Valo kfifo_in(&priv->event_fifo, (unsigned char *) &event, sizeof(u32)); 1115f988d640SKalle Valo 1116f988d640SKalle Valo wake_up(&priv->waitq); 1117f988d640SKalle Valo 1118f988d640SKalle Valo spin_unlock_irqrestore(&priv->driver_lock, flags); 1119f988d640SKalle Valo } 1120f988d640SKalle Valo EXPORT_SYMBOL_GPL(lbs_queue_event); 1121f988d640SKalle Valo 1122f988d640SKalle Valo void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) 1123f988d640SKalle Valo { 1124f988d640SKalle Valo if (priv->psstate == PS_STATE_SLEEP) 1125f988d640SKalle Valo priv->psstate = PS_STATE_AWAKE; 1126f988d640SKalle Valo 1127f988d640SKalle Valo /* Swap buffers by flipping the response index */ 1128f988d640SKalle Valo BUG_ON(resp_idx > 1); 1129f988d640SKalle Valo priv->resp_idx = resp_idx; 1130f988d640SKalle Valo 1131f988d640SKalle Valo wake_up(&priv->waitq); 1132f988d640SKalle Valo } 1133f988d640SKalle Valo EXPORT_SYMBOL_GPL(lbs_notify_command_response); 1134f988d640SKalle Valo 1135f988d640SKalle Valo static int __init lbs_init_module(void) 1136f988d640SKalle Valo { 1137f988d640SKalle Valo memset(&confirm_sleep, 0, sizeof(confirm_sleep)); 1138f988d640SKalle Valo confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE); 1139f988d640SKalle Valo confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep)); 1140f988d640SKalle Valo confirm_sleep.action = cpu_to_le16(PS_MODE_ACTION_SLEEP_CONFIRMED); 1141f988d640SKalle Valo lbs_debugfs_init(); 11424bc606afSKees Cook 1143f988d640SKalle Valo return 0; 1144f988d640SKalle Valo } 1145f988d640SKalle Valo 1146f988d640SKalle Valo static void __exit lbs_exit_module(void) 1147f988d640SKalle Valo { 1148f988d640SKalle Valo lbs_debugfs_remove(); 1149f988d640SKalle Valo } 1150f988d640SKalle Valo 1151f988d640SKalle Valo module_init(lbs_init_module); 1152f988d640SKalle Valo module_exit(lbs_exit_module); 1153f988d640SKalle Valo 1154f988d640SKalle Valo MODULE_DESCRIPTION("Libertas WLAN Driver Library"); 1155f988d640SKalle Valo MODULE_AUTHOR("Marvell International Ltd."); 1156f988d640SKalle Valo MODULE_LICENSE("GPL"); 1157