From 94b4bba1105ebe40bbb2ca7998e0dbe0ece718f3 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 23 Sep 2009 13:49:52 +0200 Subject: [PATCH] --- yaml --- r: 166317 b: refs/heads/master c: 38461c5c084ec9119f481f27629d84283733b82a h: refs/heads/master i: 166315: 90b61a477987b00356f98046fcfb75062864cb3d v: v3 --- [refs] | 2 +- .../arch/arm/mach-at91/at91sam9263_devices.c | 36 - trunk/arch/arm/mach-at91/board-sam9263ek.c | 19 - trunk/arch/arm/mach-at91/include/mach/board.h | 6 - trunk/drivers/atm/he.c | 59 +- trunk/drivers/atm/solos-attrlist.c | 11 - trunk/drivers/atm/solos-pci.c | 75 +- trunk/drivers/net/3c59x.c | 12 +- trunk/drivers/net/8139cp.c | 2 +- trunk/drivers/net/Kconfig | 2 +- trunk/drivers/net/atl1c/atl1c_main.c | 2 +- trunk/drivers/net/can/Kconfig | 13 - trunk/drivers/net/can/Makefile | 3 - trunk/drivers/net/can/sja1000/ems_pci.c | 16 +- trunk/drivers/net/can/usb/Makefile | 5 - trunk/drivers/net/can/usb/ems_usb.c | 1155 ---------------- trunk/drivers/net/cnic.c | 4 +- trunk/drivers/net/cpmac.c | 8 +- trunk/drivers/net/ehea/ehea_main.c | 1 + trunk/drivers/net/igb/e1000_mac.c | 72 +- trunk/drivers/net/igb/e1000_mac.h | 1 + trunk/drivers/net/ixgbe/ixgbe.h | 6 +- trunk/drivers/net/ixgbe/ixgbe_ethtool.c | 75 +- trunk/drivers/net/ixgbe/ixgbe_main.c | 111 +- trunk/drivers/net/netxen/netxen_nic_main.c | 8 +- trunk/drivers/net/pcmcia/pcnet_cs.c | 11 +- trunk/drivers/net/sky2.c | 4 +- trunk/drivers/net/sunvnet.c | 1 + trunk/drivers/net/tun.c | 4 +- trunk/drivers/net/usb/kaweth.c | 18 +- trunk/drivers/net/usb/smsc95xx.c | 67 +- trunk/drivers/net/usb/usbnet.c | 2 +- trunk/drivers/net/wireless/ath/ar9170/usb.c | 2 - trunk/drivers/net/wireless/ath/ath9k/calib.c | 23 +- trunk/drivers/net/wireless/ath/ath9k/calib.h | 1 - .../net/wireless/ath/ath9k/eeprom_def.c | 4 +- trunk/drivers/net/wireless/ath/ath9k/hw.c | 202 ++- trunk/drivers/net/wireless/ath/ath9k/hw.h | 4 +- trunk/drivers/net/wireless/ath/ath9k/main.c | 16 +- trunk/drivers/net/wireless/ath/ath9k/reg.h | 3 +- trunk/drivers/net/wireless/b43/Kconfig | 21 +- trunk/drivers/net/wireless/b43/Makefile | 1 - trunk/drivers/net/wireless/b43/b43.h | 23 +- trunk/drivers/net/wireless/b43/debugfs.c | 1 - trunk/drivers/net/wireless/b43/debugfs.h | 1 - trunk/drivers/net/wireless/b43/dma.c | 4 +- trunk/drivers/net/wireless/b43/leds.c | 266 ++-- trunk/drivers/net/wireless/b43/leds.h | 33 +- trunk/drivers/net/wireless/b43/main.c | 224 ++-- trunk/drivers/net/wireless/b43/phy_lp.c | 12 +- trunk/drivers/net/wireless/b43/pio.c | 2 +- trunk/drivers/net/wireless/b43/rfkill.c | 2 +- trunk/drivers/net/wireless/b43/sdio.c | 202 --- trunk/drivers/net/wireless/b43/sdio.h | 45 - trunk/drivers/net/wireless/b43/xmit.c | 5 +- trunk/drivers/net/wireless/iwlwifi/iwl-4965.c | 6 - trunk/drivers/net/wireless/iwlwifi/iwl-5000.c | 6 - trunk/drivers/net/wireless/iwlwifi/iwl-rx.c | 10 +- trunk/drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +- .../net/wireless/iwlwifi/iwl3945-base.c | 9 +- trunk/drivers/net/wireless/rt2x00/rt2x00lib.h | 2 +- trunk/drivers/net/wireless/wl12xx/Kconfig | 2 +- trunk/drivers/net/wireless/zd1211rw/zd_usb.c | 2 +- trunk/drivers/net/xilinx_emaclite.c | 7 +- trunk/drivers/staging/Kconfig | 2 + trunk/drivers/staging/Makefile | 1 + trunk/drivers/staging/cpc-usb/Kconfig | 4 + trunk/drivers/staging/cpc-usb/Makefile | 3 + trunk/drivers/staging/cpc-usb/TODO | 10 + trunk/drivers/staging/cpc-usb/cpc-usb_drv.c | 1184 +++++++++++++++++ trunk/drivers/staging/cpc-usb/cpc.h | 417 ++++++ trunk/drivers/staging/cpc-usb/cpc_int.h | 83 ++ trunk/drivers/staging/cpc-usb/cpcusb.h | 86 ++ trunk/drivers/staging/cpc-usb/sja2m16c.h | 41 + trunk/drivers/staging/cpc-usb/sja2m16c_2.c | 452 +++++++ trunk/drivers/watchdog/Kconfig | 7 + trunk/drivers/watchdog/Makefile | 1 + trunk/drivers/watchdog/adx_wdt.c | 354 +++++ trunk/include/linux/netlink.h | 1 - trunk/include/linux/phonet.h | 1 - trunk/include/linux/usb/usbnet.h | 1 - trunk/include/net/ipip.h | 1 + trunk/kernel/sys_ni.c | 1 - trunk/lib/vsprintf.c | 25 +- trunk/net/ax25/af_ax25.c | 4 +- trunk/net/core/pktgen.c | 160 +-- trunk/net/ipv4/ip_gre.c | 13 +- trunk/net/ipv4/ip_sockglue.c | 3 - trunk/net/ipv4/ipip.c | 8 + trunk/net/ipv6/ip6_tunnel.c | 7 + trunk/net/ipv6/sit.c | 8 + trunk/net/mac80211/scan.c | 4 +- trunk/net/netlink/af_netlink.c | 19 +- trunk/net/netlink/genetlink.c | 4 +- trunk/net/phonet/af_phonet.c | 6 - trunk/net/phonet/socket.c | 16 +- trunk/net/wireless/wext-sme.c | 2 +- 97 files changed, 3272 insertions(+), 2611 deletions(-) delete mode 100644 trunk/drivers/net/can/usb/Makefile delete mode 100644 trunk/drivers/net/can/usb/ems_usb.c delete mode 100644 trunk/drivers/net/wireless/b43/sdio.c delete mode 100644 trunk/drivers/net/wireless/b43/sdio.h create mode 100644 trunk/drivers/staging/cpc-usb/Kconfig create mode 100644 trunk/drivers/staging/cpc-usb/Makefile create mode 100644 trunk/drivers/staging/cpc-usb/TODO create mode 100644 trunk/drivers/staging/cpc-usb/cpc-usb_drv.c create mode 100644 trunk/drivers/staging/cpc-usb/cpc.h create mode 100644 trunk/drivers/staging/cpc-usb/cpc_int.h create mode 100644 trunk/drivers/staging/cpc-usb/cpcusb.h create mode 100644 trunk/drivers/staging/cpc-usb/sja2m16c.h create mode 100644 trunk/drivers/staging/cpc-usb/sja2m16c_2.c create mode 100644 trunk/drivers/watchdog/adx_wdt.c diff --git a/[refs] b/[refs] index dc046819263d..64f22cfdf1fb 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5c3cc2084dd9dc26b258f88abb629550090956e0 +refs/heads/master: 38461c5c084ec9119f481f27629d84283733b82a diff --git a/trunk/arch/arm/mach-at91/at91sam9263_devices.c b/trunk/arch/arm/mach-at91/at91sam9263_devices.c index fb5c23af1017..55719a974276 100644 --- a/trunk/arch/arm/mach-at91/at91sam9263_devices.c +++ b/trunk/arch/arm/mach-at91/at91sam9263_devices.c @@ -757,42 +757,6 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data) void __init at91_add_device_ac97(struct ac97c_platform_data *data) {} #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 diff --git a/trunk/arch/arm/mach-at91/board-sam9263ek.c b/trunk/arch/arm/mach-at91/board-sam9263ek.c index 2d867fb0630f..26f1aa6049af 100644 --- a/trunk/arch/arm/mach-at91/board-sam9263ek.c +++ b/trunk/arch/arm/mach-at91/board-sam9263ek.c @@ -400,23 +400,6 @@ 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) { @@ -448,8 +431,6 @@ static void __init ek_board_init(void) /* LEDs */ at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); 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") diff --git a/trunk/arch/arm/mach-at91/include/mach/board.h b/trunk/arch/arm/mach-at91/include/mach/board.h index 2f4fcedc02ba..583f38a38df7 100644 --- a/trunk/arch/arm/mach-at91/include/mach/board.h +++ b/trunk/arch/arm/mach-at91/include/mach/board.h @@ -188,12 +188,6 @@ extern void __init at91_add_device_isi(void); /* Touchscreen Controller */ 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 */ extern void __init at91_init_leds(u8 cpu_led, u8 timer_led); extern void __init at91_gpio_leds(struct gpio_led *leds, int nr); diff --git a/trunk/drivers/atm/he.c b/trunk/drivers/atm/he.c index 29e66d603d3c..2de64065aa1b 100644 --- a/trunk/drivers/atm/he.c +++ b/trunk/drivers/atm/he.c @@ -790,15 +790,11 @@ he_init_group(struct he_dev *he_dev, int group) he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys); if (he_dev->rbps_base == NULL) { - hprintk("failed to alloc rbps_base\n"); - goto out_destroy_rbps_pool; + hprintk("failed to alloc rbps\n"); + return -ENOMEM; } 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); - 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) { dma_addr_t dma_handle; @@ -806,7 +802,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); if (cpuaddr == NULL) - goto out_free_rbps_virt; + return -ENOMEM; he_dev->rbps_virt[i].virt = cpuaddr; he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF); @@ -831,21 +827,17 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_RBPL_BUFSIZE, 8, 0); if (he_dev->rbpl_pool == NULL) { hprintk("unable to create rbpl pool\n"); - goto out_free_rbps_virt; + return -ENOMEM; } he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys); if (he_dev->rbpl_base == NULL) { - hprintk("failed to alloc rbpl_base\n"); - goto out_destroy_rbpl_pool; + hprintk("failed to alloc rbpl\n"); + return -ENOMEM; } 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); - 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) { dma_addr_t dma_handle; @@ -853,7 +845,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); if (cpuaddr == NULL) - goto out_free_rbpl_virt; + return -ENOMEM; he_dev->rbpl_virt[i].virt = cpuaddr; he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF); @@ -878,7 +870,7 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys); if (he_dev->rbrq_base == NULL) { hprintk("failed to allocate rbrq\n"); - goto out_free_rbpl_virt; + return -ENOMEM; } memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq)); @@ -902,7 +894,7 @@ he_init_group(struct he_dev *he_dev, int group) CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys); if (he_dev->tbrq_base == NULL) { hprintk("failed to allocate tbrq\n"); - goto out_free_rbpq_base; + return -ENOMEM; } memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq)); @@ -914,39 +906,6 @@ he_init_group(struct he_dev *he_dev, int group) he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16)); 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 diff --git a/trunk/drivers/atm/solos-attrlist.c b/trunk/drivers/atm/solos-attrlist.c index 1a9332e4efe0..efa2808dd94d 100644 --- a/trunk/drivers/atm/solos-attrlist.c +++ b/trunk/drivers/atm/solos-attrlist.c @@ -25,10 +25,6 @@ SOLOS_ATTR_RO(RSCorrectedErrorsUp) SOLOS_ATTR_RO(RSUnCorrectedErrorsUp) SOLOS_ATTR_RO(InterleaveRDn) 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(ATURVendor) SOLOS_ATTR_RO(ATUCCountry) @@ -66,13 +62,6 @@ SOLOS_ATTR_RW(Defaults) SOLOS_ATTR_RW(LineMode) SOLOS_ATTR_RW(Profile) 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(Status) SOLOS_ATTR_RO(TotalStart) diff --git a/trunk/drivers/atm/solos-pci.c b/trunk/drivers/atm/solos-pci.c index c5f5186d62a3..307321b32cb3 100644 --- a/trunk/drivers/atm/solos-pci.c +++ b/trunk/drivers/atm/solos-pci.c @@ -59,29 +59,21 @@ #define RX_DMA_ADDR(port) (0x30 + (4 * (port))) #define DATA_RAM_SIZE 32768 -#define BUF_SIZE 2048 -#define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/ +#define BUF_SIZE 4096 #define FPGA_PAGE 528 /* FPGA flash page size*/ #define SOLOS_PAGE 512 /* Solos flash page size*/ #define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/ #define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block 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_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2) +#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE) #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 atmdebug = 0; static int firmware_upgrade = 0; static int fpga_upgrade = 0; -static int db_firmware_upgrade = 0; -static int db_fpga_upgrade = 0; struct pkt_hdr { __le16 size; @@ -124,8 +116,6 @@ struct solos_card { wait_queue_head_t param_wq; wait_queue_head_t fw_wq; int using_dma; - int fpga_version; - int buffer_size; }; @@ -146,14 +136,10 @@ MODULE_PARM_DESC(reset, "Reset Solos chips on startup"); MODULE_PARM_DESC(atmdebug, "Print ATM data"); MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware 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(atmdebug, int, 0644); module_param(firmware_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, struct atm_vcc *vcc); @@ -531,32 +517,10 @@ static int flash_upgrade(struct solos_card *card, int chip) if (chip == 0) { fw_name = "solos-FPGA.bin"; blocksize = FPGA_BLOCK; - } - - if (chip == 1) { + } else { fw_name = "solos-Firmware.bin"; 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)) return -ENOENT; @@ -572,10 +536,8 @@ static int flash_upgrade(struct solos_card *card, int chip) data32 = ioread32(card->config_regs + FPGA_MODE); /* Set mode to Chip Erase */ - 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"); + dev_info(&card->dev->dev, "Set FPGA Flash mode to %s Chip Erase\n", + chip?"Solos":"FPGA"); iowrite32((chip * 2), card->config_regs + FLASH_MODE); @@ -595,10 +557,7 @@ static int flash_upgrade(struct solos_card *card, int chip) /* Copy block to buffer, swapping each 16 bits */ for(i = 0; i < blocksize; i += 4) { uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i)); - if(card->fpga_version > LEGACY_BUFFERS) - iowrite32(word, FLASH_BUF + i); - else - iowrite32(word, RX_BUF(card, 3) + i); + iowrite32(word, RX_BUF(card, 3) + i); } /* Specify block number and then trigger flash write */ @@ -671,10 +630,6 @@ void solos_bh(unsigned long card_arg) memcpy_fromio(header, RX_BUF(card, port), sizeof(*header)); 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); if (!skb) { @@ -1139,18 +1094,12 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) fpga_ver = (data32 & 0x0000FFFF); major_ver = ((data32 & 0xFF000000) >> 24); 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", major_ver, minor_ver, fpga_ver); - if (card->fpga_version >= DMA_SUPPORTED){ + if (0 && fpga_ver > 27) card->using_dma = 1; - } else { - card->using_dma = 0; + else { /* Set RX empty flag for all ports */ iowrite32(0xF0, card->config_regs + FLAGS_ADDR); } @@ -1182,12 +1131,6 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) if (firmware_upgrade) flash_upgrade(card, 1); - if (db_fpga_upgrade) - flash_upgrade(card, 2); - - if (db_firmware_upgrade) - flash_upgrade(card, 3); - err = atm_init(card); if (err) goto out_free_irq; diff --git a/trunk/drivers/net/3c59x.c b/trunk/drivers/net/3c59x.c index b9eeadf01b74..7adff4d0960d 100644 --- a/trunk/drivers/net/3c59x.c +++ b/trunk/drivers/net/3c59x.c @@ -813,10 +813,10 @@ static int vortex_suspend(struct pci_dev *pdev, pm_message_t state) if (netif_running(dev)) { netif_device_detach(dev); vortex_down(dev, 1); - disable_irq(dev->irq); } pci_save_state(pdev); pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); + free_irq(dev->irq, dev); pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); } @@ -839,12 +839,18 @@ static int vortex_resume(struct pci_dev *pdev) return err; } 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)) { err = vortex_up(dev); if (err) return err; - enable_irq(dev->irq); - netif_device_attach(dev); + else + netif_device_attach(dev); } } return 0; diff --git a/trunk/drivers/net/8139cp.c b/trunk/drivers/net/8139cp.c index 83a1922e68e0..462d9f59c53a 100644 --- a/trunk/drivers/net/8139cp.c +++ b/trunk/drivers/net/8139cp.c @@ -87,7 +87,7 @@ /* These identify the driver base version and may not be removed. */ static char version[] = -DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; +KERN_INFO DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; MODULE_AUTHOR("Jeff Garzik "); MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver"); diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 2bea67c134f0..ed5741b2e701 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -1875,7 +1875,7 @@ config 68360_ENET config FEC bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" - depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35 || ARCH_MX25 + depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35 help 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. diff --git a/trunk/drivers/net/atl1c/atl1c_main.c b/trunk/drivers/net/atl1c/atl1c_main.c index 1372e9a99f5b..be2c6cfe6e84 100644 --- a/trunk/drivers/net/atl1c/atl1c_main.c +++ b/trunk/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 mac_ctrl_data; u32 master_ctrl_data; - u32 wol_ctrl_data = 0; + u32 wol_ctrl_data; u16 mii_bmsr_data; u16 save_autoneg_advertised; u16 mii_intr_status_data; diff --git a/trunk/drivers/net/can/Kconfig b/trunk/drivers/net/can/Kconfig index df32c109b7ac..090074372462 100644 --- a/trunk/drivers/net/can/Kconfig +++ b/trunk/drivers/net/can/Kconfig @@ -75,13 +75,6 @@ config CAN_EMS_PCI CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche (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 tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" depends on PCI && CAN_SJA1000 @@ -89,12 +82,6 @@ config CAN_KVASER_PCI This driver is for the the PCIcanx and PCIcan cards (1, 2 or 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 bool "CAN devices debugging messages" depends on CAN diff --git a/trunk/drivers/net/can/Makefile b/trunk/drivers/net/can/Makefile index 0dea62721f2f..523a941b358b 100644 --- a/trunk/drivers/net/can/Makefile +++ b/trunk/drivers/net/can/Makefile @@ -7,9 +7,6 @@ obj-$(CONFIG_CAN_VCAN) += vcan.o obj-$(CONFIG_CAN_DEV) += can-dev.o can-dev-y := dev.o -obj-y += usb/ - obj-$(CONFIG_CAN_SJA1000) += sja1000/ -obj-$(CONFIG_CAN_AT91) += at91_can.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/trunk/drivers/net/can/sja1000/ems_pci.c b/trunk/drivers/net/can/sja1000/ems_pci.c index fd04789d3370..7d84b8ac9c1c 100644 --- a/trunk/drivers/net/can/sja1000/ems_pci.c +++ b/trunk/drivers/net/can/sja1000/ems_pci.c @@ -94,14 +94,12 @@ struct ems_pci_card { #define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) #define EMS_PCI_V1_BASE_BAR 1 -#define EMS_PCI_V1_CONF_SIZE 4096 /* size of PITA control area */ +#define EMS_PCI_V1_MEM_SIZE 4096 #define EMS_PCI_V2_BASE_BAR 2 -#define EMS_PCI_V2_CONF_SIZE 128 /* size of PLX control area */ +#define EMS_PCI_V2_MEM_SIZE 128 #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_BASE_SIZE 4096 /* size of controller area */ - static struct pci_device_id ems_pci_tbl[] = { /* CPC-PCI v1 */ {PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,}, @@ -226,7 +224,7 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev, struct sja1000_priv *priv; struct net_device *dev; struct ems_pci_card *card; - int max_chan, conf_size, base_bar; + int max_chan, mem_size, base_bar; int err, i; /* Enabling PCI device */ @@ -253,22 +251,22 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev, card->version = 2; /* CPC-PCI v2 */ max_chan = EMS_PCI_V2_MAX_CHAN; base_bar = EMS_PCI_V2_BASE_BAR; - conf_size = EMS_PCI_V2_CONF_SIZE; + mem_size = EMS_PCI_V2_MEM_SIZE; } else { card->version = 1; /* CPC-PCI v1 */ max_chan = EMS_PCI_V1_MAX_CHAN; base_bar = EMS_PCI_V1_BASE_BAR; - conf_size = EMS_PCI_V1_CONF_SIZE; + mem_size = EMS_PCI_V1_MEM_SIZE; } /* Remap configuration space and controller memory area */ - card->conf_addr = pci_iomap(pdev, 0, conf_size); + card->conf_addr = pci_iomap(pdev, 0, mem_size); if (card->conf_addr == NULL) { err = -ENOMEM; goto failure_cleanup; } - card->base_addr = pci_iomap(pdev, base_bar, EMS_PCI_BASE_SIZE); + card->base_addr = pci_iomap(pdev, base_bar, mem_size); if (card->base_addr == NULL) { err = -ENOMEM; goto failure_cleanup; diff --git a/trunk/drivers/net/can/usb/Makefile b/trunk/drivers/net/can/usb/Makefile deleted file mode 100644 index c3f75ba701b1..000000000000 --- a/trunk/drivers/net/can/usb/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the Linux Controller Area Network USB drivers. -# - -obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o diff --git a/trunk/drivers/net/can/usb/ems_usb.c b/trunk/drivers/net/can/usb/ems_usb.c deleted file mode 100644 index 9012e0abc626..000000000000 --- a/trunk/drivers/net/can/usb/ems_usb.c +++ /dev/null @@ -1,1155 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include - -MODULE_AUTHOR("Sebastian Haas "); -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); diff --git a/trunk/drivers/net/cnic.c b/trunk/drivers/net/cnic.c index 211c8e9182fc..d45eacb76702 100644 --- a/trunk/drivers/net/cnic.c +++ b/trunk/drivers/net/cnic.c @@ -85,6 +85,8 @@ static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode) cp->uio_dev = iminor(inode); + cnic_shutdown_bnx2_rx_ring(dev); + cnic_init_bnx2_tx_ring(dev); cnic_init_bnx2_rx_ring(dev); @@ -96,8 +98,6 @@ static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode) struct cnic_dev *dev = uinfo->priv; struct cnic_local *cp = dev->cnic_priv; - cnic_shutdown_bnx2_rx_ring(dev); - cp->uio_dev = -1; return 0; } diff --git a/trunk/drivers/net/cpmac.c b/trunk/drivers/net/cpmac.c index 61f9da2b4943..3e3fab8afb1e 100644 --- a/trunk/drivers/net/cpmac.c +++ b/trunk/drivers/net/cpmac.c @@ -1109,7 +1109,7 @@ static int external_switch; static int __devinit cpmac_probe(struct platform_device *pdev) { int rc, phy_id; - char mdio_bus_id[MII_BUS_ID_SIZE]; + char mdio_bus_id[BUS_ID_SIZE]; struct resource *mem; struct cpmac_priv *priv; struct net_device *dev; @@ -1118,7 +1118,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev) pdata = pdev->dev.platform_data; if (external_switch || dumb_switch) { - strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */ + strncpy(mdio_bus_id, "0", BUS_ID_SIZE); /* fixed phys bus */ phy_id = pdev->id; } else { 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; if (!cpmac_mii->phy_map[phy_id]) continue; - strncpy(mdio_bus_id, cpmac_mii->id, MII_BUS_ID_SIZE); + strncpy(mdio_bus_id, cpmac_mii->id, BUS_ID_SIZE); break; } } @@ -1167,7 +1167,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev) priv->msg_enable = netif_msg_init(debug_level, 0xff); memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); - snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); + snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII); diff --git a/trunk/drivers/net/ehea/ehea_main.c b/trunk/drivers/net/ehea/ehea_main.c index 41bd7aeafd82..977c3d358279 100644 --- a/trunk/drivers/net/ehea/ehea_main.c +++ b/trunk/drivers/net/ehea/ehea_main.c @@ -3083,6 +3083,7 @@ static const struct net_device_ops ehea_netdev_ops = { .ndo_poll_controller = ehea_netpoll, #endif .ndo_get_stats = ehea_get_stats, + .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = ehea_set_mac_addr, .ndo_validate_addr = eth_validate_addr, .ndo_set_multicast_list = ehea_set_multicast_list, diff --git a/trunk/drivers/net/igb/e1000_mac.c b/trunk/drivers/net/igb/e1000_mac.c index 7d76bb085e10..a0231cd079f1 100644 --- a/trunk/drivers/net/igb/e1000_mac.c +++ b/trunk/drivers/net/igb/e1000_mac.c @@ -285,6 +285,41 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value) 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 * @hw: pointer to the HW structure @@ -294,7 +329,7 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value) * the multicast filter table array address and new table value. See * igb_mta_set() **/ -static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) +u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) { u32 hash_value, hash_mask; u8 bit_shift = 0; @@ -356,41 +391,6 @@ static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) 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 * @hw: pointer to the HW structure diff --git a/trunk/drivers/net/igb/e1000_mac.h b/trunk/drivers/net/igb/e1000_mac.h index bca17d882417..7518af8cbbf5 100644 --- a/trunk/drivers/net/igb/e1000_mac.h +++ b/trunk/drivers/net/igb/e1000_mac.h @@ -88,5 +88,6 @@ enum e1000_mng_mode { #define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 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 diff --git a/trunk/drivers/net/ixgbe/ixgbe.h b/trunk/drivers/net/ixgbe/ixgbe.h index 385be6016667..dd688d45e9cd 100644 --- a/trunk/drivers/net/ixgbe/ixgbe.h +++ b/trunk/drivers/net/ixgbe/ixgbe.h @@ -267,8 +267,7 @@ struct ixgbe_adapter { enum ixgbe_fc_mode last_lfc_mode; /* Interrupt Throttle Rate */ - u32 rx_itr_setting; - u32 tx_itr_setting; + u32 itr_setting; u16 eitr_low; u16 eitr_high; @@ -352,8 +351,7 @@ struct ixgbe_adapter { struct ixgbe_hw_stats stats; /* Interrupt Throttle Rate */ - u32 rx_eitr_param; - u32 tx_eitr_param; + u32 eitr_param; unsigned long state; u64 tx_busy; diff --git a/trunk/drivers/net/ixgbe/ixgbe_ethtool.c b/trunk/drivers/net/ixgbe/ixgbe_ethtool.c index 53b0a6680254..026e94a99849 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/trunk/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; /* only valid if in constant ITR mode */ - switch (adapter->rx_itr_setting) { + switch (adapter->itr_setting) { case 0: /* throttling disabled */ ec->rx_coalesce_usecs = 0; @@ -1940,25 +1940,9 @@ static int ixgbe_get_coalesce(struct net_device *netdev, break; default: /* fixed interrupt rate mode */ - ec->rx_coalesce_usecs = 1000000/adapter->rx_eitr_param; + ec->rx_coalesce_usecs = 1000000/adapter->eitr_param; 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; } @@ -1969,14 +1953,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev, struct ixgbe_q_vector *q_vector; 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) adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq; @@ -1987,49 +1963,26 @@ static int ixgbe_set_coalesce(struct net_device *netdev, return -EINVAL; /* store the value in ints/second */ - adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs; + adapter->eitr_param = 1000000/ec->rx_coalesce_usecs; /* static value of interrupt rate */ - adapter->rx_itr_setting = adapter->rx_eitr_param; + adapter->itr_setting = adapter->eitr_param; /* clear the lower bit as its used for dynamic state */ - adapter->rx_itr_setting &= ~1; + adapter->itr_setting &= ~1; } else if (ec->rx_coalesce_usecs == 1) { /* 1 means dynamic mode */ - adapter->rx_eitr_param = 20000; - adapter->rx_itr_setting = 1; + adapter->eitr_param = 20000; + adapter->itr_setting = 1; } else { /* * any other value means disable eitr, which is best * served by setting the interrupt rate very high */ if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) - adapter->rx_eitr_param = IXGBE_MAX_RSC_INT_RATE; + adapter->eitr_param = IXGBE_MAX_RSC_INT_RATE; else - 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; + adapter->eitr_param = IXGBE_MAX_INT_RATE; + adapter->itr_setting = 0; } /* MSI/MSIx Interrupt Mode */ @@ -2039,17 +1992,17 @@ static int ixgbe_set_coalesce(struct net_device *netdev, for (i = 0; i < num_vectors; i++) { q_vector = adapter->q_vector[i]; if (q_vector->txr_count && !q_vector->rxr_count) - /* tx only */ - q_vector->eitr = adapter->tx_eitr_param; + /* tx vector gets half the rate */ + q_vector->eitr = (adapter->eitr_param >> 1); else /* rx only or mixed */ - q_vector->eitr = adapter->rx_eitr_param; + q_vector->eitr = adapter->eitr_param; ixgbe_write_eitr(q_vector); } /* Legacy Interrupt Mode */ } else { q_vector = adapter->q_vector[0]; - q_vector->eitr = adapter->rx_eitr_param; + q_vector->eitr = adapter->eitr_param; ixgbe_write_eitr(q_vector); } diff --git a/trunk/drivers/net/ixgbe/ixgbe_main.c b/trunk/drivers/net/ixgbe/ixgbe_main.c index c407bd9de0dd..59ad9590e700 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ixgbe/ixgbe_main.c @@ -926,12 +926,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) r_idx + 1); } + /* if this is a tx only vector halve the interrupt rate */ if (q_vector->txr_count && !q_vector->rxr_count) - /* tx only */ - q_vector->eitr = adapter->tx_eitr_param; + q_vector->eitr = (adapter->eitr_param >> 1); else if (q_vector->rxr_count) - /* rx or mixed */ - q_vector->eitr = adapter->rx_eitr_param; + /* rx only */ + q_vector->eitr = adapter->eitr_param; 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 (work_done < budget) { napi_complete(napi); - if (adapter->rx_itr_setting & 1) + if (adapter->itr_setting & 1) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) 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 (work_done < budget) { napi_complete(napi); - if (adapter->rx_itr_setting & 1) + if (adapter->itr_setting & 1) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) 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)) work_done = budget; - /* If all Tx work done, exit the polling mode */ + /* If all Rx work done, exit the polling mode */ if (work_done < budget) { napi_complete(napi); - if (adapter->tx_itr_setting & 1) + if (adapter->itr_setting & 1) ixgbe_set_itr_msix(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) 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; IXGBE_WRITE_REG(hw, IXGBE_EITR(0), - EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param)); + EITR_INTS_PER_SEC_TO_REG(adapter->eitr_param)); ixgbe_set_ivar(adapter, 0, 0, 0); ixgbe_set_ivar(adapter, 1, 0, 0); @@ -1969,50 +1969,6 @@ static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) 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 * @adapter: board private structure @@ -2034,6 +1990,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) u32 fctrl, hlreg0; u32 reta = 0, mrqc = 0; u32 rdrxctl; + u32 rscctrl; int rx_buf_len; /* Decide whether to use packet split mode or not */ @@ -2191,9 +2148,36 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { /* Enable 82599 HW-RSC */ - for (i = 0; i < adapter->num_rx_queues; i++) - ixgbe_configure_rscctl(adapter, i, rx_buf_len); - + 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); + } /* Disable RSC for ACK packets */ IXGBE_WRITE_REG(hw, IXGBE_RSCDBU, (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU))); @@ -2942,8 +2926,6 @@ void ixgbe_down(struct ixgbe_adapter *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); cancel_work_sync(&adapter->watchdog_task); @@ -3007,7 +2989,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) /* If budget not fully consumed, exit the polling mode */ if (work_done < budget) { napi_complete(napi); - if (adapter->rx_itr_setting & 1) + if (adapter->itr_setting & 1) ixgbe_set_itr(adapter); if (!test_bit(__IXGBE_DOWN, &adapter->state)) ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE); @@ -3617,10 +3599,7 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) if (!q_vector) goto err_out; q_vector->adapter = adapter; - 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->eitr = adapter->eitr_param; q_vector->v_idx = q_idx; netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64); adapter->q_vector[q_idx] = q_vector; @@ -3889,10 +3868,8 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) hw->fc.disable_fc_autoneg = false; /* enable itr by default in dynamic mode */ - adapter->rx_itr_setting = 1; - adapter->rx_eitr_param = 20000; - adapter->tx_itr_setting = 1; - adapter->tx_eitr_param = 10000; + adapter->itr_setting = 1; + adapter->eitr_param = 20000; /* set defaults for eitr in MegaBytes */ adapter->eitr_low = 10; diff --git a/trunk/drivers/net/netxen/netxen_nic_main.c b/trunk/drivers/net/netxen/netxen_nic_main.c index b5aa974827e5..f7bdde111dfc 100644 --- a/trunk/drivers/net/netxen/netxen_nic_main.c +++ b/trunk/drivers/net/netxen/netxen_nic_main.c @@ -1469,7 +1469,6 @@ netxen_nic_resume(struct pci_dev *pdev) } netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY); - return 0; err_out_detach: netxen_nic_detach(adapter); @@ -1904,13 +1903,12 @@ static void netxen_tx_timeout_task(struct work_struct *work) netif_wake_queue(adapter->netdev); - clear_bit(__NX_RESETTING, &adapter->state); + goto done; } else { - clear_bit(__NX_RESETTING, &adapter->state); if (!netxen_nic_reset_context(adapter)) { adapter->netdev->trans_start = jiffies; - return; + goto done; } /* context reset failed, fall through for fw reset */ @@ -1918,6 +1916,8 @@ static void netxen_tx_timeout_task(struct work_struct *work) request_reset: adapter->need_fw_reset = 1; +done: + clear_bit(__NX_RESETTING, &adapter->state); } struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) diff --git a/trunk/drivers/net/pcmcia/pcnet_cs.c b/trunk/drivers/net/pcmcia/pcnet_cs.c index 474876c879cb..97db1c732342 100644 --- a/trunk/drivers/net/pcmcia/pcnet_cs.c +++ b/trunk/drivers/net/pcmcia/pcnet_cs.c @@ -340,11 +340,12 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link) base = &virt[hw_info[i].offset & (req.Size-1)]; if ((readb(base+0) == hw_info[i].a0) && (readb(base+2) == hw_info[i].a1) && - (readb(base+4) == hw_info[i].a2)) { - for (j = 0; j < 6; j++) - dev->dev_addr[j] = readb(base + (j<<1)); - break; - } + (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)); } iounmap(virt); diff --git a/trunk/drivers/net/sky2.c b/trunk/drivers/net/sky2.c index ef1165718dd7..15140f9f2e92 100644 --- a/trunk/drivers/net/sky2.c +++ b/trunk/drivers/net/sky2.c @@ -1497,6 +1497,7 @@ static int sky2_up(struct net_device *dev) if (ramsize > 0) { u32 rxspace; + hw->flags |= SKY2_HW_RAM_BUFFER; pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); if (ramsize < 16) rxspace = ramsize / 2; @@ -2925,9 +2926,6 @@ static int __devinit sky2_init(struct sky2_hw *hw) ++hw->ports; } - if (sky2_read8(hw, B2_E_0)) - hw->flags |= SKY2_HW_RAM_BUFFER; - return 0; } diff --git a/trunk/drivers/net/sunvnet.c b/trunk/drivers/net/sunvnet.c index bc74db0d12f3..f1e5e4542c2a 100644 --- a/trunk/drivers/net/sunvnet.c +++ b/trunk/drivers/net/sunvnet.c @@ -1016,6 +1016,7 @@ static const struct net_device_ops vnet_ops = { .ndo_open = vnet_open, .ndo_stop = vnet_close, .ndo_set_multicast_list = vnet_set_rx_mode, + .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = vnet_set_mac_addr, .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = vnet_tx_timeout, diff --git a/trunk/drivers/net/tun.c b/trunk/drivers/net/tun.c index 4fdfa2ae5418..d3ee1994b02f 100644 --- a/trunk/drivers/net/tun.c +++ b/trunk/drivers/net/tun.c @@ -946,6 +946,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) char *name; unsigned long flags = 0; + err = -EINVAL; + if (!capable(CAP_NET_ADMIN)) return -EPERM; err = security_tun_dev_create(); @@ -962,7 +964,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) flags |= TUN_TAP_DEV; name = "tap%d"; } else - return -EINVAL; + goto failed; if (*ifr->ifr_name) name = ifr->ifr_name; diff --git a/trunk/drivers/net/usb/kaweth.c b/trunk/drivers/net/usb/kaweth.c index e391ef969c28..e2a39b9be96e 100644 --- a/trunk/drivers/net/usb/kaweth.c +++ b/trunk/drivers/net/usb/kaweth.c @@ -263,7 +263,6 @@ static int kaweth_control(struct kaweth_device *kaweth, int timeout) { struct usb_ctrlrequest *dr; - int retval; dbg("kaweth_control()"); @@ -279,21 +278,18 @@ static int kaweth_control(struct kaweth_device *kaweth, return -ENOMEM; } - dr->bRequestType = requesttype; + dr->bRequestType= requesttype; dr->bRequest = request; dr->wValue = cpu_to_le16(value); dr->wIndex = cpu_to_le16(index); dr->wLength = cpu_to_le16(size); - retval = kaweth_internal_control_msg(kaweth->dev, - pipe, - dr, - data, - size, - timeout); - - kfree(dr); - return retval; + return kaweth_internal_control_msg(kaweth->dev, + pipe, + dr, + data, + size, + timeout); } /**************************************************************** diff --git a/trunk/drivers/net/usb/smsc95xx.c b/trunk/drivers/net/usb/smsc95xx.c index c6c922247d05..938fb3530a7a 100644 --- a/trunk/drivers/net/usb/smsc95xx.c +++ b/trunk/drivers/net/usb/smsc95xx.c @@ -1227,7 +1227,7 @@ static const struct driver_info smsc95xx_info = { .rx_fixup = smsc95xx_rx_fixup, .tx_fixup = smsc95xx_tx_fixup, .status = smsc95xx_status, - .flags = FLAG_ETHER | FLAG_SEND_ZLP, + .flags = FLAG_ETHER, }; static const struct usb_device_id products[] = { @@ -1236,76 +1236,11 @@ static const struct usb_device_id products[] = { USB_DEVICE(0x0424, 0x9500), .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 */ USB_DEVICE(0x0424, 0xec00), .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 */ }; MODULE_DEVICE_TABLE(usb, products); diff --git a/trunk/drivers/net/usb/usbnet.c b/trunk/drivers/net/usb/usbnet.c index ca5ca5ae061d..24b36f795151 100644 --- a/trunk/drivers/net/usb/usbnet.c +++ b/trunk/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 * the ZLP here, but ignore the one-byte packet. */ - if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) { + if ((length % dev->maxpacket) == 0) { urb->transfer_buffer_length++; if (skb_tailroom(skb)) { skb->data[skb->len] = 0; diff --git a/trunk/drivers/net/wireless/ath/ar9170/usb.c b/trunk/drivers/net/wireless/ath/ar9170/usb.c index e974e5829e1a..e0138ac8bf50 100644 --- a/trunk/drivers/net/wireless/ath/ar9170/usb.c +++ b/trunk/drivers/net/wireless/ath/ar9170/usb.c @@ -64,8 +64,6 @@ static struct usb_device_id ar9170_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x9170) }, /* Atheros TG121N */ { USB_DEVICE(0x0cf3, 0x1001) }, - /* TP-Link TL-WN821N v2 */ - { USB_DEVICE(0x0cf3, 0x1002) }, /* Cace Airpcap NX */ { USB_DEVICE(0xcace, 0x0300) }, /* D-Link DWA 160A */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/calib.c b/trunk/drivers/net/wireless/ath/ath9k/calib.c index 0ad6d0b76e9e..3234995e8881 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/calib.c @@ -609,24 +609,14 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) AR_PHY_CH1_EXT_CCA, AR_PHY_CH2_EXT_CCA }; - u8 chainmask, rx_chain_status; + u8 chainmask; - rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); if (AR_SREV_9285(ah)) chainmask = 0x9; - 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; - } + else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) + chainmask = 0x1B; + else + chainmask = 0x3F; h = ah->nfCalHist; @@ -707,8 +697,6 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; else if (AR_SREV_9285(ah)) 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 noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; @@ -936,7 +924,6 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) regVal |= (1 << (19 + i)); REG_WRITE(ah, 0x7834, regVal); udelay(1); - regVal = REG_READ(ah, 0x7834); regVal &= (~(0x1 << (19 + i))); reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); regVal |= (reg_field << (19 + i)); diff --git a/trunk/drivers/net/wireless/ath/ath9k/calib.h b/trunk/drivers/net/wireless/ath/ath9k/calib.h index 9028ab193e42..019bcbba40ed 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/calib.h +++ b/trunk/drivers/net/wireless/ath/ath9k/calib.h @@ -28,7 +28,6 @@ extern const struct ath9k_percal_data adc_init_dc_cal; #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 #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_MIN_BAD_VALUE -140 #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 diff --git a/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c b/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c index 4071fc91da0a..ae7fb5dcb266 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -509,8 +509,6 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, eep->baseEepHeader.dacLpMode); - udelay(100); - REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, pModal->miscBits >> 2); @@ -904,7 +902,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, u16 powerLimit) { #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ -#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ +#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index ca7694caf364..b6c6cca07812 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/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) { - if (AR_SREV_9287_11_OR_LATER(ah)) + if (AR_SREV_9287_11(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9287Modes_rx_gain_9287_1_1, 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)) ath9k_hw_init_rxgain_ini(ah); - if (AR_SREV_9287_11_OR_LATER(ah)) { + if (AR_SREV_9287_11(ah)) { INIT_INI_ARRAY(&ah->iniModesTxGain, ar9287Modes_tx_gain_9287_1_1, 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); if (ah->is_pciexpress) - ath9k_hw_configpcipowersave(ah, 0, 0); + ath9k_hw_configpcipowersave(ah, 0); else ath9k_hw_disablepcie(ah); @@ -1273,15 +1273,6 @@ 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)); - 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) || AR_SREV_9280_10_OR_LATER(ah)) @@ -1793,7 +1784,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, struct ath9k_channel *chan) { - if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) { + if (OLC_FOR_AR9280_20_LATER) { if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) return false; } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) @@ -2347,7 +2338,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, struct ath9k_channel *curchan = ah->curchan; u32 saveDefAntenna; u32 macStaId1; - u64 tsf = 0; int i, rx_chainmask, r; ah->extprotspacing = sc->ht_extprotspacing; @@ -2357,7 +2347,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) return -EIO; - if (curchan && !ah->chip_fullsleep) + if (curchan) ath9k_hw_getnf(ah, curchan); if (bChannelChange && @@ -2366,8 +2356,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, (chan->channel != ah->curchan->channel) && ((chan->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)) { ath9k_hw_loadnf(ah, ah->curchan); @@ -2382,10 +2372,6 @@ 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; - /* 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) & (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); @@ -2412,10 +2398,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, 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)) REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); @@ -3023,10 +3005,9 @@ void ath9k_ps_restore(struct ath_softc *sc) * Programming the SerDes must go through the same 288 bit serial shift * register as the other analog registers. Hence the 9 writes. */ -void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) +void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) { u8 i; - u32 val; if (ah->is_pciexpress != true) return; @@ -3036,113 +3017,84 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) return; /* Nothing to do on restore for 11N */ - 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); - - REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); - REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); - REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); + if (restore) + return; - /* Load the new settings */ - REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); + 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); - } else { - REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); - 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); - /* 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); + /* 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); - /* - * Ignore ah->ah_config.pcie_clock_req setting for - * pre-AR9280 11n - */ - REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); + REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); + REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); + REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); - REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); - REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); - REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); + /* Load the new settings */ + REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); - /* Load the new settings */ - REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); - } + } else { + REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); + REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - udelay(1000); + /* 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); - /* 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); + /* + * Ignore ah->ah_config.pcie_clock_req setting for + * pre-AR9280 11n + */ + REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); - /* 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; - } + REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); + REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); + REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); - REG_WRITE(ah, AR_WA, val); + /* Load the new settings */ + REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); } - if (power_off) { + udelay(1000); + + /* 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); + + /* 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); /* - * 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. + * On AR9280 chips bit 22 of 0x4004 needs to be set to + * otherwise card may disappear. */ - 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); - } - } + else if (AR_SREV_9280(ah)) + REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT); + else + REG_WRITE(ah, AR_WA, AR_WA_DEFAULT); } } @@ -3700,7 +3652,15 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) } #endif - pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; + 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; if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index b89234571829..9106a0b537dd 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -106,7 +106,7 @@ #define AH_TSF_WRITE_TIMEOUT 100 /* (us) */ #define AH_TIME_QUANTUM 10 #define AR_KEYTABLE_SIZE 128 -#define POWER_UP_TIME 10000 +#define POWER_UP_TIME 200000 #define SPUR_RSSI_THRESH 40 #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); bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); -void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off); +void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore); /* Interrupt Handling */ bool ath9k_hw_intrpend(struct ath_hw *ah); diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index 52bed89063d4..3dc7b5a13e64 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -1131,7 +1131,7 @@ void ath_radio_enable(struct ath_softc *sc) int r; ath9k_ps_wakeup(sc); - ath9k_hw_configpcipowersave(ah, 0, 0); + ath9k_hw_configpcipowersave(ah, 0); if (!ah->curchan) 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); ath9k_hw_phy_disable(ah); - ath9k_hw_configpcipowersave(ah, 1, 1); + ath9k_hw_configpcipowersave(ah, 1); ath9k_ps_restore(sc); ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); } @@ -1226,6 +1226,11 @@ static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) bool blocked = !!ath_is_rfkill_set(sc); 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) @@ -1255,7 +1260,6 @@ void ath_detach(struct ath_softc *sc) DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); ath_deinit_leds(sc); - wiphy_rfkill_stop_polling(sc->hw->wiphy); for (i = 0; i < sc->num_sec_wiphy; i++) { struct ath_wiphy *aphy = sc->sec_wiphy[i]; @@ -1938,7 +1942,7 @@ static int ath9k_start(struct ieee80211_hw *hw) init_channel = ath_get_curchannel(sc, hw); /* Reset SERDES registers */ - ath9k_hw_configpcipowersave(sc->sc_ah, 0, 0); + ath9k_hw_configpcipowersave(sc->sc_ah, 0); /* * The basic interface to setting the hardware in a good @@ -2162,9 +2166,11 @@ static void ath9k_stop(struct ieee80211_hw *hw) } else sc->rx.rxlink = NULL; + wiphy_rfkill_stop_polling(sc->hw->wiphy); + /* disable HAL and put h/w to sleep */ ath9k_hw_disable(sc->sc_ah); - ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1); + ath9k_hw_configpcipowersave(sc->sc_ah, 1); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); sc->sc_flags |= SC_OP_INVALID; diff --git a/trunk/drivers/net/wireless/ath/ath9k/reg.h b/trunk/drivers/net/wireless/ath/ath9k/reg.h index d83b77f821e9..e5c29eb86e80 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/reg.h +++ b/trunk/drivers/net/wireless/ath/ath9k/reg.h @@ -676,9 +676,8 @@ #define AR_RC_HOSTIF 0x00000100 #define AR_WA 0x4004 -#define AR_WA_D3_L1_DISABLE (1 << 14) #define AR9285_WA_DEFAULT 0x004a05cb -#define AR9280_WA_DEFAULT 0x0040073b +#define AR9280_WA_DEFAULT 0x0040073f #define AR_WA_DEFAULT 0x0000073f diff --git a/trunk/drivers/net/wireless/b43/Kconfig b/trunk/drivers/net/wireless/b43/Kconfig index 54ea61c15d8b..83e38134accb 100644 --- a/trunk/drivers/net/wireless/b43/Kconfig +++ b/trunk/drivers/net/wireless/b43/Kconfig @@ -61,28 +61,11 @@ config B43_PCMCIA 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 -# This is only needed on PCMCIA and SDIO devices. All others can do DMA properly. +# This is only needed on PCMCIA devices. All others can do DMA properly. config B43_PIO bool - depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO) + depends on B43 && (B43_PCMCIA || B43_FORCE_PIO) select SSB_BLOCKIO default y diff --git a/trunk/drivers/net/wireless/b43/Makefile b/trunk/drivers/net/wireless/b43/Makefile index 84772a2542dc..da379f4b0c3a 100644 --- a/trunk/drivers/net/wireless/b43/Makefile +++ b/trunk/drivers/net/wireless/b43/Makefile @@ -16,7 +16,6 @@ b43-$(CONFIG_B43_PIO) += pio.o b43-y += rfkill.o b43-$(CONFIG_B43_LEDS) += leds.o b43-$(CONFIG_B43_PCMCIA) += pcmcia.o -b43-$(CONFIG_B43_SDIO) += sdio.o b43-$(CONFIG_B43_DEBUG) += debugfs.o obj-$(CONFIG_B43) += b43.o diff --git a/trunk/drivers/net/wireless/b43/b43.h b/trunk/drivers/net/wireless/b43/b43.h index fa1549a03c71..09cfe68537b6 100644 --- a/trunk/drivers/net/wireless/b43/b43.h +++ b/trunk/drivers/net/wireless/b43/b43.h @@ -629,6 +629,13 @@ struct b43_wl { * from the mac80211 subsystem. */ 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) * at a time. General information about this interface follows. */ @@ -679,9 +686,6 @@ struct b43_wl { struct work_struct tx_work; /* Queue of packets to be transmitted. */ struct sk_buff_head tx_queue; - - /* The device LEDs. */ - struct b43_leds leds; }; /* The type of the firmware file. */ @@ -764,10 +768,13 @@ struct b43_wldev { /* The device initialization status. * Use b43_status() to query. */ 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 dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ 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 hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ @@ -787,6 +794,12 @@ struct b43_wldev { /* Various statistics about the physical device. */ 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. */ u32 irq_reason; u32 dma_reason[6]; @@ -817,10 +830,6 @@ struct b43_wldev { /* Debugging stuff follows. */ #ifdef CONFIG_B43_DEBUG struct b43_dfsentry *dfsentry; - unsigned int irq_count; - unsigned int irq_bit_count[32]; - unsigned int tx_count; - unsigned int rx_count; #endif }; diff --git a/trunk/drivers/net/wireless/b43/debugfs.c b/trunk/drivers/net/wireless/b43/debugfs.c index 80b19a44a407..8f64943e3f60 100644 --- a/trunk/drivers/net/wireless/b43/debugfs.c +++ b/trunk/drivers/net/wireless/b43/debugfs.c @@ -689,7 +689,6 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev) add_dyn_dbg("debug_lo", B43_DBG_LO, 0); add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0); - add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, 0); #undef add_dyn_dbg } diff --git a/trunk/drivers/net/wireless/b43/debugfs.h b/trunk/drivers/net/wireless/b43/debugfs.h index 822aad8842f4..e47b4b488b04 100644 --- a/trunk/drivers/net/wireless/b43/debugfs.h +++ b/trunk/drivers/net/wireless/b43/debugfs.h @@ -13,7 +13,6 @@ enum b43_dyndbg { /* Dynamic debugging features */ B43_DBG_LO, B43_DBG_FIRMWARE, B43_DBG_KEYS, - B43_DBG_VERBOSESTATS, __B43_NR_DYNDBG, }; diff --git a/trunk/drivers/net/wireless/b43/dma.c b/trunk/drivers/net/wireless/b43/dma.c index 8701034569fa..a467ee260a19 100644 --- a/trunk/drivers/net/wireless/b43/dma.c +++ b/trunk/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_total_packet_tries += status->frame_count; #endif /* DEBUG */ - ieee80211_tx_status(dev->wl->hw, meta->skb); + ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb); - /* skb is freed by ieee80211_tx_status() */ + /* skb is freed by ieee80211_tx_status_irqsafe() */ meta->skb = NULL; } else { /* No need to call free_descriptor_buffer here, as diff --git a/trunk/drivers/net/wireless/b43/leds.c b/trunk/drivers/net/wireless/b43/leds.c index fbe3d4f62ce2..c8b317094c31 100644 --- a/trunk/drivers/net/wireless/b43/leds.c +++ b/trunk/drivers/net/wireless/b43/leds.c @@ -34,88 +34,57 @@ static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index, bool activelow) { + struct b43_wl *wl = dev->wl; + unsigned long flags; u16 ctl; + spin_lock_irqsave(&wl->leds_lock, flags); ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); if (activelow) ctl &= ~(1 << led_index); else ctl |= (1 << led_index); 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, bool activelow) { + struct b43_wl *wl = dev->wl; + unsigned long flags; u16 ctl; + spin_lock_irqsave(&wl->leds_lock, flags); ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); if (activelow) ctl |= (1 << led_index); else ctl &= ~(1 << led_index); b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); + spin_unlock_irqrestore(&wl->leds_lock, flags); } -static void b43_led_update(struct b43_wldev *dev, - struct b43_led *led) +/* 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_wldev *dev = led->dev; bool radio_enabled; - bool turn_on; - if (!led->wl) + if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) 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); - /* 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; + if (brightness == LED_OFF || !radio_enabled) + b43_led_turn_off(dev, led->index, led->activelow); 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); - 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, @@ -124,15 +93,15 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, { int err; - if (led->wl) + b43_led_turn_off(dev, led_index, activelow); + if (led->dev) return -EEXIST; if (!default_trigger) return -EINVAL; - led->wl = dev->wl; + led->dev = dev; led->index = led_index; led->activelow = activelow; strncpy(led->name, name, sizeof(led->name)); - atomic_set(&led->state, 0); led->led_dev.name = led->name; led->led_dev.default_trigger = default_trigger; @@ -141,19 +110,19 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, err = led_classdev_register(dev->dev->dev, &led->led_dev); if (err) { b43warn(dev->wl, "LEDs: Failed to register %s\n", name); - led->wl = NULL; + led->dev = NULL; return err; } - return 0; } static void b43_unregister_led(struct b43_led *led) { - if (!led->wl) + if (!led->dev) return; led_classdev_unregister(&led->led_dev); - led->wl = NULL; + b43_led_turn_off(led->dev, led->index, led->activelow); + led->dev = NULL; } static void b43_map_led(struct b43_wldev *dev, @@ -168,20 +137,24 @@ static void b43_map_led(struct b43_wldev *dev, * generic LED triggers. */ switch (behaviour) { case B43_LED_INACTIVE: + break; case B43_LED_OFF: + b43_led_turn_off(dev, led_index, activelow); + break; case B43_LED_ON: + b43_led_turn_on(dev, led_index, activelow); break; case B43_LED_ACTIVITY: case B43_LED_TRANSFER: case B43_LED_APTRANSFER: snprintf(name, sizeof(name), "b43-%s::tx", wiphy_name(hw->wiphy)); - b43_register_led(dev, &dev->wl->leds.led_tx, name, + b43_register_led(dev, &dev->led_tx, name, ieee80211_get_tx_led_name(hw), led_index, activelow); snprintf(name, sizeof(name), "b43-%s::rx", wiphy_name(hw->wiphy)); - b43_register_led(dev, &dev->wl->leds.led_rx, name, + b43_register_led(dev, &dev->led_rx, name, ieee80211_get_rx_led_name(hw), led_index, activelow); break; @@ -191,15 +164,18 @@ static void b43_map_led(struct b43_wldev *dev, case B43_LED_MODE_BG: snprintf(name, sizeof(name), "b43-%s::radio", wiphy_name(hw->wiphy)); - b43_register_led(dev, &dev->wl->leds.led_radio, name, + b43_register_led(dev, &dev->led_radio, name, ieee80211_get_radio_led_name(hw), 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; case B43_LED_WEIRD: case B43_LED_ASSOC: snprintf(name, sizeof(name), "b43-%s::assoc", wiphy_name(hw->wiphy)); - b43_register_led(dev, &dev->wl->leds.led_assoc, name, + b43_register_led(dev, &dev->led_assoc, name, ieee80211_get_assoc_led_name(hw), led_index, activelow); break; @@ -210,150 +186,58 @@ static void b43_map_led(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) +void b43_leds_init(struct b43_wldev *dev) { struct ssb_bus *bus = dev->dev->bus; u8 sprom[4]; + int i; + enum b43_led_behaviour behaviour; + bool activelow; sprom[0] = bus->sprom.gpio0; sprom[1] = bus->sprom.gpio1; sprom[2] = bus->sprom.gpio2; sprom[3] = bus->sprom.gpio3; - 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); + 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; + } } else { - b43_led_turn_off(dev, led->index, led->activelow); - led->hw_state = 0; - atomic_set(&led->state, 0); + behaviour = sprom[i] & B43_LED_BEHAVIOUR; + activelow = !!(sprom[i] & B43_LED_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) -{ - 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) +void b43_leds_exit(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); + b43_unregister_led(&dev->led_tx); + b43_unregister_led(&dev->led_rx); + b43_unregister_led(&dev->led_assoc); + b43_unregister_led(&dev->led_radio); } diff --git a/trunk/drivers/net/wireless/b43/leds.h b/trunk/drivers/net/wireless/b43/leds.h index 9592e4c5a5f5..b8b1dd521243 100644 --- a/trunk/drivers/net/wireless/b43/leds.h +++ b/trunk/drivers/net/wireless/b43/leds.h @@ -7,13 +7,12 @@ struct b43_wldev; #include #include -#include #define B43_LED_MAX_NAME_LEN 31 struct b43_led { - struct b43_wl *wl; + struct b43_wldev *dev; /* The LED class device */ struct led_classdev led_dev; /* The index number of the LED. */ @@ -23,24 +22,8 @@ struct b43_led { bool activelow; /* The unique name string for this LED device. */ 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_ACTIVELOW 0x80 /* LED behaviour values */ @@ -59,35 +42,23 @@ enum b43_led_behaviour { 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_exit(struct b43_wldev *dev); -void b43_leds_stop(struct b43_wldev *dev); #else /* CONFIG_B43_LEDS */ /* LED support disabled */ -struct b43_leds { +struct b43_led { /* 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_exit(struct b43_wldev *dev) { } -static inline void b43_leds_stop(struct b43_wldev *dev) -{ -} #endif /* CONFIG_B43_LEDS */ #endif /* B43_LEDS_H_ */ diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index 9b907a36bb8c..e789792a36bc 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -8,9 +8,6 @@ Copyright (c) 2005 Danny van Dyk Copyright (c) 2005 Andreas Jaggi - SDIO support - Copyright (c) 2009 Albert Herranz - Some parts of the code in this file are derived from the ipw2200 driver Copyright(c) 2003 - 2004 Intel Corporation. @@ -56,8 +53,6 @@ #include "xmit.h" #include "lo.h" #include "pcmcia.h" -#include "sdio.h" -#include MODULE_DESCRIPTION("Broadcom B43 wireless driver"); MODULE_AUTHOR("Martin Langer"); @@ -1592,7 +1587,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) mutex_lock(&wl->mutex); dev = wl->current_dev; if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { + if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) { /* wl->mutex is enough. */ b43_do_beacon_update_trigger_work(dev); mmiowb(); @@ -1830,16 +1825,6 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) /* Re-enable interrupts on the device by restoring the current interrupt 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. */ @@ -1920,21 +1905,6 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) 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) { release_firmware(fw->data); @@ -2675,20 +2645,6 @@ static void b43_adjust_opmode(struct b43_wldev *dev) cfp_pretbtt = 50; } 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) @@ -2917,27 +2873,6 @@ static void b43_periodic_every15sec(struct b43_wldev *dev) atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); 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) @@ -3067,18 +3002,14 @@ static void b43_security_init(struct b43_wldev *dev) static int b43_rng_read(struct hwrng *rng, u32 *data) { struct b43_wl *wl = (struct b43_wl *)rng->priv; - struct b43_wldev *dev; - int count = -ENODEV; - 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); + /* 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. */ - return count; + *data = b43_read16(wl->current_dev, B43_MMIO_RNG); + + return (sizeof(u16)); } #endif /* CONFIG_B43_HWRNG */ @@ -3137,9 +3068,6 @@ static void b43_tx_work(struct work_struct *work) dev_kfree_skb(skb); /* Drop it */ } -#if B43_DEBUG - dev->tx_count++; -#endif mutex_unlock(&wl->mutex); } @@ -3892,7 +3820,7 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) /* Disable interrupts on the device. */ b43_set_status(dev, B43_STAT_INITIALIZED); - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { + if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) { /* wl->mutex is locked. That is enough. */ b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ @@ -3902,15 +3830,10 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ spin_unlock_irq(&wl->hardirq_lock); } - /* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */ + /* Synchronize the interrupt handlers. Unlock to avoid deadlocks. */ orig_dev = dev; mutex_unlock(&wl->mutex); - 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); - } + synchronize_irq(dev->dev->irq); mutex_lock(&wl->mutex); dev = wl->current_dev; if (!dev) @@ -3927,7 +3850,7 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) dev_kfree_skb(skb_dequeue(&wl->tx_queue)); b43_mac_suspend(dev); - b43_leds_exit(dev); + free_irq(dev->dev->irq, dev); b43dbg(wl, "Wireless interface stopped\n"); return dev; @@ -3941,20 +3864,12 @@ static int b43_wireless_core_start(struct b43_wldev *dev) B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); drain_txstatus_queue(dev); - 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; - } + 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. */ @@ -3967,10 +3882,8 @@ static int b43_wireless_core_start(struct b43_wldev *dev) /* Start maintainance work */ b43_periodic_tasks_setup(dev); - b43_leds_init(dev); - b43dbg(dev->wl, "Wireless interface started\n"); -out: + out: return err; } @@ -4247,6 +4160,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) macctl |= B43_MACCTL_PSM_JMP0; 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_pio_free(dev); b43_chip_exit(dev); @@ -4263,6 +4180,7 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) /* Initialize a wireless core */ 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_sprom *sprom = &bus->sprom; struct b43_phy *phy = &dev->phy; @@ -4346,9 +4264,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) /* Maximum Contention Window */ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); - if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || - (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || - B43_FORCE_PIO) { + if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) { dev->__using_pio_transfers = 1; err = b43_pio_init(dev); } else { @@ -4364,13 +4280,15 @@ static int b43_wireless_core_init(struct b43_wldev *dev) ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)); b43_upload_card_macaddress(dev); b43_security_init(dev); - - ieee80211_wake_queues(dev->wl->hw); + if (!dev->suspend_in_progress) + b43_rng_init(wl); ieee80211_wake_queues(dev->wl->hw); b43_set_status(dev, B43_STAT_INITIALIZED); + if (!dev->suspend_in_progress) + b43_leds_init(dev); out: return err; @@ -4919,6 +4837,7 @@ static int b43_wireless_init(struct ssb_device *dev) /* Initialize struct b43_wl */ wl->hw = hw; + spin_lock_init(&wl->leds_lock); mutex_init(&wl->mutex); spin_lock_init(&wl->hardirq_lock); INIT_LIST_HEAD(&wl->devlist); @@ -4959,8 +4878,6 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id) err = ieee80211_register_hw(wl->hw); if (err) goto err_one_core_detach; - b43_leds_register(wl->current_dev); - b43_rng_init(wl); } out: @@ -4989,15 +4906,12 @@ static void b43_remove(struct ssb_device *dev) * might have modified it. Restoring is important, so the networking * stack can properly free resources. */ wl->hw->queues = wl->mac80211_initially_registered_queues; - b43_leds_stop(wldev); ieee80211_unregister_hw(wl->hw); } b43_one_core_detach(dev); if (list_empty(&wl->devlist)) { - b43_rng_exit(wl); - b43_leds_unregister(wldev); /* Last core on the chip unregistered. * We can destroy common struct b43_wl. */ @@ -5015,17 +4929,80 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason) 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 = { .name = KBUILD_MODNAME, .id_table = b43_ssb_tbl, .probe = b43_probe, .remove = b43_remove, + .suspend = b43_suspend, + .resume = b43_resume, }; static void b43_print_driverinfo(void) { const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", - *feat_leds = "", *feat_sdio = ""; + *feat_leds = ""; #ifdef CONFIG_B43_PCI_AUTOSELECT feat_pci = "P"; @@ -5038,15 +5015,12 @@ static void b43_print_driverinfo(void) #endif #ifdef CONFIG_B43_LEDS feat_leds = "L"; -#endif -#ifdef CONFIG_B43_SDIO - feat_sdio = "S"; #endif printk(KERN_INFO "Broadcom 43xx driver loaded " - "[ Features: %s%s%s%s%s, Firmware-ID: " + "[ Features: %s%s%s%s, Firmware-ID: " B43_SUPPORTED_FIRMWARE_ID " ]\n", feat_pci, feat_pcmcia, feat_nphy, - feat_leds, feat_sdio); + feat_leds); } static int __init b43_init(void) @@ -5057,18 +5031,13 @@ static int __init b43_init(void) err = b43_pcmcia_init(); if (err) goto err_dfs_exit; - err = b43_sdio_init(); - if (err) - goto err_pcmcia_exit; err = ssb_driver_register(&b43_ssb_driver); if (err) - goto err_sdio_exit; + goto err_pcmcia_exit; b43_print_driverinfo(); return err; -err_sdio_exit: - b43_sdio_exit(); err_pcmcia_exit: b43_pcmcia_exit(); err_dfs_exit: @@ -5079,7 +5048,6 @@ static int __init b43_init(void) static void __exit b43_exit(void) { ssb_driver_unregister(&b43_ssb_driver); - b43_sdio_exit(); b43_pcmcia_exit(); b43_debugfs_exit(); } diff --git a/trunk/drivers/net/wireless/b43/phy_lp.c b/trunk/drivers/net/wireless/b43/phy_lp.c index 1e318d815a5b..3e02d969f683 100644 --- a/trunk/drivers/net/wireless/b43/phy_lp.c +++ b/trunk/drivers/net/wireless/b43/phy_lp.c @@ -2228,16 +2228,6 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev, 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 = { .allocate = b43_lpphy_op_allocate, .free = b43_lpphy_op_free, @@ -2249,7 +2239,7 @@ const struct b43_phy_operations b43_phyops_lp = { .radio_read = b43_lpphy_op_radio_read, .radio_write = b43_lpphy_op_radio_write, .software_rfkill = b43_lpphy_op_software_rfkill, - .switch_analog = b43_lpphy_op_switch_analog, + .switch_analog = b43_phyop_switch_analog_generic, .switch_channel = b43_lpphy_op_switch_channel, .get_default_chan = b43_lpphy_op_get_default_chan, .set_rx_antenna = b43_lpphy_op_set_rx_antenna, diff --git a/trunk/drivers/net/wireless/b43/pio.c b/trunk/drivers/net/wireless/b43/pio.c index e96091b31499..3498b68385e7 100644 --- a/trunk/drivers/net/wireless/b43/pio.c +++ b/trunk/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->free_packet_slots += 1; - ieee80211_tx_status(dev->wl->hw, pack->skb); + ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb); pack->skb = NULL; list_add(&pack->list, &q->packets_list); diff --git a/trunk/drivers/net/wireless/b43/rfkill.c b/trunk/drivers/net/wireless/b43/rfkill.c index 7a3218c5ba7d..31e55999893f 100644 --- a/trunk/drivers/net/wireless/b43/rfkill.c +++ b/trunk/drivers/net/wireless/b43/rfkill.c @@ -28,7 +28,7 @@ /* Returns TRUE, if the radio is enabled in hardware. */ bool b43_is_hw_radio_enabled(struct b43_wldev *dev) { - if (dev->phy.rev >= 3 || dev->phy.type == B43_PHYTYPE_LP) { + if (dev->phy.rev >= 3) { if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) & B43_MMIO_RADIO_HWENABLED_HI_MASK)) return 1; diff --git a/trunk/drivers/net/wireless/b43/sdio.c b/trunk/drivers/net/wireless/b43/sdio.c deleted file mode 100644 index 0d3ac64147a5..000000000000 --- a/trunk/drivers/net/wireless/b43/sdio.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Broadcom B43 wireless driver - * - * SDIO over Sonics Silicon Backplane bus glue for b43. - * - * Copyright (C) 2009 Albert Herranz - * Copyright (C) 2009 Michael Buesch - * - * 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 -#include -#include -#include -#include - -#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); -} diff --git a/trunk/drivers/net/wireless/b43/sdio.h b/trunk/drivers/net/wireless/b43/sdio.h deleted file mode 100644 index fb633094403a..000000000000 --- a/trunk/drivers/net/wireless/b43/sdio.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef B43_SDIO_H_ -#define B43_SDIO_H_ - -#include - -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_ */ diff --git a/trunk/drivers/net/wireless/b43/xmit.c b/trunk/drivers/net/wireless/b43/xmit.c index ac9f600995e4..14f541248b5c 100644 --- a/trunk/drivers/net/wireless/b43/xmit.c +++ b/trunk/drivers/net/wireless/b43/xmit.c @@ -690,11 +690,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) } memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - ieee80211_rx(dev->wl->hw, skb); + ieee80211_rx_irqsafe(dev->wl->hw, skb); -#if B43_DEBUG - dev->rx_count++; -#endif return; drop: b43dbg(dev->wl, "RX: Packet dropped\n"); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c b/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c index 3259b8841544..ca61d3796cef 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2021,12 +2021,6 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, agg->frame_count, 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); if (idx != (SEQ_TO_SN(sc) & 0xff)) { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c index a6391c7fea53..1d539e3b8db1 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1163,12 +1163,6 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, agg->frame_count, 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); if (idx != (SEQ_TO_SN(sc) & 0xff)) { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c index 8e1bb53c0aa3..b90adcb73b06 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -250,20 +250,12 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) } spin_unlock_irqrestore(&rxq->lock, flags); - if (rxq->free_count > RX_LOW_WATERMARK) - priority |= __GFP_NOWARN; /* Alloc a new receive buffer */ skb = alloc_skb(priv->hw_params.rx_buf_size + 256, priority); if (!skb) { - 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); + IWL_CRIT(priv, "Can not allocate SKB buffers\n"); /* We don't reschedule replenish work here -- we will * call the restock method and if it still needs * more buffers it will schedule replenish */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c index c6633fec8216..a2b9ec82b965 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/trunk/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 = { .id = REPLY_WEPKEY, .data = wep_cmd, - .flags = CMD_ASYNC, + .flags = CMD_SYNC, }; memset(wep_cmd, 0, cmd_size + diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c b/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4f2d43937283..090966837f3c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1146,18 +1146,11 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) } spin_unlock_irqrestore(&rxq->lock, flags); - if (rxq->free_count > RX_LOW_WATERMARK) - priority |= __GFP_NOWARN; /* Alloc a new receive buffer */ skb = alloc_skb(priv->hw_params.rx_buf_size, priority); if (!skb) { 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); + IWL_CRIT(priv, ": Can not allocate SKB buffers\n"); /* We don't reschedule replenish work here -- we will * call the restock method and if it still needs * more buffers it will schedule replenish */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00lib.h b/trunk/drivers/net/wireless/rt2x00/rt2x00lib.h index 567f029a8cda..5462cb5ad994 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/trunk/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, +static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, unsigned int header_length, struct rxdone_entry_desc *rxdesc) { diff --git a/trunk/drivers/net/wireless/wl12xx/Kconfig b/trunk/drivers/net/wireless/wl12xx/Kconfig index 88060e117541..7b14d5bc63d6 100644 --- a/trunk/drivers/net/wireless/wl12xx/Kconfig +++ b/trunk/drivers/net/wireless/wl12xx/Kconfig @@ -1,5 +1,5 @@ menuconfig WL12XX - tristate "TI wl12xx driver support" + boolean "TI wl12xx driver support" depends on MAC80211 && WLAN_80211 && EXPERIMENTAL ---help--- This will enable TI wl12xx driver support. The drivers make diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c index 23a6a6d4863b..38688847d568 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c @@ -1070,7 +1070,7 @@ static int eject_installer(struct usb_interface *intf) /* Find bulk out endpoint */ endpoint = &iface_desc->endpoint[1].desc; - if (usb_endpoint_dir_out(endpoint) && + if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT && usb_endpoint_xfer_bulk(endpoint)) { bulk_out_ep = endpoint->bEndpointAddress; } else { diff --git a/trunk/drivers/net/xilinx_emaclite.c b/trunk/drivers/net/xilinx_emaclite.c index 83a044dbd1d7..dc22782633a5 100644 --- a/trunk/drivers/net/xilinx_emaclite.c +++ b/trunk/drivers/net/xilinx_emaclite.c @@ -134,15 +134,18 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata) } /* 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, - XEL_RSR_RECV_IE_MASK); + reg_data | XEL_RSR_RECV_IE_MASK); /* Enable the Rx interrupts for the second Buffer if * configured in HW */ 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 + XEL_RSR_OFFSET, - XEL_RSR_RECV_IE_MASK); + reg_data | XEL_RSR_RECV_IE_MASK); } /* Enable the Global Interrupt Enable */ diff --git a/trunk/drivers/staging/Kconfig b/trunk/drivers/staging/Kconfig index 9a4dd5992f65..82b34893e5b5 100644 --- a/trunk/drivers/staging/Kconfig +++ b/trunk/drivers/staging/Kconfig @@ -117,6 +117,8 @@ source "drivers/staging/vt6655/Kconfig" source "drivers/staging/vt6656/Kconfig" +source "drivers/staging/cpc-usb/Kconfig" + source "drivers/staging/udlfb/Kconfig" source "drivers/staging/hv/Kconfig" diff --git a/trunk/drivers/staging/Makefile b/trunk/drivers/staging/Makefile index 104f2f8897ec..b1cad0d9ba72 100644 --- a/trunk/drivers/staging/Makefile +++ b/trunk/drivers/staging/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/ obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ obj-$(CONFIG_VT6655) += vt6655/ obj-$(CONFIG_VT6656) += vt6656/ +obj-$(CONFIG_USB_CPC) += cpc-usb/ obj-$(CONFIG_FB_UDL) += udlfb/ obj-$(CONFIG_HYPERV) += hv/ obj-$(CONFIG_VME_BUS) += vme/ diff --git a/trunk/drivers/staging/cpc-usb/Kconfig b/trunk/drivers/staging/cpc-usb/Kconfig new file mode 100644 index 000000000000..2be0bc9c39d0 --- /dev/null +++ b/trunk/drivers/staging/cpc-usb/Kconfig @@ -0,0 +1,4 @@ +config USB_CPC + tristate "CPC CAN USB driver" + depends on USB && PROC_FS + default n diff --git a/trunk/drivers/staging/cpc-usb/Makefile b/trunk/drivers/staging/cpc-usb/Makefile new file mode 100644 index 000000000000..3f83170a8fab --- /dev/null +++ b/trunk/drivers/staging/cpc-usb/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_USB_CPC) += cpc-usb.o + +cpc-usb-y := cpc-usb_drv.o sja2m16c_2.o diff --git a/trunk/drivers/staging/cpc-usb/TODO b/trunk/drivers/staging/cpc-usb/TODO new file mode 100644 index 000000000000..9b1752fb9cd7 --- /dev/null +++ b/trunk/drivers/staging/cpc-usb/TODO @@ -0,0 +1,10 @@ +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 diff --git a/trunk/drivers/staging/cpc-usb/cpc-usb_drv.c b/trunk/drivers/staging/cpc-usb/cpc-usb_drv.c new file mode 100644 index 000000000000..c5eca46996fb --- /dev/null +++ b/trunk/drivers/staging/cpc-usb/cpc-usb_drv.c @@ -0,0 +1,1184 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#include "cpc.h" + +#include "cpc_int.h" +#include "cpcusb.h" + +#include "sja2m16c.h" + +/* Version Information */ +#define DRIVER_AUTHOR "Sebastian Haas " +#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); diff --git a/trunk/drivers/staging/cpc-usb/cpc.h b/trunk/drivers/staging/cpc-usb/cpc.h new file mode 100644 index 000000000000..b2fda5d14c1d --- /dev/null +++ b/trunk/drivers/staging/cpc-usb/cpc.h @@ -0,0 +1,417 @@ +/* + * 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 */ diff --git a/trunk/drivers/staging/cpc-usb/cpc_int.h b/trunk/drivers/staging/cpc-usb/cpc_int.h new file mode 100644 index 000000000000..38674e9690a0 --- /dev/null +++ b/trunk/drivers/staging/cpc-usb/cpc_int.h @@ -0,0 +1,83 @@ +/* + * 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 + +#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 diff --git a/trunk/drivers/staging/cpc-usb/cpcusb.h b/trunk/drivers/staging/cpc-usb/cpcusb.h new file mode 100644 index 000000000000..6bdf30be239f --- /dev/null +++ b/trunk/drivers/staging/cpc-usb/cpcusb.h @@ -0,0 +1,86 @@ +/* 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 diff --git a/trunk/drivers/staging/cpc-usb/sja2m16c.h b/trunk/drivers/staging/cpc-usb/sja2m16c.h new file mode 100644 index 000000000000..654bd3fc91dc --- /dev/null +++ b/trunk/drivers/staging/cpc-usb/sja2m16c.h @@ -0,0 +1,41 @@ +#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 diff --git a/trunk/drivers/staging/cpc-usb/sja2m16c_2.c b/trunk/drivers/staging/cpc-usb/sja2m16c_2.c new file mode 100644 index 000000000000..bf0230fb7780 --- /dev/null +++ b/trunk/drivers/staging/cpc-usb/sja2m16c_2.c @@ -0,0 +1,452 @@ +/**************************************************************************** +* +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} + + diff --git a/trunk/drivers/watchdog/Kconfig b/trunk/drivers/watchdog/Kconfig index ff3eb8ff6bd7..3711b888d482 100644 --- a/trunk/drivers/watchdog/Kconfig +++ b/trunk/drivers/watchdog/Kconfig @@ -282,6 +282,13 @@ config NUC900_WATCHDOG To compile this driver as a module, choose M here: the module will be called nuc900_wdt. +config ADX_WATCHDOG + tristate "Avionic Design Xanthos watchdog" + depends on ARCH_PXA_ADX + help + Say Y here if you want support for the watchdog timer on Avionic + Design Xanthos boards. + # AVR32 Architecture config AT32AP700X_WDT diff --git a/trunk/drivers/watchdog/Makefile b/trunk/drivers/watchdog/Makefile index 348b3b862c99..699199b1baa6 100644 --- a/trunk/drivers/watchdog/Makefile +++ b/trunk/drivers/watchdog/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o +obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o diff --git a/trunk/drivers/watchdog/adx_wdt.c b/trunk/drivers/watchdog/adx_wdt.c new file mode 100644 index 000000000000..77afb0acc500 --- /dev/null +++ b/trunk/drivers/watchdog/adx_wdt.c @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2008-2009 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define WATCHDOG_NAME "adx-wdt" + +/* register offsets */ +#define ADX_WDT_CONTROL 0x00 +#define ADX_WDT_CONTROL_ENABLE (1 << 0) +#define ADX_WDT_CONTROL_nRESET (1 << 1) +#define ADX_WDT_TIMEOUT 0x08 + +static struct platform_device *adx_wdt_dev; +static unsigned long driver_open; + +#define WDT_STATE_STOP 0 +#define WDT_STATE_START 1 + +struct adx_wdt { + void __iomem *base; + unsigned long timeout; + unsigned int state; + unsigned int wake; + spinlock_t lock; +}; + +static struct watchdog_info adx_wdt_info = { + .identity = "Avionic Design Xanthos Watchdog", + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, +}; + +static void adx_wdt_start_locked(struct adx_wdt *wdt) +{ + u32 ctrl; + + ctrl = readl(wdt->base + ADX_WDT_CONTROL); + ctrl |= ADX_WDT_CONTROL_ENABLE; + writel(ctrl, wdt->base + ADX_WDT_CONTROL); + wdt->state = WDT_STATE_START; +} + +static void adx_wdt_start(struct adx_wdt *wdt) +{ + unsigned long flags; + + spin_lock_irqsave(&wdt->lock, flags); + adx_wdt_start_locked(wdt); + spin_unlock_irqrestore(&wdt->lock, flags); +} + +static void adx_wdt_stop_locked(struct adx_wdt *wdt) +{ + u32 ctrl; + + ctrl = readl(wdt->base + ADX_WDT_CONTROL); + ctrl &= ~ADX_WDT_CONTROL_ENABLE; + writel(ctrl, wdt->base + ADX_WDT_CONTROL); + wdt->state = WDT_STATE_STOP; +} + +static void adx_wdt_stop(struct adx_wdt *wdt) +{ + unsigned long flags; + + spin_lock_irqsave(&wdt->lock, flags); + adx_wdt_stop_locked(wdt); + spin_unlock_irqrestore(&wdt->lock, flags); +} + +static void adx_wdt_set_timeout(struct adx_wdt *wdt, unsigned long seconds) +{ + unsigned long timeout = seconds * 1000; + unsigned long flags; + unsigned int state; + + spin_lock_irqsave(&wdt->lock, flags); + state = wdt->state; + adx_wdt_stop_locked(wdt); + writel(timeout, wdt->base + ADX_WDT_TIMEOUT); + + if (state == WDT_STATE_START) + adx_wdt_start_locked(wdt); + + wdt->timeout = timeout; + spin_unlock_irqrestore(&wdt->lock, flags); +} + +static void adx_wdt_get_timeout(struct adx_wdt *wdt, unsigned long *seconds) +{ + *seconds = wdt->timeout / 1000; +} + +static void adx_wdt_keepalive(struct adx_wdt *wdt) +{ + unsigned long flags; + + spin_lock_irqsave(&wdt->lock, flags); + writel(wdt->timeout, wdt->base + ADX_WDT_TIMEOUT); + spin_unlock_irqrestore(&wdt->lock, flags); +} + +static int adx_wdt_open(struct inode *inode, struct file *file) +{ + struct adx_wdt *wdt = platform_get_drvdata(adx_wdt_dev); + + if (test_and_set_bit(0, &driver_open)) + return -EBUSY; + + file->private_data = wdt; + adx_wdt_set_timeout(wdt, 30); + adx_wdt_start(wdt); + + return nonseekable_open(inode, file); +} + +static int adx_wdt_release(struct inode *inode, struct file *file) +{ + struct adx_wdt *wdt = file->private_data; + + adx_wdt_stop(wdt); + clear_bit(0, &driver_open); + + return 0; +} + +static long adx_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct adx_wdt *wdt = file->private_data; + void __user *argp = (void __user *)arg; + unsigned long __user *p = argp; + unsigned long seconds = 0; + unsigned int options; + long ret = -EINVAL; + + switch (cmd) { + case WDIOC_GETSUPPORT: + if (copy_to_user(argp, &adx_wdt_info, sizeof(adx_wdt_info))) + return -EFAULT; + else + return 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + + case WDIOC_KEEPALIVE: + adx_wdt_keepalive(wdt); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(seconds, p)) + return -EFAULT; + + adx_wdt_set_timeout(wdt, seconds); + + /* fallthrough */ + case WDIOC_GETTIMEOUT: + adx_wdt_get_timeout(wdt, &seconds); + return put_user(seconds, p); + + case WDIOC_SETOPTIONS: + if (copy_from_user(&options, argp, sizeof(options))) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + adx_wdt_stop(wdt); + ret = 0; + } + + if (options & WDIOS_ENABLECARD) { + adx_wdt_start(wdt); + ret = 0; + } + + return ret; + + default: + break; + } + + return -ENOTTY; +} + +static ssize_t adx_wdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + struct adx_wdt *wdt = file->private_data; + + if (len) + adx_wdt_keepalive(wdt); + + return len; +} + +static const struct file_operations adx_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = adx_wdt_open, + .release = adx_wdt_release, + .unlocked_ioctl = adx_wdt_ioctl, + .write = adx_wdt_write, +}; + +static struct miscdevice adx_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &adx_wdt_fops, +}; + +static int __devinit adx_wdt_probe(struct platform_device *pdev) +{ + struct resource *res; + struct adx_wdt *wdt; + int ret = 0; + u32 ctrl; + + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); + if (!wdt) { + dev_err(&pdev->dev, "cannot allocate WDT structure\n"); + return -ENOMEM; + } + + spin_lock_init(&wdt->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "cannot obtain I/O memory region\n"); + return -ENXIO; + } + + res = devm_request_mem_region(&pdev->dev, res->start, + res->end - res->start + 1, res->name); + if (!res) { + dev_err(&pdev->dev, "cannot request I/O memory region\n"); + return -ENXIO; + } + + wdt->base = devm_ioremap_nocache(&pdev->dev, res->start, + res->end - res->start + 1); + if (!wdt->base) { + dev_err(&pdev->dev, "cannot remap I/O memory region\n"); + return -ENXIO; + } + + /* disable watchdog and reboot on timeout */ + ctrl = readl(wdt->base + ADX_WDT_CONTROL); + ctrl &= ~ADX_WDT_CONTROL_ENABLE; + ctrl &= ~ADX_WDT_CONTROL_nRESET; + writel(ctrl, wdt->base + ADX_WDT_CONTROL); + + platform_set_drvdata(pdev, wdt); + adx_wdt_dev = pdev; + + ret = misc_register(&adx_wdt_miscdev); + if (ret) { + dev_err(&pdev->dev, "cannot register miscdev on minor %d " + "(err=%d)\n", WATCHDOG_MINOR, ret); + return ret; + } + + return 0; +} + +static int __devexit adx_wdt_remove(struct platform_device *pdev) +{ + struct adx_wdt *wdt = platform_get_drvdata(pdev); + + misc_deregister(&adx_wdt_miscdev); + adx_wdt_stop(wdt); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static void adx_wdt_shutdown(struct platform_device *pdev) +{ + struct adx_wdt *wdt = platform_get_drvdata(pdev); + adx_wdt_stop(wdt); +} + +#ifdef CONFIG_PM +static int adx_wdt_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct adx_wdt *wdt = platform_get_drvdata(pdev); + + wdt->wake = (wdt->state == WDT_STATE_START) ? 1 : 0; + adx_wdt_stop(wdt); + + return 0; +} + +static int adx_wdt_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct adx_wdt *wdt = platform_get_drvdata(pdev); + + if (wdt->wake) + adx_wdt_start(wdt); + + return 0; +} + +static struct dev_pm_ops adx_wdt_pm_ops = { + .suspend = adx_wdt_suspend, + .resume = adx_wdt_resume, +}; + +# define ADX_WDT_PM_OPS (&adx_wdt_pm_ops) +#else +# define ADX_WDT_PM_OPS NULL +#endif + +static struct platform_driver adx_wdt_driver = { + .probe = adx_wdt_probe, + .remove = __devexit_p(adx_wdt_remove), + .shutdown = adx_wdt_shutdown, + .driver = { + .name = WATCHDOG_NAME, + .owner = THIS_MODULE, + .pm = ADX_WDT_PM_OPS, + }, +}; + +static int __init adx_wdt_init(void) +{ + return platform_driver_register(&adx_wdt_driver); +} + +static void __exit adx_wdt_exit(void) +{ + platform_driver_unregister(&adx_wdt_driver); +} + +module_init(adx_wdt_init); +module_exit(adx_wdt_exit); + +MODULE_DESCRIPTION("Avionic Design Xanthos Watchdog Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Thierry Reding "); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/trunk/include/linux/netlink.h b/trunk/include/linux/netlink.h index ab5d3126831f..080f6ba9e73a 100644 --- a/trunk/include/linux/netlink.h +++ b/trunk/include/linux/netlink.h @@ -187,7 +187,6 @@ extern struct sock *netlink_kernel_create(struct net *net, 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 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 int netlink_has_listeners(struct sock *sk, unsigned int group); diff --git a/trunk/include/linux/phonet.h b/trunk/include/linux/phonet.h index e5126cff9b2a..1ef5a0781831 100644 --- a/trunk/include/linux/phonet.h +++ b/trunk/include/linux/phonet.h @@ -38,7 +38,6 @@ #define PNPIPE_IFINDEX 2 #define PNADDR_ANY 0 -#define PNADDR_BROADCAST 0xFC #define PNPORT_RESOURCE_ROUTING 0 /* Values for PNPIPE_ENCAP option */ diff --git a/trunk/include/linux/usb/usbnet.h b/trunk/include/linux/usb/usbnet.h index f81473052059..bb69e256cd16 100644 --- a/trunk/include/linux/usb/usbnet.h +++ b/trunk/include/linux/usb/usbnet.h @@ -89,7 +89,6 @@ struct driver_info { #define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ #define FLAG_WLAN 0x0080 /* use "wlan%d" names */ #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 */ diff --git a/trunk/include/net/ipip.h b/trunk/include/net/ipip.h index 76e3ea6e2fe5..5d3036fa1511 100644 --- a/trunk/include/net/ipip.h +++ b/trunk/include/net/ipip.h @@ -12,6 +12,7 @@ struct ip_tunnel struct ip_tunnel *next; struct net_device *dev; + int recursion; /* Depth of hard_start_xmit recursion */ int err_count; /* Number of arrived ICMP errors */ unsigned long err_time; /* Time when the last ICMP error arrived */ diff --git a/trunk/kernel/sys_ni.c b/trunk/kernel/sys_ni.c index e06d0b8d1951..515bc230ac2a 100644 --- a/trunk/kernel/sys_ni.c +++ b/trunk/kernel/sys_ni.c @@ -49,7 +49,6 @@ cond_syscall(sys_sendmsg); cond_syscall(compat_sys_sendmsg); cond_syscall(sys_recvmsg); cond_syscall(compat_sys_recvmsg); -cond_syscall(compat_sys_recvfrom); cond_syscall(sys_socketcall); cond_syscall(sys_futex); cond_syscall(compat_sys_futex); diff --git a/trunk/lib/vsprintf.c b/trunk/lib/vsprintf.c index b91839e9e892..73a14b8c6d1f 100644 --- a/trunk/lib/vsprintf.c +++ b/trunk/lib/vsprintf.c @@ -671,7 +671,7 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros) return p; } -static char *ip6_compressed_string(char *p, const char *addr) +static char *ip6_compressed_string(char *p, const struct in6_addr *addr) { int i; int j; @@ -683,12 +683,7 @@ static char *ip6_compressed_string(char *p, const char *addr) u8 hi; u8 lo; bool needcolon = false; - bool useIPv4; - struct in6_addr in6; - - memcpy(&in6, addr, sizeof(struct in6_addr)); - - useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6); + bool useIPv4 = ipv6_addr_v4mapped(addr) || ipv6_addr_is_isatap(addr); memset(zerolength, 0, sizeof(zerolength)); @@ -700,7 +695,7 @@ static char *ip6_compressed_string(char *p, const char *addr) /* find position of longest 0 run */ for (i = 0; i < range; i++) { for (j = i; j < range; j++) { - if (in6.s6_addr16[j] != 0) + if (addr->s6_addr16[j] != 0) break; zerolength[i]++; } @@ -727,7 +722,7 @@ static char *ip6_compressed_string(char *p, const char *addr) needcolon = false; } /* hex u16 without leading 0s */ - word = ntohs(in6.s6_addr16[i]); + word = ntohs(addr->s6_addr16[i]); hi = word >> 8; lo = word & 0xff; if (hi) { @@ -746,19 +741,19 @@ static char *ip6_compressed_string(char *p, const char *addr) if (useIPv4) { if (needcolon) *p++ = ':'; - p = ip4_string(p, &in6.s6_addr[12], false); + p = ip4_string(p, &addr->s6_addr[12], false); } *p = '\0'; return p; } -static char *ip6_string(char *p, const char *addr, const char *fmt) +static char *ip6_string(char *p, const struct in6_addr *addr, const char *fmt) { int i; for (i = 0; i < 8; i++) { - p = pack_hex_byte(p, *addr++); - p = pack_hex_byte(p, *addr++); + p = pack_hex_byte(p, addr->s6_addr[2 * i]); + p = pack_hex_byte(p, addr->s6_addr[2 * i + 1]); if (fmt[0] == 'I' && i != 7) *p++ = ':'; } @@ -773,9 +768,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")]; if (fmt[0] == 'I' && fmt[2] == 'c') - ip6_compressed_string(ip6_addr, addr); + ip6_compressed_string(ip6_addr, (const struct in6_addr *)addr); else - ip6_string(ip6_addr, addr, fmt); + ip6_string(ip6_addr, (const struct in6_addr *)addr, fmt); return string(buf, end, ip6_addr, spec); } diff --git a/trunk/net/ax25/af_ax25.c b/trunk/net/ax25/af_ax25.c index d6b1b054e294..da0f64f82b57 100644 --- a/trunk/net/ax25/af_ax25.c +++ b/trunk/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.n2count = ax25->n2count; ax25_info.state = ax25->state; - ax25_info.rcv_q = sk_rmem_alloc_get(sk); - ax25_info.snd_q = sk_wmem_alloc_get(sk); + ax25_info.rcv_q = sk_wmem_alloc_get(sk); + ax25_info.snd_q = sk_rmem_alloc_get(sk); ax25_info.vs = ax25->vs; ax25_info.vr = ax25->vr; ax25_info.va = ax25->va; diff --git a/trunk/net/core/pktgen.c b/trunk/net/core/pktgen.c index 4d11c28ca8ca..0bcecbf06581 100644 --- a/trunk/net/core/pktgen.c +++ b/trunk/net/core/pktgen.c @@ -192,10 +192,11 @@ #define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ /* Thread control flag bits */ -#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 */ +#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 */ /* If lock -- can be removed after some work */ #define if_lock(t) spin_lock(&(t->if_lock)); @@ -2104,7 +2105,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) { - ktime_t start_time, end_time; + ktime_t start; s32 remaining; struct hrtimer_sleeper t; @@ -2115,7 +2116,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) if (remaining <= 0) return; - start_time = ktime_now(); + start = ktime_now(); if (remaining < 100) udelay(remaining); /* really small just spin */ else { @@ -2134,10 +2135,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) } while (t.task && pkt_dev->running && !signal_pending(current)); __set_current_state(TASK_RUNNING); } - 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); + pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), start)); } static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) @@ -3367,29 +3365,19 @@ static void pktgen_rem_thread(struct pktgen_thread *t) mutex_unlock(&pktgen_thread_lock); } -static void pktgen_resched(struct pktgen_dev *pkt_dev) -{ - ktime_t idle_start = ktime_now(); - schedule(); - pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start)); -} - -static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev) +static void idle(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()) + schedule(); + else + cpu_relax(); - if (need_resched()) - pktgen_resched(pkt_dev); - else - cpu_relax(); - } pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start)); } + static void pktgen_xmit(struct pktgen_dev *pkt_dev) { struct net_device *odev = pkt_dev->odev; @@ -3399,21 +3387,36 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) u16 queue_map; int ret; - /* If device is offline, then don't send */ - if (unlikely(!netif_running(odev) || !netif_carrier_ok(odev))) { - pktgen_stop_device(pkt_dev); - return; + 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; + } } - /* 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); + 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); + } + + 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); return; } - /* If no skb or clone count exhausted then get new one */ if (!pkt_dev->skb || (pkt_dev->last_ok && ++pkt_dev->clone_count >= pkt_dev->clone_skb)) { /* build a new pkt */ @@ -3432,45 +3435,54 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) pkt_dev->clone_count = 0; /* reset counter */ } - if (pkt_dev->delay && pkt_dev->last_ok) - spin(pkt_dev, pkt_dev->next_tx); - + /* fill_packet() might have changed the queue */ queue_map = skb_get_queue_mapping(pkt_dev->skb); txq = netdev_get_tx_queue(odev, queue_map); __netif_tx_lock_bh(txq); - atomic_inc(&(pkt_dev->skb->users)); - if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq))) - ret = NETDEV_TX_BUSY; - else - 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; - 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; + else { + atomic_inc(&(pkt_dev->skb->users)); + + retry_now: + 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); } __netif_tx_unlock_bh(txq); /* If pkt_dev->count is zero, then run forever */ if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { - pktgen_wait_for_skb(pkt_dev); + while (atomic_read(&(pkt_dev->skb->users)) != 1) { + if (signal_pending(current)) + break; + idle(pkt_dev); + } /* Done with this */ pktgen_stop_device(pkt_dev); @@ -3503,24 +3515,20 @@ static int pktgen_thread_worker(void *arg) while (!kthread_should_stop()) { pkt_dev = next_to_run(t); - if (unlikely(!pkt_dev && t->control == 0)) { - wait_event_interruptible_timeout(t->queue, - t->control != 0, - HZ/10); - continue; + 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); } __set_current_state(TASK_RUNNING); - if (likely(pkt_dev)) { + if (pkt_dev) pktgen_xmit(pkt_dev); - if (need_resched()) - pktgen_resched(pkt_dev); - else - cpu_relax(); - } - if (t->control & T_STOP) { pktgen_stop(t); t->control &= ~(T_STOP); diff --git a/trunk/net/ipv4/ip_gre.c b/trunk/net/ipv4/ip_gre.c index 41ada9904d31..d9645c94a067 100644 --- a/trunk/net/ipv4/ip_gre.c +++ b/trunk/net/ipv4/ip_gre.c @@ -66,7 +66,10 @@ solution, but it supposes maintaing new variable in ALL skb, even if no tunneling is used. - Current solution: HARD_TX_LOCK lock breaks dead loops. + 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. @@ -675,6 +678,11 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev __be32 dst; int mtu; + if (tunnel->recursion++) { + stats->collisions++; + goto tx_error; + } + if (dev->type == ARPHRD_ETHER) IPCB(skb)->flags = 0; @@ -812,6 +820,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev ip_rt_put(rt); stats->tx_dropped++; dev_kfree_skb(skb); + tunnel->recursion--; return NETDEV_TX_OK; } if (skb->sk) @@ -879,6 +888,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev nf_reset(skb); IPTUNNEL_XMIT(); + tunnel->recursion--; return NETDEV_TX_OK; tx_error_icmp: @@ -887,6 +897,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev tx_error: stats->tx_errors++; dev_kfree_skb(skb); + tunnel->recursion--; return NETDEV_TX_OK; } diff --git a/trunk/net/ipv4/ip_sockglue.c b/trunk/net/ipv4/ip_sockglue.c index 5a0693576e82..fc7993e9061f 100644 --- a/trunk/net/ipv4/ip_sockglue.c +++ b/trunk/net/ipv4/ip_sockglue.c @@ -611,9 +611,6 @@ static int do_ip_setsockopt(struct sock *sk, int level, * Check the arguments are allowable */ - if (optlen < sizeof(struct in_addr)) - goto e_inval; - err = -EFAULT; if (optlen >= sizeof(struct ip_mreqn)) { if (copy_from_user(&mreq, optval, sizeof(mreq))) diff --git a/trunk/net/ipv4/ipip.c b/trunk/net/ipv4/ipip.c index 08ccd344de7a..62548cb0923c 100644 --- a/trunk/net/ipv4/ipip.c +++ b/trunk/net/ipv4/ipip.c @@ -402,6 +402,11 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) __be32 dst = tiph->daddr; int mtu; + if (tunnel->recursion++) { + stats->collisions++; + goto tx_error; + } + if (skb->protocol != htons(ETH_P_IP)) goto tx_error; @@ -480,6 +485,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) ip_rt_put(rt); stats->tx_dropped++; dev_kfree_skb(skb); + tunnel->recursion--; return NETDEV_TX_OK; } if (skb->sk) @@ -517,6 +523,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) nf_reset(skb); IPTUNNEL_XMIT(); + tunnel->recursion--; return NETDEV_TX_OK; tx_error_icmp: @@ -524,6 +531,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) tx_error: stats->tx_errors++; dev_kfree_skb(skb); + tunnel->recursion--; return NETDEV_TX_OK; } diff --git a/trunk/net/ipv6/ip6_tunnel.c b/trunk/net/ipv6/ip6_tunnel.c index c595bbe1ed99..7d25bbe32110 100644 --- a/trunk/net/ipv6/ip6_tunnel.c +++ b/trunk/net/ipv6/ip6_tunnel.c @@ -1043,6 +1043,11 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) struct net_device_stats *stats = &t->dev->stats; int ret; + if (t->recursion++) { + stats->collisions++; + goto tx_err; + } + switch (skb->protocol) { case htons(ETH_P_IP): ret = ip4ip6_tnl_xmit(skb, dev); @@ -1057,12 +1062,14 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) if (ret < 0) goto tx_err; + t->recursion--; return NETDEV_TX_OK; tx_err: stats->tx_errors++; stats->tx_dropped++; kfree_skb(skb); + t->recursion--; return NETDEV_TX_OK; } diff --git a/trunk/net/ipv6/sit.c b/trunk/net/ipv6/sit.c index fcb539628847..0ae4f6448187 100644 --- a/trunk/net/ipv6/sit.c +++ b/trunk/net/ipv6/sit.c @@ -626,6 +626,11 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, struct in6_addr *addr6; int addr_type; + if (tunnel->recursion++) { + stats->collisions++; + goto tx_error; + } + if (skb->protocol != htons(ETH_P_IPV6)) goto tx_error; @@ -748,6 +753,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, ip_rt_put(rt); stats->tx_dropped++; dev_kfree_skb(skb); + tunnel->recursion--; return NETDEV_TX_OK; } if (skb->sk) @@ -788,6 +794,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, nf_reset(skb); IPTUNNEL_XMIT(); + tunnel->recursion--; return NETDEV_TX_OK; tx_error_icmp: @@ -795,6 +802,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, tx_error: stats->tx_errors++; dev_kfree_skb(skb); + tunnel->recursion--; return NETDEV_TX_OK; } diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c index 71e10cabf811..039901109fa1 100644 --- a/trunk/net/mac80211/scan.c +++ b/trunk/net/mac80211/scan.c @@ -90,8 +90,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local, bss->dtim_period = tim_ie->dtim_period; } - /* set default value for buggy AP/no TIM element */ - if (bss->dtim_period == 0) + /* set default value for buggy APs */ + if (!elems->tim || bss->dtim_period == 0) bss->dtim_period = 1; bss->supp_rates_len = 0; diff --git a/trunk/net/netlink/af_netlink.c b/trunk/net/netlink/af_netlink.c index a4bafbf15097..55180b99562a 100644 --- a/trunk/net/netlink/af_netlink.c +++ b/trunk/net/netlink/af_netlink.c @@ -1609,16 +1609,6 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups) 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 * @@ -1629,8 +1619,15 @@ 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_clear_multicast_users(ksk, group); + + sk_for_each_bound(sk, node, &tbl->mc_list) + netlink_update_socket_mc(nlk_sk(sk), group, 0); + netlink_table_ungrab(); } diff --git a/trunk/net/netlink/genetlink.c b/trunk/net/netlink/genetlink.c index 44ff3f3810fa..566941e03363 100644 --- a/trunk/net/netlink/genetlink.c +++ b/trunk/net/netlink/genetlink.c @@ -220,12 +220,10 @@ static void __genl_unregister_mc_group(struct genl_family *family, struct net *net; BUG_ON(grp->family != family); - netlink_table_grab(); rcu_read_lock(); 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(); - netlink_table_ungrab(); clear_bit(grp->id, mc_groups); list_del(&grp->list); diff --git a/trunk/net/phonet/af_phonet.c b/trunk/net/phonet/af_phonet.c index f60c0c2aacba..a662e62a99cf 100644 --- a/trunk/net/phonet/af_phonet.c +++ b/trunk/net/phonet/af_phonet.c @@ -168,12 +168,6 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev, goto drop; } - /* Broadcast sending is not implemented */ - if (pn_addr(dst) == PNADDR_BROADCAST) { - err = -EOPNOTSUPP; - goto drop; - } - skb_reset_transport_header(skb); WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */ skb_push(skb, sizeof(struct phonethdr)); diff --git a/trunk/net/phonet/socket.c b/trunk/net/phonet/socket.c index 07aa9f08d5fb..7a4ee397d2f7 100644 --- a/trunk/net/phonet/socket.c +++ b/trunk/net/phonet/socket.c @@ -113,8 +113,6 @@ void pn_sock_unhash(struct sock *sk) } EXPORT_SYMBOL(pn_sock_unhash); -static DEFINE_MUTEX(port_mutex); - static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) { struct sock *sk = sock->sk; @@ -142,11 +140,9 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) err = -EINVAL; /* attempt to rebind */ goto out; } - WARN_ON(sk_hashed(sk)); - mutex_lock(&port_mutex); err = sk->sk_prot->get_port(sk, pn_port(handle)); if (err) - goto out_port; + goto out; /* get_port() sets the port, bind() sets the address if applicable */ pn->sobject = pn_object(saddr, pn_port(pn->sobject)); @@ -154,8 +150,6 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) /* Enable RX on the socket */ sk->sk_prot->hash(sk); -out_port: - mutex_unlock(&port_mutex); out: release_sock(sk); return err; @@ -363,6 +357,8 @@ const struct proto_ops phonet_stream_ops = { }; EXPORT_SYMBOL(phonet_stream_ops); +static DEFINE_MUTEX(port_mutex); + /* allocate port for a socket */ int pn_sock_get_port(struct sock *sk, unsigned short sport) { @@ -374,7 +370,9 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport) memset(&try_sa, 0, sizeof(struct sockaddr_pn)); try_sa.spn_family = AF_PHONET; - WARN_ON(!mutex_is_locked(&port_mutex)); + + mutex_lock(&port_mutex); + if (!sport) { /* search free port */ int port, pmin, pmax; @@ -403,6 +401,8 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport) else sock_put(tmpsk); } + mutex_unlock(&port_mutex); + /* the port must be in use already */ return -EADDRINUSE; diff --git a/trunk/net/wireless/wext-sme.c b/trunk/net/wireless/wext-sme.c index bf725275eb8d..d16cd9ea4d00 100644 --- a/trunk/net/wireless/wext-sme.c +++ b/trunk/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_len = wdev->wext.ie_len; + wdev->wext.connect.privacy = wdev->wext.default_key != -1; if (wdev->wext.keys) { wdev->wext.keys->def = wdev->wext.default_key; wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key; - wdev->wext.connect.privacy = true; } if (!wdev->wext.connect.ssid_len)