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