Эх сурвалжийг харах

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (94 commits)
  genetlink: fix netns vs. netlink table locking (2)
  3c59x: Get rid of "Trying to free already-free IRQ"
  tunnel: eliminate recursion field
  ems_pci: fix size of CAN controllers BAR mapping for CPC-PCI v2
  net: fix htmldocs sunrpc, clnt.c
  Phonet: error on broadcast sending (unimplemented)
  Phonet: fix race for port number in concurrent bind()
  pktgen: better scheduler friendliness
  pktgen: T_TERMINATE flag is unused
  ipv4: check optlen for IP_MULTICAST_IF option
  ath9k: Initialize txgain and rxgain for newer AR9287 chipsets.
  iwlagn: fix panic in iwl{5000,4965}_rx_reply_tx
  ath9k: Fix RFKILL bugs
  drivers/net/wireless: Use usb_endpoint_dir_out
  cfg80211: don't overwrite privacy setting
  wl12xx: fix kconfig/link errors
  rt2x00: fix the definition of rt2x00crypto_rx_insert_iv
  iwlwifi: reduce noise when skb allocation fails
  iwlwifi: do not send sync command while holding spinlock
  mac80211: fix DTIM setting
  ...
Linus Torvalds 16 жил өмнө
parent
commit
5c3cc2084d
93 өөрчлөгдсөн 2610 нэмэгдсэн , 2909 устгасан
  1. 36 0
      arch/arm/mach-at91/at91sam9263_devices.c
  2. 19 0
      arch/arm/mach-at91/board-sam9263ek.c
  3. 6 0
      arch/arm/mach-at91/include/mach/board.h
  4. 50 9
      drivers/atm/he.c
  5. 11 0
      drivers/atm/solos-attrlist.c
  6. 66 9
      drivers/atm/solos-pci.c
  7. 3 9
      drivers/net/3c59x.c
  8. 1 1
      drivers/net/8139cp.c
  9. 1 1
      drivers/net/Kconfig
  10. 1 1
      drivers/net/atl1c/atl1c_main.c
  11. 13 0
      drivers/net/can/Kconfig
  12. 3 0
      drivers/net/can/Makefile
  13. 9 7
      drivers/net/can/sja1000/ems_pci.c
  14. 5 0
      drivers/net/can/usb/Makefile
  15. 1155 0
      drivers/net/can/usb/ems_usb.c
  16. 2 2
      drivers/net/cnic.c
  17. 4 4
      drivers/net/cpmac.c
  18. 0 1
      drivers/net/ehea/ehea_main.c
  19. 36 36
      drivers/net/igb/e1000_mac.c
  20. 0 1
      drivers/net/igb/e1000_mac.h
  21. 4 2
      drivers/net/ixgbe/ixgbe.h
  22. 61 14
      drivers/net/ixgbe/ixgbe_ethtool.c
  23. 67 44
      drivers/net/ixgbe/ixgbe_main.c
  24. 4 4
      drivers/net/netxen/netxen_nic_main.c
  25. 5 6
      drivers/net/pcmcia/pcnet_cs.c
  26. 3 1
      drivers/net/sky2.c
  27. 0 1
      drivers/net/sunvnet.c
  28. 1 3
      drivers/net/tun.c
  29. 11 7
      drivers/net/usb/kaweth.c
  30. 66 1
      drivers/net/usb/smsc95xx.c
  31. 1 1
      drivers/net/usb/usbnet.c
  32. 2 0
      drivers/net/wireless/ath/ar9170/usb.c
  33. 18 5
      drivers/net/wireless/ath/ath9k/calib.c
  34. 1 0
      drivers/net/wireless/ath/ath9k/calib.h
  35. 3 1
      drivers/net/wireless/ath/ath9k/eeprom_def.c
  36. 121 81
      drivers/net/wireless/ath/ath9k/hw.c
  37. 2 2
      drivers/net/wireless/ath/ath9k/hw.h
  38. 5 11
      drivers/net/wireless/ath/ath9k/main.c
  39. 2 1
      drivers/net/wireless/ath/ath9k/reg.h
  40. 19 2
      drivers/net/wireless/b43/Kconfig
  41. 1 0
      drivers/net/wireless/b43/Makefile
  42. 7 16
      drivers/net/wireless/b43/b43.h
  43. 1 0
      drivers/net/wireless/b43/debugfs.c
  44. 1 0
      drivers/net/wireless/b43/debugfs.h
  45. 2 2
      drivers/net/wireless/b43/dma.c
  46. 191 75
      drivers/net/wireless/b43/leds.c
  47. 31 2
      drivers/net/wireless/b43/leds.h
  48. 128 96
      drivers/net/wireless/b43/main.c
  49. 11 1
      drivers/net/wireless/b43/phy_lp.c
  50. 1 1
      drivers/net/wireless/b43/pio.c
  51. 1 1
      drivers/net/wireless/b43/rfkill.c
  52. 202 0
      drivers/net/wireless/b43/sdio.c
  53. 45 0
      drivers/net/wireless/b43/sdio.h
  54. 4 1
      drivers/net/wireless/b43/xmit.c
  55. 6 0
      drivers/net/wireless/iwlwifi/iwl-4965.c
  56. 6 0
      drivers/net/wireless/iwlwifi/iwl-5000.c
  57. 9 1
      drivers/net/wireless/iwlwifi/iwl-rx.c
  58. 1 1
      drivers/net/wireless/iwlwifi/iwl-sta.c
  59. 8 1
      drivers/net/wireless/iwlwifi/iwl3945-base.c
  60. 1 1
      drivers/net/wireless/rt2x00/rt2x00lib.h
  61. 1 1
      drivers/net/wireless/wl12xx/Kconfig
  62. 1 1
      drivers/net/wireless/zd1211rw/zd_usb.c
  63. 2 5
      drivers/net/xilinx_emaclite.c
  64. 0 2
      drivers/staging/Kconfig
  65. 0 1
      drivers/staging/Makefile
  66. 0 4
      drivers/staging/cpc-usb/Kconfig
  67. 0 3
      drivers/staging/cpc-usb/Makefile
  68. 0 10
      drivers/staging/cpc-usb/TODO
  69. 0 1184
      drivers/staging/cpc-usb/cpc-usb_drv.c
  70. 0 417
      drivers/staging/cpc-usb/cpc.h
  71. 0 83
      drivers/staging/cpc-usb/cpc_int.h
  72. 0 86
      drivers/staging/cpc-usb/cpcusb.h
  73. 0 41
      drivers/staging/cpc-usb/sja2m16c.h
  74. 0 452
      drivers/staging/cpc-usb/sja2m16c_2.c
  75. 1 0
      include/linux/netlink.h
  76. 1 0
      include/linux/phonet.h
  77. 1 0
      include/linux/usb/usbnet.h
  78. 0 1
      include/net/ipip.h
  79. 1 0
      kernel/sys_ni.c
  80. 15 10
      lib/vsprintf.c
  81. 2 2
      net/ax25/af_ax25.c
  82. 76 84
      net/core/pktgen.c
  83. 1 12
      net/ipv4/ip_gre.c
  84. 3 0
      net/ipv4/ip_sockglue.c
  85. 0 8
      net/ipv4/ipip.c
  86. 0 7
      net/ipv6/ip6_tunnel.c
  87. 0 8
      net/ipv6/sit.c
  88. 2 2
      net/mac80211/scan.c
  89. 11 8
      net/netlink/af_netlink.c
  90. 3 1
      net/netlink/genetlink.c
  91. 6 0
      net/phonet/af_phonet.c
  92. 8 8
      net/phonet/socket.c
  93. 1 1
      net/wireless/wext-sme.c

+ 36 - 0
arch/arm/mach-at91/at91sam9263_devices.c

@@ -757,6 +757,42 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data)
 void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
 void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
 #endif
 #endif
 
 
+/* --------------------------------------------------------------------
+ *  CAN Controller
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_CAN_AT91) || defined(CONFIG_CAN_AT91_MODULE)
+static struct resource can_resources[] = {
+	[0] = {
+		.start	= AT91SAM9263_BASE_CAN,
+		.end	= AT91SAM9263_BASE_CAN + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9263_ID_CAN,
+		.end	= AT91SAM9263_ID_CAN,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9263_can_device = {
+	.name		= "at91_can",
+	.id		= -1,
+	.resource	= can_resources,
+	.num_resources	= ARRAY_SIZE(can_resources),
+};
+
+void __init at91_add_device_can(struct at91_can_data *data)
+{
+	at91_set_A_periph(AT91_PIN_PA13, 0);	/* CANTX */
+	at91_set_A_periph(AT91_PIN_PA14, 0);	/* CANRX */
+	at91sam9263_can_device.dev.platform_data = data;
+
+	platform_device_register(&at91sam9263_can_device);
+}
+#else
+void __init at91_add_device_can(struct at91_can_data *data) {}
+#endif
 
 
 /* --------------------------------------------------------------------
 /* --------------------------------------------------------------------
  *  LCD Controller
  *  LCD Controller

+ 19 - 0
arch/arm/mach-at91/board-sam9263ek.c

@@ -400,6 +400,23 @@ static struct gpio_led ek_pwm_led[] = {
 	}
 	}
 };
 };
 
 
+/*
+ * CAN
+ */
+static void sam9263ek_transceiver_switch(int on)
+{
+	if (on) {
+		at91_set_gpio_output(AT91_PIN_PA18, 1); /* CANRXEN */
+		at91_set_gpio_output(AT91_PIN_PA19, 0); /* CANRS */
+	} else {
+		at91_set_gpio_output(AT91_PIN_PA18, 0); /* CANRXEN */
+		at91_set_gpio_output(AT91_PIN_PA19, 1); /* CANRS */
+	}
+}
+
+static struct at91_can_data ek_can_data = {
+	.transceiver_switch = sam9263ek_transceiver_switch,
+};
 
 
 static void __init ek_board_init(void)
 static void __init ek_board_init(void)
 {
 {
@@ -431,6 +448,8 @@ static void __init ek_board_init(void)
 	/* LEDs */
 	/* LEDs */
 	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
 	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
 	at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
 	at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
+	/* CAN */
+	at91_add_device_can(&ek_can_data);
 }
 }
 
 
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")

+ 6 - 0
arch/arm/mach-at91/include/mach/board.h

@@ -188,6 +188,12 @@ extern void __init at91_add_device_isi(void);
  /* Touchscreen Controller */
  /* Touchscreen Controller */
 extern void __init at91_add_device_tsadcc(void);
 extern void __init at91_add_device_tsadcc(void);
 
 
+/* CAN */
+struct at91_can_data {
+	void (*transceiver_switch)(int on);
+};
+extern void __init at91_add_device_can(struct at91_can_data *data);
+
  /* LEDs */
  /* LEDs */
 extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
 extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
 extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
 extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);

+ 50 - 9
drivers/atm/he.c

@@ -790,11 +790,15 @@ he_init_group(struct he_dev *he_dev, int group)
 	he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
 	he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
 		CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
 		CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
 	if (he_dev->rbps_base == NULL) {
 	if (he_dev->rbps_base == NULL) {
-		hprintk("failed to alloc rbps\n");
-		return -ENOMEM;
+		hprintk("failed to alloc rbps_base\n");
+		goto out_destroy_rbps_pool;
 	}
 	}
 	memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
 	memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
 	he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
 	he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+	if (he_dev->rbps_virt == NULL) {
+		hprintk("failed to alloc rbps_virt\n");
+		goto out_free_rbps_base;
+	}
 
 
 	for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
 	for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
 		dma_addr_t dma_handle;
 		dma_addr_t dma_handle;
@@ -802,7 +806,7 @@ he_init_group(struct he_dev *he_dev, int group)
 
 
 		cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
 		cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
 		if (cpuaddr == NULL)
 		if (cpuaddr == NULL)
-			return -ENOMEM;
+			goto out_free_rbps_virt;
 
 
 		he_dev->rbps_virt[i].virt = cpuaddr;
 		he_dev->rbps_virt[i].virt = cpuaddr;
 		he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
 		he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
@@ -827,17 +831,21 @@ he_init_group(struct he_dev *he_dev, int group)
 			CONFIG_RBPL_BUFSIZE, 8, 0);
 			CONFIG_RBPL_BUFSIZE, 8, 0);
 	if (he_dev->rbpl_pool == NULL) {
 	if (he_dev->rbpl_pool == NULL) {
 		hprintk("unable to create rbpl pool\n");
 		hprintk("unable to create rbpl pool\n");
-		return -ENOMEM;
+		goto out_free_rbps_virt;
 	}
 	}
 
 
 	he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
 	he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
 		CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
 		CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
 	if (he_dev->rbpl_base == NULL) {
 	if (he_dev->rbpl_base == NULL) {
-		hprintk("failed to alloc rbpl\n");
-		return -ENOMEM;
+		hprintk("failed to alloc rbpl_base\n");
+		goto out_destroy_rbpl_pool;
 	}
 	}
 	memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
 	memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
 	he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
 	he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+	if (he_dev->rbpl_virt == NULL) {
+		hprintk("failed to alloc rbpl_virt\n");
+		goto out_free_rbpl_base;
+	}
 
 
 	for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
 	for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
 		dma_addr_t dma_handle;
 		dma_addr_t dma_handle;
@@ -845,7 +853,7 @@ he_init_group(struct he_dev *he_dev, int group)
 
 
 		cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
 		cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
 		if (cpuaddr == NULL)
 		if (cpuaddr == NULL)
-			return -ENOMEM;
+			goto out_free_rbpl_virt;
 
 
 		he_dev->rbpl_virt[i].virt = cpuaddr;
 		he_dev->rbpl_virt[i].virt = cpuaddr;
 		he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
 		he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
@@ -870,7 +878,7 @@ he_init_group(struct he_dev *he_dev, int group)
 		CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
 		CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
 	if (he_dev->rbrq_base == NULL) {
 	if (he_dev->rbrq_base == NULL) {
 		hprintk("failed to allocate rbrq\n");
 		hprintk("failed to allocate rbrq\n");
-		return -ENOMEM;
+		goto out_free_rbpl_virt;
 	}
 	}
 	memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
 	memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
 
 
@@ -894,7 +902,7 @@ he_init_group(struct he_dev *he_dev, int group)
 		CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
 		CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
 	if (he_dev->tbrq_base == NULL) {
 	if (he_dev->tbrq_base == NULL) {
 		hprintk("failed to allocate tbrq\n");
 		hprintk("failed to allocate tbrq\n");
-		return -ENOMEM;
+		goto out_free_rbpq_base;
 	}
 	}
 	memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
 	memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
 
 
@@ -906,6 +914,39 @@ he_init_group(struct he_dev *he_dev, int group)
 	he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
 	he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
 
 
 	return 0;
 	return 0;
+
+out_free_rbpq_base:
+	pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE *
+			sizeof(struct he_rbrq), he_dev->rbrq_base,
+			he_dev->rbrq_phys);
+	i = CONFIG_RBPL_SIZE;
+out_free_rbpl_virt:
+	while (--i)
+		pci_pool_free(he_dev->rbps_pool, he_dev->rbpl_virt[i].virt,
+				he_dev->rbps_base[i].phys);
+	kfree(he_dev->rbpl_virt);
+
+out_free_rbpl_base:
+	pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE *
+			sizeof(struct he_rbp), he_dev->rbpl_base,
+			he_dev->rbpl_phys);
+out_destroy_rbpl_pool:
+	pci_pool_destroy(he_dev->rbpl_pool);
+
+	i = CONFIG_RBPL_SIZE;
+out_free_rbps_virt:
+	while (--i)
+		pci_pool_free(he_dev->rbpl_pool, he_dev->rbps_virt[i].virt,
+				he_dev->rbpl_base[i].phys);
+	kfree(he_dev->rbps_virt);
+
+out_free_rbps_base:
+	pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE *
+			sizeof(struct he_rbp), he_dev->rbps_base,
+			he_dev->rbps_phys);
+out_destroy_rbps_pool:
+	pci_pool_destroy(he_dev->rbps_pool);
+	return -ENOMEM;
 }
 }
 
 
 static int __devinit
 static int __devinit

+ 11 - 0
drivers/atm/solos-attrlist.c

@@ -25,6 +25,10 @@ SOLOS_ATTR_RO(RSCorrectedErrorsUp)
 SOLOS_ATTR_RO(RSUnCorrectedErrorsUp)
 SOLOS_ATTR_RO(RSUnCorrectedErrorsUp)
 SOLOS_ATTR_RO(InterleaveRDn)
 SOLOS_ATTR_RO(InterleaveRDn)
 SOLOS_ATTR_RO(InterleaveRUp)
 SOLOS_ATTR_RO(InterleaveRUp)
+SOLOS_ATTR_RO(BisRDn)
+SOLOS_ATTR_RO(BisRUp)
+SOLOS_ATTR_RO(INPdown)
+SOLOS_ATTR_RO(INPup)
 SOLOS_ATTR_RO(ShowtimeStart)
 SOLOS_ATTR_RO(ShowtimeStart)
 SOLOS_ATTR_RO(ATURVendor)
 SOLOS_ATTR_RO(ATURVendor)
 SOLOS_ATTR_RO(ATUCCountry)
 SOLOS_ATTR_RO(ATUCCountry)
@@ -62,6 +66,13 @@ SOLOS_ATTR_RW(Defaults)
 SOLOS_ATTR_RW(LineMode)
 SOLOS_ATTR_RW(LineMode)
 SOLOS_ATTR_RW(Profile)
 SOLOS_ATTR_RW(Profile)
 SOLOS_ATTR_RW(DetectNoise)
 SOLOS_ATTR_RW(DetectNoise)
+SOLOS_ATTR_RW(BisAForceSNRMarginDn)
+SOLOS_ATTR_RW(BisMForceSNRMarginDn)
+SOLOS_ATTR_RW(BisAMaxMargin)
+SOLOS_ATTR_RW(BisMMaxMargin)
+SOLOS_ATTR_RW(AnnexAForceSNRMarginDn)
+SOLOS_ATTR_RW(AnnexAMaxMargin)
+SOLOS_ATTR_RW(AnnexMMaxMargin)
 SOLOS_ATTR_RO(SupportedAnnexes)
 SOLOS_ATTR_RO(SupportedAnnexes)
 SOLOS_ATTR_RO(Status)
 SOLOS_ATTR_RO(Status)
 SOLOS_ATTR_RO(TotalStart)
 SOLOS_ATTR_RO(TotalStart)

+ 66 - 9
drivers/atm/solos-pci.c

@@ -59,21 +59,29 @@
 #define RX_DMA_ADDR(port)	(0x30 + (4 * (port)))
 #define RX_DMA_ADDR(port)	(0x30 + (4 * (port)))
 
 
 #define DATA_RAM_SIZE	32768
 #define DATA_RAM_SIZE	32768
-#define BUF_SIZE	4096
+#define BUF_SIZE	2048
+#define OLD_BUF_SIZE	4096 /* For FPGA versions <= 2*/
 #define FPGA_PAGE	528 /* FPGA flash page size*/
 #define FPGA_PAGE	528 /* FPGA flash page size*/
 #define SOLOS_PAGE	512 /* Solos flash page size*/
 #define SOLOS_PAGE	512 /* Solos flash page size*/
 #define FPGA_BLOCK	(FPGA_PAGE * 8) /* FPGA flash block size*/
 #define FPGA_BLOCK	(FPGA_PAGE * 8) /* FPGA flash block size*/
 #define SOLOS_BLOCK	(SOLOS_PAGE * 8) /* Solos flash block size*/
 #define SOLOS_BLOCK	(SOLOS_PAGE * 8) /* Solos flash block size*/
 
 
-#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2)
-#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE)
+#define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2)
+#define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size))
+#define FLASH_BUF ((card->buffers) + 4*(card->buffer_size)*2)
 
 
 #define RX_DMA_SIZE	2048
 #define RX_DMA_SIZE	2048
 
 
+#define FPGA_VERSION(a,b) (((a) << 8) + (b))
+#define LEGACY_BUFFERS	2
+#define DMA_SUPPORTED	4
+
 static int reset = 0;
 static int reset = 0;
 static int atmdebug = 0;
 static int atmdebug = 0;
 static int firmware_upgrade = 0;
 static int firmware_upgrade = 0;
 static int fpga_upgrade = 0;
 static int fpga_upgrade = 0;
+static int db_firmware_upgrade = 0;
+static int db_fpga_upgrade = 0;
 
 
 struct pkt_hdr {
 struct pkt_hdr {
 	__le16 size;
 	__le16 size;
@@ -116,6 +124,8 @@ struct solos_card {
 	wait_queue_head_t param_wq;
 	wait_queue_head_t param_wq;
 	wait_queue_head_t fw_wq;
 	wait_queue_head_t fw_wq;
 	int using_dma;
 	int using_dma;
+	int fpga_version;
+	int buffer_size;
 };
 };
 
 
 
 
@@ -136,10 +146,14 @@ MODULE_PARM_DESC(reset, "Reset Solos chips on startup");
 MODULE_PARM_DESC(atmdebug, "Print ATM data");
 MODULE_PARM_DESC(atmdebug, "Print ATM data");
 MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
 MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
 MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade");
 MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade");
+MODULE_PARM_DESC(db_firmware_upgrade, "Initiate daughter board Solos firmware upgrade");
+MODULE_PARM_DESC(db_fpga_upgrade, "Initiate daughter board FPGA upgrade");
 module_param(reset, int, 0444);
 module_param(reset, int, 0444);
 module_param(atmdebug, int, 0644);
 module_param(atmdebug, int, 0644);
 module_param(firmware_upgrade, int, 0444);
 module_param(firmware_upgrade, int, 0444);
 module_param(fpga_upgrade, int, 0444);
 module_param(fpga_upgrade, int, 0444);
+module_param(db_firmware_upgrade, int, 0444);
+module_param(db_fpga_upgrade, int, 0444);
 
 
 static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
 static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
 		       struct atm_vcc *vcc);
 		       struct atm_vcc *vcc);
@@ -517,10 +531,32 @@ static int flash_upgrade(struct solos_card *card, int chip)
 	if (chip == 0) {
 	if (chip == 0) {
 		fw_name = "solos-FPGA.bin";
 		fw_name = "solos-FPGA.bin";
 		blocksize = FPGA_BLOCK;
 		blocksize = FPGA_BLOCK;
-	} else {
+	} 
+	
+	if (chip == 1) {
 		fw_name = "solos-Firmware.bin";
 		fw_name = "solos-Firmware.bin";
 		blocksize = SOLOS_BLOCK;
 		blocksize = SOLOS_BLOCK;
 	}
 	}
+	
+	if (chip == 2){
+		if (card->fpga_version > LEGACY_BUFFERS){
+			fw_name = "solos-db-FPGA.bin";
+			blocksize = FPGA_BLOCK;
+		} else {
+			dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n");
+			return -EPERM;
+		}
+	}
+	
+	if (chip == 3){
+		if (card->fpga_version > LEGACY_BUFFERS){
+			fw_name = "solos-Firmware.bin";
+			blocksize = SOLOS_BLOCK;
+		} else {
+		dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n");
+		return -EPERM;
+		}
+	}
 
 
 	if (request_firmware(&fw, fw_name, &card->dev->dev))
 	if (request_firmware(&fw, fw_name, &card->dev->dev))
 		return -ENOENT;
 		return -ENOENT;
@@ -536,8 +572,10 @@ static int flash_upgrade(struct solos_card *card, int chip)
 	data32 = ioread32(card->config_regs + FPGA_MODE); 
 	data32 = ioread32(card->config_regs + FPGA_MODE); 
 
 
 	/* Set mode to Chip Erase */
 	/* Set mode to Chip Erase */
-	dev_info(&card->dev->dev, "Set FPGA Flash mode to %s Chip Erase\n",
-		 chip?"Solos":"FPGA");
+	if(chip == 0 || chip == 2)
+		dev_info(&card->dev->dev, "Set FPGA Flash mode to FPGA Chip Erase\n");
+	if(chip == 1 || chip == 3)
+		dev_info(&card->dev->dev, "Set FPGA Flash mode to Solos Chip Erase\n");
 	iowrite32((chip * 2), card->config_regs + FLASH_MODE);
 	iowrite32((chip * 2), card->config_regs + FLASH_MODE);
 
 
 
 
@@ -557,7 +595,10 @@ static int flash_upgrade(struct solos_card *card, int chip)
 		/* Copy block to buffer, swapping each 16 bits */
 		/* Copy block to buffer, swapping each 16 bits */
 		for(i = 0; i < blocksize; i += 4) {
 		for(i = 0; i < blocksize; i += 4) {
 			uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i));
 			uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i));
-			iowrite32(word, RX_BUF(card, 3) + i);
+			if(card->fpga_version > LEGACY_BUFFERS)
+				iowrite32(word, FLASH_BUF + i);
+			else
+				iowrite32(word, RX_BUF(card, 3) + i);
 		}
 		}
 
 
 		/* Specify block number and then trigger flash write */
 		/* Specify block number and then trigger flash write */
@@ -630,6 +671,10 @@ void solos_bh(unsigned long card_arg)
 				memcpy_fromio(header, RX_BUF(card, port), sizeof(*header));
 				memcpy_fromio(header, RX_BUF(card, port), sizeof(*header));
 
 
 				size = le16_to_cpu(header->size);
 				size = le16_to_cpu(header->size);
+				if (size > (card->buffer_size - sizeof(*header))){
+					dev_warn(&card->dev->dev, "Invalid buffer size\n");
+					continue;
+				}
 
 
 				skb = alloc_skb(size + 1, GFP_ATOMIC);
 				skb = alloc_skb(size + 1, GFP_ATOMIC);
 				if (!skb) {
 				if (!skb) {
@@ -1094,12 +1139,18 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	fpga_ver = (data32 & 0x0000FFFF);
 	fpga_ver = (data32 & 0x0000FFFF);
 	major_ver = ((data32 & 0xFF000000) >> 24);
 	major_ver = ((data32 & 0xFF000000) >> 24);
 	minor_ver = ((data32 & 0x00FF0000) >> 16);
 	minor_ver = ((data32 & 0x00FF0000) >> 16);
+	card->fpga_version = FPGA_VERSION(major_ver,minor_ver);
+	if (card->fpga_version > LEGACY_BUFFERS)
+		card->buffer_size = BUF_SIZE;
+	else
+		card->buffer_size = OLD_BUF_SIZE;
 	dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n",
 	dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n",
 		 major_ver, minor_ver, fpga_ver);
 		 major_ver, minor_ver, fpga_ver);
 
 
-	if (0 && fpga_ver > 27)
+	if (card->fpga_version >= DMA_SUPPORTED){
 		card->using_dma = 1;
 		card->using_dma = 1;
-	else {
+	} else {
+		card->using_dma = 0;
 		/* Set RX empty flag for all ports */
 		/* Set RX empty flag for all ports */
 		iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
 		iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
 	}
 	}
@@ -1131,6 +1182,12 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	if (firmware_upgrade)
 	if (firmware_upgrade)
 		flash_upgrade(card, 1);
 		flash_upgrade(card, 1);
 
 
+	if (db_fpga_upgrade)
+		flash_upgrade(card, 2);
+
+	if (db_firmware_upgrade)
+		flash_upgrade(card, 3);
+
 	err = atm_init(card);
 	err = atm_init(card);
 	if (err)
 	if (err)
 		goto out_free_irq;
 		goto out_free_irq;

+ 3 - 9
drivers/net/3c59x.c

@@ -813,10 +813,10 @@ static int vortex_suspend(struct pci_dev *pdev, pm_message_t state)
 		if (netif_running(dev)) {
 		if (netif_running(dev)) {
 			netif_device_detach(dev);
 			netif_device_detach(dev);
 			vortex_down(dev, 1);
 			vortex_down(dev, 1);
+			disable_irq(dev->irq);
 		}
 		}
 		pci_save_state(pdev);
 		pci_save_state(pdev);
 		pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
 		pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
-		free_irq(dev->irq, dev);
 		pci_disable_device(pdev);
 		pci_disable_device(pdev);
 		pci_set_power_state(pdev, pci_choose_state(pdev, state));
 		pci_set_power_state(pdev, pci_choose_state(pdev, state));
 	}
 	}
@@ -839,18 +839,12 @@ static int vortex_resume(struct pci_dev *pdev)
 			return err;
 			return err;
 		}
 		}
 		pci_set_master(pdev);
 		pci_set_master(pdev);
-		if (request_irq(dev->irq, vp->full_bus_master_rx ?
-				&boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev)) {
-			pr_warning("%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
-			pci_disable_device(pdev);
-			return -EBUSY;
-		}
 		if (netif_running(dev)) {
 		if (netif_running(dev)) {
 			err = vortex_up(dev);
 			err = vortex_up(dev);
 			if (err)
 			if (err)
 				return err;
 				return err;
-			else
-				netif_device_attach(dev);
+			enable_irq(dev->irq);
+			netif_device_attach(dev);
 		}
 		}
 	}
 	}
 	return 0;
 	return 0;

+ 1 - 1
drivers/net/8139cp.c

@@ -87,7 +87,7 @@
 
 
 /* These identify the driver base version and may not be removed. */
 /* These identify the driver base version and may not be removed. */
 static char version[] =
 static char version[] =
-KERN_INFO DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
+DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
 
 
 MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
 MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
 MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");
 MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");

+ 1 - 1
drivers/net/Kconfig

@@ -1875,7 +1875,7 @@ config 68360_ENET
 
 
 config FEC
 config FEC
 	bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
 	bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
-	depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35
+	depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35 || ARCH_MX25
 	help
 	help
 	  Say Y here if you want to use the built-in 10/100 Fast ethernet
 	  Say Y here if you want to use the built-in 10/100 Fast ethernet
 	  controller on some Motorola ColdFire and Freescale i.MX processors.
 	  controller on some Motorola ColdFire and Freescale i.MX processors.

+ 1 - 1
drivers/net/atl1c/atl1c_main.c

@@ -2296,7 +2296,7 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
 	u32 ctrl;
 	u32 ctrl;
 	u32 mac_ctrl_data;
 	u32 mac_ctrl_data;
 	u32 master_ctrl_data;
 	u32 master_ctrl_data;
-	u32 wol_ctrl_data;
+	u32 wol_ctrl_data = 0;
 	u16 mii_bmsr_data;
 	u16 mii_bmsr_data;
 	u16 save_autoneg_advertised;
 	u16 save_autoneg_advertised;
 	u16 mii_intr_status_data;
 	u16 mii_intr_status_data;

+ 13 - 0
drivers/net/can/Kconfig

