brintos

brintos / linux-shallow public Read only

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