main.c 35.0 KB
Newer Older
1 2 3 4 5 6
/**
  * This file contains the major functions in WLAN
  * driver. It includes init, exit, open, close and main
  * thread etc..
  */

7
#include <linux/moduleparam.h>
8 9 10 11
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
12
#include <linux/kthread.h>
13 14

#include <net/iw_handler.h>
15
#include <net/ieee80211.h>
16 17 18 19 20 21 22

#include "host.h"
#include "decl.h"
#include "dev.h"
#include "wext.h"
#include "debugfs.h"
#include "assoc.h"
23
#include "join.h"
24
#include "cmd.h"
25

26
#define DRIVER_RELEASE_VERSION "323.p0"
27
const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
28 29 30 31 32
#ifdef  DEBUG
    "-dbg"
#endif
    "";

33 34

/* Module parameters */
35 36 37
unsigned int lbs_debug;
EXPORT_SYMBOL_GPL(lbs_debug);
module_param_named(libertas_debug, lbs_debug, int, 0644);
38 39


40 41 42 43 44
#define LBS_TX_PWR_DEFAULT		20	/*100mW */
#define LBS_TX_PWR_US_DEFAULT		20	/*100mW */
#define LBS_TX_PWR_JP_DEFAULT		16	/*50mW */
#define LBS_TX_PWR_FR_DEFAULT		20	/*100mW */
#define LBS_TX_PWR_EMEA_DEFAULT	20	/*100mW */
45 46 47 48

/* Format { channel, frequency (MHz), maxtxpower } */
/* band: 'B/G', region: USA FCC/Canada IC */
static struct chan_freq_power channel_freq_power_US_BG[] = {
49 50 51 52 53 54 55 56 57 58 59
	{1, 2412, LBS_TX_PWR_US_DEFAULT},
	{2, 2417, LBS_TX_PWR_US_DEFAULT},
	{3, 2422, LBS_TX_PWR_US_DEFAULT},
	{4, 2427, LBS_TX_PWR_US_DEFAULT},
	{5, 2432, LBS_TX_PWR_US_DEFAULT},
	{6, 2437, LBS_TX_PWR_US_DEFAULT},
	{7, 2442, LBS_TX_PWR_US_DEFAULT},
	{8, 2447, LBS_TX_PWR_US_DEFAULT},
	{9, 2452, LBS_TX_PWR_US_DEFAULT},
	{10, 2457, LBS_TX_PWR_US_DEFAULT},
	{11, 2462, LBS_TX_PWR_US_DEFAULT}
60 61 62 63
};