@@ -75,6 +75,13 @@ config CAN_EMS_PCI
 	  CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
 	  CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
 	  (http://www.ems-wuensche.de).
 	  (http://www.ems-wuensche.de).
 
 
+config CAN_EMS_USB
+	tristate "EMS CPC-USB/ARM7 CAN/USB interface"
+	depends on USB && CAN_DEV
+	---help---
+	  This driver is for the one channel CPC-USB/ARM7 CAN/USB interface
+	  from from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
+
 config CAN_KVASER_PCI
 config CAN_KVASER_PCI
 	tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
 	tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
 	depends on PCI && CAN_SJA1000
 	depends on PCI && CAN_SJA1000
@@ -82,6 +89,12 @@ config CAN_KVASER_PCI
 	  This driver is for the the PCIcanx and PCIcan cards (1, 2 or
 	  This driver is for the the PCIcanx and PCIcan cards (1, 2 or
 	  4 channel) from Kvaser (http://www.kvaser.com).
 	  4 channel) from Kvaser (http://www.kvaser.com).
 
 
+config CAN_AT91
+	tristate "Atmel AT91 onchip CAN controller"
+	depends on CAN && CAN_DEV && ARCH_AT91SAM9263
+	---help---
+	  This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
+
 config CAN_DEBUG_DEVICES
 config CAN_DEBUG_DEVICES
 	bool "CAN devices debugging messages"
 	bool "CAN devices debugging messages"
 	depends on CAN
 	depends on CAN

+ 3 - 0
drivers/net/can/Makefile

@@ -7,6 +7,9 @@ obj-$(CONFIG_CAN_VCAN)		+= vcan.o
 obj-$(CONFIG_CAN_DEV)		+= can-dev.o
 obj-$(CONFIG_CAN_DEV)		+= can-dev.o
 can-dev-y			:= dev.o
 can-dev-y			:= dev.o
 
 
+obj-y				+= usb/
+
 obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
 obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
+obj-$(CONFIG_CAN_AT91)		+= at91_can.o
 
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG

+ 9 - 7
drivers/net/can/sja1000/ems_pci.c

@@ -94,12 +94,14 @@ struct ems_pci_card {
 #define EMS_PCI_CDR             (CDR_CBP | CDR_CLKOUT_MASK)
 #define EMS_PCI_CDR             (CDR_CBP | CDR_CLKOUT_MASK)
 
 
 #define EMS_PCI_V1_BASE_BAR     1
 #define EMS_PCI_V1_BASE_BAR     1
-#define EMS_PCI_V1_MEM_SIZE     4096
+#define EMS_PCI_V1_CONF_SIZE    4096 /* size of PITA control area */
 #define EMS_PCI_V2_BASE_BAR     2
 #define EMS_PCI_V2_BASE_BAR     2
-#define EMS_PCI_V2_MEM_SIZE     128
+#define EMS_PCI_V2_CONF_SIZE    128 /* size of PLX control area */
 #define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */
 #define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */
 #define EMS_PCI_CAN_CTRL_SIZE   0x200 /* memory size for each controller */
 #define EMS_PCI_CAN_CTRL_SIZE   0x200 /* memory size for each controller */
 
 
+#define EMS_PCI_BASE_SIZE  4096 /* size of controller area */
+
 static struct pci_device_id ems_pci_tbl[] = {
 static struct pci_device_id ems_pci_tbl[] = {
 	/* CPC-PCI v1 */
 	/* CPC-PCI v1 */
 	{PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,},
 	{PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,},
@@ -224,7 +226,7 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev,
 	struct sja1000_priv *priv;
 	struct sja1000_priv *priv;
 	struct net_device *dev;
 	struct net_device *dev;
 	struct ems_pci_card *card;
 	struct ems_pci_card *card;
-	int max_chan, mem_size, base_bar;
+	int max_chan, conf_size, base_bar;
 	int err, i;
 	int err, i;
 
 
 	/* Enabling PCI device */
 	/* Enabling PCI device */
@@ -251,22 +253,22 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev,
 		card->version = 2; /* CPC-PCI v2 */
 		card->version = 2; /* CPC-PCI v2 */
 		max_chan = EMS_PCI_V2_MAX_CHAN;
 		max_chan = EMS_PCI_V2_MAX_CHAN;
 		base_bar = EMS_PCI_V2_BASE_BAR;
 		base_bar = EMS_PCI_V2_BASE_BAR;
-		mem_size = EMS_PCI_V2_MEM_SIZE;
+		conf_size = EMS_PCI_V2_CONF_SIZE;
 	} else {
 	} else {
 		card->version = 1; /* CPC-PCI v1 */
 		card->version = 1; /* CPC-PCI v1 */
 		max_chan = EMS_PCI_V1_MAX_CHAN;
 		max_chan = EMS_PCI_V1_MAX_CHAN;
 		base_bar = EMS_PCI_V1_BASE_BAR;
 		base_bar = EMS_PCI_V1_BASE_BAR;
-		mem_size = EMS_PCI_V1_MEM_SIZE;
+		conf_size = EMS_PCI_V1_CONF_SIZE;
 	}
 	}
 
 
 	/* Remap configuration space and controller memory area */
 	/* Remap configuration space and controller memory area */
-	card->conf_addr = pci_iomap(pdev, 0, mem_size);
+	card->conf_addr = pci_iomap(pdev, 0, conf_size);
 	if (card->conf_addr == NULL) {
 	if (card->conf_addr == NULL) {
 		err = -ENOMEM;
 		err = -ENOMEM;
 		goto failure_cleanup;
 		goto failure_cleanup;
 	}
 	}
 
 
-	card->base_addr = pci_iomap(pdev, base_bar, mem_size);
+	card->base_addr = pci_iomap(pdev, base_bar, EMS_PCI_BASE_SIZE);
 	if (card->base_addr == NULL) {
 	if (card->base_addr == NULL) {
 		err = -ENOMEM;
 		err = -ENOMEM;
 		goto failure_cleanup;
 		goto failure_cleanup;

+ 5 - 0
drivers/net/can/usb/Makefile

@@ -0,0 +1,5 @@
+#
+#  Makefile for the Linux Controller Area Network USB drivers.
+#
+
+obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o

+ 1155 - 0
drivers/net/can/usb/ems_usb.c

@@ -0,0 +1,1155 @@
+/*
+ * CAN driver for EMS Dr. Thomas Wuensche CPC-USB/ARM7
+ *
+ * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+MODULE_AUTHOR("Sebastian Haas <haas@ems-wuensche.com>");
+MODULE_DESCRIPTION("CAN driver for EMS Dr. Thomas Wuensche CAN/USB interfaces");
+MODULE_LICENSE("GPL v2");
+
+/* Control-Values for CPC_Control() Command Subject Selection */
+#define CONTR_CAN_MESSAGE 0x04
+#define CONTR_CAN_STATE   0x0C
+#define CONTR_BUS_ERROR   0x1C
+
+/* Control Command Actions */
+#define CONTR_CONT_OFF 0
+#define CONTR_CONT_ON  1
+#define CONTR_ONCE     2
+
+/* Messages from CPC to PC */
+#define CPC_MSG_TYPE_CAN_FRAME       1  /* CAN data frame */
+#define CPC_MSG_TYPE_RTR_FRAME       8  /* CAN remote frame */
+#define CPC_MSG_TYPE_CAN_PARAMS      12 /* Actual CAN parameters */
+#define CPC_MSG_TYPE_CAN_STATE       14 /* CAN state message */
+#define CPC_MSG_TYPE_EXT_CAN_FRAME   16 /* Extended CAN data frame */
+#define CPC_MSG_TYPE_EXT_RTR_FRAME   17 /* Extended remote frame */
+#define CPC_MSG_TYPE_CONTROL         19 /* change interface behavior */
+#define CPC_MSG_TYPE_CONFIRM         20 /* command processed confirmation */
+#define CPC_MSG_TYPE_OVERRUN         21 /* overrun events */
+#define CPC_MSG_TYPE_CAN_FRAME_ERROR 23 /* detected bus errors */
+#define CPC_MSG_TYPE_ERR_COUNTER     25 /* RX/TX error counter */
+
+/* Messages from the PC to the CPC interface  */
+#define CPC_CMD_TYPE_CAN_FRAME     1   /* CAN data frame */
+#define CPC_CMD_TYPE_CONTROL       3   /* control of interface behavior */
+#define CPC_CMD_TYPE_CAN_PARAMS    6   /* set CAN parameters */
+#define CPC_CMD_TYPE_RTR_FRAME     13  /* CAN remote frame */
+#define CPC_CMD_TYPE_CAN_STATE     14  /* CAN state message */
+#define CPC_CMD_TYPE_EXT_CAN_FRAME 15  /* Extended CAN data frame */
+#define CPC_CMD_TYPE_EXT_RTR_FRAME 16  /* Extended CAN remote frame */
+#define CPC_CMD_TYPE_CAN_EXIT      200 /* exit the CAN */
+
+#define CPC_CMD_TYPE_INQ_ERR_COUNTER 25 /* request the CAN error counters */
+#define CPC_CMD_TYPE_CLEAR_MSG_QUEUE 8  /* clear CPC_MSG queue */
+#define CPC_CMD_TYPE_CLEAR_CMD_QUEUE 28 /* clear CPC_CMD queue */
+
+#define CPC_CC_TYPE_SJA1000 2 /* Philips basic CAN controller */
+
+#define CPC_CAN_ECODE_ERRFRAME 0x01 /* Ecode type */
+
+/* Overrun types */
+#define CPC_OVR_EVENT_CAN       0x01
+#define CPC_OVR_EVENT_CANSTATE  0x02
+#define CPC_OVR_EVENT_BUSERROR  0x04
+
+/*
+ * If the CAN controller lost a message we indicate it with the highest bit
+ * set in the count field.
+ */
+#define CPC_OVR_HW 0x80
+
+/* Size of the "struct ems_cpc_msg" without the union */
+#define CPC_MSG_HEADER_LEN   11
+#define CPC_CAN_MSG_MIN_SIZE 5
+
+/* Define these values to match your devices */
+#define USB_CPCUSB_VENDOR_ID 0x12D6
+
+#define USB_CPCUSB_ARM7_PRODUCT_ID 0x0444
+
+/* Mode register NXP LPC2119/SJA1000 CAN Controller */
+#define SJA1000_MOD_NORMAL 0x00
+#define SJA1000_MOD_RM     0x01
+
+/* ECC register NXP LPC2119/SJA1000 CAN Controller */
+#define SJA1000_ECC_SEG   0x1F
+#define SJA1000_ECC_DIR   0x20
+#define SJA1000_ECC_ERR   0x06
+#define SJA1000_ECC_BIT   0x00
+#define SJA1000_ECC_FORM  0x40
+#define SJA1000_ECC_STUFF 0x80
+#define SJA1000_ECC_MASK  0xc0
+
+/* Status register content */
+#define SJA1000_SR_BS 0x80
+#define SJA1000_SR_ES 0x40
+
+#define SJA1000_DEFAULT_OUTPUT_CONTROL 0xDA
+
+/*
+ * The device actually uses a 16MHz clock to generate the CAN clock
+ * but it expects SJA1000 bit settings based on 8MHz (is internally
+ * converted).
+ */
+#define EMS_USB_ARM7_CLOCK 8000000
+
+/*
+ * CAN-Message representation in a CPC_MSG. Message object type is
+ * CPC_MSG_TYPE_CAN_FRAME or CPC_MSG_TYPE_RTR_FRAME or
+ * CPC_MSG_TYPE_EXT_CAN_FRAME or CPC_MSG_TYPE_EXT_RTR_FRAME.
+ */
+struct cpc_can_msg {
+	u32 id;
+	u8 length;
+	u8 msg[8];
+};
+
+/* Representation of the CAN parameters for the SJA1000 controller */
+struct cpc_sja1000_params {
+	u8 mode;
+	u8 acc_code0;
+	u8 acc_code1;
+	u8 acc_code2;
+	u8 acc_code3;
+	u8 acc_mask0;
+	u8 acc_mask1;
+	u8 acc_mask2;
+	u8 acc_mask3;
+	u8 btr0;
+	u8 btr1;
+	u8 outp_contr;
+};
+
+/* CAN params message representation */
+struct cpc_can_params {
+	u8 cc_type;
+
+	/* Will support M16C CAN controller in the future */
+	union {
+		struct cpc_sja1000_params sja1000;
+	} cc_params;
+};
+
+/* Structure for confirmed message handling */
+struct cpc_confirm {
+	u8 error; /* error code */
+};
+
+/* Structure for overrun conditions */
+struct cpc_overrun {
+	u8 event;
+	u8 count;
+};
+
+/* SJA1000 CAN errors (compatible to NXP LPC2119) */
+struct cpc_sja1000_can_error {
+	u8 ecc;
+	u8 rxerr;
+	u8 txerr;
+};
+
+/* structure for CAN error conditions */
+struct cpc_can_error {
+	u8 ecode;
+
+	struct {
+		u8 cc_type;
+
+		/* Other controllers may also provide error code capture regs */
+		union {
+			struct cpc_sja1000_can_error sja1000;
+		} regs;
+	} cc;
+};
+
+/*
+ * Structure containing RX/TX error counter. This structure is used to request
+ * the values of the CAN controllers TX and RX error counter.
+ */
+struct cpc_can_err_counter {
+	u8 rx;
+	u8 tx;
+};
+
+/* Main message type used between library and application */
+struct __attribute__ ((packed)) ems_cpc_msg {
+	u8 type;	/* type of message */
+	u8 length;	/* length of data within union 'msg' */
+	u8 msgid;	/* confirmation handle */
+	u32 ts_sec;	/* timestamp in seconds */
+	u32 ts_nsec;	/* timestamp in nano seconds */
+
+	union {
+		u8 generic[64];
+		struct cpc_can_msg can_msg;
+		struct cpc_can_params can_params;
+		struct cpc_confirm confirmation;
+		struct cpc_overrun overrun;
+		struct cpc_can_error error;
+		struct cpc_can_err_counter err_counter;
+		u8 can_state;
+	} msg;
+};
+
+/*
+ * Table of devices that work with this driver
+ * NOTE: This driver supports only CPC-USB/ARM7 (LPC2119) yet.
+ */
+static struct usb_device_id ems_usb_table[] = {
+	{USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_ARM7_PRODUCT_ID)},
+	{} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, ems_usb_table);
+
+#define RX_BUFFER_SIZE      64
+#define CPC_HEADER_SIZE     4
+#define INTR_IN_BUFFER_SIZE 4
+
+#define MAX_RX_URBS 10
+#define MAX_TX_URBS CAN_ECHO_SKB_MAX
+
+struct ems_usb;
+
+struct ems_tx_urb_context {
+	struct ems_usb *dev;
+
+	u32 echo_index;
+	u8 dlc;
+};
+
+struct ems_usb {
+	struct can_priv can; /* must be the first member */
+	int open_time;
+
+	struct sk_buff *echo_skb[MAX_TX_URBS];
+
+	struct usb_device *udev;
+	struct net_device *netdev;
+
+	atomic_t active_tx_urbs;
+	struct usb_anchor tx_submitted;
+	struct ems_tx_urb_context tx_contexts[MAX_TX_URBS];
+
+	struct usb_anchor rx_submitted;
+
+	struct urb *intr_urb;
+
+	u8 *tx_msg_buffer;
+
+	u8 *intr_in_buffer;
+	unsigned int free_slots; /* remember number of available slots */
+
+	struct ems_cpc_msg active_params; /* active controller parameters */
+};
+
+static void ems_usb_read_interrupt_callback(struct urb *urb)
+{
+	struct ems_usb *dev = urb->context;
+	struct net_device *netdev = dev->netdev;
+	int err;
+
+	if (!netif_device_present(netdev))
+		return;
+
+	switch (urb->status) {
+	case 0:
+		dev->free_slots = dev->intr_in_buffer[1];
+		break;
+
+	case -ECONNRESET: /* unlink */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+
+	default:
+		dev_info(netdev->dev.parent, "Rx interrupt aborted %d\n",
+			 urb->status);
+		break;
+	}
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+
+	if (err == -ENODEV)
+		netif_device_detach(netdev);
+	else if (err)
+		dev_err(netdev->dev.parent,
+			"failed resubmitting intr urb: %d\n", err);
+
+	return;
+}
+
+static void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg)
+{
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	int i;
+	struct net_device_stats *stats = &dev->netdev->stats;
+
+	skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame));
+	if (skb == NULL)
+		return;
+
+	skb->protocol = htons(ETH_P_CAN);
+
+	cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+
+	cf->can_id = msg->msg.can_msg.id;
+	cf->can_dlc = min_t(u8, msg->msg.can_msg.length, 8);
+
+	if (msg->type == CPC_MSG_TYPE_EXT_CAN_FRAME
+	    || msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME)
+		cf->can_id |= CAN_EFF_FLAG;
+
+	if (msg->type == CPC_MSG_TYPE_RTR_FRAME
+	    || msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME) {
+		cf->can_id |= CAN_RTR_FLAG;
+	} else {
+		for (i = 0; i < cf->can_dlc; i++)
+			cf->data[i] = msg->msg.can_msg.msg[i];
+	}
+
+	netif_rx(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
+{
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	struct net_device_stats *stats = &dev->netdev->stats;
+
+	skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame));
+	if (skb == NULL)
+		return;
+
+	skb->protocol = htons(ETH_P_CAN);
+
+	cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+	memset(cf, 0, sizeof(struct can_frame));
+
+	cf->can_id = CAN_ERR_FLAG;
+	cf->can_dlc = CAN_ERR_DLC;
+
+	if (msg->type == CPC_MSG_TYPE_CAN_STATE) {
+		u8 state = msg->msg.can_state;
+
+		if (state & SJA1000_SR_BS) {
+			dev->can.state = CAN_STATE_BUS_OFF;
+			cf->can_id |= CAN_ERR_BUSOFF;
+
+			can_bus_off(dev->netdev);
+		} else if (state & SJA1000_SR_ES) {
+			dev->can.state = CAN_STATE_ERROR_WARNING;
+			dev->can.can_stats.error_warning++;
+		} else {
+			dev->can.state = CAN_STATE_ERROR_ACTIVE;
+			dev->can.can_stats.error_passive++;
+		}
+	} else if (msg->type == CPC_MSG_TYPE_CAN_FRAME_ERROR) {
+		u8 ecc = msg->msg.error.cc.regs.sja1000.ecc;
+		u8 txerr = msg->msg.error.cc.regs.sja1000.txerr;
+		u8 rxerr = msg->msg.error.cc.regs.sja1000.rxerr;
+
+		/* bus error interrupt */
+		dev->can.can_stats.bus_error++;
+		stats->rx_errors++;
+
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+		switch (ecc & SJA1000_ECC_MASK) {
+		case SJA1000_ECC_BIT:
+			cf->data[2] |= CAN_ERR_PROT_BIT;
+			break;
+		case SJA1000_ECC_FORM:
+			cf->data[2] |= CAN_ERR_PROT_FORM;
+			break;
+		case SJA1000_ECC_STUFF:
+			cf->data[2] |= CAN_ERR_PROT_STUFF;
+			break;
+		default:
+			cf->data[2] |= CAN_ERR_PROT_UNSPEC;
+			cf->data[3] = ecc & SJA1000_ECC_SEG;
+			break;
+		}
+
+		/* Error occured during transmission? */
+		if ((ecc & SJA1000_ECC_DIR) == 0)
+			cf->data[2] |= CAN_ERR_PROT_TX;
+
+		if (dev->can.state == CAN_STATE_ERROR_WARNING ||
+		    dev->can.state == CAN_STATE_ERROR_PASSIVE) {
+			cf->data[1] = (txerr > rxerr) ?
+			    CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE;
+		}
+	} else if (msg->type == CPC_MSG_TYPE_OVERRUN) {
+		cf->can_id |= CAN_ERR_CRTL;
+		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+
+		stats->rx_over_errors++;
+		stats->rx_errors++;
+	}
+
+	netif_rx(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+/*
+ * callback for bulk IN urb
+ */
+static void ems_usb_read_bulk_callback(struct urb *urb)
+{
+	struct ems_usb *dev = urb->context;
+	struct net_device *netdev;
+	int retval;
+
+	netdev = dev->netdev;
+
+	if (!netif_device_present(netdev))
+		return;
+
+	switch (urb->status) {
+	case 0: /* success */
+		break;
+
+	case -ENOENT:
+		return;
+
+	default:
+		dev_info(netdev->dev.parent, "Rx URB aborted (%d)\n",
+			 urb->status);
+		goto resubmit_urb;
+	}
+
+	if (urb->actual_length > CPC_HEADER_SIZE) {
+		struct ems_cpc_msg *msg;
+		u8 *ibuf = urb->transfer_buffer;
+		u8 msg_count, again, start;
+
+		msg_count = ibuf[0] & ~0x80;
+		again = ibuf[0] & 0x80;
+
+		start = CPC_HEADER_SIZE;
+
+		while (msg_count) {
+			msg = (struct ems_cpc_msg *)&ibuf[start];
+
+			switch (msg->type) {
+			case CPC_MSG_TYPE_CAN_STATE:
+				/* Process CAN state changes */
+				ems_usb_rx_err(dev, msg);
+				break;
+
+			case CPC_MSG_TYPE_CAN_FRAME:
+			case CPC_MSG_TYPE_EXT_CAN_FRAME:
+			case CPC_MSG_TYPE_RTR_FRAME:
+			case CPC_MSG_TYPE_EXT_RTR_FRAME:
+				ems_usb_rx_can_msg(dev, msg);
+				break;
+
+			case CPC_MSG_TYPE_CAN_FRAME_ERROR:
+				/* Process errorframe */
+				ems_usb_rx_err(dev, msg);
+				break;
+
+			case CPC_MSG_TYPE_OVERRUN:
+				/* Message lost while receiving */
+				ems_usb_rx_err(dev, msg);
+				break;
+			}
+
+			start += CPC_MSG_HEADER_LEN + msg->length;
+			msg_count--;
+
+			if (start > urb->transfer_buffer_length) {
+				dev_err(netdev->dev.parent, "format error\n");
+				break;
+			}
+		}
+	}
+
+resubmit_urb:
+	usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
+			  urb->transfer_buffer, RX_BUFFER_SIZE,
+			  ems_usb_read_bulk_callback, dev);
+
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+
+	if (retval == -ENODEV)
+		netif_device_detach(netdev);
+	else if (retval)
+		dev_err(netdev->dev.parent,
+			"failed resubmitting read bulk urb: %d\n", retval);
+
+	return;
+}
+
+/*
+ * callback for bulk IN urb
+ */
+static void ems_usb_write_bulk_callback(struct urb *urb)
+{
+	struct ems_tx_urb_context *context = urb->context;
+	struct ems_usb *dev;
+	struct net_device *netdev;
+
+	BUG_ON(!context);
+
+	dev = context->dev;
+	netdev = dev->netdev;
+
+	/* free up our allocated buffer */
+	usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+			urb->transfer_buffer, urb->transfer_dma);
+
+	atomic_dec(&dev->active_tx_urbs);
+
+	if (!netif_device_present(netdev))
+		return;
+
+	if (urb->status)
+		dev_info(netdev->dev.parent, "Tx URB aborted (%d)\n",
+			 urb->status);
+
+	netdev->trans_start = jiffies;
+
+	/* transmission complete interrupt */
+	netdev->stats.tx_packets++;
+	netdev->stats.tx_bytes += context->dlc;
+
+	can_get_echo_skb(netdev, context->echo_index);
+
+	/* Release context */
+	context->echo_index = MAX_TX_URBS;
+
+	if (netif_queue_stopped(netdev))
+		netif_wake_queue(netdev);
+}
+
+/*
+ * Send the given CPC command synchronously
+ */
+static int ems_usb_command_msg(struct ems_usb *dev, struct ems_cpc_msg *msg)
+{
+	int actual_length;
+
+	/* Copy payload */
+	memcpy(&dev->tx_msg_buffer[CPC_HEADER_SIZE], msg,
+	       msg->length + CPC_MSG_HEADER_LEN);
+
+	/* Clear header */
+	memset(&dev->tx_msg_buffer[0], 0, CPC_HEADER_SIZE);
+
+	return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
+			    &dev->tx_msg_buffer[0],
+			    msg->length + CPC_MSG_HEADER_LEN + CPC_HEADER_SIZE,
+			    &actual_length, 1000);
+}
+
+/*
+ * Change CAN controllers' mode register
+ */
+static int ems_usb_write_mode(struct ems_usb *dev, u8 mode)
+{
+	dev->active_params.msg.can_params.cc_params.sja1000.mode = mode;
+
+	return ems_usb_command_msg(dev, &dev->active_params);
+}
+
+/*
+ * Send a CPC_Control command to change behaviour when interface receives a CAN
+ * message, bus error or CAN state changed notifications.
+ */
+static int ems_usb_control_cmd(struct ems_usb *dev, u8 val)
+{
+	struct ems_cpc_msg cmd;
+
+	cmd.type = CPC_CMD_TYPE_CONTROL;
+	cmd.length = CPC_MSG_HEADER_LEN + 1;
+
+	cmd.msgid = 0;
+
+	cmd.msg.generic[0] = val;
+
+	return ems_usb_command_msg(dev, &cmd);
+}
+
+/*
+ * Start interface
+ */
+static int ems_usb_start(struct ems_usb *dev)
+{
+	struct net_device *netdev = dev->netdev;
+	int err, i;
+
+	dev->intr_in_buffer[0] = 0;
+	dev->free_slots = 15; /* initial size */
+
+	for (i = 0; i < MAX_RX_URBS; i++) {
+		struct urb *urb = NULL;
+		u8 *buf = NULL;
+
+		/* create a URB, and a buffer for it */
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			dev_err(netdev->dev.parent,
+				"No memory left for URBs\n");
+			return -ENOMEM;
+		}
+
+		buf = usb_buffer_alloc(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
+				       &urb->transfer_dma);
+		if (!buf) {
+			dev_err(netdev->dev.parent,
+				"No memory left for USB buffer\n");
+			usb_free_urb(urb);
+			return -ENOMEM;
+		}
+
+		usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
+				  buf, RX_BUFFER_SIZE,
+				  ems_usb_read_bulk_callback, dev);
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		usb_anchor_urb(urb, &dev->rx_submitted);
+
+		err = usb_submit_urb(urb, GFP_KERNEL);
+		if (err) {
+			if (err == -ENODEV)
+				netif_device_detach(dev->netdev);
+
+			usb_unanchor_urb(urb);
+			usb_buffer_free(dev->udev, RX_BUFFER_SIZE, buf,
+					urb->transfer_dma);
+			break;
+		}
+
+		/* Drop reference, USB core will take care of freeing it */
+		usb_free_urb(urb);
+	}
+
+	/* Did we submit any URBs */
+	if (i == 0) {
+		dev_warn(netdev->dev.parent, "couldn't setup read URBs\n");
+		return err;
+	}
+
+	/* Warn if we've couldn't transmit all the URBs */
+	if (i < MAX_RX_URBS)
+		dev_warn(netdev->dev.parent, "rx performance may be slow\n");
+
+	/* Setup and start interrupt URB */
+	usb_fill_int_urb(dev->intr_urb, dev->udev,
+			 usb_rcvintpipe(dev->udev, 1),
+			 dev->intr_in_buffer,
+			 INTR_IN_BUFFER_SIZE,
+			 ems_usb_read_interrupt_callback, dev, 1);
+
+	err = usb_submit_urb(dev->intr_urb, GFP_KERNEL);
+	if (err) {
+		if (err == -ENODEV)
+			netif_device_detach(dev->netdev);
+
+		dev_warn(netdev->dev.parent, "intr URB submit failed: %d\n",
+			 err);
+
+		return err;
+	}
+
+	/* CPC-USB will transfer received message to host */
+	err = ems_usb_control_cmd(dev, CONTR_CAN_MESSAGE | CONTR_CONT_ON);
+	if (err)
+		goto failed;
+
+	/* CPC-USB will transfer CAN state changes to host */
+	err = ems_usb_control_cmd(dev, CONTR_CAN_STATE | CONTR_CONT_ON);
+	if (err)
+		goto failed;
+
+	/* CPC-USB will transfer bus errors to host */
+	err = ems_usb_control_cmd(dev, CONTR_BUS_ERROR | CONTR_CONT_ON);
+	if (err)
+		goto failed;
+
+	err = ems_usb_write_mode(dev, SJA1000_MOD_NORMAL);
+	if (err)
+		goto failed;
+
+	dev->can.state = CAN_STATE_ERROR_ACTIVE;
+
+	return 0;
+
+failed:
+	if (err == -ENODEV)
+		netif_device_detach(dev->netdev);
+
+	dev_warn(netdev->dev.parent, "couldn't submit control: %d\n", err);
+
+	return err;
+}
+
+static void unlink_all_urbs(struct ems_usb *dev)
+{
+	int i;
+
+	usb_unlink_urb(dev->intr_urb);
+
+	usb_kill_anchored_urbs(&dev->rx_submitted);
+
+	usb_kill_anchored_urbs(&dev->tx_submitted);
+	atomic_set(&dev->active_tx_urbs, 0);
+
+	for (i = 0; i < MAX_TX_URBS; i++)
+		dev->tx_contexts[i].echo_index = MAX_TX_URBS;
+}
+
+static int ems_usb_open(struct net_device *netdev)
+{
+	struct ems_usb *dev = netdev_priv(netdev);
+	int err;
+
+	err = ems_usb_write_mode(dev, SJA1000_MOD_RM);
+	if (err)
+		return err;
+
+	/* common open */
+	err = open_candev(netdev);
+	if (err)
+		return err;
+
+	/* finally start device */
+	err = ems_usb_start(dev);
+	if (err) {
+		if (err == -ENODEV)
+			netif_device_detach(dev->netdev);
+
+		dev_warn(netdev->dev.parent, "couldn't start device: %d\n",
+			 err);
+
+		close_candev(netdev);
+
+		return err;
+	}
+
+	dev->open_time = jiffies;
+
+	netif_start_queue(netdev);
+
+	return 0;
+}
+
+static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct ems_usb *dev = netdev_priv(netdev);
+	struct ems_tx_urb_context *context = NULL;
+	struct net_device_stats *stats = &netdev->stats;
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	struct ems_cpc_msg *msg;
+	struct urb *urb;
+	u8 *buf;
+	int i, err;
+	size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN
+			+ sizeof(struct cpc_can_msg);
+
+	/* create a URB, and a buffer for it, and copy the data to the URB */
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		dev_err(netdev->dev.parent, "No memory left for URBs\n");
+		goto nomem;
+	}
+
+	buf = usb_buffer_alloc(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma);
+	if (!buf) {
+		dev_err(netdev->dev.parent, "No memory left for USB buffer\n");
+		usb_free_urb(urb);
+		goto nomem;
+	}
+
+	msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE];
+
+	msg->msg.can_msg.id = cf->can_id & CAN_ERR_MASK;
+	msg->msg.can_msg.length = cf->can_dlc;
+
+	if (cf->can_id & CAN_RTR_FLAG) {
+		msg->type = cf->can_id & CAN_EFF_FLAG ?
+			CPC_CMD_TYPE_EXT_RTR_FRAME : CPC_CMD_TYPE_RTR_FRAME;
+
+		msg->length = CPC_CAN_MSG_MIN_SIZE;
+	} else {
+		msg->type = cf->can_id & CAN_EFF_FLAG ?
+			CPC_CMD_TYPE_EXT_CAN_FRAME : CPC_CMD_TYPE_CAN_FRAME;
+
+		for (i = 0; i < cf->can_dlc; i++)
+			msg->msg.can_msg.msg[i] = cf->data[i];
+
+		msg->length = CPC_CAN_MSG_MIN_SIZE + cf->can_dlc;
+	}
+
+	for (i = 0; i < MAX_TX_URBS; i++) {
+		if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) {
+			context = &dev->tx_contexts[i];
+			break;
+		}
+	}
+
+	/*
+	 * May never happen! When this happens we'd more URBs in flight as
+	 * allowed (MAX_TX_URBS).
+	 */
+	if (!context) {
+		usb_unanchor_urb(urb);
+		usb_buffer_free(dev->udev, size, buf, urb->transfer_dma);
+
+		dev_warn(netdev->dev.parent, "couldn't find free context\n");
+
+		return NETDEV_TX_BUSY;
+	}
+
+	context->dev = dev;
+	context->echo_index = i;
+	context->dlc = cf->can_dlc;
+
+	usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf,
+			  size, ems_usb_write_bulk_callback, context);
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	usb_anchor_urb(urb, &dev->tx_submitted);
+
+	can_put_echo_skb(skb, netdev, context->echo_index);
+
+	atomic_inc(&dev->active_tx_urbs);
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (unlikely(err)) {
+		can_free_echo_skb(netdev, context->echo_index);
+
+		usb_unanchor_urb(urb);
+		usb_buffer_free(dev->udev, size, buf, urb->transfer_dma);
+		dev_kfree_skb(skb);
+
+		atomic_dec(&dev->active_tx_urbs);
+
+		if (err == -ENODEV) {
+			netif_device_detach(netdev);
+		} else {
+			dev_warn(netdev->dev.parent, "failed tx_urb %d\n", err);
+
+			stats->tx_dropped++;
+		}
+	} else {
+		netdev->trans_start = jiffies;
+
+		/* Slow down tx path */
+		if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS ||
+		    dev->free_slots < 5) {
+			netif_stop_queue(netdev);
+		}
+	}
+
+	/*
+	 * Release our reference to this URB, the USB core will eventually free
+	 * it entirely.
+	 */
+	usb_free_urb(urb);
+
+	return NETDEV_TX_OK;
+
+nomem:
+	if (skb)
+		dev_kfree_skb(skb);
+
+	stats->tx_dropped++;
+
+	return NETDEV_TX_OK;
+}
+
+static int ems_usb_close(struct net_device *netdev)
+{
+	struct ems_usb *dev = netdev_priv(netdev);
+
+	/* Stop polling */
+	unlink_all_urbs(dev);
+
+	netif_stop_queue(netdev);
+
+	/* Set CAN controller to reset mode */
+	if (ems_usb_write_mode(dev, SJA1000_MOD_RM))
+		dev_warn(netdev->dev.parent, "couldn't stop device");
+
+	close_candev(netdev);
+
+	dev->open_time = 0;
+
+	return 0;
+}
+
+static const struct net_device_ops ems_usb_netdev_ops = {
+	.ndo_open = ems_usb_open,
+	.ndo_stop = ems_usb_close,
+	.ndo_start_xmit = ems_usb_start_xmit,
+};
+
+static struct can_bittiming_const ems_usb_bittiming_const = {
+	.name = "ems_usb",
+	.tseg1_min = 1,
+	.tseg1_max = 16,
+	.tseg2_min = 1,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 64,
+	.brp_inc = 1,
+};
+
+static int ems_usb_set_mode(struct net_device *netdev, enum can_mode mode)
+{
+	struct ems_usb *dev = netdev_priv(netdev);
+
+	if (!dev->open_time)
+		return -EINVAL;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		if (ems_usb_write_mode(dev, SJA1000_MOD_NORMAL))
+			dev_warn(netdev->dev.parent, "couldn't start device");
+
+		if (netif_queue_stopped(netdev))
+			netif_wake_queue(netdev);
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int ems_usb_set_bittiming(struct net_device *netdev)
+{
+	struct ems_usb *dev = netdev_priv(netdev);
+	struct can_bittiming *bt = &dev->can.bittiming;
+	u8 btr0, btr1;
+
+	btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
+	btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
+		(((bt->phase_seg2 - 1) & 0x7) << 4);
+	if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+		btr1 |= 0x80;
+
+	dev_info(netdev->dev.parent, "setting BTR0=0x%02x BTR1=0x%02x\n",
+		 btr0, btr1);
+
+	dev->active_params.msg.can_params.cc_params.sja1000.btr0 = btr0;
+	dev->active_params.msg.can_params.cc_params.sja1000.btr1 = btr1;
+
+	return ems_usb_command_msg(dev, &dev->active_params);
+}
+
+static void init_params_sja1000(struct ems_cpc_msg *msg)
+{
+	struct cpc_sja1000_params *sja1000 =
+		&msg->msg.can_params.cc_params.sja1000;
+
+	msg->type = CPC_CMD_TYPE_CAN_PARAMS;
+	msg->length = sizeof(struct cpc_can_params);
+	msg->msgid = 0;
+
+	msg->msg.can_params.cc_type = CPC_CC_TYPE_SJA1000;
+
+	/* Acceptance filter open */
+	sja1000->acc_code0 = 0x00;
+	sja1000->acc_code1 = 0x00;
+	sja1000->acc_code2 = 0x00;
+	sja1000->acc_code3 = 0x00;
+
+	/* Acceptance filter open */
+	sja1000->acc_mask0 = 0xFF;
+	sja1000->acc_mask1 = 0xFF;
+	sja1000->acc_mask2 = 0xFF;
+	sja1000->acc_mask3 = 0xFF;
+
+	sja1000->btr0 = 0;
+	sja1000->btr1 = 0;
+
+	sja1000->outp_contr = SJA1000_DEFAULT_OUTPUT_CONTROL;
+	sja1000->mode = SJA1000_MOD_RM;
+}
+
+/*
+ * probe function for new CPC-USB devices
+ */
+static int ems_usb_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct net_device *netdev;
+	struct ems_usb *dev;
+	int i, err = -ENOMEM;
+
+	netdev = alloc_candev(sizeof(struct ems_usb));
+	if (!netdev) {
+		dev_err(netdev->dev.parent, "Couldn't alloc candev\n");
+		return -ENOMEM;
+	}
+
+	dev = netdev_priv(netdev);
+
+	dev->udev = interface_to_usbdev(intf);
+	dev->netdev = netdev;
+
+	dev->can.state = CAN_STATE_STOPPED;
+	dev->can.clock.freq = EMS_USB_ARM7_CLOCK;
+	dev->can.bittiming_const = &ems_usb_bittiming_const;
+	dev->can.do_set_bittiming = ems_usb_set_bittiming;
+	dev->can.do_set_mode = ems_usb_set_mode;
+
+	netdev->flags |= IFF_ECHO; /* we support local echo */
+
+	netdev->netdev_ops = &ems_usb_netdev_ops;
+
+	netdev->flags |= IFF_ECHO; /* we support local echo */
+
+	init_usb_anchor(&dev->rx_submitted);
+
+	init_usb_anchor(&dev->tx_submitted);
+	atomic_set(&dev->active_tx_urbs, 0);
+
+	for (i = 0; i < MAX_TX_URBS; i++)
+		dev->tx_contexts[i].echo_index = MAX_TX_URBS;
+
+	dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->intr_urb) {
+		dev_err(netdev->dev.parent, "Couldn't alloc intr URB\n");
+		goto cleanup_candev;
+	}
+
+	dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL);
+	if (!dev->intr_in_buffer) {
+		dev_err(netdev->dev.parent, "Couldn't alloc Intr buffer\n");
+		goto cleanup_intr_urb;
+	}
+
+	dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE +
+				     sizeof(struct ems_cpc_msg), GFP_KERNEL);
+	if (!dev->tx_msg_buffer) {
+		dev_err(netdev->dev.parent, "Couldn't alloc Tx buffer\n");
+		goto cleanup_intr_in_buffer;
+	}
+
+	usb_set_intfdata(intf, dev);
+
+	SET_NETDEV_DEV(netdev, &intf->dev);
+
+	init_params_sja1000(&dev->active_params);
+
+	err = ems_usb_command_msg(dev, &dev->active_params);
+	if (err) {
+		dev_err(netdev->dev.parent,
+			"couldn't initialize controller: %d\n", err);
+		goto cleanup_tx_msg_buffer;
+	}
+
+	err = register_candev(netdev);
+	if (err) {
+		dev_err(netdev->dev.parent,
+			"couldn't register CAN device: %d\n", err);
+		goto cleanup_tx_msg_buffer;
+	}
+
+	return 0;
+
+cleanup_tx_msg_buffer:
+	kfree(dev->tx_msg_buffer);
+
+cleanup_intr_in_buffer:
+	kfree(dev->intr_in_buffer);
+
+cleanup_intr_urb:
+	usb_free_urb(dev->intr_urb);
+
+cleanup_candev:
+	free_candev(netdev);
+
+	return err;
+}
+
+/*
+ * called by the usb core when the device is removed from the system
+ */
+static void ems_usb_disconnect(struct usb_interface *intf)
+{
+	struct ems_usb *dev = usb_get_intfdata(intf);
+
+	usb_set_intfdata(intf, NULL);
+
+	if (dev) {
+		unregister_netdev(dev->netdev);
+		free_candev(dev->netdev);
+
+		unlink_all_urbs(dev);
+
+		usb_free_urb(dev->intr_urb);
+
+		kfree(dev->intr_in_buffer);
+	}
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver ems_usb_driver = {
+	.name = "ems_usb",
+	.probe = ems_usb_probe,
+	.disconnect = ems_usb_disconnect,
+	.id_table = ems_usb_table,
+};
+
+static int __init ems_usb_init(void)
+{
+	int err;
+
+	printk(KERN_INFO "CPC-USB kernel driver loaded\n");
+
+	/* register this driver with the USB subsystem */
+	err = usb_register(&ems_usb_driver);
+
+	if (err) {
+		err("usb_register failed. Error number %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void __exit ems_usb_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&ems_usb_driver);
+}
+
+module_init(ems_usb_init);
+module_exit(ems_usb_exit);

+ 2 - 2
drivers/net/cnic.c

@@ -85,8 +85,6 @@ static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode)
 
 
 	cp->uio_dev = iminor(inode);
 	cp->uio_dev = iminor(inode);
 
 
-	cnic_shutdown_bnx2_rx_ring(dev);
-
 	cnic_init_bnx2_tx_ring(dev);
 	cnic_init_bnx2_tx_ring(dev);
 	cnic_init_bnx2_rx_ring(dev);
 	cnic_init_bnx2_rx_ring(dev);
 
 
@@ -98,6 +96,8 @@ static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode)
 	struct cnic_dev *dev = uinfo->priv;
 	struct cnic_dev *dev = uinfo->priv;
 	struct cnic_local *cp = dev->cnic_priv;
 	struct cnic_local *cp = dev->cnic_priv;
 
 
+	cnic_shutdown_bnx2_rx_ring(dev);
+
 	cp->uio_dev = -1;
 	cp->uio_dev = -1;
 	return 0;
 	return 0;
 }
 }

+ 4 - 4
drivers/net/cpmac.c

@@ -1109,7 +1109,7 @@ static int external_switch;
 static int __devinit cpmac_probe(struct platform_device *pdev)
 static int __devinit cpmac_probe(struct platform_device *pdev)
 {
 {
 	int rc, phy_id;
 	int rc, phy_id;
-	char mdio_bus_id[BUS_ID_SIZE];
+	char mdio_bus_id[MII_BUS_ID_SIZE];
 	struct resource *mem;
 	struct resource *mem;
 	struct cpmac_priv *priv;
 	struct cpmac_priv *priv;
 	struct net_device *dev;
 	struct net_device *dev;
@@ -1118,7 +1118,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
 	pdata = pdev->dev.platform_data;
 	pdata = pdev->dev.platform_data;
 
 
 	if (external_switch || dumb_switch) {
 	if (external_switch || dumb_switch) {
-		strncpy(mdio_bus_id, "0", BUS_ID_SIZE); /* fixed phys bus */
+		strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */
 		phy_id = pdev->id;
 		phy_id = pdev->id;
 	} else {
 	} else {
 		for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
 		for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
@@ -1126,7 +1126,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
 				continue;
 				continue;
 			if (!cpmac_mii->phy_map[phy_id])
 			if (!cpmac_mii->phy_map[phy_id])
 				continue;
 				continue;
-			strncpy(mdio_bus_id, cpmac_mii->id, BUS_ID_SIZE);
+			strncpy(mdio_bus_id, cpmac_mii->id, MII_BUS_ID_SIZE);
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -1167,7 +1167,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
 	priv->msg_enable = netif_msg_init(debug_level, 0xff);
 	priv->msg_enable = netif_msg_init(debug_level, 0xff);
 	memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
 	memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
 
 
-	snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
+	snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
 
 
 	priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
 	priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
 						PHY_INTERFACE_MODE_MII);
 						PHY_INTERFACE_MODE_MII);

+ 0 - 1
drivers/net/ehea/ehea_main.c

@@ -3083,7 +3083,6 @@ static const struct net_device_ops ehea_netdev_ops = {
 	.ndo_poll_controller	= ehea_netpoll,
 	.ndo_poll_controller	= ehea_netpoll,
 #endif
 #endif
 	.ndo_get_stats		= ehea_get_stats,
 	.ndo_get_stats		= ehea_get_stats,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address	= ehea_set_mac_addr,
 	.ndo_set_mac_address	= ehea_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_multicast_list	= ehea_set_multicast_list,
 	.ndo_set_multicast_list	= ehea_set_multicast_list,

+ 36 - 36
drivers/net/igb/e1000_mac.c

@@ -285,41 +285,6 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value)
 	wrfl();
 	wrfl();
 }
 }
 
 