/* band: 'B/G', region: Europe ETSI */
static struct chan_freq_power channel_freq_power_EU_BG[] = {
64 65 66 67 68 69 70 71 72 73 74 75 76
	{1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
	{2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
	{3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
	{4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
	{5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
	{6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
	{7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
	{8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
	{9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
	{10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
	{11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
	{12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
	{13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
77 78 79 80
};

/* band: 'B/G', region: Spain */
static struct chan_freq_power channel_freq_power_SPN_BG[] = {
81 82
	{10, 2457, LBS_TX_PWR_DEFAULT},
	{11, 2462, LBS_TX_PWR_DEFAULT}
83 84 85 86
};

/* band: 'B/G', region: France */
static struct chan_freq_power channel_freq_power_FR_BG[] = {
87 88 89 90
	{10, 2457, LBS_TX_PWR_FR_DEFAULT},
	{11, 2462, LBS_TX_PWR_FR_DEFAULT},
	{12, 2467, LBS_TX_PWR_FR_DEFAULT},
	{13, 2472, LBS_TX_PWR_FR_DEFAULT}
91 92 93 94
};

/* band: 'B/G', region: Japan */
static struct chan_freq_power channel_freq_power_JPN_BG[] = {
95 96 97 98 99 100 101 102 103 104 105 106 107 108
	{1, 2412, LBS_TX_PWR_JP_DEFAULT},
	{2, 2417, LBS_TX_PWR_JP_DEFAULT},
	{3, 2422, LBS_TX_PWR_JP_DEFAULT},
	{4, 2427, LBS_TX_PWR_JP_DEFAULT},
	{5, 2432, LBS_TX_PWR_JP_DEFAULT},
	{6, 2437, LBS_TX_PWR_JP_DEFAULT},
	{7, 2442, LBS_TX_PWR_JP_DEFAULT},
	{8, 2447, LBS_TX_PWR_JP_DEFAULT},
	{9, 2452, LBS_TX_PWR_JP_DEFAULT},
	{10, 2457, LBS_TX_PWR_JP_DEFAULT},
	{11, 2462, LBS_TX_PWR_JP_DEFAULT},
	{12, 2467, LBS_TX_PWR_JP_DEFAULT},
	{13, 2472, LBS_TX_PWR_JP_DEFAULT},
	{14, 2484, LBS_TX_PWR_JP_DEFAULT}
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
};

/**
 * the structure for channel, frequency and power
 */
struct region_cfp_table {
	u8 region;
	struct chan_freq_power *cfp_BG;
	int cfp_no_BG;
};

/**
 * the structure for the mapping between region and CFP
 */
static struct region_cfp_table region_cfp_table[] = {
	{0x10,			/*US FCC */
	 channel_freq_power_US_BG,
126
	 ARRAY_SIZE(channel_freq_power_US_BG),
127 128 129 130
	 }
	,
	{0x20,			/*CANADA IC */
	 channel_freq_power_US_BG,
131
	 ARRAY_SIZE(channel_freq_power_US_BG),
132 133 134
	 }
	,
	{0x30, /*EU*/ channel_freq_power_EU_BG,
135
	 ARRAY_SIZE(channel_freq_power_EU_BG),
136 137 138
	 }
	,
	{0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
139
	 ARRAY_SIZE(channel_freq_power_SPN_BG),
140 141 142
	 }
	,
	{0x32, /*FRANCE*/ channel_freq_power_FR_BG,
143
	 ARRAY_SIZE(channel_freq_power_FR_BG),
144 145 146
	 }
	,
	{0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
147
	 ARRAY_SIZE(channel_freq_power_JPN_BG),
148 149 150 151 152 153
	 }
	,
/*Add new region here */
};

/**
154
 * the table to keep region code
155
 */
156
u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
157
    { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
158 159

/**
160
 * 802.11b/g supported bitrates (in 500Kb/s units)
161
 */
162
u8 lbs_bg_rates[MAX_RATES] =
163 164
    { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
0x00, 0x00 };
165 166

/**
167 168 169
 * FW rate table.  FW refers to rates by their index in this table, not by the
 * rate value itself.  Values of 0x00 are
 * reserved positions.
170
 */
171 172 173 174
static u8 fw_data_rates[MAX_RATES] =
    { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
      0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
};
175 176

/**
177 178 179 180
 *  @brief use index to get the data rate
 *
 *  @param idx                The index of data rate
 *  @return 	   		data rate or 0
181
 */
182
u32 lbs_fw_index_to_data_rate(u8 idx)
183 184 185 186 187 188 189 190 191 192 193 194
{
	if (idx >= sizeof(fw_data_rates))
		idx = 0;
	return fw_data_rates[idx];
}

/**
 *  @brief use rate to get the index
 *
 *  @param rate                 data rate
 *  @return 	   		index or 0
 */
195
u8 lbs_data_rate_to_fw_index(u32 rate)
196 197 198 199 200 201 202 203 204 205 206 207
{
	u8 i;

	if (!rate)
		return 0;

	for (i = 0; i < sizeof(fw_data_rates); i++) {
		if (rate == fw_data_rates[i])
			return i;
	}
	return 0;
}
208 209 210 211 212 213

/**
 * Attributes exported through sysfs
 */

/**
214
 * @brief Get function for sysfs attribute anycast_mask
215
 */
216
static ssize_t lbs_anycast_get(struct device *dev,
D
Dan Williams 已提交
217 218
		struct device_attribute *attr, char * buf)
{
219
	struct lbs_private *priv = to_net_dev(dev)->priv;
220
	struct cmd_ds_mesh_access mesh_access;
221
	int ret;
222 223

	memset(&mesh_access, 0, sizeof(mesh_access));
224 225 226 227

	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
	if (ret)
		return ret;
228

229
	return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
230 231 232
}

/**
233
 * @brief Set function for sysfs attribute anycast_mask
234
 */
235
static ssize_t lbs_anycast_set(struct device *dev,
D
Dan Williams 已提交
236 237
		struct device_attribute *attr, const char * buf, size_t count)
{
238
	struct lbs_private *priv = to_net_dev(dev)->priv;
239
	struct cmd_ds_mesh_access mesh_access;
240
	uint32_t datum;
241
	int ret;
242 243

	memset(&mesh_access, 0, sizeof(mesh_access));
244
	sscanf(buf, "%x", &datum);
245 246
	mesh_access.data[0] = cpu_to_le32(datum);

247 248 249 250
	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
	if (ret)
		return ret;

251 252 253
	return strlen(buf);
}

254 255
static int lbs_add_rtap(struct lbs_private *priv);
static void lbs_remove_rtap(struct lbs_private *priv);
256 257 258
static int lbs_add_mesh(struct lbs_private *priv);
static void lbs_remove_mesh(struct lbs_private *priv);
  
259 260 261 262

/**
 * Get function for sysfs attribute rtap
 */
263
static ssize_t lbs_rtap_get(struct device *dev,
264 265
		struct device_attribute *attr, char * buf)
{
266
	struct lbs_private *priv = to_net_dev(dev)->priv;
267
	return snprintf(buf, 5, "0x%X\n", priv->monitormode);
268 269 270 271 272
}

/**
 *  Set function for sysfs attribute rtap
 */
273
static ssize_t lbs_rtap_set(struct device *dev,
274 275 276
		struct device_attribute *attr, const char * buf, size_t count)
{
	int monitor_mode;
277
	struct lbs_private *priv = to_net_dev(dev)->priv;
278 279

	sscanf(buf, "%x", &monitor_mode);
280
	if (monitor_mode != LBS_MONITOR_OFF) {
281
		if(priv->monitormode == monitor_mode)
282
			return strlen(buf);
283
		if (priv->monitormode == LBS_MONITOR_OFF) {
284 285
			if (priv->infra_open || priv->mesh_open)
				return -EBUSY;
286
			if (priv->mode == IW_MODE_INFRA)
287
				lbs_send_deauthentication(priv);
288
			else if (priv->mode == IW_MODE_ADHOC)
289 290
				lbs_stop_adhoc_network(priv);
			lbs_add_rtap(priv);
291
		}
292
		priv->monitormode = monitor_mode;
293 294 295
	}

	else {
296
		if (priv->monitormode == LBS_MONITOR_OFF)
297
			return strlen(buf);
298
		priv->monitormode = LBS_MONITOR_OFF;
299
		lbs_remove_rtap(priv);
D
David Woodhouse 已提交
300

301 302 303
		if (priv->currenttxskb) {
			dev_kfree_skb_any(priv->currenttxskb);
			priv->currenttxskb = NULL;
D
David Woodhouse 已提交
304 305 306 307
		}

		/* Wake queues, command thread, etc. */
		lbs_host_to_card_done(priv);
308 309
	}

310
	lbs_prepare_and_send_command(priv,
311
			CMD_802_11_MONITOR_MODE, CMD_ACT_SET,
312
			CMD_OPTION_WAITFORRSP, 0, &priv->monitormode);
313 314 315 316
	return strlen(buf);
}

/**
317 318
 * lbs_rtap attribute to be exported per ethX interface
 * through sysfs (/sys/class/net/ethX/lbs_rtap)
319
 */
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );

/**
 * Get function for sysfs attribute mesh
 */
static ssize_t lbs_mesh_get(struct device *dev,
		struct device_attribute *attr, char * buf)
{
	struct lbs_private *priv = to_net_dev(dev)->priv;
	return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
}

/**
 *  Set function for sysfs attribute mesh
 */
static ssize_t lbs_mesh_set(struct device *dev,
		struct device_attribute *attr, const char * buf, size_t count)
{
	struct lbs_private *priv = to_net_dev(dev)->priv;
	int enable;
	int ret;

	sscanf(buf, "%x", &enable);
	enable = !!enable;
	if (enable == !!priv->mesh_dev)
		return count;

	ret = lbs_mesh_config(priv, enable);
	if (ret)
		return ret;
		
	if (enable)
		lbs_add_mesh(priv);
	else
		lbs_remove_mesh(priv);

	return count;
}

/**
 * lbs_mesh attribute to be exported per ethX interface
 * through sysfs (/sys/class/net/ethX/lbs_mesh)
 */
static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
364

365
/**
366 367
 * anycast_mask attribute to be exported per mshX interface
 * through sysfs (/sys/class/net/mshX/anycast_mask)
368
 */
369
static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
370

371
static struct attribute *lbs_mesh_sysfs_entries[] = {
372 373 374 375
	&dev_attr_anycast_mask.attr,
	NULL,
};

376 377
static struct attribute_group lbs_mesh_attr_group = {
	.attrs = lbs_mesh_sysfs_entries,
378 379
};

380
/**
381
 *  @brief This function opens the ethX or mshX interface
382 383
 *
 *  @param dev     A pointer to net_device structure
384
 *  @return 	   0 or -EBUSY if monitor mode active
385
 */
386
static int lbs_dev_open(struct net_device *dev)
387
{
388 389
	struct lbs_private *priv = (struct lbs_private *) dev->priv ;
	int ret = 0;
390

391
	spin_lock_irq(&priv->driver_lock);
392

393 394 395 396
	if (priv->monitormode != LBS_MONITOR_OFF) {
		ret = -EBUSY;
		goto out;
	}
397

398 399 400 401 402 403 404 405 406
	if (dev == priv->mesh_dev) {
		priv->mesh_open = 1;
		priv->mesh_connect_status = LBS_CONNECTED;
		netif_carrier_on(dev);
	} else {
		priv->infra_open = 1;
		
		if (priv->connect_status == LBS_CONNECTED)
			netif_carrier_on(dev);
407
		else
408
			netif_carrier_off(dev);
409
	}
410

411 412 413
	if (!priv->tx_pending_len)
		netif_wake_queue(dev);
 out:
414

415 416
	spin_unlock_irq(&priv->driver_lock);
	return ret;
417 418 419 420 421 422 423 424
}

/**
 *  @brief This function closes the mshX interface
 *
 *  @param dev     A pointer to net_device structure
 *  @return 	   0
 */
425
static int lbs_mesh_stop(struct net_device *dev)
426
{
427
	struct lbs_private *priv = (struct lbs_private *) (dev->priv);
428

429 430
	spin_lock_irq(&priv->driver_lock);

431
	priv->mesh_open = 0;
432 433 434 435 436 437 438
	priv->mesh_connect_status = LBS_DISCONNECTED;

	netif_stop_queue(dev);
	netif_carrier_off(dev);
	
	spin_unlock_irq(&priv->driver_lock);
	return 0;
439 440 441 442 443 444 445 446
}

/**
 *  @brief This function closes the ethX interface
 *
 *  @param dev     A pointer to net_device structure
 *  @return 	   0
 */
447
static int lbs_eth_stop(struct net_device *dev)
448
{
449
	struct lbs_private *priv = (struct lbs_private *) dev->priv;
450

451 452
	spin_lock_irq(&priv->driver_lock);

453
	priv->infra_open = 0;
454 455 456 457 458

	netif_stop_queue(dev);
	
	spin_unlock_irq(&priv->driver_lock);
	return 0;
459 460
}

461
static void lbs_tx_timeout(struct net_device *dev)
462
{
463
	struct lbs_private *priv = (struct lbs_private *) dev->priv;
464

465
	lbs_deb_enter(LBS_DEB_TX);
466

467
	lbs_pr_err("tx watch dog timeout\n");
468 469 470

	dev->trans_start = jiffies;

471
	if (priv->currenttxskb) {
472 473
		priv->eventcause = 0x01000000;
		lbs_send_tx_feedback(priv);
474
	}
475 476 477
	/* XX: Shouldn't we also call into the hw-specific driver
	   to kick it somehow? */
	lbs_host_to_card_done(priv);
478

479
	lbs_deb_leave(LBS_DEB_TX);
480 481
}

482 483
void lbs_host_to_card_done(struct lbs_private *priv)
{
484 485 486
	unsigned long flags;

	spin_lock_irqsave(&priv->driver_lock, flags);
487 488 489 490

	priv->dnld_sent = DNLD_RES_RECEIVED;

	/* Wake main thread if commands are pending */
491
	if (!priv->cur_cmd || priv->tx_pending_len > 0)
492 493
		wake_up_interruptible(&priv->waitq);

494
	spin_unlock_irqrestore(&priv->driver_lock, flags);
495 496 497
}
EXPORT_SYMBOL_GPL(lbs_host_to_card_done);

498 499 500
/**
 *  @brief This function returns the network statistics
 *
501
 *  @param dev     A pointer to struct lbs_private structure
502 503
 *  @return 	   A pointer to net_device_stats structure
 */
504
static struct net_device_stats *lbs_get_stats(struct net_device *dev)
505
{
506
	struct lbs_private *priv = (struct lbs_private *) dev->priv;
507 508 509 510

	return &priv->stats;
}

511
static int lbs_set_mac_address(struct net_device *dev, void *addr)
512 513
{
	int ret = 0;
514
	struct lbs_private *priv = (struct lbs_private *) dev->priv;
515 516
	struct sockaddr *phwaddr = addr;

517
	lbs_deb_enter(LBS_DEB_NET);
518

519 520 521
	/* In case it was called from the mesh device */
	dev = priv->dev ;

522
	memset(priv->current_addr, 0, ETH_ALEN);
523 524

	/* dev->dev_addr is 8 bytes */
525
	lbs_deb_hex(LBS_DEB_NET, "dev->dev_addr", dev->dev_addr, ETH_ALEN);
526

527
	lbs_deb_hex(LBS_DEB_NET, "addr", phwaddr->sa_data, ETH_ALEN);
528
	memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
529

530
	ret = lbs_prepare_and_send_command(priv, CMD_802_11_MAC_ADDRESS,
531 532
				    CMD_ACT_SET,
				    CMD_OPTION_WAITFORRSP, 0, NULL);
533 534

	if (ret) {
535
		lbs_deb_net("set MAC address failed\n");
536 537 538 539
		ret = -1;
		goto done;
	}

540 541
	lbs_deb_hex(LBS_DEB_NET, "priv->macaddr", priv->current_addr, ETH_ALEN);
	memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN);
542
	if (priv->mesh_dev)
543
		memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
544 545

done:
546
	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
547 548 549
	return ret;
}

550
static int lbs_copy_multicast_address(struct lbs_private *priv,
551 552 553 554 555 556
				     struct net_device *dev)
{
	int i = 0;
	struct dev_mc_list *mcptr = dev->mc_list;

	for (i = 0; i < dev->mc_count; i++) {
557
		memcpy(&priv->multicastlist[i], mcptr->dmi_addr, ETH_ALEN);
558 559 560 561 562 563 564
		mcptr = mcptr->next;
	}

	return i;

}

565
static void lbs_set_multicast_list(struct net_device *dev)
566
{
567
	struct lbs_private *priv = dev->priv;
568
	int oldpacketfilter;
569
	DECLARE_MAC_BUF(mac);
570

571
	lbs_deb_enter(LBS_DEB_NET);
572

573
	oldpacketfilter = priv->currentpacketfilter;
574 575

	if (dev->flags & IFF_PROMISC) {
576
		lbs_deb_net("enable promiscuous mode\n");
577
		priv->currentpacketfilter |=
578
		    CMD_ACT_MAC_PROMISCUOUS_ENABLE;
579
		priv->currentpacketfilter &=
580 581
		    ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE |
		      CMD_ACT_MAC_MULTICAST_ENABLE);
582 583
	} else {
		/* Multicast */
584
		priv->currentpacketfilter &=
585
		    ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
586 587 588

		if (dev->flags & IFF_ALLMULTI || dev->mc_count >
		    MRVDRV_MAX_MULTICAST_LIST_SIZE) {
589
			lbs_deb_net( "enabling all multicast\n");
590
			priv->currentpacketfilter |=
591
			    CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
592
			priv->currentpacketfilter &=
593
			    ~CMD_ACT_MAC_MULTICAST_ENABLE;
594
		} else {
595
			priv->currentpacketfilter &=
596
			    ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
597 598

			if (!dev->mc_count) {
599 600
				lbs_deb_net("no multicast addresses, "
				       "disabling multicast\n");
601
				priv->currentpacketfilter &=
602
				    ~CMD_ACT_MAC_MULTICAST_ENABLE;
603 604 605
			} else {
				int i;

606
				priv->currentpacketfilter |=
607
				    CMD_ACT_MAC_MULTICAST_ENABLE;
608

609 610
				priv->nr_of_multicastmacaddr =
				    lbs_copy_multicast_address(priv, dev);
611

612
				lbs_deb_net("multicast addresses: %d\n",
613 614 615
				       dev->mc_count);

				for (i = 0; i < dev->mc_count; i++) {
616 617
					lbs_deb_net("Multicast address %d:%s\n",
					       i, print_mac(mac,
618
					       priv->multicastlist[i]));
619
				}
620
				/* send multicast addresses to firmware */
621
				lbs_prepare_and_send_command(priv,
622 623
						      CMD_MAC_MULTICAST_ADR,
						      CMD_ACT_SET, 0, 0,
624 625 626 627 628
						      NULL);
			}
		}
	}

629
	if (priv->currentpacketfilter != oldpacketfilter) {
630
		lbs_set_mac_packet_filter(priv);
631 632
	}

633
	lbs_deb_leave(LBS_DEB_NET);
634 635 636
}

/**
637
 *  @brief This function handles the major jobs in the LBS driver.
638 639
 *  It handles all events generated by firmware, RX data received
 *  from firmware and TX data sent from kernel.
640
 *
641
 *  @param data    A pointer to lbs_thread structure
642 643
 *  @return 	   0
 */
644
static int lbs_thread(void *data)
645
{
646
	struct net_device *dev = data;
647
	struct lbs_private *priv = dev->priv;
648 649 650
	wait_queue_t wait;
	u8 ireg = 0;

651
	lbs_deb_enter(LBS_DEB_THREAD);
652 653 654 655

	init_waitqueue_entry(&wait, current);

	for (;;) {
656 657
		int shouldsleep;

658
		lbs_deb_thread( "main-thread 111: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
659
				priv->intcounter, priv->currenttxskb, priv->dnld_sent);
660

661
		add_wait_queue(&priv->waitq, &wait);
662
		set_current_state(TASK_INTERRUPTIBLE);
663
		spin_lock_irq(&priv->driver_lock);
664

665 666 667 668 669 670
		if (priv->surpriseremoved)
			shouldsleep = 0;	/* Bye */
		else if (priv->psstate == PS_STATE_SLEEP)
			shouldsleep = 1;	/* Sleep mode. Nothing we can do till it wakes */
		else if (priv->intcounter)
			shouldsleep = 0;	/* Interrupt pending. Deal with it now */
671 672
		else if (!priv->fw_ready)
			shouldsleep = 1;	/* Firmware not ready. We're waiting for it */
673 674
		else if (priv->dnld_sent)
			shouldsleep = 1;	/* Something is en route to the device already */
675 676
		else if (priv->tx_pending_len > 0)
			shouldsleep = 0;	/* We've a packet to send */
677 678 679 680 681 682 683 684
		else if (priv->cur_cmd)
			shouldsleep = 1;	/* Can't send a command; one already running */
		else if (!list_empty(&priv->cmdpendingq))
			shouldsleep = 0;	/* We have a command to send */
		else
			shouldsleep = 1;	/* No command */

		if (shouldsleep) {
685
			lbs_deb_thread("main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n",
686 687 688
				       priv->connect_status, priv->intcounter,
				       priv->psmode, priv->psstate);
			spin_unlock_irq(&priv->driver_lock);
689 690
			schedule();
		} else
691
			spin_unlock_irq(&priv->driver_lock);
692

693
		lbs_deb_thread("main-thread 222 (waking up): intcounter=%d currenttxskb=%p dnld_sent=%d\n",
694
			       priv->intcounter, priv->currenttxskb, priv->dnld_sent);
695 696

		set_current_state(TASK_RUNNING);
697
		remove_wait_queue(&priv->waitq, &wait);
698

699
		lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
700
			       priv->intcounter, priv->currenttxskb, priv->dnld_sent);
701

702
		if (kthread_should_stop() || priv->surpriseremoved) {
703
			lbs_deb_thread("main-thread: break from main thread: surpriseremoved=0x%x\n",
704
				       priv->surpriseremoved);
705 706 707 708
			break;
		}


709
		spin_lock_irq(&priv->driver_lock);
710

711
		if (priv->intcounter) {
712
			u8 int_status;
713

714
			priv->intcounter = 0;
715
			int_status = priv->hw_get_int_status(priv, &ireg);
716 717

			if (int_status) {
718
				lbs_deb_thread("main-thread: reading HOST_INT_STATUS_REG failed\n");
719
				spin_unlock_irq(&priv->driver_lock);
720 721
				continue;
			}
722
			priv->hisregcpy |= ireg;
723 724
		}

725
		lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
726
			       priv->intcounter, priv->currenttxskb, priv->dnld_sent);
727 728

		/* command response? */
729
		if (priv->hisregcpy & MRVDRV_CMD_UPLD_RDY) {
730
			lbs_deb_thread("main-thread: cmd response ready\n");
731

732 733
			priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY;
			spin_unlock_irq(&priv->driver_lock);
734
			lbs_process_rx_command(priv);
735
			spin_lock_irq(&priv->driver_lock);
736 737 738
		}

		/* Any Card Event */
739
		if (priv->hisregcpy & MRVDRV_CARDEVENT) {
740
			lbs_deb_thread("main-thread: Card Event Activity\n");
741

742
			priv->hisregcpy &= ~MRVDRV_CARDEVENT;
743

744
			if (priv->hw_read_event_cause(priv)) {
745
				lbs_pr_alert("main-thread: hw_read_event_cause failed\n");
746
				spin_unlock_irq(&priv->driver_lock);
747 748
				continue;
			}
749
			spin_unlock_irq(&priv->driver_lock);
750
			lbs_process_event(priv);
751
		} else
752
			spin_unlock_irq(&priv->driver_lock);
753

754 755 756
		if (!priv->fw_ready)
			continue;

757
		/* Check if we need to confirm Sleep Request received previously */
758 759 760
		if (priv->psstate == PS_STATE_PRE_SLEEP &&
		    !priv->dnld_sent && !priv->cur_cmd) {
			if (priv->connect_status == LBS_CONNECTED) {
761
				lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n",
762
					       priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd);
763

764
				lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
765 766 767 768 769 770
			} else {
				/* workaround for firmware sending
				 * deauth/linkloss event immediately
				 * after sleep request; remove this
				 * after firmware fixes it
				 */
771
				priv->psstate = PS_STATE_AWAKE;
772
				lbs_pr_alert("main-thread: ignore PS_SleepConfirm in non-connected state\n");
773 774 775 776 777 778
			}
		}

		/* The PS state is changed during processing of Sleep Request
		 * event above
		 */
779 780
		if ((priv->psstate == PS_STATE_SLEEP) ||
		    (priv->psstate == PS_STATE_PRE_SLEEP))
781 782 783
			continue;

		/* Execute the next command */
784
		if (!priv->dnld_sent && !priv->cur_cmd)
785
			lbs_execute_next_command(priv);
786 787

		/* Wake-up command waiters which can't sleep in
788
		 * lbs_prepare_and_send_command
789
		 */
790 791
		if (!list_empty(&priv->cmdpendingq))
			wake_up_all(&priv->cmd_pending);
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813

		spin_lock_irq(&priv->driver_lock);
		if (!priv->dnld_sent && priv->tx_pending_len > 0) {
			int ret = priv->hw_host_to_card(priv, MVMS_DAT,
							priv->tx_pending_buf,
							priv->tx_pending_len);
			if (ret) {
				lbs_deb_tx("host_to_card failed %d\n", ret);
				priv->dnld_sent = DNLD_RES_RECEIVED;
			}
			priv->tx_pending_len = 0;
			if (!priv->currenttxskb) {
				/* We can wake the queues immediately if we aren't
				   waiting for TX feedback */
				if (priv->connect_status == LBS_CONNECTED)
					netif_wake_queue(priv->dev);
				if (priv->mesh_dev &&
				    priv->mesh_connect_status == LBS_CONNECTED)
					netif_wake_queue(priv->mesh_dev);
			}
		}
		spin_unlock_irq(&priv->driver_lock);
814 815
	}

816 817
	del_timer(&priv->command_timer);
	wake_up_all(&priv->cmd_pending);
818

819
	lbs_deb_leave(LBS_DEB_THREAD);
820 821 822
	return 0;
}

H
Holger Schurig 已提交
823 824 825 826 827
/**
 *  @brief This function downloads firmware image, gets
 *  HW spec from firmware and set basic parameters to
 *  firmware.
 *
828
 *  @param priv    A pointer to struct lbs_private structure
H
Holger Schurig 已提交
829 830
 *  @return 	   0 or -1
 */
831
static int lbs_setup_firmware(struct lbs_private *priv)
H
Holger Schurig 已提交
832 833 834 835 836 837 838 839
{
	int ret = -1;

	lbs_deb_enter(LBS_DEB_FW);

	/*
	 * Read MAC address from HW
	 */
840
	memset(priv->current_addr, 0xff, ETH_ALEN);
841
	ret = lbs_update_hw_spec(priv);
H
Holger Schurig 已提交
842 843 844 845 846
	if (ret) {
		ret = -1;
		goto done;
	}

847
	lbs_set_mac_packet_filter(priv);
H
Holger Schurig 已提交
848

849 850
	ret = lbs_get_data_rate(priv);
	if (ret < 0) {
H
Holger Schurig 已提交
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
		ret = -1;
		goto done;
	}

	ret = 0;
done:
	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
	return ret;
}

/**
 *  This function handles the timeout of command sending.
 *  It will re-send the same command again.
 */
static void command_timer_fn(unsigned long data)
{
867
	struct lbs_private *priv = (struct lbs_private *)data;
868
	struct cmd_ctrl_node *node;
H
Holger Schurig 已提交
869 870
	unsigned long flags;

871 872
	node = priv->cur_cmd;
	if (node == NULL) {
H
Holger Schurig 已提交
873 874 875 876
		lbs_deb_fw("ptempnode empty\n");
		return;
	}

877
	if (!node->cmdbuf) {
H
Holger Schurig 已提交
878 879 880 881
		lbs_deb_fw("cmd is NULL\n");
		return;
	}

882
	lbs_pr_info("command %x timed out\n", le16_to_cpu(node->cmdbuf->command));
H
Holger Schurig 已提交
883

884
	if (!priv->fw_ready)
H
Holger Schurig 已提交
885 886
		return;

887 888 889
	spin_lock_irqsave(&priv->driver_lock, flags);
	priv->cur_cmd = NULL;
	spin_unlock_irqrestore(&priv->driver_lock, flags);
H
Holger Schurig 已提交
890 891

	lbs_deb_fw("re-sending same command because of timeout\n");
892
	lbs_queue_cmd(priv, node, 0);
H
Holger Schurig 已提交
893 894 895 896 897 898

	wake_up_interruptible(&priv->waitq);

	return;
}

899
static int lbs_init_adapter(struct lbs_private *priv)
900
{
H
Holger Schurig 已提交
901
	size_t bufsize;
902
	int i, ret = 0;
H
Holger Schurig 已提交
903 904 905

	/* Allocate buffer to store the BSSID list */
	bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
906 907
	priv->networks = kzalloc(bufsize, GFP_KERNEL);
	if (!priv->networks) {
H
Holger Schurig 已提交
908
		lbs_pr_err("Out of memory allocating beacons\n");
909 910
		ret = -1;
		goto out;
H
Holger Schurig 已提交
911 912
	}

913
	/* Initialize scan result lists */
914 915
	INIT_LIST_HEAD(&priv->network_free_list);
	INIT_LIST_HEAD(&priv->network_list);
916
	for (i = 0; i < MAX_NETWORK_COUNT; i++) {
917 918
		list_add_tail(&priv->networks[i].list,
			      &priv->network_free_list);
919
	}
H
Holger Schurig 已提交
920

921 922
	priv->lbs_ps_confirm_sleep.seqnum = cpu_to_le16(++priv->seqnum);
	priv->lbs_ps_confirm_sleep.command =
H
Holger Schurig 已提交
923
	    cpu_to_le16(CMD_802_11_PS_MODE);
924
	priv->lbs_ps_confirm_sleep.size =
H
Holger Schurig 已提交
925
	    cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep));
926
	priv->lbs_ps_confirm_sleep.action =
H
Holger Schurig 已提交
927 928
	    cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);

929
	memset(priv->current_addr, 0xff, ETH_ALEN);
H
Holger Schurig 已提交
930

931 932 933 934 935 936 937 938 939 940 941
	priv->connect_status = LBS_DISCONNECTED;
	priv->mesh_connect_status = LBS_DISCONNECTED;
	priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
	priv->mode = IW_MODE_INFRA;
	priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
	priv->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
	priv->radioon = RADIO_ON;
	priv->auto_rate = 1;
	priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
	priv->psmode = LBS802_11POWERMODECAM;
	priv->psstate = PS_STATE_FULL_POWER;
H
Holger Schurig 已提交
942

943
	mutex_init(&priv->lock);
H
Holger Schurig 已提交
944

945
	setup_timer(&priv->command_timer, command_timer_fn,
946
	            (unsigned long)priv);
H
Holger Schurig 已提交
947

948 949
	INIT_LIST_HEAD(&priv->cmdfreeq);
	INIT_LIST_HEAD(&priv->cmdpendingq);
H
Holger Schurig 已提交
950

951 952
	spin_lock_init(&priv->driver_lock);
	init_waitqueue_head(&priv->cmd_pending);
H
Holger Schurig 已提交
953

954
	/* Allocate the command buffers */
955
	if (lbs_allocate_cmd_buffer(priv)) {
956 957 958
		lbs_pr_err("Out of memory allocating command buffers\n");
		ret = -1;
	}
H
Holger Schurig 已提交
959

960 961 962
out:
	return ret;
}
H
Holger Schurig 已提交
963

964
static void lbs_free_adapter(struct lbs_private *priv)
965 966
{
	lbs_deb_fw("free command buffer\n");
967
	lbs_free_cmd_buffer(priv);
H
Holger Schurig 已提交
968

969
	lbs_deb_fw("free command_timer\n");
970
	del_timer(&priv->command_timer);
971 972

	lbs_deb_fw("free scan results table\n");
973 974
	kfree(priv->networks);
	priv->networks = NULL;
H
Holger Schurig 已提交
975 976
}

977 978
/**
 * @brief This function adds the card. it will probe the
979
 * card, allocate the lbs_priv and initialize the device.
980 981
 *
 *  @param card    A pointer to card
982
 *  @return 	   A pointer to struct lbs_private structure
983
 */
984
struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
985 986
{
	struct net_device *dev = NULL;
987
	struct lbs_private *priv = NULL;
988

989
	lbs_deb_enter(LBS_DEB_NET);
990 991

	/* Allocate an Ethernet device and register it */
992 993
	dev = alloc_etherdev(sizeof(struct lbs_private));
	if (!dev) {
994
		lbs_pr_err("init ethX device failed\n");
995
		goto done;
996
	}
997
	priv = dev->priv;
998

999
	if (lbs_init_adapter(priv)) {
1000 1001 1002 1003
		lbs_pr_err("failed to initialize adapter structure.\n");
		goto err_init_adapter;
	}

1004 1005
	priv->dev = dev;
	priv->card = card;
1006 1007 1008 1009
	priv->mesh_open = 0;
	priv->infra_open = 0;

	/* Setup the OS Interface to our functions */
1010
	dev->open = lbs_dev_open;
1011
	dev->hard_start_xmit = lbs_hard_start_xmit;
1012
	dev->stop = lbs_eth_stop;
1013 1014 1015
	dev->set_mac_address = lbs_set_mac_address;
	dev->tx_timeout = lbs_tx_timeout;
	dev->get_stats = lbs_get_stats;
1016
	dev->watchdog_timeo = 5 * HZ;
1017
	dev->ethtool_ops = &lbs_ethtool_ops;
1018
#ifdef	WIRELESS_EXT
1019
	dev->wireless_handlers = (struct iw_handler_def *)&lbs_handler_def;
1020 1021
#endif
	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
1022
	dev->set_multicast_list = lbs_set_multicast_list;
1023

1024 1025
	SET_NETDEV_DEV(dev, dmdev);

1026
	priv->rtap_net_dev = NULL;
1027 1028 1029

	lbs_deb_thread("Starting main thread...\n");
	init_waitqueue_head(&priv->waitq);
1030
	priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main");
1031 1032
	if (IS_ERR(priv->main_thread)) {
		lbs_deb_thread("Error creating main thread.\n");
1033
		goto err_init_adapter;
1034 1035
	}

1036 1037 1038 1039
	priv->work_thread = create_singlethread_workqueue("lbs_worker");
	INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
	INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
	INIT_WORK(&priv->sync_channel, lbs_sync_channel);
1040

1041 1042 1043
	sprintf(priv->mesh_ssid, "mesh");
	priv->mesh_ssid_len = 4;

1044 1045
	goto done;

1046
err_init_adapter:
1047
	lbs_free_adapter(priv);
1048
	free_netdev(dev);
1049
	priv = NULL;
1050

1051 1052 1053 1054
done:
	lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv);
	return priv;
}
1055
EXPORT_SYMBOL_GPL(lbs_add_card);
1056

1057

1058
int lbs_remove_card(struct lbs_private *priv)
1059
{
1060
	struct net_device *dev = priv->dev;
1061
	union iwreq_data wrqu;
1062 1063

	lbs_deb_enter(LBS_DEB_MAIN);
1064

1065
	lbs_remove_mesh(priv);
1066
	lbs_remove_rtap(priv);
1067

1068
	dev = priv->dev;
1069

1070 1071 1072
	cancel_delayed_work(&priv->scan_work);
	cancel_delayed_work(&priv->assoc_work);
	destroy_workqueue(priv->work_thread);
1073

1074 1075
	if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
		priv->psmode = LBS802_11POWERMODECAM;
1076
		lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
1077 1078
	}

1079 1080 1081 1082 1083
	memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);

	/* Stop the thread servicing the interrupts */
1084
	priv->surpriseremoved = 1;
1085 1086
	kthread_stop(priv->main_thread);

1087
	lbs_free_adapter(priv);
1088 1089 1090 1091 1092 1093 1094

	priv->dev = NULL;
	free_netdev(dev);

	lbs_deb_leave(LBS_DEB_MAIN);
	return 0;
}
1095
EXPORT_SYMBOL_GPL(lbs_remove_card);
1096 1097


1098
int lbs_start_card(struct lbs_private *priv)
1099 1100 1101 1102 1103 1104 1105
{
	struct net_device *dev = priv->dev;
	int ret = -1;

	lbs_deb_enter(LBS_DEB_MAIN);

	/* poke the firmware */
1106
	ret = lbs_setup_firmware(priv);
1107 1108 1109 1110
	if (ret)
		goto done;

	/* init 802.11d */
1111
	lbs_init_11d(priv);
1112 1113

	if (register_netdev(dev)) {
1114
		lbs_pr_err("cannot register ethX device\n");
1115
		goto done;
1116
	}
1117 1118
	if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
		lbs_pr_err("cannot register lbs_rtap attribute\n");
1119 1120
	if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
		lbs_pr_err("cannot register lbs_mesh attribute\n");
1121

1122
	lbs_debugfs_init_one(priv, dev);
1123

1124 1125
	lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);

1126
	ret = 0;
1127

1128
done:
1129 1130 1131
	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
	return ret;
}
1132
EXPORT_SYMBOL_GPL(lbs_start_card);
1133 1134


1135
int lbs_stop_card(struct lbs_private *priv)
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
{
	struct net_device *dev = priv->dev;
	int ret = -1;
	struct cmd_ctrl_node *cmdnode;
	unsigned long flags;

	lbs_deb_enter(LBS_DEB_MAIN);

	netif_stop_queue(priv->dev);
	netif_carrier_off(priv->dev);

1147
	lbs_debugfs_remove_one(priv);
1148
	device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
1149
	device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
1150 1151

	/* Flush pending command nodes */
1152 1153
	spin_lock_irqsave(&priv->driver_lock, flags);
	list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
1154 1155 1156
		cmdnode->cmdwaitqwoken = 1;
		wake_up_interruptible(&cmdnode->cmdwait_q);
	}
1157
	spin_unlock_irqrestore(&priv->driver_lock, flags);
1158 1159 1160 1161