-/**
- *  igb_update_mc_addr_list - Update Multicast addresses
- *  @hw: pointer to the HW structure
- *  @mc_addr_list: array of multicast addresses to program
- *  @mc_addr_count: number of multicast addresses to program
- *
- *  Updates entire Multicast Table Array.
- *  The caller must have a packed mc_addr_list of multicast addresses.
- **/
-void igb_update_mc_addr_list(struct e1000_hw *hw,
-                             u8 *mc_addr_list, u32 mc_addr_count)
-{
-	u32 hash_value, hash_bit, hash_reg;
-	int i;
-
-	/* clear mta_shadow */
-	memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
-
-	/* update mta_shadow from mc_addr_list */
-	for (i = 0; (u32) i < mc_addr_count; i++) {
-		hash_value = igb_hash_mc_addr(hw, mc_addr_list);
-
-		hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
-		hash_bit = hash_value & 0x1F;
-
-		hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
-		mc_addr_list += (ETH_ALEN);
-	}
-
-	/* replace the entire MTA table */
-	for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
-		array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]);
-	wrfl();
-}
-
 /**
 /**
  *  igb_hash_mc_addr - Generate a multicast hash value
  *  igb_hash_mc_addr - Generate a multicast hash value
  *  @hw: pointer to the HW structure
  *  @hw: pointer to the HW structure
@@ -329,7 +294,7 @@ void igb_update_mc_addr_list(struct e1000_hw *hw,
  *  the multicast filter table array address and new table value.  See
  *  the multicast filter table array address and new table value.  See
  *  igb_mta_set()
  *  igb_mta_set()
  **/
  **/
-u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
 {
 {
 	u32 hash_value, hash_mask;
 	u32 hash_value, hash_mask;
 	u8 bit_shift = 0;
 	u8 bit_shift = 0;
@@ -391,6 +356,41 @@ u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
 	return hash_value;
 	return hash_value;
 }
 }
 
 
+/**
+ *  igb_update_mc_addr_list - Update Multicast addresses
+ *  @hw: pointer to the HW structure
+ *  @mc_addr_list: array of multicast addresses to program
+ *  @mc_addr_count: number of multicast addresses to program
+ *
+ *  Updates entire Multicast Table Array.
+ *  The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+void igb_update_mc_addr_list(struct e1000_hw *hw,
+                             u8 *mc_addr_list, u32 mc_addr_count)
+{
+	u32 hash_value, hash_bit, hash_reg;
+	int i;
+
+	/* clear mta_shadow */
+	memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
+
+	/* update mta_shadow from mc_addr_list */
+	for (i = 0; (u32) i < mc_addr_count; i++) {
+		hash_value = igb_hash_mc_addr(hw, mc_addr_list);
+
+		hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
+		hash_bit = hash_value & 0x1F;
+
+		hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
+		mc_addr_list += (ETH_ALEN);
+	}
+
+	/* replace the entire MTA table */
+	for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
+		array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]);
+	wrfl();
+}
+
 /**
 /**
  *  igb_clear_hw_cntrs_base - Clear base hardware counters
  *  igb_clear_hw_cntrs_base - Clear base hardware counters
  *  @hw: pointer to the HW structure
  *  @hw: pointer to the HW structure

+ 0 - 1
drivers/net/igb/e1000_mac.h

@@ -88,6 +88,5 @@ enum e1000_mng_mode {
 #define E1000_MNG_DHCP_COOKIE_STATUS_VLAN    0x2
 #define E1000_MNG_DHCP_COOKIE_STATUS_VLAN    0x2
 
 
 extern void e1000_init_function_pointers_82575(struct e1000_hw *hw);
 extern void e1000_init_function_pointers_82575(struct e1000_hw *hw);
-extern u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
 
 
 #endif
 #endif

+ 4 - 2
drivers/net/ixgbe/ixgbe.h

@@ -267,7 +267,8 @@ struct ixgbe_adapter {
 	enum ixgbe_fc_mode last_lfc_mode;
 	enum ixgbe_fc_mode last_lfc_mode;
 
 
 	/* Interrupt Throttle Rate */
 	/* Interrupt Throttle Rate */
-	u32 itr_setting;
+	u32 rx_itr_setting;
+	u32 tx_itr_setting;
 	u16 eitr_low;
 	u16 eitr_low;
 	u16 eitr_high;
 	u16 eitr_high;
 
 
@@ -351,7 +352,8 @@ struct ixgbe_adapter {
 	struct ixgbe_hw_stats stats;
 	struct ixgbe_hw_stats stats;
 
 
 	/* Interrupt Throttle Rate */
 	/* Interrupt Throttle Rate */
-	u32 eitr_param;
+	u32 rx_eitr_param;
+	u32 tx_eitr_param;
 
 
 	unsigned long state;
 	unsigned long state;
 	u64 tx_busy;
 	u64 tx_busy;

+ 61 - 14
drivers/net/ixgbe/ixgbe_ethtool.c

@@ -1929,7 +1929,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
 	ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit;
 	ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit;
 
 
 	/* only valid if in constant ITR mode */
 	/* only valid if in constant ITR mode */
-	switch (adapter->itr_setting) {
+	switch (adapter->rx_itr_setting) {
 	case 0:
 	case 0:
 		/* throttling disabled */
 		/* throttling disabled */
 		ec->rx_coalesce_usecs = 0;
 		ec->rx_coalesce_usecs = 0;
@@ -1940,9 +1940,25 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
 		break;
 		break;
 	default:
 	default:
 		/* fixed interrupt rate mode */
 		/* fixed interrupt rate mode */
-		ec->rx_coalesce_usecs = 1000000/adapter->eitr_param;
+		ec->rx_coalesce_usecs = 1000000/adapter->rx_eitr_param;
 		break;
 		break;
 	}
 	}
+
+	/* only valid if in constant ITR mode */
+	switch (adapter->tx_itr_setting) {
+	case 0:
+		/* throttling disabled */
+		ec->tx_coalesce_usecs = 0;
+		break;
+	case 1:
+		/* dynamic ITR mode */
+		ec->tx_coalesce_usecs = 1;
+		break;
+	default:
+		ec->tx_coalesce_usecs = 1000000/adapter->tx_eitr_param;
+		break;
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1953,6 +1969,14 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
 	struct ixgbe_q_vector *q_vector;
 	struct ixgbe_q_vector *q_vector;
 	int i;
 	int i;
 
 
+	/*
+	 * don't accept tx specific changes if we've got mixed RxTx vectors
+	 * test and jump out here if needed before changing the rx numbers
+	 */
+	if ((1000000/ec->tx_coalesce_usecs) != adapter->tx_eitr_param &&
+	    adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count)
+		return -EINVAL;
+
 	if (ec->tx_max_coalesced_frames_irq)
 	if (ec->tx_max_coalesced_frames_irq)
 		adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq;
 		adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq;
 
 
@@ -1963,26 +1987,49 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
 			return -EINVAL;
 			return -EINVAL;
 
 
 		/* store the value in ints/second */
 		/* store the value in ints/second */
-		adapter->eitr_param = 1000000/ec->rx_coalesce_usecs;
+		adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
 
 
 		/* static value of interrupt rate */
 		/* static value of interrupt rate */
-		adapter->itr_setting = adapter->eitr_param;
+		adapter->rx_itr_setting = adapter->rx_eitr_param;
 		/* clear the lower bit as its used for dynamic state */
 		/* clear the lower bit as its used for dynamic state */
-		adapter->itr_setting &= ~1;
+		adapter->rx_itr_setting &= ~1;
 	} else if (ec->rx_coalesce_usecs == 1) {
 	} else if (ec->rx_coalesce_usecs == 1) {
 		/* 1 means dynamic mode */
 		/* 1 means dynamic mode */
-		adapter->eitr_param = 20000;
-		adapter->itr_setting = 1;
+		adapter->rx_eitr_param = 20000;
+		adapter->rx_itr_setting = 1;
 	} else {
 	} else {
 		/*
 		/*
 		 * any other value means disable eitr, which is best
 		 * any other value means disable eitr, which is best
 		 * served by setting the interrupt rate very high
 		 * served by setting the interrupt rate very high
 		 */
 		 */
 		if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
 		if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
-			adapter->eitr_param = IXGBE_MAX_RSC_INT_RATE;
+			adapter->rx_eitr_param = IXGBE_MAX_RSC_INT_RATE;
 		else
 		else
-			adapter->eitr_param = IXGBE_MAX_INT_RATE;
-		adapter->itr_setting = 0;
+			adapter->rx_eitr_param = IXGBE_MAX_INT_RATE;
+		adapter->rx_itr_setting = 0;
+	}
+
+	if (ec->tx_coalesce_usecs > 1) {
+		/* check the limits */
+		if ((1000000/ec->tx_coalesce_usecs > IXGBE_MAX_INT_RATE) ||
+		    (1000000/ec->tx_coalesce_usecs < IXGBE_MIN_INT_RATE))
+			return -EINVAL;
+
+		/* store the value in ints/second */
+		adapter->tx_eitr_param = 1000000/ec->tx_coalesce_usecs;
+
+		/* static value of interrupt rate */
+		adapter->tx_itr_setting = adapter->tx_eitr_param;
+
+		/* clear the lower bit as its used for dynamic state */
+		adapter->tx_itr_setting &= ~1;
+	} else if (ec->tx_coalesce_usecs == 1) {
+		/* 1 means dynamic mode */
+		adapter->tx_eitr_param = 10000;
+		adapter->tx_itr_setting = 1;
+	} else {
+		adapter->tx_eitr_param = IXGBE_MAX_INT_RATE;
+		adapter->tx_itr_setting = 0;
 	}
 	}
 
 
 	/* MSI/MSIx Interrupt Mode */
 	/* MSI/MSIx Interrupt Mode */
@@ -1992,17 +2039,17 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
 		for (i = 0; i < num_vectors; i++) {
 		for (i = 0; i < num_vectors; i++) {
 			q_vector = adapter->q_vector[i];
 			q_vector = adapter->q_vector[i];
 			if (q_vector->txr_count && !q_vector->rxr_count)
 			if (q_vector->txr_count && !q_vector->rxr_count)
-				/* tx vector gets half the rate */
-				q_vector->eitr = (adapter->eitr_param >> 1);
+				/* tx only */
+				q_vector->eitr = adapter->tx_eitr_param;
 			else
 			else
 				/* rx only or mixed */
 				/* rx only or mixed */
-				q_vector->eitr = adapter->eitr_param;
+				q_vector->eitr = adapter->rx_eitr_param;
 			ixgbe_write_eitr(q_vector);
 			ixgbe_write_eitr(q_vector);
 		}
 		}
 	/* Legacy Interrupt Mode */
 	/* Legacy Interrupt Mode */
 	} else {
 	} else {
 		q_vector = adapter->q_vector[0];
 		q_vector = adapter->q_vector[0];
-		q_vector->eitr = adapter->eitr_param;
+		q_vector->eitr = adapter->rx_eitr_param;
 		ixgbe_write_eitr(q_vector);
 		ixgbe_write_eitr(q_vector);
 	}
 	}
 
 

+ 67 - 44
drivers/net/ixgbe/ixgbe_main.c

@@ -926,12 +926,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
 			                      r_idx + 1);
 			                      r_idx + 1);
 		}
 		}
 
 
-		/* if this is a tx only vector halve the interrupt rate */
 		if (q_vector->txr_count && !q_vector->rxr_count)
 		if (q_vector->txr_count && !q_vector->rxr_count)
-			q_vector->eitr = (adapter->eitr_param >> 1);
+			/* tx only */
+			q_vector->eitr = adapter->tx_eitr_param;
 		else if (q_vector->rxr_count)
 		else if (q_vector->rxr_count)
-			/* rx only */
-			q_vector->eitr = adapter->eitr_param;
+			/* rx or mixed */
+			q_vector->eitr = adapter->rx_eitr_param;
 
 
 		ixgbe_write_eitr(q_vector);
 		ixgbe_write_eitr(q_vector);
 	}
 	}
@@ -1359,7 +1359,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
 	/* If all Rx work done, exit the polling mode */
 	/* If all Rx work done, exit the polling mode */
 	if (work_done < budget) {
 	if (work_done < budget) {
 		napi_complete(napi);
 		napi_complete(napi);
-		if (adapter->itr_setting & 1)
+		if (adapter->rx_itr_setting & 1)
 			ixgbe_set_itr_msix(q_vector);
 			ixgbe_set_itr_msix(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			ixgbe_irq_enable_queues(adapter,
 			ixgbe_irq_enable_queues(adapter,
@@ -1420,7 +1420,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
 	/* If all Rx work done, exit the polling mode */
 	/* If all Rx work done, exit the polling mode */
 	if (work_done < budget) {
 	if (work_done < budget) {
 		napi_complete(napi);
 		napi_complete(napi);
-		if (adapter->itr_setting & 1)
+		if (adapter->rx_itr_setting & 1)
 			ixgbe_set_itr_msix(q_vector);
 			ixgbe_set_itr_msix(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			ixgbe_irq_enable_queues(adapter,
 			ixgbe_irq_enable_queues(adapter,
@@ -1458,10 +1458,10 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
 	if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
 	if (!ixgbe_clean_tx_irq(q_vector, tx_ring))
 		work_done = budget;
 		work_done = budget;
 
 
-	/* If all Rx work done, exit the polling mode */
+	/* If all Tx work done, exit the polling mode */
 	if (work_done < budget) {
 	if (work_done < budget) {
 		napi_complete(napi);
 		napi_complete(napi);
-		if (adapter->itr_setting & 1)
+		if (adapter->tx_itr_setting & 1)
 			ixgbe_set_itr_msix(q_vector);
 			ixgbe_set_itr_msix(q_vector);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
 			ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
@@ -1848,7 +1848,7 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ixgbe_hw *hw = &adapter->hw;
 
 
 	IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
 	IXGBE_WRITE_REG(hw, IXGBE_EITR(0),
-	                EITR_INTS_PER_SEC_TO_REG(adapter->eitr_param));
+	                EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param));
 
 
 	ixgbe_set_ivar(adapter, 0, 0, 0);
 	ixgbe_set_ivar(adapter, 0, 0, 0);
 	ixgbe_set_ivar(adapter, 1, 0, 0);
 	ixgbe_set_ivar(adapter, 1, 0, 0);
@@ -1969,6 +1969,50 @@ static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
 	return mrqc;
 	return mrqc;
 }
 }
 
 
+/**
+ * ixgbe_configure_rscctl - enable RSC for the indicated ring
+ * @adapter:    address of board private structure
+ * @index:      index of ring to set
+ * @rx_buf_len: rx buffer length
+ **/
+static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index,
+                                   int rx_buf_len)
+{
+	struct ixgbe_ring *rx_ring;
+	struct ixgbe_hw *hw = &adapter->hw;
+	int j;
+	u32 rscctrl;
+
+	rx_ring = &adapter->rx_ring[index];
+	j = rx_ring->reg_idx;
+	rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
+	rscctrl |= IXGBE_RSCCTL_RSCEN;
+	/*
+	 * we must limit the number of descriptors so that the
+	 * total size of max desc * buf_len is not greater
+	 * than 65535
+	 */
+	if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
+#if (MAX_SKB_FRAGS > 16)
+		rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
+#elif (MAX_SKB_FRAGS > 8)
+		rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
+#elif (MAX_SKB_FRAGS > 4)
+		rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
+#else
+		rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
+#endif
+	} else {
+		if (rx_buf_len < IXGBE_RXBUFFER_4096)
+			rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
+		else if (rx_buf_len < IXGBE_RXBUFFER_8192)
+			rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
+		else
+			rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
+	}
+	IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl);
+}
+
 /**
 /**
  * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
  * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset
  * @adapter: board private structure
  * @adapter: board private structure
@@ -1990,7 +2034,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
 	u32 fctrl, hlreg0;
 	u32 fctrl, hlreg0;
 	u32 reta = 0, mrqc = 0;
 	u32 reta = 0, mrqc = 0;
 	u32 rdrxctl;
 	u32 rdrxctl;
-	u32 rscctrl;
 	int rx_buf_len;
 	int rx_buf_len;
 
 
 	/* Decide whether to use packet split mode or not */
 	/* Decide whether to use packet split mode or not */
@@ -2148,36 +2191,9 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
 
 
 	if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
 	if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
 		/* Enable 82599 HW-RSC */
 		/* Enable 82599 HW-RSC */
-		for (i = 0; i < adapter->num_rx_queues; i++) {
-			rx_ring = &adapter->rx_ring[i];
-			j = rx_ring->reg_idx;
-			rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
-			rscctrl |= IXGBE_RSCCTL_RSCEN;
-			/*
-			 * we must limit the number of descriptors so that the
-			 * total size of max desc * buf_len is not greater
-			 * than 65535
-			 */
-			if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
-#if (MAX_SKB_FRAGS > 16)
-				rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
-#elif (MAX_SKB_FRAGS > 8)
-				rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
-#elif (MAX_SKB_FRAGS > 4)
-				rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
-#else
-				rscctrl |= IXGBE_RSCCTL_MAXDESC_1;
-#endif
-			} else {
-				if (rx_buf_len < IXGBE_RXBUFFER_4096)
-					rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
-				else if (rx_buf_len < IXGBE_RXBUFFER_8192)
-					rscctrl |= IXGBE_RSCCTL_MAXDESC_8;
-				else
-					rscctrl |= IXGBE_RSCCTL_MAXDESC_4;
-			}
-			IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl);
-		}
+		for (i = 0; i < adapter->num_rx_queues; i++)
+			ixgbe_configure_rscctl(adapter, i, rx_buf_len);
+
 		/* Disable RSC for ACK packets */
 		/* Disable RSC for ACK packets */
 		IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
 		IXGBE_WRITE_REG(hw, IXGBE_RSCDBU,
 		   (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
 		   (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU)));
@@ -2926,6 +2942,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
 
 
 	ixgbe_napi_disable_all(adapter);
 	ixgbe_napi_disable_all(adapter);
 
 
+	clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
+	del_timer_sync(&adapter->sfp_timer);
 	del_timer_sync(&adapter->watchdog_timer);
 	del_timer_sync(&adapter->watchdog_timer);
 	cancel_work_sync(&adapter->watchdog_task);
 	cancel_work_sync(&adapter->watchdog_task);
 
 
@@ -2989,7 +3007,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
 	/* If budget not fully consumed, exit the polling mode */
 	/* If budget not fully consumed, exit the polling mode */
 	if (work_done < budget) {
 	if (work_done < budget) {
 		napi_complete(napi);
 		napi_complete(napi);
-		if (adapter->itr_setting & 1)
+		if (adapter->rx_itr_setting & 1)
 			ixgbe_set_itr(adapter);
 			ixgbe_set_itr(adapter);
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
 			ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE);
@@ -3599,7 +3617,10 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
 		if (!q_vector)
 		if (!q_vector)
 			goto err_out;
 			goto err_out;
 		q_vector->adapter = adapter;
 		q_vector->adapter = adapter;
-		q_vector->eitr = adapter->eitr_param;
+		if (q_vector->txr_count && !q_vector->rxr_count)
+			q_vector->eitr = adapter->tx_eitr_param;
+		else
+			q_vector->eitr = adapter->rx_eitr_param;
 		q_vector->v_idx = q_idx;
 		q_vector->v_idx = q_idx;
 		netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
 		netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64);
 		adapter->q_vector[q_idx] = q_vector;
 		adapter->q_vector[q_idx] = q_vector;
@@ -3868,8 +3889,10 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 	hw->fc.disable_fc_autoneg = false;
 	hw->fc.disable_fc_autoneg = false;
 
 
 	/* enable itr by default in dynamic mode */
 	/* enable itr by default in dynamic mode */
-	adapter->itr_setting = 1;
-	adapter->eitr_param = 20000;
+	adapter->rx_itr_setting = 1;
+	adapter->rx_eitr_param = 20000;
+	adapter->tx_itr_setting = 1;
+	adapter->tx_eitr_param = 10000;
 
 
 	/* set defaults for eitr in MegaBytes */
 	/* set defaults for eitr in MegaBytes */
 	adapter->eitr_low = 10;
 	adapter->eitr_low = 10;

+ 4 - 4
drivers/net/netxen/netxen_nic_main.c

@@ -1469,6 +1469,7 @@ netxen_nic_resume(struct pci_dev *pdev)
 	}
 	}
 
 
 	netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY);
 	netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY);
+	return 0;
 
 
 err_out_detach:
 err_out_detach:
 	netxen_nic_detach(adapter);
 	netxen_nic_detach(adapter);
@@ -1903,12 +1904,13 @@ static void netxen_tx_timeout_task(struct work_struct *work)
 
 
 		netif_wake_queue(adapter->netdev);
 		netif_wake_queue(adapter->netdev);
 
 
-		goto done;
+		clear_bit(__NX_RESETTING, &adapter->state);
 
 
 	} else {
 	} else {
+		clear_bit(__NX_RESETTING, &adapter->state);
 		if (!netxen_nic_reset_context(adapter)) {
 		if (!netxen_nic_reset_context(adapter)) {
 			adapter->netdev->trans_start = jiffies;
 			adapter->netdev->trans_start = jiffies;
-			goto done;
+			return;
 		}
 		}
 
 
 		/* context reset failed, fall through for fw reset */
 		/* context reset failed, fall through for fw reset */
@@ -1916,8 +1918,6 @@ static void netxen_tx_timeout_task(struct work_struct *work)
 
 
 request_reset:
 request_reset:
 	adapter->need_fw_reset = 1;
 	adapter->need_fw_reset = 1;
-done:
-	clear_bit(__NX_RESETTING, &adapter->state);
 }
 }
 
 
 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)

+ 5 - 6
drivers/net/pcmcia/pcnet_cs.c

@@ -340,12 +340,11 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
 	base = &virt[hw_info[i].offset & (req.Size-1)];
 	base = &virt[hw_info[i].offset & (req.Size-1)];
 	if ((readb(base+0) == hw_info[i].a0) &&
 	if ((readb(base+0) == hw_info[i].a0) &&
 	    (readb(base+2) == hw_info[i].a1) &&
 	    (readb(base+2) == hw_info[i].a1) &&
-	    (readb(base+4) == hw_info[i].a2))
-	    break;
-    }
-    if (i < NR_INFO) {
-	for (j = 0; j < 6; j++)
-	    dev->dev_addr[j] = readb(base + (j<<1));
+	    (readb(base+4) == hw_info[i].a2)) {
+		for (j = 0; j < 6; j++)
+		    dev->dev_addr[j] = readb(base + (j<<1));
+		break;
+	}
     }
     }
 
 
     iounmap(virt);
     iounmap(virt);

+ 3 - 1
drivers/net/sky2.c

@@ -1497,7 +1497,6 @@ static int sky2_up(struct net_device *dev)
 	if (ramsize > 0) {
 	if (ramsize > 0) {
 		u32 rxspace;
 		u32 rxspace;
 
 
-		hw->flags |= SKY2_HW_RAM_BUFFER;
 		pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
 		pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
 		if (ramsize < 16)
 		if (ramsize < 16)
 			rxspace = ramsize / 2;
 			rxspace = ramsize / 2;
@@ -2926,6 +2925,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
 			++hw->ports;
 			++hw->ports;
 	}
 	}
 
 
+	if (sky2_read8(hw, B2_E_0))
+		hw->flags |= SKY2_HW_RAM_BUFFER;
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 0 - 1
drivers/net/sunvnet.c

@@ -1016,7 +1016,6 @@ static const struct net_device_ops vnet_ops = {
 	.ndo_open		= vnet_open,
 	.ndo_open		= vnet_open,
 	.ndo_stop		= vnet_close,
 	.ndo_stop		= vnet_close,
 	.ndo_set_multicast_list	= vnet_set_rx_mode,
 	.ndo_set_multicast_list	= vnet_set_rx_mode,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address	= vnet_set_mac_addr,
 	.ndo_set_mac_address	= vnet_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_tx_timeout		= vnet_tx_timeout,
 	.ndo_tx_timeout		= vnet_tx_timeout,

+ 1 - 3
drivers/net/tun.c

@@ -946,8 +946,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		char *name;
 		char *name;
 		unsigned long flags = 0;
 		unsigned long flags = 0;
 
 
-		err = -EINVAL;
-
 		if (!capable(CAP_NET_ADMIN))
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 			return -EPERM;
 		err = security_tun_dev_create();
 		err = security_tun_dev_create();
@@ -964,7 +962,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 			flags |= TUN_TAP_DEV;
 			flags |= TUN_TAP_DEV;
 			name = "tap%d";
 			name = "tap%d";
 		} else
 		} else
-			goto failed;
+			return -EINVAL;
 
 
 		if (*ifr->ifr_name)
 		if (*ifr->ifr_name)
 			name = ifr->ifr_name;
 			name = ifr->ifr_name;

+ 11 - 7
drivers/net/usb/kaweth.c

@@ -263,6 +263,7 @@ static int kaweth_control(struct kaweth_device *kaweth,
 			  int timeout)
 			  int timeout)
 {
 {
 	struct usb_ctrlrequest *dr;
 	struct usb_ctrlrequest *dr;
+	int retval;
 
 
 	dbg("kaweth_control()");
 	dbg("kaweth_control()");
 
 
@@ -278,18 +279,21 @@ static int kaweth_control(struct kaweth_device *kaweth,
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	dr->bRequestType= requesttype;
+	dr->bRequestType = requesttype;
 	dr->bRequest = request;
 	dr->bRequest = request;
 	dr->wValue = cpu_to_le16(value);
 	dr->wValue = cpu_to_le16(value);
 	dr->wIndex = cpu_to_le16(index);
 	dr->wIndex = cpu_to_le16(index);
 	dr->wLength = cpu_to_le16(size);
 	dr->wLength = cpu_to_le16(size);
 
 
-	return kaweth_internal_control_msg(kaweth->dev,
-					pipe,
-					dr,
-					data,
-					size,
-					timeout);
+	retval = kaweth_internal_control_msg(kaweth->dev,
+					     pipe,
+					     dr,
+					     data,
+					     size,
+					     timeout);
+
+	kfree(dr);
+	return retval;
 }
 }
 
 
 /****************************************************************
 /****************************************************************

+ 66 - 1
drivers/net/usb/smsc95xx.c

@@ -1227,7 +1227,7 @@ static const struct driver_info smsc95xx_info = {
 	.rx_fixup	= smsc95xx_rx_fixup,
 	.rx_fixup	= smsc95xx_rx_fixup,
 	.tx_fixup	= smsc95xx_tx_fixup,
 	.tx_fixup	= smsc95xx_tx_fixup,
 	.status		= smsc95xx_status,
 	.status		= smsc95xx_status,
-	.flags		= FLAG_ETHER,
+	.flags		= FLAG_ETHER | FLAG_SEND_ZLP,
 };
 };
 
 
 static const struct usb_device_id products[] = {
 static const struct usb_device_id products[] = {
@@ -1236,11 +1236,76 @@ static const struct usb_device_id products[] = {
 		USB_DEVICE(0x0424, 0x9500),
 		USB_DEVICE(0x0424, 0x9500),
 		.driver_info = (unsigned long) &smsc95xx_info,
 		.driver_info = (unsigned long) &smsc95xx_info,
 	},
 	},
+	{
+		/* SMSC9505 USB Ethernet Device */
+		USB_DEVICE(0x0424, 0x9505),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC9500A USB Ethernet Device */
+		USB_DEVICE(0x0424, 0x9E00),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC9505A USB Ethernet Device */
+		USB_DEVICE(0x0424, 0x9E01),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
 	{
 	{
 		/* SMSC9512/9514 USB Hub & Ethernet Device */
 		/* SMSC9512/9514 USB Hub & Ethernet Device */
 		USB_DEVICE(0x0424, 0xec00),
 		USB_DEVICE(0x0424, 0xec00),
 		.driver_info = (unsigned long) &smsc95xx_info,
 		.driver_info = (unsigned long) &smsc95xx_info,
 	},
 	},
+	{
+		/* SMSC9500 USB Ethernet Device (SAL10) */
+		USB_DEVICE(0x0424, 0x9900),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC9505 USB Ethernet Device (SAL10) */
+		USB_DEVICE(0x0424, 0x9901),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC9500A USB Ethernet Device (SAL10) */
+		USB_DEVICE(0x0424, 0x9902),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC9505A USB Ethernet Device (SAL10) */
+		USB_DEVICE(0x0424, 0x9903),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC9512/9514 USB Hub & Ethernet Device (SAL10) */
+		USB_DEVICE(0x0424, 0x9904),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC9500A USB Ethernet Device (HAL) */
+		USB_DEVICE(0x0424, 0x9905),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC9505A USB Ethernet Device (HAL) */
+		USB_DEVICE(0x0424, 0x9906),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC9500 USB Ethernet Device (Alternate ID) */
+		USB_DEVICE(0x0424, 0x9907),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC9500A USB Ethernet Device (Alternate ID) */
+		USB_DEVICE(0x0424, 0x9908),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC9512/9514 USB Hub & Ethernet Device (Alternate ID) */
+		USB_DEVICE(0x0424, 0x9909),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
 	{ },		/* END */
 	{ },		/* END */
 };
 };
 MODULE_DEVICE_TABLE(usb, products);
 MODULE_DEVICE_TABLE(usb, products);

+ 1 - 1
drivers/net/usb/usbnet.c

@@ -1049,7 +1049,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
 	 * NOTE:  strictly conforming cdc-ether devices should expect
 	 * NOTE:  strictly conforming cdc-ether devices should expect
 	 * the ZLP here, but ignore the one-byte packet.
 	 * the ZLP here, but ignore the one-byte packet.
 	 */
 	 */
-	if ((length % dev->maxpacket) == 0) {
+	if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) {
 		urb->transfer_buffer_length++;
 		urb->transfer_buffer_length++;
 		if (skb_tailroom(skb)) {
 		if (skb_tailroom(skb)) {
 			skb->data[skb->len] = 0;
 			skb->data[skb->len] = 0;

+ 2 - 0
drivers/net/wireless/ath/ar9170/usb.c

@@ -64,6 +64,8 @@ static struct usb_device_id ar9170_usb_ids[] = {
 	{ USB_DEVICE(0x0cf3, 0x9170) },
 	{ USB_DEVICE(0x0cf3, 0x9170) },
 	/* Atheros TG121N */
 	/* Atheros TG121N */
 	{ USB_DEVICE(0x0cf3, 0x1001) },
 	{ USB_DEVICE(0x0cf3, 0x1001) },
+	/* TP-Link TL-WN821N v2 */
+	{ USB_DEVICE(0x0cf3, 0x1002) },
 	/* Cace Airpcap NX */
 	/* Cace Airpcap NX */
 	{ USB_DEVICE(0xcace, 0x0300) },
 	{ USB_DEVICE(0xcace, 0x0300) },
 	/* D-Link DWA 160A */
 	/* D-Link DWA 160A */

+ 18 - 5
drivers/net/wireless/ath/ath9k/calib.c

@@ -609,14 +609,24 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
 		AR_PHY_CH1_EXT_CCA,
 		AR_PHY_CH1_EXT_CCA,
 		AR_PHY_CH2_EXT_CCA
 		AR_PHY_CH2_EXT_CCA
 	};
 	};
-	u8 chainmask;
+	u8 chainmask, rx_chain_status;
 
 
+	rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK);
 	if (AR_SREV_9285(ah))
 	if (AR_SREV_9285(ah))
 		chainmask = 0x9;
 		chainmask = 0x9;
-	else if (AR_SREV_9280(ah) || AR_SREV_9287(ah))
-		chainmask = 0x1B;
-	else
-		chainmask = 0x3F;
+	else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
+		if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4))
+			chainmask = 0x1B;
+		else
+			chainmask = 0x09;
+	} else {
+		if (rx_chain_status & 0x4)
+			chainmask = 0x3F;
+		else if (rx_chain_status & 0x2)
+			chainmask = 0x1B;
+		else
+			chainmask = 0x09;
+	}
 
 
 	h = ah->nfCalHist;
 	h = ah->nfCalHist;
 
 
@@ -697,6 +707,8 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
 		noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
 		noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
 	else if (AR_SREV_9285(ah))
 	else if (AR_SREV_9285(ah))
 		noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
 		noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
+	else if (AR_SREV_9287(ah))
+		noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE;
 	else
 	else
 		noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
 		noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
 
 
@@ -924,6 +936,7 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset)
 		regVal |= (1 << (19 + i));
 		regVal |= (1 << (19 + i));
 		REG_WRITE(ah, 0x7834, regVal);
 		REG_WRITE(ah, 0x7834, regVal);
 		udelay(1);
 		udelay(1);
+		regVal = REG_READ(ah, 0x7834);
 		regVal &= (~(0x1 << (19 + i)));
 		regVal &= (~(0x1 << (19 + i)));
 		reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
 		reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
 		regVal |= (reg_field << (19 + i));
 		regVal |= (reg_field << (19 + i));

+ 1 - 0
drivers/net/wireless/ath/ath9k/calib.h

@@ -28,6 +28,7 @@ extern const struct ath9k_percal_data adc_init_dc_cal;
 #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE	-85
 #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE	-85
 #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE	-112
 #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE	-112
 #define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE	-118
 #define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE	-118
+#define AR_PHY_CCA_MAX_AR9287_GOOD_VALUE	-118
 #define AR_PHY_CCA_MAX_HIGH_VALUE      		-62
 #define AR_PHY_CCA_MAX_HIGH_VALUE      		-62
 #define AR_PHY_CCA_MIN_BAD_VALUE       		-140
 #define AR_PHY_CCA_MIN_BAD_VALUE       		-140
 #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT     3
 #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT     3

+ 3 - 1
drivers/net/wireless/ath/ath9k/eeprom_def.c

@@ -509,6 +509,8 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
 			REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
 			REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
 				      eep->baseEepHeader.dacLpMode);
 				      eep->baseEepHeader.dacLpMode);
 
 
+		udelay(100);
+
 		REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
 		REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
 			      pModal->miscBits >> 2);
 			      pModal->miscBits >> 2);
 
 
@@ -902,7 +904,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
 						  u16 powerLimit)
 						  u16 powerLimit)
 {
 {
 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
-#define REDUCE_SCALED_POWER_BY_THREE_CHAIN   10 /* 10*log10(3)*2 */
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN   9 /* 10*log10(3)*2 */
 
 
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
 	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;

+ 121 - 81
drivers/net/wireless/ath/ath9k/hw.c

@@ -842,7 +842,7 @@ static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
 
 
 static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
 static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
 {
 {
-	if (AR_SREV_9287_11(ah))
+	if (AR_SREV_9287_11_OR_LATER(ah))
 		INIT_INI_ARRAY(&ah->iniModesRxGain,
 		INIT_INI_ARRAY(&ah->iniModesRxGain,
 		ar9287Modes_rx_gain_9287_1_1,
 		ar9287Modes_rx_gain_9287_1_1,
 		ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
 		ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
@@ -853,7 +853,7 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
 	else if (AR_SREV_9280_20(ah))
 	else if (AR_SREV_9280_20(ah))
 		ath9k_hw_init_rxgain_ini(ah);
 		ath9k_hw_init_rxgain_ini(ah);
 
 
-	if (AR_SREV_9287_11(ah)) {
+	if (AR_SREV_9287_11_OR_LATER(ah)) {
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
 		INIT_INI_ARRAY(&ah->iniModesTxGain,
 		ar9287Modes_tx_gain_9287_1_1,
 		ar9287Modes_tx_gain_9287_1_1,
 		ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
 		ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
@@ -965,7 +965,7 @@ int ath9k_hw_init(struct ath_hw *ah)
 	ath9k_hw_init_mode_regs(ah);
 	ath9k_hw_init_mode_regs(ah);
 
 
 	if (ah->is_pciexpress)
 	if (ah->is_pciexpress)
-		ath9k_hw_configpcipowersave(ah, 0);
+		ath9k_hw_configpcipowersave(ah, 0, 0);
 	else
 	else
 		ath9k_hw_disablepcie(ah);
 		ath9k_hw_disablepcie(ah);
 
 
@@ -1273,6 +1273,15 @@ static void ath9k_hw_override_ini(struct ath_hw *ah,
 	 */
 	 */
 	REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
 	REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
 
 
+	if (AR_SREV_9280_10_OR_LATER(ah)) {
+		val = REG_READ(ah, AR_PCU_MISC_MODE2) &
+			       (~AR_PCU_MISC_MODE2_HWWAR1);
+
+		if (AR_SREV_9287_10_OR_LATER(ah))
+			val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
+
+		REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
+	}
 
 
 	if (!AR_SREV_5416_20_OR_LATER(ah) ||
 	if (!AR_SREV_5416_20_OR_LATER(ah) ||
 	    AR_SREV_9280_10_OR_LATER(ah))
 	    AR_SREV_9280_10_OR_LATER(ah))
@@ -1784,7 +1793,7 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan,
 static bool ath9k_hw_chip_reset(struct ath_hw *ah,
 static bool ath9k_hw_chip_reset(struct ath_hw *ah,
 				struct ath9k_channel *chan)
 				struct ath9k_channel *chan)
 {
 {
-	if (OLC_FOR_AR9280_20_LATER) {
+	if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) {
 		if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
 		if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
 			return false;
 			return false;
 	} else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
 	} else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
@@ -2338,6 +2347,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	struct ath9k_channel *curchan = ah->curchan;
 	struct ath9k_channel *curchan = ah->curchan;
 	u32 saveDefAntenna;
 	u32 saveDefAntenna;
 	u32 macStaId1;
 	u32 macStaId1;
+	u64 tsf = 0;
 	int i, rx_chainmask, r;
 	int i, rx_chainmask, r;
 
 
 	ah->extprotspacing = sc->ht_extprotspacing;
 	ah->extprotspacing = sc->ht_extprotspacing;
@@ -2347,7 +2357,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
 	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
 		return -EIO;
 		return -EIO;
 
 
-	if (curchan)
+	if (curchan && !ah->chip_fullsleep)
 		ath9k_hw_getnf(ah, curchan);
 		ath9k_hw_getnf(ah, curchan);
 
 
 	if (bChannelChange &&
 	if (bChannelChange &&
@@ -2356,8 +2366,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	    (chan->channel != ah->curchan->channel) &&
 	    (chan->channel != ah->curchan->channel) &&
 	    ((chan->channelFlags & CHANNEL_ALL) ==
 	    ((chan->channelFlags & CHANNEL_ALL) ==
 	     (ah->curchan->channelFlags & CHANNEL_ALL)) &&
 	     (ah->curchan->channelFlags & CHANNEL_ALL)) &&
-	    (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) &&
-				   !IS_CHAN_A_5MHZ_SPACED(ah->curchan)))) {
+	     !(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) ||
+	     IS_CHAN_A_5MHZ_SPACED(ah->curchan))) {
 
 
 		if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) {
 		if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) {
 			ath9k_hw_loadnf(ah, ah->curchan);
 			ath9k_hw_loadnf(ah, ah->curchan);
@@ -2372,6 +2382,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
 
 	macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
 	macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
 
 
+	/* For chips on which RTC reset is done, save TSF before it gets cleared */
+	if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+		tsf = ath9k_hw_gettsf64(ah);
+
 	saveLedState = REG_READ(ah, AR_CFG_LED) &
 	saveLedState = REG_READ(ah, AR_CFG_LED) &
 		(AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
 		(AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
 		 AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
 		 AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
@@ -2398,6 +2412,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 		udelay(50);
 		udelay(50);
 	}
 	}
 
 
+	/* Restore TSF */
+	if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+		ath9k_hw_settsf64(ah, tsf);
+
 	if (AR_SREV_9280_10_OR_LATER(ah))
 	if (AR_SREV_9280_10_OR_LATER(ah))
 		REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
 		REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
 
 
@@ -3005,9 +3023,10 @@ void ath9k_ps_restore(struct ath_softc *sc)
  * Programming the SerDes must go through the same 288 bit serial shift
  * Programming the SerDes must go through the same 288 bit serial shift
  * register as the other analog registers.  Hence the 9 writes.
  * register as the other analog registers.  Hence the 9 writes.
  */
  */
-void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
+void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off)
 {
 {
 	u8 i;
 	u8 i;
+	u32 val;
 
 
 	if (ah->is_pciexpress != true)
 	if (ah->is_pciexpress != true)
 		return;
 		return;
@@ -3017,84 +3036,113 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore)
 		return;
 		return;
 
 
 	/* Nothing to do on restore for 11N */
 	/* Nothing to do on restore for 11N */
-	if (restore)
-		return;
+	if (!restore) {
+		if (AR_SREV_9280_20_OR_LATER(ah)) {
+			/*
+			 * AR9280 2.0 or later chips use SerDes values from the
+			 * initvals.h initialized depending on chipset during
+			 * ath9k_hw_init()
+			 */
+			for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
+				REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
+					  INI_RA(&ah->iniPcieSerdes, i, 1));
+			}
+		} else if (AR_SREV_9280(ah) &&
+			   (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+
+			/* RX shut off when elecidle is asserted */
+			REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
+
+			/* Shut off CLKREQ active in L1 */
+			if (ah->config.pcie_clock_req)
+				REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
+			else
+				REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
 
 
-	if (AR_SREV_9280_20_OR_LATER(ah)) {
-		/*
-		 * AR9280 2.0 or later chips use SerDes values from the
-		 * initvals.h initialized depending on chipset during
-		 * ath9k_hw_init()
-		 */
-		for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
-			REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
-				  INI_RA(&ah->iniPcieSerdes, i, 1));
-		}
-	} else if (AR_SREV_9280(ah) &&
-		   (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
 
 
-		/* RX shut off when elecidle is asserted */
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
+			/* Load the new settings */
+			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
 
 
-		/* Shut off CLKREQ active in L1 */
-		if (ah->config.pcie_clock_req)
-			REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
-		else
-			REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
-
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
+		} else {
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
 
 
-		/* Load the new settings */
-		REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+			/* RX shut off when elecidle is asserted */
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
 
 
-	} else {
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+			/*
+			 * Ignore ah->ah_config.pcie_clock_req setting for
+			 * pre-AR9280 11n
+			 */
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
 
 
-		/* RX shut off when elecidle is asserted */
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+			REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
 
 
-		/*
-		 * Ignore ah->ah_config.pcie_clock_req setting for
-		 * pre-AR9280 11n
-		 */
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
+			/* Load the new settings */
+			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+		}
 
 
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-		REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
+		udelay(1000);
 
 
-		/* Load the new settings */
-		REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-	}
+		/* set bit 19 to allow forcing of pcie core into L1 state */
+		REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
 
 
-	udelay(1000);
+		/* Several PCIe massages to ensure proper behaviour */
+		if (ah->config.pcie_waen) {
+			val = ah->config.pcie_waen;
+			if (!power_off)
+				val &= (~AR_WA_D3_L1_DISABLE);
+		} else {
+			if (AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
+			    AR_SREV_9287(ah)) {
+				val = AR9285_WA_DEFAULT;
+				if (!power_off)
+					val &= (~AR_WA_D3_L1_DISABLE);
+			} else if (AR_SREV_9280(ah)) {
+				/*
+				 * On AR9280 chips bit 22 of 0x4004 needs to be
+				 * set otherwise card may disappear.
+				 */
+				val = AR9280_WA_DEFAULT;
+				if (!power_off)
+					val &= (~AR_WA_D3_L1_DISABLE);
+			} else
+				val = AR_WA_DEFAULT;
+		}
 
 
-	/* set bit 19 to allow forcing of pcie core into L1 state */
-	REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+		REG_WRITE(ah, AR_WA, val);
+	}
 
 
-	/* Several PCIe massages to ensure proper behaviour */
-	if (ah->config.pcie_waen) {
-		REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
-	} else {
-		if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah))
-			REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
+	if (power_off) {
 		/*
 		/*
-		 * On AR9280 chips bit 22 of 0x4004 needs to be set to
-		 * otherwise card may disappear.
+		 * Set PCIe workaround bits
+		 * bit 14 in WA register (disable L1) should only
+		 * be set when device enters D3 and be cleared
+		 * when device comes back to D0.
 		 */
 		 */
-		else if (AR_SREV_9280(ah))
-			REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT);
-		else
-			REG_WRITE(ah, AR_WA, AR_WA_DEFAULT);
+		if (ah->config.pcie_waen) {
+			if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
+				REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
+		} else {
+			if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
+			      AR_SREV_9287(ah)) &&
+			     (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
+			    (AR_SREV_9280(ah) &&
+			     (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
+				REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
+			}
+		}
 	}
 	}
 }
 }
 
 
@@ -3652,15 +3700,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
 	}
 	}
 #endif
 #endif
 
 
-	if ((ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) ||
-	    (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) ||
-	    (ah->hw_version.macVersion == AR_SREV_VERSION_9160) ||
-	    (ah->hw_version.macVersion == AR_SREV_VERSION_9100) ||
-	    (ah->hw_version.macVersion == AR_SREV_VERSION_9280) ||
-	    (ah->hw_version.macVersion == AR_SREV_VERSION_9285))
-		pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
-	else
-		pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
+	pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
 
 
 	if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
 	if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
 		pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
 		pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;

+ 2 - 2
drivers/net/wireless/ath/ath9k/hw.h

@@ -106,7 +106,7 @@
 #define AH_TSF_WRITE_TIMEOUT        100    /* (us) */
 #define AH_TSF_WRITE_TIMEOUT        100    /* (us) */
 #define AH_TIME_QUANTUM             10
 #define AH_TIME_QUANTUM             10
 #define AR_KEYTABLE_SIZE            128
 #define AR_KEYTABLE_SIZE            128
-#define POWER_UP_TIME               200000
+#define POWER_UP_TIME               10000
 #define SPUR_RSSI_THRESH            40
 #define SPUR_RSSI_THRESH            40
 
 
 #define CAB_TIMEOUT_VAL             10
 #define CAB_TIMEOUT_VAL             10
@@ -650,7 +650,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
 				    const struct ath9k_beacon_state *bs);
 				    const struct ath9k_beacon_state *bs);
 bool ath9k_hw_setpower(struct ath_hw *ah,
 bool ath9k_hw_setpower(struct ath_hw *ah,
 		       enum ath9k_power_mode mode);
 		       enum ath9k_power_mode mode);
-void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore);
+void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off);
 
 
 /* Interrupt Handling */
 /* Interrupt Handling */
 bool ath9k_hw_intrpend(struct ath_hw *ah);
 bool ath9k_hw_intrpend(struct ath_hw *ah);

+ 5 - 11
drivers/net/wireless/ath/ath9k/main.c

@@ -1131,7 +1131,7 @@ void ath_radio_enable(struct ath_softc *sc)
 	int r;
 	int r;
 
 
 	ath9k_ps_wakeup(sc);
 	ath9k_ps_wakeup(sc);
-	ath9k_hw_configpcipowersave(ah, 0);
+	ath9k_hw_configpcipowersave(ah, 0, 0);
 
 
 	if (!ah->curchan)
 	if (!ah->curchan)
 		ah->curchan = ath_get_curchannel(sc, sc->hw);
 		ah->curchan = ath_get_curchannel(sc, sc->hw);
@@ -1202,7 +1202,7 @@ void ath_radio_disable(struct ath_softc *sc)
 	spin_unlock_bh(&sc->sc_resetlock);
 	spin_unlock_bh(&sc->sc_resetlock);
 
 
 	ath9k_hw_phy_disable(ah);
 	ath9k_hw_phy_disable(ah);
-	ath9k_hw_configpcipowersave(ah, 1);
+	ath9k_hw_configpcipowersave(ah, 1, 1);
 	ath9k_ps_restore(sc);
 	ath9k_ps_restore(sc);
 	ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
 	ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
 }
 }
@@ -1226,11 +1226,6 @@ static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
 	bool blocked = !!ath_is_rfkill_set(sc);
 	bool blocked = !!ath_is_rfkill_set(sc);
 
 
 	wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
 	wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
-
-	if (blocked)
-		ath_radio_disable(sc);
-	else
-		ath_radio_enable(sc);
 }
 }
 
 
 static void ath_start_rfkill_poll(struct ath_softc *sc)
 static void ath_start_rfkill_poll(struct ath_softc *sc)
@@ -1260,6 +1255,7 @@ void ath_detach(struct ath_softc *sc)
 	DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
 	DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
 
 
 	ath_deinit_leds(sc);
 	ath_deinit_leds(sc);
+	wiphy_rfkill_stop_polling(sc->hw->wiphy);
 
 
 	for (i = 0; i < sc->num_sec_wiphy; i++) {
 	for (i = 0; i < sc->num_sec_wiphy; i++) {
 		struct ath_wiphy *aphy = sc->sec_wiphy[i];
 		struct ath_wiphy *aphy = sc->sec_wiphy[i];
@@ -1942,7 +1938,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
 	init_channel = ath_get_curchannel(sc, hw);
 	init_channel = ath_get_curchannel(sc, hw);
 
 
 	/* Reset SERDES registers */
 	/* Reset SERDES registers */
-	ath9k_hw_configpcipowersave(sc->sc_ah, 0);
+	ath9k_hw_configpcipowersave(sc->sc_ah, 0, 0);
 
 
 	/*
 	/*
 	 * The basic interface to setting the hardware in a good
 	 * The basic interface to setting the hardware in a good
@@ -2166,11 +2162,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 	} else
 	} else
 		sc->rx.rxlink = NULL;
 		sc->rx.rxlink = NULL;
 
 
-	wiphy_rfkill_stop_polling(sc->hw->wiphy);
-
 	/* disable HAL and put h/w to sleep */
 	/* disable HAL and put h/w to sleep */
 	ath9k_hw_disable(sc->sc_ah);
 	ath9k_hw_disable(sc->sc_ah);
-	ath9k_hw_configpcipowersave(sc->sc_ah, 1);
+	ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1);
 	ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
 	ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
 
 
 	sc->sc_flags |= SC_OP_INVALID;
 	sc->sc_flags |= SC_OP_INVALID;

+ 2 - 1
drivers/net/wireless/ath/ath9k/reg.h

@@ -676,8 +676,9 @@
 #define AR_RC_HOSTIF         0x00000100
 #define AR_RC_HOSTIF         0x00000100
 
 
 #define AR_WA                		0x4004
 #define AR_WA                		0x4004
+#define AR_WA_D3_L1_DISABLE		(1 << 14)
 #define AR9285_WA_DEFAULT 		0x004a05cb
 #define AR9285_WA_DEFAULT 		0x004a05cb
-#define AR9280_WA_DEFAULT           	0x0040073f
+#define AR9280_WA_DEFAULT           	0x0040073b
 #define AR_WA_DEFAULT               	0x0000073f
 #define AR_WA_DEFAULT               	0x0000073f
 
 
 
 

+ 19 - 2
drivers/net/wireless/b43/Kconfig

@@ -61,11 +61,28 @@ config B43_PCMCIA
 
 
 	  If unsure, say N.
 	  If unsure, say N.
 
 
+config B43_SDIO
+	bool "Broadcom 43xx SDIO device support (EXPERIMENTAL)"
+	depends on B43 && SSB_SDIOHOST_POSSIBLE && EXPERIMENTAL
+	select SSB_SDIOHOST
+	---help---
+	  Broadcom 43xx device support for Soft-MAC SDIO devices.
+
+	  With this config option you can drive Soft-MAC b43 cards with a
+	  Secure Digital I/O interface.
+	  This includes the WLAN daughter card found on the Nintendo Wii
+	  video game console.
+	  Note that this does not support Broadcom 43xx Full-MAC devices.
+
+	  It's safe to select Y here, even if you don't have a B43 SDIO device.
+
+	  If unsure, say N.
+
 # Data transfers to the device via PIO
 # Data transfers to the device via PIO
-# This is only needed on PCMCIA devices. All others can do DMA properly.
+# This is only needed on PCMCIA and SDIO devices. All others can do DMA properly.
 config B43_PIO
 config B43_PIO
 	bool
 	bool
-	depends on B43 && (B43_PCMCIA || B43_FORCE_PIO)
+	depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO)
 	select SSB_BLOCKIO
 	select SSB_BLOCKIO
 	default y
 	default y
 
 

+ 1 - 0
drivers/net/wireless/b43/Makefile

@@ -16,6 +16,7 @@ b43-$(CONFIG_B43_PIO)		+= pio.o
 b43-y				+= rfkill.o
 b43-y				+= rfkill.o
 b43-$(CONFIG_B43_LEDS)		+= leds.o
 b43-$(CONFIG_B43_LEDS)		+= leds.o
 b43-$(CONFIG_B43_PCMCIA)	+= pcmcia.o
 b43-$(CONFIG_B43_PCMCIA)	+= pcmcia.o
+b43-$(CONFIG_B43_SDIO)		+= sdio.o
 b43-$(CONFIG_B43_DEBUG)		+= debugfs.o
 b43-$(CONFIG_B43_DEBUG)		+= debugfs.o
 
 
 obj-$(CONFIG_B43)		+= b43.o
 obj-$(CONFIG_B43)		+= b43.o

+ 7 - 16
drivers/net/wireless/b43/b43.h

@@ -629,13 +629,6 @@ struct b43_wl {
 	 * from the mac80211 subsystem. */
 	 * from the mac80211 subsystem. */
 	u16 mac80211_initially_registered_queues;
 	u16 mac80211_initially_registered_queues;
 
 
-	/* R/W lock for data transmission.
-	 * Transmissions on 2+ queues can run concurrently, but somebody else
-	 * might sync with TX by write_lock_irqsave()'ing. */
-	rwlock_t tx_lock;
-	/* Lock for LEDs access. */
-	spinlock_t leds_lock;
-
 	/* We can only have one operating interface (802.11 core)
 	/* We can only have one operating interface (802.11 core)
 	 * at a time. General information about this interface follows.
 	 * at a time. General information about this interface follows.
 	 */
 	 */
@@ -686,6 +679,9 @@ struct b43_wl {
 	struct work_struct tx_work;
 	struct work_struct tx_work;
 	/* Queue of packets to be transmitted. */
 	/* Queue of packets to be transmitted. */
 	struct sk_buff_head tx_queue;
 	struct sk_buff_head tx_queue;
+
+	/* The device LEDs. */
+	struct b43_leds leds;
 };
 };
 
 
 /* The type of the firmware file. */
 /* The type of the firmware file. */
@@ -768,13 +764,10 @@ struct b43_wldev {
 	/* The device initialization status.
 	/* The device initialization status.
 	 * Use b43_status() to query. */
 	 * Use b43_status() to query. */
 	atomic_t __init_status;
 	atomic_t __init_status;
-	/* Saved init status for handling suspend. */
-	int suspend_init_status;
 
 
 	bool bad_frames_preempt;	/* Use "Bad Frames Preemption" (default off) */
 	bool bad_frames_preempt;	/* Use "Bad Frames Preemption" (default off) */
 	bool dfq_valid;		/* Directed frame queue valid (IBSS PS mode, ATIM) */
 	bool dfq_valid;		/* Directed frame queue valid (IBSS PS mode, ATIM) */
 	bool radio_hw_enable;	/* saved state of radio hardware enabled state */
 	bool radio_hw_enable;	/* saved state of radio hardware enabled state */
-	bool suspend_in_progress;	/* TRUE, if we are in a suspend/resume cycle */
 	bool qos_enabled;		/* TRUE, if QoS is used. */
 	bool qos_enabled;		/* TRUE, if QoS is used. */
 	bool hwcrypto_enabled;		/* TRUE, if HW crypto acceleration is enabled. */
 	bool hwcrypto_enabled;		/* TRUE, if HW crypto acceleration is enabled. */
 
 
@@ -794,12 +787,6 @@ struct b43_wldev {
 	/* Various statistics about the physical device. */
 	/* Various statistics about the physical device. */
 	struct b43_stats stats;
 	struct b43_stats stats;
 
 
-	/* The device LEDs. */
-	struct b43_led led_tx;
-	struct b43_led led_rx;
-	struct b43_led led_assoc;
-	struct b43_led led_radio;
-
 	/* Reason code of the last interrupt. */
 	/* Reason code of the last interrupt. */
 	u32 irq_reason;
 	u32 irq_reason;
 	u32 dma_reason[6];
 	u32 dma_reason[6];
@@ -830,6 +817,10 @@ struct b43_wldev {
 	/* Debugging stuff follows. */
 	/* Debugging stuff follows. */
 #ifdef CONFIG_B43_DEBUG
 #ifdef CONFIG_B43_DEBUG
 	struct b43_dfsentry *dfsentry;
 	struct b43_dfsentry *dfsentry;
+	unsigned int irq_count;
+	unsigned int irq_bit_count[32];
+	unsigned int tx_count;
+	unsigned int rx_count;
 #endif
 #endif
 };
 };
 
 

+ 1 - 0
drivers/net/wireless/b43/debugfs.c

@@ -689,6 +689,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev)
 	add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
 	add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
 	add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0);
 	add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0);
 	add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0);
 	add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0);
+	add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, 0);
 
 
 #undef add_dyn_dbg
 #undef add_dyn_dbg
 }
 }

+ 1 - 0
drivers/net/wireless/b43/debugfs.h

@@ -13,6 +13,7 @@ enum b43_dyndbg {		/* Dynamic debugging features */
 	B43_DBG_LO,
 	B43_DBG_LO,
 	B43_DBG_FIRMWARE,
 	B43_DBG_FIRMWARE,
 	B43_DBG_KEYS,
 	B43_DBG_KEYS,
+	B43_DBG_VERBOSESTATS,
 	__B43_NR_DYNDBG,
 	__B43_NR_DYNDBG,
 };
 };
 
 

+ 2 - 2
drivers/net/wireless/b43/dma.c

@@ -1428,9 +1428,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 				ring->nr_failed_tx_packets++;
 				ring->nr_failed_tx_packets++;
 			ring->nr_total_packet_tries += status->frame_count;
 			ring->nr_total_packet_tries += status->frame_count;
 #endif /* DEBUG */
 #endif /* DEBUG */
-			ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb);
+			ieee80211_tx_status(dev->wl->hw, meta->skb);
 
 
-			/* skb is freed by ieee80211_tx_status_irqsafe() */
+			/* skb is freed by ieee80211_tx_status() */
 			meta->skb = NULL;
 			meta->skb = NULL;
 		} else {
 		} else {
 			/* No need to call free_descriptor_buffer here, as
 			/* No need to call free_descriptor_buffer here, as

+ 191 - 75
drivers/net/wireless/b43/leds.c

@@ -34,57 +34,88 @@
 static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index,
 static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index,
 			    bool activelow)
 			    bool activelow)
 {
 {
-	struct b43_wl *wl = dev->wl;
-	unsigned long flags;
 	u16 ctl;
 	u16 ctl;
 
 
-	spin_lock_irqsave(&wl->leds_lock, flags);
 	ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
 	ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
 	if (activelow)
 	if (activelow)
 		ctl &= ~(1 << led_index);
 		ctl &= ~(1 << led_index);
 	else
 	else
 		ctl |= (1 << led_index);
 		ctl |= (1 << led_index);
 	b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
 	b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
-	spin_unlock_irqrestore(&wl->leds_lock, flags);
 }
 }
 
 
 static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index,
 static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index,
 			     bool activelow)
 			     bool activelow)
 {
 {
-	struct b43_wl *wl = dev->wl;
-	unsigned long flags;
 	u16 ctl;
 	u16 ctl;
 
 
-	spin_lock_irqsave(&wl->leds_lock, flags);
 	ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
 	ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
 	if (activelow)
 	if (activelow)
 		ctl |= (1 << led_index);
 		ctl |= (1 << led_index);
 	else
 	else
 		ctl &= ~(1 << led_index);
 		ctl &= ~(1 << led_index);
 	b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
 	b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
-	spin_unlock_irqrestore(&wl->leds_lock, flags);
 }
 }
 
 
-/* Callback from the LED subsystem. */
-static void b43_led_brightness_set(struct led_classdev *led_dev,
-				   enum led_brightness brightness)
+static void b43_led_update(struct b43_wldev *dev,
+			   struct b43_led *led)
 {
 {
-	struct b43_led *led = container_of(led_dev, struct b43_led, led_dev);
-	struct b43_wldev *dev = led->dev;
 	bool radio_enabled;
 	bool radio_enabled;
+	bool turn_on;
 
 
-	if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED))
+	if (!led->wl)
 		return;
 		return;
 
 
-	/* Checking the radio-enabled status here is slightly racy,
-	 * but we want to avoid the locking overhead and we don't care
-	 * whether the LED has the wrong state for a second. */
 	radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
 	radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
 
 
-	if (brightness == LED_OFF || !radio_enabled)
-		b43_led_turn_off(dev, led->index, led->activelow);
+	/* The led->state read is racy, but we don't care. In case we raced
+	 * with the brightness_set handler, we will be called again soon
+	 * to fixup our state. */
+	if (radio_enabled)
+		turn_on = atomic_read(&led->state) != LED_OFF;
 	else
 	else
+		turn_on = 0;
+	if (turn_on == led->hw_state)
+		return;
+	led->hw_state = turn_on;
+
+	if (turn_on)
 		b43_led_turn_on(dev, led->index, led->activelow);
 		b43_led_turn_on(dev, led->index, led->activelow);
+	else
+		b43_led_turn_off(dev, led->index, led->activelow);
+}
+
+static void b43_leds_work(struct work_struct *work)
+{
+	struct b43_leds *leds = container_of(work, struct b43_leds, work);
+	struct b43_wl *wl = container_of(leds, struct b43_wl, leds);
+	struct b43_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED))
+		goto out_unlock;
+
+	b43_led_update(dev, &wl->leds.led_tx);
+	b43_led_update(dev, &wl->leds.led_rx);
+	b43_led_update(dev, &wl->leds.led_radio);
+	b43_led_update(dev, &wl->leds.led_assoc);
+
+out_unlock:
+	mutex_unlock(&wl->mutex);
+}
+
+/* Callback from the LED subsystem. */
+static void b43_led_brightness_set(struct led_classdev *led_dev,
+				   enum led_brightness brightness)
+{
+	struct b43_led *led = container_of(led_dev, struct b43_led, led_dev);
+	struct b43_wl *wl = led->wl;
+
+	if (likely(!wl->leds.stop)) {
+		atomic_set(&led->state, brightness);
+		ieee80211_queue_work(wl->hw, &wl->leds.work);
+	}
 }
 }
 
 
 static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
 static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
@@ -93,15 +124,15 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
 {
 {
 	int err;
 	int err;
 
 
-	b43_led_turn_off(dev, led_index, activelow);
-	if (led->dev)
+	if (led->wl)
 		return -EEXIST;
 		return -EEXIST;
 	if (!default_trigger)
 	if (!default_trigger)
 		return -EINVAL;
 		return -EINVAL;
-	led->dev = dev;
+	led->wl = dev->wl;
 	led->index = led_index;
 	led->index = led_index;
 	led->activelow = activelow;
 	led->activelow = activelow;
 	strncpy(led->name, name, sizeof(led->name));
 	strncpy(led->name, name, sizeof(led->name));
+	atomic_set(&led->state, 0);
 
 
 	led->led_dev.name = led->name;
 	led->led_dev.name = led->name;
 	led->led_dev.default_trigger = default_trigger;
 	led->led_dev.default_trigger = default_trigger;
@@ -110,19 +141,19 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
 	err = led_classdev_register(dev->dev->dev, &led->led_dev);
 	err = led_classdev_register(dev->dev->dev, &led->led_dev);
 	if (err) {
 	if (err) {
 		b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
 		b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
-		led->dev = NULL;
+		led->wl = NULL;
 		return err;
 		return err;
 	}
 	}
+
 	return 0;
 	return 0;
 }
 }
 
 
 static void b43_unregister_led(struct b43_led *led)
 static void b43_unregister_led(struct b43_led *led)
 {
 {
-	if (!led->dev)
+	if (!led->wl)
 		return;
 		return;
 	led_classdev_unregister(&led->led_dev);
 	led_classdev_unregister(&led->led_dev);
-	b43_led_turn_off(led->dev, led->index, led->activelow);
-	led->dev = NULL;
+	led->wl = NULL;
 }
 }
 
 
 static void b43_map_led(struct b43_wldev *dev,
 static void b43_map_led(struct b43_wldev *dev,
@@ -137,24 +168,20 @@ static void b43_map_led(struct b43_wldev *dev,
 	 * generic LED triggers. */
 	 * generic LED triggers. */
 	switch (behaviour) {
 	switch (behaviour) {
 	case B43_LED_INACTIVE:
 	case B43_LED_INACTIVE:
-		break;
 	case B43_LED_OFF:
 	case B43_LED_OFF:
-		b43_led_turn_off(dev, led_index, activelow);
-		break;
 	case B43_LED_ON:
 	case B43_LED_ON:
-		b43_led_turn_on(dev, led_index, activelow);
 		break;
 		break;
 	case B43_LED_ACTIVITY:
 	case B43_LED_ACTIVITY:
 	case B43_LED_TRANSFER:
 	case B43_LED_TRANSFER:
 	case B43_LED_APTRANSFER:
 	case B43_LED_APTRANSFER:
 		snprintf(name, sizeof(name),
 		snprintf(name, sizeof(name),
 			 "b43-%s::tx", wiphy_name(hw->wiphy));
 			 "b43-%s::tx", wiphy_name(hw->wiphy));
-		b43_register_led(dev, &dev->led_tx, name,
+		b43_register_led(dev, &dev->wl->leds.led_tx, name,
 				 ieee80211_get_tx_led_name(hw),
 				 ieee80211_get_tx_led_name(hw),
 				 led_index, activelow);
 				 led_index, activelow);
 		snprintf(name, sizeof(name),
 		snprintf(name, sizeof(name),
 			 "b43-%s::rx", wiphy_name(hw->wiphy));
 			 "b43-%s::rx", wiphy_name(hw->wiphy));
-		b43_register_led(dev, &dev->led_rx, name,
+		b43_register_led(dev, &dev->wl->leds.led_rx, name,
 				 ieee80211_get_rx_led_name(hw),
 				 ieee80211_get_rx_led_name(hw),
 				 led_index, activelow);
 				 led_index, activelow);
 		break;
 		break;
@@ -164,18 +191,15 @@ static void b43_map_led(struct b43_wldev *dev,
 	case B43_LED_MODE_BG:
 	case B43_LED_MODE_BG:
 		snprintf(name, sizeof(name),
 		snprintf(name, sizeof(name),
 			 "b43-%s::radio", wiphy_name(hw->wiphy));
 			 "b43-%s::radio", wiphy_name(hw->wiphy));
-		b43_register_led(dev, &dev->led_radio, name,
+		b43_register_led(dev, &dev->wl->leds.led_radio, name,
 				 ieee80211_get_radio_led_name(hw),
 				 ieee80211_get_radio_led_name(hw),
 				 led_index, activelow);
 				 led_index, activelow);
-		/* Sync the RF-kill LED state with radio and switch states. */
-		if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev))
-			b43_led_turn_on(dev, led_index, activelow);
 		break;
 		break;
 	case B43_LED_WEIRD:
 	case B43_LED_WEIRD:
 	case B43_LED_ASSOC:
 	case B43_LED_ASSOC:
 		snprintf(name, sizeof(name),
 		snprintf(name, sizeof(name),
 			 "b43-%s::assoc", wiphy_name(hw->wiphy));
 			 "b43-%s::assoc", wiphy_name(hw->wiphy));
-		b43_register_led(dev, &dev->led_assoc, name,
+		b43_register_led(dev, &dev->wl->leds.led_assoc, name,
 				 ieee80211_get_assoc_led_name(hw),
 				 ieee80211_get_assoc_led_name(hw),
 				 led_index, activelow);
 				 led_index, activelow);
 		break;
 		break;
@@ -186,58 +210,150 @@ static void b43_map_led(struct b43_wldev *dev,
 	}
 	}
 }
 }
 
 
-void b43_leds_init(struct b43_wldev *dev)
+static void b43_led_get_sprominfo(struct b43_wldev *dev,
+				  unsigned int led_index,
+				  enum b43_led_behaviour *behaviour,
+				  bool *activelow)
 {
 {
 	struct ssb_bus *bus = dev->dev->bus;
 	struct ssb_bus *bus = dev->dev->bus;
 	u8 sprom[4];
 	u8 sprom[4];
-	int i;
-	enum b43_led_behaviour behaviour;
-	bool activelow;
 
 
 	sprom[0] = bus->sprom.gpio0;
 	sprom[0] = bus->sprom.gpio0;
 	sprom[1] = bus->sprom.gpio1;
 	sprom[1] = bus->sprom.gpio1;
 	sprom[2] = bus->sprom.gpio2;
 	sprom[2] = bus->sprom.gpio2;
 	sprom[3] = bus->sprom.gpio3;
 	sprom[3] = bus->sprom.gpio3;
 
 
-	for (i = 0; i < 4; i++) {
-		if (sprom[i] == 0xFF) {
-			/* There is no LED information in the SPROM
-			 * for this LED. Hardcode it here. */
-			activelow = 0;
-			switch (i) {
-			case 0:
-				behaviour = B43_LED_ACTIVITY;
-				activelow = 1;
-				if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
-					behaviour = B43_LED_RADIO_ALL;
-				break;
-			case 1:
-				behaviour = B43_LED_RADIO_B;
-				if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
-					behaviour = B43_LED_ASSOC;
-				break;
-			case 2:
-				behaviour = B43_LED_RADIO_A;
-				break;
-			case 3:
-				behaviour = B43_LED_OFF;
-				break;
-			default:
-				B43_WARN_ON(1);
-				return;
-			}
+	if (sprom[led_index] == 0xFF) {
+		/* There is no LED information in the SPROM
+		 * for this LED. Hardcode it here. */
+		*activelow = 0;
+		switch (led_index) {
+		case 0:
+			*behaviour = B43_LED_ACTIVITY;
+			*activelow = 1;
+			if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
+				*behaviour = B43_LED_RADIO_ALL;
+			break;
+		case 1:
+			*behaviour = B43_LED_RADIO_B;
+			if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
+				*behaviour = B43_LED_ASSOC;
+			break;
+		case 2:
+			*behaviour = B43_LED_RADIO_A;
+			break;
+		case 3:
+			*behaviour = B43_LED_OFF;
+			break;
+		default:
+			B43_WARN_ON(1);
+			return;
+		}
+	} else {
+		*behaviour = sprom[led_index] & B43_LED_BEHAVIOUR;
+		*activelow = !!(sprom[led_index] & B43_LED_ACTIVELOW);
+	}
+}
+
+void b43_leds_init(struct b43_wldev *dev)
+{
+	struct b43_led *led;
+	unsigned int i;
+	enum b43_led_behaviour behaviour;
+	bool activelow;
+
+	/* Sync the RF-kill LED state (if we have one) with radio and switch states. */
+	led = &dev->wl->leds.led_radio;
+	if (led->wl) {
+		if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) {
+			b43_led_turn_on(dev, led->index, led->activelow);
+			led->hw_state = 1;
+			atomic_set(&led->state, 1);
 		} else {
 		} else {
-			behaviour = sprom[i] & B43_LED_BEHAVIOUR;
-			activelow = !!(sprom[i] & B43_LED_ACTIVELOW);
+			b43_led_turn_off(dev, led->index, led->activelow);
+			led->hw_state = 0;
+			atomic_set(&led->state, 0);
 		}
 		}
-		b43_map_led(dev, i, behaviour, activelow);
 	}
 	}
+
+	/* Initialize TX/RX/ASSOC leds */
+	led = &dev->wl->leds.led_tx;
+	if (led->wl) {
+		b43_led_turn_off(dev, led->index, led->activelow);
+		led->hw_state = 0;
+		atomic_set(&led->state, 0);
+	}
+	led = &dev->wl->leds.led_rx;
+	if (led->wl) {
+		b43_led_turn_off(dev, led->index, led->activelow);
+		led->hw_state = 0;
+		atomic_set(&led->state, 0);
+	}
+	led = &dev->wl->leds.led_assoc;
+	if (led->wl) {
+		b43_led_turn_off(dev, led->index, led->activelow);
+		led->hw_state = 0;
+		atomic_set(&led->state, 0);
+	}
+
+	/* Initialize other LED states. */
+	for (i = 0; i < B43_MAX_NR_LEDS; i++) {
+		b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
+		switch (behaviour) {
+		case B43_LED_OFF:
+			b43_led_turn_off(dev, i, activelow);
+			break;
+		case B43_LED_ON:
+			b43_led_turn_on(dev, i, activelow);
+			break;
+		default:
+			/* Leave others as-is. */
+			break;
+		}
+	}
+
+	dev->wl->leds.stop = 0;
 }
 }
 
 
 void b43_leds_exit(struct b43_wldev *dev)
 void b43_leds_exit(struct b43_wldev *dev)
 {
 {
-	b43_unregister_led(&dev->led_tx);
-	b43_unregister_led(&dev->led_rx);
-	b43_unregister_led(&dev->led_assoc);
-	b43_unregister_led(&dev->led_radio);
+	struct b43_leds *leds = &dev->wl->leds;
+
+	b43_led_turn_off(dev, leds->led_tx.index, leds->led_tx.activelow);
+	b43_led_turn_off(dev, leds->led_rx.index, leds->led_rx.activelow);
+	b43_led_turn_off(dev, leds->led_assoc.index, leds->led_assoc.activelow);
+	b43_led_turn_off(dev, leds->led_radio.index, leds->led_radio.activelow);
+}
+
+void b43_leds_stop(struct b43_wldev *dev)
+{
+	struct b43_leds *leds = &dev->wl->leds;
+
+	leds->stop = 1;
+	cancel_work_sync(&leds->work);
+}
+
+void b43_leds_register(struct b43_wldev *dev)
+{
+	unsigned int i;
+	enum b43_led_behaviour behaviour;
+	bool activelow;
+
+	INIT_WORK(&dev->wl->leds.work, b43_leds_work);
+
+	/* Register the LEDs to the LED subsystem. */
+	for (i = 0; i < B43_MAX_NR_LEDS; i++) {
+		b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
+		b43_map_led(dev, i, behaviour, activelow);
+	}
+}
+
+void b43_leds_unregister(struct b43_wldev *dev)
+{
+	struct b43_leds *leds = &dev->wl->leds;
+
+	b43_unregister_led(&leds->led_tx);
+	b43_unregister_led(&leds->led_rx);
+	b43_unregister_led(&leds->led_assoc);
+	b43_unregister_led(&leds->led_radio);
 }
 }

+ 31 - 2
drivers/net/wireless/b43/leds.h

@@ -7,12 +7,13 @@ struct b43_wldev;
 
 
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/leds.h>
 #include <linux/leds.h>
+#include <linux/workqueue.h>
 
 
 
 
 #define B43_LED_MAX_NAME_LEN	31
 #define B43_LED_MAX_NAME_LEN	31
 
 
 struct b43_led {
 struct b43_led {
-	struct b43_wldev *dev;
+	struct b43_wl *wl;
 	/* The LED class device */
 	/* The LED class device */
 	struct led_classdev led_dev;
 	struct led_classdev led_dev;
 	/* The index number of the LED. */
 	/* The index number of the LED. */
@@ -22,8 +23,24 @@ struct b43_led {
 	bool activelow;
 	bool activelow;
 	/* The unique name string for this LED device. */
 	/* The unique name string for this LED device. */
 	char name[B43_LED_MAX_NAME_LEN + 1];
 	char name[B43_LED_MAX_NAME_LEN + 1];
+	/* The current status of the LED. This is updated locklessly. */
+	atomic_t state;
+	/* The active state in hardware. */
+	bool hw_state;
 };
 };
 
 
+struct b43_leds {
+	struct b43_led led_tx;
+	struct b43_led led_rx;
+	struct b43_led led_radio;
+	struct b43_led led_assoc;
+
+	bool stop;
+	struct work_struct work;
+};
+
+#define B43_MAX_NR_LEDS			4
+
 #define B43_LED_BEHAVIOUR		0x7F
 #define B43_LED_BEHAVIOUR		0x7F
 #define B43_LED_ACTIVELOW		0x80
 #define B43_LED_ACTIVELOW		0x80
 /* LED behaviour values */
 /* LED behaviour values */
@@ -42,23 +59,35 @@ enum b43_led_behaviour {
 	B43_LED_INACTIVE,
 	B43_LED_INACTIVE,
 };
 };
 
 
+void b43_leds_register(struct b43_wldev *dev);
+void b43_leds_unregister(struct b43_wldev *dev);
 void b43_leds_init(struct b43_wldev *dev);
 void b43_leds_init(struct b43_wldev *dev);
 void b43_leds_exit(struct b43_wldev *dev);
 void b43_leds_exit(struct b43_wldev *dev);
+void b43_leds_stop(struct b43_wldev *dev);
 
 
 
 
 #else /* CONFIG_B43_LEDS */
 #else /* CONFIG_B43_LEDS */
 /* LED support disabled */
 /* LED support disabled */
 
 
-struct b43_led {
+struct b43_leds {
 	/* empty */
 	/* empty */
 };
 };
 
 