	unregister_netdev(dev);

	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
1162
	return ret;
1163
}
1164
EXPORT_SYMBOL_GPL(lbs_stop_card);
1165

1166

1167 1168 1169
/**
 * @brief This function adds mshX interface
 *
1170
 *  @param priv    A pointer to the struct lbs_private structure
1171 1172
 *  @return 	   0 if successful, -X otherwise
 */
1173
static int lbs_add_mesh(struct lbs_private *priv)
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
{
	struct net_device *mesh_dev = NULL;
	int ret = 0;

	lbs_deb_enter(LBS_DEB_MESH);

	/* Allocate a virtual mesh device */
	if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
		lbs_deb_mesh("init mshX device failed\n");
		ret = -ENOMEM;
		goto done;
	}
	mesh_dev->priv = priv;
	priv->mesh_dev = mesh_dev;

1189
	mesh_dev->open = lbs_dev_open;
1190
	mesh_dev->hard_start_xmit = lbs_hard_start_xmit;
1191
	mesh_dev->stop = lbs_mesh_stop;
1192 1193 1194
	mesh_dev->get_stats = lbs_get_stats;
	mesh_dev->set_mac_address = lbs_set_mac_address;
	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
1195 1196
	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
			sizeof(priv->dev->dev_addr));
1197