+static inline void b43_leds_register(struct b43_wldev *dev)
+{
+}
+static inline void b43_leds_unregister(struct b43_wldev *dev)
+{
+}
 static inline void b43_leds_init(struct b43_wldev *dev)
 static inline void b43_leds_init(struct b43_wldev *dev)
 {
 {
 }
 }
 static inline void b43_leds_exit(struct b43_wldev *dev)
 static inline void b43_leds_exit(struct b43_wldev *dev)
 {
 {
 }
 }
+static inline void b43_leds_stop(struct b43_wldev *dev)
+{
+}
 #endif /* CONFIG_B43_LEDS */
 #endif /* CONFIG_B43_LEDS */
 
 
 #endif /* B43_LEDS_H_ */
 #endif /* B43_LEDS_H_ */

+ 128 - 96
drivers/net/wireless/b43/main.c

@@ -8,6 +8,9 @@
   Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
   Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
   Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
 
+  SDIO support
+  Copyright (c) 2009 Albert Herranz <albert_herranz@yahoo.es>
+
   Some parts of the code in this file are derived from the ipw2200
   Some parts of the code in this file are derived from the ipw2200
   driver  Copyright(c) 2003 - 2004 Intel Corporation.
   driver  Copyright(c) 2003 - 2004 Intel Corporation.
 
 
@@ -53,6 +56,8 @@
 #include "xmit.h"
 #include "xmit.h"
 #include "lo.h"
 #include "lo.h"
 #include "pcmcia.h"
 #include "pcmcia.h"
+#include "sdio.h"
+#include <linux/mmc/sdio_func.h>
 
 
 MODULE_DESCRIPTION("Broadcom B43 wireless driver");
 MODULE_DESCRIPTION("Broadcom B43 wireless driver");
 MODULE_AUTHOR("Martin Langer");
 MODULE_AUTHOR("Martin Langer");
@@ -1587,7 +1592,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
 	mutex_lock(&wl->mutex);
 	mutex_lock(&wl->mutex);
 	dev = wl->current_dev;
 	dev = wl->current_dev;
 	if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
 	if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
-		if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) {
+		if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
 			/* wl->mutex is enough. */
 			/* wl->mutex is enough. */
 			b43_do_beacon_update_trigger_work(dev);
 			b43_do_beacon_update_trigger_work(dev);
 			mmiowb();
 			mmiowb();
@@ -1825,6 +1830,16 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
 
 
 	/* Re-enable interrupts on the device by restoring the current interrupt mask. */
 	/* Re-enable interrupts on the device by restoring the current interrupt mask. */
 	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+
+#if B43_DEBUG
+	if (b43_debug(dev, B43_DBG_VERBOSESTATS)) {
+		dev->irq_count++;
+		for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) {
+			if (reason & (1 << i))
+				dev->irq_bit_count[i]++;
+		}
+	}
+#endif
 }
 }
 
 
 /* Interrupt thread handler. Handles device interrupts in thread context. */
 /* Interrupt thread handler. Handles device interrupts in thread context. */
@@ -1905,6 +1920,21 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
 	return ret;
 	return ret;
 }
 }
 
 
+/* SDIO interrupt handler. This runs in process context. */
+static void b43_sdio_interrupt_handler(struct b43_wldev *dev)
+{
+	struct b43_wl *wl = dev->wl;
+	irqreturn_t ret;
+
+	mutex_lock(&wl->mutex);
+
+	ret = b43_do_interrupt(dev);
+	if (ret == IRQ_WAKE_THREAD)
+		b43_do_interrupt_thread(dev);
+
+	mutex_unlock(&wl->mutex);
+}
+
 void b43_do_release_fw(struct b43_firmware_file *fw)
 void b43_do_release_fw(struct b43_firmware_file *fw)
 {
 {
 	release_firmware(fw->data);
 	release_firmware(fw->data);
@@ -2645,6 +2675,20 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
 			cfp_pretbtt = 50;
 			cfp_pretbtt = 50;
 	}
 	}
 	b43_write16(dev, 0x612, cfp_pretbtt);
 	b43_write16(dev, 0x612, cfp_pretbtt);
+
+	/* FIXME: We don't currently implement the PMQ mechanism,
+	 *        so always disable it. If we want to implement PMQ,
+	 *        we need to enable it here (clear DISCPMQ) in AP mode.
+	 */
+	if (0  /* ctl & B43_MACCTL_AP */) {
+		b43_write32(dev, B43_MMIO_MACCTL,
+			    b43_read32(dev, B43_MMIO_MACCTL)
+			    & ~B43_MACCTL_DISCPMQ);
+	} else {
+		b43_write32(dev, B43_MMIO_MACCTL,
+			    b43_read32(dev, B43_MMIO_MACCTL)
+			    | B43_MACCTL_DISCPMQ);
+	}
 }
 }
 
 
 static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm)
 static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm)
@@ -2873,6 +2917,27 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
 
 
 	atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
 	atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
 	wmb();
 	wmb();
+
+#if B43_DEBUG
+	if (b43_debug(dev, B43_DBG_VERBOSESTATS)) {
+		unsigned int i;
+
+		b43dbg(dev->wl, "Stats: %7u IRQs/sec, %7u TX/sec, %7u RX/sec\n",
+		       dev->irq_count / 15,
+		       dev->tx_count / 15,
+		       dev->rx_count / 15);
+		dev->irq_count = 0;
+		dev->tx_count = 0;
+		dev->rx_count = 0;
+		for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) {
+			if (dev->irq_bit_count[i]) {
+				b43dbg(dev->wl, "Stats: %7u IRQ-%02u/sec (0x%08X)\n",
+				       dev->irq_bit_count[i] / 15, i, (1 << i));
+				dev->irq_bit_count[i] = 0;
+			}
+		}
+	}
+#endif
 }
 }
 
 
 static void do_periodic_work(struct b43_wldev *dev)
 static void do_periodic_work(struct b43_wldev *dev)
@@ -3002,14 +3067,18 @@ static void b43_security_init(struct b43_wldev *dev)
 static int b43_rng_read(struct hwrng *rng, u32 *data)
 static int b43_rng_read(struct hwrng *rng, u32 *data)
 {
 {
 	struct b43_wl *wl = (struct b43_wl *)rng->priv;
 	struct b43_wl *wl = (struct b43_wl *)rng->priv;
+	struct b43_wldev *dev;
+	int count = -ENODEV;
 
 
-	/* FIXME: We need to take wl->mutex here to make sure the device
-	 * is not going away from under our ass. However it could deadlock
-	 * with hwrng internal locking. */
-
-	*data = b43_read16(wl->current_dev, B43_MMIO_RNG);
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (likely(dev && b43_status(dev) >= B43_STAT_INITIALIZED)) {
+		*data = b43_read16(dev, B43_MMIO_RNG);
+		count = sizeof(u16);
+	}
+	mutex_unlock(&wl->mutex);
 
 
-	return (sizeof(u16));
+	return count;
 }
 }
 #endif /* CONFIG_B43_HWRNG */
 #endif /* CONFIG_B43_HWRNG */
 
 
@@ -3068,6 +3137,9 @@ static void b43_tx_work(struct work_struct *work)
 			dev_kfree_skb(skb); /* Drop it */
 			dev_kfree_skb(skb); /* Drop it */
 	}
 	}
 
 
+#if B43_DEBUG
+	dev->tx_count++;
+#endif
 	mutex_unlock(&wl->mutex);
 	mutex_unlock(&wl->mutex);
 }
 }
 
 
@@ -3820,7 +3892,7 @@ redo:
 
 
 	/* Disable interrupts on the device. */
 	/* Disable interrupts on the device. */
 	b43_set_status(dev, B43_STAT_INITIALIZED);
 	b43_set_status(dev, B43_STAT_INITIALIZED);
-	if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) {
+	if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
 		/* wl->mutex is locked. That is enough. */
 		/* wl->mutex is locked. That is enough. */
 		b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
 		b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
 		b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);	/* Flush */
 		b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);	/* Flush */
@@ -3830,10 +3902,15 @@ redo:
 		b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);	/* Flush */
 		b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);	/* Flush */
 		spin_unlock_irq(&wl->hardirq_lock);
 		spin_unlock_irq(&wl->hardirq_lock);
 	}
 	}
-	/* Synchronize the interrupt handlers. Unlock to avoid deadlocks. */
+	/* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */
 	orig_dev = dev;
 	orig_dev = dev;
 	mutex_unlock(&wl->mutex);
 	mutex_unlock(&wl->mutex);
-	synchronize_irq(dev->dev->irq);
+	if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
+		b43_sdio_free_irq(dev);
+	} else {
+		synchronize_irq(dev->dev->irq);
+		free_irq(dev->dev->irq, dev);
+	}
 	mutex_lock(&wl->mutex);
 	mutex_lock(&wl->mutex);
 	dev = wl->current_dev;
 	dev = wl->current_dev;
 	if (!dev)
 	if (!dev)
@@ -3850,7 +3927,7 @@ redo:
 		dev_kfree_skb(skb_dequeue(&wl->tx_queue));
 		dev_kfree_skb(skb_dequeue(&wl->tx_queue));
 
 
 	b43_mac_suspend(dev);
 	b43_mac_suspend(dev);
-	free_irq(dev->dev->irq, dev);
+	b43_leds_exit(dev);
 	b43dbg(wl, "Wireless interface stopped\n");
 	b43dbg(wl, "Wireless interface stopped\n");
 
 
 	return dev;
 	return dev;
@@ -3864,12 +3941,20 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
 	B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
 	B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
 
 
 	drain_txstatus_queue(dev);
 	drain_txstatus_queue(dev);
-	err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
-				   b43_interrupt_thread_handler,
-				   IRQF_SHARED, KBUILD_MODNAME, dev);
-	if (err) {
-		b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
-		goto out;
+	if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
+		err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler);
+		if (err) {
+			b43err(dev->wl, "Cannot request SDIO IRQ\n");
+			goto out;
+		}
+	} else {
+		err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
+					   b43_interrupt_thread_handler,
+					   IRQF_SHARED, KBUILD_MODNAME, dev);
+		if (err) {
+			b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
+			goto out;
+		}
 	}
 	}
 
 
 	/* We are ready to run. */
 	/* We are ready to run. */
@@ -3882,8 +3967,10 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
 	/* Start maintainance work */
 	/* Start maintainance work */
 	b43_periodic_tasks_setup(dev);
 	b43_periodic_tasks_setup(dev);
 
 
+	b43_leds_init(dev);
+
 	b43dbg(dev->wl, "Wireless interface started\n");
 	b43dbg(dev->wl, "Wireless interface started\n");
-      out:
+out:
 	return err;
 	return err;
 }
 }
 
 
@@ -4160,10 +4247,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
 	macctl |= B43_MACCTL_PSM_JMP0;
 	macctl |= B43_MACCTL_PSM_JMP0;
 	b43_write32(dev, B43_MMIO_MACCTL, macctl);
 	b43_write32(dev, B43_MMIO_MACCTL, macctl);
 
 
-	if (!dev->suspend_in_progress) {
-		b43_leds_exit(dev);
-		b43_rng_exit(dev->wl);
-	}
 	b43_dma_free(dev);
 	b43_dma_free(dev);
 	b43_pio_free(dev);
 	b43_pio_free(dev);
 	b43_chip_exit(dev);
 	b43_chip_exit(dev);
@@ -4180,7 +4263,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
 /* Initialize a wireless core */
 /* Initialize a wireless core */
 static int b43_wireless_core_init(struct b43_wldev *dev)
 static int b43_wireless_core_init(struct b43_wldev *dev)
 {
 {
-	struct b43_wl *wl = dev->wl;
 	struct ssb_bus *bus = dev->dev->bus;
 	struct ssb_bus *bus = dev->dev->bus;
 	struct ssb_sprom *sprom = &bus->sprom;
 	struct ssb_sprom *sprom = &bus->sprom;
 	struct b43_phy *phy = &dev->phy;
 	struct b43_phy *phy = &dev->phy;
@@ -4264,7 +4346,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 	/* Maximum Contention Window */
 	/* Maximum Contention Window */
 	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
 	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
 
 
-	if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) {
+	if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
+	    (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) ||
+	    B43_FORCE_PIO) {
 		dev->__using_pio_transfers = 1;
 		dev->__using_pio_transfers = 1;
 		err = b43_pio_init(dev);
 		err = b43_pio_init(dev);
 	} else {
 	} else {
@@ -4280,15 +4364,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
 	ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
 	ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
 	b43_upload_card_macaddress(dev);
 	b43_upload_card_macaddress(dev);
 	b43_security_init(dev);
 	b43_security_init(dev);
-	if (!dev->suspend_in_progress)
-		b43_rng_init(wl);
+
+	ieee80211_wake_queues(dev->wl->hw);
 
 
 	ieee80211_wake_queues(dev->wl->hw);
 	ieee80211_wake_queues(dev->wl->hw);
 
 
 	b43_set_status(dev, B43_STAT_INITIALIZED);
 	b43_set_status(dev, B43_STAT_INITIALIZED);
 
 
-	if (!dev->suspend_in_progress)
-		b43_leds_init(dev);
 out:
 out:
 	return err;
 	return err;
 
 
@@ -4837,7 +4919,6 @@ static int b43_wireless_init(struct ssb_device *dev)
 
 
 	/* Initialize struct b43_wl */
 	/* Initialize struct b43_wl */
 	wl->hw = hw;
 	wl->hw = hw;
-	spin_lock_init(&wl->leds_lock);
 	mutex_init(&wl->mutex);
 	mutex_init(&wl->mutex);
 	spin_lock_init(&wl->hardirq_lock);
 	spin_lock_init(&wl->hardirq_lock);
 	INIT_LIST_HEAD(&wl->devlist);
 	INIT_LIST_HEAD(&wl->devlist);
@@ -4878,6 +4959,8 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id)
 		err = ieee80211_register_hw(wl->hw);
 		err = ieee80211_register_hw(wl->hw);
 		if (err)
 		if (err)
 			goto err_one_core_detach;
 			goto err_one_core_detach;
+		b43_leds_register(wl->current_dev);
+		b43_rng_init(wl);
 	}
 	}
 
 
       out:
       out:
@@ -4906,12 +4989,15 @@ static void b43_remove(struct ssb_device *dev)
 		 * might have modified it. Restoring is important, so the networking
 		 * might have modified it. Restoring is important, so the networking
 		 * stack can properly free resources. */
 		 * stack can properly free resources. */
 		wl->hw->queues = wl->mac80211_initially_registered_queues;
 		wl->hw->queues = wl->mac80211_initially_registered_queues;
+		b43_leds_stop(wldev);
 		ieee80211_unregister_hw(wl->hw);
 		ieee80211_unregister_hw(wl->hw);
 	}
 	}
 
 
 	b43_one_core_detach(dev);
 	b43_one_core_detach(dev);
 
 
 	if (list_empty(&wl->devlist)) {
 	if (list_empty(&wl->devlist)) {
+		b43_rng_exit(wl);
+		b43_leds_unregister(wldev);
 		/* Last core on the chip unregistered.
 		/* Last core on the chip unregistered.
 		 * We can destroy common struct b43_wl.
 		 * We can destroy common struct b43_wl.
 		 */
 		 */
@@ -4929,80 +5015,17 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
 	ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
 	ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
 }
 }
 
 
-#ifdef CONFIG_PM
-
-static int b43_suspend(struct ssb_device *dev, pm_message_t state)
-{
-	struct b43_wldev *wldev = ssb_get_drvdata(dev);
-	struct b43_wl *wl = wldev->wl;
-
-	b43dbg(wl, "Suspending...\n");
-
-	mutex_lock(&wl->mutex);
-	wldev->suspend_in_progress = true;
-	wldev->suspend_init_status = b43_status(wldev);
-	if (wldev->suspend_init_status >= B43_STAT_STARTED)
-		wldev = b43_wireless_core_stop(wldev);
-	if (wldev && wldev->suspend_init_status >= B43_STAT_INITIALIZED)
-		b43_wireless_core_exit(wldev);
-	mutex_unlock(&wl->mutex);
-
-	b43dbg(wl, "Device suspended.\n");
-
-	return 0;
-}
-
-static int b43_resume(struct ssb_device *dev)
-{
-	struct b43_wldev *wldev = ssb_get_drvdata(dev);
-	struct b43_wl *wl = wldev->wl;
-	int err = 0;
-
-	b43dbg(wl, "Resuming...\n");
-
-	mutex_lock(&wl->mutex);
-	if (wldev->suspend_init_status >= B43_STAT_INITIALIZED) {
-		err = b43_wireless_core_init(wldev);
-		if (err) {
-			b43err(wl, "Resume failed at core init\n");
-			goto out;
-		}
-	}
-	if (wldev->suspend_init_status >= B43_STAT_STARTED) {
-		err = b43_wireless_core_start(wldev);
-		if (err) {
-			b43_leds_exit(wldev);
-			b43_rng_exit(wldev->wl);
-			b43_wireless_core_exit(wldev);
-			b43err(wl, "Resume failed at core start\n");
-			goto out;
-		}
-	}
-	b43dbg(wl, "Device resumed.\n");
- out:
-	wldev->suspend_in_progress = false;
-	mutex_unlock(&wl->mutex);
-	return err;
-}
-
-#else /* CONFIG_PM */
-# define b43_suspend	NULL
-# define b43_resume	NULL
-#endif /* CONFIG_PM */
-
 static struct ssb_driver b43_ssb_driver = {
 static struct ssb_driver b43_ssb_driver = {
 	.name		= KBUILD_MODNAME,
 	.name		= KBUILD_MODNAME,
 	.id_table	= b43_ssb_tbl,
 	.id_table	= b43_ssb_tbl,
 	.probe		= b43_probe,
 	.probe		= b43_probe,
 	.remove		= b43_remove,
 	.remove		= b43_remove,
-	.suspend	= b43_suspend,
-	.resume		= b43_resume,
 };
 };
 
 
 static void b43_print_driverinfo(void)
 static void b43_print_driverinfo(void)
 {
 {
 	const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
 	const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
-		   *feat_leds = "";
+		   *feat_leds = "", *feat_sdio = "";
 
 
 #ifdef CONFIG_B43_PCI_AUTOSELECT
 #ifdef CONFIG_B43_PCI_AUTOSELECT
 	feat_pci = "P";
 	feat_pci = "P";
@@ -5015,12 +5038,15 @@ static void b43_print_driverinfo(void)
 #endif
 #endif
 #ifdef CONFIG_B43_LEDS
 #ifdef CONFIG_B43_LEDS
 	feat_leds = "L";
 	feat_leds = "L";
+#endif
+#ifdef CONFIG_B43_SDIO
+	feat_sdio = "S";
 #endif
 #endif
 	printk(KERN_INFO "Broadcom 43xx driver loaded "
 	printk(KERN_INFO "Broadcom 43xx driver loaded "
-	       "[ Features: %s%s%s%s, Firmware-ID: "
+	       "[ Features: %s%s%s%s%s, Firmware-ID: "
 	       B43_SUPPORTED_FIRMWARE_ID " ]\n",
 	       B43_SUPPORTED_FIRMWARE_ID " ]\n",
 	       feat_pci, feat_pcmcia, feat_nphy,
 	       feat_pci, feat_pcmcia, feat_nphy,
-	       feat_leds);
+	       feat_leds, feat_sdio);
 }
 }
 
 
 static int __init b43_init(void)
 static int __init b43_init(void)
@@ -5031,13 +5057,18 @@ static int __init b43_init(void)
 	err = b43_pcmcia_init();
 	err = b43_pcmcia_init();
 	if (err)
 	if (err)
 		goto err_dfs_exit;
 		goto err_dfs_exit;
-	err = ssb_driver_register(&b43_ssb_driver);
+	err = b43_sdio_init();
 	if (err)
 	if (err)
 		goto err_pcmcia_exit;
 		goto err_pcmcia_exit;
+	err = ssb_driver_register(&b43_ssb_driver);
+	if (err)
+		goto err_sdio_exit;
 	b43_print_driverinfo();
 	b43_print_driverinfo();
 
 
 	return err;
 	return err;
 
 
+err_sdio_exit:
+	b43_sdio_exit();
 err_pcmcia_exit:
 err_pcmcia_exit:
 	b43_pcmcia_exit();
 	b43_pcmcia_exit();
 err_dfs_exit:
 err_dfs_exit:
@@ -5048,6 +5079,7 @@ err_dfs_exit:
 static void __exit b43_exit(void)
 static void __exit b43_exit(void)
 {
 {
 	ssb_driver_unregister(&b43_ssb_driver);
 	ssb_driver_unregister(&b43_ssb_driver);
+	b43_sdio_exit();
 	b43_pcmcia_exit();
 	b43_pcmcia_exit();
 	b43_debugfs_exit();
 	b43_debugfs_exit();
 }
 }

+ 11 - 1
drivers/net/wireless/b43/phy_lp.c

@@ -2228,6 +2228,16 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
 	return B43_TXPWR_RES_DONE;
 	return B43_TXPWR_RES_DONE;
 }
 }
 
 
+void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+       if (on) {
+               b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8);
+       } else {
+               b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0x0007);
+               b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x0007);
+       }
+}
+
 const struct b43_phy_operations b43_phyops_lp = {
 const struct b43_phy_operations b43_phyops_lp = {
 	.allocate		= b43_lpphy_op_allocate,
 	.allocate		= b43_lpphy_op_allocate,
 	.free			= b43_lpphy_op_free,
 	.free			= b43_lpphy_op_free,
@@ -2239,7 +2249,7 @@ const struct b43_phy_operations b43_phyops_lp = {
 	.radio_read		= b43_lpphy_op_radio_read,
 	.radio_read		= b43_lpphy_op_radio_read,
 	.radio_write		= b43_lpphy_op_radio_write,
 	.radio_write		= b43_lpphy_op_radio_write,
 	.software_rfkill	= b43_lpphy_op_software_rfkill,
 	.software_rfkill	= b43_lpphy_op_software_rfkill,
-	.switch_analog		= b43_phyop_switch_analog_generic,
+	.switch_analog		= b43_lpphy_op_switch_analog,
 	.switch_channel		= b43_lpphy_op_switch_channel,
 	.switch_channel		= b43_lpphy_op_switch_channel,
 	.get_default_chan	= b43_lpphy_op_get_default_chan,
 	.get_default_chan	= b43_lpphy_op_get_default_chan,
 	.set_rx_antenna		= b43_lpphy_op_set_rx_antenna,
 	.set_rx_antenna		= b43_lpphy_op_set_rx_antenna,

+ 1 - 1
drivers/net/wireless/b43/pio.c

@@ -574,7 +574,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
 	q->buffer_used -= total_len;
 	q->buffer_used -= total_len;
 	q->free_packet_slots += 1;
 	q->free_packet_slots += 1;
 
 
-	ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb);
+	ieee80211_tx_status(dev->wl->hw, pack->skb);
 	pack->skb = NULL;
 	pack->skb = NULL;
 	list_add(&pack->list, &q->packets_list);
 	list_add(&pack->list, &q->packets_list);
 
 

+ 1 - 1
drivers/net/wireless/b43/rfkill.c

@@ -28,7 +28,7 @@
 /* Returns TRUE, if the radio is enabled in hardware. */
 /* Returns TRUE, if the radio is enabled in hardware. */
 bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
 bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
 {
 {
-	if (dev->phy.rev >= 3) {
+	if (dev->phy.rev >= 3 || dev->phy.type == B43_PHYTYPE_LP) {
 		if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
 		if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
 		      & B43_MMIO_RADIO_HWENABLED_HI_MASK))
 		      & B43_MMIO_RADIO_HWENABLED_HI_MASK))
 			return 1;
 			return 1;

+ 202 - 0
drivers/net/wireless/b43/sdio.c

@@ -0,0 +1,202 @@
+/*
+ * Broadcom B43 wireless driver
+ *
+ * SDIO over Sonics Silicon Backplane bus glue for b43.
+ *
+ * Copyright (C) 2009 Albert Herranz
+ * Copyright (C) 2009 Michael Buesch <mb@bu3sch.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/ssb/ssb.h>
+
+#include "sdio.h"
+#include "b43.h"
+
+
+#define HNBU_CHIPID		0x01	/* vendor & device id */
+
+#define B43_SDIO_BLOCK_SIZE	64	/* rx fifo max size in bytes */
+
+
+static const struct b43_sdio_quirk {
+	u16 vendor;
+	u16 device;
+	unsigned int quirks;
+} b43_sdio_quirks[] = {
+	{ 0x14E4, 0x4318, SSB_QUIRK_SDIO_READ_AFTER_WRITE32, },
+	{ },
+};
+
+
+static unsigned int b43_sdio_get_quirks(u16 vendor, u16 device)
+{
+	const struct b43_sdio_quirk *q;
+
+	for (q = b43_sdio_quirks; q->quirks; q++) {
+		if (vendor == q->vendor && device == q->device)
+			return q->quirks;
+	}
+
+	return 0;
+}
+
+static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
+{
+	struct b43_sdio *sdio = sdio_get_drvdata(func);
+	struct b43_wldev *dev = sdio->irq_handler_opaque;
+
+	if (unlikely(b43_status(dev) < B43_STAT_STARTED))
+		return;
+
+	sdio_release_host(func);
+	sdio->irq_handler(dev);
+	sdio_claim_host(func);
+}
+
+int b43_sdio_request_irq(struct b43_wldev *dev,
+			 void (*handler)(struct b43_wldev *dev))
+{
+	struct ssb_bus *bus = dev->dev->bus;
+	struct sdio_func *func = bus->host_sdio;
+	struct b43_sdio *sdio = sdio_get_drvdata(func);
+	int err;
+
+	sdio->irq_handler_opaque = dev;
+	sdio->irq_handler = handler;
+	sdio_claim_host(func);
+	err = sdio_claim_irq(func, b43_sdio_interrupt_dispatcher);
+	sdio_release_host(func);
+
+	return err;
+}
+
+void b43_sdio_free_irq(struct b43_wldev *dev)
+{
+	struct ssb_bus *bus = dev->dev->bus;
+	struct sdio_func *func = bus->host_sdio;
+	struct b43_sdio *sdio = sdio_get_drvdata(func);
+
+	sdio_claim_host(func);
+	sdio_release_irq(func);
+	sdio_release_host(func);
+	sdio->irq_handler_opaque = NULL;
+	sdio->irq_handler = NULL;
+}
+
+static int b43_sdio_probe(struct sdio_func *func,
+			  const struct sdio_device_id *id)
+{
+	struct b43_sdio *sdio;
+	struct sdio_func_tuple *tuple;
+	u16 vendor = 0, device = 0;
+	int error;
+
+	/* Look for the card chip identifier. */
+	tuple = func->tuples;
+	while (tuple) {
+		switch (tuple->code) {
+		case 0x80:
+			switch (tuple->data[0]) {
+			case HNBU_CHIPID:
+				if (tuple->size != 5)
+					break;
+				vendor = tuple->data[1] | (tuple->data[2]<<8);
+				device = tuple->data[3] | (tuple->data[4]<<8);
+				dev_info(&func->dev, "Chip ID %04x:%04x\n",
+					 vendor, device);
+				break;
+			default:
+				break;
+			}
+			break;
+		default:
+			break;
+		}
+		tuple = tuple->next;
+	}
+	if (!vendor || !device) {
+		error = -ENODEV;
+		goto out;
+	}
+
+	sdio_claim_host(func);
+	error = sdio_set_block_size(func, B43_SDIO_BLOCK_SIZE);
+	if (error) {
+		dev_err(&func->dev, "failed to set block size to %u bytes,"
+			" error %d\n", B43_SDIO_BLOCK_SIZE, error);
+		goto err_release_host;
+	}
+	error = sdio_enable_func(func);
+	if (error) {
+		dev_err(&func->dev, "failed to enable func, error %d\n", error);
+		goto err_release_host;
+	}
+	sdio_release_host(func);
+
+	sdio = kzalloc(sizeof(*sdio), GFP_KERNEL);
+	if (!sdio) {
+		error = -ENOMEM;
+		dev_err(&func->dev, "failed to allocate ssb bus\n");
+		goto err_disable_func;
+	}
+	error = ssb_bus_sdiobus_register(&sdio->ssb, func,
+					 b43_sdio_get_quirks(vendor, device));
+	if (error) {
+		dev_err(&func->dev, "failed to register ssb sdio bus,"
+			" error %d\n", error);
+		goto err_free_ssb;
+	}
+	sdio_set_drvdata(func, sdio);
+
+	return 0;
+
+err_free_ssb:
+	kfree(sdio);
+err_disable_func:
+	sdio_disable_func(func);
+err_release_host:
+	sdio_release_host(func);
+out:
+	return error;
+}
+
+static void b43_sdio_remove(struct sdio_func *func)
+{
+	struct b43_sdio *sdio = sdio_get_drvdata(func);
+
+	ssb_bus_unregister(&sdio->ssb);
+	sdio_disable_func(func);
+	kfree(sdio);
+	sdio_set_drvdata(func, NULL);
+}
+
+static const struct sdio_device_id b43_sdio_ids[] = {
+	{ SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */
+	{ },
+};
+
+static struct sdio_driver b43_sdio_driver = {
+	.name		= "b43-sdio",
+	.id_table	= b43_sdio_ids,
+	.probe		= b43_sdio_probe,
+	.remove		= b43_sdio_remove,
+};
+
+int b43_sdio_init(void)
+{
+	return sdio_register_driver(&b43_sdio_driver);
+}
+
+void b43_sdio_exit(void)
+{
+	sdio_unregister_driver(&b43_sdio_driver);
+}

+ 45 - 0
drivers/net/wireless/b43/sdio.h

@@ -0,0 +1,45 @@
+#ifndef B43_SDIO_H_
+#define B43_SDIO_H_
+
+#include <linux/ssb/ssb.h>
+
+struct b43_wldev;
+
+
+#ifdef CONFIG_B43_SDIO
+
+struct b43_sdio {
+	struct ssb_bus ssb;
+	void *irq_handler_opaque;
+	void (*irq_handler)(struct b43_wldev *dev);
+};
+
+int b43_sdio_request_irq(struct b43_wldev *dev,
+			 void (*handler)(struct b43_wldev *dev));
+void b43_sdio_free_irq(struct b43_wldev *dev);
+
+int b43_sdio_init(void);
+void b43_sdio_exit(void);
+
+
+#else /* CONFIG_B43_SDIO */
+
+
+int b43_sdio_request_irq(struct b43_wldev *dev,
+			 void (*handler)(struct b43_wldev *dev))
+{
+	return -ENODEV;
+}
+void b43_sdio_free_irq(struct b43_wldev *dev)
+{
+}
+static inline int b43_sdio_init(void)
+{
+	return 0;
+}
+static inline void b43_sdio_exit(void)
+{
+}
+
+#endif /* CONFIG_B43_SDIO */
+#endif /* B43_SDIO_H_ */

+ 4 - 1
drivers/net/wireless/b43/xmit.c

@@ -690,8 +690,11 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
 	}
 	}
 
 
 	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
 	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
-	ieee80211_rx_irqsafe(dev->wl->hw, skb);
+	ieee80211_rx(dev->wl->hw, skb);
 
 
+#if B43_DEBUG
+	dev->rx_count++;
+#endif
 	return;
 	return;
 drop:
 drop:
 	b43dbg(dev->wl, "RX: Packet dropped\n");
 	b43dbg(dev->wl, "RX: Packet dropped\n");

+ 6 - 0
drivers/net/wireless/iwlwifi/iwl-4965.c

@@ -2021,6 +2021,12 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
 					   agg->frame_count, txq_id, idx);
 					   agg->frame_count, txq_id, idx);
 
 
 			hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
 			hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
+			if (!hdr) {
+				IWL_ERR(priv,
+					"BUG_ON idx doesn't point to valid skb"
+					" idx=%d, txq_id=%d\n", idx, txq_id);
+				return -1;
+			}
 
 
 			sc = le16_to_cpu(hdr->seq_ctrl);
 			sc = le16_to_cpu(hdr->seq_ctrl);
 			if (idx != (SEQ_TO_SN(sc) & 0xff)) {
 			if (idx != (SEQ_TO_SN(sc) & 0xff)) {

+ 6 - 0
drivers/net/wireless/iwlwifi/iwl-5000.c

@@ -1163,6 +1163,12 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
 					   agg->frame_count, txq_id, idx);
 					   agg->frame_count, txq_id, idx);
 
 
 			hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
 			hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
+			if (!hdr) {
+				IWL_ERR(priv,
+					"BUG_ON idx doesn't point to valid skb"
+					" idx=%d, txq_id=%d\n", idx, txq_id);
+				return -1;
+			}
 
 
 			sc = le16_to_cpu(hdr->seq_ctrl);
 			sc = le16_to_cpu(hdr->seq_ctrl);
 			if (idx != (SEQ_TO_SN(sc) & 0xff)) {
 			if (idx != (SEQ_TO_SN(sc) & 0xff)) {

+ 9 - 1
drivers/net/wireless/iwlwifi/iwl-rx.c

@@ -250,12 +250,20 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
 		}
 		}
 		spin_unlock_irqrestore(&rxq->lock, flags);
 		spin_unlock_irqrestore(&rxq->lock, flags);
 
 
+		if (rxq->free_count > RX_LOW_WATERMARK)
+			priority |= __GFP_NOWARN;
 		/* Alloc a new receive buffer */
 		/* Alloc a new receive buffer */
 		skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
 		skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
 						priority);
 						priority);
 
 
 		if (!skb) {
 		if (!skb) {
-			IWL_CRIT(priv, "Can not allocate SKB buffers\n");
+			if (net_ratelimit())
+				IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
+			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+			    net_ratelimit())
+				IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
+					 priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
+					 rxq->free_count);
 			/* We don't reschedule replenish work here -- we will
 			/* We don't reschedule replenish work here -- we will
 			 * call the restock method and if it still needs
 			 * call the restock method and if it still needs
 			 * more buffers it will schedule replenish */
 			 * more buffers it will schedule replenish */

+ 1 - 1
drivers/net/wireless/iwlwifi/iwl-sta.c

@@ -520,7 +520,7 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
 	struct iwl_host_cmd cmd = {
 	struct iwl_host_cmd cmd = {
 		.id = REPLY_WEPKEY,
 		.id = REPLY_WEPKEY,
 		.data = wep_cmd,
 		.data = wep_cmd,
-		.flags = CMD_SYNC,
+		.flags = CMD_ASYNC,
 	};
 	};
 
 
 	memset(wep_cmd, 0, cmd_size +
 	memset(wep_cmd, 0, cmd_size +

+ 8 - 1
drivers/net/wireless/iwlwifi/iwl3945-base.c

@@ -1146,11 +1146,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
 		}
 		}
 		spin_unlock_irqrestore(&rxq->lock, flags);
 		spin_unlock_irqrestore(&rxq->lock, flags);
 
 
+		if (rxq->free_count > RX_LOW_WATERMARK)
+			priority |= __GFP_NOWARN;
 		/* Alloc a new receive buffer */
 		/* Alloc a new receive buffer */
 		skb = alloc_skb(priv->hw_params.rx_buf_size, priority);
 		skb = alloc_skb(priv->hw_params.rx_buf_size, priority);
 		if (!skb) {
 		if (!skb) {
 			if (net_ratelimit())
 			if (net_ratelimit())
-				IWL_CRIT(priv, ": Can not allocate SKB buffers\n");
+				IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
+			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+			    net_ratelimit())
+				IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
+					 priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
+					 rxq->free_count);
 			/* We don't reschedule replenish work here -- we will
 			/* We don't reschedule replenish work here -- we will
 			 * call the restock method and if it still needs
 			 * call the restock method and if it still needs
 			 * more buffers it will schedule replenish */
 			 * more buffers it will schedule replenish */

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00lib.h

@@ -380,7 +380,7 @@ static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb,
 {
 {
 }
 }
 
 
-static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
+static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
 					     unsigned int header_length,
 					     unsigned int header_length,
 					     struct rxdone_entry_desc *rxdesc)
 					     struct rxdone_entry_desc *rxdesc)
 {
 {

+ 1 - 1
drivers/net/wireless/wl12xx/Kconfig

@@ -1,5 +1,5 @@
 menuconfig WL12XX
 menuconfig WL12XX
-	boolean "TI wl12xx driver support"
+	tristate "TI wl12xx driver support"
 	depends on MAC80211 && WLAN_80211 && EXPERIMENTAL
 	depends on MAC80211 && WLAN_80211 && EXPERIMENTAL
 	---help---
 	---help---
 	  This will enable TI wl12xx driver support. The drivers make
 	  This will enable TI wl12xx driver support. The drivers make

+ 1 - 1
drivers/net/wireless/zd1211rw/zd_usb.c

@@ -1070,7 +1070,7 @@ static int eject_installer(struct usb_interface *intf)
 
 
 	/* Find bulk out endpoint */
 	/* Find bulk out endpoint */
 	endpoint = &iface_desc->endpoint[1].desc;
 	endpoint = &iface_desc->endpoint[1].desc;
-	if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT &&
+	if (usb_endpoint_dir_out(endpoint) &&
 	    usb_endpoint_xfer_bulk(endpoint)) {
 	    usb_endpoint_xfer_bulk(endpoint)) {
 		bulk_out_ep = endpoint->bEndpointAddress;
 		bulk_out_ep = endpoint->bEndpointAddress;
 	} else {
 	} else {

+ 2 - 5
drivers/net/xilinx_emaclite.c

@@ -134,18 +134,15 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata)
 	}
 	}
 
 
 	/* Enable the Rx interrupts for the first buffer */
 	/* Enable the Rx interrupts for the first buffer */
-	reg_data = in_be32(drvdata->base_addr + XEL_RSR_OFFSET);
 	out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
 	out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
-		 reg_data | XEL_RSR_RECV_IE_MASK);
+		 XEL_RSR_RECV_IE_MASK);
 
 
 	/* Enable the Rx interrupts for the second Buffer if
 	/* Enable the Rx interrupts for the second Buffer if
 	 * configured in HW */
 	 * configured in HW */
 	if (drvdata->rx_ping_pong != 0) {
 	if (drvdata->rx_ping_pong != 0) {
-		reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
-				   XEL_RSR_OFFSET);
 		out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
 		out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
 			 XEL_RSR_OFFSET,
 			 XEL_RSR_OFFSET,
-			 reg_data | XEL_RSR_RECV_IE_MASK);
+			 XEL_RSR_RECV_IE_MASK);
 	}
 	}
 
 
 	/* Enable the Global Interrupt Enable */
 	/* Enable the Global Interrupt Enable */

+ 0 - 2
drivers/staging/Kconfig

@@ -117,8 +117,6 @@ source "drivers/staging/vt6655/Kconfig"
 
 
 source "drivers/staging/vt6656/Kconfig"
 source "drivers/staging/vt6656/Kconfig"
 
 
-source "drivers/staging/cpc-usb/Kconfig"
-
 source "drivers/staging/udlfb/Kconfig"
 source "drivers/staging/udlfb/Kconfig"
 
 
 source "drivers/staging/hv/Kconfig"
 source "drivers/staging/hv/Kconfig"

+ 0 - 1
drivers/staging/Makefile

@@ -40,7 +40,6 @@ obj-$(CONFIG_USB_SERIAL_QUATECH_USB2)	+= quatech_usb2/
 obj-$(CONFIG_OCTEON_ETHERNET)	+= octeon/
 obj-$(CONFIG_OCTEON_ETHERNET)	+= octeon/
 obj-$(CONFIG_VT6655)		+= vt6655/
 obj-$(CONFIG_VT6655)		+= vt6655/
 obj-$(CONFIG_VT6656)		+= vt6656/
 obj-$(CONFIG_VT6656)		+= vt6656/
-obj-$(CONFIG_USB_CPC)		+= cpc-usb/
 obj-$(CONFIG_FB_UDL)		+= udlfb/
 obj-$(CONFIG_FB_UDL)		+= udlfb/
 obj-$(CONFIG_HYPERV)		+= hv/
 obj-$(CONFIG_HYPERV)		+= hv/
 obj-$(CONFIG_VME_BUS)		+= vme/
 obj-$(CONFIG_VME_BUS)		+= vme/

+ 0 - 4
drivers/staging/cpc-usb/Kconfig

@@ -1,4 +0,0 @@
-config USB_CPC
-	tristate "CPC CAN USB driver"
-	depends on USB && PROC_FS
-	default n

+ 0 - 3
drivers/staging/cpc-usb/Makefile

@@ -1,3 +0,0 @@
-obj-$(CONFIG_USB_CPC)	+= cpc-usb.o
-
-cpc-usb-y := cpc-usb_drv.o sja2m16c_2.o

+ 0 - 10
drivers/staging/cpc-usb/TODO

@@ -1,10 +0,0 @@
-Things to do for this driver to get merged into the main portion of the
-kernel:
-	- checkpatch cleanups
-	- sparse clean
-	- remove proc code
-	- tie into CAN socket interfaces if possible
-	- figure out sane userspace api
-	- use linux's error codes
-
-Send patches to Greg Kroah-Hartman <greg@kroah.com>

+ 0 - 1184
drivers/staging/cpc-usb/cpc-usb_drv.c

@@ -1,1184 +0,0 @@
-/*
- * CPC-USB CAN Interface Kernel Driver
- *
- * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published
- * by the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <asm/uaccess.h>
-#include <linux/usb.h>
-
-
-#include <linux/proc_fs.h>
-
-#include "cpc.h"
-
-#include "cpc_int.h"
-#include "cpcusb.h"
-
-#include "sja2m16c.h"
-
-/* Version Information */
-#define DRIVER_AUTHOR  "Sebastian Haas <haas@ems-wuensche.com>"
-#define DRIVER_DESC    "CPC-USB Driver for Linux Kernel 2.6"
-#define DRIVER_VERSION CPC_DRIVER_VERSION
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL v2");
-
-/* Define these values to match your devices */
-#define USB_CPCUSB_VENDOR_ID	0x12D6
-
-#define USB_CPCUSB_M16C_PRODUCT_ID    0x0888
-#define USB_CPCUSB_LPC2119_PRODUCT_ID 0x0444
-
-#define CPC_USB_PROC_DIR     CPC_PROC_DIR "cpc-usb"
-
-static struct proc_dir_entry *procDir;
-static struct proc_dir_entry *procEntry;
-
-/* Module parameters */
-static int debug;
-module_param(debug, int, S_IRUGO);
-
-/* table of devices that work with this driver */
-static struct usb_device_id cpcusb_table[] = {
-	{USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_M16C_PRODUCT_ID)},
-	{USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_LPC2119_PRODUCT_ID)},
-	{}			/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, cpcusb_table);
-
-/* use to prevent kernel panic if driver is unloaded
- * while a programm has still open the device
- */
-DECLARE_WAIT_QUEUE_HEAD(rmmodWq);
-atomic_t useCount;
-
-static CPC_USB_T *CPCUSB_Table[CPC_USB_CARD_CNT] = { 0 };
-static unsigned int CPCUsbCnt;
-
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX(disconnect_sem);
-
-/* local function prototypes */
-static ssize_t cpcusb_read(struct file *file, char *buffer, size_t count,
-			   loff_t *ppos);
-static ssize_t cpcusb_write(struct file *file, const char *buffer,
-			    size_t count, loff_t *ppos);
-static unsigned int cpcusb_poll(struct file *file, poll_table * wait);
-static int cpcusb_open(struct inode *inode, struct file *file);
-static int cpcusb_release(struct inode *inode, struct file *file);
-
-static int cpcusb_probe(struct usb_interface *interface,
-			const struct usb_device_id *id);
-static void cpcusb_disconnect(struct usb_interface *interface);
-
-static void cpcusb_read_bulk_callback(struct urb *urb);
-static void cpcusb_write_bulk_callback(struct urb *urb);
-static void cpcusb_read_interrupt_callback(struct urb *urb);
-
-static int cpcusb_setup_intrep(CPC_USB_T *card);
-
-static struct file_operations cpcusb_fops = {
-	/*
-	 * The owner field is part of the module-locking
-	 * mechanism. The idea is that the kernel knows
-	 * which module to increment the use-counter of
-	 * BEFORE it calls the device's open() function.
-	 * This also means that the kernel can decrement
-	 * the use-counter again before calling release()
-	 * or should the open() function fail.
-	 */
-	.owner = THIS_MODULE,
-
-	.read = cpcusb_read,
-	.write = cpcusb_write,
-	.poll = cpcusb_poll,
-	.open = cpcusb_open,
-	.release = cpcusb_release,
-};
-
-/*
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
- */
-static struct usb_class_driver cpcusb_class = {
-	.name = "usb/cpc_usb%d",
-	.fops = &cpcusb_fops,
-	.minor_base = CPC_USB_BASE_MNR,
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver cpcusb_driver = {
-	.name = "cpc-usb",
-	.probe = cpcusb_probe,
-	.disconnect = cpcusb_disconnect,
-	.id_table = cpcusb_table,
-};
-
-static int cpcusb_create_info_output(char *buf)
-{
-	int i = 0, j;
-
-	for (j = 0; j < CPC_USB_CARD_CNT; j++) {
-		if (CPCUSB_Table[j]) {
-			CPC_USB_T *card = CPCUSB_Table[j];
-			CPC_CHAN_T *chan = card->chan;
-
-			/* MINOR CHANNELNO BUSNO SLOTNO */
-			i += sprintf(&buf[i], "%d %s\n", chan->minor,
-				     card->serialNumber);
-		}
-	}
-
-	return i;
-}
-
-static int cpcusb_proc_read_info(char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
-{
-	int len = cpcusb_create_info_output(page);
-
-	if (len <= off + count)
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-
-	return len;
-}
-
-/*
- * Remove CPC-USB and cleanup
- */
-static inline void cpcusb_delete(CPC_USB_T *card)
-{
-	if (card) {
-		if (card->chan) {
-			if (card->chan->buf)
-				vfree(card->chan->buf);
-
-			if (card->chan->CPCWait_q)
-				kfree(card->chan->CPCWait_q);
-
-			kfree(card->chan);
-		}
-
-		CPCUSB_Table[card->idx] = NULL;
-		kfree(card);
-	}
-}
-
-/*
- * setup the interrupt IN endpoint of a specific CPC-USB device
- */
-static int cpcusb_setup_intrep(CPC_USB_T *card)
-{
-	int retval = 0;
-	struct usb_endpoint_descriptor *ep;
-
-	ep = &card->interface->altsetting[0].endpoint[card->num_intr_in].desc;
-
-	card->intr_in_buffer[0] = 0;
-	card->free_slots = 15;	/* initial size */
-
-	/* setup the urb */
-	usb_fill_int_urb(card->intr_in_urb, card->udev,
-			 usb_rcvintpipe(card->udev, card->num_intr_in),
-			 card->intr_in_buffer,
-			 sizeof(card->intr_in_buffer),
-			 cpcusb_read_interrupt_callback,
-			 card,
-			 ep->bInterval);
-
-	card->intr_in_urb->status = 0;	/* needed! */
-
-	/* submit the urb */
-	retval = usb_submit_urb(card->intr_in_urb, GFP_KERNEL);
-
-	if (retval)
-		err("%s - failed submitting intr urb, error %d", __func__,
-		    retval);
-
-	return retval;
-}
-
-static int cpcusb_open(struct inode *inode, struct file *file)
-{
-	CPC_USB_T *card = NULL;
-	struct usb_interface *interface;
-	int subminor;
-	int j, retval = 0;
-
-	subminor = iminor(inode);
-
-	/* prevent disconnects */
-	down(&disconnect_sem);
-
-	interface = usb_find_interface(&cpcusb_driver, subminor);
-	if (!interface) {
-		err("%s - error, can't find device for minor %d",
-				__func__, subminor);
-		retval = CPC_ERR_NO_INTERFACE_PRESENT;
-		goto exit_no_device;
-	}
-
-	card = usb_get_intfdata(interface);
-	if (!card) {
-		retval = CPC_ERR_NO_INTERFACE_PRESENT;
-		goto exit_no_device;
-	}
-
-	/* lock this device */
-	down(&card->sem);
-
-	/* increment our usage count for the driver */
-	if (card->open) {
-		dbg("device already opened");
-		retval = CPC_ERR_CHANNEL_ALREADY_OPEN;
-		goto exit_on_error;
-	}
-
-	/* save our object in the file's private structure */
-	file->private_data = card;
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		usb_fill_bulk_urb(card->urbs[j].urb, card->udev,
-				  usb_rcvbulkpipe(card->udev, card->num_bulk_in),
-				  card->urbs[j].buffer, card->urbs[j].size,
-				  cpcusb_read_bulk_callback, card);
-
-		retval = usb_submit_urb(card->urbs[j].urb, GFP_KERNEL);
-
-		if (retval) {
-			err("%s - failed submitting read urb, error %d",
-			    __func__, retval);
-			retval = CPC_ERR_TRANSMISSION_FAILED;
-			goto exit_on_error;
-		}
-	}
-
-	info("%s - %d URB's submitted", __func__, j);
-
-	ResetBuffer(card->chan);
-
-	cpcusb_setup_intrep(card);
-	card->open = 1;
-
-	atomic_inc(&useCount);
-
-exit_on_error:
-	/* unlock this device */
-	up(&card->sem);
-
-exit_no_device:
-	up(&disconnect_sem);
-
-	return retval;
-}
-
-static unsigned int cpcusb_poll(struct file *file, poll_table * wait)
-{
-	CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-	unsigned int retval = 0;
-
-	if (!card) {
-		err("%s - device object lost", __func__);
-		return -EIO;
-	}
-
-	poll_wait(file, card->chan->CPCWait_q, wait);
-
-	if (IsBufferNotEmpty(card->chan) || !(card->present))
-		retval |= (POLLIN | POLLRDNORM);
-
-	if (card->free_slots)
-		retval |= (POLLOUT | POLLWRNORM);
-
-	return retval;
-}
-
-static int cpcusb_release(struct inode *inode, struct file *file)
-{
-	CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-	int j, retval = 0;
-
-	if (card == NULL) {
-		dbg("%s - object is NULL", __func__);
-		return CPC_ERR_NO_INTERFACE_PRESENT;
-	}
-
-	/* lock our device */
-	down(&card->sem);
-
-	if (!card->open) {
-		dbg("%s - device not opened", __func__);
-		retval = CPC_ERR_NO_INTERFACE_PRESENT;
-		goto exit_not_opened;
-	}
-
-	/* if device wasn't unplugged kill all urbs */
-	if (card->present) {
-		/* kill read urbs */
-		for (j = 0; j < CPC_USB_URB_CNT; j++) {
-			usb_kill_urb(card->urbs[j].urb);
-		}
-
-		/* kill irq urb */
-		usb_kill_urb(card->intr_in_urb);
-
-		/* kill write urbs */
-		for (j = 0; j < CPC_USB_URB_CNT; j++) {
-			if (atomic_read(&card->wrUrbs[j].busy)) {
-				usb_kill_urb(card->wrUrbs[j].urb);
-				wait_for_completion(&card->wrUrbs[j].finished);
-			}
-		}
-	}
-
-	atomic_dec(&useCount);
-
-	/* last process detached */
-	if (atomic_read(&useCount) == 0) {
-		wake_up(&rmmodWq);
-	}
-
-	if (!card->present && card->open) {
-		/* the device was unplugged before the file was released */
-		up(&card->sem);
-		cpcusb_delete(card);
-		return 0;
-	}
-
-	card->open = 0;
-
-exit_not_opened:
-	up(&card->sem);
-
-	return 0;
-}
-
-static ssize_t cpcusb_read(struct file *file, char *buffer, size_t count,
-			   loff_t *ppos)
-{
-	CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-	CPC_CHAN_T *chan;
-	int retval = 0;
-
-	if (count < sizeof(CPC_MSG_T))
-		return CPC_ERR_UNKNOWN;
-
-	/* check if can read from the given address */
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return CPC_ERR_UNKNOWN;
-
-	/* lock this object */
-	down(&card->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!card->present) {
-		up(&card->sem);
-		return CPC_ERR_NO_INTERFACE_PRESENT;
-	}
-
-	if (IsBufferEmpty(card->chan)) {
-		retval = 0;
-	} else {
-		chan = card->chan;
-
-#if 0
-		/* convert LPC2119 params back to SJA1000 params */
-		if (card->deviceRevision >= 0x0200
-		    && chan->buf[chan->oidx].type == CPC_MSG_T_CAN_PRMS) {
-			LPC2119_TO_SJA1000_Params(&chan->buf[chan->oidx]);
-		}
-#endif
-
-		if (copy_to_user(buffer, &chan->buf[chan->oidx], count) != 0) {
-			retval = CPC_ERR_IO_TRANSFER;
-		} else {
-			chan->oidx = (chan->oidx + 1) % CPC_MSG_BUF_CNT;
-			chan->WnR = 1;
-			retval = sizeof(CPC_MSG_T);
-		}
-	}
-/*	spin_unlock_irqrestore(&card->slock, flags); */
-
-	/* unlock the device */
-	up(&card->sem);
-
-	return retval;
-}
-
-#define SHIFT  1
-static inline void cpcusb_align_buffer_alignment(unsigned char *buf)
-{
-	/* CPC-USB uploads packed bytes. */
-	CPC_MSG_T *cpc = (CPC_MSG_T *) buf;
-	unsigned int i;
-
-	for (i = 0; i < cpc->length + (2 * sizeof(unsigned long)); i++) {
-		((unsigned char *) &cpc->msgid)[1 + i] =
-		    ((unsigned char *) &cpc->msgid)[1 + SHIFT + i];
-	}
-}
-
-static int cpc_get_buffer_count(CPC_CHAN_T *chan)
-{
-	/* check the buffer parameters */
-	if (chan->iidx == chan->oidx)
-		return !chan->WnR ? CPC_MSG_BUF_CNT : 0;
-	else if (chan->iidx >= chan->oidx)
-		return (chan->iidx - chan->oidx) % CPC_MSG_BUF_CNT;
-
-	return (chan->iidx + CPC_MSG_BUF_CNT - chan->oidx) % CPC_MSG_BUF_CNT;
-}
-
-static ssize_t cpcusb_write(struct file *file, const char *buffer,
-			    size_t count, loff_t *ppos)
-{
-	CPC_USB_T *card = (CPC_USB_T *) file->private_data;
-	CPC_USB_WRITE_URB_T *wrUrb = NULL;
-
-	ssize_t bytes_written = 0;
-	int retval = 0;
-	int j;
-
-	unsigned char *obuf = NULL;
-	unsigned char type = 0;
-	CPC_MSG_T *info = NULL;
-
-	dbg("%s - entered minor %d, count = %zu, present = %d",
-	    __func__, card->minor, count, card->present);
-
-	if (count > sizeof(CPC_MSG_T))
-		return CPC_ERR_UNKNOWN;
-
-	/* check if can read from the given address */
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return CPC_ERR_UNKNOWN;
-
-	/* lock this object */
-	down(&card->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!card->present) {
-		retval = CPC_ERR_NO_INTERFACE_PRESENT;
-		goto exit;
-	}
-
-	/* verify that we actually have some data to write */
-	if (count == 0) {
-		dbg("%s - write request of 0 bytes", __func__);
-		goto exit;
-	}
-
-	if (card->free_slots <= 5) {
-		info = (CPC_MSG_T *) buffer;
-
-		if (info->type != CPC_CMD_T_CLEAR_CMD_QUEUE
-		    || card->free_slots <= 0) {
-			dbg("%s - send buffer full please try again %d",
-			    __func__, card->free_slots);
-			retval = CPC_ERR_CAN_NO_TRANSMIT_BUF;
-			goto exit;
-		}
-	}
-
-	/* Find a free write urb */
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		if (!atomic_read(&card->wrUrbs[j].busy)) {
-			wrUrb = &card->wrUrbs[j];	/* remember found URB */
-			atomic_set(&wrUrb->busy, 1);	/* lock this URB      */
-			init_completion(&wrUrb->finished);	/* init completion    */
-			dbg("WR URB no. %d started", j);
-			break;
-		}
-	}
-
-	/* don't found write urb say error */
-	if (!wrUrb) {
-		dbg("%s - no free send urb available", __func__);
-		retval = CPC_ERR_CAN_NO_TRANSMIT_BUF;
-		goto exit;
-	}
-	dbg("URB write req");
-
-	obuf = (unsigned char *) wrUrb->urb->transfer_buffer;
-
-	/* copy the data from userspace into our transfer buffer;
-	 * this is the only copy required.
-	 */
-	if (copy_from_user(&obuf[4], buffer, count) != 0) {
-		atomic_set(&wrUrb->busy, 0);	/* release urb */
-		retval = CPC_ERR_IO_TRANSFER;
-		goto exit;
-	}
-
-	/* check if it is a DRIVER information message, so we can
-	 * response to that message and not the USB
-	 */
-	info = (CPC_MSG_T *) &obuf[4];
-
-	bytes_written = 11 + info->length;
-	if (bytes_written >= wrUrb->size) {
-		retval = CPC_ERR_IO_TRANSFER;
-		goto exit;
-	}
-
-	switch (info->type) {
-	case CPC_CMD_T_CLEAR_MSG_QUEUE:
-		ResetBuffer(card->chan);
-		break;
-
-	case CPC_CMD_T_INQ_MSG_QUEUE_CNT:
-		retval = cpc_get_buffer_count(card->chan);
-		atomic_set(&wrUrb->busy, 0);
-
-		goto exit;
-
-	case CPC_CMD_T_INQ_INFO:
-		if (info->msg.info.source == CPC_INFOMSG_T_DRIVER) {
-			/* release urb cause we'll use it for driver
-			 * information
-			 */
-			atomic_set(&wrUrb->busy, 0);
-			if (IsBufferFull(card->chan)) {
-				retval = CPC_ERR_IO_TRANSFER;
-				goto exit;
-			}
-
-			/* it is a driver information request message and we have
-			 * free rx slots to store the response
-			 */
-			type = info->msg.info.type;
-			info = &card->chan->buf[card->chan->iidx];
-
-			info->type = CPC_MSG_T_INFO;
-			info->msg.info.source = CPC_INFOMSG_T_DRIVER;
-			info->msg.info.type = type;
-
-			switch (type) {
-			case CPC_INFOMSG_T_VERSION:
-				info->length = strlen(CPC_DRIVER_VERSION) + 2;
-				sprintf(info->msg.info.msg, "%s\n",
-					CPC_DRIVER_VERSION);
-				break;
-
-			case CPC_INFOMSG_T_SERIAL:
-				info->length = strlen(CPC_DRIVER_SERIAL) + 2;
-				sprintf(info->msg.info.msg, "%s\n",
-					CPC_DRIVER_SERIAL);
-				break;
-
-			default:
-				info->length = 2;
-				info->msg.info.type =
-				    CPC_INFOMSG_T_UNKNOWN_TYPE;
-			}
-
-			card->chan->WnR = 0;
-			card->chan->iidx =
-			    (card->chan->iidx + 1) % CPC_MSG_BUF_CNT;
-
-			retval = info->length;
-			goto exit;
-		}
-		break;
-	case CPC_CMD_T_CAN_PRMS:
-		/* Check the controller type. If it's the new CPC-USB, make sure if these are SJA1000 params */
-		if (info->msg.canparams.cc_type != SJA1000
-		    && info->msg.canparams.cc_type != M16C_BASIC
-		    && (card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID
-			&& info->msg.canparams.cc_type != SJA1000)) {
-			/* don't forget to release the urb */
-			atomic_set(&wrUrb->busy, 0);
-			retval = CPC_ERR_WRONG_CONTROLLER_TYPE;
-			goto exit;
-		}
-		break;
-	}
-
-	/* just convert the params if it is an old CPC-USB with M16C controller */
-	if (card->productId == USB_CPCUSB_M16C_PRODUCT_ID) {
-		/* if it is a parameter message convert it from SJA1000 controller
-		 * settings to M16C Basic controller settings
-		 */
-		SJA1000_TO_M16C_BASIC_Params((CPC_MSG_T *) &obuf[4]);
-	}
-
-	/* don't forget the byte alignment */
-	cpcusb_align_buffer_alignment(&obuf[4]);
-
-	/* setup a the 4 byte header */
-	obuf[0] = obuf[1] = obuf[2] = obuf[3] = 0;
-
-	/* this urb was already set up, except for this write size */
-	wrUrb->urb->transfer_buffer_length = bytes_written + 4;
-
-	/* send the data out the bulk port */
-	/* a character device write uses GFP_KERNEL,
-	   unless a spinlock is held */
-	retval = usb_submit_urb(wrUrb->urb, GFP_KERNEL);
-	if (retval) {
-		atomic_set(&wrUrb->busy, 0);	/* release urb */
-		err("%s - failed submitting write urb, error %d",
-		    __func__, retval);
-	} else {
-		retval = bytes_written;
-	}
-
-exit:
-	/* unlock the device */
-	up(&card->sem);
-
-	dbg("%s - leaved", __func__);
-
-	return retval;
-}
-
-/*
- * callback for interrupt IN urb
- */
-static void cpcusb_read_interrupt_callback(struct urb *urb)
-{
-	CPC_USB_T *card = (CPC_USB_T *) urb->context;
-	int retval;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->slock, flags);
-
-	if (!card->present) {
-		spin_unlock_irqrestore(&card->slock, flags);
-		info("%s - no such device", __func__);
-		return;
-	}
-
-	switch (urb->status) {
-	case 0: /* success */
-		card->free_slots = card->intr_in_buffer[1];
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* urb was killed */
-		spin_unlock_irqrestore(&card->slock, flags);
-		dbg("%s - intr urb killed", __func__);
-		return;
-	default:
-		info("%s - nonzero urb status %d", __func__, urb->status);
-		break;
-	}
-
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if (retval) {
-		err("%s - failed resubmitting intr urb, error %d",
-		    __func__, retval);
-	}
-
-	spin_unlock_irqrestore(&card->slock, flags);
-	wake_up_interruptible(card->chan->CPCWait_q);
-
-	return;
-}
-
-#define UN_SHIFT  1
-#define CPCMSG_HEADER_LEN_FIRMWARE   11
-static inline int cpcusb_unalign_and_copy_buffy(unsigned char *out,
-						unsigned char *in)
-{
-	unsigned int i, j;
-
-	for (i = 0; i < 3; i++)
-		out[i] = in[i];
-
-	for (j = 0; j < (in[1] + (CPCMSG_HEADER_LEN_FIRMWARE - 3)); j++)
-		out[j + i + UN_SHIFT] = in[j + i];
-
-	return i + j;
-}
-
-/*
- * callback for bulk IN urb
- */
-static void cpcusb_read_bulk_callback(struct urb *urb)
-{
-	CPC_USB_T *card = (CPC_USB_T *) urb->context;
-	CPC_CHAN_T *chan;
-	unsigned char *ibuf = urb->transfer_buffer;
-	int retval, msgCnt, start, again = 0;
-	unsigned long flags;
-
-	if (!card) {
-		err("%s - device object lost", __func__);
-		return;
-	}
-
-	spin_lock_irqsave(&card->slock, flags);
-
-	if (!card->present) {
-		spin_unlock_irqrestore(&card->slock, flags);
-		info("%s - no such device", __func__);
-		return;
-	}
-
-	switch (urb->status) {
-	case 0:		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* urb was killed */
-		spin_unlock_irqrestore(&card->slock, flags);
-		dbg("%s - read urb killed", __func__);
-		return;
-	default:
-		info("%s - nonzero urb status %d", __func__, urb->status);
-		break;
-	}
-
-	if (urb->actual_length) {
-		msgCnt = ibuf[0] & ~0x80;
-		again = ibuf[0] & 0x80;
-
-		/* we have a 4 byte header */
-		start = 4;
-		chan = card->chan;
-		while (msgCnt) {
-			if (!(IsBufferFull(card->chan))) {
-				start +=
-				    cpcusb_unalign_and_copy_buffy((unsigned char *)
-							  &chan->buf[chan->iidx], &ibuf[start]);
-
-				if (start > urb->transfer_buffer_length) {
-					err("%d > %d", start, urb->transfer_buffer_length);
-					break;
-				}
-
-				chan->WnR = 0;
-				chan->iidx = (chan->iidx + 1) % CPC_MSG_BUF_CNT;
-				msgCnt--;
-			} else {
-				break;
-			}
-		}
-	}
-
-	usb_fill_bulk_urb(urb, card->udev,
-			  usb_rcvbulkpipe(card->udev, card->num_bulk_in),
-			  urb->transfer_buffer,
-			  urb->transfer_buffer_length,
-			  cpcusb_read_bulk_callback, card);
-
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-
-	if (retval) {
-		err("%s - failed resubmitting read urb, error %d", __func__, retval);
-	}
-
-	spin_unlock_irqrestore(&card->slock, flags);
-
-	wake_up_interruptible(card->chan->CPCWait_q);
-}
-
-/*
- * callback for bulk IN urb
- */
-static void cpcusb_write_bulk_callback(struct urb *urb)
-{
-	CPC_USB_T *card = (CPC_USB_T *) urb->context;
-	unsigned long flags;
-	int j;
-
-	spin_lock_irqsave(&card->slock, flags);
-
-	/* find this urb */
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		if (card->wrUrbs[j].urb == urb) {
-			dbg("URB found no. %d", j);
-			/* notify anyone waiting that the write has finished */
-			complete(&card->wrUrbs[j].finished);
-			atomic_set(&card->wrUrbs[j].busy, 0);
-			break;
-		}
-	}
-
-	switch (urb->status) {
-	case 0:		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* urb was killed */
-		spin_unlock_irqrestore(&card->slock, flags);
-		dbg("%s - write urb no. %d killed", __func__, j);
-		return;
-	default:
-		info("%s - nonzero urb status %d", __func__, urb->status);
-		break;
-	}
-
-	spin_unlock_irqrestore(&card->slock, flags);
-
-	wake_up_interruptible(card->chan->CPCWait_q);
-}
-
-static inline int cpcusb_get_free_slot(void)
-{
-	int i;
-
-	for (i = 0; i < CPC_USB_CARD_CNT; i++) {
-		if (!CPCUSB_Table[i])
-			return i;
-	}
-
-	return -1;
-}
-
-/*
- * probe function for new CPC-USB devices
- */
-static int cpcusb_probe(struct usb_interface *interface,
-			const struct usb_device_id *id)
-{
-	CPC_USB_T *card = NULL;
-	CPC_CHAN_T *chan = NULL;
-
-	struct usb_device *udev = interface_to_usbdev(interface);
-	struct usb_host_interface *iface_desc;
-	struct usb_endpoint_descriptor *endpoint;
-
-	int i, j, retval = -ENOMEM, slot;
-
-	slot = cpcusb_get_free_slot();
-	if (slot < 0) {
-		info("No more devices supported");
-		return -ENOMEM;
-	}
-
-	/* allocate memory for our device state and initialize it */
-	card = kzalloc(sizeof(CPC_USB_T), GFP_KERNEL);
-	if (!card) {
-		err("Out of memory");
-		return -ENOMEM;
-	}
-	CPCUSB_Table[slot] = card;
-
-	/* allocate and initialize the channel struct */
-	card->chan = kmalloc(sizeof(CPC_CHAN_T), GFP_KERNEL);
-	if (!card->chan) {
-		kfree(card);
-		err("Out of memory");
-		return -ENOMEM;
-	}
-
-	chan = card->chan;
-	memset(chan, 0, sizeof(CPC_CHAN_T));
-	ResetBuffer(chan);
-
-	init_MUTEX(&card->sem);
-	spin_lock_init(&card->slock);
-
-	card->udev = udev;
-	card->interface = interface;
-	if (udev->descriptor.iSerialNumber) {
-		usb_string(udev, udev->descriptor.iSerialNumber, card->serialNumber,
-				   128);
-		info("Serial %s", card->serialNumber);
-	}
-
-	card->productId = udev->descriptor.idProduct;
-	info("Product %s",
-	     card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID ?
-			 "CPC-USB/ARM7" : "CPC-USB/M16C");
-
-	/* set up the endpoint information */
-	/* check out the endpoints */
-	/* use only the first bulk-in and bulk-out endpoints */
-	iface_desc = &interface->altsetting[0];
-	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-		endpoint = &iface_desc->endpoint[i].desc;
-
-		if (!card->num_intr_in &&
-		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-		     == USB_ENDPOINT_XFER_INT)) {
-			card->intr_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-			card->num_intr_in = 1;
-
-			if (!card->intr_in_urb) {
-				err("No free urbs available");
-				goto error;
-			}
-
-			dbg("intr_in urb %d", card->num_intr_in);
-		}
-
-		if (!card->num_bulk_in &&
-		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-		     == USB_ENDPOINT_XFER_BULK)) {
-			card->num_bulk_in = 2;
-			for (j = 0; j < CPC_USB_URB_CNT; j++) {
-				card->urbs[j].size = endpoint->wMaxPacketSize;
-				card->urbs[j].urb = usb_alloc_urb(0, GFP_KERNEL);
-				if (!card->urbs[j].urb) {
-					err("No free urbs available");
-					goto error;
-				}
-				card->urbs[j].buffer =
-				    usb_buffer_alloc(udev,
-						     card->urbs[j].size,
-						     GFP_KERNEL,
-						     &card->urbs[j].urb->transfer_dma);
-				if (!card->urbs[j].buffer) {
-					err("Couldn't allocate bulk_in_buffer");
-					goto error;
-				}
-			}
-			info("%s - %d reading URB's allocated",
-			     __func__, CPC_USB_URB_CNT);
-		}
-
-		if (!card->num_bulk_out &&
-		    !(endpoint->bEndpointAddress & USB_DIR_IN) &&
-		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-		     == USB_ENDPOINT_XFER_BULK)) {
-
-			card->num_bulk_out = 2;
-
-			for (j = 0; j < CPC_USB_URB_CNT; j++) {
-				card->wrUrbs[j].size =
-				    endpoint->wMaxPacketSize;
-				card->wrUrbs[j].urb =
-				    usb_alloc_urb(0, GFP_KERNEL);
-				if (!card->wrUrbs[j].urb) {
-					err("No free urbs available");
-					goto error;
-				}
-				card->wrUrbs[j].buffer = usb_buffer_alloc(udev,
-							       card->wrUrbs[j].size, GFP_KERNEL,
-							       &card->wrUrbs[j].urb->transfer_dma);
-
-				if (!card->wrUrbs[j].buffer) {
-					err("Couldn't allocate bulk_out_buffer");
-					goto error;
-				}
-
-				usb_fill_bulk_urb(card->wrUrbs[j].urb, udev,
-						usb_sndbulkpipe(udev, endpoint->bEndpointAddress),
-						card->wrUrbs[j].buffer,
-						card->wrUrbs[j].size,
-						cpcusb_write_bulk_callback,
-						card);
-			}
-
-			info("%s - %d writing URB's allocated", __func__, CPC_USB_URB_CNT);
-		}
-	}
-
-	if (!(card->num_bulk_in && card->num_bulk_out)) {
-		err("Couldn't find both bulk-in and bulk-out endpoints");
-		goto error;
-	}
-
-	/* allow device read, write and ioctl */
-	card->present = 1;
-
-	/* we can register the device now, as it is ready */
-	usb_set_intfdata(interface, card);
-	retval = usb_register_dev(interface, &cpcusb_class);
-
-	if (retval) {
-		/* something prevented us from registering this driver */
-		err("Not able to get a minor for this device.");
-		usb_set_intfdata(interface, NULL);
-		goto error;
-	}
-
-	card->chan->minor = card->minor = interface->minor;
-
-	chan->buf = vmalloc(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT);
-	if (chan->buf == NULL) {
-		err("Out of memory");
-		retval = -ENOMEM;
-		goto error;
-	}
-	info("Allocated memory for %d messages (%lu kbytes)",
-	     CPC_MSG_BUF_CNT, (long unsigned int)(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT) / 1000);
-	memset(chan->buf, 0, sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT);
-
-	ResetBuffer(chan);
-
-	card->chan->CPCWait_q = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
-	if (!card->chan->CPCWait_q) {
-		err("Out of memory");
-		retval = -ENOMEM;
-		goto error;
-	}
-	init_waitqueue_head(card->chan->CPCWait_q);
-
-	CPCUSB_Table[slot] = card;
-	card->idx = slot;
-	CPCUsbCnt++;
-
-	/* let the user know what node this device is now attached to */
-	info("Device now attached to USB-%d", card->minor);
-	return 0;
-
-error:
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		if (card->urbs[j].buffer) {
-			usb_buffer_free(card->udev, card->urbs[j].size,
-					card->urbs[j].buffer,
-					card->urbs[j].urb->transfer_dma);
-			card->urbs[j].buffer = NULL;
-		}
-		if (card->urbs[j].urb) {
-			usb_free_urb(card->urbs[j].urb);
-			card->urbs[j].urb = NULL;
-		}
-	}
-
-	cpcusb_delete(card);
-	return retval;
-}
-
-/*
- * called by the usb core when the device is removed from the system
- */
-static void cpcusb_disconnect(struct usb_interface *interface)
-{
-	CPC_USB_T *card = NULL;
-	int minor, j;
-
-	/* prevent races with open() */
-	down(&disconnect_sem);
-
-	card = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
-
-	down(&card->sem);
-
-	/* prevent device read, write and ioctl */
-	card->present = 0;
-
-	minor = card->minor;
-
-	/* free all urbs and their buffers */
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		/* terminate an ongoing write */
-		if (atomic_read(&card->wrUrbs[j].busy)) {
-			usb_kill_urb(card->wrUrbs[j].urb);
-			wait_for_completion(&card->wrUrbs[j].finished);
-		}
-		usb_buffer_free(card->udev, card->wrUrbs[j].size,
-				card->wrUrbs[j].buffer,
-				card->wrUrbs[j].urb->transfer_dma);
-		usb_free_urb(card->wrUrbs[j].urb);
-	}
-	info("%d write URBs freed", CPC_USB_URB_CNT);
-
-	/* free all urbs and their buffers */
-	for (j = 0; j < CPC_USB_URB_CNT; j++) {
-		usb_buffer_free(card->udev, card->urbs[j].size,
-				card->urbs[j].buffer,
-				card->urbs[j].urb->transfer_dma);
-		usb_free_urb(card->urbs[j].urb);
-	}
-	info("%d read URBs freed", CPC_USB_URB_CNT);
-	usb_free_urb(card->intr_in_urb);
-
-	/* give back our minor */
-	usb_deregister_dev(interface, &cpcusb_class);
-
-	up(&card->sem);
-
-	/* if the device is opened, cpcusb_release will clean this up */
-	if (!card->open)
-		cpcusb_delete(card);
-	else
-		wake_up_interruptible(card->chan->CPCWait_q);
-
-	up(&disconnect_sem);
-
-	CPCUsbCnt--;
-	info("USB-%d now disconnected", minor);
-}
-
-static int __init CPCUsb_Init(void)
-{
-	int result, i;
-
-	info(DRIVER_DESC " v" DRIVER_VERSION);
-	info("Build on " __DATE__ " at " __TIME__);
-
-	for (i = 0; i < CPC_USB_CARD_CNT; i++)
-		CPCUSB_Table[i] = 0;
-
-	/* register this driver with the USB subsystem */
-	result = usb_register(&cpcusb_driver);
-	if (result) {
-		err("usb_register failed. Error number %d", result);
-		return result;
-	}
-
-	procDir = proc_mkdir(CPC_USB_PROC_DIR, NULL);
-	if (!procDir) {
-		err("Could not create proc entry");
-	} else {
-		procEntry = create_proc_read_entry("info", 0444, procDir,
-						   cpcusb_proc_read_info,
-						   NULL);
-		if (!procEntry) {
-			err("Could not create proc entry %s", CPC_USB_PROC_DIR "/info");
-			remove_proc_entry(CPC_USB_PROC_DIR, NULL);
-			procDir = NULL;
-		}
-	}
-
-	return 0;
-}
-
-static void __exit CPCUsb_Exit(void)
-{
-	wait_event(rmmodWq, !atomic_read(&useCount));
-
-	/* deregister this driver with the USB subsystem */
-	usb_deregister(&cpcusb_driver);
-
-	if (procDir) {
-		if (procEntry)
-			remove_proc_entry("info", procDir);
-		remove_proc_entry(CPC_USB_PROC_DIR, NULL);
-	}
-}
-
-module_init(CPCUsb_Init);
-module_exit(CPCUsb_Exit);