1198
	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
1199

1200
#ifdef	WIRELESS_EXT
1201
	mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
1202 1203 1204 1205 1206 1207 1208 1209
#endif
	/* Register virtual mesh interface */
	ret = register_netdev(mesh_dev);
	if (ret) {
		lbs_pr_err("cannot register mshX virtual interface\n");
		goto err_free;
	}

1210
	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
	if (ret)
		goto err_unregister;

	/* Everything successful */
	ret = 0;
	goto done;

err_unregister:
	unregister_netdev(mesh_dev);

err_free:
	free_netdev(mesh_dev);

done:
	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
	return ret;
}
1228
EXPORT_SYMBOL_GPL(lbs_add_mesh);
1229

1230

1231
static void lbs_remove_mesh(struct lbs_private *priv)
1232 1233 1234
{
	struct net_device *mesh_dev;

1235
	lbs_deb_enter(LBS_DEB_MAIN);
1236 1237 1238 1239 1240

	if (!priv)
		goto out;

	mesh_dev = priv->mesh_dev;
1241 1242
	if (!mesh_dev)
		goto out;
1243 1244

	netif_stop_queue(mesh_dev);
1245
	netif_carrier_off(priv->mesh_dev);
1246

1247
	sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
1248 1249
	unregister_netdev(mesh_dev);

1250
	priv->mesh_dev = NULL;
1251 1252 1253
	free_netdev(mesh_dev);

out:
1254
	lbs_deb_leave(LBS_DEB_MAIN);
1255
}
1256
EXPORT_SYMBOL_GPL(lbs_remove_mesh);
1257