+ 0 - 417
drivers/staging/cpc-usb/cpc.h

@@ -1,417 +0,0 @@
-/*
- * CPC CAN Interface Definitions
- *
- * Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- */
-#ifndef CPC_HEADER
-#define CPC_HEADER
-
-/*
- * the maximum length of the union members within a CPC_MSG
- * this value can be defined by the customer, but has to be
- * >= 64 bytes
- * however, if not defined before, we set a length of 64 byte
- */
-#if !defined(CPC_MSG_LEN) || (CPC_MSG_LEN < 64)
-#undef CPC_MSG_LEN
-#define CPC_MSG_LEN 64
-#endif
-
-/*
- * Transmission of events from CPC interfaces to PC can be individually
- * controlled per event type. Default state is: don't transmit
- * Control values are constructed by bit-or of Subject and Action
- * and passed to CPC_Control()
- */
-
-/* Control-Values for CPC_Control() Command Subject Selection */
-#define CONTR_CAN_Message 0x04
-#define CONTR_Busload	  0x08
-#define	CONTR_CAN_State	  0x0C
-#define	CONTR_SendAck	  0x10
-#define	CONTR_Filter	  0x14
-#define CONTR_CmdQueue    0x18	/* reserved, do not use */
-#define CONTR_BusError    0x1C
-
-/* Control Command Actions */
-#define CONTR_CONT_OFF    0
-#define CONTR_CONT_ON     1
-#define CONTR_SING_ON     2
-/*
- * CONTR_SING_ON doesn't change CONTR_CONT_ON state, so it should be
- * read as: transmit at least once
- */
-
-/* defines for confirmed request */
-#define DO_NOT_CONFIRM 0
-#define DO_CONFIRM     1
-
-/* event flags */
-#define EVENT_READ 0x01
-#define EVENT_WRITE 0x02
-
-/*
- * Messages from CPC to PC contain a message object type field.
- * The following message types are sent by CPC and can be used in
- * handlers, others should be ignored.
- */
-#define CPC_MSG_T_RESYNC        0 /* Normally to be ignored */
-#define CPC_MSG_T_CAN           1 /* CAN data frame */
-#define CPC_MSG_T_BUSLOAD       2 /* Busload message */
-#define CPC_MSG_T_STRING        3 /* Normally to be ignored */
-#define CPC_MSG_T_CONTI         4 /* Normally to be ignored */
-#define CPC_MSG_T_MEM           7 /* Normally not to be handled */
-#define	CPC_MSG_T_RTR           8 /* CAN remote frame */
-#define CPC_MSG_T_TXACK	        9 /* Send acknowledge */
-#define CPC_MSG_T_POWERUP      10 /* Power-up message */
-#define	CPC_MSG_T_CMD_NO       11 /* Normally to be ignored */
-#define	CPC_MSG_T_CAN_PRMS     12 /* Actual CAN parameters */
-#define	CPC_MSG_T_ABORTED      13 /* Command aborted message */
-#define	CPC_MSG_T_CANSTATE     14 /* CAN state message */
-#define CPC_MSG_T_RESET        15 /* used to reset CAN-Controller */
-#define	CPC_MSG_T_XCAN         16 /* XCAN data frame */
-#define CPC_MSG_T_XRTR         17 /* XCAN remote frame */
-#define CPC_MSG_T_INFO         18 /* information strings */
-#define CPC_MSG_T_CONTROL      19 /* used for control of interface/driver behaviour */
-#define CPC_MSG_T_CONFIRM      20 /* response type for confirmed requests */
-#define CPC_MSG_T_OVERRUN      21 /* response type for overrun conditions */
-#define CPC_MSG_T_KEEPALIVE    22 /* response type for keep alive conditions */
-#define CPC_MSG_T_CANERROR     23 /* response type for bus error conditions */
-#define CPC_MSG_T_DISCONNECTED 24 /* response type for a disconnected interface */
-#define CPC_MSG_T_ERR_COUNTER  25 /* RX/TX error counter of CAN controller */
-
-#define CPC_MSG_T_FIRMWARE    100 /* response type for USB firmware download */
-
-/*
- * Messages from the PC to the CPC interface contain a command field
- * Most of the command types are wrapped by the library functions and have therefore
- * normally not to be used.
- * However, programmers who wish to circumvent the library and talk directly
- * to the drivers (mainly Linux programmers) can use the following
- * command types:
- */
-#define CPC_CMD_T_CAN                 1	/* CAN data frame */
-#define CPC_CMD_T_CONTROL             3	/* used for control of interface/driver behaviour */
-#define	CPC_CMD_T_CAN_PRMS            6	/* set CAN parameters */
-#define	CPC_CMD_T_CLEARBUF            8	/* clears input queue; this is depricated, use CPC_CMD_T_CLEAR_MSG_QUEUE instead */
-#define	CPC_CMD_T_INQ_CAN_PARMS      11	/* inquire actual CAN parameters */
-#define	CPC_CMD_T_FILTER_PRMS        12	/* set filter parameter */
-#define	CPC_CMD_T_RTR                13	/* CAN remote frame */
-#define	CPC_CMD_T_CANSTATE           14	/* CAN state message */
-#define	CPC_CMD_T_XCAN               15	/* XCAN data frame */
-#define CPC_CMD_T_XRTR               16	/* XCAN remote frame */
-#define CPC_CMD_T_RESET              17	/* used to reset CAN-Controller */
-#define CPC_CMD_T_INQ_INFO           18	/* miscellanous information strings */
-#define CPC_CMD_T_OPEN_CHAN          19	/* open a channel */
-#define CPC_CMD_T_CLOSE_CHAN         20	/* close a channel */
-#define CPC_CMD_T_CNTBUF             21	/* this is depricated, use CPC_CMD_T_INQ_MSG_QUEUE_CNT instead */
-#define CPC_CMD_T_CAN_EXIT          200 /* exit the CAN (disable interrupts; reset bootrate; reset output_cntr; mode = 1) */
-
-#define CPC_CMD_T_INQ_MSG_QUEUE_CNT  CPC_CMD_T_CNTBUF   /* inquires the count of elements in the message queue */
-#define CPC_CMD_T_INQ_ERR_COUNTER    25	                /* request the CAN controllers error counter */
-#define	CPC_CMD_T_CLEAR_MSG_QUEUE    CPC_CMD_T_CLEARBUF /* clear CPC_MSG queue */
-#define	CPC_CMD_T_CLEAR_CMD_QUEUE    28	                /* clear CPC_CMD queue */
-#define CPC_CMD_T_FIRMWARE          100                 /* reserved, must not be used */
-#define CPC_CMD_T_USB_RESET         101                 /* reserved, must not be used */
-#define CPC_CMD_T_WAIT_NOTIFY       102                 /* reserved, must not be used */
-#define CPC_CMD_T_WAIT_SETUP        103                 /* reserved, must not be used */
-#define	CPC_CMD_T_ABORT             255                 /* Normally not to be used */
-
-/* definitions for CPC_MSG_T_INFO information sources */
-#define CPC_INFOMSG_T_UNKNOWN_SOURCE 0
-#define CPC_INFOMSG_T_INTERFACE      1
-#define CPC_INFOMSG_T_DRIVER         2
-#define CPC_INFOMSG_T_LIBRARY        3
-
-/* information types */
-#define CPC_INFOMSG_T_UNKNOWN_TYPE   0
-#define CPC_INFOMSG_T_VERSION        1
-#define CPC_INFOMSG_T_SERIAL         2
-
-/* definitions for controller types */
-#define PCA82C200   1 /* Philips basic CAN controller, replaced by SJA1000 */
-#define SJA1000     2 /* Philips basic CAN controller */
-#define AN82527     3 /* Intel full CAN controller */
-#define M16C_BASIC  4 /* M16C controller running in basic CAN (not full CAN) mode */
-
-/* channel open error codes */
-#define CPC_ERR_NO_FREE_CHANNEL            -1	/* no more free space within the channel array */
-#define CPC_ERR_CHANNEL_ALREADY_OPEN       -2	/* the channel is already open */
-#define CPC_ERR_CHANNEL_NOT_ACTIVE         -3	/* access to a channel not active failed */
-#define CPC_ERR_NO_DRIVER_PRESENT          -4	/* no driver at the location searched by the library */
-#define CPC_ERR_NO_INIFILE_PRESENT         -5	/* the library could not find the inifile */
-#define CPC_ERR_WRONG_PARAMETERS           -6	/* wrong parameters in the inifile */
-#define CPC_ERR_NO_INTERFACE_PRESENT       -7	/* 1. The specified interface is not connected */
-						/* 2. The interface (mostly CPC-USB) was disconnected upon operation */
-#define CPC_ERR_NO_MATCHING_CHANNEL        -8	/* the driver couldn't find a matching channel */
-#define CPC_ERR_NO_BUFFER_AVAILABLE        -9	/* the driver couldn't allocate buffer for messages */
-#define CPC_ERR_NO_INTERRUPT               -10	/* the requested interrupt couldn't be claimed */
-#define CPC_ERR_NO_MATCHING_INTERFACE      -11	/* no interface type related to this channel was found */
-#define CPC_ERR_NO_RESOURCES               -12	/* the requested resources could not be claimed */
-#define CPC_ERR_SOCKET                     -13	/* error concerning TCP sockets */
-
-/* init error codes */
-#define CPC_ERR_WRONG_CONTROLLER_TYPE      -14	/* wrong CAN controller type within initialization */
-#define CPC_ERR_NO_RESET_MODE              -15	/* the controller could not be set into reset mode */
-#define CPC_ERR_NO_CAN_ACCESS              -16	/* the CAN controller could not be accessed */
-
-/* transmit error codes */
-#define CPC_ERR_CAN_WRONG_ID               -20	/* the provided CAN id is too big */
-#define CPC_ERR_CAN_WRONG_LENGTH           -21	/* the provided CAN length is too long */
-#define CPC_ERR_CAN_NO_TRANSMIT_BUF        -22	/* the transmit buffer was occupied */
-#define CPC_ERR_CAN_TRANSMIT_TIMEOUT       -23	/* The message could not be sent within a */
-						/* specified time */
-
-/* other error codes */
-#define CPC_ERR_SERVICE_NOT_SUPPORTED      -30	/* the requested service is not supported by the interface */
-#define CPC_ERR_IO_TRANSFER                -31	/* a transmission error down to the driver occurred */
-#define CPC_ERR_TRANSMISSION_FAILED        -32	/* a transmission error down to the interface occurred */
-#define CPC_ERR_TRANSMISSION_TIMEOUT       -33	/* a timeout occurred within transmission to the interface */
-#define CPC_ERR_OP_SYS_NOT_SUPPORTED       -35	/* the operating system is not supported */
-#define CPC_ERR_UNKNOWN                    -40	/* an unknown error ocurred (mostly IOCTL errors) */
-
-#define CPC_ERR_LOADING_DLL                -50	/* the library 'cpcwin.dll' could not be loaded */
-#define CPC_ERR_ASSIGNING_FUNCTION         -51	/* the specified function could not be assigned */
-#define CPC_ERR_DLL_INITIALIZATION         -52	/* the DLL was not initialized correctly */
-#define CPC_ERR_MISSING_LICFILE            -55	/* the file containing the licenses does not exist */
-#define CPC_ERR_MISSING_LICENSE            -56	/* a required license was not found */
-
-/* CAN state bit values. Ignore any bits not listed */
-#define CPC_CAN_STATE_BUSOFF     0x80
-#define CPC_CAN_STATE_ERROR      0x40
-
-/* Mask to help ignore undefined bits */
-#define CPC_CAN_STATE_MASK       0xc0
-
-/*
- * CAN-Message representation in a CPC_MS
- * Message object type is CPC_MSG_T_CAN or CPC_MSG_T_RTR
- * or CPC_MSG_T_XCAN or CPC_MSG_T_XRTR
- */
-typedef struct CPC_CAN_MSG {
-	u32 id;
-	u8 length;
-	u8 msg[8];
-} CPC_CAN_MSG_T;
-
-/* representation of the CAN parameters for the PCA82C200 controller */
-typedef struct CPC_PCA82C200_PARAMS {
-	u8 acc_code;	/* Acceptance-code for receive, Standard: 0 */
-	u8 acc_mask;	/* Acceptance-mask for receive, Standard: 0xff (everything) */
-	u8 btr0;	/* Bus-timing register 0 */
-	u8 btr1;	/* Bus-timing register 1 */
-	u8 outp_contr;	/* Output-control register */
-} CPC_PCA82C200_PARAMS_T;
-
-/* representation of the CAN parameters for the SJA1000 controller */
-typedef struct CPC_SJA1000_PARAMS {
-	u8 mode;	/* enables single or dual acceptance filtering */
-	u8 acc_code0;	/* Acceptance-code for receive, Standard: 0 */
-	u8 acc_code1;
-	u8 acc_code2;
-	u8 acc_code3;
-	u8 acc_mask0;	/* Acceptance-mask for receive, Standard: 0xff (everything) */
-	u8 acc_mask1;
-	u8 acc_mask2;
-	u8 acc_mask3;
-	u8 btr0;	/* Bus-timing register 0 */
-	u8 btr1;	/* Bus-timing register 1 */
-	u8 outp_contr;	/* Output-control register */
-} CPC_SJA1000_PARAMS_T;
-
-/*
- * representation of the CAN parameters for the M16C controller
- * in basic CAN mode (means no full CAN)
- */
-typedef struct CPC_M16C_BASIC_PARAMS {
-	u8 con0;
-	u8 con1;
-	u8 ctlr0;
-	u8 ctlr1;
-	u8 clk;
-	u8 acc_std_code0;
-	u8 acc_std_code1;
-	u8 acc_ext_code0;
-	u8 acc_ext_code1;
-	u8 acc_ext_code2;
-	u8 acc_ext_code3;
-	u8 acc_std_mask0;
-	u8 acc_std_mask1;
-	u8 acc_ext_mask0;
-	u8 acc_ext_mask1;
-	u8 acc_ext_mask2;
-	u8 acc_ext_mask3;
-} CPC_M16C_BASIC_PARAMS_T;
-
-/* CAN params message representation */
-typedef struct CPC_CAN_PARAMS {
-	u8 cc_type;	/* represents the controller type */
-	union {
-		CPC_M16C_BASIC_PARAMS_T m16c_basic;
-		CPC_SJA1000_PARAMS_T sja1000;
-		CPC_PCA82C200_PARAMS_T pca82c200;
-	} cc_params;
-} CPC_CAN_PARAMS_T;
-
-/* CHAN init params representation */
-typedef struct CPC_CHAN_PARAMS {
-	int fd;
-} CPC_CHAN_PARAMS_T;
-
-/* CAN init params message representation */
-typedef struct CPC_INIT_PARAMS {
-	CPC_CHAN_PARAMS_T chanparams;
-	CPC_CAN_PARAMS_T canparams;
-} CPC_INIT_PARAMS_T;
-
-/* structure for confirmed message handling */
-typedef struct CPC_CONFIRM {
-	u8 result; /* error code */
-} CPC_CONFIRM_T;
-
-/* structure for information requests */
-typedef struct CPC_INFO {
-	u8 source;                 /* interface, driver or library */
-	u8 type;                   /* version or serial number */
-	char msg[CPC_MSG_LEN - 2]; /* string holding the requested information */
-} CPC_INFO_T;
-
-/*
- * OVERRUN
- * In general two types of overrun may occur.
- * A hardware overrun, where the CAN controller
- * lost a message, because the interrupt was
- * not handled before the next messgae comes in.
- * Or a software overrun, where i.e. a received
- * message could not be stored in the CPC_MSG
- * buffer.
- */
-
-/* After a software overrun has occurred
- * we wait until we have CPC_OVR_GAP slots
- * free in the CPC_MSG buffer.
- */
-#define CPC_OVR_GAP               10
-
-/*
- * Two types of software overrun may occur.
- * A received CAN message or a CAN state event
- * can cause an overrun.
- * Note: A CPC_CMD which would normally store
- * its result immediately in the CPC_MSG
- * queue may fail, because the message queue is full.
- * This will not generate an overrun message, but
- * will halt command execution, until this command
- * is able to store its message in the message queue.
- */
-#define CPC_OVR_EVENT_CAN       0x01
-#define CPC_OVR_EVENT_CANSTATE  0x02
-#define CPC_OVR_EVENT_BUSERROR  0x04
-
-/*
- * If the CAN controller lost a message
- * we indicate it with the highest bit
- * set in the count field.
- */
-#define CPC_OVR_HW              0x80
-
-/* structure for overrun conditions */
-typedef struct {
-	u8 event;
-	u8 count;
-} CPC_OVERRUN_T;
-
-/*
- * CAN errors
- * Each CAN controller type has different
- * registers to record errors.
- * Therefor a structure containing the specific
- * errors is set up for each controller here
- */
-
-/*
- * SJA1000 error structure
- * see the SJA1000 datasheet for detailed
- * explanation of the registers
- */
-typedef struct CPC_SJA1000_CAN_ERROR {
-	u8 ecc;   /* error capture code register */
-	u8 rxerr; /* RX error counter register */
-	u8 txerr; /* TX error counter register */
-} CPC_SJA1000_CAN_ERROR_T;
-
-/*
- * M16C error structure
- * see the M16C datasheet for detailed
- * explanation of the registers
- */
-typedef struct CPC_M16C_CAN_ERROR {
-	u8 tbd;	/* to be defined */
-} CPC_M16C_CAN_ERROR_T;
-
-/* structure for CAN error conditions */
-#define  CPC_CAN_ECODE_ERRFRAME   0x01
-typedef struct CPC_CAN_ERROR {
-	u8 ecode;
-	struct {
-		u8 cc_type; /* CAN controller type */
-		union {
-			CPC_SJA1000_CAN_ERROR_T sja1000;
-			CPC_M16C_CAN_ERROR_T m16c;
-		} regs;
-	} cc;
-} CPC_CAN_ERROR_T;
-
-/*
- * Structure containing RX/TX error counter.
- * This structure is used to request the
- * values of the CAN controllers TX and RX
- * error counter.
- */
-typedef struct CPC_CAN_ERR_COUNTER {
-	u8 rx;
-	u8 tx;
-} CPC_CAN_ERR_COUNTER_T;
-
-/* If this flag is set, transmissions from PC to CPC are protected against loss */
-#define CPC_SECURE_TO_CPC	0x01
-
-/* If this flag is set, transmissions from CPC to PC are protected against loss */
-#define CPC_SECURE_TO_PC	0x02
-
-/* If this flag is set, the CAN-transmit buffer is checked to be free before sending a message */
-#define CPC_SECURE_SEND		0x04
-
-/*
- * If this flag is set, the transmission complete flag is checked
- * after sending a message
- * THIS IS CURRENTLY ONLY IMPLEMENTED IN THE PASSIVE INTERFACE DRIVERS
- */
-#define CPC_SECURE_TRANSMIT	0x08
-
-/* main message type used between library and application */
-typedef struct CPC_MSG {
-	u8 type;	/* type of message */
-	u8 length;	/* length of data within union 'msg' */
-	u8 msgid;	/* confirmation handle */
-	u32 ts_sec;	/* timestamp in seconds */
-	u32 ts_nsec;	/* timestamp in nano seconds */
-	union {
-		u8 generic[CPC_MSG_LEN];
-		CPC_CAN_MSG_T canmsg;
-		CPC_CAN_PARAMS_T canparams;
-		CPC_CONFIRM_T confirmation;
-		CPC_INFO_T info;
-		CPC_OVERRUN_T overrun;
-		CPC_CAN_ERROR_T error;
-		CPC_CAN_ERR_COUNTER_T err_counter;
-		u8 busload;
-		u8 canstate;
-	} msg;
-} CPC_MSG_T;
-
-#endif /* CPC_HEADER */

+ 0 - 83
drivers/staging/cpc-usb/cpc_int.h

@@ -1,83 +0,0 @@
-/*
- * CPCLIB
- *
- * Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-#ifndef CPC_INT_H
-#define CPC_INT_H
-
-#include <linux/wait.h>
-
-#define CPC_MSG_BUF_CNT	1500
-
-#define CPC_PROC_DIR "driver/"
-
-#undef dbg
-#undef err
-#undef info
-
-/* Use our own dbg macro */
-#define dbg(format, arg...) do { if (debug) printk( KERN_INFO format "\n" , ## arg); } while (0)
-#define err(format, arg...) do { printk( KERN_INFO "ERROR " format "\n" , ## arg); } while (0)
-#define info(format, arg...) do { printk( KERN_INFO format "\n" , ## arg); } while (0)
-
-/* Macros help using of our buffers */
-#define IsBufferFull(x)     (!(x)->WnR) && ((x)->iidx == (x)->oidx)
-#define IsBufferEmpty(x)    ((x)->WnR) && ((x)->iidx == (x)->oidx)
-#define IsBufferNotEmpty(x) (!(x)->WnR) || ((x)->iidx != (x)->oidx)
-#define ResetBuffer(x)      do { (x)->oidx = (x)->iidx=0; (x)->WnR = 1; } while(0);
-
-#define CPC_BufWriteAllowed ((chan->oidx != chan->iidx) || chan->WnR)
-
-typedef void (*chan_write_byte_t) (void *chan, unsigned int reg,
-				   unsigned char val);
-typedef unsigned char (*chan_read_byte_t) (void *chan, unsigned int reg);
-
-typedef struct CPC_CHAN {
-	void __iomem * canBase;	/* base address of SJA1000 */
-	chan_read_byte_t read_byte;	/* CAN controller read access routine */
-	chan_write_byte_t write_byte;	/* CAN controller write access routine */
-	CPC_MSG_T *buf;		/* buffer for CPC msg */
-	unsigned int iidx;
-	unsigned int oidx;
-	unsigned int WnR;
-	unsigned int minor;
-	unsigned int locked;
-	unsigned int irqDisabled;
-
-	unsigned char cpcCtrlCANMessage;
-	unsigned char cpcCtrlCANState;
-	unsigned char cpcCtrlBUSState;
-
-	unsigned char controllerType;
-
-	unsigned long ovrTimeSec;
-	unsigned long ovrTimeNSec;
-	unsigned long ovrLockedBuffer;
-	CPC_OVERRUN_T ovr;
-
-	/* for debugging only */
-	unsigned int handledIrqs;
-	unsigned int lostMessages;
-
-	unsigned int sentStdCan;
-	unsigned int sentExtCan;
-	unsigned int sentStdRtr;
-	unsigned int sentExtRtr;
-
-	unsigned int recvStdCan;
-	unsigned int recvExtCan;
-	unsigned int recvStdRtr;
-	unsigned int recvExtRtr;
-
-	wait_queue_head_t *CPCWait_q;
-
-	void *private;
-} CPC_CHAN_T;
-
-#endif

+ 0 - 86
drivers/staging/cpc-usb/cpcusb.h

@@ -1,86 +0,0 @@
-/* Header for CPC-USB Driver ********************
- * Copyright 1999, 2000, 2001
- *
- * Company:  EMS Dr. Thomas Wuensche
- *           Sonnenhang 3
- *           85304 Ilmmuenster
- *           Phone: +49-8441-490260
- *           Fax:   +49-8441-81860
- *           email: support@ems-wuensche.com
- *           WWW:   www.ems-wuensche.com
- */
-
-#ifndef CPCUSB_H
-#define CPCUSB_H
-
-#undef err
-#undef dbg
-#undef info
-
-/* Use our own dbg macro */
-#define dbg(format, arg...) do { if (debug) printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
-#define info(format, arg...) do { printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0)
-#define err(format, arg...) do { printk(KERN_INFO "CPC-USB(ERROR): " format "\n" , ## arg); } while (0)
-
-#define CPC_USB_CARD_CNT      4
-
-typedef struct CPC_USB_READ_URB {
-	unsigned char *buffer;	/* the buffer to send data */
-	size_t size;		/* the size of the send buffer */
-	struct urb *urb;	/* the urb used to send data */
-} CPC_USB_READ_URB_T;
-
-typedef struct CPC_USB_WRITE_URB {
-	unsigned char *buffer;	/* the buffer to send data */
-	size_t size;		/* the size of the send buffer */
-	struct urb *urb;	/* the urb used to send data */
-	atomic_t busy;		/* true if write urb is busy */
-	struct completion finished;	/* wait for the write to finish */
-} CPC_USB_WRITE_URB_T;
-
-#define CPC_USB_URB_CNT  10
-
-typedef struct CPC_USB {
-	struct usb_device *udev;	/* save off the usb device pointer */
-	struct usb_interface *interface;	/* the interface for this device */
-	unsigned char minor;	/* the starting minor number for this device */
-	unsigned char num_ports;	/* the number of ports this device has */
-	int num_intr_in;	/* number of interrupt in endpoints we have */
-	int num_bulk_in;	/* number of bulk in endpoints we have */
-	int num_bulk_out;	/* number of bulk out endpoints we have */
-
-	CPC_USB_READ_URB_T urbs[CPC_USB_URB_CNT];
-
-	unsigned char intr_in_buffer[4];	/* interrupt transfer buffer */
-	struct urb *intr_in_urb;	/* interrupt transfer urb */
-
-	CPC_USB_WRITE_URB_T wrUrbs[CPC_USB_URB_CNT];
-
-	int open;		/* if the port is open or not */
-	int present;		/* if the device is not disconnected */
-	struct semaphore sem;	/* locks this structure */
-
-	int free_slots;		/* free send slots of CPC-USB */
-	int idx;
-
-	spinlock_t slock;
-
-	char serialNumber[128];	/* serial number */
-	int productId;		/* product id to differ between M16C and LPC2119 */
-	CPC_CHAN_T *chan;
-} CPC_USB_T;
-
-#define CPCTable               CPCUSB_Table
-
-#define CPC_DRIVER_VERSION "0.724"
-#define CPC_DRIVER_SERIAL  "not applicable"
-
-#define OBUF_SIZE 255		/* 4096 */
-
-/* read timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
-#define RD_NAK_TIMEOUT (10*HZ)	/* Default number of X seconds to wait */
-#define RD_EXPIRE 12		/* Number of attempts to wait X seconds */
-
-#define CPC_USB_BASE_MNR 0	/* CPC-USB start at minor 0  */
-
-#endif

+ 0 - 41
drivers/staging/cpc-usb/sja2m16c.h

@@ -1,41 +0,0 @@
-#ifndef _SJA2M16C_H
-#define _SJA2M16C_H
-
-#include "cpc.h"
-
-#define BAUDRATE_TOLERANCE_PERCENT	1
-#define SAMPLEPOINT_TOLERANCE_PERCENT	5
-#define SAMPLEPOINT_UPPER_LIMIT		88
-
-/* M16C parameters */
-struct FIELD_C0CONR {
-	unsigned int brp:4;
-	unsigned int sam:1;
-	unsigned int pr:3;
-	unsigned int dummy:8;
-};
-struct FIELD_C1CONR {
-	unsigned int ph1:3;
-	unsigned int ph2:3;
-	unsigned int sjw:2;
-	unsigned int dummy:8;
-};
-typedef union C0CONR {
-	unsigned char c0con;
-	struct FIELD_C0CONR bc0con;
-} C0CONR_T;
-typedef union C1CONR {
-	unsigned char c1con;
-	struct FIELD_C1CONR bc1con;
-} C1CONR_T;
-
-#define SJA_TSEG1	((pParams->btr1 & 0x0f)+1)
-#define SJA_TSEG2	(((pParams->btr1 & 0x70)>>4)+1)
-#define SJA_BRP		((pParams->btr0 & 0x3f)+1)
-#define SJA_SJW		((pParams->btr0 & 0xc0)>>6)
-#define SJA_SAM		((pParams->btr1 & 0x80)>>7)
-int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2);
-int samplepoint_m16c(int brp, int pr, int ph1, int ph2);
-int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T *pMsg);
-
-#endif

+ 0 - 452
drivers/staging/cpc-usb/sja2m16c_2.c