1258 1259 1260 1261 1262 1263 1264 1265 1266
/**
 *  @brief This function finds the CFP in
 *  region_cfp_table based on region and band parameter.
 *
 *  @param region  The region code
 *  @param band	   The band
 *  @param cfp_no  A pointer to CFP number
 *  @return 	   A pointer to CFP
 */
1267
struct chan_freq_power *lbs_get_region_cfp_table(u8 region, u8 band, int *cfp_no)
1268 1269 1270
{
	int i, end;

1271
	lbs_deb_enter(LBS_DEB_MAIN);
1272

1273
	end = ARRAY_SIZE(region_cfp_table);
1274 1275

	for (i = 0; i < end ; i++) {
1276
		lbs_deb_main("region_cfp_table[i].region=%d\n",
1277 1278 1279
			region_cfp_table[i].region);
		if (region_cfp_table[i].region == region) {
			*cfp_no = region_cfp_table[i].cfp_no_BG;
1280
			lbs_deb_leave(LBS_DEB_MAIN);
1281 1282 1283 1284
			return region_cfp_table[i].cfp_BG;
		}
	}

1285
	lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
1286 1287 1288
	return NULL;
}

1289
int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
1290
{
1291
	int ret = 0;
1292 1293 1294 1295 1296
	int i = 0;

	struct chan_freq_power *cfp;
	int cfp_no;

1297
	lbs_deb_enter(LBS_DEB_MAIN);
1298

1299
	memset(priv->region_channel, 0, sizeof(priv->region_channel));
1300 1301

	{
1302
		cfp = lbs_get_region_cfp_table(region, band, &cfp_no);
1303
		if (cfp != NULL) {
1304 1305
			priv->region_channel[i].nrcfp = cfp_no;
			priv->region_channel[i].CFP = cfp;
1306
		} else {
1307
			lbs_deb_main("wrong region code %#x in band B/G\n",
1308
			       region);
1309 1310
			ret = -1;
			goto out;
1311
		}
1312 1313 1314
		priv->region_channel[i].valid = 1;
		priv->region_channel[i].region = region;
		priv->region_channel[i].band = band;
1315 1316
		i++;
	}
1317 1318 1319
out:
	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
	return ret;
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329
}