@@ -1,452 +0,0 @@
-/****************************************************************************
-*
-*      Copyright (c) 2003,2004 by EMS Dr. Thomas Wuensche
-*
-*                  - All rights reserved -
-*
-* This code is provided "as is" without warranty of any kind, either
-* expressed or implied, including but not limited to the liability
-* concerning the freedom from material defects, the fitness for parti-
-* cular purposes or the freedom of proprietary rights of third parties.
-*
-*****************************************************************************
-* Module name.: cpcusb
-*****************************************************************************
-* Include file: cpc.h
-*****************************************************************************
-* Project.....: Windows Driver Development Kit
-* Filename....: sja2m16c.cpp
-* Authors.....: (GU) Gerhard Uttenthaler
-*               (CS) Christian Schoett
-*****************************************************************************
-* Short descr.: converts baudrate between SJA1000 and M16C
-*****************************************************************************
-* Description.: handles the baudrate conversion from SJA1000 parameters to
-*               M16C parameters
-*****************************************************************************
-* Address     : EMS Dr. Thomas Wuensche
-*               Sonnenhang 3
-*               D-85304 Ilmmuenster
-*               Tel. : +49-8441-490260
-*               Fax. : +49-8441-81860
-*               email: support@ems-wuensche.com
-*****************************************************************************
-*                            History
-*****************************************************************************
-* Version  Date        Auth Remark
-*
-* 01.00    ??          GU   - initial release
-* 01.10    ??????????  CS   - adapted to fit into the USB Windows driver
-* 02.00    18.08.2004  GU   - improved the baudrate calculating algorithm
-*                           - implemented acceptance filtering
-* 02.10    10.09.2004  CS   - adapted to fit into the USB Windows driver
-*****************************************************************************
-*                            ToDo's
-*****************************************************************************
-*/
-
-/****************************************************************************/
-/*     I N C L U D E S
-*/
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
-#include <asm/uaccess.h>
-#include <linux/usb.h>
-
-#include "cpc.h"
-#include "cpc_int.h"
-#include "cpcusb.h"
-
-#include "sja2m16c.h"
-
-/*********************************************************************/
-int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2)
-{
-	return (16000000 / (1 << clk)) / 2 / (brp + 1) / (1 + pr + 1 +
-							    ph1 + 1 + ph2 +
-							    1);
-}
-
-
-/*********************************************************************/
-int samplepoint_m16c(int brp, int pr, int ph1, int ph2)
-{
-	return (100 * (1 + pr + 1 + ph1 + 1)) / (1 + pr + 1 + ph1 + 1 +
-						  ph2 + 1);
-}
-
-
-/****************************************************************************
-* Function.....: SJA1000_TO_M16C_BASIC_Params
-*
-* Task.........: This routine converts SJA1000 CAN btr parameters into M16C
-*                parameters based on the sample point and the error. In
-*                addition it converts the acceptance filter parameters to
-*                suit the M16C parameters
-*
-* Parameters...: None
-*
-* Return values: None
-*
-* Comments.....:
-*****************************************************************************
-*                History
-*****************************************************************************
-* 19.01.2005  CS   - modifed the conversion of SJA1000 filter params into
-*                    M16C params. Due to compatibility reasons with the
-*                    older 82C200 CAN controller the SJA1000
-****************************************************************************/
-int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T * in)
-{
-	int sjaBaudrate;
-	int sjaSamplepoint;
-	int *baudrate_error;	// BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
-	int *samplepoint_error;	// BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7]
-	int baudrate_error_merk;
-	int clk, brp, pr, ph1, ph2;
-	int clk_merk, brp_merk, pr_merk, ph1_merk, ph2_merk;
-	int index;
-	unsigned char acc_code0, acc_code1, acc_code2, acc_code3;
-	unsigned char acc_mask0, acc_mask1, acc_mask2, acc_mask3;
-	CPC_MSG_T * out;
-	C0CONR_T c0con;
-	C1CONR_T c1con;
-	int tmpAccCode;
-	int tmpAccMask;
-
-	    // we have to convert the parameters into M16C parameters
-	    CPC_SJA1000_PARAMS_T * pParams;
-
-	    // check if the type is CAN parameters and if we have to convert the given params
-	    if (in->type != CPC_CMD_T_CAN_PRMS
-		|| in->msg.canparams.cc_type != SJA1000)
-		return 0;
-	pParams =
-	    (CPC_SJA1000_PARAMS_T *) & in->msg.canparams.cc_params.sja1000;
-	acc_code0 = pParams->acc_code0;
-	acc_code1 = pParams->acc_code1;
-	acc_code2 = pParams->acc_code2;
-	acc_code3 = pParams->acc_code3;
-	acc_mask0 = pParams->acc_mask0;
-	acc_mask1 = pParams->acc_mask1;
-	acc_mask2 = pParams->acc_mask2;
-	acc_mask3 = pParams->acc_mask3;
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
-	    info("acc_code0: %2.2Xh\n", acc_code0);
-	info("acc_code1: %2.2Xh\n", acc_code1);
-	info("acc_code2: %2.2Xh\n", acc_code2);
-	info("acc_code3: %2.2Xh\n", acc_code3);
-	info("acc_mask0: %2.2Xh\n", acc_mask0);
-	info("acc_mask1: %2.2Xh\n", acc_mask1);
-	info("acc_mask2: %2.2Xh\n", acc_mask2);
-	info("acc_mask3: %2.2Xh\n", acc_mask3);
-
-#endif	/*  */
-	    if (!
-		 (baudrate_error =
-		  (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
-		err("Could not allocate memory\n");
-		return -3;
-	}
-	if (!
-	      (samplepoint_error =
-	       (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) {
-		err("Could not allocate memory\n");
-		vfree(baudrate_error);
-		return -3;
-	}
-	memset(baudrate_error, 0xff, sizeof(baudrate_error));
-	memset(samplepoint_error, 0xff, sizeof(baudrate_error));
-	sjaBaudrate =
-	    16000000 / 2 / SJA_BRP / (1 + SJA_TSEG1 + SJA_TSEG2);
-	sjaSamplepoint =
-	    100 * (1 + SJA_TSEG1) / (1 + SJA_TSEG1 + SJA_TSEG2);
-	if (sjaBaudrate == 0) {
-		vfree(baudrate_error);
-		vfree(samplepoint_error);
-		return -2;
-	}
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
-	    info("\nStarting SJA CAN params\n");
-	info("-------------------------\n");
-	info("TS1     : %2.2Xh TS2 : %2.2Xh\n", SJA_TSEG1, SJA_TSEG2);
-	info("BTR0    : %2.2Xh BTR1: %2.2Xh\n", pParams->btr0,
-	      pParams->btr1);
-	info("Baudrate: %d.%dkBaud\n", sjaBaudrate / 1000,
-	      sjaBaudrate % 1000);
-	info("Sample P: 0.%d\n", sjaSamplepoint);
-	info("\n");
-
-#endif	/*  */
-	    c0con.bc0con.sam = SJA_SAM;
-	c1con.bc1con.sjw = SJA_SJW;
-
-	    // calculate errors for all baudrates
-	    index = 0;
-	for (clk = 0; clk < 5; clk++) {
-		for (brp = 0; brp < 16; brp++) {
-			for (pr = 0; pr < 8; pr++) {
-				for (ph1 = 0; ph1 < 8; ph1++) {
-					for (ph2 = 0; ph2 < 8; ph2++) {
-						baudrate_error[index] =
-						    100 *
-						    abs(baudrate_m16c
-							(clk, brp, pr, ph1,
-							 ph2) -
-							sjaBaudrate) /
-						    sjaBaudrate;
-						samplepoint_error[index] =
-						    abs(samplepoint_m16c
-							(brp, pr, ph1,
-							 ph2) -
-							sjaSamplepoint);
-
-#if 0
-						    info
-						    ("Baudrate      : %d kBaud\n",
-						     baudrate_m16c(clk,
-								   brp, pr,
-								   ph1,
-								   ph2));
-						info
-						    ("Baudrate Error: %d\n",
-						     baudrate_error
-						     [index]);
-						info
-						    ("Sample P Error: %d\n",
-						     samplepoint_error
-						     [index]);
-						info
-						    ("clk           : %d\n",
-						     clk);
-
-#endif	/*  */
-						    index++;
-					}
-				}
-			}
-		}
-	}
-
-	    // mark all baudrate_error entries which are outer limits
-	    index = 0;
-	for (clk = 0; clk < 5; clk++) {
-		for (brp = 0; brp < 16; brp++) {
-			for (pr = 0; pr < 8; pr++) {
-				for (ph1 = 0; ph1 < 8; ph1++) {
-					for (ph2 = 0; ph2 < 8; ph2++) {
-						if ((baudrate_error[index]
-						      >
-						      BAUDRATE_TOLERANCE_PERCENT)
-						     ||
-						     (samplepoint_error
-						       [index] >
-						       SAMPLEPOINT_TOLERANCE_PERCENT)
-						     ||
-						     (samplepoint_m16c
-						       (brp, pr, ph1,
-							ph2) >
-						       SAMPLEPOINT_UPPER_LIMIT))
-						{
-							baudrate_error
-							    [index] = -1;
-						} else
-						    if (((1 + pr + 1 +
-							  ph1 + 1 + ph2 +
-							  1) < 8)
-							||
-							((1 + pr + 1 +
-							  ph1 + 1 + ph2 +
-							  1) > 25)) {
-							baudrate_error
-							    [index] = -1;
-						}
-
-#if 0
-						    else {
-							info
-							    ("Baudrate      : %d kBaud\n",
-							     baudrate_m16c
-							     (clk, brp, pr,
-							      ph1, ph2));
-							info
-							    ("Baudrate Error: %d\n",
-							     baudrate_error
-							     [index]);
-							info
-							    ("Sample P Error: %d\n",
-							     samplepoint_error
-							     [index]);
-						}
-
-#endif	/*  */
-						    index++;
-					}
-				}
-			}
-		}
-	}
-
-	    // find list of minimum of baudrate_error within unmarked entries
-	    clk_merk = brp_merk = pr_merk = ph1_merk = ph2_merk = 0;
-	baudrate_error_merk = 100;
-	index = 0;
-	for (clk = 0; clk < 5; clk++) {
-		for (brp = 0; brp < 16; brp++) {
-			for (pr = 0; pr < 8; pr++) {
-				for (ph1 = 0; ph1 < 8; ph1++) {
-					for (ph2 = 0; ph2 < 8; ph2++) {
-						if (baudrate_error[index]
-						     != -1) {
-							if (baudrate_error
-							     [index] <
-							     baudrate_error_merk)
-							{
-								baudrate_error_merk
-								    =
-								    baudrate_error
-								    [index];
-								brp_merk =
-								    brp;
-								pr_merk =
-								    pr;
-								ph1_merk =
-								    ph1;
-								ph2_merk =
-								    ph2;
-								clk_merk =
-								    clk;
-
-#if 0
-								    info
-								    ("brp: %2.2Xh pr: %2.2Xh ph1: %2.2Xh ph2: %2.2Xh\n",
-								     brp,
-								     pr,
-								     ph1,
-								     ph2);
-								info
-								    ("Baudrate      : %d kBaud\n",
-								     baudrate_m16c
-								     (clk,
-								      brp,
-								      pr,
-								      ph1,
-								      ph2));
-								info
-								    ("Baudrate Error: %d\n",
-								     baudrate_error
-								     [index]);
-								info
-								    ("Sample P Error: %d\n",
-								     samplepoint_error
-								     [index]);
-
-#endif	/*  */
-							}
-						}
-						index++;
-					}
-				}
-			}
-		}
-	}
-	if (baudrate_error_merk == 100) {
-		info("ERROR: Could not convert CAN init parameter\n");
-		vfree(baudrate_error);
-		vfree(samplepoint_error);
-		return -1;
-	}
-
-	    // setting m16c CAN parameter
-	    c0con.bc0con.brp = brp_merk;
-	c0con.bc0con.pr = pr_merk;
-	c1con.bc1con.ph1 = ph1_merk;
-	c1con.bc1con.ph2 = ph2_merk;
-
-#ifdef _DEBUG_OUTPUT_CAN_PARAMS
-	    info("\nResulting M16C CAN params\n");
-	info("-------------------------\n");
-	info("clk     : %2.2Xh\n", clk_merk);
-	info("ph1     : %2.2Xh ph2: %2.2Xh\n", c1con.bc1con.ph1 + 1,
-	      c1con.bc1con.ph2 + 1);
-	info("pr      : %2.2Xh brp: %2.2Xh\n", c0con.bc0con.pr + 1,
-	      c0con.bc0con.brp + 1);
-	info("sjw     : %2.2Xh sam: %2.2Xh\n", c1con.bc1con.sjw,
-	      c0con.bc0con.sam);
-	info("co1     : %2.2Xh co0: %2.2Xh\n", c1con.c1con, c0con.c0con);
-	info("Baudrate: %d.%dBaud\n",
-	       baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
-			     c1con.bc1con.ph1, c1con.bc1con.ph2) / 1000,
-	       baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr,
-			      c1con.bc1con.ph1, c1con.bc1con.ph2) % 1000);
-	info("Sample P: 0.%d\n",
-	      samplepoint_m16c(c0con.bc0con.brp, c0con.bc0con.pr,
-			       c1con.bc1con.ph1, c1con.bc1con.ph2));
-	info("\n");
-
-#endif	/*  */
-	    out = in;
-	out->type = 6;
-	out->length = sizeof(CPC_M16C_BASIC_PARAMS_T) + 1;
-	out->msg.canparams.cc_type = M16C_BASIC;
-	out->msg.canparams.cc_params.m16c_basic.con0 = c0con.c0con;
-	out->msg.canparams.cc_params.m16c_basic.con1 = c1con.c1con;
-	out->msg.canparams.cc_params.m16c_basic.ctlr0 = 0x4C;
-	out->msg.canparams.cc_params.m16c_basic.ctlr1 = 0x00;
-	out->msg.canparams.cc_params.m16c_basic.clk = clk_merk;
-	out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
-	    acc_code0;
-	out->msg.canparams.cc_params.m16c_basic.acc_std_code1 = acc_code1;
-
-//      info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
-	    tmpAccCode = (acc_code1 >> 5) + (acc_code0 << 3);
-	out->msg.canparams.cc_params.m16c_basic.acc_std_code0 =
-	    (unsigned char) tmpAccCode;
-	out->msg.canparams.cc_params.m16c_basic.acc_std_code1 =
-	    (unsigned char) (tmpAccCode >> 8);
-
-//      info("code0: 0x%2.2X, code1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_code0, out->msg.canparams.cc_params.m16c_basic.acc_std_code1);
-	    out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
-	    ~acc_mask0;
-	out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
-	    ~acc_mask1;
-
-//      info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
-	    tmpAccMask = ((acc_mask1) >> 5) + ((acc_mask0) << 3);
-
-//      info("tmpAccMask: 0x%4.4X\n", tmpAccMask);
-	    out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 =
-	    (unsigned char) ~tmpAccMask;
-	out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 =
-	    (unsigned char) ~(tmpAccMask >> 8);
-
-//      info("mask0: 0x%2.2X, mask1: 0x%2.2X\n", out->msg.canparams.cc_params.m16c_basic.acc_std_mask0, out->msg.canparams.cc_params.m16c_basic.acc_std_mask1);
-	    out->msg.canparams.cc_params.m16c_basic.acc_ext_code0 =
-	    (unsigned char) tmpAccCode;
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_code1 =
-	    (unsigned char) (tmpAccCode >> 8);
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_code2 = acc_code2;
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_code3 = acc_code3;
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_mask0 =
-	    (unsigned char) ~tmpAccMask;
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_mask1 =
-	    (unsigned char) ~(tmpAccMask >> 8);
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_mask2 =
-	    ~acc_mask2;
-	out->msg.canparams.cc_params.m16c_basic.acc_ext_mask3 =
-	    ~acc_mask3;
-	vfree(baudrate_error);
-	vfree(samplepoint_error);
-	return 0;
-}
-
-

+ 1 - 0
include/linux/netlink.h

@@ -187,6 +187,7 @@ extern struct sock *netlink_kernel_create(struct net *net,
 extern void netlink_kernel_release(struct sock *sk);
 extern void netlink_kernel_release(struct sock *sk);
 extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
 extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
 extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
 extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
+extern void __netlink_clear_multicast_users(struct sock *sk, unsigned int group);
 extern void netlink_clear_multicast_users(struct sock *sk, unsigned int group);
 extern void netlink_clear_multicast_users(struct sock *sk, unsigned int group);
 extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
 extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
 extern int netlink_has_listeners(struct sock *sk, unsigned int group);
 extern int netlink_has_listeners(struct sock *sk, unsigned int group);

+ 1 - 0
include/linux/phonet.h

@@ -38,6 +38,7 @@
 #define PNPIPE_IFINDEX		2
 #define PNPIPE_IFINDEX		2
 
 
 #define PNADDR_ANY		0
 #define PNADDR_ANY		0
+#define PNADDR_BROADCAST	0xFC
 #define PNPORT_RESOURCE_ROUTING	0
 #define PNPORT_RESOURCE_ROUTING	0
 
 
 /* Values for PNPIPE_ENCAP option */
 /* Values for PNPIPE_ENCAP option */

+ 1 - 0
include/linux/usb/usbnet.h

@@ -89,6 +89,7 @@ struct driver_info {
 #define FLAG_FRAMING_AX 0x0040		/* AX88772/178 packets */
 #define FLAG_FRAMING_AX 0x0040		/* AX88772/178 packets */
 #define FLAG_WLAN	0x0080		/* use "wlan%d" names */
 #define FLAG_WLAN	0x0080		/* use "wlan%d" names */
 #define FLAG_AVOID_UNLINK_URBS 0x0100	/* don't unlink urbs at usbnet_stop() */
 #define FLAG_AVOID_UNLINK_URBS 0x0100	/* don't unlink urbs at usbnet_stop() */
+#define FLAG_SEND_ZLP	0x0200		/* hw requires ZLPs are sent */
 
 
 
 
 	/* init device ... can sleep, or cause probe() failure */
 	/* init device ... can sleep, or cause probe() failure */

+ 0 - 1
include/net/ipip.h

@@ -12,7 +12,6 @@ struct ip_tunnel
 	struct ip_tunnel	*next;
 	struct ip_tunnel	*next;
 	struct net_device	*dev;
 	struct net_device	*dev;
 
 
-	int			recursion;	/* Depth of hard_start_xmit recursion */
 	int			err_count;	/* Number of arrived ICMP errors */
 	int			err_count;	/* Number of arrived ICMP errors */
 	unsigned long		err_time;	/* Time when the last ICMP error arrived */
 	unsigned long		err_time;	/* Time when the last ICMP error arrived */
 
 

+ 1 - 0
kernel/sys_ni.c

@@ -49,6 +49,7 @@ cond_syscall(sys_sendmsg);
 cond_syscall(compat_sys_sendmsg);
 cond_syscall(compat_sys_sendmsg);
 cond_syscall(sys_recvmsg);
 cond_syscall(sys_recvmsg);
 cond_syscall(compat_sys_recvmsg);
 cond_syscall(compat_sys_recvmsg);
+cond_syscall(compat_sys_recvfrom);
 cond_syscall(sys_socketcall);
 cond_syscall(sys_socketcall);
 cond_syscall(sys_futex);
 cond_syscall(sys_futex);
 cond_syscall(compat_sys_futex);
 cond_syscall(compat_sys_futex);

+ 15 - 10
lib/vsprintf.c

@@ -671,7 +671,7 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros)
 	return p;
 	return p;
 }
 }
 
 
-static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
+static char *ip6_compressed_string(char *p, const char *addr)
 {
 {
 	int i;
 	int i;
 	int j;
 	int j;
@@ -683,7 +683,12 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
 	u8 hi;
 	u8 hi;
 	u8 lo;
 	u8 lo;
 	bool needcolon = false;
 	bool needcolon = false;
-	bool useIPv4 = ipv6_addr_v4mapped(addr) || ipv6_addr_is_isatap(addr);
+	bool useIPv4;
+	struct in6_addr in6;
+
+	memcpy(&in6, addr, sizeof(struct in6_addr));
+
+	useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
 
 
 	memset(zerolength, 0, sizeof(zerolength));
 	memset(zerolength, 0, sizeof(zerolength));
 
 
@@ -695,7 +700,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
 	/* find position of longest 0 run */
 	/* find position of longest 0 run */
 	for (i = 0; i < range; i++) {
 	for (i = 0; i < range; i++) {
 		for (j = i; j < range; j++) {
 		for (j = i; j < range; j++) {
-			if (addr->s6_addr16[j] != 0)
+			if (in6.s6_addr16[j] != 0)
 				break;
 				break;
 			zerolength[i]++;
 			zerolength[i]++;
 		}
 		}
@@ -722,7 +727,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
 			needcolon = false;
 			needcolon = false;
 		}
 		}
 		/* hex u16 without leading 0s */
 		/* hex u16 without leading 0s */
-		word = ntohs(addr->s6_addr16[i]);
+		word = ntohs(in6.s6_addr16[i]);
 		hi = word >> 8;
 		hi = word >> 8;
 		lo = word & 0xff;
 		lo = word & 0xff;
 		if (hi) {
 		if (hi) {
@@ -741,19 +746,19 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr)
 	if (useIPv4) {
 	if (useIPv4) {
 		if (needcolon)
 		if (needcolon)
 			*p++ = ':';
 			*p++ = ':';
-		p = ip4_string(p, &addr->s6_addr[12], false);
+		p = ip4_string(p, &in6.s6_addr[12], false);
 	}
 	}
 
 
 	*p = '\0';
 	*p = '\0';
 	return p;
 	return p;
 }
 }
 
 
-static char *ip6_string(char *p, const struct in6_addr *addr, const char *fmt)
+static char *ip6_string(char *p, const char *addr, const char *fmt)
 {
 {
 	int i;
 	int i;
 	for (i = 0; i < 8; i++) {
 	for (i = 0; i < 8; i++) {
-		p = pack_hex_byte(p, addr->s6_addr[2 * i]);
-		p = pack_hex_byte(p, addr->s6_addr[2 * i + 1]);
+		p = pack_hex_byte(p, *addr++);
+		p = pack_hex_byte(p, *addr++);
 		if (fmt[0] == 'I' && i != 7)
 		if (fmt[0] == 'I' && i != 7)
 			*p++ = ':';
 			*p++ = ':';
 	}
 	}
@@ -768,9 +773,9 @@ static char *ip6_addr_string(char *buf, char *end, const u8 *addr,
 	char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
 	char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
 
 
 	if (fmt[0] == 'I' && fmt[2] == 'c')
 	if (fmt[0] == 'I' && fmt[2] == 'c')
-		ip6_compressed_string(ip6_addr, (const struct in6_addr *)addr);
+		ip6_compressed_string(ip6_addr, addr);
 	else
 	else
-		ip6_string(ip6_addr, (const struct in6_addr *)addr, fmt);
+		ip6_string(ip6_addr, addr, fmt);
 
 
 	return string(buf, end, ip6_addr, spec);
 	return string(buf, end, ip6_addr, spec);
 }
 }

+ 2 - 2
net/ax25/af_ax25.c

@@ -1781,8 +1781,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 		ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ);
 		ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ);
 		ax25_info.n2count   = ax25->n2count;
 		ax25_info.n2count   = ax25->n2count;
 		ax25_info.state     = ax25->state;
 		ax25_info.state     = ax25->state;
-		ax25_info.rcv_q     = sk_wmem_alloc_get(sk);
-		ax25_info.snd_q     = sk_rmem_alloc_get(sk);
+		ax25_info.rcv_q     = sk_rmem_alloc_get(sk);
+		ax25_info.snd_q     = sk_wmem_alloc_get(sk);
 		ax25_info.vs        = ax25->vs;
 		ax25_info.vs        = ax25->vs;
 		ax25_info.vr        = ax25->vr;
 		ax25_info.vr        = ax25->vr;
 		ax25_info.va        = ax25->va;
 		ax25_info.va        = ax25->va;

+ 76 - 84
net/core/pktgen.c

@@ -192,11 +192,10 @@
 #define F_QUEUE_MAP_CPU (1<<14)	/* queue map mirrors smp_processor_id() */
 #define F_QUEUE_MAP_CPU (1<<14)	/* queue map mirrors smp_processor_id() */
 
 
 /* Thread control flag bits */
 /* Thread control flag bits */
-#define T_TERMINATE   (1<<0)
-#define T_STOP        (1<<1)	/* Stop run */
-#define T_RUN         (1<<2)	/* Start run */
-#define T_REMDEVALL   (1<<3)	/* Remove all devs */
-#define T_REMDEV      (1<<4)	/* Remove one dev */
+#define T_STOP        (1<<0)	/* Stop run */
+#define T_RUN         (1<<1)	/* Start run */
+#define T_REMDEVALL   (1<<2)	/* Remove all devs */
+#define T_REMDEV      (1<<3)	/* Remove one dev */
 
 
 /* If lock -- can be removed after some work */
 /* If lock -- can be removed after some work */
 #define   if_lock(t)           spin_lock(&(t->if_lock));
 #define   if_lock(t)           spin_lock(&(t->if_lock));
@@ -2105,7 +2104,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
 
 
 static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
 static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
 {
 {
-	ktime_t start;
+	ktime_t start_time, end_time;
 	s32 remaining;
 	s32 remaining;
 	struct hrtimer_sleeper t;
 	struct hrtimer_sleeper t;
 
 
@@ -2116,7 +2115,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
 	if (remaining <= 0)
 	if (remaining <= 0)
 		return;
 		return;
 
 
-	start = ktime_now();
+	start_time = ktime_now();
 	if (remaining < 100)
 	if (remaining < 100)
 		udelay(remaining); 	/* really small just spin */
 		udelay(remaining); 	/* really small just spin */
 	else {
 	else {
@@ -2135,7 +2134,10 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
 		} while (t.task && pkt_dev->running && !signal_pending(current));
 		} while (t.task && pkt_dev->running && !signal_pending(current));
 		__set_current_state(TASK_RUNNING);
 		__set_current_state(TASK_RUNNING);
 	}
 	}
-	pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), start));
+	end_time = ktime_now();
+
+	pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time));
+	pkt_dev->next_tx = ktime_add_ns(end_time, pkt_dev->delay);
 }
 }
 
 
 static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
 static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
@@ -3365,19 +3367,29 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
 	mutex_unlock(&pktgen_thread_lock);
 	mutex_unlock(&pktgen_thread_lock);
 }
 }
 
 
-static void idle(struct pktgen_dev *pkt_dev)
+static void pktgen_resched(struct pktgen_dev *pkt_dev)
 {
 {
 	ktime_t idle_start = ktime_now();
 	ktime_t idle_start = ktime_now();
+	schedule();
+	pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
+}
 
 
-	if (need_resched())
-		schedule();
-	else
-		cpu_relax();
+static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev)
+{
+	ktime_t idle_start = ktime_now();
 
 
+	while (atomic_read(&(pkt_dev->skb->users)) != 1) {
+		if (signal_pending(current))
+			break;
+
+		if (need_resched())
+			pktgen_resched(pkt_dev);
+		else
+			cpu_relax();
+	}
 	pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
 	pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
 }
 }
 
 
-
 static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 {
 {
 	struct net_device *odev = pkt_dev->odev;
 	struct net_device *odev = pkt_dev->odev;
@@ -3387,36 +3399,21 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 	u16 queue_map;
 	u16 queue_map;
 	int ret;
 	int ret;
 
 
-	if (pkt_dev->delay) {
-		spin(pkt_dev, pkt_dev->next_tx);
-
-		/* This is max DELAY, this has special meaning of
-		 * "never transmit"
-		 */
-		if (pkt_dev->delay == ULLONG_MAX) {
-			pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX);
-			return;
-		}
-	}
-
-	if (!pkt_dev->skb) {
-		set_cur_queue_map(pkt_dev);
-		queue_map = pkt_dev->cur_queue_map;
-	} else {
-		queue_map = skb_get_queue_mapping(pkt_dev->skb);
+	/* If device is offline, then don't send */
+	if (unlikely(!netif_running(odev) || !netif_carrier_ok(odev))) {
+		pktgen_stop_device(pkt_dev);
+		return;
 	}
 	}
 
 
-	txq = netdev_get_tx_queue(odev, queue_map);
-	/* Did we saturate the queue already? */
-	if (netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)) {
-		/* If device is down, then all queues are permnantly frozen */
-		if (netif_running(odev))
-			idle(pkt_dev);
-		else
-			pktgen_stop_device(pkt_dev);
+	/* This is max DELAY, this has special meaning of
+	 * "never transmit"
+	 */
+	if (unlikely(pkt_dev->delay == ULLONG_MAX)) {
+		pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX);
 		return;
 		return;
 	}
 	}
 
 
+	/* If no skb or clone count exhausted then get new one */
 	if (!pkt_dev->skb || (pkt_dev->last_ok &&
 	if (!pkt_dev->skb || (pkt_dev->last_ok &&
 			      ++pkt_dev->clone_count >= pkt_dev->clone_skb)) {
 			      ++pkt_dev->clone_count >= pkt_dev->clone_skb)) {
 		/* build a new pkt */
 		/* build a new pkt */
@@ -3435,54 +3432,45 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
 		pkt_dev->clone_count = 0;	/* reset counter */
 		pkt_dev->clone_count = 0;	/* reset counter */
 	}
 	}
 
 
-	/* fill_packet() might have changed the queue */
+	if (pkt_dev->delay && pkt_dev->last_ok)
+		spin(pkt_dev, pkt_dev->next_tx);
+
 	queue_map = skb_get_queue_mapping(pkt_dev->skb);
 	queue_map = skb_get_queue_mapping(pkt_dev->skb);
 	txq = netdev_get_tx_queue(odev, queue_map);
 	txq = netdev_get_tx_queue(odev, queue_map);
 
 
 	__netif_tx_lock_bh(txq);
 	__netif_tx_lock_bh(txq);
-	if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)))
-		pkt_dev->last_ok = 0;
-	else {
-		atomic_inc(&(pkt_dev->skb->users));
+	atomic_inc(&(pkt_dev->skb->users));
 
 
-	retry_now:
+	if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)))
+		ret = NETDEV_TX_BUSY;
+	else
 		ret = (*xmit)(pkt_dev->skb, odev);
 		ret = (*xmit)(pkt_dev->skb, odev);
-		switch (ret) {
-		case NETDEV_TX_OK:
-			txq_trans_update(txq);
-			pkt_dev->last_ok = 1;
-			pkt_dev->sofar++;
-			pkt_dev->seq_num++;
-			pkt_dev->tx_bytes += pkt_dev->cur_pkt_size;
-			break;
-		case NETDEV_TX_LOCKED:
-			cpu_relax();
-			goto retry_now;
-		default: /* Drivers are not supposed to return other values! */
-			if (net_ratelimit())
-				pr_info("pktgen: %s xmit error: %d\n",
-					odev->name, ret);
-			pkt_dev->errors++;
-			/* fallthru */
-		case NETDEV_TX_BUSY:
-			/* Retry it next time */
-			atomic_dec(&(pkt_dev->skb->users));
-			pkt_dev->last_ok = 0;
-		}
-
-		if (pkt_dev->delay)
-			pkt_dev->next_tx = ktime_add_ns(ktime_now(),
-							pkt_dev->delay);
+
+	switch (ret) {
+	case NETDEV_TX_OK:
+		txq_trans_update(txq);
+		pkt_dev->last_ok = 1;
+		pkt_dev->sofar++;
+		pkt_dev->seq_num++;
+		pkt_dev->tx_bytes += pkt_dev->cur_pkt_size;
+		break;
+	default: /* Drivers are not supposed to return other values! */
+		if (net_ratelimit())
+			pr_info("pktgen: %s xmit error: %d\n",
+				odev->name, ret);
+		pkt_dev->errors++;
+		/* fallthru */
+	case NETDEV_TX_LOCKED:
+	case NETDEV_TX_BUSY:
+		/* Retry it next time */
+		atomic_dec(&(pkt_dev->skb->users));
+		pkt_dev->last_ok = 0;
 	}
 	}
 	__netif_tx_unlock_bh(txq);
 	__netif_tx_unlock_bh(txq);
 
 
 	/* If pkt_dev->count is zero, then run forever */
 	/* If pkt_dev->count is zero, then run forever */
 	if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
 	if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
-		while (atomic_read(&(pkt_dev->skb->users)) != 1) {
-			if (signal_pending(current))
-				break;
-			idle(pkt_dev);
-		}
+		pktgen_wait_for_skb(pkt_dev);
 
 
 		/* Done with this */
 		/* Done with this */
 		pktgen_stop_device(pkt_dev);
 		pktgen_stop_device(pkt_dev);
@@ -3515,20 +3503,24 @@ static int pktgen_thread_worker(void *arg)
 	while (!kthread_should_stop()) {
 	while (!kthread_should_stop()) {
 		pkt_dev = next_to_run(t);
 		pkt_dev = next_to_run(t);
 
 
-		if (!pkt_dev &&
-		    (t->control & (T_STOP | T_RUN | T_REMDEVALL | T_REMDEV))
-		    == 0) {
-			prepare_to_wait(&(t->queue), &wait,
-					TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ / 10);
-			finish_wait(&(t->queue), &wait);
+		if (unlikely(!pkt_dev && t->control == 0)) {
+			wait_event_interruptible_timeout(t->queue,
+							 t->control != 0,
+							 HZ/10);
+			continue;
 		}
 		}
 
 
 		__set_current_state(TASK_RUNNING);
 		__set_current_state(TASK_RUNNING);
 
 
-		if (pkt_dev)
+		if (likely(pkt_dev)) {
 			pktgen_xmit(pkt_dev);
 			pktgen_xmit(pkt_dev);
 
 
+			if (need_resched())
+				pktgen_resched(pkt_dev);
+			else
+				cpu_relax();
+		}
+
 		if (t->control & T_STOP) {
 		if (t->control & T_STOP) {
 			pktgen_stop(t);
 			pktgen_stop(t);
 			t->control &= ~(T_STOP);
 			t->control &= ~(T_STOP);

+ 1 - 12
net/ipv4/ip_gre.c

@@ -66,10 +66,7 @@
    solution, but it supposes maintaing new variable in ALL
    solution, but it supposes maintaing new variable in ALL
    skb, even if no tunneling is used.
    skb, even if no tunneling is used.
 
 
-   Current solution: t->recursion lock breaks dead loops. It looks
-   like dev->tbusy flag, but I preferred new variable, because
-   the semantics is different. One day, when hard_start_xmit
-   will be multithreaded we will have to use skb->encapsulation.
+   Current solution: HARD_TX_LOCK lock breaks dead loops.
 
 
 
 
 
 
@@ -678,11 +675,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
 	__be32 dst;
 	__be32 dst;
 	int    mtu;
 	int    mtu;
 
 
-	if (tunnel->recursion++) {
-		stats->collisions++;
-		goto tx_error;
-	}
-
 	if (dev->type == ARPHRD_ETHER)
 	if (dev->type == ARPHRD_ETHER)
 		IPCB(skb)->flags = 0;
 		IPCB(skb)->flags = 0;
 
 
@@ -820,7 +812,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
 			ip_rt_put(rt);
 			ip_rt_put(rt);
 			stats->tx_dropped++;
 			stats->tx_dropped++;
 			dev_kfree_skb(skb);
 			dev_kfree_skb(skb);
-			tunnel->recursion--;
 			return NETDEV_TX_OK;
 			return NETDEV_TX_OK;
 		}
 		}
 		if (skb->sk)
 		if (skb->sk)
@@ -888,7 +879,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
 	nf_reset(skb);
 	nf_reset(skb);
 
 
 	IPTUNNEL_XMIT();
 	IPTUNNEL_XMIT();
-	tunnel->recursion--;
 	return NETDEV_TX_OK;
 	return NETDEV_TX_OK;
 
 
 tx_error_icmp:
 tx_error_icmp:
@@ -897,7 +887,6 @@ tx_error_icmp:
 tx_error:
 tx_error:
 	stats->tx_errors++;
 	stats->tx_errors++;
 	dev_kfree_skb(skb);
 	dev_kfree_skb(skb);
-	tunnel->recursion--;
 	return NETDEV_TX_OK;
 	return NETDEV_TX_OK;
 }
 }
 
 

+ 3 - 0
net/ipv4/ip_sockglue.c

@@ -611,6 +611,9 @@ static int do_ip_setsockopt(struct sock *sk, int level,
 		 *	Check the arguments are allowable
 		 *	Check the arguments are allowable
 		 */
 		 */
 
 
+		if (optlen < sizeof(struct in_addr))
+			goto e_inval;
+
 		err = -EFAULT;
 		err = -EFAULT;
 		if (optlen >= sizeof(struct ip_mreqn)) {
 		if (optlen >= sizeof(struct ip_mreqn)) {
 			if (copy_from_user(&mreq, optval, sizeof(mreq)))
 			if (copy_from_user(&mreq, optval, sizeof(mreq)))

+ 0 - 8
net/ipv4/ipip.c

@@ -402,11 +402,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 	__be32 dst = tiph->daddr;
 	__be32 dst = tiph->daddr;
 	int    mtu;
 	int    mtu;
 
 
-	if (tunnel->recursion++) {
-		stats->collisions++;
-		goto tx_error;
-	}
-
 	if (skb->protocol != htons(ETH_P_IP))
 	if (skb->protocol != htons(ETH_P_IP))
 		goto tx_error;
 		goto tx_error;
 
 
@@ -485,7 +480,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 			ip_rt_put(rt);
 			ip_rt_put(rt);
 			stats->tx_dropped++;
 			stats->tx_dropped++;
 			dev_kfree_skb(skb);
 			dev_kfree_skb(skb);
-			tunnel->recursion--;
 			return NETDEV_TX_OK;
 			return NETDEV_TX_OK;
 		}
 		}
 		if (skb->sk)
 		if (skb->sk)
@@ -523,7 +517,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 	nf_reset(skb);
 	nf_reset(skb);
 
 
 	IPTUNNEL_XMIT();
 	IPTUNNEL_XMIT();
-	tunnel->recursion--;
 	return NETDEV_TX_OK;
 	return NETDEV_TX_OK;
 
 
 tx_error_icmp:
 tx_error_icmp:
@@ -531,7 +524,6 @@ tx_error_icmp:
 tx_error:
 tx_error:
 	stats->tx_errors++;
 	stats->tx_errors++;
 	dev_kfree_skb(skb);
 	dev_kfree_skb(skb);
-	tunnel->recursion--;
 	return NETDEV_TX_OK;
 	return NETDEV_TX_OK;
 }
 }
 
 

+ 0 - 7
net/ipv6/ip6_tunnel.c

@@ -1043,11 +1043,6 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct net_device_stats *stats = &t->dev->stats;
 	struct net_device_stats *stats = &t->dev->stats;
 	int ret;
 	int ret;
 
 
-	if (t->recursion++) {
-		stats->collisions++;
-		goto tx_err;
-	}
-
 	switch (skb->protocol) {
 	switch (skb->protocol) {
 	case htons(ETH_P_IP):
 	case htons(ETH_P_IP):
 		ret = ip4ip6_tnl_xmit(skb, dev);
 		ret = ip4ip6_tnl_xmit(skb, dev);
@@ -1062,14 +1057,12 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (ret < 0)
 	if (ret < 0)
 		goto tx_err;
 		goto tx_err;
 
 
-	t->recursion--;
 	return NETDEV_TX_OK;
 	return NETDEV_TX_OK;
 
 
 tx_err:
 tx_err:
 	stats->tx_errors++;
 	stats->tx_errors++;
 	stats->tx_dropped++;
 	stats->tx_dropped++;
 	kfree_skb(skb);
 	kfree_skb(skb);
-	t->recursion--;
 	return NETDEV_TX_OK;
 	return NETDEV_TX_OK;
 }
 }
 
 

+ 0 - 8
net/ipv6/sit.c

@@ -626,11 +626,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 	struct in6_addr *addr6;
 	struct in6_addr *addr6;
 	int addr_type;
 	int addr_type;
 
 
-	if (tunnel->recursion++) {
-		stats->collisions++;
-		goto tx_error;
-	}
-
 	if (skb->protocol != htons(ETH_P_IPV6))
 	if (skb->protocol != htons(ETH_P_IPV6))
 		goto tx_error;
 		goto tx_error;
 
 
@@ -753,7 +748,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 			ip_rt_put(rt);
 			ip_rt_put(rt);
 			stats->tx_dropped++;
 			stats->tx_dropped++;
 			dev_kfree_skb(skb);
 			dev_kfree_skb(skb);
-			tunnel->recursion--;
 			return NETDEV_TX_OK;
 			return NETDEV_TX_OK;
 		}
 		}
 		if (skb->sk)
 		if (skb->sk)
@@ -794,7 +788,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 	nf_reset(skb);
 	nf_reset(skb);
 
 
 	IPTUNNEL_XMIT();
 	IPTUNNEL_XMIT();
-	tunnel->recursion--;
 	return NETDEV_TX_OK;
 	return NETDEV_TX_OK;
 
 
 tx_error_icmp:
 tx_error_icmp:
@@ -802,7 +795,6 @@ tx_error_icmp:
 tx_error:
 tx_error:
 	stats->tx_errors++;
 	stats->tx_errors++;
 	dev_kfree_skb(skb);
 	dev_kfree_skb(skb);
-	tunnel->recursion--;
 	return NETDEV_TX_OK;
 	return NETDEV_TX_OK;
 }
 }
 
 

+ 2 - 2
net/mac80211/scan.c

@@ -90,8 +90,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
 		bss->dtim_period = tim_ie->dtim_period;
 		bss->dtim_period = tim_ie->dtim_period;
 	}
 	}
 
 
-	/* set default value for buggy APs */
-	if (!elems->tim || bss->dtim_period == 0)
+	/* set default value for buggy AP/no TIM element */
+	if (bss->dtim_period == 0)
 		bss->dtim_period = 1;
 		bss->dtim_period = 1;
 
 
 	bss->supp_rates_len = 0;
 	bss->supp_rates_len = 0;

+ 11 - 8
net/netlink/af_netlink.c

@@ -1609,6 +1609,16 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups)
 	return err;
 	return err;
 }
 }
 
 
+void __netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
+{
+	struct sock *sk;
+	struct hlist_node *node;
+	struct netlink_table *tbl = &nl_table[ksk->sk_protocol];
+
+	sk_for_each_bound(sk, node, &tbl->mc_list)
+		netlink_update_socket_mc(nlk_sk(sk), group, 0);
+}
+
 /**
 /**
  * netlink_clear_multicast_users - kick off multicast listeners
  * netlink_clear_multicast_users - kick off multicast listeners
  *
  *
@@ -1619,15 +1629,8 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups)
  */
  */
 void netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
 void netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
 {
 {
-	struct sock *sk;
-	struct hlist_node *node;
-	struct netlink_table *tbl = &nl_table[ksk->sk_protocol];
-
 	netlink_table_grab();
 	netlink_table_grab();
-
-	sk_for_each_bound(sk, node, &tbl->mc_list)
-		netlink_update_socket_mc(nlk_sk(sk), group, 0);
-
+	__netlink_clear_multicast_users(ksk, group);
 	netlink_table_ungrab();
 	netlink_table_ungrab();
 }
 }
 
 

+ 3 - 1
net/netlink/genetlink.c

@@ -220,10 +220,12 @@ static void __genl_unregister_mc_group(struct genl_family *family,
 	struct net *net;
 	struct net *net;
 	BUG_ON(grp->family != family);
 	BUG_ON(grp->family != family);
 
 
+	netlink_table_grab();
 	rcu_read_lock();
 	rcu_read_lock();
 	for_each_net_rcu(net)
 	for_each_net_rcu(net)
-		netlink_clear_multicast_users(net->genl_sock, grp->id);
+		__netlink_clear_multicast_users(net->genl_sock, grp->id);
 	rcu_read_unlock();
 	rcu_read_unlock();
+	netlink_table_ungrab();
 
 
 	clear_bit(grp->id, mc_groups);
 	clear_bit(grp->id, mc_groups);
 	list_del(&grp->list);
 	list_del(&grp->list);

+ 6 - 0
net/phonet/af_phonet.c

@@ -168,6 +168,12 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev,
 		goto drop;
 		goto drop;
 	}
 	}
 
 
+	/* Broadcast sending is not implemented */
+	if (pn_addr(dst) == PNADDR_BROADCAST) {
+		err = -EOPNOTSUPP;
+		goto drop;
+	}
+
 	skb_reset_transport_header(skb);
 	skb_reset_transport_header(skb);
 	WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */
 	WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */
 	skb_push(skb, sizeof(struct phonethdr));
 	skb_push(skb, sizeof(struct phonethdr));

+ 8 - 8
net/phonet/socket.c

@@ -113,6 +113,8 @@ void pn_sock_unhash(struct sock *sk)
 }
 }
 EXPORT_SYMBOL(pn_sock_unhash);
 EXPORT_SYMBOL(pn_sock_unhash);
 
 
+static DEFINE_MUTEX(port_mutex);
+
 static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
 static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
 {
 {
 	struct sock *sk = sock->sk;
 	struct sock *sk = sock->sk;
@@ -140,9 +142,11 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
 		err = -EINVAL; /* attempt to rebind */
 		err = -EINVAL; /* attempt to rebind */
 		goto out;
 		goto out;
 	}
 	}
+	WARN_ON(sk_hashed(sk));
+	mutex_lock(&port_mutex);
 	err = sk->sk_prot->get_port(sk, pn_port(handle));
 	err = sk->sk_prot->get_port(sk, pn_port(handle));
 	if (err)
 	if (err)
-		goto out;
+		goto out_port;
 
 
 	/* get_port() sets the port, bind() sets the address if applicable */
 	/* get_port() sets the port, bind() sets the address if applicable */
 	pn->sobject = pn_object(saddr, pn_port(pn->sobject));
 	pn->sobject = pn_object(saddr, pn_port(pn->sobject));
@@ -150,6 +154,8 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
 
 
 	/* Enable RX on the socket */
 	/* Enable RX on the socket */
 	sk->sk_prot->hash(sk);
 	sk->sk_prot->hash(sk);
+out_port:
+	mutex_unlock(&port_mutex);
 out:
 out:
 	release_sock(sk);
 	release_sock(sk);
 	return err;
 	return err;
@@ -357,8 +363,6 @@ const struct proto_ops phonet_stream_ops = {
 };
 };
 EXPORT_SYMBOL(phonet_stream_ops);
 EXPORT_SYMBOL(phonet_stream_ops);
 
 
-static DEFINE_MUTEX(port_mutex);
-
 /* allocate port for a socket */
 /* allocate port for a socket */
 int pn_sock_get_port(struct sock *sk, unsigned short sport)
 int pn_sock_get_port(struct sock *sk, unsigned short sport)
 {
 {
@@ -370,9 +374,7 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport)
 
 
 	memset(&try_sa, 0, sizeof(struct sockaddr_pn));
 	memset(&try_sa, 0, sizeof(struct sockaddr_pn));
 	try_sa.spn_family = AF_PHONET;
 	try_sa.spn_family = AF_PHONET;
-
-	mutex_lock(&port_mutex);
-
+	WARN_ON(!mutex_is_locked(&port_mutex));
 	if (!sport) {
 	if (!sport) {
 		/* search free port */
 		/* search free port */
 		int port, pmin, pmax;
 		int port, pmin, pmax;
@@ -401,8 +403,6 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport)
 		else
 		else
 			sock_put(tmpsk);
 			sock_put(tmpsk);
 	}
 	}
-	mutex_unlock(&port_mutex);
-
 	/* the port must be in use already */
 	/* the port must be in use already */
 	return -EADDRINUSE;
 	return -EADDRINUSE;
 
 

+ 1 - 1
net/wireless/wext-sme.c

@@ -26,11 +26,11 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
 
 
 	wdev->wext.connect.ie = wdev->wext.ie;
 	wdev->wext.connect.ie = wdev->wext.ie;
 	wdev->wext.connect.ie_len = wdev->wext.ie_len;
 	wdev->wext.connect.ie_len = wdev->wext.ie_len;
-	wdev->wext.connect.privacy = wdev->wext.default_key != -1;
 
 
 	if (wdev->wext.keys) {
 	if (wdev->wext.keys) {
 		wdev->wext.keys->def = wdev->wext.default_key;
 		wdev->wext.keys->def = wdev->wext.default_key;
 		wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
 		wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
+		wdev->wext.connect.privacy = true;
 	}
 	}
 
 
 	if (!wdev->wext.connect.ssid_len)
 	if (!wdev->wext.connect.ssid_len)