/**
 *  @brief This function handles the interrupt. it will change PS
 *  state if applicable. it will wake up main_thread to handle
 *  the interrupt event as well.
 *
 *  @param dev     A pointer to net_device structure
 *  @return 	   n/a
 */
1330
void lbs_interrupt(struct lbs_private *priv)
1331
{
1332
	lbs_deb_enter(LBS_DEB_THREAD);
1333

1334 1335 1336 1337 1338 1339 1340
	lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter);

	if (spin_trylock(&priv->driver_lock)) {
		spin_unlock(&priv->driver_lock);
		printk(KERN_CRIT "%s called without driver_lock held\n", __func__);
		WARN_ON(1);
	}
1341

1342
	priv->intcounter++;
1343

1344
	if (priv->psstate == PS_STATE_SLEEP)
1345
		priv->psstate = PS_STATE_AWAKE;
1346

1347
	wake_up_interruptible(&priv->waitq);
1348

1349
	lbs_deb_leave(LBS_DEB_THREAD);
1350
}
1351
EXPORT_SYMBOL_GPL(lbs_interrupt);
1352

1353
int lbs_reset_device(struct lbs_private *priv)
1354 1355 1356 1357
{
	int ret;

	lbs_deb_enter(LBS_DEB_MAIN);
1358
	ret = lbs_prepare_and_send_command(priv, CMD_802_11_RESET,
1359 1360 1361 1362 1363 1364
				    CMD_ACT_HALT, 0, 0, NULL);
	msleep_interruptible(10);

	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
	return ret;
}
1365
EXPORT_SYMBOL_GPL(lbs_reset_device);
1366

1367
static int __init lbs_init_module(void)
1368
{
1369
	lbs_deb_enter(LBS_DEB_MAIN);
1370
	lbs_debugfs_init();
1371 1372
	lbs_deb_leave(LBS_DEB_MAIN);
	return 0;
1373 1374
}

1375
static void __exit lbs_exit_module(void)
1376
{
1377
	lbs_deb_enter(LBS_DEB_MAIN);
1378

1379
	lbs_debugfs_remove();
1380

1381
	lbs_deb_leave(LBS_DEB_MAIN);
1382 1383
}

1384 1385 1386 1387
/*
 * rtap interface support fuctions
 */

1388
static int lbs_rtap_open(struct net_device *dev)
1389
{
1390
	/* Yes, _stop_ the queue. Because we don't support injection */
1391 1392 1393 1394 1395
        netif_carrier_off(dev);
        netif_stop_queue(dev);
        return 0;
}

1396
static int lbs_rtap_stop(struct net_device *dev)
1397 1398 1399 1400
{
        return 0;
}

1401
static int lbs_rtap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
1402 1403
{
        netif_stop_queue(dev);
1404
        return NETDEV_TX_BUSY;
1405 1406
}

1407
static struct net_device_stats *lbs_rtap_get_stats(struct net_device *dev)
1408
{
1409
	struct lbs_private *priv = dev->priv;
1410
	return &priv->stats;
1411 1412 1413
}


1414
static void lbs_remove_rtap(struct lbs_private *priv)
1415 1416 1417 1418
{
	if (priv->rtap_net_dev == NULL)
		return;
	unregister_netdev(priv->rtap_net_dev);
1419
	free_netdev(priv->rtap_net_dev);
1420 1421 1422
	priv->rtap_net_dev = NULL;
}

1423
static int lbs_add_rtap(struct lbs_private *priv)
1424 1425
{
	int rc = 0;
1426
	struct net_device *rtap_dev;
1427 1428 1429 1430

	if (priv->rtap_net_dev)
		return -EPERM;

1431 1432
	rtap_dev = alloc_netdev(0, "rtap%d", ether_setup);
	if (rtap_dev == NULL)
1433 1434
		return -ENOMEM;

1435
	memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN);
1436 1437 1438 1439 1440 1441 1442
	rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP;
	rtap_dev->open = lbs_rtap_open;
	rtap_dev->stop = lbs_rtap_stop;
	rtap_dev->get_stats = lbs_rtap_get_stats;
	rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit;
	rtap_dev->set_multicast_list = lbs_set_multicast_list;
	rtap_dev->priv = priv;
1443

1444
	rc = register_netdev(rtap_dev);
1445
	if (rc) {
1446
		free_netdev(rtap_dev);
1447 1448
		return rc;
	}
1449
	priv->rtap_net_dev = rtap_dev;
1450 1451 1452 1453 1454

	return 0;
}


1455 1456
module_init(lbs_init_module);
module_exit(lbs_exit_module);
1457

1458
MODULE_DESCRIPTION("Libertas WLAN Driver Library");
1459 1460
MODULE_AUTHOR("Marvell International Ltd.");
MODULE_LICENSE("GPL");