diff options
93 files changed, 2610 insertions, 2909 deletions
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 55719a974276..fb5c23af1017 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c | |||
| @@ -757,6 +757,42 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data) | |||
| 757 | void __init at91_add_device_ac97(struct ac97c_platform_data *data) {} | 757 | void __init at91_add_device_ac97(struct ac97c_platform_data *data) {} |
| 758 | #endif | 758 | #endif |
| 759 | 759 | ||
| 760 | /* -------------------------------------------------------------------- | ||
| 761 | * CAN Controller | ||
| 762 | * -------------------------------------------------------------------- */ | ||
| 763 | |||
| 764 | #if defined(CONFIG_CAN_AT91) || defined(CONFIG_CAN_AT91_MODULE) | ||
| 765 | static struct resource can_resources[] = { | ||
| 766 | [0] = { | ||
| 767 | .start = AT91SAM9263_BASE_CAN, | ||
| 768 | .end = AT91SAM9263_BASE_CAN + SZ_16K - 1, | ||
| 769 | .flags = IORESOURCE_MEM, | ||
| 770 | }, | ||
| 771 | [1] = { | ||
| 772 | .start = AT91SAM9263_ID_CAN, | ||
| 773 | .end = AT91SAM9263_ID_CAN, | ||
| 774 | .flags = IORESOURCE_IRQ, | ||
| 775 | }, | ||
| 776 | }; | ||
| 777 | |||
| 778 | static struct platform_device at91sam9263_can_device = { | ||
| 779 | .name = "at91_can", | ||
| 780 | .id = -1, | ||
| 781 | .resource = can_resources, | ||
| 782 | .num_resources = ARRAY_SIZE(can_resources), | ||
| 783 | }; | ||
| 784 | |||
| 785 | void __init at91_add_device_can(struct at91_can_data *data) | ||
| 786 | { | ||
| 787 | at91_set_A_periph(AT91_PIN_PA13, 0); /* CANTX */ | ||
| 788 | at91_set_A_periph(AT91_PIN_PA14, 0); /* CANRX */ | ||
| 789 | at91sam9263_can_device.dev.platform_data = data; | ||
| 790 | |||
| 791 | platform_device_register(&at91sam9263_can_device); | ||
| 792 | } | ||
| 793 | #else | ||
| 794 | void __init at91_add_device_can(struct at91_can_data *data) {} | ||
| 795 | #endif | ||
| 760 | 796 | ||
| 761 | /* -------------------------------------------------------------------- | 797 | /* -------------------------------------------------------------------- |
| 762 | * LCD Controller | 798 | * LCD Controller |
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 26f1aa6049af..2d867fb0630f 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c | |||
| @@ -400,6 +400,23 @@ static struct gpio_led ek_pwm_led[] = { | |||
| 400 | } | 400 | } |
| 401 | }; | 401 | }; |
| 402 | 402 | ||
| 403 | /* | ||
| 404 | * CAN | ||
| 405 | */ | ||
| 406 | static void sam9263ek_transceiver_switch(int on) | ||
| 407 | { | ||
| 408 | if (on) { | ||
| 409 | at91_set_gpio_output(AT91_PIN_PA18, 1); /* CANRXEN */ | ||
| 410 | at91_set_gpio_output(AT91_PIN_PA19, 0); /* CANRS */ | ||
| 411 | } else { | ||
| 412 | at91_set_gpio_output(AT91_PIN_PA18, 0); /* CANRXEN */ | ||
| 413 | at91_set_gpio_output(AT91_PIN_PA19, 1); /* CANRS */ | ||
| 414 | } | ||
| 415 | } | ||
| 416 | |||
| 417 | static struct at91_can_data ek_can_data = { | ||
| 418 | .transceiver_switch = sam9263ek_transceiver_switch, | ||
| 419 | }; | ||
| 403 | 420 | ||
| 404 | static void __init ek_board_init(void) | 421 | static void __init ek_board_init(void) |
| 405 | { | 422 | { |
| @@ -431,6 +448,8 @@ static void __init ek_board_init(void) | |||
| 431 | /* LEDs */ | 448 | /* LEDs */ |
| 432 | at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); | 449 | at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); |
| 433 | at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led)); | 450 | at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led)); |
| 451 | /* CAN */ | ||
| 452 | at91_add_device_can(&ek_can_data); | ||
| 434 | } | 453 | } |
| 435 | 454 | ||
| 436 | MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK") | 455 | MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK") |
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index 583f38a38df7..2f4fcedc02ba 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h | |||
| @@ -188,6 +188,12 @@ extern void __init at91_add_device_isi(void); | |||
| 188 | /* Touchscreen Controller */ | 188 | /* Touchscreen Controller */ |
| 189 | extern void __init at91_add_device_tsadcc(void); | 189 | extern void __init at91_add_device_tsadcc(void); |
| 190 | 190 | ||
| 191 | /* CAN */ | ||
| 192 | struct at91_can_data { | ||
| 193 | void (*transceiver_switch)(int on); | ||
| 194 | }; | ||
| 195 | extern void __init at91_add_device_can(struct at91_can_data *data); | ||
| 196 | |||
| 191 | /* LEDs */ | 197 | /* LEDs */ |
| 192 | extern void __init at91_init_leds(u8 cpu_led, u8 timer_led); | 198 | extern void __init at91_init_leds(u8 cpu_led, u8 timer_led); |
| 193 | extern void __init at91_gpio_leds(struct gpio_led *leds, int nr); | 199 | extern void __init at91_gpio_leds(struct gpio_led *leds, int nr); |
diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 2de64065aa1b..29e66d603d3c 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c | |||
| @@ -790,11 +790,15 @@ he_init_group(struct he_dev *he_dev, int group) | |||
| 790 | he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev, | 790 | he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev, |
| 791 | CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys); | 791 | CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys); |
| 792 | if (he_dev->rbps_base == NULL) { | 792 | if (he_dev->rbps_base == NULL) { |
| 793 | hprintk("failed to alloc rbps\n"); | 793 | hprintk("failed to alloc rbps_base\n"); |
| 794 | return -ENOMEM; | 794 | goto out_destroy_rbps_pool; |
| 795 | } | 795 | } |
| 796 | memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp)); | 796 | memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp)); |
| 797 | he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL); | 797 | he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL); |
| 798 | if (he_dev->rbps_virt == NULL) { | ||
| 799 | hprintk("failed to alloc rbps_virt\n"); | ||
| 800 | goto out_free_rbps_base; | ||
| 801 | } | ||
| 798 | 802 | ||
| 799 | for (i = 0; i < CONFIG_RBPS_SIZE; ++i) { | 803 | for (i = 0; i < CONFIG_RBPS_SIZE; ++i) { |
| 800 | dma_addr_t dma_handle; | 804 | dma_addr_t dma_handle; |
| @@ -802,7 +806,7 @@ he_init_group(struct he_dev *he_dev, int group) | |||
| 802 | 806 | ||
| 803 | cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle); | 807 | cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle); |
| 804 | if (cpuaddr == NULL) | 808 | if (cpuaddr == NULL) |
| 805 | return -ENOMEM; | 809 | goto out_free_rbps_virt; |
| 806 | 810 | ||
| 807 | he_dev->rbps_virt[i].virt = cpuaddr; | 811 | he_dev->rbps_virt[i].virt = cpuaddr; |
| 808 | he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF); | 812 | he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF); |
| @@ -827,17 +831,21 @@ he_init_group(struct he_dev *he_dev, int group) | |||
| 827 | CONFIG_RBPL_BUFSIZE, 8, 0); | 831 | CONFIG_RBPL_BUFSIZE, 8, 0); |
| 828 | if (he_dev->rbpl_pool == NULL) { | 832 | if (he_dev->rbpl_pool == NULL) { |
| 829 | hprintk("unable to create rbpl pool\n"); | 833 | hprintk("unable to create rbpl pool\n"); |
| 830 | return -ENOMEM; | 834 | goto out_free_rbps_virt; |
| 831 | } | 835 | } |
| 832 | 836 | ||
| 833 | he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev, | 837 | he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev, |
| 834 | CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys); | 838 | CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys); |
| 835 | if (he_dev->rbpl_base == NULL) { | 839 | if (he_dev->rbpl_base == NULL) { |
| 836 | hprintk("failed to alloc rbpl\n"); | 840 | hprintk("failed to alloc rbpl_base\n"); |
| 837 | return -ENOMEM; | 841 | goto out_destroy_rbpl_pool; |
| 838 | } | 842 | } |
| 839 | memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp)); | 843 | memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp)); |
| 840 | he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL); | 844 | he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL); |
| 845 | if (he_dev->rbpl_virt == NULL) { | ||
| 846 | hprintk("failed to alloc rbpl_virt\n"); | ||
| 847 | goto out_free_rbpl_base; | ||
| 848 | } | ||
| 841 | 849 | ||
| 842 | for (i = 0; i < CONFIG_RBPL_SIZE; ++i) { | 850 | for (i = 0; i < CONFIG_RBPL_SIZE; ++i) { |
| 843 | dma_addr_t dma_handle; | 851 | dma_addr_t dma_handle; |
| @@ -845,7 +853,7 @@ he_init_group(struct he_dev *he_dev, int group) | |||
| 845 | 853 | ||
| 846 | cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle); | 854 | cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle); |
| 847 | if (cpuaddr == NULL) | 855 | if (cpuaddr == NULL) |
| 848 | return -ENOMEM; | 856 | goto out_free_rbpl_virt; |
| 849 | 857 | ||
| 850 | he_dev->rbpl_virt[i].virt = cpuaddr; | 858 | he_dev->rbpl_virt[i].virt = cpuaddr; |
| 851 | he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF); | 859 | he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF); |
| @@ -870,7 +878,7 @@ he_init_group(struct he_dev *he_dev, int group) | |||
| 870 | CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys); | 878 | CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys); |
| 871 | if (he_dev->rbrq_base == NULL) { | 879 | if (he_dev->rbrq_base == NULL) { |
| 872 | hprintk("failed to allocate rbrq\n"); | 880 | hprintk("failed to allocate rbrq\n"); |
| 873 | return -ENOMEM; | 881 | goto out_free_rbpl_virt; |
| 874 | } | 882 | } |
| 875 | memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq)); | 883 | memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq)); |
| 876 | 884 | ||
| @@ -894,7 +902,7 @@ he_init_group(struct he_dev *he_dev, int group) | |||
| 894 | CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys); | 902 | CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys); |
| 895 | if (he_dev->tbrq_base == NULL) { | 903 | if (he_dev->tbrq_base == NULL) { |
| 896 | hprintk("failed to allocate tbrq\n"); | 904 | hprintk("failed to allocate tbrq\n"); |
| 897 | return -ENOMEM; | 905 | goto out_free_rbpq_base; |
| 898 | } | 906 | } |
| 899 | memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq)); | 907 | memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq)); |
| 900 | 908 | ||
| @@ -906,6 +914,39 @@ he_init_group(struct he_dev *he_dev, int group) | |||
| 906 | he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16)); | 914 | he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16)); |
| 907 | 915 | ||
| 908 | return 0; | 916 | return 0; |
| 917 | |||
| 918 | out_free_rbpq_base: | ||
| 919 | pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * | ||
| 920 | sizeof(struct he_rbrq), he_dev->rbrq_base, | ||
| 921 | he_dev->rbrq_phys); | ||
| 922 | i = CONFIG_RBPL_SIZE; | ||
| 923 | out_free_rbpl_virt: | ||
| 924 | while (--i) | ||
| 925 | pci_pool_free(he_dev->rbps_pool, he_dev->rbpl_virt[i].virt, | ||
| 926 | he_dev->rbps_base[i].phys); | ||
| 927 | kfree(he_dev->rbpl_virt); | ||
| 928 | |||
| 929 | out_free_rbpl_base: | ||
| 930 | pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE * | ||
| 931 | sizeof(struct he_rbp), he_dev->rbpl_base, | ||
| 932 | he_dev->rbpl_phys); | ||
| 933 | out_destroy_rbpl_pool: | ||
| 934 | pci_pool_destroy(he_dev->rbpl_pool); | ||
| 935 | |||
| 936 | i = CONFIG_RBPL_SIZE; | ||
| 937 | out_free_rbps_virt: | ||
| 938 | while (--i) | ||
| 939 | pci_pool_free(he_dev->rbpl_pool, he_dev->rbps_virt[i].virt, | ||
| 940 | he_dev->rbpl_base[i].phys); | ||
| 941 | kfree(he_dev->rbps_virt); | ||
| 942 | |||
| 943 | out_free_rbps_base: | ||
| 944 | pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE * | ||
| 945 | sizeof(struct he_rbp), he_dev->rbps_base, | ||
| 946 | he_dev->rbps_phys); | ||
| 947 | out_destroy_rbps_pool: | ||
| 948 | pci_pool_destroy(he_dev->rbps_pool); | ||
| 949 | return -ENOMEM; | ||
| 909 | } | 950 | } |
| 910 | 951 | ||
| 911 | static int __devinit | 952 | static int __devinit |
diff --git a/drivers/atm/solos-attrlist.c b/drivers/atm/solos-attrlist.c index efa2808dd94d..1a9332e4efe0 100644 --- a/drivers/atm/solos-attrlist.c +++ b/drivers/atm/solos-attrlist.c | |||
| @@ -25,6 +25,10 @@ SOLOS_ATTR_RO(RSCorrectedErrorsUp) | |||
| 25 | SOLOS_ATTR_RO(RSUnCorrectedErrorsUp) | 25 | SOLOS_ATTR_RO(RSUnCorrectedErrorsUp) |
| 26 | SOLOS_ATTR_RO(InterleaveRDn) | 26 | SOLOS_ATTR_RO(InterleaveRDn) |
| 27 | SOLOS_ATTR_RO(InterleaveRUp) | 27 | SOLOS_ATTR_RO(InterleaveRUp) |
| 28 | SOLOS_ATTR_RO(BisRDn) | ||
| 29 | SOLOS_ATTR_RO(BisRUp) | ||
| 30 | SOLOS_ATTR_RO(INPdown) | ||
| 31 | SOLOS_ATTR_RO(INPup) | ||
| 28 | SOLOS_ATTR_RO(ShowtimeStart) | 32 | SOLOS_ATTR_RO(ShowtimeStart) |
| 29 | SOLOS_ATTR_RO(ATURVendor) | 33 | SOLOS_ATTR_RO(ATURVendor) |
| 30 | SOLOS_ATTR_RO(ATUCCountry) | 34 | SOLOS_ATTR_RO(ATUCCountry) |
| @@ -62,6 +66,13 @@ SOLOS_ATTR_RW(Defaults) | |||
| 62 | SOLOS_ATTR_RW(LineMode) | 66 | SOLOS_ATTR_RW(LineMode) |
| 63 | SOLOS_ATTR_RW(Profile) | 67 | SOLOS_ATTR_RW(Profile) |
| 64 | SOLOS_ATTR_RW(DetectNoise) | 68 | SOLOS_ATTR_RW(DetectNoise) |
| 69 | SOLOS_ATTR_RW(BisAForceSNRMarginDn) | ||
| 70 | SOLOS_ATTR_RW(BisMForceSNRMarginDn) | ||
| 71 | SOLOS_ATTR_RW(BisAMaxMargin) | ||
| 72 | SOLOS_ATTR_RW(BisMMaxMargin) | ||
| 73 | SOLOS_ATTR_RW(AnnexAForceSNRMarginDn) | ||
| 74 | SOLOS_ATTR_RW(AnnexAMaxMargin) | ||
| 75 | SOLOS_ATTR_RW(AnnexMMaxMargin) | ||
| 65 | SOLOS_ATTR_RO(SupportedAnnexes) | 76 | SOLOS_ATTR_RO(SupportedAnnexes) |
| 66 | SOLOS_ATTR_RO(Status) | 77 | SOLOS_ATTR_RO(Status) |
| 67 | SOLOS_ATTR_RO(TotalStart) | 78 | SOLOS_ATTR_RO(TotalStart) |
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 307321b32cb3..c5f5186d62a3 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c | |||
| @@ -59,21 +59,29 @@ | |||
| 59 | #define RX_DMA_ADDR(port) (0x30 + (4 * (port))) | 59 | #define RX_DMA_ADDR(port) (0x30 + (4 * (port))) |
| 60 | 60 | ||
| 61 | #define DATA_RAM_SIZE 32768 | 61 | #define DATA_RAM_SIZE 32768 |
| 62 | #define BUF_SIZE 4096 | 62 | #define BUF_SIZE 2048 |
| 63 | #define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/ | ||
| 63 | #define FPGA_PAGE 528 /* FPGA flash page size*/ | 64 | #define FPGA_PAGE 528 /* FPGA flash page size*/ |
| 64 | #define SOLOS_PAGE 512 /* Solos flash page size*/ | 65 | #define SOLOS_PAGE 512 /* Solos flash page size*/ |
| 65 | #define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/ | 66 | #define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/ |
| 66 | #define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/ | 67 | #define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/ |
| 67 | 68 | ||
| 68 | #define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2) | 69 | #define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2) |
| 69 | #define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE) | 70 | #define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size)) |
| 71 | #define FLASH_BUF ((card->buffers) + 4*(card->buffer_size)*2) | ||
| 70 | 72 | ||
| 71 | #define RX_DMA_SIZE 2048 | 73 | #define RX_DMA_SIZE 2048 |
| 72 | 74 | ||
| 75 | #define FPGA_VERSION(a,b) (((a) << 8) + (b)) | ||
| 76 | #define LEGACY_BUFFERS 2 | ||
| 77 | #define DMA_SUPPORTED 4 | ||
| 78 | |||
| 73 | static int reset = 0; | 79 | static int reset = 0; |
| 74 | static int atmdebug = 0; | 80 | static int atmdebug = 0; |
| 75 | static int firmware_upgrade = 0; | 81 | static int firmware_upgrade = 0; |
| 76 | static int fpga_upgrade = 0; | 82 | static int fpga_upgrade = 0; |
| 83 | static int db_firmware_upgrade = 0; | ||
| 84 | static int db_fpga_upgrade = 0; | ||
| 77 | 85 | ||
| 78 | struct pkt_hdr { | 86 | struct pkt_hdr { |
| 79 | __le16 size; | 87 | __le16 size; |
| @@ -116,6 +124,8 @@ struct solos_card { | |||
| 116 | wait_queue_head_t param_wq; | 124 | wait_queue_head_t param_wq; |
| 117 | wait_queue_head_t fw_wq; | 125 | wait_queue_head_t fw_wq; |
| 118 | int using_dma; | 126 | int using_dma; |
| 127 | int fpga_version; | ||
| 128 | int buffer_size; | ||
| 119 | }; | 129 | }; |
| 120 | 130 | ||
| 121 | 131 | ||
| @@ -136,10 +146,14 @@ MODULE_PARM_DESC(reset, "Reset Solos chips on startup"); | |||
| 136 | MODULE_PARM_DESC(atmdebug, "Print ATM data"); | 146 | MODULE_PARM_DESC(atmdebug, "Print ATM data"); |
| 137 | MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade"); | 147 | MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade"); |
| 138 | MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade"); | 148 | MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade"); |
| 149 | MODULE_PARM_DESC(db_firmware_upgrade, "Initiate daughter board Solos firmware upgrade"); | ||
| 150 | MODULE_PARM_DESC(db_fpga_upgrade, "Initiate daughter board FPGA upgrade"); | ||
| 139 | module_param(reset, int, 0444); | 151 | module_param(reset, int, 0444); |
| 140 | module_param(atmdebug, int, 0644); | 152 | module_param(atmdebug, int, 0644); |
| 141 | module_param(firmware_upgrade, int, 0444); | 153 | module_param(firmware_upgrade, int, 0444); |
| 142 | module_param(fpga_upgrade, int, 0444); | 154 | module_param(fpga_upgrade, int, 0444); |
| 155 | module_param(db_firmware_upgrade, int, 0444); | ||
| 156 | module_param(db_fpga_upgrade, int, 0444); | ||
| 143 | 157 | ||
| 144 | static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, | 158 | static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, |
| 145 | struct atm_vcc *vcc); | 159 | struct atm_vcc *vcc); |
| @@ -517,10 +531,32 @@ static int flash_upgrade(struct solos_card *card, int chip) | |||
| 517 | if (chip == 0) { | 531 | if (chip == 0) { |
| 518 | fw_name = "solos-FPGA.bin"; | 532 | fw_name = "solos-FPGA.bin"; |
| 519 | blocksize = FPGA_BLOCK; | 533 | blocksize = FPGA_BLOCK; |
| 520 | } else { | 534 | } |
| 535 | |||
| 536 | if (chip == 1) { | ||
| 521 | fw_name = "solos-Firmware.bin"; | 537 | fw_name = "solos-Firmware.bin"; |
| 522 | blocksize = SOLOS_BLOCK; | 538 | blocksize = SOLOS_BLOCK; |
| 523 | } | 539 | } |
| 540 | |||
| 541 | if (chip == 2){ | ||
| 542 | if (card->fpga_version > LEGACY_BUFFERS){ | ||
| 543 | fw_name = "solos-db-FPGA.bin"; | ||
| 544 | blocksize = FPGA_BLOCK; | ||
| 545 | } else { | ||
| 546 | dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n"); | ||
| 547 | return -EPERM; | ||
| 548 | } | ||
| 549 | } | ||
| 550 | |||
| 551 | if (chip == 3){ | ||
| 552 | if (card->fpga_version > LEGACY_BUFFERS){ | ||
| 553 | fw_name = "solos-Firmware.bin"; | ||
| 554 | blocksize = SOLOS_BLOCK; | ||
| 555 | } else { | ||
| 556 | dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n"); | ||
| 557 | return -EPERM; | ||
| 558 | } | ||
| 559 | } | ||
| 524 | 560 | ||
| 525 | if (request_firmware(&fw, fw_name, &card->dev->dev)) | 561 | if (request_firmware(&fw, fw_name, &card->dev->dev)) |
| 526 | return -ENOENT; | 562 | return -ENOENT; |
| @@ -536,8 +572,10 @@ static int flash_upgrade(struct solos_card *card, int chip) | |||
| 536 | data32 = ioread32(card->config_regs + FPGA_MODE); | 572 | data32 = ioread32(card->config_regs + FPGA_MODE); |
| 537 | 573 | ||
| 538 | /* Set mode to Chip Erase */ | 574 | /* Set mode to Chip Erase */ |
| 539 | dev_info(&card->dev->dev, "Set FPGA Flash mode to %s Chip Erase\n", | 575 | if(chip == 0 || chip == 2) |
| 540 | chip?"Solos":"FPGA"); | 576 | dev_info(&card->dev->dev, "Set FPGA Flash mode to FPGA Chip Erase\n"); |
| 577 | if(chip == 1 || chip == 3) | ||
| 578 | dev_info(&card->dev->dev, "Set FPGA Flash mode to Solos Chip Erase\n"); | ||
| 541 | iowrite32((chip * 2), card->config_regs + FLASH_MODE); | 579 | iowrite32((chip * 2), card->config_regs + FLASH_MODE); |
| 542 | 580 | ||
| 543 | 581 | ||
| @@ -557,7 +595,10 @@ static int flash_upgrade(struct solos_card *card, int chip) | |||
| 557 | /* Copy block to buffer, swapping each 16 bits */ | 595 | /* Copy block to buffer, swapping each 16 bits */ |
| 558 | for(i = 0; i < blocksize; i += 4) { | 596 | for(i = 0; i < blocksize; i += 4) { |
| 559 | uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i)); | 597 | uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i)); |
| 560 | iowrite32(word, RX_BUF(card, 3) + i); | 598 | if(card->fpga_version > LEGACY_BUFFERS) |
| 599 | iowrite32(word, FLASH_BUF + i); | ||
| 600 | else | ||
| 601 | iowrite32(word, RX_BUF(card, 3) + i); | ||
| 561 | } | 602 | } |
| 562 | 603 | ||
| 563 | /* Specify block number and then trigger flash write */ | 604 | /* Specify block number and then trigger flash write */ |
| @@ -630,6 +671,10 @@ void solos_bh(unsigned long card_arg) | |||
| 630 | memcpy_fromio(header, RX_BUF(card, port), sizeof(*header)); | 671 | memcpy_fromio(header, RX_BUF(card, port), sizeof(*header)); |
| 631 | 672 | ||
| 632 | size = le16_to_cpu(header->size); | 673 | size = le16_to_cpu(header->size); |
| 674 | if (size > (card->buffer_size - sizeof(*header))){ | ||
| 675 | dev_warn(&card->dev->dev, "Invalid buffer size\n"); | ||
| 676 | continue; | ||
| 677 | } | ||
| 633 | 678 | ||
| 634 | skb = alloc_skb(size + 1, GFP_ATOMIC); | 679 | skb = alloc_skb(size + 1, GFP_ATOMIC); |
| 635 | if (!skb) { | 680 | if (!skb) { |
| @@ -1094,12 +1139,18 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 1094 | fpga_ver = (data32 & 0x0000FFFF); | 1139 | fpga_ver = (data32 & 0x0000FFFF); |
| 1095 | major_ver = ((data32 & 0xFF000000) >> 24); | 1140 | major_ver = ((data32 & 0xFF000000) >> 24); |
| 1096 | minor_ver = ((data32 & 0x00FF0000) >> 16); | 1141 | minor_ver = ((data32 & 0x00FF0000) >> 16); |
| 1142 | card->fpga_version = FPGA_VERSION(major_ver,minor_ver); | ||
| 1143 | if (card->fpga_version > LEGACY_BUFFERS) | ||
| 1144 | card->buffer_size = BUF_SIZE; | ||
| 1145 | else | ||
| 1146 | card->buffer_size = OLD_BUF_SIZE; | ||
| 1097 | dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n", | 1147 | dev_info(&dev->dev, "Solos FPGA Version %d.%02d svn-%d\n", |
| 1098 | major_ver, minor_ver, fpga_ver); | 1148 | major_ver, minor_ver, fpga_ver); |
| 1099 | 1149 | ||
| 1100 | if (0 && fpga_ver > 27) | 1150 | if (card->fpga_version >= DMA_SUPPORTED){ |
| 1101 | card->using_dma = 1; | 1151 | card->using_dma = 1; |
| 1102 | else { | 1152 | } else { |
| 1153 | card->using_dma = 0; | ||
| 1103 | /* Set RX empty flag for all ports */ | 1154 | /* Set RX empty flag for all ports */ |
| 1104 | iowrite32(0xF0, card->config_regs + FLAGS_ADDR); | 1155 | iowrite32(0xF0, card->config_regs + FLAGS_ADDR); |
| 1105 | } | 1156 | } |
| @@ -1131,6 +1182,12 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 1131 | if (firmware_upgrade) | 1182 | if (firmware_upgrade) |
| 1132 | flash_upgrade(card, 1); | 1183 | flash_upgrade(card, 1); |
| 1133 | 1184 | ||
| 1185 | if (db_fpga_upgrade) | ||
| 1186 | flash_upgrade(card, 2); | ||
| 1187 | |||
| 1188 | if (db_firmware_upgrade) | ||
| 1189 | flash_upgrade(card, 3); | ||
| 1190 | |||
| 1134 | err = atm_init(card); | 1191 | err = atm_init(card); |
| 1135 | if (err) | 1192 | if (err) |
| 1136 | goto out_free_irq; | 1193 | goto out_free_irq; |
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 7adff4d0960d..b9eeadf01b74 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c | |||
| @@ -813,10 +813,10 @@ static int vortex_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 813 | if (netif_running(dev)) { | 813 | if (netif_running(dev)) { |
| 814 | netif_device_detach(dev); | 814 | netif_device_detach(dev); |
| 815 | vortex_down(dev, 1); | 815 | vortex_down(dev, 1); |
| 816 | disable_irq(dev->irq); | ||
| 816 | } | 817 | } |
| 817 | pci_save_state(pdev); | 818 | pci_save_state(pdev); |
| 818 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | 819 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); |
| 819 | free_irq(dev->irq, dev); | ||
| 820 | pci_disable_device(pdev); | 820 | pci_disable_device(pdev); |
| 821 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 821 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); |
| 822 | } | 822 | } |
| @@ -839,18 +839,12 @@ static int vortex_resume(struct pci_dev *pdev) | |||
| 839 | return err; | 839 | return err; |
| 840 | } | 840 | } |
| 841 | pci_set_master(pdev); | 841 | pci_set_master(pdev); |
| 842 | if (request_irq(dev->irq, vp->full_bus_master_rx ? | ||
| 843 | &boomerang_interrupt : &vortex_interrupt, IRQF_SHARED, dev->name, dev)) { | ||
| 844 | pr_warning("%s: Could not reserve IRQ %d\n", dev->name, dev->irq); | ||
| 845 | pci_disable_device(pdev); | ||
| 846 | return -EBUSY; | ||
| 847 | } | ||
| 848 | if (netif_running(dev)) { | 842 | if (netif_running(dev)) { |
| 849 | err = vortex_up(dev); | 843 | err = vortex_up(dev); |
| 850 | if (err) | 844 | if (err) |
| 851 | return err; | 845 | return err; |
| 852 | else | 846 | enable_irq(dev->irq); |
| 853 | netif_device_attach(dev); | 847 | netif_device_attach(dev); |
| 854 | } | 848 | } |
| 855 | } | 849 | } |
| 856 | return 0; | 850 | return 0; |
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 462d9f59c53a..83a1922e68e0 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c | |||
| @@ -87,7 +87,7 @@ | |||
| 87 | 87 | ||
| 88 | /* These identify the driver base version and may not be removed. */ | 88 | /* These identify the driver base version and may not be removed. */ |
| 89 | static char version[] = | 89 | static char version[] = |
| 90 | KERN_INFO DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; | 90 | DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; |
| 91 | 91 | ||
| 92 | MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>"); | 92 | MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>"); |
| 93 | MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver"); | 93 | MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver"); |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ed5741b2e701..2bea67c134f0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -1875,7 +1875,7 @@ config 68360_ENET | |||
| 1875 | 1875 | ||
| 1876 | config FEC | 1876 | config FEC |
| 1877 | bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" | 1877 | bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" |
| 1878 | depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35 | 1878 | depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35 || ARCH_MX25 |
| 1879 | help | 1879 | help |
| 1880 | Say Y here if you want to use the built-in 10/100 Fast ethernet | 1880 | Say Y here if you want to use the built-in 10/100 Fast ethernet |
| 1881 | controller on some Motorola ColdFire and Freescale i.MX processors. | 1881 | controller on some Motorola ColdFire and Freescale i.MX processors. |
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index be2c6cfe6e84..1372e9a99f5b 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c | |||
| @@ -2296,7 +2296,7 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 2296 | u32 ctrl; | 2296 | u32 ctrl; |
| 2297 | u32 mac_ctrl_data; | 2297 | u32 mac_ctrl_data; |
| 2298 | u32 master_ctrl_data; | 2298 | u32 master_ctrl_data; |
| 2299 | u32 wol_ctrl_data; | 2299 | u32 wol_ctrl_data = 0; |
| 2300 | u16 mii_bmsr_data; | 2300 | u16 mii_bmsr_data; |
| 2301 | u16 save_autoneg_advertised; | 2301 | u16 save_autoneg_advertised; |
| 2302 | u16 mii_intr_status_data; | 2302 | u16 mii_intr_status_data; |
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 090074372462..df32c109b7ac 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig | |||
| @@ -75,6 +75,13 @@ config CAN_EMS_PCI | |||
| 75 | CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche | 75 | CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche |
| 76 | (http://www.ems-wuensche.de). | 76 | (http://www.ems-wuensche.de). |
| 77 | 77 | ||
| 78 | config CAN_EMS_USB | ||
| 79 | tristate "EMS CPC-USB/ARM7 CAN/USB interface" | ||
| 80 | depends on USB && CAN_DEV | ||
| 81 | ---help--- | ||
| 82 | This driver is for the one channel CPC-USB/ARM7 CAN/USB interface | ||
| 83 | from from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). | ||
| 84 | |||
| 78 | config CAN_KVASER_PCI | 85 | config CAN_KVASER_PCI |
| 79 | tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" | 86 | tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" |
| 80 | depends on PCI && CAN_SJA1000 | 87 | depends on PCI && CAN_SJA1000 |
| @@ -82,6 +89,12 @@ config CAN_KVASER_PCI | |||
| 82 | This driver is for the the PCIcanx and PCIcan cards (1, 2 or | 89 | This driver is for the the PCIcanx and PCIcan cards (1, 2 or |
| 83 | 4 channel) from Kvaser (http://www.kvaser.com). | 90 | 4 channel) from Kvaser (http://www.kvaser.com). |
| 84 | 91 | ||
| 92 | config CAN_AT91 | ||
| 93 | tristate "Atmel AT91 onchip CAN controller" | ||
| 94 | depends on CAN && CAN_DEV && ARCH_AT91SAM9263 | ||
| 95 | ---help--- | ||
| 96 | This is a driver for the SoC CAN controller in Atmel's AT91SAM9263. | ||
| 97 | |||
| 85 | config CAN_DEBUG_DEVICES | 98 | config CAN_DEBUG_DEVICES |
| 86 | bool "CAN devices debugging messages" | 99 | bool "CAN devices debugging messages" |
| 87 | depends on CAN | 100 | depends on CAN |
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index 523a941b358b..0dea62721f2f 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile | |||
| @@ -7,6 +7,9 @@ obj-$(CONFIG_CAN_VCAN) += vcan.o | |||
| 7 | obj-$(CONFIG_CAN_DEV) += can-dev.o | 7 | obj-$(CONFIG_CAN_DEV) += can-dev.o |
| 8 | can-dev-y := dev.o | 8 | can-dev-y := dev.o |
| 9 | 9 | ||
| 10 | obj-y += usb/ | ||
| 11 | |||
| 10 | obj-$(CONFIG_CAN_SJA1000) += sja1000/ | 12 | obj-$(CONFIG_CAN_SJA1000) += sja1000/ |
| 13 | obj-$(CONFIG_CAN_AT91) += at91_can.o | ||
| 11 | 14 | ||
| 12 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG | 15 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG |
diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c index 7d84b8ac9c1c..fd04789d3370 100644 --- a/drivers/net/can/sja1000/ems_pci.c +++ b/drivers/net/can/sja1000/ems_pci.c | |||
| @@ -94,12 +94,14 @@ struct ems_pci_card { | |||
| 94 | #define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) | 94 | #define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) |
| 95 | 95 | ||
| 96 | #define EMS_PCI_V1_BASE_BAR 1 | 96 | #define EMS_PCI_V1_BASE_BAR 1 |
| 97 | #define EMS_PCI_V1_MEM_SIZE 4096 | 97 | #define EMS_PCI_V1_CONF_SIZE 4096 /* size of PITA control area */ |
| 98 | #define EMS_PCI_V2_BASE_BAR 2 | 98 | #define EMS_PCI_V2_BASE_BAR 2 |
| 99 | #define EMS_PCI_V2_MEM_SIZE 128 | 99 | #define EMS_PCI_V2_CONF_SIZE 128 /* size of PLX control area */ |
| 100 | #define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */ | 100 | #define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */ |
| 101 | #define EMS_PCI_CAN_CTRL_SIZE 0x200 /* memory size for each controller */ | 101 | #define EMS_PCI_CAN_CTRL_SIZE 0x200 /* memory size for each controller */ |
| 102 | 102 | ||
| 103 | #define EMS_PCI_BASE_SIZE 4096 /* size of controller area */ | ||
| 104 | |||
| 103 | static struct pci_device_id ems_pci_tbl[] = { | 105 | static struct pci_device_id ems_pci_tbl[] = { |
| 104 | /* CPC-PCI v1 */ | 106 | /* CPC-PCI v1 */ |
| 105 | {PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,}, | 107 | {PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,}, |
| @@ -224,7 +226,7 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev, | |||
| 224 | struct sja1000_priv *priv; | 226 | struct sja1000_priv *priv; |
| 225 | struct net_device *dev; | 227 | struct net_device *dev; |
| 226 | struct ems_pci_card *card; | 228 | struct ems_pci_card *card; |
| 227 | int max_chan, mem_size, base_bar; | 229 | int max_chan, conf_size, base_bar; |
| 228 | int err, i; | 230 | int err, i; |
| 229 | 231 | ||
| 230 | /* Enabling PCI device */ | 232 | /* Enabling PCI device */ |
| @@ -251,22 +253,22 @@ static int __devinit ems_pci_add_card(struct pci_dev *pdev, | |||
| 251 | card->version = 2; /* CPC-PCI v2 */ | 253 | card->version = 2; /* CPC-PCI v2 */ |
| 252 | max_chan = EMS_PCI_V2_MAX_CHAN; | 254 | max_chan = EMS_PCI_V2_MAX_CHAN; |
| 253 | base_bar = EMS_PCI_V2_BASE_BAR; | 255 | base_bar = EMS_PCI_V2_BASE_BAR; |
| 254 | mem_size = EMS_PCI_V2_MEM_SIZE; | 256 | conf_size = EMS_PCI_V2_CONF_SIZE; |
| 255 | } else { | 257 | } else { |
| 256 | card->version = 1; /* CPC-PCI v1 */ | 258 | card->version = 1; /* CPC-PCI v1 */ |
| 257 | max_chan = EMS_PCI_V1_MAX_CHAN; | 259 | max_chan = EMS_PCI_V1_MAX_CHAN; |
| 258 | base_bar = EMS_PCI_V1_BASE_BAR; | 260 | base_bar = EMS_PCI_V1_BASE_BAR; |
| 259 | mem_size = EMS_PCI_V1_MEM_SIZE; | 261 | conf_size = EMS_PCI_V1_CONF_SIZE; |
| 260 | } | 262 | } |
| 261 | 263 | ||
| 262 | /* Remap configuration space and controller memory area */ | 264 | /* Remap configuration space and controller memory area */ |
| 263 | card->conf_addr = pci_iomap(pdev, 0, mem_size); | 265 | card->conf_addr = pci_iomap(pdev, 0, conf_size); |
| 264 | if (card->conf_addr == NULL) { | 266 | if (card->conf_addr == NULL) { |
| 265 | err = -ENOMEM; | 267 | err = -ENOMEM; |
| 266 | goto failure_cleanup; | 268 | goto failure_cleanup; |
| 267 | } | 269 | } |
| 268 | 270 | ||
| 269 | card->base_addr = pci_iomap(pdev, base_bar, mem_size); | 271 | card->base_addr = pci_iomap(pdev, base_bar, EMS_PCI_BASE_SIZE); |
| 270 | if (card->base_addr == NULL) { | 272 | if (card->base_addr == NULL) { |
| 271 | err = -ENOMEM; | 273 | err = -ENOMEM; |
| 272 | goto failure_cleanup; | 274 | goto failure_cleanup; |
diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile new file mode 100644 index 000000000000..c3f75ba701b1 --- /dev/null +++ b/drivers/net/can/usb/Makefile | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | # | ||
| 2 | # Makefile for the Linux Controller Area Network USB drivers. | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o | ||
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c new file mode 100644 index 000000000000..9012e0abc626 --- /dev/null +++ b/drivers/net/can/usb/ems_usb.c | |||
| @@ -0,0 +1,1155 @@ | |||
| 1 | /* | ||
| 2 | * CAN driver for EMS Dr. Thomas Wuensche CPC-USB/ARM7 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published | ||
| 8 | * by the Free Software Foundation; version 2 of the License. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, but | ||
| 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | * General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License along | ||
| 16 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | */ | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/signal.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/netdevice.h> | ||
| 24 | #include <linux/usb.h> | ||
| 25 | |||
| 26 | #include <linux/can.h> | ||
| 27 | #include <linux/can/dev.h> | ||
| 28 | #include <linux/can/error.h> | ||
| 29 | |||
| 30 | MODULE_AUTHOR("Sebastian Haas <haas@ems-wuensche.com>"); | ||
| 31 | MODULE_DESCRIPTION("CAN driver for EMS Dr. Thomas Wuensche CAN/USB interfaces"); | ||
| 32 | MODULE_LICENSE("GPL v2"); | ||
| 33 | |||
| 34 | /* Control-Values for CPC_Control() Command Subject Selection */ | ||
| 35 | #define CONTR_CAN_MESSAGE 0x04 | ||
| 36 | #define CONTR_CAN_STATE 0x0C | ||
| 37 | #define CONTR_BUS_ERROR 0x1C | ||
| 38 | |||
| 39 | /* Control Command Actions */ | ||
| 40 | #define CONTR_CONT_OFF 0 | ||
| 41 | #define CONTR_CONT_ON 1 | ||
| 42 | #define CONTR_ONCE 2 | ||
| 43 | |||
| 44 | /* Messages from CPC to PC */ | ||
| 45 | #define CPC_MSG_TYPE_CAN_FRAME 1 /* CAN data frame */ | ||
| 46 | #define CPC_MSG_TYPE_RTR_FRAME 8 /* CAN remote frame */ | ||
| 47 | #define CPC_MSG_TYPE_CAN_PARAMS 12 /* Actual CAN parameters */ | ||
| 48 | #define CPC_MSG_TYPE_CAN_STATE 14 /* CAN state message */ | ||
| 49 | #define CPC_MSG_TYPE_EXT_CAN_FRAME 16 /* Extended CAN data frame */ | ||
| 50 | #define CPC_MSG_TYPE_EXT_RTR_FRAME 17 /* Extended remote frame */ | ||
| 51 | #define CPC_MSG_TYPE_CONTROL 19 /* change interface behavior */ | ||
| 52 | #define CPC_MSG_TYPE_CONFIRM 20 /* command processed confirmation */ | ||
| 53 | #define CPC_MSG_TYPE_OVERRUN 21 /* overrun events */ | ||
| 54 | #define CPC_MSG_TYPE_CAN_FRAME_ERROR 23 /* detected bus errors */ | ||
| 55 | #define CPC_MSG_TYPE_ERR_COUNTER 25 /* RX/TX error counter */ | ||
| 56 | |||
| 57 | /* Messages from the PC to the CPC interface */ | ||
| 58 | #define CPC_CMD_TYPE_CAN_FRAME 1 /* CAN data frame */ | ||
| 59 | #define CPC_CMD_TYPE_CONTROL 3 /* control of interface behavior */ | ||
| 60 | #define CPC_CMD_TYPE_CAN_PARAMS 6 /* set CAN parameters */ | ||
| 61 | #define CPC_CMD_TYPE_RTR_FRAME 13 /* CAN remote frame */ | ||
| 62 | #define CPC_CMD_TYPE_CAN_STATE 14 /* CAN state message */ | ||
| 63 | #define CPC_CMD_TYPE_EXT_CAN_FRAME 15 /* Extended CAN data frame */ | ||
| 64 | #define CPC_CMD_TYPE_EXT_RTR_FRAME 16 /* Extended CAN remote frame */ | ||
| 65 | #define CPC_CMD_TYPE_CAN_EXIT 200 /* exit the CAN */ | ||
| 66 | |||
| 67 | #define CPC_CMD_TYPE_INQ_ERR_COUNTER 25 /* request the CAN error counters */ | ||
| 68 | #define CPC_CMD_TYPE_CLEAR_MSG_QUEUE 8 /* clear CPC_MSG queue */ | ||
| 69 | #define CPC_CMD_TYPE_CLEAR_CMD_QUEUE 28 /* clear CPC_CMD queue */ | ||
| 70 | |||
| 71 | #define CPC_CC_TYPE_SJA1000 2 /* Philips basic CAN controller */ | ||
| 72 | |||
| 73 | #define CPC_CAN_ECODE_ERRFRAME 0x01 /* Ecode type */ | ||
| 74 | |||
| 75 | /* Overrun types */ | ||
| 76 | #define CPC_OVR_EVENT_CAN 0x01 | ||
| 77 | #define CPC_OVR_EVENT_CANSTATE 0x02 | ||
| 78 | #define CPC_OVR_EVENT_BUSERROR 0x04 | ||
| 79 | |||
| 80 | /* | ||
| 81 | * If the CAN controller lost a message we indicate it with the highest bit | ||
| 82 | * set in the count field. | ||
| 83 | */ | ||
| 84 | #define CPC_OVR_HW 0x80 | ||
| 85 | |||
| 86 | /* Size of the "struct ems_cpc_msg" without the union */ | ||
| 87 | #define CPC_MSG_HEADER_LEN 11 | ||
| 88 | #define CPC_CAN_MSG_MIN_SIZE 5 | ||
| 89 | |||
| 90 | /* Define these values to match your devices */ | ||
| 91 | #define USB_CPCUSB_VENDOR_ID 0x12D6 | ||
| 92 | |||
| 93 | #define USB_CPCUSB_ARM7_PRODUCT_ID 0x0444 | ||
| 94 | |||
| 95 | /* Mode register NXP LPC2119/SJA1000 CAN Controller */ | ||
| 96 | #define SJA1000_MOD_NORMAL 0x00 | ||
| 97 | #define SJA1000_MOD_RM 0x01 | ||
| 98 | |||
| 99 | /* ECC register NXP LPC2119/SJA1000 CAN Controller */ | ||
| 100 | #define SJA1000_ECC_SEG 0x1F | ||
| 101 | #define SJA1000_ECC_DIR 0x20 | ||
| 102 | #define SJA1000_ECC_ERR 0x06 | ||
| 103 | #define SJA1000_ECC_BIT 0x00 | ||
| 104 | #define SJA1000_ECC_FORM 0x40 | ||
| 105 | #define SJA1000_ECC_STUFF 0x80 | ||
| 106 | #define SJA1000_ECC_MASK 0xc0 | ||
| 107 | |||
| 108 | /* Status register content */ | ||
| 109 | #define SJA1000_SR_BS 0x80 | ||
| 110 | #define SJA1000_SR_ES 0x40 | ||
| 111 | |||
| 112 | #define SJA1000_DEFAULT_OUTPUT_CONTROL 0xDA | ||
| 113 | |||
| 114 | /* | ||
| 115 | * The device actually uses a 16MHz clock to generate the CAN clock | ||
| 116 | * but it expects SJA1000 bit settings based on 8MHz (is internally | ||
| 117 | * converted). | ||
| 118 | */ | ||
| 119 | #define EMS_USB_ARM7_CLOCK 8000000 | ||
| 120 | |||
| 121 | /* | ||
| 122 | * CAN-Message representation in a CPC_MSG. Message object type is | ||
| 123 | * CPC_MSG_TYPE_CAN_FRAME or CPC_MSG_TYPE_RTR_FRAME or | ||
| 124 | * CPC_MSG_TYPE_EXT_CAN_FRAME or CPC_MSG_TYPE_EXT_RTR_FRAME. | ||
| 125 | */ | ||
| 126 | struct cpc_can_msg { | ||
| 127 | u32 id; | ||
| 128 | u8 length; | ||
| 129 | u8 msg[8]; | ||
| 130 | }; | ||
| 131 | |||
| 132 | /* Representation of the CAN parameters for the SJA1000 controller */ | ||
| 133 | struct cpc_sja1000_params { | ||
| 134 | u8 mode; | ||
| 135 | u8 acc_code0; | ||
| 136 | u8 acc_code1; | ||
| 137 | u8 acc_code2; | ||
| 138 | u8 acc_code3; | ||
| 139 | u8 acc_mask0; | ||
| 140 | u8 acc_mask1; | ||
| 141 | u8 acc_mask2; | ||
| 142 | u8 acc_mask3; | ||
| 143 | u8 btr0; | ||
| 144 | u8 btr1; | ||
| 145 | u8 outp_contr; | ||
| 146 | }; | ||
| 147 | |||
| 148 | /* CAN params message representation */ | ||
| 149 | struct cpc_can_params { | ||
| 150 | u8 cc_type; | ||
| 151 | |||
| 152 | /* Will support M16C CAN controller in the future */ | ||
| 153 | union { | ||
| 154 | struct cpc_sja1000_params sja1000; | ||
| 155 | } cc_params; | ||
| 156 | }; | ||
| 157 | |||
| 158 | /* Structure for confirmed message handling */ | ||
| 159 | struct cpc_confirm { | ||
| 160 | u8 error; /* error code */ | ||
| 161 | }; | ||
| 162 | |||
| 163 | /* Structure for overrun conditions */ | ||
| 164 | struct cpc_overrun { | ||
| 165 | u8 event; | ||
| 166 | u8 count; | ||
| 167 | }; | ||
| 168 | |||
| 169 | /* SJA1000 CAN errors (compatible to NXP LPC2119) */ | ||
| 170 | struct cpc_sja1000_can_error { | ||
| 171 | u8 ecc; | ||
| 172 | u8 rxerr; | ||
| 173 | u8 txerr; | ||
| 174 | }; | ||
| 175 | |||
| 176 | /* structure for CAN error conditions */ | ||
| 177 | struct cpc_can_error { | ||
| 178 | u8 ecode; | ||
| 179 | |||
| 180 | struct { | ||
| 181 | u8 cc_type; | ||
| 182 | |||
| 183 | /* Other controllers may also provide error code capture regs */ | ||
| 184 | union { | ||
| 185 | struct cpc_sja1000_can_error sja1000; | ||
| 186 | } regs; | ||
| 187 | } cc; | ||
| 188 | }; | ||
| 189 | |||
| 190 | /* | ||
| 191 | * Structure containing RX/TX error counter. This structure is used to request | ||
| 192 | * the values of the CAN controllers TX and RX error counter. | ||
| 193 | */ | ||
| 194 | struct cpc_can_err_counter { | ||
| 195 | u8 rx; | ||
| 196 | u8 tx; | ||
| 197 | }; | ||
| 198 | |||
| 199 | /* Main message type used between library and application */ | ||
| 200 | struct __attribute__ ((packed)) ems_cpc_msg { | ||
| 201 | u8 type; /* type of message */ | ||
| 202 | u8 length; /* length of data within union 'msg' */ | ||
| 203 | u8 msgid; /* confirmation handle */ | ||
| 204 | u32 ts_sec; /* timestamp in seconds */ | ||
| 205 | u32 ts_nsec; /* timestamp in nano seconds */ | ||
| 206 | |||
| 207 | union { | ||
| 208 | u8 generic[64]; | ||
| 209 | struct cpc_can_msg can_msg; | ||
| 210 | struct cpc_can_params can_params; | ||
| 211 | struct cpc_confirm confirmation; | ||
| 212 | struct cpc_overrun overrun; | ||
| 213 | struct cpc_can_error error; | ||
| 214 | struct cpc_can_err_counter err_counter; | ||
| 215 | u8 can_state; | ||
| 216 | } msg; | ||
| 217 | }; | ||
| 218 | |||
| 219 | /* | ||
| 220 | * Table of devices that work with this driver | ||
| 221 | * NOTE: This driver supports only CPC-USB/ARM7 (LPC2119) yet. | ||
| 222 | */ | ||
| 223 | static struct usb_device_id ems_usb_table[] = { | ||
| 224 | {USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_ARM7_PRODUCT_ID)}, | ||
| 225 | {} /* Terminating entry */ | ||
| 226 | }; | ||
| 227 | |||
| 228 | MODULE_DEVICE_TABLE(usb, ems_usb_table); | ||
| 229 | |||
| 230 | #define RX_BUFFER_SIZE 64 | ||
| 231 | #define CPC_HEADER_SIZE 4 | ||
| 232 | #define INTR_IN_BUFFER_SIZE 4 | ||
| 233 | |||
| 234 | #define MAX_RX_URBS 10 | ||
| 235 | #define MAX_TX_URBS CAN_ECHO_SKB_MAX | ||
| 236 | |||
| 237 | struct ems_usb; | ||
| 238 | |||
| 239 | struct ems_tx_urb_context { | ||
| 240 | struct ems_usb *dev; | ||
| 241 | |||
| 242 | u32 echo_index; | ||
| 243 | u8 dlc; | ||
| 244 | }; | ||
| 245 | |||
| 246 | struct ems_usb { | ||
| 247 | struct can_priv can; /* must be the first member */ | ||
| 248 | int open_time; | ||
| 249 | |||
| 250 | struct sk_buff *echo_skb[MAX_TX_URBS]; | ||
| 251 | |||
| 252 | struct usb_device *udev; | ||
| 253 | struct net_device *netdev; | ||
| 254 | |||
| 255 | atomic_t active_tx_urbs; | ||
| 256 | struct usb_anchor tx_submitted; | ||
| 257 | struct ems_tx_urb_context tx_contexts[MAX_TX_URBS]; | ||
| 258 | |||
| 259 | struct usb_anchor rx_submitted; | ||
| 260 | |||
| 261 | struct urb *intr_urb; | ||
| 262 | |||
| 263 | u8 *tx_msg_buffer; | ||
| 264 | |||
| 265 | u8 *intr_in_buffer; | ||
| 266 | unsigned int free_slots; /* remember number of available slots */ | ||
| 267 | |||
| 268 | struct ems_cpc_msg active_params; /* active controller parameters */ | ||
| 269 | }; | ||
| 270 | |||
| 271 | static void ems_usb_read_interrupt_callback(struct urb *urb) | ||
| 272 | { | ||
| 273 | struct ems_usb *dev = urb->context; | ||
| 274 | struct net_device *netdev = dev->netdev; | ||
| 275 | int err; | ||
| 276 | |||
| 277 | if (!netif_device_present(netdev)) | ||
| 278 | return; | ||
| 279 | |||
| 280 | switch (urb->status) { | ||
| 281 | case 0: | ||
| 282 | dev->free_slots = dev->intr_in_buffer[1]; | ||
| 283 | break; | ||
| 284 | |||
| 285 | case -ECONNRESET: /* unlink */ | ||
| 286 | case -ENOENT: | ||
| 287 | case -ESHUTDOWN: | ||
| 288 | return; | ||
| 289 | |||
| 290 | default: | ||
| 291 | dev_info(netdev->dev.parent, "Rx interrupt aborted %d\n", | ||
| 292 | urb->status); | ||
| 293 | break; | ||
| 294 | } | ||
| 295 | |||
| 296 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 297 | |||
| 298 | if (err == -ENODEV) | ||
| 299 | netif_device_detach(netdev); | ||
| 300 | else if (err) | ||
| 301 | dev_err(netdev->dev.parent, | ||
| 302 | "failed resubmitting intr urb: %d\n", err); | ||
| 303 | |||
| 304 | return; | ||
| 305 | } | ||
| 306 | |||
| 307 | static void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg) | ||
| 308 | { | ||
| 309 | struct can_frame *cf; | ||
| 310 | struct sk_buff *skb; | ||
| 311 | int i; | ||
| 312 | struct net_device_stats *stats = &dev->netdev->stats; | ||
| 313 | |||
| 314 | skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame)); | ||
| 315 | if (skb == NULL) | ||
| 316 | return; | ||
| 317 | |||
| 318 | skb->protocol = htons(ETH_P_CAN); | ||
| 319 | |||
| 320 | cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); | ||
| 321 | |||
| 322 | cf->can_id = msg->msg.can_msg.id; | ||
| 323 | cf->can_dlc = min_t(u8, msg->msg.can_msg.length, 8); | ||
| 324 | |||
| 325 | if (msg->type == CPC_MSG_TYPE_EXT_CAN_FRAME | ||
| 326 | || msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME) | ||
| 327 | cf->can_id |= CAN_EFF_FLAG; | ||
| 328 | |||
| 329 | if (msg->type == CPC_MSG_TYPE_RTR_FRAME | ||
| 330 | || msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME) { | ||
| 331 | cf->can_id |= CAN_RTR_FLAG; | ||
| 332 | } else { | ||
| 333 | for (i = 0; i < cf->can_dlc; i++) | ||
| 334 | cf->data[i] = msg->msg.can_msg.msg[i]; | ||
| 335 | } | ||
| 336 | |||
| 337 | netif_rx(skb); | ||
| 338 | |||
| 339 | stats->rx_packets++; | ||
| 340 | stats->rx_bytes += cf->can_dlc; | ||
| 341 | } | ||
| 342 | |||
| 343 | static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg) | ||
| 344 | { | ||
| 345 | struct can_frame *cf; | ||
| 346 | struct sk_buff *skb; | ||
| 347 | struct net_device_stats *stats = &dev->netdev->stats; | ||
| 348 | |||
| 349 | skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame)); | ||
| 350 | if (skb == NULL) | ||
| 351 | return; | ||
| 352 | |||
| 353 | skb->protocol = htons(ETH_P_CAN); | ||
| 354 | |||
| 355 | cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); | ||
| 356 | memset(cf, 0, sizeof(struct can_frame)); | ||
| 357 | |||
| 358 | cf->can_id = CAN_ERR_FLAG; | ||
| 359 | cf->can_dlc = CAN_ERR_DLC; | ||
| 360 | |||
| 361 | if (msg->type == CPC_MSG_TYPE_CAN_STATE) { | ||
| 362 | u8 state = msg->msg.can_state; | ||
| 363 | |||
| 364 | if (state & SJA1000_SR_BS) { | ||
| 365 | dev->can.state = CAN_STATE_BUS_OFF; | ||
| 366 | cf->can_id |= CAN_ERR_BUSOFF; | ||
| 367 | |||
| 368 | can_bus_off(dev->netdev); | ||
| 369 | } else if (state & SJA1000_SR_ES) { | ||
| 370 | dev->can.state = CAN_STATE_ERROR_WARNING; | ||
| 371 | dev->can.can_stats.error_warning++; | ||
| 372 | } else { | ||
| 373 | dev->can.state = CAN_STATE_ERROR_ACTIVE; | ||
| 374 | dev->can.can_stats.error_passive++; | ||
| 375 | } | ||
| 376 | } else if (msg->type == CPC_MSG_TYPE_CAN_FRAME_ERROR) { | ||
| 377 | u8 ecc = msg->msg.error.cc.regs.sja1000.ecc; | ||
| 378 | u8 txerr = msg->msg.error.cc.regs.sja1000.txerr; | ||
| 379 | u8 rxerr = msg->msg.error.cc.regs.sja1000.rxerr; | ||
| 380 | |||
| 381 | /* bus error interrupt */ | ||
| 382 | dev->can.can_stats.bus_error++; | ||
| 383 | stats->rx_errors++; | ||
| 384 | |||
| 385 | cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; | ||
| 386 | |||
| 387 | switch (ecc & SJA1000_ECC_MASK) { | ||
| 388 | case SJA1000_ECC_BIT: | ||
| 389 | cf->data[2] |= CAN_ERR_PROT_BIT; | ||
| 390 | break; | ||
| 391 | case SJA1000_ECC_FORM: | ||
| 392 | cf->data[2] |= CAN_ERR_PROT_FORM; | ||
| 393 | break; | ||
| 394 | case SJA1000_ECC_STUFF: | ||
| 395 | cf->data[2] |= CAN_ERR_PROT_STUFF; | ||
| 396 | break; | ||
| 397 | default: | ||
| 398 | cf->data[2] |= CAN_ERR_PROT_UNSPEC; | ||
| 399 | cf->data[3] = ecc & SJA1000_ECC_SEG; | ||
| 400 | break; | ||
| 401 | } | ||
| 402 | |||
| 403 | /* Error occured during transmission? */ | ||
| 404 | if ((ecc & SJA1000_ECC_DIR) == 0) | ||
| 405 | cf->data[2] |= CAN_ERR_PROT_TX; | ||
| 406 | |||
| 407 | if (dev->can.state == CAN_STATE_ERROR_WARNING || | ||
| 408 | dev->can.state == CAN_STATE_ERROR_PASSIVE) { | ||
| 409 | cf->data[1] = (txerr > rxerr) ? | ||
| 410 | CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; | ||
| 411 | } | ||
| 412 | } else if (msg->type == CPC_MSG_TYPE_OVERRUN) { | ||
| 413 | cf->can_id |= CAN_ERR_CRTL; | ||
| 414 | cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; | ||
| 415 | |||
| 416 | stats->rx_over_errors++; | ||
| 417 | stats->rx_errors++; | ||
| 418 | } | ||
| 419 | |||
| 420 | netif_rx(skb); | ||
| 421 | |||
| 422 | stats->rx_packets++; | ||
| 423 | stats->rx_bytes += cf->can_dlc; | ||
| 424 | } | ||
| 425 | |||
| 426 | /* | ||
| 427 | * callback for bulk IN urb | ||
| 428 | */ | ||
| 429 | static void ems_usb_read_bulk_callback(struct urb *urb) | ||
| 430 | { | ||
| 431 | struct ems_usb *dev = urb->context; | ||
| 432 | struct net_device *netdev; | ||
| 433 | int retval; | ||
| 434 | |||
| 435 | netdev = dev->netdev; | ||
| 436 | |||
| 437 | if (!netif_device_present(netdev)) | ||
| 438 | return; | ||
| 439 | |||
| 440 | switch (urb->status) { | ||
| 441 | case 0: /* success */ | ||
| 442 | break; | ||
| 443 | |||
| 444 | case -ENOENT: | ||
| 445 | return; | ||
| 446 | |||
| 447 | default: | ||
| 448 | dev_info(netdev->dev.parent, "Rx URB aborted (%d)\n", | ||
| 449 | urb->status); | ||
| 450 | goto resubmit_urb; | ||
| 451 | } | ||
| 452 | |||
| 453 | if (urb->actual_length > CPC_HEADER_SIZE) { | ||
| 454 | struct ems_cpc_msg *msg; | ||
| 455 | u8 *ibuf = urb->transfer_buffer; | ||
| 456 | u8 msg_count, again, start; | ||
| 457 | |||
| 458 | msg_count = ibuf[0] & ~0x80; | ||
| 459 | again = ibuf[0] & 0x80; | ||
| 460 | |||
| 461 | start = CPC_HEADER_SIZE; | ||
| 462 | |||
| 463 | while (msg_count) { | ||
| 464 | msg = (struct ems_cpc_msg *)&ibuf[start]; | ||
| 465 | |||
| 466 | switch (msg->type) { | ||
| 467 | case CPC_MSG_TYPE_CAN_STATE: | ||
| 468 | /* Process CAN state changes */ | ||
| 469 | ems_usb_rx_err(dev, msg); | ||
| 470 | break; | ||
| 471 | |||
| 472 | case CPC_MSG_TYPE_CAN_FRAME: | ||
| 473 | case CPC_MSG_TYPE_EXT_CAN_FRAME: | ||
| 474 | case CPC_MSG_TYPE_RTR_FRAME: | ||
| 475 | case CPC_MSG_TYPE_EXT_RTR_FRAME: | ||
| 476 | ems_usb_rx_can_msg(dev, msg); | ||
| 477 | break; | ||
| 478 | |||
| 479 | case CPC_MSG_TYPE_CAN_FRAME_ERROR: | ||
| 480 | /* Process errorframe */ | ||
| 481 | ems_usb_rx_err(dev, msg); | ||
| 482 | break; | ||
| 483 | |||
| 484 | case CPC_MSG_TYPE_OVERRUN: | ||
| 485 | /* Message lost while receiving */ | ||
| 486 | ems_usb_rx_err(dev, msg); | ||
| 487 | break; | ||
| 488 | } | ||
| 489 | |||
| 490 | start += CPC_MSG_HEADER_LEN + msg->length; | ||
| 491 | msg_count--; | ||
| 492 | |||
| 493 | if (start > urb->transfer_buffer_length) { | ||
| 494 | dev_err(netdev->dev.parent, "format error\n"); | ||
| 495 | break; | ||
| 496 | } | ||
| 497 | } | ||
| 498 | } | ||
| 499 | |||
| 500 | resubmit_urb: | ||
| 501 | usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2), | ||
| 502 | urb->transfer_buffer, RX_BUFFER_SIZE, | ||
| 503 | ems_usb_read_bulk_callback, dev); | ||
| 504 | |||
| 505 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 506 | |||
| 507 | if (retval == -ENODEV) | ||
| 508 | netif_device_detach(netdev); | ||
| 509 | else if (retval) | ||
| 510 | dev_err(netdev->dev.parent, | ||
| 511 | "failed resubmitting read bulk urb: %d\n", retval); | ||
| 512 | |||
| 513 | return; | ||
| 514 | } | ||
| 515 | |||
| 516 | /* | ||
| 517 | * callback for bulk IN urb | ||
| 518 | */ | ||
| 519 | static void ems_usb_write_bulk_callback(struct urb *urb) | ||
| 520 | { | ||
| 521 | struct ems_tx_urb_context *context = urb->context; | ||
| 522 | struct ems_usb *dev; | ||
| 523 | struct net_device *netdev; | ||
| 524 | |||
| 525 | BUG_ON(!context); | ||
| 526 | |||
| 527 | dev = context->dev; | ||
| 528 | netdev = dev->netdev; | ||
| 529 | |||
| 530 | /* free up our allocated buffer */ | ||
| 531 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, | ||
| 532 | urb->transfer_buffer, urb->transfer_dma); | ||
| 533 | |||
| 534 | atomic_dec(&dev->active_tx_urbs); | ||
| 535 | |||
| 536 | if (!netif_device_present(netdev)) | ||
| 537 | return; | ||
| 538 | |||
| 539 | if (urb->status) | ||
| 540 | dev_info(netdev->dev.parent, "Tx URB aborted (%d)\n", | ||
| 541 | urb->status); | ||
| 542 | |||
| 543 | netdev->trans_start = jiffies; | ||
| 544 | |||
| 545 | /* transmission complete interrupt */ | ||
| 546 | netdev->stats.tx_packets++; | ||
| 547 | netdev->stats.tx_bytes += context->dlc; | ||
| 548 | |||
| 549 | can_get_echo_skb(netdev, context->echo_index); | ||
| 550 | |||
| 551 | /* Release context */ | ||
| 552 | context->echo_index = MAX_TX_URBS; | ||
| 553 | |||
| 554 | if (netif_queue_stopped(netdev)) | ||
| 555 | netif_wake_queue(netdev); | ||
| 556 | } | ||
| 557 | |||
| 558 | /* | ||
| 559 | * Send the given CPC command synchronously | ||
| 560 | */ | ||
| 561 | static int ems_usb_command_msg(struct ems_usb *dev, struct ems_cpc_msg *msg) | ||
| 562 | { | ||
| 563 | int actual_length; | ||
| 564 | |||
| 565 | /* Copy payload */ | ||
| 566 | memcpy(&dev->tx_msg_buffer[CPC_HEADER_SIZE], msg, | ||
| 567 | msg->length + CPC_MSG_HEADER_LEN); | ||
| 568 | |||
| 569 | /* Clear header */ | ||
| 570 | memset(&dev->tx_msg_buffer[0], 0, CPC_HEADER_SIZE); | ||
| 571 | |||
| 572 | return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), | ||
| 573 | &dev->tx_msg_buffer[0], | ||
| 574 | msg->length + CPC_MSG_HEADER_LEN + CPC_HEADER_SIZE, | ||
| 575 | &actual_length, 1000); | ||
| 576 | } | ||
| 577 | |||
| 578 | /* | ||
| 579 | * Change CAN controllers' mode register | ||
| 580 | */ | ||
| 581 | static int ems_usb_write_mode(struct ems_usb *dev, u8 mode) | ||
| 582 | { | ||
| 583 | dev->active_params.msg.can_params.cc_params.sja1000.mode = mode; | ||
| 584 | |||
| 585 | return ems_usb_command_msg(dev, &dev->active_params); | ||
| 586 | } | ||
| 587 | |||
| 588 | /* | ||
| 589 | * Send a CPC_Control command to change behaviour when interface receives a CAN | ||
| 590 | * message, bus error or CAN state changed notifications. | ||
| 591 | */ | ||
| 592 | static int ems_usb_control_cmd(struct ems_usb *dev, u8 val) | ||
| 593 | { | ||
| 594 | struct ems_cpc_msg cmd; | ||
| 595 | |||
| 596 | cmd.type = CPC_CMD_TYPE_CONTROL; | ||
| 597 | cmd.length = CPC_MSG_HEADER_LEN + 1; | ||
| 598 | |||
| 599 | cmd.msgid = 0; | ||
| 600 | |||
| 601 | cmd.msg.generic[0] = val; | ||
| 602 | |||
| 603 | return ems_usb_command_msg(dev, &cmd); | ||
| 604 | } | ||
| 605 | |||
| 606 | /* | ||
| 607 | * Start interface | ||
| 608 | */ | ||
| 609 | static int ems_usb_start(struct ems_usb *dev) | ||
| 610 | { | ||
| 611 | struct net_device *netdev = dev->netdev; | ||
| 612 | int err, i; | ||
| 613 | |||
| 614 | dev->intr_in_buffer[0] = 0; | ||
| 615 | dev->free_slots = 15; /* initial size */ | ||
| 616 | |||
| 617 | for (i = 0; i < MAX_RX_URBS; i++) { | ||
| 618 | struct urb *urb = NULL; | ||
| 619 | u8 *buf = NULL; | ||
| 620 | |||
| 621 | /* create a URB, and a buffer for it */ | ||
| 622 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 623 | if (!urb) { | ||
| 624 | dev_err(netdev->dev.parent, | ||
| 625 | "No memory left for URBs\n"); | ||
| 626 | return -ENOMEM; | ||
| 627 | } | ||
| 628 | |||
| 629 | buf = usb_buffer_alloc(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL, | ||
| 630 | &urb->transfer_dma); | ||
| 631 | if (!buf) { | ||
| 632 | dev_err(netdev->dev.parent, | ||
| 633 | "No memory left for USB buffer\n"); | ||
| 634 | usb_free_urb(urb); | ||
| 635 | return -ENOMEM; | ||
| 636 | } | ||
| 637 | |||
| 638 | usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2), | ||
| 639 | buf, RX_BUFFER_SIZE, | ||
| 640 | ems_usb_read_bulk_callback, dev); | ||
| 641 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 642 | usb_anchor_urb(urb, &dev->rx_submitted); | ||
| 643 | |||
| 644 | err = usb_submit_urb(urb, GFP_KERNEL); | ||
| 645 | if (err) { | ||
| 646 | if (err == -ENODEV) | ||
| 647 | netif_device_detach(dev->netdev); | ||
| 648 | |||
| 649 | usb_unanchor_urb(urb); | ||
| 650 | usb_buffer_free(dev->udev, RX_BUFFER_SIZE, buf, | ||
| 651 | urb->transfer_dma); | ||
| 652 | break; | ||
| 653 | } | ||
| 654 | |||
| 655 | /* Drop reference, USB core will take care of freeing it */ | ||
| 656 | usb_free_urb(urb); | ||
| 657 | } | ||
| 658 | |||
| 659 | /* Did we submit any URBs */ | ||
| 660 | if (i == 0) { | ||
| 661 | dev_warn(netdev->dev.parent, "couldn't setup read URBs\n"); | ||
| 662 | return err; | ||
| 663 | } | ||
| 664 | |||
| 665 | /* Warn if we've couldn't transmit all the URBs */ | ||
| 666 | if (i < MAX_RX_URBS) | ||
| 667 | dev_warn(netdev->dev.parent, "rx performance may be slow\n"); | ||
| 668 | |||
| 669 | /* Setup and start interrupt URB */ | ||
| 670 | usb_fill_int_urb(dev->intr_urb, dev->udev, | ||
| 671 | usb_rcvintpipe(dev->udev, 1), | ||
| 672 | dev->intr_in_buffer, | ||
| 673 | INTR_IN_BUFFER_SIZE, | ||
| 674 | ems_usb_read_interrupt_callback, dev, 1); | ||
| 675 | |||
| 676 | err = usb_submit_urb(dev->intr_urb, GFP_KERNEL); | ||
| 677 | if (err) { | ||
| 678 | if (err == -ENODEV) | ||
| 679 | netif_device_detach(dev->netdev); | ||
| 680 | |||
| 681 | dev_warn(netdev->dev.parent, "intr URB submit failed: %d\n", | ||
| 682 | err); | ||
| 683 | |||
| 684 | return err; | ||
| 685 | } | ||
| 686 | |||
| 687 | /* CPC-USB will transfer received message to host */ | ||
| 688 | err = ems_usb_control_cmd(dev, CONTR_CAN_MESSAGE | CONTR_CONT_ON); | ||
| 689 | if (err) | ||
| 690 | goto failed; | ||
| 691 | |||
| 692 | /* CPC-USB will transfer CAN state changes to host */ | ||
| 693 | err = ems_usb_control_cmd(dev, CONTR_CAN_STATE | CONTR_CONT_ON); | ||
| 694 | if (err) | ||
| 695 | goto failed; | ||
| 696 | |||
| 697 | /* CPC-USB will transfer bus errors to host */ | ||
| 698 | err = ems_usb_control_cmd(dev, CONTR_BUS_ERROR | CONTR_CONT_ON); | ||
| 699 | if (err) | ||
| 700 | goto failed; | ||
| 701 | |||
| 702 | err = ems_usb_write_mode(dev, SJA1000_MOD_NORMAL); | ||
| 703 | if (err) | ||
| 704 | goto failed; | ||
| 705 | |||
| 706 | dev->can.state = CAN_STATE_ERROR_ACTIVE; | ||
| 707 | |||
| 708 | return 0; | ||
| 709 | |||
| 710 | failed: | ||
| 711 | if (err == -ENODEV) | ||
| 712 | netif_device_detach(dev->netdev); | ||
| 713 | |||
| 714 | dev_warn(netdev->dev.parent, "couldn't submit control: %d\n", err); | ||
| 715 | |||
| 716 | return err; | ||
| 717 | } | ||
| 718 | |||
| 719 | static void unlink_all_urbs(struct ems_usb *dev) | ||
| 720 | { | ||
| 721 | int i; | ||
| 722 | |||
| 723 | usb_unlink_urb(dev->intr_urb); | ||
| 724 | |||
| 725 | usb_kill_anchored_urbs(&dev->rx_submitted); | ||
| 726 | |||
| 727 | usb_kill_anchored_urbs(&dev->tx_submitted); | ||
| 728 | atomic_set(&dev->active_tx_urbs, 0); | ||
| 729 | |||
| 730 | for (i = 0; i < MAX_TX_URBS; i++) | ||
| 731 | dev->tx_contexts[i].echo_index = MAX_TX_URBS; | ||
| 732 | } | ||
| 733 | |||
| 734 | static int ems_usb_open(struct net_device *netdev) | ||
| 735 | { | ||
| 736 | struct ems_usb *dev = netdev_priv(netdev); | ||
| 737 | int err; | ||
| 738 | |||
| 739 | err = ems_usb_write_mode(dev, SJA1000_MOD_RM); | ||
| 740 | if (err) | ||
| 741 | return err; | ||
| 742 | |||
| 743 | /* common open */ | ||
| 744 | err = open_candev(netdev); | ||
| 745 | if (err) | ||
| 746 | return err; | ||
| 747 | |||
| 748 | /* finally start device */ | ||
| 749 | err = ems_usb_start(dev); | ||
| 750 | if (err) { | ||
| 751 | if (err == -ENODEV) | ||
| 752 | netif_device_detach(dev->netdev); | ||
| 753 | |||
| 754 | dev_warn(netdev->dev.parent, "couldn't start device: %d\n", | ||
| 755 | err); | ||
| 756 | |||
| 757 | close_candev(netdev); | ||
| 758 | |||
| 759 | return err; | ||
| 760 | } | ||
| 761 | |||
| 762 | dev->open_time = jiffies; | ||
| 763 | |||
| 764 | netif_start_queue(netdev); | ||
| 765 | |||
| 766 | return 0; | ||
| 767 | } | ||
| 768 | |||
| 769 | static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *netdev) | ||
| 770 | { | ||
| 771 | struct ems_usb *dev = netdev_priv(netdev); | ||
| 772 | struct ems_tx_urb_context *context = NULL; | ||
| 773 | struct net_device_stats *stats = &netdev->stats; | ||
| 774 | struct can_frame *cf = (struct can_frame *)skb->data; | ||
| 775 | struct ems_cpc_msg *msg; | ||
| 776 | struct urb *urb; | ||
| 777 | u8 *buf; | ||
| 778 | int i, err; | ||
| 779 | size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN | ||
| 780 | + sizeof(struct cpc_can_msg); | ||
| 781 | |||
| 782 | /* create a URB, and a buffer for it, and copy the data to the URB */ | ||
| 783 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
| 784 | if (!urb) { | ||
| 785 | dev_err(netdev->dev.parent, "No memory left for URBs\n"); | ||
| 786 | goto nomem; | ||
| 787 | } | ||
| 788 | |||
| 789 | buf = usb_buffer_alloc(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma); | ||
| 790 | if (!buf) { | ||
| 791 | dev_err(netdev->dev.parent, "No memory left for USB buffer\n"); | ||
| 792 | usb_free_urb(urb); | ||
| 793 | goto nomem; | ||
| 794 | } | ||
| 795 | |||
| 796 | msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE]; | ||
| 797 | |||
| 798 | msg->msg.can_msg.id = cf->can_id & CAN_ERR_MASK; | ||
| 799 | msg->msg.can_msg.length = cf->can_dlc; | ||
| 800 | |||
| 801 | if (cf->can_id & CAN_RTR_FLAG) { | ||
| 802 | msg->type = cf->can_id & CAN_EFF_FLAG ? | ||
| 803 | CPC_CMD_TYPE_EXT_RTR_FRAME : CPC_CMD_TYPE_RTR_FRAME; | ||
| 804 | |||
| 805 | msg->length = CPC_CAN_MSG_MIN_SIZE; | ||
| 806 | } else { | ||
| 807 | msg->type = cf->can_id & CAN_EFF_FLAG ? | ||
| 808 | CPC_CMD_TYPE_EXT_CAN_FRAME : CPC_CMD_TYPE_CAN_FRAME; | ||
| 809 | |||
| 810 | for (i = 0; i < cf->can_dlc; i++) | ||
| 811 | msg->msg.can_msg.msg[i] = cf->data[i]; | ||
| 812 | |||
| 813 | msg->length = CPC_CAN_MSG_MIN_SIZE + cf->can_dlc; | ||
| 814 | } | ||
| 815 | |||
| 816 | for (i = 0; i < MAX_TX_URBS; i++) { | ||
| 817 | if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) { | ||
| 818 | context = &dev->tx_contexts[i]; | ||
| 819 | break; | ||
| 820 | } | ||
| 821 | } | ||
| 822 | |||
| 823 | /* | ||
| 824 | * May never happen! When this happens we'd more URBs in flight as | ||
| 825 | * allowed (MAX_TX_URBS). | ||
| 826 | */ | ||
| 827 | if (!context) { | ||
| 828 | usb_unanchor_urb(urb); | ||
| 829 | usb_buffer_free(dev->udev, size, buf, urb->transfer_dma); | ||
| 830 | |||
| 831 | dev_warn(netdev->dev.parent, "couldn't find free context\n"); | ||
| 832 | |||
| 833 | return NETDEV_TX_BUSY; | ||
| 834 | } | ||
| 835 | |||
| 836 | context->dev = dev; | ||
| 837 | context->echo_index = i; | ||
| 838 | context->dlc = cf->can_dlc; | ||
| 839 | |||
| 840 | usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf, | ||
| 841 | size, ems_usb_write_bulk_callback, context); | ||
| 842 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 843 | usb_anchor_urb(urb, &dev->tx_submitted); | ||
| 844 | |||
| 845 | can_put_echo_skb(skb, netdev, context->echo_index); | ||
| 846 | |||
| 847 | atomic_inc(&dev->active_tx_urbs); | ||
| 848 | |||
| 849 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 850 | if (unlikely(err)) { | ||
| 851 | can_free_echo_skb(netdev, context->echo_index); | ||
| 852 | |||
| 853 | usb_unanchor_urb(urb); | ||
| 854 | usb_buffer_free(dev->udev, size, buf, urb->transfer_dma); | ||
| 855 | dev_kfree_skb(skb); | ||
| 856 | |||
| 857 | atomic_dec(&dev->active_tx_urbs); | ||
| 858 | |||
| 859 | if (err == -ENODEV) { | ||
| 860 | netif_device_detach(netdev); | ||
| 861 | } else { | ||
| 862 | dev_warn(netdev->dev.parent, "failed tx_urb %d\n", err); | ||
| 863 | |||
| 864 | stats->tx_dropped++; | ||
| 865 | } | ||
| 866 | } else { | ||
| 867 | netdev->trans_start = jiffies; | ||
| 868 | |||
| 869 | /* Slow down tx path */ | ||
| 870 | if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS || | ||
| 871 | dev->free_slots < 5) { | ||
| 872 | netif_stop_queue(netdev); | ||
| 873 | } | ||
| 874 | } | ||
| 875 | |||
| 876 | /* | ||
| 877 | * Release our reference to this URB, the USB core will eventually free | ||
| 878 | * it entirely. | ||
| 879 | */ | ||
| 880 | usb_free_urb(urb); | ||
| 881 | |||
| 882 | return NETDEV_TX_OK; | ||
| 883 | |||
| 884 | nomem: | ||
| 885 | if (skb) | ||
| 886 | dev_kfree_skb(skb); | ||
| 887 | |||
| 888 | stats->tx_dropped++; | ||
| 889 | |||
| 890 | return NETDEV_TX_OK; | ||
| 891 | } | ||
| 892 | |||
| 893 | static int ems_usb_close(struct net_device *netdev) | ||
| 894 | { | ||
| 895 | struct ems_usb *dev = netdev_priv(netdev); | ||
| 896 | |||
| 897 | /* Stop polling */ | ||
| 898 | unlink_all_urbs(dev); | ||
| 899 | |||
| 900 | netif_stop_queue(netdev); | ||
| 901 | |||
| 902 | /* Set CAN controller to reset mode */ | ||
| 903 | if (ems_usb_write_mode(dev, SJA1000_MOD_RM)) | ||
| 904 | dev_warn(netdev->dev.parent, "couldn't stop device"); | ||
| 905 | |||
| 906 | close_candev(netdev); | ||
| 907 | |||
| 908 | dev->open_time = 0; | ||
| 909 | |||
| 910 | return 0; | ||
| 911 | } | ||
| 912 | |||
| 913 | static const struct net_device_ops ems_usb_netdev_ops = { | ||
| 914 | .ndo_open = ems_usb_open, | ||
| 915 | .ndo_stop = ems_usb_close, | ||
| 916 | .ndo_start_xmit = ems_usb_start_xmit, | ||
| 917 | }; | ||
| 918 | |||
| 919 | static struct can_bittiming_const ems_usb_bittiming_const = { | ||
| 920 | .name = "ems_usb", | ||
| 921 | .tseg1_min = 1, | ||
| 922 | .tseg1_max = 16, | ||
| 923 | .tseg2_min = 1, | ||
| 924 | .tseg2_max = 8, | ||
| 925 | .sjw_max = 4, | ||
| 926 | .brp_min = 1, | ||
| 927 | .brp_max = 64, | ||
| 928 | .brp_inc = 1, | ||
| 929 | }; | ||
| 930 | |||
| 931 | static int ems_usb_set_mode(struct net_device *netdev, enum can_mode mode) | ||
| 932 | { | ||
| 933 | struct ems_usb *dev = netdev_priv(netdev); | ||
| 934 | |||
| 935 | if (!dev->open_time) | ||
| 936 | return -EINVAL; | ||
| 937 | |||
| 938 | switch (mode) { | ||
| 939 | case CAN_MODE_START: | ||
| 940 | if (ems_usb_write_mode(dev, SJA1000_MOD_NORMAL)) | ||
| 941 | dev_warn(netdev->dev.parent, "couldn't start device"); | ||
| 942 | |||
| 943 | if (netif_queue_stopped(netdev)) | ||
| 944 | netif_wake_queue(netdev); | ||
| 945 | break; | ||
| 946 | |||
| 947 | default: | ||
| 948 | return -EOPNOTSUPP; | ||
| 949 | } | ||
| 950 | |||
| 951 | return 0; | ||
| 952 | } | ||
| 953 | |||
| 954 | static int ems_usb_set_bittiming(struct net_device *netdev) | ||
| 955 | { | ||
| 956 | struct ems_usb *dev = netdev_priv(netdev); | ||
| 957 | struct can_bittiming *bt = &dev->can.bittiming; | ||
| 958 | u8 btr0, btr1; | ||
| 959 | |||
| 960 | btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6); | ||
| 961 | btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) | | ||
| 962 | (((bt->phase_seg2 - 1) & 0x7) << 4); | ||
| 963 | if (dev->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) | ||
| 964 | btr1 |= 0x80; | ||
| 965 | |||
| 966 | dev_info(netdev->dev.parent, "setting BTR0=0x%02x BTR1=0x%02x\n", | ||
| 967 | btr0, btr1); | ||
| 968 | |||
| 969 | dev->active_params.msg.can_params.cc_params.sja1000.btr0 = btr0; | ||
| 970 | dev->active_params.msg.can_params.cc_params.sja1000.btr1 = btr1; | ||
| 971 | |||
| 972 | return ems_usb_command_msg(dev, &dev->active_params); | ||
| 973 | } | ||
| 974 | |||
| 975 | static void init_params_sja1000(struct ems_cpc_msg *msg) | ||
| 976 | { | ||
| 977 | struct cpc_sja1000_params *sja1000 = | ||
| 978 | &msg->msg.can_params.cc_params.sja1000; | ||
| 979 | |||
| 980 | msg->type = CPC_CMD_TYPE_CAN_PARAMS; | ||
| 981 | msg->length = sizeof(struct cpc_can_params); | ||
| 982 | msg->msgid = 0; | ||
| 983 | |||
| 984 | msg->msg.can_params.cc_type = CPC_CC_TYPE_SJA1000; | ||
| 985 | |||
| 986 | /* Acceptance filter open */ | ||
| 987 | sja1000->acc_code0 = 0x00; | ||
| 988 | sja1000->acc_code1 = 0x00; | ||
| 989 | sja1000->acc_code2 = 0x00; | ||
| 990 | sja1000->acc_code3 = 0x00; | ||
| 991 | |||
| 992 | /* Acceptance filter open */ | ||
| 993 | sja1000->acc_mask0 = 0xFF; | ||
| 994 | sja1000->acc_mask1 = 0xFF; | ||
| 995 | sja1000->acc_mask2 = 0xFF; | ||
| 996 | sja1000->acc_mask3 = 0xFF; | ||
| 997 | |||
| 998 | sja1000->btr0 = 0; | ||
| 999 | sja1000->btr1 = 0; | ||
| 1000 | |||
| 1001 | sja1000->outp_contr = SJA1000_DEFAULT_OUTPUT_CONTROL; | ||
| 1002 | sja1000->mode = SJA1000_MOD_RM; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | /* | ||
| 1006 | * probe function for new CPC-USB devices | ||
| 1007 | */ | ||
| 1008 | static int ems_usb_probe(struct usb_interface *intf, | ||
| 1009 | const struct usb_device_id *id) | ||
| 1010 | { | ||
| 1011 | struct net_device *netdev; | ||
| 1012 | struct ems_usb *dev; | ||
| 1013 | int i, err = -ENOMEM; | ||
| 1014 | |||
| 1015 | netdev = alloc_candev(sizeof(struct ems_usb)); | ||
| 1016 | if (!netdev) { | ||
| 1017 | dev_err(netdev->dev.parent, "Couldn't alloc candev\n"); | ||
| 1018 | return -ENOMEM; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | dev = netdev_priv(netdev); | ||
| 1022 | |||
| 1023 | dev->udev = interface_to_usbdev(intf); | ||
| 1024 | dev->netdev = netdev; | ||
| 1025 | |||
| 1026 | dev->can.state = CAN_STATE_STOPPED; | ||
| 1027 | dev->can.clock.freq = EMS_USB_ARM7_CLOCK; | ||
| 1028 | dev->can.bittiming_const = &ems_usb_bittiming_const; | ||
| 1029 | dev->can.do_set_bittiming = ems_usb_set_bittiming; | ||
| 1030 | dev->can.do_set_mode = ems_usb_set_mode; | ||
| 1031 | |||
| 1032 | netdev->flags |= IFF_ECHO; /* we support local echo */ | ||
| 1033 | |||
| 1034 | netdev->netdev_ops = &ems_usb_netdev_ops; | ||
| 1035 | |||
| 1036 | netdev->flags |= IFF_ECHO; /* we support local echo */ | ||
| 1037 | |||
| 1038 | init_usb_anchor(&dev->rx_submitted); | ||
| 1039 | |||
| 1040 | init_usb_anchor(&dev->tx_submitted); | ||
| 1041 | atomic_set(&dev->active_tx_urbs, 0); | ||
| 1042 | |||
| 1043 | for (i = 0; i < MAX_TX_URBS; i++) | ||
| 1044 | dev->tx_contexts[i].echo_index = MAX_TX_URBS; | ||
| 1045 | |||
| 1046 | dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1047 | if (!dev->intr_urb) { | ||
| 1048 | dev_err(netdev->dev.parent, "Couldn't alloc intr URB\n"); | ||
| 1049 | goto cleanup_candev; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL); | ||
| 1053 | if (!dev->intr_in_buffer) { | ||
| 1054 | dev_err(netdev->dev.parent, "Couldn't alloc Intr buffer\n"); | ||
| 1055 | goto cleanup_intr_urb; | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE + | ||
| 1059 | sizeof(struct ems_cpc_msg), GFP_KERNEL); | ||
| 1060 | if (!dev->tx_msg_buffer) { | ||
| 1061 | dev_err(netdev->dev.parent, "Couldn't alloc Tx buffer\n"); | ||
| 1062 | goto cleanup_intr_in_buffer; | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | usb_set_intfdata(intf, dev); | ||
| 1066 | |||
| 1067 | SET_NETDEV_DEV(netdev, &intf->dev); | ||
| 1068 | |||
| 1069 | init_params_sja1000(&dev->active_params); | ||
| 1070 | |||
| 1071 | err = ems_usb_command_msg(dev, &dev->active_params); | ||
| 1072 | if (err) { | ||
| 1073 | dev_err(netdev->dev.parent, | ||
| 1074 | "couldn't initialize controller: %d\n", err); | ||
| 1075 | goto cleanup_tx_msg_buffer; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | err = register_candev(netdev); | ||
| 1079 | if (err) { | ||
| 1080 | dev_err(netdev->dev.parent, | ||
| 1081 | "couldn't register CAN device: %d\n", err); | ||
| 1082 | goto cleanup_tx_msg_buffer; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | return 0; | ||
| 1086 | |||
| 1087 | cleanup_tx_msg_buffer: | ||
| 1088 | kfree(dev->tx_msg_buffer); | ||
| 1089 | |||
| 1090 | cleanup_intr_in_buffer: | ||
| 1091 | kfree(dev->intr_in_buffer); | ||
| 1092 | |||
| 1093 | cleanup_intr_urb: | ||
| 1094 | usb_free_urb(dev->intr_urb); | ||
| 1095 | |||
| 1096 | cleanup_candev: | ||
| 1097 | free_candev(netdev); | ||
| 1098 | |||
| 1099 | return err; | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | /* | ||
| 1103 | * called by the usb core when the device is removed from the system | ||
| 1104 | */ | ||
| 1105 | static void ems_usb_disconnect(struct usb_interface *intf) | ||
| 1106 | { | ||
| 1107 | struct ems_usb *dev = usb_get_intfdata(intf); | ||
| 1108 | |||
| 1109 | usb_set_intfdata(intf, NULL); | ||
| 1110 | |||
| 1111 | if (dev) { | ||
| 1112 | unregister_netdev(dev->netdev); | ||
| 1113 | free_candev(dev->netdev); | ||
| 1114 | |||
| 1115 | unlink_all_urbs(dev); | ||
| 1116 | |||
| 1117 | usb_free_urb(dev->intr_urb); | ||
| 1118 | |||
| 1119 | kfree(dev->intr_in_buffer); | ||
| 1120 | } | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 1124 | static struct usb_driver ems_usb_driver = { | ||
| 1125 | .name = "ems_usb", | ||
| 1126 | .probe = ems_usb_probe, | ||
| 1127 | .disconnect = ems_usb_disconnect, | ||
| 1128 | .id_table = ems_usb_table, | ||
| 1129 | }; | ||
| 1130 | |||
| 1131 | static int __init ems_usb_init(void) | ||
| 1132 | { | ||
| 1133 | int err; | ||
| 1134 | |||
| 1135 | printk(KERN_INFO "CPC-USB kernel driver loaded\n"); | ||
| 1136 | |||
| 1137 | /* register this driver with the USB subsystem */ | ||
| 1138 | err = usb_register(&ems_usb_driver); | ||
| 1139 | |||
| 1140 | if (err) { | ||
| 1141 | err("usb_register failed. Error number %d\n", err); | ||
| 1142 | return err; | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | return 0; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | static void __exit ems_usb_exit(void) | ||
| 1149 | { | ||
| 1150 | /* deregister this driver with the USB subsystem */ | ||
| 1151 | usb_deregister(&ems_usb_driver); | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | module_init(ems_usb_init); | ||
| 1155 | module_exit(ems_usb_exit); | ||
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index d45eacb76702..211c8e9182fc 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c | |||
| @@ -85,8 +85,6 @@ static int cnic_uio_open(struct uio_info *uinfo, struct inode *inode) | |||
| 85 | 85 | ||
| 86 | cp->uio_dev = iminor(inode); | 86 | cp->uio_dev = iminor(inode); |
| 87 | 87 | ||
| 88 | cnic_shutdown_bnx2_rx_ring(dev); | ||
| 89 | |||
| 90 | cnic_init_bnx2_tx_ring(dev); | 88 | cnic_init_bnx2_tx_ring(dev); |
| 91 | cnic_init_bnx2_rx_ring(dev); | 89 | cnic_init_bnx2_rx_ring(dev); |
| 92 | 90 | ||
| @@ -98,6 +96,8 @@ static int cnic_uio_close(struct uio_info *uinfo, struct inode *inode) | |||
| 98 | struct cnic_dev *dev = uinfo->priv; | 96 | struct cnic_dev *dev = uinfo->priv; |
| 99 | struct cnic_local *cp = dev->cnic_priv; | 97 | struct cnic_local *cp = dev->cnic_priv; |
| 100 | 98 | ||
| 99 | cnic_shutdown_bnx2_rx_ring(dev); | ||
| 100 | |||
| 101 | cp->uio_dev = -1; | 101 | cp->uio_dev = -1; |
| 102 | return 0; | 102 | return 0; |
| 103 | } | 103 | } |
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 3e3fab8afb1e..61f9da2b4943 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c | |||
| @@ -1109,7 +1109,7 @@ static int external_switch; | |||
| 1109 | static int __devinit cpmac_probe(struct platform_device *pdev) | 1109 | static int __devinit cpmac_probe(struct platform_device *pdev) |
| 1110 | { | 1110 | { |
| 1111 | int rc, phy_id; | 1111 | int rc, phy_id; |
| 1112 | char mdio_bus_id[BUS_ID_SIZE]; | 1112 | char mdio_bus_id[MII_BUS_ID_SIZE]; |
| 1113 | struct resource *mem; | 1113 | struct resource *mem; |
| 1114 | struct cpmac_priv *priv; | 1114 | struct cpmac_priv *priv; |
| 1115 | struct net_device *dev; | 1115 | struct net_device *dev; |
| @@ -1118,7 +1118,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev) | |||
| 1118 | pdata = pdev->dev.platform_data; | 1118 | pdata = pdev->dev.platform_data; |
| 1119 | 1119 | ||
| 1120 | if (external_switch || dumb_switch) { | 1120 | if (external_switch || dumb_switch) { |
| 1121 | strncpy(mdio_bus_id, "0", BUS_ID_SIZE); /* fixed phys bus */ | 1121 | strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */ |
| 1122 | phy_id = pdev->id; | 1122 | phy_id = pdev->id; |
| 1123 | } else { | 1123 | } else { |
| 1124 | for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) { | 1124 | for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) { |
| @@ -1126,7 +1126,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev) | |||
| 1126 | continue; | 1126 | continue; |
| 1127 | if (!cpmac_mii->phy_map[phy_id]) | 1127 | if (!cpmac_mii->phy_map[phy_id]) |
| 1128 | continue; | 1128 | continue; |
| 1129 | strncpy(mdio_bus_id, cpmac_mii->id, BUS_ID_SIZE); | 1129 | strncpy(mdio_bus_id, cpmac_mii->id, MII_BUS_ID_SIZE); |
| 1130 | break; | 1130 | break; |
| 1131 | } | 1131 | } |
| 1132 | } | 1132 | } |
| @@ -1167,7 +1167,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev) | |||
| 1167 | priv->msg_enable = netif_msg_init(debug_level, 0xff); | 1167 | priv->msg_enable = netif_msg_init(debug_level, 0xff); |
| 1168 | memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); | 1168 | memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); |
| 1169 | 1169 | ||
| 1170 | snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); | 1170 | snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); |
| 1171 | 1171 | ||
| 1172 | priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, | 1172 | priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, |
| 1173 | PHY_INTERFACE_MODE_MII); | 1173 | PHY_INTERFACE_MODE_MII); |
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 977c3d358279..41bd7aeafd82 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
| @@ -3083,7 +3083,6 @@ static const struct net_device_ops ehea_netdev_ops = { | |||
| 3083 | .ndo_poll_controller = ehea_netpoll, | 3083 | .ndo_poll_controller = ehea_netpoll, |
| 3084 | #endif | 3084 | #endif |
| 3085 | .ndo_get_stats = ehea_get_stats, | 3085 | .ndo_get_stats = ehea_get_stats, |
| 3086 | .ndo_change_mtu = eth_change_mtu, | ||
| 3087 | .ndo_set_mac_address = ehea_set_mac_addr, | 3086 | .ndo_set_mac_address = ehea_set_mac_addr, |
| 3088 | .ndo_validate_addr = eth_validate_addr, | 3087 | .ndo_validate_addr = eth_validate_addr, |
| 3089 | .ndo_set_multicast_list = ehea_set_multicast_list, | 3088 | .ndo_set_multicast_list = ehea_set_multicast_list, |
diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index a0231cd079f1..7d76bb085e10 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c | |||
| @@ -286,41 +286,6 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value) | |||
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | /** | 288 | /** |
| 289 | * igb_update_mc_addr_list - Update Multicast addresses | ||
| 290 | * @hw: pointer to the HW structure | ||
| 291 | * @mc_addr_list: array of multicast addresses to program | ||
| 292 | * @mc_addr_count: number of multicast addresses to program | ||
| 293 | * | ||
| 294 | * Updates entire Multicast Table Array. | ||
| 295 | * The caller must have a packed mc_addr_list of multicast addresses. | ||
| 296 | **/ | ||
| 297 | void igb_update_mc_addr_list(struct e1000_hw *hw, | ||
| 298 | u8 *mc_addr_list, u32 mc_addr_count) | ||
| 299 | { | ||
| 300 | u32 hash_value, hash_bit, hash_reg; | ||
| 301 | int i; | ||
| 302 | |||
| 303 | /* clear mta_shadow */ | ||
| 304 | memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); | ||
| 305 | |||
| 306 | /* update mta_shadow from mc_addr_list */ | ||
| 307 | for (i = 0; (u32) i < mc_addr_count; i++) { | ||
| 308 | hash_value = igb_hash_mc_addr(hw, mc_addr_list); | ||
| 309 | |||
| 310 | hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); | ||
| 311 | hash_bit = hash_value & 0x1F; | ||
| 312 | |||
| 313 | hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); | ||
| 314 | mc_addr_list += (ETH_ALEN); | ||
| 315 | } | ||
| 316 | |||
| 317 | /* replace the entire MTA table */ | ||
| 318 | for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) | ||
| 319 | array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]); | ||
| 320 | wrfl(); | ||
| 321 | } | ||
| 322 | |||
| 323 | /** | ||
| 324 | * igb_hash_mc_addr - Generate a multicast hash value | 289 | * igb_hash_mc_addr - Generate a multicast hash value |
| 325 | * @hw: pointer to the HW structure | 290 | * @hw: pointer to the HW structure |
| 326 | * @mc_addr: pointer to a multicast address | 291 | * @mc_addr: pointer to a multicast address |
| @@ -329,7 +294,7 @@ void igb_update_mc_addr_list(struct e1000_hw *hw, | |||
| 329 | * the multicast filter table array address and new table value. See | 294 | * the multicast filter table array address and new table value. See |
| 330 | * igb_mta_set() | 295 | * igb_mta_set() |
| 331 | **/ | 296 | **/ |
| 332 | u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) | 297 | static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) |
| 333 | { | 298 | { |
| 334 | u32 hash_value, hash_mask; | 299 | u32 hash_value, hash_mask; |
| 335 | u8 bit_shift = 0; | 300 | u8 bit_shift = 0; |
| @@ -392,6 +357,41 @@ u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) | |||
| 392 | } | 357 | } |
| 393 | 358 | ||
| 394 | /** | 359 | /** |
| 360 | * igb_update_mc_addr_list - Update Multicast addresses | ||
| 361 | * @hw: pointer to the HW structure | ||
| 362 | * @mc_addr_list: array of multicast addresses to program | ||
| 363 | * @mc_addr_count: number of multicast addresses to program | ||
| 364 | * | ||
| 365 | * Updates entire Multicast Table Array. | ||
| 366 | * The caller must have a packed mc_addr_list of multicast addresses. | ||
| 367 | **/ | ||
| 368 | void igb_update_mc_addr_list(struct e1000_hw *hw, | ||
| 369 | u8 *mc_addr_list, u32 mc_addr_count) | ||
| 370 | { | ||
| 371 | u32 hash_value, hash_bit, hash_reg; | ||
| 372 | int i; | ||
| 373 | |||
| 374 | /* clear mta_shadow */ | ||
| 375 | memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); | ||
| 376 | |||
| 377 | /* update mta_shadow from mc_addr_list */ | ||
| 378 | for (i = 0; (u32) i < mc_addr_count; i++) { | ||
| 379 | hash_value = igb_hash_mc_addr(hw, mc_addr_list); | ||
| 380 | |||
| 381 | hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); | ||
| 382 | hash_bit = hash_value & 0x1F; | ||
| 383 | |||
| 384 | hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); | ||
| 385 | mc_addr_list += (ETH_ALEN); | ||
| 386 | } | ||
| 387 | |||
| 388 | /* replace the entire MTA table */ | ||
| 389 | for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) | ||
| 390 | array_wr32(E1000_MTA, i, hw->mac.mta_shadow[i]); | ||
| 391 | wrfl(); | ||
| 392 | } | ||
| 393 | |||
| 394 | /** | ||
| 395 | * igb_clear_hw_cntrs_base - Clear base hardware counters | 395 | * igb_clear_hw_cntrs_base - Clear base hardware counters |
| 396 | * @hw: pointer to the HW structure | 396 | * @hw: pointer to the HW structure |
| 397 | * | 397 | * |
diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h index 7518af8cbbf5..bca17d882417 100644 --- a/drivers/net/igb/e1000_mac.h +++ b/drivers/net/igb/e1000_mac.h | |||
| @@ -88,6 +88,5 @@ enum e1000_mng_mode { | |||
| 88 | #define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 | 88 | #define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 |
| 89 | 89 | ||
| 90 | extern void e1000_init_function_pointers_82575(struct e1000_hw *hw); | 90 | extern void e1000_init_function_pointers_82575(struct e1000_hw *hw); |
| 91 | extern u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr); | ||
| 92 | 91 | ||
| 93 | #endif | 92 | #endif |
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index dd688d45e9cd..385be6016667 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h | |||
| @@ -267,7 +267,8 @@ struct ixgbe_adapter { | |||
| 267 | enum ixgbe_fc_mode last_lfc_mode; | 267 | enum ixgbe_fc_mode last_lfc_mode; |
| 268 | 268 | ||
| 269 | /* Interrupt Throttle Rate */ | 269 | /* Interrupt Throttle Rate */ |
| 270 | u32 itr_setting; | 270 | u32 rx_itr_setting; |
| 271 | u32 tx_itr_setting; | ||
| 271 | u16 eitr_low; | 272 | u16 eitr_low; |
| 272 | u16 eitr_high; | 273 | u16 eitr_high; |
| 273 | 274 | ||
| @@ -351,7 +352,8 @@ struct ixgbe_adapter { | |||
| 351 | struct ixgbe_hw_stats stats; | 352 | struct ixgbe_hw_stats stats; |
| 352 | 353 | ||
| 353 | /* Interrupt Throttle Rate */ | 354 | /* Interrupt Throttle Rate */ |
| 354 | u32 eitr_param; | 355 | u32 rx_eitr_param; |
| 356 | u32 tx_eitr_param; | ||
| 355 | 357 | ||
| 356 | unsigned long state; | 358 | unsigned long state; |
| 357 | u64 tx_busy; | 359 | u64 tx_busy; |
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 026e94a99849..53b0a6680254 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c | |||
| @@ -1929,7 +1929,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev, | |||
| 1929 | ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit; | 1929 | ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit; |
| 1930 | 1930 | ||
| 1931 | /* only valid if in constant ITR mode */ | 1931 | /* only valid if in constant ITR mode */ |
| 1932 | switch (adapter->itr_setting) { | 1932 | switch (adapter->rx_itr_setting) { |
| 1933 | case 0: | 1933 | case 0: |
| 1934 | /* throttling disabled */ | 1934 | /* throttling disabled */ |
| 1935 | ec->rx_coalesce_usecs = 0; | 1935 | ec->rx_coalesce_usecs = 0; |
| @@ -1940,9 +1940,25 @@ static int ixgbe_get_coalesce(struct net_device *netdev, | |||
| 1940 | break; | 1940 | break; |
| 1941 | default: | 1941 | default: |
| 1942 | /* fixed interrupt rate mode */ | 1942 | /* fixed interrupt rate mode */ |
| 1943 | ec->rx_coalesce_usecs = 1000000/adapter->eitr_param; | 1943 | ec->rx_coalesce_usecs = 1000000/adapter->rx_eitr_param; |
| 1944 | break; | 1944 | break; |
| 1945 | } | 1945 | } |
| 1946 | |||
| 1947 | /* only valid if in constant ITR mode */ | ||
| 1948 | switch (adapter->tx_itr_setting) { | ||
| 1949 | case 0: | ||
| 1950 | /* throttling disabled */ | ||
| 1951 | ec->tx_coalesce_usecs = 0; | ||
| 1952 | break; | ||
| 1953 | case 1: | ||
| 1954 | /* dynamic ITR mode */ | ||
| 1955 | ec->tx_coalesce_usecs = 1; | ||
| 1956 | break; | ||
| 1957 | default: | ||
| 1958 | ec->tx_coalesce_usecs = 1000000/adapter->tx_eitr_param; | ||
| 1959 | break; | ||
| 1960 | } | ||
| 1961 | |||
| 1946 | return 0; | 1962 | return 0; |
| 1947 | } | 1963 | } |
| 1948 | 1964 | ||
| @@ -1953,6 +1969,14 @@ static int ixgbe_set_coalesce(struct net_device *netdev, | |||
| 1953 | struct ixgbe_q_vector *q_vector; | 1969 | struct ixgbe_q_vector *q_vector; |
| 1954 | int i; | 1970 | int i; |
| 1955 | 1971 | ||
| 1972 | /* | ||
| 1973 | * don't accept tx specific changes if we've got mixed RxTx vectors | ||
| 1974 | * test and jump out here if needed before changing the rx numbers | ||
| 1975 | */ | ||
| 1976 | if ((1000000/ec->tx_coalesce_usecs) != adapter->tx_eitr_param && | ||
| 1977 | adapter->q_vector[0]->txr_count && adapter->q_vector[0]->rxr_count) | ||
| 1978 | return -EINVAL; | ||
| 1979 | |||
| 1956 | if (ec->tx_max_coalesced_frames_irq) | 1980 | if (ec->tx_max_coalesced_frames_irq) |
| 1957 | adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq; | 1981 | adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq; |
| 1958 | 1982 | ||
| @@ -1963,26 +1987,49 @@ static int ixgbe_set_coalesce(struct net_device *netdev, | |||
| 1963 | return -EINVAL; | 1987 | return -EINVAL; |
| 1964 | 1988 | ||
| 1965 | /* store the value in ints/second */ | 1989 | /* store the value in ints/second */ |
| 1966 | adapter->eitr_param = 1000000/ec->rx_coalesce_usecs; | 1990 | adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs; |
| 1967 | 1991 | ||
| 1968 | /* static value of interrupt rate */ | 1992 | /* static value of interrupt rate */ |
| 1969 | adapter->itr_setting = adapter->eitr_param; | 1993 | adapter->rx_itr_setting = adapter->rx_eitr_param; |
| 1970 | /* clear the lower bit as its used for dynamic state */ | 1994 | /* clear the lower bit as its used for dynamic state */ |
| 1971 | adapter->itr_setting &= ~1; | 1995 | adapter->rx_itr_setting &= ~1; |
| 1972 | } else if (ec->rx_coalesce_usecs == 1) { | 1996 | } else if (ec->rx_coalesce_usecs == 1) { |
| 1973 | /* 1 means dynamic mode */ | 1997 | /* 1 means dynamic mode */ |
| 1974 | adapter->eitr_param = 20000; | 1998 | adapter->rx_eitr_param = 20000; |
| 1975 | adapter->itr_setting = 1; | 1999 | adapter->rx_itr_setting = 1; |
| 1976 | } else { | 2000 | } else { |
| 1977 | /* | 2001 | /* |
| 1978 | * any other value means disable eitr, which is best | 2002 | * any other value means disable eitr, which is best |
| 1979 | * served by setting the interrupt rate very high | 2003 | * served by setting the interrupt rate very high |
| 1980 | */ | 2004 | */ |
| 1981 | if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) | 2005 | if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) |
| 1982 | adapter->eitr_param = IXGBE_MAX_RSC_INT_RATE; | 2006 | adapter->rx_eitr_param = IXGBE_MAX_RSC_INT_RATE; |
| 1983 | else | 2007 | else |
| 1984 | adapter->eitr_param = IXGBE_MAX_INT_RATE; | 2008 | adapter->rx_eitr_param = IXGBE_MAX_INT_RATE; |
| 1985 | adapter->itr_setting = 0; | 2009 | adapter->rx_itr_setting = 0; |
| 2010 | } | ||
| 2011 | |||
| 2012 | if (ec->tx_coalesce_usecs > 1) { | ||
| 2013 | /* check the limits */ | ||
| 2014 | if ((1000000/ec->tx_coalesce_usecs > IXGBE_MAX_INT_RATE) || | ||
| 2015 | (1000000/ec->tx_coalesce_usecs < IXGBE_MIN_INT_RATE)) | ||
| 2016 | return -EINVAL; | ||
| 2017 | |||
| 2018 | /* store the value in ints/second */ | ||
| 2019 | adapter->tx_eitr_param = 1000000/ec->tx_coalesce_usecs; | ||
| 2020 | |||
| 2021 | /* static value of interrupt rate */ | ||
| 2022 | adapter->tx_itr_setting = adapter->tx_eitr_param; | ||
| 2023 | |||
| 2024 | /* clear the lower bit as its used for dynamic state */ | ||
| 2025 | adapter->tx_itr_setting &= ~1; | ||
| 2026 | } else if (ec->tx_coalesce_usecs == 1) { | ||
| 2027 | /* 1 means dynamic mode */ | ||
| 2028 | adapter->tx_eitr_param = 10000; | ||
| 2029 | adapter->tx_itr_setting = 1; | ||
| 2030 | } else { | ||
| 2031 | adapter->tx_eitr_param = IXGBE_MAX_INT_RATE; | ||
| 2032 | adapter->tx_itr_setting = 0; | ||
| 1986 | } | 2033 | } |
| 1987 | 2034 | ||
| 1988 | /* MSI/MSIx Interrupt Mode */ | 2035 | /* MSI/MSIx Interrupt Mode */ |
| @@ -1992,17 +2039,17 @@ static int ixgbe_set_coalesce(struct net_device *netdev, | |||
| 1992 | for (i = 0; i < num_vectors; i++) { | 2039 | for (i = 0; i < num_vectors; i++) { |
| 1993 | q_vector = adapter->q_vector[i]; | 2040 | q_vector = adapter->q_vector[i]; |
| 1994 | if (q_vector->txr_count && !q_vector->rxr_count) | 2041 | if (q_vector->txr_count && !q_vector->rxr_count) |
| 1995 | /* tx vector gets half the rate */ | 2042 | /* tx only */ |
| 1996 | q_vector->eitr = (adapter->eitr_param >> 1); | 2043 | q_vector->eitr = adapter->tx_eitr_param; |
| 1997 | else | 2044 | else |
| 1998 | /* rx only or mixed */ | 2045 | /* rx only or mixed */ |
| 1999 | q_vector->eitr = adapter->eitr_param; | 2046 | q_vector->eitr = adapter->rx_eitr_param; |
| 2000 | ixgbe_write_eitr(q_vector); | 2047 | ixgbe_write_eitr(q_vector); |
| 2001 | } | 2048 | } |
| 2002 | /* Legacy Interrupt Mode */ | 2049 | /* Legacy Interrupt Mode */ |
| 2003 | } else { | 2050 | } else { |
| 2004 | q_vector = adapter->q_vector[0]; | 2051 | q_vector = adapter->q_vector[0]; |
| 2005 | q_vector->eitr = adapter->eitr_param; | 2052 | q_vector->eitr = adapter->rx_eitr_param; |
| 2006 | ixgbe_write_eitr(q_vector); | 2053 | ixgbe_write_eitr(q_vector); |
| 2007 | } | 2054 | } |
| 2008 | 2055 | ||
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 59ad9590e700..c407bd9de0dd 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
| @@ -926,12 +926,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) | |||
| 926 | r_idx + 1); | 926 | r_idx + 1); |
| 927 | } | 927 | } |
| 928 | 928 | ||
| 929 | /* if this is a tx only vector halve the interrupt rate */ | ||
| 930 | if (q_vector->txr_count && !q_vector->rxr_count) | 929 | if (q_vector->txr_count && !q_vector->rxr_count) |
| 931 | q_vector->eitr = (adapter->eitr_param >> 1); | 930 | /* tx only */ |
| 931 | q_vector->eitr = adapter->tx_eitr_param; | ||
| 932 | else if (q_vector->rxr_count) | 932 | else if (q_vector->rxr_count) |
| 933 | /* rx only */ | 933 | /* rx or mixed */ |
| 934 | q_vector->eitr = adapter->eitr_param; | 934 | q_vector->eitr = adapter->rx_eitr_param; |
| 935 | 935 | ||
| 936 | ixgbe_write_eitr(q_vector); | 936 | ixgbe_write_eitr(q_vector); |
| 937 | } | 937 | } |
| @@ -1359,7 +1359,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) | |||
| 1359 | /* If all Rx work done, exit the polling mode */ | 1359 | /* If all Rx work done, exit the polling mode */ |
| 1360 | if (work_done < budget) { | 1360 | if (work_done < budget) { |
| 1361 | napi_complete(napi); | 1361 | napi_complete(napi); |
| 1362 | if (adapter->itr_setting & 1) | 1362 | if (adapter->rx_itr_setting & 1) |
| 1363 | ixgbe_set_itr_msix(q_vector); | 1363 | ixgbe_set_itr_msix(q_vector); |
| 1364 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) | 1364 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
| 1365 | ixgbe_irq_enable_queues(adapter, | 1365 | ixgbe_irq_enable_queues(adapter, |
| @@ -1420,7 +1420,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget) | |||
| 1420 | /* If all Rx work done, exit the polling mode */ | 1420 | /* If all Rx work done, exit the polling mode */ |
| 1421 | if (work_done < budget) { | 1421 | if (work_done < budget) { |
| 1422 | napi_complete(napi); | 1422 | napi_complete(napi); |
| 1423 | if (adapter->itr_setting & 1) | 1423 | if (adapter->rx_itr_setting & 1) |
| 1424 | ixgbe_set_itr_msix(q_vector); | 1424 | ixgbe_set_itr_msix(q_vector); |
| 1425 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) | 1425 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
| 1426 | ixgbe_irq_enable_queues(adapter, | 1426 | ixgbe_irq_enable_queues(adapter, |
| @@ -1458,10 +1458,10 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget) | |||
| 1458 | if (!ixgbe_clean_tx_irq(q_vector, tx_ring)) | 1458 | if (!ixgbe_clean_tx_irq(q_vector, tx_ring)) |
| 1459 | work_done = budget; | 1459 | work_done = budget; |
| 1460 | 1460 | ||
| 1461 | /* If all Rx work done, exit the polling mode */ | 1461 | /* If all Tx work done, exit the polling mode */ |
| 1462 | if (work_done < budget) { | 1462 | if (work_done < budget) { |
| 1463 | napi_complete(napi); | 1463 | napi_complete(napi); |
| 1464 | if (adapter->itr_setting & 1) | 1464 | if (adapter->tx_itr_setting & 1) |
| 1465 | ixgbe_set_itr_msix(q_vector); | 1465 | ixgbe_set_itr_msix(q_vector); |
| 1466 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) | 1466 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
| 1467 | ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx)); | 1467 | 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) | |||
| 1848 | struct ixgbe_hw *hw = &adapter->hw; | 1848 | struct ixgbe_hw *hw = &adapter->hw; |
| 1849 | 1849 | ||
| 1850 | IXGBE_WRITE_REG(hw, IXGBE_EITR(0), | 1850 | IXGBE_WRITE_REG(hw, IXGBE_EITR(0), |
| 1851 | EITR_INTS_PER_SEC_TO_REG(adapter->eitr_param)); | 1851 | EITR_INTS_PER_SEC_TO_REG(adapter->rx_eitr_param)); |
| 1852 | 1852 | ||
| 1853 | ixgbe_set_ivar(adapter, 0, 0, 0); | 1853 | ixgbe_set_ivar(adapter, 0, 0, 0); |
| 1854 | ixgbe_set_ivar(adapter, 1, 0, 0); | 1854 | ixgbe_set_ivar(adapter, 1, 0, 0); |
| @@ -1970,6 +1970,50 @@ static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) | |||
| 1970 | } | 1970 | } |
| 1971 | 1971 | ||
| 1972 | /** | 1972 | /** |
| 1973 | * ixgbe_configure_rscctl - enable RSC for the indicated ring | ||
| 1974 | * @adapter: address of board private structure | ||
| 1975 | * @index: index of ring to set | ||
| 1976 | * @rx_buf_len: rx buffer length | ||
| 1977 | **/ | ||
| 1978 | static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index, | ||
| 1979 | int rx_buf_len) | ||
| 1980 | { | ||
| 1981 | struct ixgbe_ring *rx_ring; | ||
| 1982 | struct ixgbe_hw *hw = &adapter->hw; | ||
| 1983 | int j; | ||
| 1984 | u32 rscctrl; | ||
| 1985 | |||
| 1986 | rx_ring = &adapter->rx_ring[index]; | ||
| 1987 | j = rx_ring->reg_idx; | ||
| 1988 | rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j)); | ||
| 1989 | rscctrl |= IXGBE_RSCCTL_RSCEN; | ||
| 1990 | /* | ||
| 1991 | * we must limit the number of descriptors so that the | ||
| 1992 | * total size of max desc * buf_len is not greater | ||
| 1993 | * than 65535 | ||
| 1994 | */ | ||
| 1995 | if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { | ||
| 1996 | #if (MAX_SKB_FRAGS > 16) | ||
| 1997 | rscctrl |= IXGBE_RSCCTL_MAXDESC_16; | ||
| 1998 | #elif (MAX_SKB_FRAGS > 8) | ||
| 1999 | rscctrl |= IXGBE_RSCCTL_MAXDESC_8; | ||
| 2000 | #elif (MAX_SKB_FRAGS > 4) | ||
| 2001 | rscctrl |= IXGBE_RSCCTL_MAXDESC_4; | ||
| 2002 | #else | ||
| 2003 | rscctrl |= IXGBE_RSCCTL_MAXDESC_1; | ||
| 2004 | #endif | ||
| 2005 | } else { | ||
| 2006 | if (rx_buf_len < IXGBE_RXBUFFER_4096) | ||
| 2007 | rscctrl |= IXGBE_RSCCTL_MAXDESC_16; | ||
| 2008 | else if (rx_buf_len < IXGBE_RXBUFFER_8192) | ||
| 2009 | rscctrl |= IXGBE_RSCCTL_MAXDESC_8; | ||
| 2010 | else | ||
| 2011 | rscctrl |= IXGBE_RSCCTL_MAXDESC_4; | ||
| 2012 | } | ||
| 2013 | IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl); | ||
| 2014 | } | ||
| 2015 | |||
| 2016 | /** | ||
| 1973 | * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset | 2017 | * ixgbe_configure_rx - Configure 8259x Receive Unit after Reset |
| 1974 | * @adapter: board private structure | 2018 | * @adapter: board private structure |
| 1975 | * | 2019 | * |
| @@ -1990,7 +2034,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) | |||
| 1990 | u32 fctrl, hlreg0; | 2034 | u32 fctrl, hlreg0; |
| 1991 | u32 reta = 0, mrqc = 0; | 2035 | u32 reta = 0, mrqc = 0; |
| 1992 | u32 rdrxctl; | 2036 | u32 rdrxctl; |
| 1993 | u32 rscctrl; | ||
| 1994 | int rx_buf_len; | 2037 | int rx_buf_len; |
| 1995 | 2038 | ||
| 1996 | /* Decide whether to use packet split mode or not */ | 2039 | /* Decide whether to use packet split mode or not */ |
| @@ -2148,36 +2191,9 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) | |||
| 2148 | 2191 | ||
| 2149 | if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { | 2192 | if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { |
| 2150 | /* Enable 82599 HW-RSC */ | 2193 | /* Enable 82599 HW-RSC */ |
| 2151 | for (i = 0; i < adapter->num_rx_queues; i++) { | 2194 | for (i = 0; i < adapter->num_rx_queues; i++) |
| 2152 | rx_ring = &adapter->rx_ring[i]; | 2195 | ixgbe_configure_rscctl(adapter, i, rx_buf_len); |
| 2153 | j = rx_ring->reg_idx; | 2196 | |
| 2154 | rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j)); | ||
| 2155 | rscctrl |= IXGBE_RSCCTL_RSCEN; | ||
| 2156 | /* | ||
| 2157 | * we must limit the number of descriptors so that the | ||
| 2158 | * total size of max desc * buf_len is not greater | ||
| 2159 | * than 65535 | ||
| 2160 | */ | ||
| 2161 | if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { | ||
| 2162 | #if (MAX_SKB_FRAGS > 16) | ||
| 2163 | rscctrl |= IXGBE_RSCCTL_MAXDESC_16; | ||
| 2164 | #elif (MAX_SKB_FRAGS > 8) | ||
| 2165 | rscctrl |= IXGBE_RSCCTL_MAXDESC_8; | ||
| 2166 | #elif (MAX_SKB_FRAGS > 4) | ||
| 2167 | rscctrl |= IXGBE_RSCCTL_MAXDESC_4; | ||
| 2168 | #else | ||
| 2169 | rscctrl |= IXGBE_RSCCTL_MAXDESC_1; | ||
| 2170 | #endif | ||
| 2171 | } else { | ||
| 2172 | if (rx_buf_len < IXGBE_RXBUFFER_4096) | ||
| 2173 | rscctrl |= IXGBE_RSCCTL_MAXDESC_16; | ||
| 2174 | else if (rx_buf_len < IXGBE_RXBUFFER_8192) | ||
| 2175 | rscctrl |= IXGBE_RSCCTL_MAXDESC_8; | ||
| 2176 | else | ||
| 2177 | rscctrl |= IXGBE_RSCCTL_MAXDESC_4; | ||
| 2178 | } | ||
| 2179 | IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(j), rscctrl); | ||
| 2180 | } | ||
| 2181 | /* Disable RSC for ACK packets */ | 2197 | /* Disable RSC for ACK packets */ |
| 2182 | IXGBE_WRITE_REG(hw, IXGBE_RSCDBU, | 2198 | IXGBE_WRITE_REG(hw, IXGBE_RSCDBU, |
| 2183 | (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU))); | 2199 | (IXGBE_RSCDBU_RSCACKDIS | IXGBE_READ_REG(hw, IXGBE_RSCDBU))); |
| @@ -2926,6 +2942,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter) | |||
| 2926 | 2942 | ||
| 2927 | ixgbe_napi_disable_all(adapter); | 2943 | ixgbe_napi_disable_all(adapter); |
| 2928 | 2944 | ||
| 2945 | clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); | ||
| 2946 | del_timer_sync(&adapter->sfp_timer); | ||
| 2929 | del_timer_sync(&adapter->watchdog_timer); | 2947 | del_timer_sync(&adapter->watchdog_timer); |
| 2930 | cancel_work_sync(&adapter->watchdog_task); | 2948 | cancel_work_sync(&adapter->watchdog_task); |
| 2931 | 2949 | ||
| @@ -2989,7 +3007,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) | |||
| 2989 | /* If budget not fully consumed, exit the polling mode */ | 3007 | /* If budget not fully consumed, exit the polling mode */ |
| 2990 | if (work_done < budget) { | 3008 | if (work_done < budget) { |
| 2991 | napi_complete(napi); | 3009 | napi_complete(napi); |
| 2992 | if (adapter->itr_setting & 1) | 3010 | if (adapter->rx_itr_setting & 1) |
| 2993 | ixgbe_set_itr(adapter); | 3011 | ixgbe_set_itr(adapter); |
| 2994 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) | 3012 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
| 2995 | ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE); | 3013 | ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE); |
| @@ -3599,7 +3617,10 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) | |||
| 3599 | if (!q_vector) | 3617 | if (!q_vector) |
| 3600 | goto err_out; | 3618 | goto err_out; |
| 3601 | q_vector->adapter = adapter; | 3619 | q_vector->adapter = adapter; |
| 3602 | q_vector->eitr = adapter->eitr_param; | 3620 | if (q_vector->txr_count && !q_vector->rxr_count) |
| 3621 | q_vector->eitr = adapter->tx_eitr_param; | ||
| 3622 | else | ||
| 3623 | q_vector->eitr = adapter->rx_eitr_param; | ||
| 3603 | q_vector->v_idx = q_idx; | 3624 | q_vector->v_idx = q_idx; |
| 3604 | netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64); | 3625 | netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64); |
| 3605 | adapter->q_vector[q_idx] = q_vector; | 3626 | adapter->q_vector[q_idx] = q_vector; |
| @@ -3868,8 +3889,10 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) | |||
| 3868 | hw->fc.disable_fc_autoneg = false; | 3889 | hw->fc.disable_fc_autoneg = false; |
| 3869 | 3890 | ||
| 3870 | /* enable itr by default in dynamic mode */ | 3891 | /* enable itr by default in dynamic mode */ |
| 3871 | adapter->itr_setting = 1; | 3892 | adapter->rx_itr_setting = 1; |
| 3872 | adapter->eitr_param = 20000; | 3893 | adapter->rx_eitr_param = 20000; |
| 3894 | adapter->tx_itr_setting = 1; | ||
| 3895 | adapter->tx_eitr_param = 10000; | ||
| 3873 | 3896 | ||
| 3874 | /* set defaults for eitr in MegaBytes */ | 3897 | /* set defaults for eitr in MegaBytes */ |
| 3875 | adapter->eitr_low = 10; | 3898 | adapter->eitr_low = 10; |
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index f7bdde111dfc..b5aa974827e5 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
| @@ -1469,6 +1469,7 @@ netxen_nic_resume(struct pci_dev *pdev) | |||
| 1469 | } | 1469 | } |
| 1470 | 1470 | ||
| 1471 | netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY); | 1471 | netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY); |
| 1472 | return 0; | ||
| 1472 | 1473 | ||
| 1473 | err_out_detach: | 1474 | err_out_detach: |
| 1474 | netxen_nic_detach(adapter); | 1475 | netxen_nic_detach(adapter); |
| @@ -1903,12 +1904,13 @@ static void netxen_tx_timeout_task(struct work_struct *work) | |||
| 1903 | 1904 | ||
| 1904 | netif_wake_queue(adapter->netdev); | 1905 | netif_wake_queue(adapter->netdev); |
| 1905 | 1906 | ||
| 1906 | goto done; | 1907 | clear_bit(__NX_RESETTING, &adapter->state); |
| 1907 | 1908 | ||
| 1908 | } else { | 1909 | } else { |
| 1910 | clear_bit(__NX_RESETTING, &adapter->state); | ||
| 1909 | if (!netxen_nic_reset_context(adapter)) { | 1911 | if (!netxen_nic_reset_context(adapter)) { |
| 1910 | adapter->netdev->trans_start = jiffies; | 1912 | adapter->netdev->trans_start = jiffies; |
| 1911 | goto done; | 1913 | return; |
| 1912 | } | 1914 | } |
| 1913 | 1915 | ||
| 1914 | /* context reset failed, fall through for fw reset */ | 1916 | /* context reset failed, fall through for fw reset */ |
| @@ -1916,8 +1918,6 @@ static void netxen_tx_timeout_task(struct work_struct *work) | |||
| 1916 | 1918 | ||
| 1917 | request_reset: | 1919 | request_reset: |
| 1918 | adapter->need_fw_reset = 1; | 1920 | adapter->need_fw_reset = 1; |
| 1919 | done: | ||
| 1920 | clear_bit(__NX_RESETTING, &adapter->state); | ||
| 1921 | } | 1921 | } |
| 1922 | 1922 | ||
| 1923 | struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) | 1923 | struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) |
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 97db1c732342..474876c879cb 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
| @@ -340,12 +340,11 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link) | |||
| 340 | base = &virt[hw_info[i].offset & (req.Size-1)]; | 340 | base = &virt[hw_info[i].offset & (req.Size-1)]; |
| 341 | if ((readb(base+0) == hw_info[i].a0) && | 341 | if ((readb(base+0) == hw_info[i].a0) && |
| 342 | (readb(base+2) == hw_info[i].a1) && | 342 | (readb(base+2) == hw_info[i].a1) && |
| 343 | (readb(base+4) == hw_info[i].a2)) | 343 | (readb(base+4) == hw_info[i].a2)) { |
| 344 | break; | 344 | for (j = 0; j < 6; j++) |
| 345 | } | 345 | dev->dev_addr[j] = readb(base + (j<<1)); |
| 346 | if (i < NR_INFO) { | 346 | break; |
| 347 | for (j = 0; j < 6; j++) | 347 | } |
| 348 | dev->dev_addr[j] = readb(base + (j<<1)); | ||
| 349 | } | 348 | } |
| 350 | 349 | ||
| 351 | iounmap(virt); | 350 | iounmap(virt); |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 15140f9f2e92..ef1165718dd7 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
| @@ -1497,7 +1497,6 @@ static int sky2_up(struct net_device *dev) | |||
| 1497 | if (ramsize > 0) { | 1497 | if (ramsize > 0) { |
| 1498 | u32 rxspace; | 1498 | u32 rxspace; |
| 1499 | 1499 | ||
| 1500 | hw->flags |= SKY2_HW_RAM_BUFFER; | ||
| 1501 | pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); | 1500 | pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); |
| 1502 | if (ramsize < 16) | 1501 | if (ramsize < 16) |
| 1503 | rxspace = ramsize / 2; | 1502 | rxspace = ramsize / 2; |
| @@ -2926,6 +2925,9 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
| 2926 | ++hw->ports; | 2925 | ++hw->ports; |
| 2927 | } | 2926 | } |
| 2928 | 2927 | ||
| 2928 | if (sky2_read8(hw, B2_E_0)) | ||
| 2929 | hw->flags |= SKY2_HW_RAM_BUFFER; | ||
| 2930 | |||
| 2929 | return 0; | 2931 | return 0; |
| 2930 | } | 2932 | } |
| 2931 | 2933 | ||
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index f1e5e4542c2a..bc74db0d12f3 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c | |||
| @@ -1016,7 +1016,6 @@ static const struct net_device_ops vnet_ops = { | |||
| 1016 | .ndo_open = vnet_open, | 1016 | .ndo_open = vnet_open, |
| 1017 | .ndo_stop = vnet_close, | 1017 | .ndo_stop = vnet_close, |
| 1018 | .ndo_set_multicast_list = vnet_set_rx_mode, | 1018 | .ndo_set_multicast_list = vnet_set_rx_mode, |
| 1019 | .ndo_change_mtu = eth_change_mtu, | ||
| 1020 | .ndo_set_mac_address = vnet_set_mac_addr, | 1019 | .ndo_set_mac_address = vnet_set_mac_addr, |
| 1021 | .ndo_validate_addr = eth_validate_addr, | 1020 | .ndo_validate_addr = eth_validate_addr, |
| 1022 | .ndo_tx_timeout = vnet_tx_timeout, | 1021 | .ndo_tx_timeout = vnet_tx_timeout, |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index d3ee1994b02f..4fdfa2ae5418 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
| @@ -946,8 +946,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
| 946 | char *name; | 946 | char *name; |
| 947 | unsigned long flags = 0; | 947 | unsigned long flags = 0; |
| 948 | 948 | ||
| 949 | err = -EINVAL; | ||
| 950 | |||
| 951 | if (!capable(CAP_NET_ADMIN)) | 949 | if (!capable(CAP_NET_ADMIN)) |
| 952 | return -EPERM; | 950 | return -EPERM; |
| 953 | err = security_tun_dev_create(); | 951 | err = security_tun_dev_create(); |
| @@ -964,7 +962,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
| 964 | flags |= TUN_TAP_DEV; | 962 | flags |= TUN_TAP_DEV; |
| 965 | name = "tap%d"; | 963 | name = "tap%d"; |
| 966 | } else | 964 | } else |
| 967 | goto failed; | 965 | return -EINVAL; |
| 968 | 966 | ||
| 969 | if (*ifr->ifr_name) | 967 | if (*ifr->ifr_name) |
| 970 | name = ifr->ifr_name; | 968 | name = ifr->ifr_name; |
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index e2a39b9be96e..e391ef969c28 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c | |||
| @@ -263,6 +263,7 @@ static int kaweth_control(struct kaweth_device *kaweth, | |||
| 263 | int timeout) | 263 | int timeout) |
| 264 | { | 264 | { |
| 265 | struct usb_ctrlrequest *dr; | 265 | struct usb_ctrlrequest *dr; |
| 266 | int retval; | ||
| 266 | 267 | ||
| 267 | dbg("kaweth_control()"); | 268 | dbg("kaweth_control()"); |
| 268 | 269 | ||
| @@ -278,18 +279,21 @@ static int kaweth_control(struct kaweth_device *kaweth, | |||
| 278 | return -ENOMEM; | 279 | return -ENOMEM; |
| 279 | } | 280 | } |
| 280 | 281 | ||
| 281 | dr->bRequestType= requesttype; | 282 | dr->bRequestType = requesttype; |
| 282 | dr->bRequest = request; | 283 | dr->bRequest = request; |
| 283 | dr->wValue = cpu_to_le16(value); | 284 | dr->wValue = cpu_to_le16(value); |
| 284 | dr->wIndex = cpu_to_le16(index); | 285 | dr->wIndex = cpu_to_le16(index); |
| 285 | dr->wLength = cpu_to_le16(size); | 286 | dr->wLength = cpu_to_le16(size); |
| 286 | 287 | ||
| 287 | return kaweth_internal_control_msg(kaweth->dev, | 288 | retval = kaweth_internal_control_msg(kaweth->dev, |
| 288 | pipe, | 289 | pipe, |
| 289 | dr, | 290 | dr, |
| 290 | data, | 291 | data, |
| 291 | size, | 292 | size, |
| 292 | timeout); | 293 | timeout); |
| 294 | |||
| 295 | kfree(dr); | ||
| 296 | return retval; | ||
| 293 | } | 297 | } |
| 294 | 298 | ||
| 295 | /**************************************************************** | 299 | /**************************************************************** |
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 938fb3530a7a..c6c922247d05 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c | |||
| @@ -1227,7 +1227,7 @@ static const struct driver_info smsc95xx_info = { | |||
| 1227 | .rx_fixup = smsc95xx_rx_fixup, | 1227 | .rx_fixup = smsc95xx_rx_fixup, |
| 1228 | .tx_fixup = smsc95xx_tx_fixup, | 1228 | .tx_fixup = smsc95xx_tx_fixup, |
| 1229 | .status = smsc95xx_status, | 1229 | .status = smsc95xx_status, |
| 1230 | .flags = FLAG_ETHER, | 1230 | .flags = FLAG_ETHER | FLAG_SEND_ZLP, |
| 1231 | }; | 1231 | }; |
| 1232 | 1232 | ||
| 1233 | static const struct usb_device_id products[] = { | 1233 | static const struct usb_device_id products[] = { |
| @@ -1237,10 +1237,75 @@ static const struct usb_device_id products[] = { | |||
| 1237 | .driver_info = (unsigned long) &smsc95xx_info, | 1237 | .driver_info = (unsigned long) &smsc95xx_info, |
| 1238 | }, | 1238 | }, |
| 1239 | { | 1239 | { |
| 1240 | /* SMSC9505 USB Ethernet Device */ | ||
| 1241 | USB_DEVICE(0x0424, 0x9505), | ||
| 1242 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1243 | }, | ||
| 1244 | { | ||
| 1245 | /* SMSC9500A USB Ethernet Device */ | ||
| 1246 | USB_DEVICE(0x0424, 0x9E00), | ||
| 1247 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1248 | }, | ||
| 1249 | { | ||
| 1250 | /* SMSC9505A USB Ethernet Device */ | ||
| 1251 | USB_DEVICE(0x0424, 0x9E01), | ||
| 1252 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1253 | }, | ||
| 1254 | { | ||
| 1240 | /* SMSC9512/9514 USB Hub & Ethernet Device */ | 1255 | /* SMSC9512/9514 USB Hub & Ethernet Device */ |
| 1241 | USB_DEVICE(0x0424, 0xec00), | 1256 | USB_DEVICE(0x0424, 0xec00), |
| 1242 | .driver_info = (unsigned long) &smsc95xx_info, | 1257 | .driver_info = (unsigned long) &smsc95xx_info, |
| 1243 | }, | 1258 | }, |
| 1259 | { | ||
| 1260 | /* SMSC9500 USB Ethernet Device (SAL10) */ | ||
| 1261 | USB_DEVICE(0x0424, 0x9900), | ||
| 1262 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1263 | }, | ||
| 1264 | { | ||
| 1265 | /* SMSC9505 USB Ethernet Device (SAL10) */ | ||
| 1266 | USB_DEVICE(0x0424, 0x9901), | ||
| 1267 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1268 | }, | ||
| 1269 | { | ||
| 1270 | /* SMSC9500A USB Ethernet Device (SAL10) */ | ||
| 1271 | USB_DEVICE(0x0424, 0x9902), | ||
| 1272 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1273 | }, | ||
| 1274 | { | ||
| 1275 | /* SMSC9505A USB Ethernet Device (SAL10) */ | ||
| 1276 | USB_DEVICE(0x0424, 0x9903), | ||
| 1277 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1278 | }, | ||
| 1279 | { | ||
| 1280 | /* SMSC9512/9514 USB Hub & Ethernet Device (SAL10) */ | ||
| 1281 | USB_DEVICE(0x0424, 0x9904), | ||
| 1282 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1283 | }, | ||
| 1284 | { | ||
| 1285 | /* SMSC9500A USB Ethernet Device (HAL) */ | ||
| 1286 | USB_DEVICE(0x0424, 0x9905), | ||
| 1287 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1288 | }, | ||
| 1289 | { | ||
| 1290 | /* SMSC9505A USB Ethernet Device (HAL) */ | ||
| 1291 | USB_DEVICE(0x0424, 0x9906), | ||
| 1292 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1293 | }, | ||
| 1294 | { | ||
| 1295 | /* SMSC9500 USB Ethernet Device (Alternate ID) */ | ||
| 1296 | USB_DEVICE(0x0424, 0x9907), | ||
| 1297 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1298 | }, | ||
| 1299 | { | ||
| 1300 | /* SMSC9500A USB Ethernet Device (Alternate ID) */ | ||
| 1301 | USB_DEVICE(0x0424, 0x9908), | ||
| 1302 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1303 | }, | ||
| 1304 | { | ||
| 1305 | /* SMSC9512/9514 USB Hub & Ethernet Device (Alternate ID) */ | ||
| 1306 | USB_DEVICE(0x0424, 0x9909), | ||
| 1307 | .driver_info = (unsigned long) &smsc95xx_info, | ||
| 1308 | }, | ||
| 1244 | { }, /* END */ | 1309 | { }, /* END */ |
| 1245 | }; | 1310 | }; |
| 1246 | MODULE_DEVICE_TABLE(usb, products); | 1311 | MODULE_DEVICE_TABLE(usb, products); |
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 24b36f795151..ca5ca5ae061d 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
| @@ -1049,7 +1049,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, | |||
| 1049 | * NOTE: strictly conforming cdc-ether devices should expect | 1049 | * NOTE: strictly conforming cdc-ether devices should expect |
| 1050 | * the ZLP here, but ignore the one-byte packet. | 1050 | * the ZLP here, but ignore the one-byte packet. |
| 1051 | */ | 1051 | */ |
| 1052 | if ((length % dev->maxpacket) == 0) { | 1052 | if (!(info->flags & FLAG_SEND_ZLP) && (length % dev->maxpacket) == 0) { |
| 1053 | urb->transfer_buffer_length++; | 1053 | urb->transfer_buffer_length++; |
| 1054 | if (skb_tailroom(skb)) { | 1054 | if (skb_tailroom(skb)) { |
| 1055 | skb->data[skb->len] = 0; | 1055 | skb->data[skb->len] = 0; |
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e0138ac8bf50..e974e5829e1a 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
| @@ -64,6 +64,8 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
| 64 | { USB_DEVICE(0x0cf3, 0x9170) }, | 64 | { USB_DEVICE(0x0cf3, 0x9170) }, |
| 65 | /* Atheros TG121N */ | 65 | /* Atheros TG121N */ |
| 66 | { USB_DEVICE(0x0cf3, 0x1001) }, | 66 | { USB_DEVICE(0x0cf3, 0x1001) }, |
| 67 | /* TP-Link TL-WN821N v2 */ | ||
| 68 | { USB_DEVICE(0x0cf3, 0x1002) }, | ||
| 67 | /* Cace Airpcap NX */ | 69 | /* Cace Airpcap NX */ |
| 68 | { USB_DEVICE(0xcace, 0x0300) }, | 70 | { USB_DEVICE(0xcace, 0x0300) }, |
| 69 | /* D-Link DWA 160A */ | 71 | /* D-Link DWA 160A */ |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 3234995e8881..0ad6d0b76e9e 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
| @@ -609,14 +609,24 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
| 609 | AR_PHY_CH1_EXT_CCA, | 609 | AR_PHY_CH1_EXT_CCA, |
| 610 | AR_PHY_CH2_EXT_CCA | 610 | AR_PHY_CH2_EXT_CCA |
| 611 | }; | 611 | }; |
| 612 | u8 chainmask; | 612 | u8 chainmask, rx_chain_status; |
| 613 | 613 | ||
| 614 | rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); | ||
| 614 | if (AR_SREV_9285(ah)) | 615 | if (AR_SREV_9285(ah)) |
| 615 | chainmask = 0x9; | 616 | chainmask = 0x9; |
| 616 | else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) | 617 | else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { |
| 617 | chainmask = 0x1B; | 618 | if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) |
| 618 | else | 619 | chainmask = 0x1B; |
| 619 | chainmask = 0x3F; | 620 | else |
| 621 | chainmask = 0x09; | ||
| 622 | } else { | ||
| 623 | if (rx_chain_status & 0x4) | ||
| 624 | chainmask = 0x3F; | ||
| 625 | else if (rx_chain_status & 0x2) | ||
| 626 | chainmask = 0x1B; | ||
| 627 | else | ||
| 628 | chainmask = 0x09; | ||
| 629 | } | ||
| 620 | 630 | ||
| 621 | h = ah->nfCalHist; | 631 | h = ah->nfCalHist; |
| 622 | 632 | ||
| @@ -697,6 +707,8 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) | |||
| 697 | noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; | 707 | noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; |
| 698 | else if (AR_SREV_9285(ah)) | 708 | else if (AR_SREV_9285(ah)) |
| 699 | noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; | 709 | noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; |
| 710 | else if (AR_SREV_9287(ah)) | ||
| 711 | noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE; | ||
| 700 | else | 712 | else |
| 701 | noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; | 713 | noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; |
| 702 | 714 | ||
| @@ -924,6 +936,7 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) | |||
| 924 | regVal |= (1 << (19 + i)); | 936 | regVal |= (1 << (19 + i)); |
| 925 | REG_WRITE(ah, 0x7834, regVal); | 937 | REG_WRITE(ah, 0x7834, regVal); |
| 926 | udelay(1); | 938 | udelay(1); |
| 939 | regVal = REG_READ(ah, 0x7834); | ||
| 927 | regVal &= (~(0x1 << (19 + i))); | 940 | regVal &= (~(0x1 << (19 + i))); |
| 928 | reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); | 941 | reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); |
| 929 | regVal |= (reg_field << (19 + i)); | 942 | regVal |= (reg_field << (19 + i)); |
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 019bcbba40ed..9028ab193e42 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
| @@ -28,6 +28,7 @@ extern const struct ath9k_percal_data adc_init_dc_cal; | |||
| 28 | #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 | 28 | #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 |
| 29 | #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 | 29 | #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 |
| 30 | #define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 | 30 | #define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 |
| 31 | #define AR_PHY_CCA_MAX_AR9287_GOOD_VALUE -118 | ||
| 31 | #define AR_PHY_CCA_MAX_HIGH_VALUE -62 | 32 | #define AR_PHY_CCA_MAX_HIGH_VALUE -62 |
| 32 | #define AR_PHY_CCA_MIN_BAD_VALUE -140 | 33 | #define AR_PHY_CCA_MIN_BAD_VALUE -140 |
| 33 | #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 | 34 | #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index ae7fb5dcb266..4071fc91da0a 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
| @@ -509,6 +509,8 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
| 509 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, | 509 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, |
| 510 | eep->baseEepHeader.dacLpMode); | 510 | eep->baseEepHeader.dacLpMode); |
| 511 | 511 | ||
| 512 | udelay(100); | ||
| 513 | |||
| 512 | REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, | 514 | REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, |
| 513 | pModal->miscBits >> 2); | 515 | pModal->miscBits >> 2); |
| 514 | 516 | ||
| @@ -902,7 +904,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
| 902 | u16 powerLimit) | 904 | u16 powerLimit) |
| 903 | { | 905 | { |
| 904 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ | 906 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ |
| 905 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ | 907 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ |
| 906 | 908 | ||
| 907 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 909 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
| 908 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | 910 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b6c6cca07812..ca7694caf364 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
| @@ -842,7 +842,7 @@ static void ath9k_hw_init_mode_regs(struct ath_hw *ah) | |||
| 842 | 842 | ||
| 843 | static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) | 843 | static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) |
| 844 | { | 844 | { |
| 845 | if (AR_SREV_9287_11(ah)) | 845 | if (AR_SREV_9287_11_OR_LATER(ah)) |
| 846 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 846 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
| 847 | ar9287Modes_rx_gain_9287_1_1, | 847 | ar9287Modes_rx_gain_9287_1_1, |
| 848 | ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); | 848 | 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) | |||
| 853 | else if (AR_SREV_9280_20(ah)) | 853 | else if (AR_SREV_9280_20(ah)) |
| 854 | ath9k_hw_init_rxgain_ini(ah); | 854 | ath9k_hw_init_rxgain_ini(ah); |
| 855 | 855 | ||
| 856 | if (AR_SREV_9287_11(ah)) { | 856 | if (AR_SREV_9287_11_OR_LATER(ah)) { |
| 857 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 857 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
| 858 | ar9287Modes_tx_gain_9287_1_1, | 858 | ar9287Modes_tx_gain_9287_1_1, |
| 859 | ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); | 859 | ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); |
| @@ -965,7 +965,7 @@ int ath9k_hw_init(struct ath_hw *ah) | |||
| 965 | ath9k_hw_init_mode_regs(ah); | 965 | ath9k_hw_init_mode_regs(ah); |
| 966 | 966 | ||
| 967 | if (ah->is_pciexpress) | 967 | if (ah->is_pciexpress) |
| 968 | ath9k_hw_configpcipowersave(ah, 0); | 968 | ath9k_hw_configpcipowersave(ah, 0, 0); |
| 969 | else | 969 | else |
| 970 | ath9k_hw_disablepcie(ah); | 970 | ath9k_hw_disablepcie(ah); |
| 971 | 971 | ||
| @@ -1273,6 +1273,15 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, | |||
| 1273 | */ | 1273 | */ |
| 1274 | REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | 1274 | REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); |
| 1275 | 1275 | ||
| 1276 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
| 1277 | val = REG_READ(ah, AR_PCU_MISC_MODE2) & | ||
| 1278 | (~AR_PCU_MISC_MODE2_HWWAR1); | ||
| 1279 | |||
| 1280 | if (AR_SREV_9287_10_OR_LATER(ah)) | ||
| 1281 | val = val & (~AR_PCU_MISC_MODE2_HWWAR2); | ||
| 1282 | |||
| 1283 | REG_WRITE(ah, AR_PCU_MISC_MODE2, val); | ||
| 1284 | } | ||
| 1276 | 1285 | ||
| 1277 | if (!AR_SREV_5416_20_OR_LATER(ah) || | 1286 | if (!AR_SREV_5416_20_OR_LATER(ah) || |
| 1278 | AR_SREV_9280_10_OR_LATER(ah)) | 1287 | AR_SREV_9280_10_OR_LATER(ah)) |
| @@ -1784,7 +1793,7 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 1784 | static bool ath9k_hw_chip_reset(struct ath_hw *ah, | 1793 | static bool ath9k_hw_chip_reset(struct ath_hw *ah, |
| 1785 | struct ath9k_channel *chan) | 1794 | struct ath9k_channel *chan) |
| 1786 | { | 1795 | { |
| 1787 | if (OLC_FOR_AR9280_20_LATER) { | 1796 | if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) { |
| 1788 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) | 1797 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) |
| 1789 | return false; | 1798 | return false; |
| 1790 | } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) | 1799 | } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) |
| @@ -2338,6 +2347,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2338 | struct ath9k_channel *curchan = ah->curchan; | 2347 | struct ath9k_channel *curchan = ah->curchan; |
| 2339 | u32 saveDefAntenna; | 2348 | u32 saveDefAntenna; |
| 2340 | u32 macStaId1; | 2349 | u32 macStaId1; |
| 2350 | u64 tsf = 0; | ||
| 2341 | int i, rx_chainmask, r; | 2351 | int i, rx_chainmask, r; |
| 2342 | 2352 | ||
| 2343 | ah->extprotspacing = sc->ht_extprotspacing; | 2353 | ah->extprotspacing = sc->ht_extprotspacing; |
| @@ -2347,7 +2357,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2347 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | 2357 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
| 2348 | return -EIO; | 2358 | return -EIO; |
| 2349 | 2359 | ||
| 2350 | if (curchan) | 2360 | if (curchan && !ah->chip_fullsleep) |
| 2351 | ath9k_hw_getnf(ah, curchan); | 2361 | ath9k_hw_getnf(ah, curchan); |
| 2352 | 2362 | ||
| 2353 | if (bChannelChange && | 2363 | if (bChannelChange && |
| @@ -2356,8 +2366,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2356 | (chan->channel != ah->curchan->channel) && | 2366 | (chan->channel != ah->curchan->channel) && |
| 2357 | ((chan->channelFlags & CHANNEL_ALL) == | 2367 | ((chan->channelFlags & CHANNEL_ALL) == |
| 2358 | (ah->curchan->channelFlags & CHANNEL_ALL)) && | 2368 | (ah->curchan->channelFlags & CHANNEL_ALL)) && |
| 2359 | (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) && | 2369 | !(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) || |
| 2360 | !IS_CHAN_A_5MHZ_SPACED(ah->curchan)))) { | 2370 | IS_CHAN_A_5MHZ_SPACED(ah->curchan))) { |
| 2361 | 2371 | ||
| 2362 | if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) { | 2372 | if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) { |
| 2363 | ath9k_hw_loadnf(ah, ah->curchan); | 2373 | ath9k_hw_loadnf(ah, ah->curchan); |
| @@ -2372,6 +2382,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2372 | 2382 | ||
| 2373 | macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; | 2383 | macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; |
| 2374 | 2384 | ||
| 2385 | /* For chips on which RTC reset is done, save TSF before it gets cleared */ | ||
| 2386 | if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | ||
| 2387 | tsf = ath9k_hw_gettsf64(ah); | ||
| 2388 | |||
| 2375 | saveLedState = REG_READ(ah, AR_CFG_LED) & | 2389 | saveLedState = REG_READ(ah, AR_CFG_LED) & |
| 2376 | (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | | 2390 | (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | |
| 2377 | AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); | 2391 | AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); |
| @@ -2398,6 +2412,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
| 2398 | udelay(50); | 2412 | udelay(50); |
| 2399 | } | 2413 | } |
| 2400 | 2414 | ||
| 2415 | /* Restore TSF */ | ||
| 2416 | if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | ||
| 2417 | ath9k_hw_settsf64(ah, tsf); | ||
| 2418 | |||
| 2401 | if (AR_SREV_9280_10_OR_LATER(ah)) | 2419 | if (AR_SREV_9280_10_OR_LATER(ah)) |
| 2402 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); | 2420 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); |
| 2403 | 2421 | ||
| @@ -3005,9 +3023,10 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
| 3005 | * Programming the SerDes must go through the same 288 bit serial shift | 3023 | * Programming the SerDes must go through the same 288 bit serial shift |
| 3006 | * register as the other analog registers. Hence the 9 writes. | 3024 | * register as the other analog registers. Hence the 9 writes. |
| 3007 | */ | 3025 | */ |
| 3008 | void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) | 3026 | void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) |
| 3009 | { | 3027 | { |
| 3010 | u8 i; | 3028 | u8 i; |
| 3029 | u32 val; | ||
| 3011 | 3030 | ||
| 3012 | if (ah->is_pciexpress != true) | 3031 | if (ah->is_pciexpress != true) |
| 3013 | return; | 3032 | return; |
| @@ -3017,84 +3036,113 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) | |||
| 3017 | return; | 3036 | return; |
| 3018 | 3037 | ||
| 3019 | /* Nothing to do on restore for 11N */ | 3038 | /* Nothing to do on restore for 11N */ |
| 3020 | if (restore) | 3039 | if (!restore) { |
| 3021 | return; | 3040 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
| 3041 | /* | ||
| 3042 | * AR9280 2.0 or later chips use SerDes values from the | ||
| 3043 | * initvals.h initialized depending on chipset during | ||
| 3044 | * ath9k_hw_init() | ||
| 3045 | */ | ||
| 3046 | for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { | ||
| 3047 | REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), | ||
| 3048 | INI_RA(&ah->iniPcieSerdes, i, 1)); | ||
| 3049 | } | ||
| 3050 | } else if (AR_SREV_9280(ah) && | ||
| 3051 | (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { | ||
| 3052 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); | ||
| 3053 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | ||
| 3054 | |||
| 3055 | /* RX shut off when elecidle is asserted */ | ||
| 3056 | REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); | ||
| 3057 | REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); | ||
| 3058 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); | ||
| 3059 | |||
| 3060 | /* Shut off CLKREQ active in L1 */ | ||
| 3061 | if (ah->config.pcie_clock_req) | ||
| 3062 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); | ||
| 3063 | else | ||
| 3064 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); | ||
| 3022 | 3065 | ||
| 3023 | if (AR_SREV_9280_20_OR_LATER(ah)) { | 3066 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); |
| 3024 | /* | 3067 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); |
| 3025 | * AR9280 2.0 or later chips use SerDes values from the | 3068 | REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); |
| 3026 | * initvals.h initialized depending on chipset during | ||
| 3027 | * ath9k_hw_init() | ||
| 3028 | */ | ||
| 3029 | for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { | ||
| 3030 | REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), | ||
| 3031 | INI_RA(&ah->iniPcieSerdes, i, 1)); | ||
| 3032 | } | ||
| 3033 | } else if (AR_SREV_9280(ah) && | ||
| 3034 | (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { | ||
| 3035 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); | ||
| 3036 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | ||
| 3037 | 3069 | ||
| 3038 | /* RX shut off when elecidle is asserted */ | 3070 | /* Load the new settings */ |
| 3039 | REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); | 3071 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); |
| 3040 | REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); | ||
| 3041 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); | ||
| 3042 | 3072 | ||
| 3043 | /* Shut off CLKREQ active in L1 */ | 3073 | } else { |
| 3044 | if (ah->config.pcie_clock_req) | 3074 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); |
| 3045 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); | 3075 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); |
| 3046 | else | ||
| 3047 | REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); | ||
| 3048 | |||
| 3049 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | ||
| 3050 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | ||
| 3051 | REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); | ||
| 3052 | 3076 | ||
| 3053 | /* Load the new settings */ | 3077 | /* RX shut off when elecidle is asserted */ |
| 3054 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | 3078 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); |
| 3079 | REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); | ||
| 3080 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); | ||
| 3055 | 3081 | ||
| 3056 | } else { | 3082 | /* |
| 3057 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); | 3083 | * Ignore ah->ah_config.pcie_clock_req setting for |
| 3058 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | 3084 | * pre-AR9280 11n |
| 3085 | */ | ||
| 3086 | REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); | ||
| 3059 | 3087 | ||
| 3060 | /* RX shut off when elecidle is asserted */ | 3088 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); |
| 3061 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); | 3089 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); |
| 3062 | REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); | 3090 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); |
| 3063 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); | ||
| 3064 | 3091 | ||
| 3065 | /* | 3092 | /* Load the new settings */ |
| 3066 | * Ignore ah->ah_config.pcie_clock_req setting for | 3093 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); |
| 3067 | * pre-AR9280 11n | 3094 | } |
| 3068 | */ | ||
| 3069 | REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); | ||
| 3070 | 3095 | ||
| 3071 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | 3096 | udelay(1000); |
| 3072 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | ||
| 3073 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); | ||
| 3074 | 3097 | ||
| 3075 | /* Load the new settings */ | 3098 | /* set bit 19 to allow forcing of pcie core into L1 state */ |
| 3076 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | 3099 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); |
| 3077 | } | ||
| 3078 | 3100 | ||
| 3079 | udelay(1000); | 3101 | /* Several PCIe massages to ensure proper behaviour */ |
| 3102 | if (ah->config.pcie_waen) { | ||
| 3103 | val = ah->config.pcie_waen; | ||
| 3104 | if (!power_off) | ||
| 3105 | val &= (~AR_WA_D3_L1_DISABLE); | ||
| 3106 | } else { | ||
| 3107 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || | ||
| 3108 | AR_SREV_9287(ah)) { | ||
| 3109 | val = AR9285_WA_DEFAULT; | ||
| 3110 | if (!power_off) | ||
| 3111 | val &= (~AR_WA_D3_L1_DISABLE); | ||
| 3112 | } else if (AR_SREV_9280(ah)) { | ||
| 3113 | /* | ||
| 3114 | * On AR9280 chips bit 22 of 0x4004 needs to be | ||
| 3115 | * set otherwise card may disappear. | ||
| 3116 | */ | ||
| 3117 | val = AR9280_WA_DEFAULT; | ||
| 3118 | if (!power_off) | ||
| 3119 | val &= (~AR_WA_D3_L1_DISABLE); | ||
| 3120 | } else | ||
| 3121 | val = AR_WA_DEFAULT; | ||
| 3122 | } | ||
| 3080 | 3123 | ||
| 3081 | /* set bit 19 to allow forcing of pcie core into L1 state */ | 3124 | REG_WRITE(ah, AR_WA, val); |
| 3082 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); | 3125 | } |
| 3083 | 3126 | ||
| 3084 | /* Several PCIe massages to ensure proper behaviour */ | 3127 | if (power_off) { |
| 3085 | if (ah->config.pcie_waen) { | ||
| 3086 | REG_WRITE(ah, AR_WA, ah->config.pcie_waen); | ||
| 3087 | } else { | ||
| 3088 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) | ||
| 3089 | REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); | ||
| 3090 | /* | 3128 | /* |
| 3091 | * On AR9280 chips bit 22 of 0x4004 needs to be set to | 3129 | * Set PCIe workaround bits |
| 3092 | * otherwise card may disappear. | 3130 | * bit 14 in WA register (disable L1) should only |
| 3131 | * be set when device enters D3 and be cleared | ||
| 3132 | * when device comes back to D0. | ||
| 3093 | */ | 3133 | */ |
| 3094 | else if (AR_SREV_9280(ah)) | 3134 | if (ah->config.pcie_waen) { |
| 3095 | REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT); | 3135 | if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) |
| 3096 | else | 3136 | REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); |
| 3097 | REG_WRITE(ah, AR_WA, AR_WA_DEFAULT); | 3137 | } else { |
| 3138 | if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) || | ||
| 3139 | AR_SREV_9287(ah)) && | ||
| 3140 | (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || | ||
| 3141 | (AR_SREV_9280(ah) && | ||
| 3142 | (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { | ||
| 3143 | REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); | ||
| 3144 | } | ||
| 3145 | } | ||
| 3098 | } | 3146 | } |
| 3099 | } | 3147 | } |
| 3100 | 3148 | ||
| @@ -3652,15 +3700,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
| 3652 | } | 3700 | } |
| 3653 | #endif | 3701 | #endif |
| 3654 | 3702 | ||
| 3655 | if ((ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || | 3703 | pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; |
| 3656 | (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) || | ||
| 3657 | (ah->hw_version.macVersion == AR_SREV_VERSION_9160) || | ||
| 3658 | (ah->hw_version.macVersion == AR_SREV_VERSION_9100) || | ||
| 3659 | (ah->hw_version.macVersion == AR_SREV_VERSION_9280) || | ||
| 3660 | (ah->hw_version.macVersion == AR_SREV_VERSION_9285)) | ||
| 3661 | pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; | ||
| 3662 | else | ||
| 3663 | pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; | ||
| 3664 | 3704 | ||
| 3665 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) | 3705 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) |
| 3666 | pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; | 3706 | pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 9106a0b537dd..b89234571829 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
| @@ -106,7 +106,7 @@ | |||
| 106 | #define AH_TSF_WRITE_TIMEOUT 100 /* (us) */ | 106 | #define AH_TSF_WRITE_TIMEOUT 100 /* (us) */ |
| 107 | #define AH_TIME_QUANTUM 10 | 107 | #define AH_TIME_QUANTUM 10 |
| 108 | #define AR_KEYTABLE_SIZE 128 | 108 | #define AR_KEYTABLE_SIZE 128 |
| 109 | #define POWER_UP_TIME 200000 | 109 | #define POWER_UP_TIME 10000 |
| 110 | #define SPUR_RSSI_THRESH 40 | 110 | #define SPUR_RSSI_THRESH 40 |
| 111 | 111 | ||
| 112 | #define CAB_TIMEOUT_VAL 10 | 112 | #define CAB_TIMEOUT_VAL 10 |
| @@ -650,7 +650,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
| 650 | const struct ath9k_beacon_state *bs); | 650 | const struct ath9k_beacon_state *bs); |
| 651 | bool ath9k_hw_setpower(struct ath_hw *ah, | 651 | bool ath9k_hw_setpower(struct ath_hw *ah, |
| 652 | enum ath9k_power_mode mode); | 652 | enum ath9k_power_mode mode); |
| 653 | void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore); | 653 | void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off); |
| 654 | 654 | ||
| 655 | /* Interrupt Handling */ | 655 | /* Interrupt Handling */ |
| 656 | bool ath9k_hw_intrpend(struct ath_hw *ah); | 656 | bool ath9k_hw_intrpend(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3dc7b5a13e64..52bed89063d4 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -1131,7 +1131,7 @@ void ath_radio_enable(struct ath_softc *sc) | |||
| 1131 | int r; | 1131 | int r; |
| 1132 | 1132 | ||
| 1133 | ath9k_ps_wakeup(sc); | 1133 | ath9k_ps_wakeup(sc); |
| 1134 | ath9k_hw_configpcipowersave(ah, 0); | 1134 | ath9k_hw_configpcipowersave(ah, 0, 0); |
| 1135 | 1135 | ||
| 1136 | if (!ah->curchan) | 1136 | if (!ah->curchan) |
| 1137 | ah->curchan = ath_get_curchannel(sc, sc->hw); | 1137 | ah->curchan = ath_get_curchannel(sc, sc->hw); |
| @@ -1202,7 +1202,7 @@ void ath_radio_disable(struct ath_softc *sc) | |||
| 1202 | spin_unlock_bh(&sc->sc_resetlock); | 1202 | spin_unlock_bh(&sc->sc_resetlock); |
| 1203 | 1203 | ||
| 1204 | ath9k_hw_phy_disable(ah); | 1204 | ath9k_hw_phy_disable(ah); |
| 1205 | ath9k_hw_configpcipowersave(ah, 1); | 1205 | ath9k_hw_configpcipowersave(ah, 1, 1); |
| 1206 | ath9k_ps_restore(sc); | 1206 | ath9k_ps_restore(sc); |
| 1207 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); | 1207 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); |
| 1208 | } | 1208 | } |
| @@ -1226,11 +1226,6 @@ static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) | |||
| 1226 | bool blocked = !!ath_is_rfkill_set(sc); | 1226 | bool blocked = !!ath_is_rfkill_set(sc); |
| 1227 | 1227 | ||
| 1228 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); | 1228 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); |
| 1229 | |||
| 1230 | if (blocked) | ||
| 1231 | ath_radio_disable(sc); | ||
| 1232 | else | ||
| 1233 | ath_radio_enable(sc); | ||
| 1234 | } | 1229 | } |
| 1235 | 1230 | ||
| 1236 | static void ath_start_rfkill_poll(struct ath_softc *sc) | 1231 | static void ath_start_rfkill_poll(struct ath_softc *sc) |
| @@ -1260,6 +1255,7 @@ void ath_detach(struct ath_softc *sc) | |||
| 1260 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); | 1255 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); |
| 1261 | 1256 | ||
| 1262 | ath_deinit_leds(sc); | 1257 | ath_deinit_leds(sc); |
| 1258 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | ||
| 1263 | 1259 | ||
| 1264 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 1260 | for (i = 0; i < sc->num_sec_wiphy; i++) { |
| 1265 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 1261 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; |
| @@ -1942,7 +1938,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
| 1942 | init_channel = ath_get_curchannel(sc, hw); | 1938 | init_channel = ath_get_curchannel(sc, hw); |
| 1943 | 1939 | ||
| 1944 | /* Reset SERDES registers */ | 1940 | /* Reset SERDES registers */ |
| 1945 | ath9k_hw_configpcipowersave(sc->sc_ah, 0); | 1941 | ath9k_hw_configpcipowersave(sc->sc_ah, 0, 0); |
| 1946 | 1942 | ||
| 1947 | /* | 1943 | /* |
| 1948 | * The basic interface to setting the hardware in a good | 1944 | * The basic interface to setting the hardware in a good |
| @@ -2166,11 +2162,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
| 2166 | } else | 2162 | } else |
| 2167 | sc->rx.rxlink = NULL; | 2163 | sc->rx.rxlink = NULL; |
| 2168 | 2164 | ||
| 2169 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | ||
| 2170 | |||
| 2171 | /* disable HAL and put h/w to sleep */ | 2165 | /* disable HAL and put h/w to sleep */ |
| 2172 | ath9k_hw_disable(sc->sc_ah); | 2166 | ath9k_hw_disable(sc->sc_ah); |
| 2173 | ath9k_hw_configpcipowersave(sc->sc_ah, 1); | 2167 | ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1); |
| 2174 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); | 2168 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); |
| 2175 | 2169 | ||
| 2176 | sc->sc_flags |= SC_OP_INVALID; | 2170 | sc->sc_flags |= SC_OP_INVALID; |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index e5c29eb86e80..d83b77f821e9 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
| @@ -676,8 +676,9 @@ | |||
| 676 | #define AR_RC_HOSTIF 0x00000100 | 676 | #define AR_RC_HOSTIF 0x00000100 |
| 677 | 677 | ||
| 678 | #define AR_WA 0x4004 | 678 | #define AR_WA 0x4004 |
| 679 | #define AR_WA_D3_L1_DISABLE (1 << 14) | ||
| 679 | #define AR9285_WA_DEFAULT 0x004a05cb | 680 | #define AR9285_WA_DEFAULT 0x004a05cb |
| 680 | #define AR9280_WA_DEFAULT 0x0040073f | 681 | #define AR9280_WA_DEFAULT 0x0040073b |
| 681 | #define AR_WA_DEFAULT 0x0000073f | 682 | #define AR_WA_DEFAULT 0x0000073f |
| 682 | 683 | ||
| 683 | 684 | ||
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 83e38134accb..54ea61c15d8b 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
| @@ -61,11 +61,28 @@ config B43_PCMCIA | |||
| 61 | 61 | ||
| 62 | If unsure, say N. | 62 | If unsure, say N. |
| 63 | 63 | ||
| 64 | config B43_SDIO | ||
| 65 | bool "Broadcom 43xx SDIO device support (EXPERIMENTAL)" | ||
| 66 | depends on B43 && SSB_SDIOHOST_POSSIBLE && EXPERIMENTAL | ||
| 67 | select SSB_SDIOHOST | ||
| 68 | ---help--- | ||
| 69 | Broadcom 43xx device support for Soft-MAC SDIO devices. | ||
| 70 | |||
| 71 | With this config option you can drive Soft-MAC b43 cards with a | ||
| 72 | Secure Digital I/O interface. | ||
| 73 | This includes the WLAN daughter card found on the Nintendo Wii | ||
| 74 | video game console. | ||
| 75 | Note that this does not support Broadcom 43xx Full-MAC devices. | ||
| 76 | |||
| 77 | It's safe to select Y here, even if you don't have a B43 SDIO device. | ||
| 78 | |||
| 79 | If unsure, say N. | ||
| 80 | |||
| 64 | # Data transfers to the device via PIO | 81 | # Data transfers to the device via PIO |
| 65 | # This is only needed on PCMCIA devices. All others can do DMA properly. | 82 | # This is only needed on PCMCIA and SDIO devices. All others can do DMA properly. |
| 66 | config B43_PIO | 83 | config B43_PIO |
| 67 | bool | 84 | bool |
| 68 | depends on B43 && (B43_PCMCIA || B43_FORCE_PIO) | 85 | depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO) |
| 69 | select SSB_BLOCKIO | 86 | select SSB_BLOCKIO |
| 70 | default y | 87 | default y |
| 71 | 88 | ||
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index da379f4b0c3a..84772a2542dc 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile | |||
| @@ -16,6 +16,7 @@ b43-$(CONFIG_B43_PIO) += pio.o | |||
| 16 | b43-y += rfkill.o | 16 | b43-y += rfkill.o |
| 17 | b43-$(CONFIG_B43_LEDS) += leds.o | 17 | b43-$(CONFIG_B43_LEDS) += leds.o |
| 18 | b43-$(CONFIG_B43_PCMCIA) += pcmcia.o | 18 | b43-$(CONFIG_B43_PCMCIA) += pcmcia.o |
| 19 | b43-$(CONFIG_B43_SDIO) += sdio.o | ||
| 19 | b43-$(CONFIG_B43_DEBUG) += debugfs.o | 20 | b43-$(CONFIG_B43_DEBUG) += debugfs.o |
| 20 | 21 | ||
| 21 | obj-$(CONFIG_B43) += b43.o | 22 | obj-$(CONFIG_B43) += b43.o |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 09cfe68537b6..fa1549a03c71 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
| @@ -629,13 +629,6 @@ struct b43_wl { | |||
| 629 | * from the mac80211 subsystem. */ | 629 | * from the mac80211 subsystem. */ |
| 630 | u16 mac80211_initially_registered_queues; | 630 | u16 mac80211_initially_registered_queues; |
| 631 | 631 | ||
| 632 | /* R/W lock for data transmission. | ||
| 633 | * Transmissions on 2+ queues can run concurrently, but somebody else | ||
| 634 | * might sync with TX by write_lock_irqsave()'ing. */ | ||
| 635 | rwlock_t tx_lock; | ||
| 636 | /* Lock for LEDs access. */ | ||
| 637 | spinlock_t leds_lock; | ||
| 638 | |||
| 639 | /* We can only have one operating interface (802.11 core) | 632 | /* We can only have one operating interface (802.11 core) |
| 640 | * at a time. General information about this interface follows. | 633 | * at a time. General information about this interface follows. |
| 641 | */ | 634 | */ |
| @@ -686,6 +679,9 @@ struct b43_wl { | |||
| 686 | struct work_struct tx_work; | 679 | struct work_struct tx_work; |
| 687 | /* Queue of packets to be transmitted. */ | 680 | /* Queue of packets to be transmitted. */ |
| 688 | struct sk_buff_head tx_queue; | 681 | struct sk_buff_head tx_queue; |
| 682 | |||
| 683 | /* The device LEDs. */ | ||
| 684 | struct b43_leds leds; | ||
| 689 | }; | 685 | }; |
| 690 | 686 | ||
| 691 | /* The type of the firmware file. */ | 687 | /* The type of the firmware file. */ |
| @@ -768,13 +764,10 @@ struct b43_wldev { | |||
| 768 | /* The device initialization status. | 764 | /* The device initialization status. |
| 769 | * Use b43_status() to query. */ | 765 | * Use b43_status() to query. */ |
| 770 | atomic_t __init_status; | 766 | atomic_t __init_status; |
| 771 | /* Saved init status for handling suspend. */ | ||
| 772 | int suspend_init_status; | ||
| 773 | 767 | ||
| 774 | bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ | 768 | bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ |
| 775 | bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ | 769 | bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ |
| 776 | bool radio_hw_enable; /* saved state of radio hardware enabled state */ | 770 | bool radio_hw_enable; /* saved state of radio hardware enabled state */ |
| 777 | bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */ | ||
| 778 | bool qos_enabled; /* TRUE, if QoS is used. */ | 771 | bool qos_enabled; /* TRUE, if QoS is used. */ |
| 779 | bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ | 772 | bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ |
| 780 | 773 | ||
| @@ -794,12 +787,6 @@ struct b43_wldev { | |||
| 794 | /* Various statistics about the physical device. */ | 787 | /* Various statistics about the physical device. */ |
| 795 | struct b43_stats stats; | 788 | struct b43_stats stats; |
| 796 | 789 | ||
| 797 | /* The device LEDs. */ | ||
| 798 | struct b43_led led_tx; | ||
| 799 | struct b43_led led_rx; | ||
| 800 | struct b43_led led_assoc; | ||
| 801 | struct b43_led led_radio; | ||
| 802 | |||
| 803 | /* Reason code of the last interrupt. */ | 790 | /* Reason code of the last interrupt. */ |
| 804 | u32 irq_reason; | 791 | u32 irq_reason; |
| 805 | u32 dma_reason[6]; | 792 | u32 dma_reason[6]; |
| @@ -830,6 +817,10 @@ struct b43_wldev { | |||
| 830 | /* Debugging stuff follows. */ | 817 | /* Debugging stuff follows. */ |
| 831 | #ifdef CONFIG_B43_DEBUG | 818 | #ifdef CONFIG_B43_DEBUG |
| 832 | struct b43_dfsentry *dfsentry; | 819 | struct b43_dfsentry *dfsentry; |
| 820 | unsigned int irq_count; | ||
| 821 | unsigned int irq_bit_count[32]; | ||
| 822 | unsigned int tx_count; | ||
| 823 | unsigned int rx_count; | ||
| 833 | #endif | 824 | #endif |
| 834 | }; | 825 | }; |
| 835 | 826 | ||
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 8f64943e3f60..80b19a44a407 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c | |||
| @@ -689,6 +689,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev) | |||
| 689 | add_dyn_dbg("debug_lo", B43_DBG_LO, 0); | 689 | add_dyn_dbg("debug_lo", B43_DBG_LO, 0); |
| 690 | add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); | 690 | add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); |
| 691 | add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0); | 691 | add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0); |
| 692 | add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, 0); | ||
| 692 | 693 | ||
| 693 | #undef add_dyn_dbg | 694 | #undef add_dyn_dbg |
| 694 | } | 695 | } |
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index e47b4b488b04..822aad8842f4 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h | |||
| @@ -13,6 +13,7 @@ enum b43_dyndbg { /* Dynamic debugging features */ | |||
| 13 | B43_DBG_LO, | 13 | B43_DBG_LO, |
| 14 | B43_DBG_FIRMWARE, | 14 | B43_DBG_FIRMWARE, |
| 15 | B43_DBG_KEYS, | 15 | B43_DBG_KEYS, |
| 16 | B43_DBG_VERBOSESTATS, | ||
| 16 | __B43_NR_DYNDBG, | 17 | __B43_NR_DYNDBG, |
| 17 | }; | 18 | }; |
| 18 | 19 | ||
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index a467ee260a19..8701034569fa 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
| @@ -1428,9 +1428,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
| 1428 | ring->nr_failed_tx_packets++; | 1428 | ring->nr_failed_tx_packets++; |
| 1429 | ring->nr_total_packet_tries += status->frame_count; | 1429 | ring->nr_total_packet_tries += status->frame_count; |
| 1430 | #endif /* DEBUG */ | 1430 | #endif /* DEBUG */ |
| 1431 | ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb); | 1431 | ieee80211_tx_status(dev->wl->hw, meta->skb); |
| 1432 | 1432 | ||
| 1433 | /* skb is freed by ieee80211_tx_status_irqsafe() */ | 1433 | /* skb is freed by ieee80211_tx_status() */ |
| 1434 | meta->skb = NULL; | 1434 | meta->skb = NULL; |
| 1435 | } else { | 1435 | } else { |
| 1436 | /* No need to call free_descriptor_buffer here, as | 1436 | /* No need to call free_descriptor_buffer here, as |
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c index c8b317094c31..fbe3d4f62ce2 100644 --- a/drivers/net/wireless/b43/leds.c +++ b/drivers/net/wireless/b43/leds.c | |||
| @@ -34,57 +34,88 @@ | |||
| 34 | static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index, | 34 | static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index, |
| 35 | bool activelow) | 35 | bool activelow) |
| 36 | { | 36 | { |
| 37 | struct b43_wl *wl = dev->wl; | ||
| 38 | unsigned long flags; | ||
| 39 | u16 ctl; | 37 | u16 ctl; |
| 40 | 38 | ||
| 41 | spin_lock_irqsave(&wl->leds_lock, flags); | ||
| 42 | ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); | 39 | ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); |
| 43 | if (activelow) | 40 | if (activelow) |
| 44 | ctl &= ~(1 << led_index); | 41 | ctl &= ~(1 << led_index); |
| 45 | else | 42 | else |
| 46 | ctl |= (1 << led_index); | 43 | ctl |= (1 << led_index); |
| 47 | b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); | 44 | b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); |
| 48 | spin_unlock_irqrestore(&wl->leds_lock, flags); | ||
| 49 | } | 45 | } |
| 50 | 46 | ||
| 51 | static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index, | 47 | static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index, |
| 52 | bool activelow) | 48 | bool activelow) |
| 53 | { | 49 | { |
| 54 | struct b43_wl *wl = dev->wl; | ||
| 55 | unsigned long flags; | ||
| 56 | u16 ctl; | 50 | u16 ctl; |
| 57 | 51 | ||
| 58 | spin_lock_irqsave(&wl->leds_lock, flags); | ||
| 59 | ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); | 52 | ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); |
| 60 | if (activelow) | 53 | if (activelow) |
| 61 | ctl |= (1 << led_index); | 54 | ctl |= (1 << led_index); |
| 62 | else | 55 | else |
| 63 | ctl &= ~(1 << led_index); | 56 | ctl &= ~(1 << led_index); |
| 64 | b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); | 57 | b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); |
| 65 | spin_unlock_irqrestore(&wl->leds_lock, flags); | ||
| 66 | } | 58 | } |
| 67 | 59 | ||
| 68 | /* Callback from the LED subsystem. */ | 60 | static void b43_led_update(struct b43_wldev *dev, |
| 69 | static void b43_led_brightness_set(struct led_classdev *led_dev, | 61 | struct b43_led *led) |
| 70 | enum led_brightness brightness) | ||
| 71 | { | 62 | { |
| 72 | struct b43_led *led = container_of(led_dev, struct b43_led, led_dev); | ||
| 73 | struct b43_wldev *dev = led->dev; | ||
| 74 | bool radio_enabled; | 63 | bool radio_enabled; |
| 64 | bool turn_on; | ||
| 75 | 65 | ||
| 76 | if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) | 66 | if (!led->wl) |
| 77 | return; | 67 | return; |
| 78 | 68 | ||
| 79 | /* Checking the radio-enabled status here is slightly racy, | ||
| 80 | * but we want to avoid the locking overhead and we don't care | ||
| 81 | * whether the LED has the wrong state for a second. */ | ||
| 82 | radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable); | 69 | radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable); |
| 83 | 70 | ||
| 84 | if (brightness == LED_OFF || !radio_enabled) | 71 | /* The led->state read is racy, but we don't care. In case we raced |
| 85 | b43_led_turn_off(dev, led->index, led->activelow); | 72 | * with the brightness_set handler, we will be called again soon |
| 73 | * to fixup our state. */ | ||
| 74 | if (radio_enabled) | ||
| 75 | turn_on = atomic_read(&led->state) != LED_OFF; | ||
| 86 | else | 76 | else |
| 77 | turn_on = 0; | ||
| 78 | if (turn_on == led->hw_state) | ||
| 79 | return; | ||
| 80 | led->hw_state = turn_on; | ||
| 81 | |||
| 82 | if (turn_on) | ||
| 87 | b43_led_turn_on(dev, led->index, led->activelow); | 83 | b43_led_turn_on(dev, led->index, led->activelow); |
| 84 | else | ||
| 85 | b43_led_turn_off(dev, led->index, led->activelow); | ||
| 86 | } | ||
| 87 | |||
| 88 | static void b43_leds_work(struct work_struct *work) | ||
| 89 | { | ||
| 90 | struct b43_leds *leds = container_of(work, struct b43_leds, work); | ||
| 91 | struct b43_wl *wl = container_of(leds, struct b43_wl, leds); | ||
| 92 | struct b43_wldev *dev; | ||
| 93 | |||
| 94 | mutex_lock(&wl->mutex); | ||
| 95 | dev = wl->current_dev; | ||
| 96 | if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED)) | ||
| 97 | goto out_unlock; | ||
| 98 | |||
| 99 | b43_led_update(dev, &wl->leds.led_tx); | ||
| 100 | b43_led_update(dev, &wl->leds.led_rx); | ||
| 101 | b43_led_update(dev, &wl->leds.led_radio); | ||
| 102 | b43_led_update(dev, &wl->leds.led_assoc); | ||
| 103 | |||
| 104 | out_unlock: | ||
| 105 | mutex_unlock(&wl->mutex); | ||
| 106 | } | ||
| 107 | |||
| 108 | /* Callback from the LED subsystem. */ | ||
| 109 | static void b43_led_brightness_set(struct led_classdev *led_dev, | ||
| 110 | enum led_brightness brightness) | ||
| 111 | { | ||
| 112 | struct b43_led *led = container_of(led_dev, struct b43_led, led_dev); | ||
| 113 | struct b43_wl *wl = led->wl; | ||
| 114 | |||
| 115 | if (likely(!wl->leds.stop)) { | ||
| 116 | atomic_set(&led->state, brightness); | ||
| 117 | ieee80211_queue_work(wl->hw, &wl->leds.work); | ||
| 118 | } | ||
| 88 | } | 119 | } |
| 89 | 120 | ||
| 90 | static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, | 121 | static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, |
| @@ -93,15 +124,15 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, | |||
| 93 | { | 124 | { |
| 94 | int err; | 125 | int err; |
| 95 | 126 | ||
| 96 | b43_led_turn_off(dev, led_index, activelow); | 127 | if (led->wl) |
| 97 | if (led->dev) | ||
| 98 | return -EEXIST; | 128 | return -EEXIST; |
| 99 | if (!default_trigger) | 129 | if (!default_trigger) |
| 100 | return -EINVAL; | 130 | return -EINVAL; |
| 101 | led->dev = dev; | 131 | led->wl = dev->wl; |
| 102 | led->index = led_index; | 132 | led->index = led_index; |
| 103 | led->activelow = activelow; | 133 | led->activelow = activelow; |
| 104 | strncpy(led->name, name, sizeof(led->name)); | 134 | strncpy(led->name, name, sizeof(led->name)); |
| 135 | atomic_set(&led->state, 0); | ||
| 105 | 136 | ||
| 106 | led->led_dev.name = led->name; | 137 | led->led_dev.name = led->name; |
| 107 | led->led_dev.default_trigger = default_trigger; | 138 | led->led_dev.default_trigger = default_trigger; |
| @@ -110,19 +141,19 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, | |||
| 110 | err = led_classdev_register(dev->dev->dev, &led->led_dev); | 141 | err = led_classdev_register(dev->dev->dev, &led->led_dev); |
| 111 | if (err) { | 142 | if (err) { |
| 112 | b43warn(dev->wl, "LEDs: Failed to register %s\n", name); | 143 | b43warn(dev->wl, "LEDs: Failed to register %s\n", name); |
| 113 | led->dev = NULL; | 144 | led->wl = NULL; |
| 114 | return err; | 145 | return err; |
| 115 | } | 146 | } |
| 147 | |||
| 116 | return 0; | 148 | return 0; |
| 117 | } | 149 | } |
| 118 | 150 | ||
| 119 | static void b43_unregister_led(struct b43_led *led) | 151 | static void b43_unregister_led(struct b43_led *led) |
| 120 | { | 152 | { |
| 121 | if (!led->dev) | 153 | if (!led->wl) |
| 122 | return; | 154 | return; |
| 123 | led_classdev_unregister(&led->led_dev); | 155 | led_classdev_unregister(&led->led_dev); |
| 124 | b43_led_turn_off(led->dev, led->index, led->activelow); | 156 | led->wl = NULL; |
| 125 | led->dev = NULL; | ||
| 126 | } | 157 | } |
| 127 | 158 | ||
| 128 | static void b43_map_led(struct b43_wldev *dev, | 159 | static void b43_map_led(struct b43_wldev *dev, |
| @@ -137,24 +168,20 @@ static void b43_map_led(struct b43_wldev *dev, | |||
| 137 | * generic LED triggers. */ | 168 | * generic LED triggers. */ |
| 138 | switch (behaviour) { | 169 | switch (behaviour) { |
| 139 | case B43_LED_INACTIVE: | 170 | case B43_LED_INACTIVE: |
| 140 | break; | ||
| 141 | case B43_LED_OFF: | 171 | case B43_LED_OFF: |
| 142 | b43_led_turn_off(dev, led_index, activelow); | ||
| 143 | break; | ||
| 144 | case B43_LED_ON: | 172 | case B43_LED_ON: |
| 145 | b43_led_turn_on(dev, led_index, activelow); | ||
| 146 | break; | 173 | break; |
| 147 | case B43_LED_ACTIVITY: | 174 | case B43_LED_ACTIVITY: |
| 148 | case B43_LED_TRANSFER: | 175 | case B43_LED_TRANSFER: |
| 149 | case B43_LED_APTRANSFER: | 176 | case B43_LED_APTRANSFER: |
| 150 | snprintf(name, sizeof(name), | 177 | snprintf(name, sizeof(name), |
| 151 | "b43-%s::tx", wiphy_name(hw->wiphy)); | 178 | "b43-%s::tx", wiphy_name(hw->wiphy)); |
| 152 | b43_register_led(dev, &dev->led_tx, name, | 179 | b43_register_led(dev, &dev->wl->leds.led_tx, name, |
| 153 | ieee80211_get_tx_led_name(hw), | 180 | ieee80211_get_tx_led_name(hw), |
| 154 | led_index, activelow); | 181 | led_index, activelow); |
| 155 | snprintf(name, sizeof(name), | 182 | snprintf(name, sizeof(name), |
| 156 | "b43-%s::rx", wiphy_name(hw->wiphy)); | 183 | "b43-%s::rx", wiphy_name(hw->wiphy)); |
| 157 | b43_register_led(dev, &dev->led_rx, name, | 184 | b43_register_led(dev, &dev->wl->leds.led_rx, name, |
| 158 | ieee80211_get_rx_led_name(hw), | 185 | ieee80211_get_rx_led_name(hw), |
| 159 | led_index, activelow); | 186 | led_index, activelow); |
| 160 | break; | 187 | break; |
| @@ -164,18 +191,15 @@ static void b43_map_led(struct b43_wldev *dev, | |||
| 164 | case B43_LED_MODE_BG: | 191 | case B43_LED_MODE_BG: |
| 165 | snprintf(name, sizeof(name), | 192 | snprintf(name, sizeof(name), |
| 166 | "b43-%s::radio", wiphy_name(hw->wiphy)); | 193 | "b43-%s::radio", wiphy_name(hw->wiphy)); |
| 167 | b43_register_led(dev, &dev->led_radio, name, | 194 | b43_register_led(dev, &dev->wl->leds.led_radio, name, |
| 168 | ieee80211_get_radio_led_name(hw), | 195 | ieee80211_get_radio_led_name(hw), |
| 169 | led_index, activelow); | 196 | led_index, activelow); |
| 170 | /* Sync the RF-kill LED state with radio and switch states. */ | ||
| 171 | if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) | ||
| 172 | b43_led_turn_on(dev, led_index, activelow); | ||
| 173 | break; | 197 | break; |
| 174 | case B43_LED_WEIRD: | 198 | case B43_LED_WEIRD: |
| 175 | case B43_LED_ASSOC: | 199 | case B43_LED_ASSOC: |
| 176 | snprintf(name, sizeof(name), | 200 | snprintf(name, sizeof(name), |
| 177 | "b43-%s::assoc", wiphy_name(hw->wiphy)); | 201 | "b43-%s::assoc", wiphy_name(hw->wiphy)); |
| 178 | b43_register_led(dev, &dev->led_assoc, name, | 202 | b43_register_led(dev, &dev->wl->leds.led_assoc, name, |
| 179 | ieee80211_get_assoc_led_name(hw), | 203 | ieee80211_get_assoc_led_name(hw), |
| 180 | led_index, activelow); | 204 | led_index, activelow); |
| 181 | break; | 205 | break; |
| @@ -186,58 +210,150 @@ static void b43_map_led(struct b43_wldev *dev, | |||
| 186 | } | 210 | } |
| 187 | } | 211 | } |
| 188 | 212 | ||
| 189 | void b43_leds_init(struct b43_wldev *dev) | 213 | static void b43_led_get_sprominfo(struct b43_wldev *dev, |
| 214 | unsigned int led_index, | ||
| 215 | enum b43_led_behaviour *behaviour, | ||
| 216 | bool *activelow) | ||
| 190 | { | 217 | { |
| 191 | struct ssb_bus *bus = dev->dev->bus; | 218 | struct ssb_bus *bus = dev->dev->bus; |
| 192 | u8 sprom[4]; | 219 | u8 sprom[4]; |
| 193 | int i; | ||
| 194 | enum b43_led_behaviour behaviour; | ||
| 195 | bool activelow; | ||
| 196 | 220 | ||
| 197 | sprom[0] = bus->sprom.gpio0; | 221 | sprom[0] = bus->sprom.gpio0; |
| 198 | sprom[1] = bus->sprom.gpio1; | 222 | sprom[1] = bus->sprom.gpio1; |
| 199 | sprom[2] = bus->sprom.gpio2; | 223 | sprom[2] = bus->sprom.gpio2; |
| 200 | sprom[3] = bus->sprom.gpio3; | 224 | sprom[3] = bus->sprom.gpio3; |
| 201 | 225 | ||
| 202 | for (i = 0; i < 4; i++) { | 226 | if (sprom[led_index] == 0xFF) { |
| 203 | if (sprom[i] == 0xFF) { | 227 | /* There is no LED information in the SPROM |
| 204 | /* There is no LED information in the SPROM | 228 | * for this LED. Hardcode it here. */ |
| 205 | * for this LED. Hardcode it here. */ | 229 | *activelow = 0; |
| 206 | activelow = 0; | 230 | switch (led_index) { |
| 207 | switch (i) { | 231 | case 0: |
| 208 | case 0: | 232 | *behaviour = B43_LED_ACTIVITY; |
| 209 | behaviour = B43_LED_ACTIVITY; | 233 | *activelow = 1; |
| 210 | activelow = 1; | 234 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ) |
| 211 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ) | 235 | *behaviour = B43_LED_RADIO_ALL; |
| 212 | behaviour = B43_LED_RADIO_ALL; | 236 | break; |
| 213 | break; | 237 | case 1: |
| 214 | case 1: | 238 | *behaviour = B43_LED_RADIO_B; |
| 215 | behaviour = B43_LED_RADIO_B; | 239 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK) |
| 216 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK) | 240 | *behaviour = B43_LED_ASSOC; |
| 217 | behaviour = B43_LED_ASSOC; | 241 | break; |
| 218 | break; | 242 | case 2: |
| 219 | case 2: | 243 | *behaviour = B43_LED_RADIO_A; |
| 220 | behaviour = B43_LED_RADIO_A; | 244 | break; |
| 221 | break; | 245 | case 3: |
| 222 | case 3: | 246 | *behaviour = B43_LED_OFF; |
| 223 | behaviour = B43_LED_OFF; | 247 | break; |
| 224 | break; | 248 | default: |
| 225 | default: | 249 | B43_WARN_ON(1); |
| 226 | B43_WARN_ON(1); | 250 | return; |
| 227 | return; | 251 | } |
| 228 | } | 252 | } else { |
| 253 | *behaviour = sprom[led_index] & B43_LED_BEHAVIOUR; | ||
| 254 | *activelow = !!(sprom[led_index] & B43_LED_ACTIVELOW); | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | void b43_leds_init(struct b43_wldev *dev) | ||
| 259 | { | ||
| 260 | struct b43_led *led; | ||
| 261 | unsigned int i; | ||
| 262 | enum b43_led_behaviour behaviour; | ||
| 263 | bool activelow; | ||
| 264 | |||
| 265 | /* Sync the RF-kill LED state (if we have one) with radio and switch states. */ | ||
| 266 | led = &dev->wl->leds.led_radio; | ||
| 267 | if (led->wl) { | ||
| 268 | if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) { | ||
| 269 | b43_led_turn_on(dev, led->index, led->activelow); | ||
| 270 | led->hw_state = 1; | ||
| 271 | atomic_set(&led->state, 1); | ||
| 229 | } else { | 272 | } else { |
| 230 | behaviour = sprom[i] & B43_LED_BEHAVIOUR; | 273 | b43_led_turn_off(dev, led->index, led->activelow); |
| 231 | activelow = !!(sprom[i] & B43_LED_ACTIVELOW); | 274 | led->hw_state = 0; |
| 275 | atomic_set(&led->state, 0); | ||
| 232 | } | 276 | } |
| 233 | b43_map_led(dev, i, behaviour, activelow); | ||
| 234 | } | 277 | } |
| 278 | |||
| 279 | /* Initialize TX/RX/ASSOC leds */ | ||
| 280 | led = &dev->wl->leds.led_tx; | ||
| 281 | if (led->wl) { | ||
| 282 | b43_led_turn_off(dev, led->index, led->activelow); | ||
| 283 | led->hw_state = 0; | ||
| 284 | atomic_set(&led->state, 0); | ||
| 285 | } | ||
| 286 | led = &dev->wl->leds.led_rx; | ||
| 287 | if (led->wl) { | ||
| 288 | b43_led_turn_off(dev, led->index, led->activelow); | ||
| 289 | led->hw_state = 0; | ||
| 290 | atomic_set(&led->state, 0); | ||
| 291 | } | ||
| 292 | led = &dev->wl->leds.led_assoc; | ||
| 293 | if (led->wl) { | ||
| 294 | b43_led_turn_off(dev, led->index, led->activelow); | ||
| 295 | led->hw_state = 0; | ||
| 296 | atomic_set(&led->state, 0); | ||
| 297 | } | ||
| 298 | |||
| 299 | /* Initialize other LED states. */ | ||
| 300 | for (i = 0; i < B43_MAX_NR_LEDS; i++) { | ||
| 301 | b43_led_get_sprominfo(dev, i, &behaviour, &activelow); | ||
| 302 | switch (behaviour) { | ||
| 303 | case B43_LED_OFF: | ||
| 304 | b43_led_turn_off(dev, i, activelow); | ||
| 305 | break; | ||
| 306 | case B43_LED_ON: | ||
| 307 | b43_led_turn_on(dev, i, activelow); | ||
| 308 | break; | ||
| 309 | default: | ||
| 310 | /* Leave others as-is. */ | ||
| 311 | break; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | dev->wl->leds.stop = 0; | ||
| 235 | } | 316 | } |
| 236 | 317 | ||
| 237 | void b43_leds_exit(struct b43_wldev *dev) | 318 | void b43_leds_exit(struct b43_wldev *dev) |
| 238 | { | 319 | { |
| 239 | b43_unregister_led(&dev->led_tx); | 320 | struct b43_leds *leds = &dev->wl->leds; |
| 240 | b43_unregister_led(&dev->led_rx); | 321 | |
| 241 | b43_unregister_led(&dev->led_assoc); | 322 | b43_led_turn_off(dev, leds->led_tx.index, leds->led_tx.activelow); |
| 242 | b43_unregister_led(&dev->led_radio); | 323 | b43_led_turn_off(dev, leds->led_rx.index, leds->led_rx.activelow); |
| 324 | b43_led_turn_off(dev, leds->led_assoc.index, leds->led_assoc.activelow); | ||
| 325 | b43_led_turn_off(dev, leds->led_radio.index, leds->led_radio.activelow); | ||
| 326 | } | ||
| 327 | |||
| 328 | void b43_leds_stop(struct b43_wldev *dev) | ||
| 329 | { | ||
| 330 | struct b43_leds *leds = &dev->wl->leds; | ||
| 331 | |||
| 332 | leds->stop = 1; | ||
| 333 | cancel_work_sync(&leds->work); | ||
| 334 | } | ||
| 335 | |||
| 336 | void b43_leds_register(struct b43_wldev *dev) | ||
| 337 | { | ||
| 338 | unsigned int i; | ||
| 339 | enum b43_led_behaviour behaviour; | ||
| 340 | bool activelow; | ||
| 341 | |||
| 342 | INIT_WORK(&dev->wl->leds.work, b43_leds_work); | ||
| 343 | |||
| 344 | /* Register the LEDs to the LED subsystem. */ | ||
| 345 | for (i = 0; i < B43_MAX_NR_LEDS; i++) { | ||
| 346 | b43_led_get_sprominfo(dev, i, &behaviour, &activelow); | ||
| 347 | b43_map_led(dev, i, behaviour, activelow); | ||
| 348 | } | ||
| 349 | } | ||
| 350 | |||
| 351 | void b43_leds_unregister(struct b43_wldev *dev) | ||
| 352 | { | ||
| 353 | struct b43_leds *leds = &dev->wl->leds; | ||
| 354 | |||
| 355 | b43_unregister_led(&leds->led_tx); | ||
| 356 | b43_unregister_led(&leds->led_rx); | ||
| 357 | b43_unregister_led(&leds->led_assoc); | ||
| 358 | b43_unregister_led(&leds->led_radio); | ||
| 243 | } | 359 | } |
diff --git a/drivers/net/wireless/b43/leds.h b/drivers/net/wireless/b43/leds.h index b8b1dd521243..9592e4c5a5f5 100644 --- a/drivers/net/wireless/b43/leds.h +++ b/drivers/net/wireless/b43/leds.h | |||
| @@ -7,12 +7,13 @@ struct b43_wldev; | |||
| 7 | 7 | ||
| 8 | #include <linux/types.h> | 8 | #include <linux/types.h> |
| 9 | #include <linux/leds.h> | 9 | #include <linux/leds.h> |
| 10 | #include <linux/workqueue.h> | ||
| 10 | 11 | ||
| 11 | 12 | ||
| 12 | #define B43_LED_MAX_NAME_LEN 31 | 13 | #define B43_LED_MAX_NAME_LEN 31 |
| 13 | 14 | ||
| 14 | struct b43_led { | 15 | struct b43_led { |
| 15 | struct b43_wldev *dev; | 16 | struct b43_wl *wl; |
| 16 | /* The LED class device */ | 17 | /* The LED class device */ |
| 17 | struct led_classdev led_dev; | 18 | struct led_classdev led_dev; |
| 18 | /* The index number of the LED. */ | 19 | /* The index number of the LED. */ |
| @@ -22,8 +23,24 @@ struct b43_led { | |||
| 22 | bool activelow; | 23 | bool activelow; |
| 23 | /* The unique name string for this LED device. */ | 24 | /* The unique name string for this LED device. */ |
| 24 | char name[B43_LED_MAX_NAME_LEN + 1]; | 25 | char name[B43_LED_MAX_NAME_LEN + 1]; |
| 26 | /* The current status of the LED. This is updated locklessly. */ | ||
| 27 | atomic_t state; | ||
| 28 | /* The active state in hardware. */ | ||
| 29 | bool hw_state; | ||
| 25 | }; | 30 | }; |
| 26 | 31 | ||
| 32 | struct b43_leds { | ||
| 33 | struct b43_led led_tx; | ||
| 34 | struct b43_led led_rx; | ||
| 35 | struct b43_led led_radio; | ||
| 36 | struct b43_led led_assoc; | ||
| 37 | |||
| 38 | bool stop; | ||
| 39 | struct work_struct work; | ||
| 40 | }; | ||
| 41 | |||
| 42 | #define B43_MAX_NR_LEDS 4 | ||
| 43 | |||
| 27 | #define B43_LED_BEHAVIOUR 0x7F | 44 | #define B43_LED_BEHAVIOUR 0x7F |
| 28 | #define B43_LED_ACTIVELOW 0x80 | 45 | #define B43_LED_ACTIVELOW 0x80 |
| 29 | /* LED behaviour values */ | 46 | /* LED behaviour values */ |
| @@ -42,23 +59,35 @@ enum b43_led_behaviour { | |||
| 42 | B43_LED_INACTIVE, | 59 | B43_LED_INACTIVE, |
| 43 | }; | 60 | }; |
| 44 | 61 | ||
| 62 | void b43_leds_register(struct b43_wldev *dev); | ||
| 63 | void b43_leds_unregister(struct b43_wldev *dev); | ||
| 45 | void b43_leds_init(struct b43_wldev *dev); | 64 | void b43_leds_init(struct b43_wldev *dev); |
| 46 | void b43_leds_exit(struct b43_wldev *dev); | 65 | void b43_leds_exit(struct b43_wldev *dev); |
| 66 | void b43_leds_stop(struct b43_wldev *dev); | ||
| 47 | 67 | ||
| 48 | 68 | ||
| 49 | #else /* CONFIG_B43_LEDS */ | 69 | #else /* CONFIG_B43_LEDS */ |
| 50 | /* LED support disabled */ | 70 | /* LED support disabled */ |
| 51 | 71 | ||
| 52 | struct b43_led { | 72 | struct b43_leds { |
| 53 | /* empty */ | 73 | /* empty */ |
| 54 | }; | 74 | }; |
| 55 | 75 | ||
| 76 | static inline void b43_leds_register(struct b43_wldev *dev) | ||
| 77 | { | ||
| 78 | } | ||
| 79 | static inline void b43_leds_unregister(struct b43_wldev *dev) | ||
| 80 | { | ||
| 81 | } | ||
| 56 | static inline void b43_leds_init(struct b43_wldev *dev) | 82 | static inline void b43_leds_init(struct b43_wldev *dev) |
| 57 | { | 83 | { |
| 58 | } | 84 | } |
| 59 | static inline void b43_leds_exit(struct b43_wldev *dev) | 85 | static inline void b43_leds_exit(struct b43_wldev *dev) |
| 60 | { | 86 | { |
| 61 | } | 87 | } |
| 88 | static inline void b43_leds_stop(struct b43_wldev *dev) | ||
| 89 | { | ||
| 90 | } | ||
| 62 | #endif /* CONFIG_B43_LEDS */ | 91 | #endif /* CONFIG_B43_LEDS */ |
| 63 | 92 | ||
| 64 | #endif /* B43_LEDS_H_ */ | 93 | #endif /* B43_LEDS_H_ */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e789792a36bc..9b907a36bb8c 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -8,6 +8,9 @@ | |||
| 8 | Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org> | 8 | Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org> |
| 9 | Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> | 9 | Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> |
| 10 | 10 | ||
| 11 | SDIO support | ||
| 12 | Copyright (c) 2009 Albert Herranz <albert_herranz@yahoo.es> | ||
| 13 | |||
| 11 | Some parts of the code in this file are derived from the ipw2200 | 14 | Some parts of the code in this file are derived from the ipw2200 |
| 12 | driver Copyright(c) 2003 - 2004 Intel Corporation. | 15 | driver Copyright(c) 2003 - 2004 Intel Corporation. |
| 13 | 16 | ||
| @@ -53,6 +56,8 @@ | |||
| 53 | #include "xmit.h" | 56 | #include "xmit.h" |
| 54 | #include "lo.h" | 57 | #include "lo.h" |
| 55 | #include "pcmcia.h" | 58 | #include "pcmcia.h" |
| 59 | #include "sdio.h" | ||
| 60 | #include <linux/mmc/sdio_func.h> | ||
| 56 | 61 | ||
| 57 | MODULE_DESCRIPTION("Broadcom B43 wireless driver"); | 62 | MODULE_DESCRIPTION("Broadcom B43 wireless driver"); |
| 58 | MODULE_AUTHOR("Martin Langer"); | 63 | MODULE_AUTHOR("Martin Langer"); |
| @@ -1587,7 +1592,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) | |||
| 1587 | mutex_lock(&wl->mutex); | 1592 | mutex_lock(&wl->mutex); |
| 1588 | dev = wl->current_dev; | 1593 | dev = wl->current_dev; |
| 1589 | if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { | 1594 | if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { |
| 1590 | if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) { | 1595 | if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { |
| 1591 | /* wl->mutex is enough. */ | 1596 | /* wl->mutex is enough. */ |
| 1592 | b43_do_beacon_update_trigger_work(dev); | 1597 | b43_do_beacon_update_trigger_work(dev); |
| 1593 | mmiowb(); | 1598 | mmiowb(); |
| @@ -1825,6 +1830,16 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
| 1825 | 1830 | ||
| 1826 | /* Re-enable interrupts on the device by restoring the current interrupt mask. */ | 1831 | /* Re-enable interrupts on the device by restoring the current interrupt mask. */ |
| 1827 | b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); | 1832 | b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); |
| 1833 | |||
| 1834 | #if B43_DEBUG | ||
| 1835 | if (b43_debug(dev, B43_DBG_VERBOSESTATS)) { | ||
| 1836 | dev->irq_count++; | ||
| 1837 | for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) { | ||
| 1838 | if (reason & (1 << i)) | ||
| 1839 | dev->irq_bit_count[i]++; | ||
| 1840 | } | ||
| 1841 | } | ||
| 1842 | #endif | ||
| 1828 | } | 1843 | } |
| 1829 | 1844 | ||
| 1830 | /* Interrupt thread handler. Handles device interrupts in thread context. */ | 1845 | /* Interrupt thread handler. Handles device interrupts in thread context. */ |
| @@ -1905,6 +1920,21 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) | |||
| 1905 | return ret; | 1920 | return ret; |
| 1906 | } | 1921 | } |
| 1907 | 1922 | ||
| 1923 | /* SDIO interrupt handler. This runs in process context. */ | ||
| 1924 | static void b43_sdio_interrupt_handler(struct b43_wldev *dev) | ||
| 1925 | { | ||
| 1926 | struct b43_wl *wl = dev->wl; | ||
| 1927 | irqreturn_t ret; | ||
| 1928 | |||
| 1929 | mutex_lock(&wl->mutex); | ||
| 1930 | |||
| 1931 | ret = b43_do_interrupt(dev); | ||
| 1932 | if (ret == IRQ_WAKE_THREAD) | ||
| 1933 | b43_do_interrupt_thread(dev); | ||
| 1934 | |||
| 1935 | mutex_unlock(&wl->mutex); | ||
| 1936 | } | ||
| 1937 | |||
| 1908 | void b43_do_release_fw(struct b43_firmware_file *fw) | 1938 | void b43_do_release_fw(struct b43_firmware_file *fw) |
| 1909 | { | 1939 | { |
| 1910 | release_firmware(fw->data); | 1940 | release_firmware(fw->data); |
| @@ -2645,6 +2675,20 @@ static void b43_adjust_opmode(struct b43_wldev *dev) | |||
| 2645 | cfp_pretbtt = 50; | 2675 | cfp_pretbtt = 50; |
| 2646 | } | 2676 | } |
| 2647 | b43_write16(dev, 0x612, cfp_pretbtt); | 2677 | b43_write16(dev, 0x612, cfp_pretbtt); |
| 2678 | |||
| 2679 | /* FIXME: We don't currently implement the PMQ mechanism, | ||
| 2680 | * so always disable it. If we want to implement PMQ, | ||
| 2681 | * we need to enable it here (clear DISCPMQ) in AP mode. | ||
| 2682 | */ | ||
| 2683 | if (0 /* ctl & B43_MACCTL_AP */) { | ||
| 2684 | b43_write32(dev, B43_MMIO_MACCTL, | ||
| 2685 | b43_read32(dev, B43_MMIO_MACCTL) | ||
| 2686 | & ~B43_MACCTL_DISCPMQ); | ||
| 2687 | } else { | ||
| 2688 | b43_write32(dev, B43_MMIO_MACCTL, | ||
| 2689 | b43_read32(dev, B43_MMIO_MACCTL) | ||
| 2690 | | B43_MACCTL_DISCPMQ); | ||
| 2691 | } | ||
| 2648 | } | 2692 | } |
| 2649 | 2693 | ||
| 2650 | static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm) | 2694 | static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm) |
| @@ -2873,6 +2917,27 @@ static void b43_periodic_every15sec(struct b43_wldev *dev) | |||
| 2873 | 2917 | ||
| 2874 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); | 2918 | atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); |
| 2875 | wmb(); | 2919 | wmb(); |
| 2920 | |||
| 2921 | #if B43_DEBUG | ||
| 2922 | if (b43_debug(dev, B43_DBG_VERBOSESTATS)) { | ||
| 2923 | unsigned int i; | ||
| 2924 | |||
| 2925 | b43dbg(dev->wl, "Stats: %7u IRQs/sec, %7u TX/sec, %7u RX/sec\n", | ||
| 2926 | dev->irq_count / 15, | ||
| 2927 | dev->tx_count / 15, | ||
| 2928 | dev->rx_count / 15); | ||
| 2929 | dev->irq_count = 0; | ||
| 2930 | dev->tx_count = 0; | ||
| 2931 | dev->rx_count = 0; | ||
| 2932 | for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) { | ||
| 2933 | if (dev->irq_bit_count[i]) { | ||
| 2934 | b43dbg(dev->wl, "Stats: %7u IRQ-%02u/sec (0x%08X)\n", | ||
| 2935 | dev->irq_bit_count[i] / 15, i, (1 << i)); | ||
| 2936 | dev->irq_bit_count[i] = 0; | ||
| 2937 | } | ||
| 2938 | } | ||
| 2939 | } | ||
| 2940 | #endif | ||
| 2876 | } | 2941 | } |
| 2877 | 2942 | ||
| 2878 | static void do_periodic_work(struct b43_wldev *dev) | 2943 | static void do_periodic_work(struct b43_wldev *dev) |
| @@ -3002,14 +3067,18 @@ static void b43_security_init(struct b43_wldev *dev) | |||
| 3002 | static int b43_rng_read(struct hwrng *rng, u32 *data) | 3067 | static int b43_rng_read(struct hwrng *rng, u32 *data) |
| 3003 | { | 3068 | { |
| 3004 | struct b43_wl *wl = (struct b43_wl *)rng->priv; | 3069 | struct b43_wl *wl = (struct b43_wl *)rng->priv; |
| 3070 | struct b43_wldev *dev; | ||
| 3071 | int count = -ENODEV; | ||
| 3005 | 3072 | ||
| 3006 | /* FIXME: We need to take wl->mutex here to make sure the device | 3073 | mutex_lock(&wl->mutex); |
| 3007 | * is not going away from under our ass. However it could deadlock | 3074 | dev = wl->current_dev; |
| 3008 | * with hwrng internal locking. */ | 3075 | if (likely(dev && b43_status(dev) >= B43_STAT_INITIALIZED)) { |
| 3009 | 3076 | *data = b43_read16(dev, B43_MMIO_RNG); | |
| 3010 | *data = b43_read16(wl->current_dev, B43_MMIO_RNG); | 3077 | count = sizeof(u16); |
| 3078 | } | ||
| 3079 | mutex_unlock(&wl->mutex); | ||
| 3011 | 3080 | ||
| 3012 | return (sizeof(u16)); | 3081 | return count; |
| 3013 | } | 3082 | } |
| 3014 | #endif /* CONFIG_B43_HWRNG */ | 3083 | #endif /* CONFIG_B43_HWRNG */ |
| 3015 | 3084 | ||
| @@ -3068,6 +3137,9 @@ static void b43_tx_work(struct work_struct *work) | |||
| 3068 | dev_kfree_skb(skb); /* Drop it */ | 3137 | dev_kfree_skb(skb); /* Drop it */ |
| 3069 | } | 3138 | } |
| 3070 | 3139 | ||
| 3140 | #if B43_DEBUG | ||
| 3141 | dev->tx_count++; | ||
| 3142 | #endif | ||
| 3071 | mutex_unlock(&wl->mutex); | 3143 | mutex_unlock(&wl->mutex); |
| 3072 | } | 3144 | } |
| 3073 | 3145 | ||
| @@ -3820,7 +3892,7 @@ redo: | |||
| 3820 | 3892 | ||
| 3821 | /* Disable interrupts on the device. */ | 3893 | /* Disable interrupts on the device. */ |
| 3822 | b43_set_status(dev, B43_STAT_INITIALIZED); | 3894 | b43_set_status(dev, B43_STAT_INITIALIZED); |
| 3823 | if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) { | 3895 | if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { |
| 3824 | /* wl->mutex is locked. That is enough. */ | 3896 | /* wl->mutex is locked. That is enough. */ |
| 3825 | b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); | 3897 | b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); |
| 3826 | b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ | 3898 | b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ |
| @@ -3830,10 +3902,15 @@ redo: | |||
| 3830 | b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ | 3902 | b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ |
| 3831 | spin_unlock_irq(&wl->hardirq_lock); | 3903 | spin_unlock_irq(&wl->hardirq_lock); |
| 3832 | } | 3904 | } |
| 3833 | /* Synchronize the interrupt handlers. Unlock to avoid deadlocks. */ | 3905 | /* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */ |
| 3834 | orig_dev = dev; | 3906 | orig_dev = dev; |
| 3835 | mutex_unlock(&wl->mutex); | 3907 | mutex_unlock(&wl->mutex); |
| 3836 | synchronize_irq(dev->dev->irq); | 3908 | if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { |
| 3909 | b43_sdio_free_irq(dev); | ||
| 3910 | } else { | ||
| 3911 | synchronize_irq(dev->dev->irq); | ||
| 3912 | free_irq(dev->dev->irq, dev); | ||
| 3913 | } | ||
| 3837 | mutex_lock(&wl->mutex); | 3914 | mutex_lock(&wl->mutex); |
| 3838 | dev = wl->current_dev; | 3915 | dev = wl->current_dev; |
| 3839 | if (!dev) | 3916 | if (!dev) |
| @@ -3850,7 +3927,7 @@ redo: | |||
| 3850 | dev_kfree_skb(skb_dequeue(&wl->tx_queue)); | 3927 | dev_kfree_skb(skb_dequeue(&wl->tx_queue)); |
| 3851 | 3928 | ||
| 3852 | b43_mac_suspend(dev); | 3929 | b43_mac_suspend(dev); |
| 3853 | free_irq(dev->dev->irq, dev); | 3930 | b43_leds_exit(dev); |
| 3854 | b43dbg(wl, "Wireless interface stopped\n"); | 3931 | b43dbg(wl, "Wireless interface stopped\n"); |
| 3855 | 3932 | ||
| 3856 | return dev; | 3933 | return dev; |
| @@ -3864,12 +3941,20 @@ static int b43_wireless_core_start(struct b43_wldev *dev) | |||
| 3864 | B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); | 3941 | B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); |
| 3865 | 3942 | ||
| 3866 | drain_txstatus_queue(dev); | 3943 | drain_txstatus_queue(dev); |
| 3867 | err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler, | 3944 | if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { |
| 3868 | b43_interrupt_thread_handler, | 3945 | err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler); |
| 3869 | IRQF_SHARED, KBUILD_MODNAME, dev); | 3946 | if (err) { |
| 3870 | if (err) { | 3947 | b43err(dev->wl, "Cannot request SDIO IRQ\n"); |
| 3871 | b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq); | 3948 | goto out; |
| 3872 | goto out; | 3949 | } |
| 3950 | } else { | ||
| 3951 | err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler, | ||
| 3952 | b43_interrupt_thread_handler, | ||
| 3953 | IRQF_SHARED, KBUILD_MODNAME, dev); | ||
| 3954 | if (err) { | ||
| 3955 | b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq); | ||
| 3956 | goto out; | ||
| 3957 | } | ||
| 3873 | } | 3958 | } |
| 3874 | 3959 | ||
| 3875 | /* We are ready to run. */ | 3960 | /* We are ready to run. */ |
| @@ -3882,8 +3967,10 @@ static int b43_wireless_core_start(struct b43_wldev *dev) | |||
| 3882 | /* Start maintainance work */ | 3967 | /* Start maintainance work */ |
| 3883 | b43_periodic_tasks_setup(dev); | 3968 | b43_periodic_tasks_setup(dev); |
| 3884 | 3969 | ||
| 3970 | b43_leds_init(dev); | ||
| 3971 | |||
| 3885 | b43dbg(dev->wl, "Wireless interface started\n"); | 3972 | b43dbg(dev->wl, "Wireless interface started\n"); |
| 3886 | out: | 3973 | out: |
| 3887 | return err; | 3974 | return err; |
| 3888 | } | 3975 | } |
| 3889 | 3976 | ||
| @@ -4160,10 +4247,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) | |||
| 4160 | macctl |= B43_MACCTL_PSM_JMP0; | 4247 | macctl |= B43_MACCTL_PSM_JMP0; |
| 4161 | b43_write32(dev, B43_MMIO_MACCTL, macctl); | 4248 | b43_write32(dev, B43_MMIO_MACCTL, macctl); |
| 4162 | 4249 | ||
| 4163 | if (!dev->suspend_in_progress) { | ||
| 4164 | b43_leds_exit(dev); | ||
| 4165 | b43_rng_exit(dev->wl); | ||
| 4166 | } | ||
| 4167 | b43_dma_free(dev); | 4250 | b43_dma_free(dev); |
| 4168 | b43_pio_free(dev); | 4251 | b43_pio_free(dev); |
| 4169 | b43_chip_exit(dev); | 4252 | b43_chip_exit(dev); |
| @@ -4180,7 +4263,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) | |||
| 4180 | /* Initialize a wireless core */ | 4263 | /* Initialize a wireless core */ |
| 4181 | static int b43_wireless_core_init(struct b43_wldev *dev) | 4264 | static int b43_wireless_core_init(struct b43_wldev *dev) |
| 4182 | { | 4265 | { |
| 4183 | struct b43_wl *wl = dev->wl; | ||
| 4184 | struct ssb_bus *bus = dev->dev->bus; | 4266 | struct ssb_bus *bus = dev->dev->bus; |
| 4185 | struct ssb_sprom *sprom = &bus->sprom; | 4267 | struct ssb_sprom *sprom = &bus->sprom; |
| 4186 | struct b43_phy *phy = &dev->phy; | 4268 | struct b43_phy *phy = &dev->phy; |
| @@ -4264,7 +4346,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
| 4264 | /* Maximum Contention Window */ | 4346 | /* Maximum Contention Window */ |
| 4265 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); | 4347 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); |
| 4266 | 4348 | ||
| 4267 | if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) { | 4349 | if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || |
| 4350 | (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || | ||
| 4351 | B43_FORCE_PIO) { | ||
| 4268 | dev->__using_pio_transfers = 1; | 4352 | dev->__using_pio_transfers = 1; |
| 4269 | err = b43_pio_init(dev); | 4353 | err = b43_pio_init(dev); |
| 4270 | } else { | 4354 | } else { |
| @@ -4280,15 +4364,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
| 4280 | ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)); | 4364 | ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)); |
| 4281 | b43_upload_card_macaddress(dev); | 4365 | b43_upload_card_macaddress(dev); |
| 4282 | b43_security_init(dev); | 4366 | b43_security_init(dev); |
| 4283 | if (!dev->suspend_in_progress) | 4367 | |
| 4284 | b43_rng_init(wl); | 4368 | ieee80211_wake_queues(dev->wl->hw); |
| 4285 | 4369 | ||
| 4286 | ieee80211_wake_queues(dev->wl->hw); | 4370 | ieee80211_wake_queues(dev->wl->hw); |
| 4287 | 4371 | ||
| 4288 | b43_set_status(dev, B43_STAT_INITIALIZED); | 4372 | b43_set_status(dev, B43_STAT_INITIALIZED); |
| 4289 | 4373 | ||
| 4290 | if (!dev->suspend_in_progress) | ||
| 4291 | b43_leds_init(dev); | ||
| 4292 | out: | 4374 | out: |
| 4293 | return err; | 4375 | return err; |
| 4294 | 4376 | ||
| @@ -4837,7 +4919,6 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
| 4837 | 4919 | ||
| 4838 | /* Initialize struct b43_wl */ | 4920 | /* Initialize struct b43_wl */ |
| 4839 | wl->hw = hw; | 4921 | wl->hw = hw; |
| 4840 | spin_lock_init(&wl->leds_lock); | ||
| 4841 | mutex_init(&wl->mutex); | 4922 | mutex_init(&wl->mutex); |
| 4842 | spin_lock_init(&wl->hardirq_lock); | 4923 | spin_lock_init(&wl->hardirq_lock); |
| 4843 | INIT_LIST_HEAD(&wl->devlist); | 4924 | INIT_LIST_HEAD(&wl->devlist); |
| @@ -4878,6 +4959,8 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id) | |||
| 4878 | err = ieee80211_register_hw(wl->hw); | 4959 | err = ieee80211_register_hw(wl->hw); |
| 4879 | if (err) | 4960 | if (err) |
| 4880 | goto err_one_core_detach; | 4961 | goto err_one_core_detach; |
| 4962 | b43_leds_register(wl->current_dev); | ||
| 4963 | b43_rng_init(wl); | ||
| 4881 | } | 4964 | } |
| 4882 | 4965 | ||
| 4883 | out: | 4966 | out: |
| @@ -4906,12 +4989,15 @@ static void b43_remove(struct ssb_device *dev) | |||
| 4906 | * might have modified it. Restoring is important, so the networking | 4989 | * might have modified it. Restoring is important, so the networking |
| 4907 | * stack can properly free resources. */ | 4990 | * stack can properly free resources. */ |
| 4908 | wl->hw->queues = wl->mac80211_initially_registered_queues; | 4991 | wl->hw->queues = wl->mac80211_initially_registered_queues; |
| 4992 | b43_leds_stop(wldev); | ||
| 4909 | ieee80211_unregister_hw(wl->hw); | 4993 | ieee80211_unregister_hw(wl->hw); |
| 4910 | } | 4994 | } |
| 4911 | 4995 | ||
| 4912 | b43_one_core_detach(dev); | 4996 | b43_one_core_detach(dev); |
| 4913 | 4997 | ||
| 4914 | if (list_empty(&wl->devlist)) { | 4998 | if (list_empty(&wl->devlist)) { |
| 4999 | b43_rng_exit(wl); | ||
| 5000 | b43_leds_unregister(wldev); | ||
| 4915 | /* Last core on the chip unregistered. | 5001 | /* Last core on the chip unregistered. |
| 4916 | * We can destroy common struct b43_wl. | 5002 | * We can destroy common struct b43_wl. |
| 4917 | */ | 5003 | */ |
| @@ -4929,80 +5015,17 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason) | |||
| 4929 | ieee80211_queue_work(dev->wl->hw, &dev->restart_work); | 5015 | ieee80211_queue_work(dev->wl->hw, &dev->restart_work); |
| 4930 | } | 5016 | } |
| 4931 | 5017 | ||
| 4932 | #ifdef CONFIG_PM | ||
| 4933 | |||
| 4934 | static int b43_suspend(struct ssb_device *dev, pm_message_t state) | ||
| 4935 | { | ||
| 4936 | struct b43_wldev *wldev = ssb_get_drvdata(dev); | ||
| 4937 | struct b43_wl *wl = wldev->wl; | ||
| 4938 | |||
| 4939 | b43dbg(wl, "Suspending...\n"); | ||
| 4940 | |||
| 4941 | mutex_lock(&wl->mutex); | ||
| 4942 | wldev->suspend_in_progress = true; | ||
| 4943 | wldev->suspend_init_status = b43_status(wldev); | ||
| 4944 | if (wldev->suspend_init_status >= B43_STAT_STARTED) | ||
| 4945 | wldev = b43_wireless_core_stop(wldev); | ||
| 4946 | if (wldev && wldev->suspend_init_status >= B43_STAT_INITIALIZED) | ||
| 4947 | b43_wireless_core_exit(wldev); | ||
| 4948 | mutex_unlock(&wl->mutex); | ||
| 4949 | |||
| 4950 | b43dbg(wl, "Device suspended.\n"); | ||
| 4951 | |||
| 4952 | return 0; | ||
| 4953 | } | ||
| 4954 | |||
| 4955 | static int b43_resume(struct ssb_device *dev) | ||
| 4956 | { | ||
| 4957 | struct b43_wldev *wldev = ssb_get_drvdata(dev); | ||
| 4958 | struct b43_wl *wl = wldev->wl; | ||
| 4959 | int err = 0; | ||
| 4960 | |||
| 4961 | b43dbg(wl, "Resuming...\n"); | ||
| 4962 | |||
| 4963 | mutex_lock(&wl->mutex); | ||
| 4964 | if (wldev->suspend_init_status >= B43_STAT_INITIALIZED) { | ||
| 4965 | err = b43_wireless_core_init(wldev); | ||
| 4966 | if (err) { | ||
| 4967 | b43err(wl, "Resume failed at core init\n"); | ||
| 4968 | goto out; | ||
| 4969 | } | ||
| 4970 | } | ||
| 4971 | if (wldev->suspend_init_status >= B43_STAT_STARTED) { | ||
| 4972 | err = b43_wireless_core_start(wldev); | ||
| 4973 | if (err) { | ||
| 4974 | b43_leds_exit(wldev); | ||
| 4975 | b43_rng_exit(wldev->wl); | ||
| 4976 | b43_wireless_core_exit(wldev); | ||
| 4977 | b43err(wl, "Resume failed at core start\n"); | ||
| 4978 | goto out; | ||
| 4979 | } | ||
| 4980 | } | ||
| 4981 | b43dbg(wl, "Device resumed.\n"); | ||
| 4982 | out: | ||
| 4983 | wldev->suspend_in_progress = false; | ||
| 4984 | mutex_unlock(&wl->mutex); | ||
| 4985 | return err; | ||
| 4986 | } | ||
| 4987 | |||
| 4988 | #else /* CONFIG_PM */ | ||
| 4989 | # define b43_suspend NULL | ||
| 4990 | # define b43_resume NULL | ||
| 4991 | #endif /* CONFIG_PM */ | ||
| 4992 | |||
| 4993 | static struct ssb_driver b43_ssb_driver = { | 5018 | static struct ssb_driver b43_ssb_driver = { |
| 4994 | .name = KBUILD_MODNAME, | 5019 | .name = KBUILD_MODNAME, |
| 4995 | .id_table = b43_ssb_tbl, | 5020 | .id_table = b43_ssb_tbl, |
| 4996 | .probe = b43_probe, | 5021 | .probe = b43_probe, |
| 4997 | .remove = b43_remove, | 5022 | .remove = b43_remove, |
| 4998 | .suspend = b43_suspend, | ||
| 4999 | .resume = b43_resume, | ||
| 5000 | }; | 5023 | }; |
| 5001 | 5024 | ||
| 5002 | static void b43_print_driverinfo(void) | 5025 | static void b43_print_driverinfo(void) |
| 5003 | { | 5026 | { |
| 5004 | const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", | 5027 | const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", |
| 5005 | *feat_leds = ""; | 5028 | *feat_leds = "", *feat_sdio = ""; |
| 5006 | 5029 | ||
| 5007 | #ifdef CONFIG_B43_PCI_AUTOSELECT | 5030 | #ifdef CONFIG_B43_PCI_AUTOSELECT |
| 5008 | feat_pci = "P"; | 5031 | feat_pci = "P"; |
| @@ -5016,11 +5039,14 @@ static void b43_print_driverinfo(void) | |||
| 5016 | #ifdef CONFIG_B43_LEDS | 5039 | #ifdef CONFIG_B43_LEDS |
| 5017 | feat_leds = "L"; | 5040 | feat_leds = "L"; |
| 5018 | #endif | 5041 | #endif |
| 5042 | #ifdef CONFIG_B43_SDIO | ||
| 5043 | feat_sdio = "S"; | ||
| 5044 | #endif | ||
| 5019 | printk(KERN_INFO "Broadcom 43xx driver loaded " | 5045 | printk(KERN_INFO "Broadcom 43xx driver loaded " |
| 5020 | "[ Features: %s%s%s%s, Firmware-ID: " | 5046 | "[ Features: %s%s%s%s%s, Firmware-ID: " |
| 5021 | B43_SUPPORTED_FIRMWARE_ID " ]\n", | 5047 | B43_SUPPORTED_FIRMWARE_ID " ]\n", |
| 5022 | feat_pci, feat_pcmcia, feat_nphy, | 5048 | feat_pci, feat_pcmcia, feat_nphy, |
| 5023 | feat_leds); | 5049 | feat_leds, feat_sdio); |
| 5024 | } | 5050 | } |
| 5025 | 5051 | ||
| 5026 | static int __init b43_init(void) | 5052 | static int __init b43_init(void) |
| @@ -5031,13 +5057,18 @@ static int __init b43_init(void) | |||
| 5031 | err = b43_pcmcia_init(); | 5057 | err = b43_pcmcia_init(); |
| 5032 | if (err) | 5058 | if (err) |
| 5033 | goto err_dfs_exit; | 5059 | goto err_dfs_exit; |
| 5034 | err = ssb_driver_register(&b43_ssb_driver); | 5060 | err = b43_sdio_init(); |
| 5035 | if (err) | 5061 | if (err) |
| 5036 | goto err_pcmcia_exit; | 5062 | goto err_pcmcia_exit; |
| 5063 | err = ssb_driver_register(&b43_ssb_driver); | ||
| 5064 | if (err) | ||
| 5065 | goto err_sdio_exit; | ||
| 5037 | b43_print_driverinfo(); | 5066 | b43_print_driverinfo(); |
| 5038 | 5067 | ||
| 5039 | return err; | 5068 | return err; |
| 5040 | 5069 | ||
| 5070 | err_sdio_exit: | ||
| 5071 | b43_sdio_exit(); | ||
| 5041 | err_pcmcia_exit: | 5072 | err_pcmcia_exit: |
| 5042 | b43_pcmcia_exit(); | 5073 | b43_pcmcia_exit(); |
| 5043 | err_dfs_exit: | 5074 | err_dfs_exit: |
| @@ -5048,6 +5079,7 @@ err_dfs_exit: | |||
| 5048 | static void __exit b43_exit(void) | 5079 | static void __exit b43_exit(void) |
| 5049 | { | 5080 | { |
| 5050 | ssb_driver_unregister(&b43_ssb_driver); | 5081 | ssb_driver_unregister(&b43_ssb_driver); |
| 5082 | b43_sdio_exit(); | ||
| 5051 | b43_pcmcia_exit(); | 5083 | b43_pcmcia_exit(); |
| 5052 | b43_debugfs_exit(); | 5084 | b43_debugfs_exit(); |
| 5053 | } | 5085 | } |
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 3e02d969f683..1e318d815a5b 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
| @@ -2228,6 +2228,16 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev, | |||
| 2228 | return B43_TXPWR_RES_DONE; | 2228 | return B43_TXPWR_RES_DONE; |
| 2229 | } | 2229 | } |
| 2230 | 2230 | ||
| 2231 | void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on) | ||
| 2232 | { | ||
| 2233 | if (on) { | ||
| 2234 | b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8); | ||
| 2235 | } else { | ||
| 2236 | b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0x0007); | ||
| 2237 | b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x0007); | ||
| 2238 | } | ||
| 2239 | } | ||
| 2240 | |||
| 2231 | const struct b43_phy_operations b43_phyops_lp = { | 2241 | const struct b43_phy_operations b43_phyops_lp = { |
| 2232 | .allocate = b43_lpphy_op_allocate, | 2242 | .allocate = b43_lpphy_op_allocate, |
| 2233 | .free = b43_lpphy_op_free, | 2243 | .free = b43_lpphy_op_free, |
| @@ -2239,7 +2249,7 @@ const struct b43_phy_operations b43_phyops_lp = { | |||
| 2239 | .radio_read = b43_lpphy_op_radio_read, | 2249 | .radio_read = b43_lpphy_op_radio_read, |
| 2240 | .radio_write = b43_lpphy_op_radio_write, | 2250 | .radio_write = b43_lpphy_op_radio_write, |
| 2241 | .software_rfkill = b43_lpphy_op_software_rfkill, | 2251 | .software_rfkill = b43_lpphy_op_software_rfkill, |
| 2242 | .switch_analog = b43_phyop_switch_analog_generic, | 2252 | .switch_analog = b43_lpphy_op_switch_analog, |
| 2243 | .switch_channel = b43_lpphy_op_switch_channel, | 2253 | .switch_channel = b43_lpphy_op_switch_channel, |
| 2244 | .get_default_chan = b43_lpphy_op_get_default_chan, | 2254 | .get_default_chan = b43_lpphy_op_get_default_chan, |
| 2245 | .set_rx_antenna = b43_lpphy_op_set_rx_antenna, | 2255 | .set_rx_antenna = b43_lpphy_op_set_rx_antenna, |
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 3498b68385e7..e96091b31499 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c | |||
| @@ -574,7 +574,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev, | |||
| 574 | q->buffer_used -= total_len; | 574 | q->buffer_used -= total_len; |
| 575 | q->free_packet_slots += 1; | 575 | q->free_packet_slots += 1; |
| 576 | 576 | ||
| 577 | ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb); | 577 | ieee80211_tx_status(dev->wl->hw, pack->skb); |
| 578 | pack->skb = NULL; | 578 | pack->skb = NULL; |
| 579 | list_add(&pack->list, &q->packets_list); | 579 | list_add(&pack->list, &q->packets_list); |
| 580 | 580 | ||
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 31e55999893f..7a3218c5ba7d 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | /* Returns TRUE, if the radio is enabled in hardware. */ | 28 | /* Returns TRUE, if the radio is enabled in hardware. */ |
| 29 | bool b43_is_hw_radio_enabled(struct b43_wldev *dev) | 29 | bool b43_is_hw_radio_enabled(struct b43_wldev *dev) |
| 30 | { | 30 | { |
| 31 | if (dev->phy.rev >= 3) { | 31 | if (dev->phy.rev >= 3 || dev->phy.type == B43_PHYTYPE_LP) { |
| 32 | if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) | 32 | if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) |
| 33 | & B43_MMIO_RADIO_HWENABLED_HI_MASK)) | 33 | & B43_MMIO_RADIO_HWENABLED_HI_MASK)) |
| 34 | return 1; | 34 | return 1; |
diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c new file mode 100644 index 000000000000..0d3ac64147a5 --- /dev/null +++ b/drivers/net/wireless/b43/sdio.c | |||
| @@ -0,0 +1,202 @@ | |||
| 1 | /* | ||
| 2 | * Broadcom B43 wireless driver | ||
| 3 | * | ||
| 4 | * SDIO over Sonics Silicon Backplane bus glue for b43. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2009 Albert Herranz | ||
| 7 | * Copyright (C) 2009 Michael Buesch <mb@bu3sch.de> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or (at | ||
| 12 | * your option) any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/mmc/card.h> | ||
| 17 | #include <linux/mmc/sdio_func.h> | ||
| 18 | #include <linux/mmc/sdio_ids.h> | ||
| 19 | #include <linux/ssb/ssb.h> | ||
| 20 | |||
| 21 | #include "sdio.h" | ||
| 22 | #include "b43.h" | ||
| 23 | |||
| 24 | |||
| 25 | #define HNBU_CHIPID 0x01 /* vendor & device id */ | ||
| 26 | |||
| 27 | #define B43_SDIO_BLOCK_SIZE 64 /* rx fifo max size in bytes */ | ||
| 28 | |||
| 29 | |||
| 30 | static const struct b43_sdio_quirk { | ||
| 31 | u16 vendor; | ||
| 32 | u16 device; | ||
| 33 | unsigned int quirks; | ||
| 34 | } b43_sdio_quirks[] = { | ||
| 35 | { 0x14E4, 0x4318, SSB_QUIRK_SDIO_READ_AFTER_WRITE32, }, | ||
| 36 | { }, | ||
| 37 | }; | ||
| 38 | |||
| 39 | |||
| 40 | static unsigned int b43_sdio_get_quirks(u16 vendor, u16 device) | ||
| 41 | { | ||
| 42 | const struct b43_sdio_quirk *q; | ||
| 43 | |||
| 44 | for (q = b43_sdio_quirks; q->quirks; q++) { | ||
| 45 | if (vendor == q->vendor && device == q->device) | ||
| 46 | return q->quirks; | ||
| 47 | } | ||
| 48 | |||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static void b43_sdio_interrupt_dispatcher(struct sdio_func *func) | ||
| 53 | { | ||
| 54 | struct b43_sdio *sdio = sdio_get_drvdata(func); | ||
| 55 | struct b43_wldev *dev = sdio->irq_handler_opaque; | ||
| 56 | |||
| 57 | if (unlikely(b43_status(dev) < B43_STAT_STARTED)) | ||
| 58 | return; | ||
| 59 | |||
| 60 | sdio_release_host(func); | ||
| 61 | sdio->irq_handler(dev); | ||
| 62 | sdio_claim_host(func); | ||
| 63 | } | ||
| 64 | |||
| 65 | int b43_sdio_request_irq(struct b43_wldev *dev, | ||
| 66 | void (*handler)(struct b43_wldev *dev)) | ||
| 67 | { | ||
| 68 | struct ssb_bus *bus = dev->dev->bus; | ||
| 69 | struct sdio_func *func = bus->host_sdio; | ||
| 70 | struct b43_sdio *sdio = sdio_get_drvdata(func); | ||
| 71 | int err; | ||
| 72 | |||
| 73 | sdio->irq_handler_opaque = dev; | ||
| 74 | sdio->irq_handler = handler; | ||
| 75 | sdio_claim_host(func); | ||
| 76 | err = sdio_claim_irq(func, b43_sdio_interrupt_dispatcher); | ||
| 77 | sdio_release_host(func); | ||
| 78 | |||
| 79 | return err; | ||
| 80 | } | ||
| 81 | |||
| 82 | void b43_sdio_free_irq(struct b43_wldev *dev) | ||
| 83 | { | ||
| 84 | struct ssb_bus *bus = dev->dev->bus; | ||
| 85 | struct sdio_func *func = bus->host_sdio; | ||
| 86 | struct b43_sdio *sdio = sdio_get_drvdata(func); | ||
| 87 | |||
| 88 | sdio_claim_host(func); | ||
| 89 | sdio_release_irq(func); | ||
| 90 | sdio_release_host(func); | ||
| 91 | sdio->irq_handler_opaque = NULL; | ||
| 92 | sdio->irq_handler = NULL; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int b43_sdio_probe(struct sdio_func *func, | ||
| 96 | const struct sdio_device_id *id) | ||
| 97 | { | ||
| 98 | struct b43_sdio *sdio; | ||
| 99 | struct sdio_func_tuple *tuple; | ||
| 100 | u16 vendor = 0, device = 0; | ||
| 101 | int error; | ||
| 102 | |||
| 103 | /* Look for the card chip identifier. */ | ||
| 104 | tuple = func->tuples; | ||
| 105 | while (tuple) { | ||
| 106 | switch (tuple->code) { | ||
| 107 | case 0x80: | ||
| 108 | switch (tuple->data[0]) { | ||
| 109 | case HNBU_CHIPID: | ||
| 110 | if (tuple->size != 5) | ||
| 111 | break; | ||
| 112 | vendor = tuple->data[1] | (tuple->data[2]<<8); | ||
| 113 | device = tuple->data[3] | (tuple->data[4]<<8); | ||
| 114 | dev_info(&func->dev, "Chip ID %04x:%04x\n", | ||
| 115 | vendor, device); | ||
| 116 | break; | ||
| 117 | default: | ||
| 118 | break; | ||
| 119 | } | ||
| 120 | break; | ||
| 121 | default: | ||
| 122 | break; | ||
| 123 | } | ||
| 124 | tuple = tuple->next; | ||
| 125 | } | ||
| 126 | if (!vendor || !device) { | ||
| 127 | error = -ENODEV; | ||
| 128 | goto out; | ||
| 129 | } | ||
| 130 | |||
| 131 | sdio_claim_host(func); | ||
| 132 | error = sdio_set_block_size(func, B43_SDIO_BLOCK_SIZE); | ||
| 133 | if (error) { | ||
| 134 | dev_err(&func->dev, "failed to set block size to %u bytes," | ||
| 135 | " error %d\n", B43_SDIO_BLOCK_SIZE, error); | ||
| 136 | goto err_release_host; | ||
| 137 | } | ||
| 138 | error = sdio_enable_func(func); | ||
| 139 | if (error) { | ||
| 140 | dev_err(&func->dev, "failed to enable func, error %d\n", error); | ||
| 141 | goto err_release_host; | ||
| 142 | } | ||
| 143 | sdio_release_host(func); | ||
| 144 | |||
| 145 | sdio = kzalloc(sizeof(*sdio), GFP_KERNEL); | ||
| 146 | if (!sdio) { | ||
| 147 | error = -ENOMEM; | ||
| 148 | dev_err(&func->dev, "failed to allocate ssb bus\n"); | ||
| 149 | goto err_disable_func; | ||
| 150 | } | ||
| 151 | error = ssb_bus_sdiobus_register(&sdio->ssb, func, | ||
| 152 | b43_sdio_get_quirks(vendor, device)); | ||
| 153 | if (error) { | ||
| 154 | dev_err(&func->dev, "failed to register ssb sdio bus," | ||
| 155 | " error %d\n", error); | ||
| 156 | goto err_free_ssb; | ||
| 157 | } | ||
| 158 | sdio_set_drvdata(func, sdio); | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | |||
| 162 | err_free_ssb: | ||
| 163 | kfree(sdio); | ||
| 164 | err_disable_func: | ||
| 165 | sdio_disable_func(func); | ||
| 166 | err_release_host: | ||
| 167 | sdio_release_host(func); | ||
| 168 | out: | ||
| 169 | return error; | ||
| 170 | } | ||
| 171 | |||
| 172 | static void b43_sdio_remove(struct sdio_func *func) | ||
| 173 | { | ||
| 174 | struct b43_sdio *sdio = sdio_get_drvdata(func); | ||
| 175 | |||
| 176 | ssb_bus_unregister(&sdio->ssb); | ||
| 177 | sdio_disable_func(func); | ||
| 178 | kfree(sdio); | ||
| 179 | sdio_set_drvdata(func, NULL); | ||
| 180 | } | ||
| 181 | |||
| 182 | static const struct sdio_device_id b43_sdio_ids[] = { | ||
| 183 | { SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */ | ||
| 184 | { }, | ||
| 185 | }; | ||
| 186 | |||
| 187 | static struct sdio_driver b43_sdio_driver = { | ||
| 188 | .name = "b43-sdio", | ||
| 189 | .id_table = b43_sdio_ids, | ||
| 190 | .probe = b43_sdio_probe, | ||
| 191 | .remove = b43_sdio_remove, | ||
| 192 | }; | ||
| 193 | |||
| 194 | int b43_sdio_init(void) | ||
| 195 | { | ||
| 196 | return sdio_register_driver(&b43_sdio_driver); | ||
| 197 | } | ||
| 198 | |||
| 199 | void b43_sdio_exit(void) | ||
| 200 | { | ||
| 201 | sdio_unregister_driver(&b43_sdio_driver); | ||
| 202 | } | ||
diff --git a/drivers/net/wireless/b43/sdio.h b/drivers/net/wireless/b43/sdio.h new file mode 100644 index 000000000000..fb633094403a --- /dev/null +++ b/drivers/net/wireless/b43/sdio.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | #ifndef B43_SDIO_H_ | ||
| 2 | #define B43_SDIO_H_ | ||
| 3 | |||
| 4 | #include <linux/ssb/ssb.h> | ||
| 5 | |||
| 6 | struct b43_wldev; | ||
| 7 | |||
| 8 | |||
| 9 | #ifdef CONFIG_B43_SDIO | ||
| 10 | |||
| 11 | struct b43_sdio { | ||
| 12 | struct ssb_bus ssb; | ||
| 13 | void *irq_handler_opaque; | ||
| 14 | void (*irq_handler)(struct b43_wldev *dev); | ||
| 15 | }; | ||
| 16 | |||
| 17 | int b43_sdio_request_irq(struct b43_wldev *dev, | ||
| 18 | void (*handler)(struct b43_wldev *dev)); | ||
| 19 | void b43_sdio_free_irq(struct b43_wldev *dev); | ||
| 20 | |||
| 21 | int b43_sdio_init(void); | ||
| 22 | void b43_sdio_exit(void); | ||
| 23 | |||
| 24 | |||
| 25 | #else /* CONFIG_B43_SDIO */ | ||
| 26 | |||
| 27 | |||
| 28 | int b43_sdio_request_irq(struct b43_wldev *dev, | ||
| 29 | void (*handler)(struct b43_wldev *dev)) | ||
| 30 | { | ||
| 31 | return -ENODEV; | ||
| 32 | } | ||
| 33 | void b43_sdio_free_irq(struct b43_wldev *dev) | ||
| 34 | { | ||
| 35 | } | ||
| 36 | static inline int b43_sdio_init(void) | ||
| 37 | { | ||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | static inline void b43_sdio_exit(void) | ||
| 41 | { | ||
| 42 | } | ||
| 43 | |||
| 44 | #endif /* CONFIG_B43_SDIO */ | ||
| 45 | #endif /* B43_SDIO_H_ */ | ||
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 14f541248b5c..ac9f600995e4 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
| @@ -690,8 +690,11 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
| 690 | } | 690 | } |
| 691 | 691 | ||
| 692 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | 692 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); |
| 693 | ieee80211_rx_irqsafe(dev->wl->hw, skb); | 693 | ieee80211_rx(dev->wl->hw, skb); |
| 694 | 694 | ||
| 695 | #if B43_DEBUG | ||
| 696 | dev->rx_count++; | ||
| 697 | #endif | ||
| 695 | return; | 698 | return; |
| 696 | drop: | 699 | drop: |
| 697 | b43dbg(dev->wl, "RX: Packet dropped\n"); | 700 | b43dbg(dev->wl, "RX: Packet dropped\n"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index ca61d3796cef..3259b8841544 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
| @@ -2021,6 +2021,12 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
| 2021 | agg->frame_count, txq_id, idx); | 2021 | agg->frame_count, txq_id, idx); |
| 2022 | 2022 | ||
| 2023 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | 2023 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); |
| 2024 | if (!hdr) { | ||
| 2025 | IWL_ERR(priv, | ||
| 2026 | "BUG_ON idx doesn't point to valid skb" | ||
| 2027 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
| 2028 | return -1; | ||
| 2029 | } | ||
| 2024 | 2030 | ||
| 2025 | sc = le16_to_cpu(hdr->seq_ctrl); | 2031 | sc = le16_to_cpu(hdr->seq_ctrl); |
| 2026 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | 2032 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 1d539e3b8db1..a6391c7fea53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
| @@ -1163,6 +1163,12 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, | |||
| 1163 | agg->frame_count, txq_id, idx); | 1163 | agg->frame_count, txq_id, idx); |
| 1164 | 1164 | ||
| 1165 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | 1165 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); |
| 1166 | if (!hdr) { | ||
| 1167 | IWL_ERR(priv, | ||
| 1168 | "BUG_ON idx doesn't point to valid skb" | ||
| 1169 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
| 1170 | return -1; | ||
| 1171 | } | ||
| 1166 | 1172 | ||
| 1167 | sc = le16_to_cpu(hdr->seq_ctrl); | 1173 | sc = le16_to_cpu(hdr->seq_ctrl); |
| 1168 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | 1174 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index b90adcb73b06..8e1bb53c0aa3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
| @@ -250,12 +250,20 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
| 250 | } | 250 | } |
| 251 | spin_unlock_irqrestore(&rxq->lock, flags); | 251 | spin_unlock_irqrestore(&rxq->lock, flags); |
| 252 | 252 | ||
| 253 | if (rxq->free_count > RX_LOW_WATERMARK) | ||
| 254 | priority |= __GFP_NOWARN; | ||
| 253 | /* Alloc a new receive buffer */ | 255 | /* Alloc a new receive buffer */ |
| 254 | skb = alloc_skb(priv->hw_params.rx_buf_size + 256, | 256 | skb = alloc_skb(priv->hw_params.rx_buf_size + 256, |
| 255 | priority); | 257 | priority); |
| 256 | 258 | ||
| 257 | if (!skb) { | 259 | if (!skb) { |
| 258 | IWL_CRIT(priv, "Can not allocate SKB buffers\n"); | 260 | if (net_ratelimit()) |
| 261 | IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); | ||
| 262 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | ||
| 263 | net_ratelimit()) | ||
| 264 | IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n", | ||
| 265 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | ||
| 266 | rxq->free_count); | ||
| 259 | /* We don't reschedule replenish work here -- we will | 267 | /* We don't reschedule replenish work here -- we will |
| 260 | * call the restock method and if it still needs | 268 | * call the restock method and if it still needs |
| 261 | * more buffers it will schedule replenish */ | 269 | * more buffers it will schedule replenish */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index a2b9ec82b965..c6633fec8216 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/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) | |||
| 520 | struct iwl_host_cmd cmd = { | 520 | struct iwl_host_cmd cmd = { |
| 521 | .id = REPLY_WEPKEY, | 521 | .id = REPLY_WEPKEY, |
| 522 | .data = wep_cmd, | 522 | .data = wep_cmd, |
| 523 | .flags = CMD_SYNC, | 523 | .flags = CMD_ASYNC, |
| 524 | }; | 524 | }; |
| 525 | 525 | ||
| 526 | memset(wep_cmd, 0, cmd_size + | 526 | memset(wep_cmd, 0, cmd_size + |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 090966837f3c..4f2d43937283 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
| @@ -1146,11 +1146,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
| 1146 | } | 1146 | } |
| 1147 | spin_unlock_irqrestore(&rxq->lock, flags); | 1147 | spin_unlock_irqrestore(&rxq->lock, flags); |
| 1148 | 1148 | ||
| 1149 | if (rxq->free_count > RX_LOW_WATERMARK) | ||
| 1150 | priority |= __GFP_NOWARN; | ||
| 1149 | /* Alloc a new receive buffer */ | 1151 | /* Alloc a new receive buffer */ |
| 1150 | skb = alloc_skb(priv->hw_params.rx_buf_size, priority); | 1152 | skb = alloc_skb(priv->hw_params.rx_buf_size, priority); |
| 1151 | if (!skb) { | 1153 | if (!skb) { |
| 1152 | if (net_ratelimit()) | 1154 | if (net_ratelimit()) |
| 1153 | IWL_CRIT(priv, ": Can not allocate SKB buffers\n"); | 1155 | IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); |
| 1156 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | ||
| 1157 | net_ratelimit()) | ||
| 1158 | IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n", | ||
| 1159 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | ||
| 1160 | rxq->free_count); | ||
| 1154 | /* We don't reschedule replenish work here -- we will | 1161 | /* We don't reschedule replenish work here -- we will |
| 1155 | * call the restock method and if it still needs | 1162 | * call the restock method and if it still needs |
| 1156 | * more buffers it will schedule replenish */ | 1163 | * more buffers it will schedule replenish */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 5462cb5ad994..567f029a8cda 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
| @@ -380,7 +380,7 @@ static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, | |||
| 380 | { | 380 | { |
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad, | 383 | static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, |
| 384 | unsigned int header_length, | 384 | unsigned int header_length, |
| 385 | struct rxdone_entry_desc *rxdesc) | 385 | struct rxdone_entry_desc *rxdesc) |
| 386 | { | 386 | { |
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 7b14d5bc63d6..88060e117541 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | menuconfig WL12XX | 1 | menuconfig WL12XX |
| 2 | boolean "TI wl12xx driver support" | 2 | tristate "TI wl12xx driver support" |
| 3 | depends on MAC80211 && WLAN_80211 && EXPERIMENTAL | 3 | depends on MAC80211 && WLAN_80211 && EXPERIMENTAL |
| 4 | ---help--- | 4 | ---help--- |
| 5 | This will enable TI wl12xx driver support. The drivers make | 5 | This will enable TI wl12xx driver support. The drivers make |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 38688847d568..23a6a6d4863b 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
| @@ -1070,7 +1070,7 @@ static int eject_installer(struct usb_interface *intf) | |||
| 1070 | 1070 | ||
| 1071 | /* Find bulk out endpoint */ | 1071 | /* Find bulk out endpoint */ |
| 1072 | endpoint = &iface_desc->endpoint[1].desc; | 1072 | endpoint = &iface_desc->endpoint[1].desc; |
| 1073 | if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT && | 1073 | if (usb_endpoint_dir_out(endpoint) && |
| 1074 | usb_endpoint_xfer_bulk(endpoint)) { | 1074 | usb_endpoint_xfer_bulk(endpoint)) { |
| 1075 | bulk_out_ep = endpoint->bEndpointAddress; | 1075 | bulk_out_ep = endpoint->bEndpointAddress; |
| 1076 | } else { | 1076 | } else { |
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index dc22782633a5..83a044dbd1d7 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c | |||
| @@ -134,18 +134,15 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata) | |||
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | /* Enable the Rx interrupts for the first buffer */ | 136 | /* Enable the Rx interrupts for the first buffer */ |
| 137 | reg_data = in_be32(drvdata->base_addr + XEL_RSR_OFFSET); | ||
| 138 | out_be32(drvdata->base_addr + XEL_RSR_OFFSET, | 137 | out_be32(drvdata->base_addr + XEL_RSR_OFFSET, |
| 139 | reg_data | XEL_RSR_RECV_IE_MASK); | 138 | XEL_RSR_RECV_IE_MASK); |
| 140 | 139 | ||
| 141 | /* Enable the Rx interrupts for the second Buffer if | 140 | /* Enable the Rx interrupts for the second Buffer if |
| 142 | * configured in HW */ | 141 | * configured in HW */ |
| 143 | if (drvdata->rx_ping_pong != 0) { | 142 | if (drvdata->rx_ping_pong != 0) { |
| 144 | reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET + | ||
| 145 | XEL_RSR_OFFSET); | ||
| 146 | out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET + | 143 | out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET + |
| 147 | XEL_RSR_OFFSET, | 144 | XEL_RSR_OFFSET, |
| 148 | reg_data | XEL_RSR_RECV_IE_MASK); | 145 | XEL_RSR_RECV_IE_MASK); |
| 149 | } | 146 | } |
| 150 | 147 | ||
| 151 | /* Enable the Global Interrupt Enable */ | 148 | /* Enable the Global Interrupt Enable */ |
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 82b34893e5b5..9a4dd5992f65 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
| @@ -117,8 +117,6 @@ source "drivers/staging/vt6655/Kconfig" | |||
| 117 | 117 | ||
| 118 | source "drivers/staging/vt6656/Kconfig" | 118 | source "drivers/staging/vt6656/Kconfig" |
| 119 | 119 | ||
| 120 | source "drivers/staging/cpc-usb/Kconfig" | ||
| 121 | |||
| 122 | source "drivers/staging/udlfb/Kconfig" | 120 | source "drivers/staging/udlfb/Kconfig" |
| 123 | 121 | ||
| 124 | source "drivers/staging/hv/Kconfig" | 122 | source "drivers/staging/hv/Kconfig" |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index b1cad0d9ba72..104f2f8897ec 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
| @@ -40,7 +40,6 @@ obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/ | |||
| 40 | obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ | 40 | obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ |
| 41 | obj-$(CONFIG_VT6655) += vt6655/ | 41 | obj-$(CONFIG_VT6655) += vt6655/ |
| 42 | obj-$(CONFIG_VT6656) += vt6656/ | 42 | obj-$(CONFIG_VT6656) += vt6656/ |
| 43 | obj-$(CONFIG_USB_CPC) += cpc-usb/ | ||
| 44 | obj-$(CONFIG_FB_UDL) += udlfb/ | 43 | obj-$(CONFIG_FB_UDL) += udlfb/ |
| 45 | obj-$(CONFIG_HYPERV) += hv/ | 44 | obj-$(CONFIG_HYPERV) += hv/ |
| 46 | obj-$(CONFIG_VME_BUS) += vme/ | 45 | obj-$(CONFIG_VME_BUS) += vme/ |
diff --git a/drivers/staging/cpc-usb/Kconfig b/drivers/staging/cpc-usb/Kconfig deleted file mode 100644 index 2be0bc9c39d0..000000000000 --- a/drivers/staging/cpc-usb/Kconfig +++ /dev/null | |||
| @@ -1,4 +0,0 @@ | |||
| 1 | config USB_CPC | ||
| 2 | tristate "CPC CAN USB driver" | ||
| 3 | depends on USB && PROC_FS | ||
| 4 | default n | ||
diff --git a/drivers/staging/cpc-usb/Makefile b/drivers/staging/cpc-usb/Makefile deleted file mode 100644 index 3f83170a8fab..000000000000 --- a/drivers/staging/cpc-usb/Makefile +++ /dev/null | |||
| @@ -1,3 +0,0 @@ | |||
| 1 | obj-$(CONFIG_USB_CPC) += cpc-usb.o | ||
| 2 | |||
| 3 | cpc-usb-y := cpc-usb_drv.o sja2m16c_2.o | ||
diff --git a/drivers/staging/cpc-usb/TODO b/drivers/staging/cpc-usb/TODO deleted file mode 100644 index 9b1752fb9cd7..000000000000 --- a/drivers/staging/cpc-usb/TODO +++ /dev/null | |||
| @@ -1,10 +0,0 @@ | |||
| 1 | Things to do for this driver to get merged into the main portion of the | ||
| 2 | kernel: | ||
| 3 | - checkpatch cleanups | ||
| 4 | - sparse clean | ||
| 5 | - remove proc code | ||
| 6 | - tie into CAN socket interfaces if possible | ||
| 7 | - figure out sane userspace api | ||
| 8 | - use linux's error codes | ||
| 9 | |||
| 10 | Send patches to Greg Kroah-Hartman <greg@kroah.com> | ||
diff --git a/drivers/staging/cpc-usb/cpc-usb_drv.c b/drivers/staging/cpc-usb/cpc-usb_drv.c deleted file mode 100644 index c5eca46996fb..000000000000 --- a/drivers/staging/cpc-usb/cpc-usb_drv.c +++ /dev/null | |||
| @@ -1,1184 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * CPC-USB CAN Interface Kernel Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004-2009 EMS Dr. Thomas Wuensche | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published | ||
| 8 | * by the Free Software Foundation; version 2 of the License. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, but | ||
| 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | * General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License along | ||
| 16 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | */ | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/errno.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | #include <linux/vmalloc.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/poll.h> | ||
| 26 | #include <linux/smp_lock.h> | ||
| 27 | #include <linux/completion.h> | ||
| 28 | #include <asm/uaccess.h> | ||
| 29 | #include <linux/usb.h> | ||
| 30 | |||
| 31 | |||
| 32 | #include <linux/proc_fs.h> | ||
| 33 | |||
| 34 | #include "cpc.h" | ||
| 35 | |||
| 36 | #include "cpc_int.h" | ||
| 37 | #include "cpcusb.h" | ||
| 38 | |||
| 39 | #include "sja2m16c.h" | ||
| 40 | |||
| 41 | /* Version Information */ | ||
| 42 | #define DRIVER_AUTHOR "Sebastian Haas <haas@ems-wuensche.com>" | ||
| 43 | #define DRIVER_DESC "CPC-USB Driver for Linux Kernel 2.6" | ||
| 44 | #define DRIVER_VERSION CPC_DRIVER_VERSION | ||
| 45 | |||
| 46 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 47 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 48 | MODULE_VERSION(DRIVER_VERSION); | ||
| 49 | MODULE_LICENSE("GPL v2"); | ||
| 50 | |||
| 51 | /* Define these values to match your devices */ | ||
| 52 | #define USB_CPCUSB_VENDOR_ID 0x12D6 | ||
| 53 | |||
| 54 | #define USB_CPCUSB_M16C_PRODUCT_ID 0x0888 | ||
| 55 | #define USB_CPCUSB_LPC2119_PRODUCT_ID 0x0444 | ||
| 56 | |||
| 57 | #define CPC_USB_PROC_DIR CPC_PROC_DIR "cpc-usb" | ||
| 58 | |||
| 59 | static struct proc_dir_entry *procDir; | ||
| 60 | static struct proc_dir_entry *procEntry; | ||
| 61 | |||
| 62 | /* Module parameters */ | ||
| 63 | static int debug; | ||
| 64 | module_param(debug, int, S_IRUGO); | ||
| 65 | |||
| 66 | /* table of devices that work with this driver */ | ||
| 67 | static struct usb_device_id cpcusb_table[] = { | ||
| 68 | {USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_M16C_PRODUCT_ID)}, | ||
| 69 | {USB_DEVICE(USB_CPCUSB_VENDOR_ID, USB_CPCUSB_LPC2119_PRODUCT_ID)}, | ||
| 70 | {} /* Terminating entry */ | ||
| 71 | }; | ||
| 72 | |||
| 73 | MODULE_DEVICE_TABLE(usb, cpcusb_table); | ||
| 74 | |||
| 75 | /* use to prevent kernel panic if driver is unloaded | ||
| 76 | * while a programm has still open the device | ||
| 77 | */ | ||
| 78 | DECLARE_WAIT_QUEUE_HEAD(rmmodWq); | ||
| 79 | atomic_t useCount; | ||
| 80 | |||
| 81 | static CPC_USB_T *CPCUSB_Table[CPC_USB_CARD_CNT] = { 0 }; | ||
| 82 | static unsigned int CPCUsbCnt; | ||
| 83 | |||
| 84 | /* prevent races between open() and disconnect() */ | ||
| 85 | static DECLARE_MUTEX(disconnect_sem); | ||
| 86 | |||
| 87 | /* local function prototypes */ | ||
| 88 | static ssize_t cpcusb_read(struct file *file, char *buffer, size_t count, | ||
| 89 | loff_t *ppos); | ||
| 90 | static ssize_t cpcusb_write(struct file *file, const char *buffer, | ||
| 91 | size_t count, loff_t *ppos); | ||
| 92 | static unsigned int cpcusb_poll(struct file *file, poll_table * wait); | ||
| 93 | static int cpcusb_open(struct inode *inode, struct file *file); | ||
| 94 | static int cpcusb_release(struct inode *inode, struct file *file); | ||
| 95 | |||
| 96 | static int cpcusb_probe(struct usb_interface *interface, | ||
| 97 | const struct usb_device_id *id); | ||
| 98 | static void cpcusb_disconnect(struct usb_interface *interface); | ||
| 99 | |||
| 100 | static void cpcusb_read_bulk_callback(struct urb *urb); | ||
| 101 | static void cpcusb_write_bulk_callback(struct urb *urb); | ||
| 102 | static void cpcusb_read_interrupt_callback(struct urb *urb); | ||
| 103 | |||
| 104 | static int cpcusb_setup_intrep(CPC_USB_T *card); | ||
| 105 | |||
| 106 | static struct file_operations cpcusb_fops = { | ||
| 107 | /* | ||
| 108 | * The owner field is part of the module-locking | ||
| 109 | * mechanism. The idea is that the kernel knows | ||
| 110 | * which module to increment the use-counter of | ||
| 111 | * BEFORE it calls the device's open() function. | ||
| 112 | * This also means that the kernel can decrement | ||
| 113 | * the use-counter again before calling release() | ||
| 114 | * or should the open() function fail. | ||
| 115 | */ | ||
| 116 | .owner = THIS_MODULE, | ||
| 117 | |||
| 118 | .read = cpcusb_read, | ||
| 119 | .write = cpcusb_write, | ||
| 120 | .poll = cpcusb_poll, | ||
| 121 | .open = cpcusb_open, | ||
| 122 | .release = cpcusb_release, | ||
| 123 | }; | ||
| 124 | |||
| 125 | /* | ||
| 126 | * usb class driver info in order to get a minor number from the usb core, | ||
| 127 | * and to have the device registered with devfs and the driver core | ||
| 128 | */ | ||
| 129 | static struct usb_class_driver cpcusb_class = { | ||
| 130 | .name = "usb/cpc_usb%d", | ||
| 131 | .fops = &cpcusb_fops, | ||
| 132 | .minor_base = CPC_USB_BASE_MNR, | ||
| 133 | }; | ||
| 134 | |||
| 135 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
| 136 | static struct usb_driver cpcusb_driver = { | ||
| 137 | .name = "cpc-usb", | ||
| 138 | .probe = cpcusb_probe, | ||
| 139 | .disconnect = cpcusb_disconnect, | ||
| 140 | .id_table = cpcusb_table, | ||
| 141 | }; | ||
| 142 | |||
| 143 | static int cpcusb_create_info_output(char *buf) | ||
| 144 | { | ||
| 145 | int i = 0, j; | ||
| 146 | |||
| 147 | for (j = 0; j < CPC_USB_CARD_CNT; j++) { | ||
| 148 | if (CPCUSB_Table[j]) { | ||
| 149 | CPC_USB_T *card = CPCUSB_Table[j]; | ||
| 150 | CPC_CHAN_T *chan = card->chan; | ||
| 151 | |||
| 152 | /* MINOR CHANNELNO BUSNO SLOTNO */ | ||
| 153 | i += sprintf(&buf[i], "%d %s\n", chan->minor, | ||
| 154 | card->serialNumber); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | return i; | ||
| 159 | } | ||
| 160 | |||
| 161 | static int cpcusb_proc_read_info(char *page, char **start, off_t off, | ||
| 162 | int count, int *eof, void *data) | ||
| 163 | { | ||
| 164 | int len = cpcusb_create_info_output(page); | ||
| 165 | |||
| 166 | if (len <= off + count) | ||
| 167 | *eof = 1; | ||
| 168 | *start = page + off; | ||
| 169 | len -= off; | ||
| 170 | if (len > count) | ||
| 171 | len = count; | ||
| 172 | if (len < 0) | ||
| 173 | len = 0; | ||
| 174 | |||
| 175 | return len; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* | ||
| 179 | * Remove CPC-USB and cleanup | ||
| 180 | */ | ||
| 181 | static inline void cpcusb_delete(CPC_USB_T *card) | ||
| 182 | { | ||
| 183 | if (card) { | ||
| 184 | if (card->chan) { | ||
| 185 | if (card->chan->buf) | ||
| 186 | vfree(card->chan->buf); | ||
| 187 | |||
| 188 | if (card->chan->CPCWait_q) | ||
| 189 | kfree(card->chan->CPCWait_q); | ||
| 190 | |||
| 191 | kfree(card->chan); | ||
| 192 | } | ||
| 193 | |||
| 194 | CPCUSB_Table[card->idx] = NULL; | ||
| 195 | kfree(card); | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | /* | ||
| 200 | * setup the interrupt IN endpoint of a specific CPC-USB device | ||
| 201 | */ | ||
| 202 | static int cpcusb_setup_intrep(CPC_USB_T *card) | ||
| 203 | { | ||
| 204 | int retval = 0; | ||
| 205 | struct usb_endpoint_descriptor *ep; | ||
| 206 | |||
| 207 | ep = &card->interface->altsetting[0].endpoint[card->num_intr_in].desc; | ||
| 208 | |||
| 209 | card->intr_in_buffer[0] = 0; | ||
| 210 | card->free_slots = 15; /* initial size */ | ||
| 211 | |||
| 212 | /* setup the urb */ | ||
| 213 | usb_fill_int_urb(card->intr_in_urb, card->udev, | ||
| 214 | usb_rcvintpipe(card->udev, card->num_intr_in), | ||
| 215 | card->intr_in_buffer, | ||
| 216 | sizeof(card->intr_in_buffer), | ||
| 217 | cpcusb_read_interrupt_callback, | ||
| 218 | card, | ||
| 219 | ep->bInterval); | ||
| 220 | |||
| 221 | card->intr_in_urb->status = 0; /* needed! */ | ||
| 222 | |||
| 223 | /* submit the urb */ | ||
| 224 | retval = usb_submit_urb(card->intr_in_urb, GFP_KERNEL); | ||
| 225 | |||
| 226 | if (retval) | ||
| 227 | err("%s - failed submitting intr urb, error %d", __func__, | ||
| 228 | retval); | ||
| 229 | |||
| 230 | return retval; | ||
| 231 | } | ||
| 232 | |||
| 233 | static int cpcusb_open(struct inode *inode, struct file *file) | ||
| 234 | { | ||
| 235 | CPC_USB_T *card = NULL; | ||
| 236 | struct usb_interface *interface; | ||
| 237 | int subminor; | ||
| 238 | int j, retval = 0; | ||
| 239 | |||
| 240 | subminor = iminor(inode); | ||
| 241 | |||
| 242 | /* prevent disconnects */ | ||
| 243 | down(&disconnect_sem); | ||
| 244 | |||
| 245 | interface = usb_find_interface(&cpcusb_driver, subminor); | ||
| 246 | if (!interface) { | ||
| 247 | err("%s - error, can't find device for minor %d", | ||
| 248 | __func__, subminor); | ||
| 249 | retval = CPC_ERR_NO_INTERFACE_PRESENT; | ||
| 250 | goto exit_no_device; | ||
| 251 | } | ||
| 252 | |||
| 253 | card = usb_get_intfdata(interface); | ||
| 254 | if (!card) { | ||
| 255 | retval = CPC_ERR_NO_INTERFACE_PRESENT; | ||
| 256 | goto exit_no_device; | ||
| 257 | } | ||
| 258 | |||
| 259 | /* lock this device */ | ||
| 260 | down(&card->sem); | ||
| 261 | |||
| 262 | /* increment our usage count for the driver */ | ||
| 263 | if (card->open) { | ||
| 264 | dbg("device already opened"); | ||
| 265 | retval = CPC_ERR_CHANNEL_ALREADY_OPEN; | ||
| 266 | goto exit_on_error; | ||
| 267 | } | ||
| 268 | |||
| 269 | /* save our object in the file's private structure */ | ||
| 270 | file->private_data = card; | ||
| 271 | for (j = 0; j < CPC_USB_URB_CNT; j++) { | ||
| 272 | usb_fill_bulk_urb(card->urbs[j].urb, card->udev, | ||
| 273 | usb_rcvbulkpipe(card->udev, card->num_bulk_in), | ||
| 274 | card->urbs[j].buffer, card->urbs[j].size, | ||
| 275 | cpcusb_read_bulk_callback, card); | ||
| 276 | |||
| 277 | retval = usb_submit_urb(card->urbs[j].urb, GFP_KERNEL); | ||
| 278 | |||
| 279 | if (retval) { | ||
| 280 | err("%s - failed submitting read urb, error %d", | ||
| 281 | __func__, retval); | ||
| 282 | retval = CPC_ERR_TRANSMISSION_FAILED; | ||
| 283 | goto exit_on_error; | ||
| 284 | } | ||
| 285 | } | ||
| 286 | |||
| 287 | info("%s - %d URB's submitted", __func__, j); | ||
| 288 | |||
| 289 | ResetBuffer(card->chan); | ||
| 290 | |||
| 291 | cpcusb_setup_intrep(card); | ||
| 292 | card->open = 1; | ||
| 293 | |||
| 294 | atomic_inc(&useCount); | ||
| 295 | |||
| 296 | exit_on_error: | ||
| 297 | /* unlock this device */ | ||
| 298 | up(&card->sem); | ||
| 299 | |||
| 300 | exit_no_device: | ||
| 301 | up(&disconnect_sem); | ||
| 302 | |||
| 303 | return retval; | ||
| 304 | } | ||
| 305 | |||
| 306 | static unsigned int cpcusb_poll(struct file *file, poll_table * wait) | ||
| 307 | { | ||
| 308 | CPC_USB_T *card = (CPC_USB_T *) file->private_data; | ||
| 309 | unsigned int retval = 0; | ||
| 310 | |||
| 311 | if (!card) { | ||
| 312 | err("%s - device object lost", __func__); | ||
| 313 | return -EIO; | ||
| 314 | } | ||
| 315 | |||
| 316 | poll_wait(file, card->chan->CPCWait_q, wait); | ||
| 317 | |||
| 318 | if (IsBufferNotEmpty(card->chan) || !(card->present)) | ||
| 319 | retval |= (POLLIN | POLLRDNORM); | ||
| 320 | |||
| 321 | if (card->free_slots) | ||
| 322 | retval |= (POLLOUT | POLLWRNORM); | ||
| 323 | |||
| 324 | return retval; | ||
| 325 | } | ||
| 326 | |||
| 327 | static int cpcusb_release(struct inode *inode, struct file *file) | ||
| 328 | { | ||
| 329 | CPC_USB_T *card = (CPC_USB_T *) file->private_data; | ||
| 330 | int j, retval = 0; | ||
| 331 | |||
| 332 | if (card == NULL) { | ||
| 333 | dbg("%s - object is NULL", __func__); | ||
| 334 | return CPC_ERR_NO_INTERFACE_PRESENT; | ||
| 335 | } | ||
| 336 | |||
| 337 | /* lock our device */ | ||
| 338 | down(&card->sem); | ||
| 339 | |||
| 340 | if (!card->open) { | ||
| 341 | dbg("%s - device not opened", __func__); | ||
| 342 | retval = CPC_ERR_NO_INTERFACE_PRESENT; | ||
| 343 | goto exit_not_opened; | ||
| 344 | } | ||
| 345 | |||
| 346 | /* if device wasn't unplugged kill all urbs */ | ||
| 347 | if (card->present) { | ||
| 348 | /* kill read urbs */ | ||
| 349 | for (j = 0; j < CPC_USB_URB_CNT; j++) { | ||
| 350 | usb_kill_urb(card->urbs[j].urb); | ||
| 351 | } | ||
| 352 | |||
| 353 | /* kill irq urb */ | ||
| 354 | usb_kill_urb(card->intr_in_urb); | ||
| 355 | |||
| 356 | /* kill write urbs */ | ||
| 357 | for (j = 0; j < CPC_USB_URB_CNT; j++) { | ||
| 358 | if (atomic_read(&card->wrUrbs[j].busy)) { | ||
| 359 | usb_kill_urb(card->wrUrbs[j].urb); | ||
| 360 | wait_for_completion(&card->wrUrbs[j].finished); | ||
| 361 | } | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | atomic_dec(&useCount); | ||
| 366 | |||
| 367 | /* last process detached */ | ||
| 368 | if (atomic_read(&useCount) == 0) { | ||
| 369 | wake_up(&rmmodWq); | ||
| 370 | } | ||
| 371 | |||
| 372 | if (!card->present && card->open) { | ||
| 373 | /* the device was unplugged before the file was released */ | ||
| 374 | up(&card->sem); | ||
| 375 | cpcusb_delete(card); | ||
| 376 | return 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | card->open = 0; | ||
| 380 | |||
| 381 | exit_not_opened: | ||
| 382 | up(&card->sem); | ||
| 383 | |||
| 384 | return 0; | ||
| 385 | } | ||
| 386 | |||
| 387 | static ssize_t cpcusb_read(struct file *file, char *buffer, size_t count, | ||
| 388 | loff_t *ppos) | ||
| 389 | { | ||
| 390 | CPC_USB_T *card = (CPC_USB_T *) file->private_data; | ||
| 391 | CPC_CHAN_T *chan; | ||
| 392 | int retval = 0; | ||
| 393 | |||
| 394 | if (count < sizeof(CPC_MSG_T)) | ||
| 395 | return CPC_ERR_UNKNOWN; | ||
| 396 | |||
| 397 | /* check if can read from the given address */ | ||
| 398 | if (!access_ok(VERIFY_WRITE, buffer, count)) | ||
| 399 | return CPC_ERR_UNKNOWN; | ||
| 400 | |||
| 401 | /* lock this object */ | ||
| 402 | down(&card->sem); | ||
| 403 | |||
| 404 | /* verify that the device wasn't unplugged */ | ||
| 405 | if (!card->present) { | ||
| 406 | up(&card->sem); | ||
| 407 | return CPC_ERR_NO_INTERFACE_PRESENT; | ||
| 408 | } | ||
| 409 | |||
| 410 | if (IsBufferEmpty(card->chan)) { | ||
| 411 | retval = 0; | ||
| 412 | } else { | ||
| 413 | chan = card->chan; | ||
| 414 | |||
| 415 | #if 0 | ||
| 416 | /* convert LPC2119 params back to SJA1000 params */ | ||
| 417 | if (card->deviceRevision >= 0x0200 | ||
| 418 | && chan->buf[chan->oidx].type == CPC_MSG_T_CAN_PRMS) { | ||
| 419 | LPC2119_TO_SJA1000_Params(&chan->buf[chan->oidx]); | ||
| 420 | } | ||
| 421 | #endif | ||
| 422 | |||
| 423 | if (copy_to_user(buffer, &chan->buf[chan->oidx], count) != 0) { | ||
| 424 | retval = CPC_ERR_IO_TRANSFER; | ||
| 425 | } else { | ||
| 426 | chan->oidx = (chan->oidx + 1) % CPC_MSG_BUF_CNT; | ||
| 427 | chan->WnR = 1; | ||
| 428 | retval = sizeof(CPC_MSG_T); | ||
| 429 | } | ||
| 430 | } | ||
| 431 | /* spin_unlock_irqrestore(&card->slock, flags); */ | ||
| 432 | |||
| 433 | /* unlock the device */ | ||
| 434 | up(&card->sem); | ||
| 435 | |||
| 436 | return retval; | ||
| 437 | } | ||
| 438 | |||
| 439 | #define SHIFT 1 | ||
| 440 | static inline void cpcusb_align_buffer_alignment(unsigned char *buf) | ||
| 441 | { | ||
| 442 | /* CPC-USB uploads packed bytes. */ | ||
| 443 | CPC_MSG_T *cpc = (CPC_MSG_T *) buf; | ||
| 444 | unsigned int i; | ||
| 445 | |||
| 446 | for (i = 0; i < cpc->length + (2 * sizeof(unsigned long)); i++) { | ||
| 447 | ((unsigned char *) &cpc->msgid)[1 + i] = | ||
| 448 | ((unsigned char *) &cpc->msgid)[1 + SHIFT + i]; | ||
| 449 | } | ||
| 450 | } | ||
| 451 | |||
| 452 | static int cpc_get_buffer_count(CPC_CHAN_T *chan) | ||
| 453 | { | ||
| 454 | /* check the buffer parameters */ | ||
| 455 | if (chan->iidx == chan->oidx) | ||
| 456 | return !chan->WnR ? CPC_MSG_BUF_CNT : 0; | ||
| 457 | else if (chan->iidx >= chan->oidx) | ||
| 458 | return (chan->iidx - chan->oidx) % CPC_MSG_BUF_CNT; | ||
| 459 | |||
| 460 | return (chan->iidx + CPC_MSG_BUF_CNT - chan->oidx) % CPC_MSG_BUF_CNT; | ||
| 461 | } | ||
| 462 | |||
| 463 | static ssize_t cpcusb_write(struct file *file, const char *buffer, | ||
| 464 | size_t count, loff_t *ppos) | ||
| 465 | { | ||
| 466 | CPC_USB_T *card = (CPC_USB_T *) file->private_data; | ||
| 467 | CPC_USB_WRITE_URB_T *wrUrb = NULL; | ||
| 468 | |||
| 469 | ssize_t bytes_written = 0; | ||
| 470 | int retval = 0; | ||
| 471 | int j; | ||
| 472 | |||
| 473 | unsigned char *obuf = NULL; | ||
| 474 | unsigned char type = 0; | ||
| 475 | CPC_MSG_T *info = NULL; | ||
| 476 | |||
| 477 | dbg("%s - entered minor %d, count = %zu, present = %d", | ||
| 478 | __func__, card->minor, count, card->present); | ||
| 479 | |||
| 480 | if (count > sizeof(CPC_MSG_T)) | ||
| 481 | return CPC_ERR_UNKNOWN; | ||
| 482 | |||
| 483 | /* check if can read from the given address */ | ||
| 484 | if (!access_ok(VERIFY_READ, buffer, count)) | ||
| 485 | return CPC_ERR_UNKNOWN; | ||
| 486 | |||
| 487 | /* lock this object */ | ||
| 488 | down(&card->sem); | ||
| 489 | |||
| 490 | /* verify that the device wasn't unplugged */ | ||
| 491 | if (!card->present) { | ||
| 492 | retval = CPC_ERR_NO_INTERFACE_PRESENT; | ||
| 493 | goto exit; | ||
| 494 | } | ||
| 495 | |||
| 496 | /* verify that we actually have some data to write */ | ||
| 497 | if (count == 0) { | ||
| 498 | dbg("%s - write request of 0 bytes", __func__); | ||
| 499 | goto exit; | ||
| 500 | } | ||
| 501 | |||
| 502 | if (card->free_slots <= 5) { | ||
| 503 | info = (CPC_MSG_T *) buffer; | ||
| 504 | |||
| 505 | if (info->type != CPC_CMD_T_CLEAR_CMD_QUEUE | ||
| 506 | || card->free_slots <= 0) { | ||
| 507 | dbg("%s - send buffer full please try again %d", | ||
| 508 | __func__, card->free_slots); | ||
| 509 | retval = CPC_ERR_CAN_NO_TRANSMIT_BUF; | ||
| 510 | goto exit; | ||
| 511 | } | ||
| 512 | } | ||
| 513 | |||
| 514 | /* Find a free write urb */ | ||
| 515 | for (j = 0; j < CPC_USB_URB_CNT; j++) { | ||
| 516 | if (!atomic_read(&card->wrUrbs[j].busy)) { | ||
| 517 | wrUrb = &card->wrUrbs[j]; /* remember found URB */ | ||
| 518 | atomic_set(&wrUrb->busy, 1); /* lock this URB */ | ||
| 519 | init_completion(&wrUrb->finished); /* init completion */ | ||
| 520 | dbg("WR URB no. %d started", j); | ||
| 521 | break; | ||
| 522 | } | ||
| 523 | } | ||
| 524 | |||
| 525 | /* don't found write urb say error */ | ||
| 526 | if (!wrUrb) { | ||
| 527 | dbg("%s - no free send urb available", __func__); | ||
| 528 | retval = CPC_ERR_CAN_NO_TRANSMIT_BUF; | ||
| 529 | goto exit; | ||
| 530 | } | ||
| 531 | dbg("URB write req"); | ||
| 532 | |||
| 533 | obuf = (unsigned char *) wrUrb->urb->transfer_buffer; | ||
| 534 | |||
| 535 | /* copy the data from userspace into our transfer buffer; | ||
| 536 | * this is the only copy required. | ||
| 537 | */ | ||
| 538 | if (copy_from_user(&obuf[4], buffer, count) != 0) { | ||
| 539 | atomic_set(&wrUrb->busy, 0); /* release urb */ | ||
| 540 | retval = CPC_ERR_IO_TRANSFER; | ||
| 541 | goto exit; | ||
| 542 | } | ||
| 543 | |||
| 544 | /* check if it is a DRIVER information message, so we can | ||
| 545 | * response to that message and not the USB | ||
| 546 | */ | ||
| 547 | info = (CPC_MSG_T *) &obuf[4]; | ||
| 548 | |||
| 549 | bytes_written = 11 + info->length; | ||
| 550 | if (bytes_written >= wrUrb->size) { | ||
| 551 | retval = CPC_ERR_IO_TRANSFER; | ||
| 552 | goto exit; | ||
| 553 | } | ||
| 554 | |||
| 555 | switch (info->type) { | ||
| 556 | case CPC_CMD_T_CLEAR_MSG_QUEUE: | ||
| 557 | ResetBuffer(card->chan); | ||
| 558 | break; | ||
| 559 | |||
| 560 | case CPC_CMD_T_INQ_MSG_QUEUE_CNT: | ||
| 561 | retval = cpc_get_buffer_count(card->chan); | ||
| 562 | atomic_set(&wrUrb->busy, 0); | ||
| 563 | |||
| 564 | goto exit; | ||
| 565 | |||
| 566 | case CPC_CMD_T_INQ_INFO: | ||
| 567 | if (info->msg.info.source == CPC_INFOMSG_T_DRIVER) { | ||
| 568 | /* release urb cause we'll use it for driver | ||
| 569 | * information | ||
| 570 | */ | ||
| 571 | atomic_set(&wrUrb->busy, 0); | ||
| 572 | if (IsBufferFull(card->chan)) { | ||
| 573 | retval = CPC_ERR_IO_TRANSFER; | ||
| 574 | goto exit; | ||
| 575 | } | ||
| 576 | |||
| 577 | /* it is a driver information request message and we have | ||
| 578 | * free rx slots to store the response | ||
| 579 | */ | ||
| 580 | type = info->msg.info.type; | ||
| 581 | info = &card->chan->buf[card->chan->iidx]; | ||
| 582 | |||
| 583 | info->type = CPC_MSG_T_INFO; | ||
| 584 | info->msg.info.source = CPC_INFOMSG_T_DRIVER; | ||
| 585 | info->msg.info.type = type; | ||
| 586 | |||
| 587 | switch (type) { | ||
| 588 | case CPC_INFOMSG_T_VERSION: | ||
| 589 | info->length = strlen(CPC_DRIVER_VERSION) + 2; | ||
| 590 | sprintf(info->msg.info.msg, "%s\n", | ||
| 591 | CPC_DRIVER_VERSION); | ||
| 592 | break; | ||
| 593 | |||
| 594 | case CPC_INFOMSG_T_SERIAL: | ||
| 595 | info->length = strlen(CPC_DRIVER_SERIAL) + 2; | ||
| 596 | sprintf(info->msg.info.msg, "%s\n", | ||
| 597 | CPC_DRIVER_SERIAL); | ||
| 598 | break; | ||
| 599 | |||
| 600 | default: | ||
| 601 | info->length = 2; | ||
| 602 | info->msg.info.type = | ||
| 603 | CPC_INFOMSG_T_UNKNOWN_TYPE; | ||
| 604 | } | ||
| 605 | |||
| 606 | card->chan->WnR = 0; | ||
| 607 | card->chan->iidx = | ||
| 608 | (card->chan->iidx + 1) % CPC_MSG_BUF_CNT; | ||
| 609 | |||
| 610 | retval = info->length; | ||
| 611 | goto exit; | ||
| 612 | } | ||
| 613 | break; | ||
| 614 | case CPC_CMD_T_CAN_PRMS: | ||
| 615 | /* Check the controller type. If it's the new CPC-USB, make sure if these are SJA1000 params */ | ||
| 616 | if (info->msg.canparams.cc_type != SJA1000 | ||
| 617 | && info->msg.canparams.cc_type != M16C_BASIC | ||
| 618 | && (card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID | ||
| 619 | && info->msg.canparams.cc_type != SJA1000)) { | ||
| 620 | /* don't forget to release the urb */ | ||
| 621 | atomic_set(&wrUrb->busy, 0); | ||
| 622 | retval = CPC_ERR_WRONG_CONTROLLER_TYPE; | ||
| 623 | goto exit; | ||
| 624 | } | ||
| 625 | break; | ||
| 626 | } | ||
| 627 | |||
| 628 | /* just convert the params if it is an old CPC-USB with M16C controller */ | ||
| 629 | if (card->productId == USB_CPCUSB_M16C_PRODUCT_ID) { | ||
| 630 | /* if it is a parameter message convert it from SJA1000 controller | ||
| 631 | * settings to M16C Basic controller settings | ||
| 632 | */ | ||
| 633 | SJA1000_TO_M16C_BASIC_Params((CPC_MSG_T *) &obuf[4]); | ||
| 634 | } | ||
| 635 | |||
| 636 | /* don't forget the byte alignment */ | ||
| 637 | cpcusb_align_buffer_alignment(&obuf[4]); | ||
| 638 | |||
| 639 | /* setup a the 4 byte header */ | ||
| 640 | obuf[0] = obuf[1] = obuf[2] = obuf[3] = 0; | ||
| 641 | |||
| 642 | /* this urb was already set up, except for this write size */ | ||
| 643 | wrUrb->urb->transfer_buffer_length = bytes_written + 4; | ||
| 644 | |||
| 645 | /* send the data out the bulk port */ | ||
| 646 | /* a character device write uses GFP_KERNEL, | ||
| 647 | unless a spinlock is held */ | ||
| 648 | retval = usb_submit_urb(wrUrb->urb, GFP_KERNEL); | ||
| 649 | if (retval) { | ||
| 650 | atomic_set(&wrUrb->busy, 0); /* release urb */ | ||
| 651 | err("%s - failed submitting write urb, error %d", | ||
| 652 | __func__, retval); | ||
| 653 | } else { | ||
| 654 | retval = bytes_written; | ||
| 655 | } | ||
| 656 | |||
| 657 | exit: | ||
| 658 | /* unlock the device */ | ||
| 659 | up(&card->sem); | ||
| 660 | |||
| 661 | dbg("%s - leaved", __func__); | ||
| 662 | |||
| 663 | return retval; | ||
| 664 | } | ||
| 665 | |||
| 666 | /* | ||
| 667 | * callback for interrupt IN urb | ||
| 668 | */ | ||
| 669 | static void cpcusb_read_interrupt_callback(struct urb *urb) | ||
| 670 | { | ||
| 671 | CPC_USB_T *card = (CPC_USB_T *) urb->context; | ||
| 672 | int retval; | ||
| 673 | unsigned long flags; | ||
| 674 | |||
| 675 | spin_lock_irqsave(&card->slock, flags); | ||
| 676 | |||
| 677 | if (!card->present) { | ||
| 678 | spin_unlock_irqrestore(&card->slock, flags); | ||
| 679 | info("%s - no such device", __func__); | ||
| 680 | return; | ||
| 681 | } | ||
| 682 | |||
| 683 | switch (urb->status) { | ||
| 684 | case 0: /* success */ | ||
| 685 | card->free_slots = card->intr_in_buffer[1]; | ||
| 686 | break; | ||
| 687 | case -ECONNRESET: | ||
| 688 | case -ENOENT: | ||
| 689 | case -ESHUTDOWN: | ||
| 690 | /* urb was killed */ | ||
| 691 | spin_unlock_irqrestore(&card->slock, flags); | ||
| 692 | dbg("%s - intr urb killed", __func__); | ||
| 693 | return; | ||
| 694 | default: | ||
| 695 | info("%s - nonzero urb status %d", __func__, urb->status); | ||
| 696 | break; | ||
| 697 | } | ||
| 698 | |||
| 699 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 700 | if (retval) { | ||
| 701 | err("%s - failed resubmitting intr urb, error %d", | ||
| 702 | __func__, retval); | ||
| 703 | } | ||
| 704 | |||
| 705 | spin_unlock_irqrestore(&card->slock, flags); | ||
| 706 | wake_up_interruptible(card->chan->CPCWait_q); | ||
| 707 | |||
| 708 | return; | ||
| 709 | } | ||
| 710 | |||
| 711 | #define UN_SHIFT 1 | ||
| 712 | #define CPCMSG_HEADER_LEN_FIRMWARE 11 | ||
| 713 | static inline int cpcusb_unalign_and_copy_buffy(unsigned char *out, | ||
| 714 | unsigned char *in) | ||
| 715 | { | ||
| 716 | unsigned int i, j; | ||
| 717 | |||
| 718 | for (i = 0; i < 3; i++) | ||
| 719 | out[i] = in[i]; | ||
| 720 | |||
| 721 | for (j = 0; j < (in[1] + (CPCMSG_HEADER_LEN_FIRMWARE - 3)); j++) | ||
| 722 | out[j + i + UN_SHIFT] = in[j + i]; | ||
| 723 | |||
| 724 | return i + j; | ||
| 725 | } | ||
| 726 | |||
| 727 | /* | ||
| 728 | * callback for bulk IN urb | ||
| 729 | */ | ||
| 730 | static void cpcusb_read_bulk_callback(struct urb *urb) | ||
| 731 | { | ||
| 732 | CPC_USB_T *card = (CPC_USB_T *) urb->context; | ||
| 733 | CPC_CHAN_T *chan; | ||
| 734 | unsigned char *ibuf = urb->transfer_buffer; | ||
| 735 | int retval, msgCnt, start, again = 0; | ||
| 736 | unsigned long flags; | ||
| 737 | |||
| 738 | if (!card) { | ||
| 739 | err("%s - device object lost", __func__); | ||
| 740 | return; | ||
| 741 | } | ||
| 742 | |||
| 743 | spin_lock_irqsave(&card->slock, flags); | ||
| 744 | |||
| 745 | if (!card->present) { | ||
| 746 | spin_unlock_irqrestore(&card->slock, flags); | ||
| 747 | info("%s - no such device", __func__); | ||
| 748 | return; | ||
| 749 | } | ||
| 750 | |||
| 751 | switch (urb->status) { | ||
| 752 | case 0: /* success */ | ||
| 753 | break; | ||
| 754 | case -ECONNRESET: | ||
| 755 | case -ENOENT: | ||
| 756 | case -ESHUTDOWN: | ||
| 757 | /* urb was killed */ | ||
| 758 | spin_unlock_irqrestore(&card->slock, flags); | ||
| 759 | dbg("%s - read urb killed", __func__); | ||
| 760 | return; | ||
| 761 | default: | ||
| 762 | info("%s - nonzero urb status %d", __func__, urb->status); | ||
| 763 | break; | ||
| 764 | } | ||
| 765 | |||
| 766 | if (urb->actual_length) { | ||
| 767 | msgCnt = ibuf[0] & ~0x80; | ||
| 768 | again = ibuf[0] & 0x80; | ||
| 769 | |||
| 770 | /* we have a 4 byte header */ | ||
| 771 | start = 4; | ||
| 772 | chan = card->chan; | ||
| 773 | while (msgCnt) { | ||
| 774 | if (!(IsBufferFull(card->chan))) { | ||
| 775 | start += | ||
| 776 | cpcusb_unalign_and_copy_buffy((unsigned char *) | ||
| 777 | &chan->buf[chan->iidx], &ibuf[start]); | ||
| 778 | |||
| 779 | if (start > urb->transfer_buffer_length) { | ||
| 780 | err("%d > %d", start, urb->transfer_buffer_length); | ||
| 781 | break; | ||
| 782 | } | ||
| 783 | |||
| 784 | chan->WnR = 0; | ||
| 785 | chan->iidx = (chan->iidx + 1) % CPC_MSG_BUF_CNT; | ||
| 786 | msgCnt--; | ||
| 787 | } else { | ||
| 788 | break; | ||
| 789 | } | ||
| 790 | } | ||
| 791 | } | ||
| 792 | |||
| 793 | usb_fill_bulk_urb(urb, card->udev, | ||
| 794 | usb_rcvbulkpipe(card->udev, card->num_bulk_in), | ||
| 795 | urb->transfer_buffer, | ||
| 796 | urb->transfer_buffer_length, | ||
| 797 | cpcusb_read_bulk_callback, card); | ||
| 798 | |||
| 799 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 800 | |||
| 801 | if (retval) { | ||
| 802 | err("%s - failed resubmitting read urb, error %d", __func__, retval); | ||
| 803 | } | ||
| 804 | |||
| 805 | spin_unlock_irqrestore(&card->slock, flags); | ||
| 806 | |||
| 807 | wake_up_interruptible(card->chan->CPCWait_q); | ||
| 808 | } | ||
| 809 | |||
| 810 | /* | ||
| 811 | * callback for bulk IN urb | ||
| 812 | */ | ||
| 813 | static void cpcusb_write_bulk_callback(struct urb *urb) | ||
| 814 | { | ||
| 815 | CPC_USB_T *card = (CPC_USB_T *) urb->context; | ||
| 816 | unsigned long flags; | ||
| 817 | int j; | ||
| 818 | |||
| 819 | spin_lock_irqsave(&card->slock, flags); | ||
| 820 | |||
| 821 | /* find this urb */ | ||
| 822 | for (j = 0; j < CPC_USB_URB_CNT; j++) { | ||
| 823 | if (card->wrUrbs[j].urb == urb) { | ||
| 824 | dbg("URB found no. %d", j); | ||
| 825 | /* notify anyone waiting that the write has finished */ | ||
| 826 | complete(&card->wrUrbs[j].finished); | ||
| 827 | atomic_set(&card->wrUrbs[j].busy, 0); | ||
| 828 | break; | ||
| 829 | } | ||
| 830 | } | ||
| 831 | |||
| 832 | switch (urb->status) { | ||
| 833 | case 0: /* success */ | ||
| 834 | break; | ||
| 835 | case -ECONNRESET: | ||
| 836 | case -ENOENT: | ||
| 837 | case -ESHUTDOWN: | ||
| 838 | /* urb was killed */ | ||
| 839 | spin_unlock_irqrestore(&card->slock, flags); | ||
| 840 | dbg("%s - write urb no. %d killed", __func__, j); | ||
| 841 | return; | ||
| 842 | default: | ||
| 843 | info("%s - nonzero urb status %d", __func__, urb->status); | ||
| 844 | break; | ||
| 845 | } | ||
| 846 | |||
| 847 | spin_unlock_irqrestore(&card->slock, flags); | ||
| 848 | |||
| 849 | wake_up_interruptible(card->chan->CPCWait_q); | ||
| 850 | } | ||
| 851 | |||
| 852 | static inline int cpcusb_get_free_slot(void) | ||
| 853 | { | ||
| 854 | int i; | ||
| 855 | |||
| 856 | for (i = 0; i < CPC_USB_CARD_CNT; i++) { | ||
| 857 | if (!CPCUSB_Table[i]) | ||
| 858 | return i; | ||
| 859 | } | ||
| 860 | |||
| 861 | return -1; | ||
| 862 | } | ||
| 863 | |||
| 864 | /* | ||
| 865 | * probe function for new CPC-USB devices | ||
| 866 | */ | ||
| 867 | static int cpcusb_probe(struct usb_interface *interface, | ||
| 868 | const struct usb_device_id *id) | ||
| 869 | { | ||
| 870 | CPC_USB_T *card = NULL; | ||
| 871 | CPC_CHAN_T *chan = NULL; | ||
| 872 | |||
| 873 | struct usb_device *udev = interface_to_usbdev(interface); | ||
| 874 | struct usb_host_interface *iface_desc; | ||
| 875 | struct usb_endpoint_descriptor *endpoint; | ||
| 876 | |||
| 877 | int i, j, retval = -ENOMEM, slot; | ||
| 878 | |||
| 879 | slot = cpcusb_get_free_slot(); | ||
| 880 | if (slot < 0) { | ||
| 881 | info("No more devices supported"); | ||
| 882 | return -ENOMEM; | ||
| 883 | } | ||
| 884 | |||
| 885 | /* allocate memory for our device state and initialize it */ | ||
| 886 | card = kzalloc(sizeof(CPC_USB_T), GFP_KERNEL); | ||
| 887 | if (!card) { | ||
| 888 | err("Out of memory"); | ||
| 889 | return -ENOMEM; | ||
| 890 | } | ||
| 891 | CPCUSB_Table[slot] = card; | ||
| 892 | |||
| 893 | /* allocate and initialize the channel struct */ | ||
| 894 | card->chan = kmalloc(sizeof(CPC_CHAN_T), GFP_KERNEL); | ||
| 895 | if (!card->chan) { | ||
| 896 | kfree(card); | ||
| 897 | err("Out of memory"); | ||
| 898 | return -ENOMEM; | ||
| 899 | } | ||
| 900 | |||
| 901 | chan = card->chan; | ||
| 902 | memset(chan, 0, sizeof(CPC_CHAN_T)); | ||
| 903 | ResetBuffer(chan); | ||
| 904 | |||
| 905 | init_MUTEX(&card->sem); | ||
| 906 | spin_lock_init(&card->slock); | ||
| 907 | |||
| 908 | card->udev = udev; | ||
| 909 | card->interface = interface; | ||
| 910 | if (udev->descriptor.iSerialNumber) { | ||
| 911 | usb_string(udev, udev->descriptor.iSerialNumber, card->serialNumber, | ||
| 912 | 128); | ||
| 913 | info("Serial %s", card->serialNumber); | ||
| 914 | } | ||
| 915 | |||
| 916 | card->productId = udev->descriptor.idProduct; | ||
| 917 | info("Product %s", | ||
| 918 | card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID ? | ||
| 919 | "CPC-USB/ARM7" : "CPC-USB/M16C"); | ||
| 920 | |||
| 921 | /* set up the endpoint information */ | ||
| 922 | /* check out the endpoints */ | ||
| 923 | /* use only the first bulk-in and bulk-out endpoints */ | ||
| 924 | iface_desc = &interface->altsetting[0]; | ||
| 925 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
| 926 | endpoint = &iface_desc->endpoint[i].desc; | ||
| 927 | |||
| 928 | if (!card->num_intr_in && | ||
| 929 | (endpoint->bEndpointAddress & USB_DIR_IN) && | ||
| 930 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
| 931 | == USB_ENDPOINT_XFER_INT)) { | ||
| 932 | card->intr_in_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 933 | card->num_intr_in = 1; | ||
| 934 | |||
| 935 | if (!card->intr_in_urb) { | ||
| 936 | err("No free urbs available"); | ||
| 937 | goto error; | ||
| 938 | } | ||
| 939 | |||
| 940 | dbg("intr_in urb %d", card->num_intr_in); | ||
| 941 | } | ||
| 942 | |||
| 943 | if (!card->num_bulk_in && | ||
| 944 | (endpoint->bEndpointAddress & USB_DIR_IN) && | ||
| 945 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
| 946 | == USB_ENDPOINT_XFER_BULK)) { | ||
| 947 | card->num_bulk_in = 2; | ||
| 948 | for (j = 0; j < CPC_USB_URB_CNT; j++) { | ||
| 949 | card->urbs[j].size = endpoint->wMaxPacketSize; | ||
| 950 | card->urbs[j].urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 951 | if (!card->urbs[j].urb) { | ||
| 952 | err("No free urbs available"); | ||
| 953 | goto error; | ||
| 954 | } | ||
| 955 | card->urbs[j].buffer = | ||
| 956 | usb_buffer_alloc(udev, | ||
| 957 | card->urbs[j].size, | ||
| 958 | GFP_KERNEL, | ||
| 959 | &card->urbs[j].urb->transfer_dma); | ||
| 960 | if (!card->urbs[j].buffer) { | ||
| 961 | err("Couldn't allocate bulk_in_buffer"); | ||
| 962 | goto error; | ||
| 963 | } | ||
| 964 | } | ||
| 965 | info("%s - %d reading URB's allocated", | ||
| 966 | __func__, CPC_USB_URB_CNT); | ||
| 967 | } | ||
| 968 | |||
| 969 | if (!card->num_bulk_out && | ||
| 970 | !(endpoint->bEndpointAddress & USB_DIR_IN) && | ||
| 971 | ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
| 972 | == USB_ENDPOINT_XFER_BULK)) { | ||
| 973 | |||
| 974 | card->num_bulk_out = 2; | ||
| 975 | |||
| 976 | for (j = 0; j < CPC_USB_URB_CNT; j++) { | ||
| 977 | card->wrUrbs[j].size = | ||
| 978 | endpoint->wMaxPacketSize; | ||
| 979 | card->wrUrbs[j].urb = | ||
| 980 | usb_alloc_urb(0, GFP_KERNEL); | ||
| 981 | if (!card->wrUrbs[j].urb) { | ||
| 982 | err("No free urbs available"); | ||
| 983 | goto error; | ||
| 984 | } | ||
| 985 | card->wrUrbs[j].buffer = usb_buffer_alloc(udev, | ||
| 986 | card->wrUrbs[j].size, GFP_KERNEL, | ||
| 987 | &card->wrUrbs[j].urb->transfer_dma); | ||
| 988 | |||
| 989 | if (!card->wrUrbs[j].buffer) { | ||
| 990 | err("Couldn't allocate bulk_out_buffer"); | ||
| 991 | goto error; | ||
| 992 | } | ||
| 993 | |||
| 994 | usb_fill_bulk_urb(card->wrUrbs[j].urb, udev, | ||
| 995 | usb_sndbulkpipe(udev, endpoint->bEndpointAddress), | ||
| 996 | card->wrUrbs[j].buffer, | ||
| 997 | card->wrUrbs[j].size, | ||
| 998 | cpcusb_write_bulk_callback, | ||
| 999 | card); | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | info("%s - %d writing URB's allocated", __func__, CPC_USB_URB_CNT); | ||
| 1003 | } | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | if (!(card->num_bulk_in && card->num_bulk_out)) { | ||
| 1007 | err("Couldn't find both bulk-in and bulk-out endpoints"); | ||
| 1008 | goto error; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | /* allow device read, write and ioctl */ | ||
| 1012 | card->present = 1; | ||
| 1013 | |||
| 1014 | /* we can register the device now, as it is ready */ | ||
| 1015 | usb_set_intfdata(interface, card); | ||
| 1016 | retval = usb_register_dev(interface, &cpcusb_class); | ||
| 1017 | |||
| 1018 | if (retval) { | ||
| 1019 | /* something prevented us from registering this driver */ | ||
| 1020 | err("Not able to get a minor for this device."); | ||
| 1021 | usb_set_intfdata(interface, NULL); | ||
| 1022 | goto error; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | card->chan->minor = card->minor = interface->minor; | ||
| 1026 | |||
| 1027 | chan->buf = vmalloc(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT); | ||
| 1028 | if (chan->buf == NULL) { | ||
| 1029 | err("Out of memory"); | ||
| 1030 | retval = -ENOMEM; | ||
| 1031 | goto error; | ||
| 1032 | } | ||
| 1033 | info("Allocated memory for %d messages (%lu kbytes)", | ||
| 1034 | CPC_MSG_BUF_CNT, (long unsigned int)(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT) / 1000); | ||
| 1035 | memset(chan->buf, 0, sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT); | ||
| 1036 | |||
| 1037 | ResetBuffer(chan); | ||
| 1038 | |||
| 1039 | card->chan->CPCWait_q = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); | ||
| 1040 | if (!card->chan->CPCWait_q) { | ||
| 1041 | err("Out of memory"); | ||
| 1042 | retval = -ENOMEM; | ||
| 1043 | goto error; | ||
| 1044 | } | ||
| 1045 | init_waitqueue_head(card->chan->CPCWait_q); | ||
| 1046 | |||
| 1047 | CPCUSB_Table[slot] = card; | ||
| 1048 | card->idx = slot; | ||
| 1049 | CPCUsbCnt++; | ||
| 1050 | |||
| 1051 | /* let the user know what node this device is now attached to */ | ||
| 1052 | info("Device now attached to USB-%d", card->minor); | ||
| 1053 | return 0; | ||
| 1054 | |||
| 1055 | error: | ||
| 1056 | for (j = 0; j < CPC_USB_URB_CNT; j++) { | ||
| 1057 | if (card->urbs[j].buffer) { | ||
| 1058 | usb_buffer_free(card->udev, card->urbs[j].size, | ||
| 1059 | card->urbs[j].buffer, | ||
| 1060 | card->urbs[j].urb->transfer_dma); | ||
| 1061 | card->urbs[j].buffer = NULL; | ||
| 1062 | } | ||
| 1063 | if (card->urbs[j].urb) { | ||
| 1064 | usb_free_urb(card->urbs[j].urb); | ||
| 1065 | card->urbs[j].urb = NULL; | ||
| 1066 | } | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | cpcusb_delete(card); | ||
| 1070 | return retval; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | /* | ||
| 1074 | * called by the usb core when the device is removed from the system | ||
| 1075 | */ | ||
| 1076 | static void cpcusb_disconnect(struct usb_interface *interface) | ||
| 1077 | { | ||
| 1078 | CPC_USB_T *card = NULL; | ||
| 1079 | int minor, j; | ||
| 1080 | |||
| 1081 | /* prevent races with open() */ | ||
| 1082 | down(&disconnect_sem); | ||
| 1083 | |||
| 1084 | card = usb_get_intfdata(interface); | ||
| 1085 | usb_set_intfdata(interface, NULL); | ||
| 1086 | |||
| 1087 | down(&card->sem); | ||
| 1088 | |||
| 1089 | /* prevent device read, write and ioctl */ | ||
| 1090 | card->present = 0; | ||
| 1091 | |||
| 1092 | minor = card->minor; | ||
| 1093 | |||
| 1094 | /* free all urbs and their buffers */ | ||
| 1095 | for (j = 0; j < CPC_USB_URB_CNT; j++) { | ||
| 1096 | /* terminate an ongoing write */ | ||
| 1097 | if (atomic_read(&card->wrUrbs[j].busy)) { | ||
| 1098 | usb_kill_urb(card->wrUrbs[j].urb); | ||
| 1099 | wait_for_completion(&card->wrUrbs[j].finished); | ||
| 1100 | } | ||
| 1101 | usb_buffer_free(card->udev, card->wrUrbs[j].size, | ||
| 1102 | card->wrUrbs[j].buffer, | ||
| 1103 | card->wrUrbs[j].urb->transfer_dma); | ||
| 1104 | usb_free_urb(card->wrUrbs[j].urb); | ||
| 1105 | } | ||
| 1106 | info("%d write URBs freed", CPC_USB_URB_CNT); | ||
| 1107 | |||
| 1108 | /* free all urbs and their buffers */ | ||
| 1109 | for (j = 0; j < CPC_USB_URB_CNT; j++) { | ||
| 1110 | usb_buffer_free(card->udev, card->urbs[j].size, | ||
| 1111 | card->urbs[j].buffer, | ||
| 1112 | card->urbs[j].urb->transfer_dma); | ||
| 1113 | usb_free_urb(card->urbs[j].urb); | ||
| 1114 | } | ||
| 1115 | info("%d read URBs freed", CPC_USB_URB_CNT); | ||
| 1116 | usb_free_urb(card->intr_in_urb); | ||
| 1117 | |||
| 1118 | /* give back our minor */ | ||
| 1119 | usb_deregister_dev(interface, &cpcusb_class); | ||
| 1120 | |||
| 1121 | up(&card->sem); | ||
| 1122 | |||
| 1123 | /* if the device is opened, cpcusb_release will clean this up */ | ||
| 1124 | if (!card->open) | ||
| 1125 | cpcusb_delete(card); | ||
| 1126 | else | ||
| 1127 | wake_up_interruptible(card->chan->CPCWait_q); | ||
| 1128 | |||
| 1129 | up(&disconnect_sem); | ||
| 1130 | |||
| 1131 | CPCUsbCnt--; | ||
| 1132 | info("USB-%d now disconnected", minor); | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | static int __init CPCUsb_Init(void) | ||
| 1136 | { | ||
| 1137 | int result, i; | ||
| 1138 | |||
| 1139 | info(DRIVER_DESC " v" DRIVER_VERSION); | ||
| 1140 | info("Build on " __DATE__ " at " __TIME__); | ||
| 1141 | |||
| 1142 | for (i = 0; i < CPC_USB_CARD_CNT; i++) | ||
| 1143 | CPCUSB_Table[i] = 0; | ||
| 1144 | |||
| 1145 | /* register this driver with the USB subsystem */ | ||
| 1146 | result = usb_register(&cpcusb_driver); | ||
| 1147 | if (result) { | ||
| 1148 | err("usb_register failed. Error number %d", result); | ||
| 1149 | return result; | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | procDir = proc_mkdir(CPC_USB_PROC_DIR, NULL); | ||
| 1153 | if (!procDir) { | ||
| 1154 | err("Could not create proc entry"); | ||
| 1155 | } else { | ||
| 1156 | procEntry = create_proc_read_entry("info", 0444, procDir, | ||
| 1157 | cpcusb_proc_read_info, | ||
| 1158 | NULL); | ||
| 1159 | if (!procEntry) { | ||
| 1160 | err("Could not create proc entry %s", CPC_USB_PROC_DIR "/info"); | ||
| 1161 | remove_proc_entry(CPC_USB_PROC_DIR, NULL); | ||
| 1162 | procDir = NULL; | ||
| 1163 | } | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | return 0; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | static void __exit CPCUsb_Exit(void) | ||
| 1170 | { | ||
| 1171 | wait_event(rmmodWq, !atomic_read(&useCount)); | ||
| 1172 | |||
| 1173 | /* deregister this driver with the USB subsystem */ | ||
| 1174 | usb_deregister(&cpcusb_driver); | ||
| 1175 | |||
| 1176 | if (procDir) { | ||
| 1177 | if (procEntry) | ||
| 1178 | remove_proc_entry("info", procDir); | ||
| 1179 | remove_proc_entry(CPC_USB_PROC_DIR, NULL); | ||
| 1180 | } | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | module_init(CPCUsb_Init); | ||
| 1184 | module_exit(CPCUsb_Exit); | ||
diff --git a/drivers/staging/cpc-usb/cpc.h b/drivers/staging/cpc-usb/cpc.h deleted file mode 100644 index b2fda5d14c1d..000000000000 --- a/drivers/staging/cpc-usb/cpc.h +++ /dev/null | |||
| @@ -1,417 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * CPC CAN Interface Definitions | ||
| 3 | * | ||
| 4 | * Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, but | ||
| 7 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | */ | ||
| 10 | #ifndef CPC_HEADER | ||
| 11 | #define CPC_HEADER | ||
| 12 | |||
| 13 | /* | ||
| 14 | * the maximum length of the union members within a CPC_MSG | ||
| 15 | * this value can be defined by the customer, but has to be | ||
| 16 | * >= 64 bytes | ||
| 17 | * however, if not defined before, we set a length of 64 byte | ||
| 18 | */ | ||
| 19 | #if !defined(CPC_MSG_LEN) || (CPC_MSG_LEN < 64) | ||
| 20 | #undef CPC_MSG_LEN | ||
| 21 | #define CPC_MSG_LEN 64 | ||
| 22 | #endif | ||
| 23 | |||
| 24 | /* | ||
| 25 | * Transmission of events from CPC interfaces to PC can be individually | ||
| 26 | * controlled per event type. Default state is: don't transmit | ||
| 27 | * Control values are constructed by bit-or of Subject and Action | ||
| 28 | * and passed to CPC_Control() | ||
| 29 | */ | ||
| 30 | |||
| 31 | /* Control-Values for CPC_Control() Command Subject Selection */ | ||
| 32 | #define CONTR_CAN_Message 0x04 | ||
| 33 | #define CONTR_Busload 0x08 | ||
| 34 | #define CONTR_CAN_State 0x0C | ||
| 35 | #define CONTR_SendAck 0x10 | ||
| 36 | #define CONTR_Filter 0x14 | ||
| 37 | #define CONTR_CmdQueue 0x18 /* reserved, do not use */ | ||
| 38 | #define CONTR_BusError 0x1C | ||
| 39 | |||
| 40 | /* Control Command Actions */ | ||
| 41 | #define CONTR_CONT_OFF 0 | ||
| 42 | #define CONTR_CONT_ON 1 | ||
| 43 | #define CONTR_SING_ON 2 | ||
| 44 | /* | ||
| 45 | * CONTR_SING_ON doesn't change CONTR_CONT_ON state, so it should be | ||
| 46 | * read as: transmit at least once | ||
| 47 | */ | ||
| 48 | |||
| 49 | /* defines for confirmed request */ | ||
| 50 | #define DO_NOT_CONFIRM 0 | ||
| 51 | #define DO_CONFIRM 1 | ||
| 52 | |||
| 53 | /* event flags */ | ||
| 54 | #define EVENT_READ 0x01 | ||
| 55 | #define EVENT_WRITE 0x02 | ||
| 56 | |||
| 57 | /* | ||
| 58 | * Messages from CPC to PC contain a message object type field. | ||
| 59 | * The following message types are sent by CPC and can be used in | ||
| 60 | * handlers, others should be ignored. | ||
| 61 | */ | ||
| 62 | #define CPC_MSG_T_RESYNC 0 /* Normally to be ignored */ | ||
| 63 | #define CPC_MSG_T_CAN 1 /* CAN data frame */ | ||
| 64 | #define CPC_MSG_T_BUSLOAD 2 /* Busload message */ | ||
| 65 | #define CPC_MSG_T_STRING 3 /* Normally to be ignored */ | ||
| 66 | #define CPC_MSG_T_CONTI 4 /* Normally to be ignored */ | ||
| 67 | #define CPC_MSG_T_MEM 7 /* Normally not to be handled */ | ||
| 68 | #define CPC_MSG_T_RTR 8 /* CAN remote frame */ | ||
| 69 | #define CPC_MSG_T_TXACK 9 /* Send acknowledge */ | ||
| 70 | #define CPC_MSG_T_POWERUP 10 /* Power-up message */ | ||
| 71 | #define CPC_MSG_T_CMD_NO 11 /* Normally to be ignored */ | ||
| 72 | #define CPC_MSG_T_CAN_PRMS 12 /* Actual CAN parameters */ | ||
| 73 | #define CPC_MSG_T_ABORTED 13 /* Command aborted message */ | ||
| 74 | #define CPC_MSG_T_CANSTATE 14 /* CAN state message */ | ||
| 75 | #define CPC_MSG_T_RESET 15 /* used to reset CAN-Controller */ | ||
| 76 | #define CPC_MSG_T_XCAN 16 /* XCAN data frame */ | ||
| 77 | #define CPC_MSG_T_XRTR 17 /* XCAN remote frame */ | ||
| 78 | #define CPC_MSG_T_INFO 18 /* information strings */ | ||
| 79 | #define CPC_MSG_T_CONTROL 19 /* used for control of interface/driver behaviour */ | ||
| 80 | #define CPC_MSG_T_CONFIRM 20 /* response type for confirmed requests */ | ||
| 81 | #define CPC_MSG_T_OVERRUN 21 /* response type for overrun conditions */ | ||
| 82 | #define CPC_MSG_T_KEEPALIVE 22 /* response type for keep alive conditions */ | ||
| 83 | #define CPC_MSG_T_CANERROR 23 /* response type for bus error conditions */ | ||
| 84 | #define CPC_MSG_T_DISCONNECTED 24 /* response type for a disconnected interface */ | ||
| 85 | #define CPC_MSG_T_ERR_COUNTER 25 /* RX/TX error counter of CAN controller */ | ||
| 86 | |||
| 87 | #define CPC_MSG_T_FIRMWARE 100 /* response type for USB firmware download */ | ||
| 88 | |||
| 89 | /* | ||
| 90 | * Messages from the PC to the CPC interface contain a command field | ||
| 91 | * Most of the command types are wrapped by the library functions and have therefore | ||
| 92 | * normally not to be used. | ||
| 93 | * However, programmers who wish to circumvent the library and talk directly | ||
| 94 | * to the drivers (mainly Linux programmers) can use the following | ||
| 95 | * command types: | ||
| 96 | */ | ||
| 97 | #define CPC_CMD_T_CAN 1 /* CAN data frame */ | ||
| 98 | #define CPC_CMD_T_CONTROL 3 /* used for control of interface/driver behaviour */ | ||
| 99 | #define CPC_CMD_T_CAN_PRMS 6 /* set CAN parameters */ | ||
| 100 | #define CPC_CMD_T_CLEARBUF 8 /* clears input queue; this is depricated, use CPC_CMD_T_CLEAR_MSG_QUEUE instead */ | ||
| 101 | #define CPC_CMD_T_INQ_CAN_PARMS 11 /* inquire actual CAN parameters */ | ||
| 102 | #define CPC_CMD_T_FILTER_PRMS 12 /* set filter parameter */ | ||
| 103 | #define CPC_CMD_T_RTR 13 /* CAN remote frame */ | ||
| 104 | #define CPC_CMD_T_CANSTATE 14 /* CAN state message */ | ||
| 105 | #define CPC_CMD_T_XCAN 15 /* XCAN data frame */ | ||
| 106 | #define CPC_CMD_T_XRTR 16 /* XCAN remote frame */ | ||
| 107 | #define CPC_CMD_T_RESET 17 /* used to reset CAN-Controller */ | ||
| 108 | #define CPC_CMD_T_INQ_INFO 18 /* miscellanous information strings */ | ||
| 109 | #define CPC_CMD_T_OPEN_CHAN 19 /* open a channel */ | ||
| 110 | #define CPC_CMD_T_CLOSE_CHAN 20 /* close a channel */ | ||
| 111 | #define CPC_CMD_T_CNTBUF 21 /* this is depricated, use CPC_CMD_T_INQ_MSG_QUEUE_CNT instead */ | ||
| 112 | #define CPC_CMD_T_CAN_EXIT 200 /* exit the CAN (disable interrupts; reset bootrate; reset output_cntr; mode = 1) */ | ||
| 113 | |||
| 114 | #define CPC_CMD_T_INQ_MSG_QUEUE_CNT CPC_CMD_T_CNTBUF /* inquires the count of elements in the message queue */ | ||
| 115 | #define CPC_CMD_T_INQ_ERR_COUNTER 25 /* request the CAN controllers error counter */ | ||
| 116 | #define CPC_CMD_T_CLEAR_MSG_QUEUE CPC_CMD_T_CLEARBUF /* clear CPC_MSG queue */ | ||
| 117 | #define CPC_CMD_T_CLEAR_CMD_QUEUE 28 /* clear CPC_CMD queue */ | ||
| 118 | #define CPC_CMD_T_FIRMWARE 100 /* reserved, must not be used */ | ||
| 119 | #define CPC_CMD_T_USB_RESET 101 /* reserved, must not be used */ | ||
| 120 | #define CPC_CMD_T_WAIT_NOTIFY 102 /* reserved, must not be used */ | ||
| 121 | #define CPC_CMD_T_WAIT_SETUP 103 /* reserved, must not be used */ | ||
| 122 | #define CPC_CMD_T_ABORT 255 /* Normally not to be used */ | ||
| 123 | |||
| 124 | /* definitions for CPC_MSG_T_INFO information sources */ | ||
| 125 | #define CPC_INFOMSG_T_UNKNOWN_SOURCE 0 | ||
| 126 | #define CPC_INFOMSG_T_INTERFACE 1 | ||
| 127 | #define CPC_INFOMSG_T_DRIVER 2 | ||
| 128 | #define CPC_INFOMSG_T_LIBRARY 3 | ||
| 129 | |||
| 130 | /* information types */ | ||
| 131 | #define CPC_INFOMSG_T_UNKNOWN_TYPE 0 | ||
| 132 | #define CPC_INFOMSG_T_VERSION 1 | ||
| 133 | #define CPC_INFOMSG_T_SERIAL 2 | ||
| 134 | |||
| 135 | /* definitions for controller types */ | ||
| 136 | #define PCA82C200 1 /* Philips basic CAN controller, replaced by SJA1000 */ | ||
| 137 | #define SJA1000 2 /* Philips basic CAN controller */ | ||
| 138 | #define AN82527 3 /* Intel full CAN controller */ | ||
| 139 | #define M16C_BASIC 4 /* M16C controller running in basic CAN (not full CAN) mode */ | ||
| 140 | |||
| 141 | /* channel open error codes */ | ||
| 142 | #define CPC_ERR_NO_FREE_CHANNEL -1 /* no more free space within the channel array */ | ||
| 143 | #define CPC_ERR_CHANNEL_ALREADY_OPEN -2 /* the channel is already open */ | ||
| 144 | #define CPC_ERR_CHANNEL_NOT_ACTIVE -3 /* access to a channel not active failed */ | ||
| 145 | #define CPC_ERR_NO_DRIVER_PRESENT -4 /* no driver at the location searched by the library */ | ||
| 146 | #define CPC_ERR_NO_INIFILE_PRESENT -5 /* the library could not find the inifile */ | ||
| 147 | #define CPC_ERR_WRONG_PARAMETERS -6 /* wrong parameters in the inifile */ | ||
| 148 | #define CPC_ERR_NO_INTERFACE_PRESENT -7 /* 1. The specified interface is not connected */ | ||
| 149 | /* 2. The interface (mostly CPC-USB) was disconnected upon operation */ | ||
| 150 | #define CPC_ERR_NO_MATCHING_CHANNEL -8 /* the driver couldn't find a matching channel */ | ||
| 151 | #define CPC_ERR_NO_BUFFER_AVAILABLE -9 /* the driver couldn't allocate buffer for messages */ | ||
| 152 | #define CPC_ERR_NO_INTERRUPT -10 /* the requested interrupt couldn't be claimed */ | ||
| 153 | #define CPC_ERR_NO_MATCHING_INTERFACE -11 /* no interface type related to this channel was found */ | ||
| 154 | #define CPC_ERR_NO_RESOURCES -12 /* the requested resources could not be claimed */ | ||
| 155 | #define CPC_ERR_SOCKET -13 /* error concerning TCP sockets */ | ||
| 156 | |||
| 157 | /* init error codes */ | ||
| 158 | #define CPC_ERR_WRONG_CONTROLLER_TYPE -14 /* wrong CAN controller type within initialization */ | ||
| 159 | #define CPC_ERR_NO_RESET_MODE -15 /* the controller could not be set into reset mode */ | ||
| 160 | #define CPC_ERR_NO_CAN_ACCESS -16 /* the CAN controller could not be accessed */ | ||
| 161 | |||
| 162 | /* transmit error codes */ | ||
| 163 | #define CPC_ERR_CAN_WRONG_ID -20 /* the provided CAN id is too big */ | ||
| 164 | #define CPC_ERR_CAN_WRONG_LENGTH -21 /* the provided CAN length is too long */ | ||
| 165 | #define CPC_ERR_CAN_NO_TRANSMIT_BUF -22 /* the transmit buffer was occupied */ | ||
| 166 | #define CPC_ERR_CAN_TRANSMIT_TIMEOUT -23 /* The message could not be sent within a */ | ||
| 167 | /* specified time */ | ||
| 168 | |||
| 169 | /* other error codes */ | ||
| 170 | #define CPC_ERR_SERVICE_NOT_SUPPORTED -30 /* the requested service is not supported by the interface */ | ||
| 171 | #define CPC_ERR_IO_TRANSFER -31 /* a transmission error down to the driver occurred */ | ||
| 172 | #define CPC_ERR_TRANSMISSION_FAILED -32 /* a transmission error down to the interface occurred */ | ||
| 173 | #define CPC_ERR_TRANSMISSION_TIMEOUT -33 /* a timeout occurred within transmission to the interface */ | ||
| 174 | #define CPC_ERR_OP_SYS_NOT_SUPPORTED -35 /* the operating system is not supported */ | ||
| 175 | #define CPC_ERR_UNKNOWN -40 /* an unknown error ocurred (mostly IOCTL errors) */ | ||
| 176 | |||
| 177 | #define CPC_ERR_LOADING_DLL -50 /* the library 'cpcwin.dll' could not be loaded */ | ||
| 178 | #define CPC_ERR_ASSIGNING_FUNCTION -51 /* the specified function could not be assigned */ | ||
| 179 | #define CPC_ERR_DLL_INITIALIZATION -52 /* the DLL was not initialized correctly */ | ||
| 180 | #define CPC_ERR_MISSING_LICFILE -55 /* the file containing the licenses does not exist */ | ||
| 181 | #define CPC_ERR_MISSING_LICENSE -56 /* a required license was not found */ | ||
| 182 | |||
| 183 | /* CAN state bit values. Ignore any bits not listed */ | ||
| 184 | #define CPC_CAN_STATE_BUSOFF 0x80 | ||
| 185 | #define CPC_CAN_STATE_ERROR 0x40 | ||
| 186 | |||
| 187 | /* Mask to help ignore undefined bits */ | ||
| 188 | #define CPC_CAN_STATE_MASK 0xc0 | ||
| 189 | |||
| 190 | /* | ||
| 191 | * CAN-Message representation in a CPC_MS | ||
| 192 | * Message object type is CPC_MSG_T_CAN or CPC_MSG_T_RTR | ||
| 193 | * or CPC_MSG_T_XCAN or CPC_MSG_T_XRTR | ||
| 194 | */ | ||
| 195 | typedef struct CPC_CAN_MSG { | ||
| 196 | u32 id; | ||
| 197 | u8 length; | ||
| 198 | u8 msg[8]; | ||
| 199 | } CPC_CAN_MSG_T; | ||
| 200 | |||
| 201 | /* representation of the CAN parameters for the PCA82C200 controller */ | ||
| 202 | typedef struct CPC_PCA82C200_PARAMS { | ||
| 203 | u8 acc_code; /* Acceptance-code for receive, Standard: 0 */ | ||
| 204 | u8 acc_mask; /* Acceptance-mask for receive, Standard: 0xff (everything) */ | ||
| 205 | u8 btr0; /* Bus-timing register 0 */ | ||
| 206 | u8 btr1; /* Bus-timing register 1 */ | ||
| 207 | u8 outp_contr; /* Output-control register */ | ||
| 208 | } CPC_PCA82C200_PARAMS_T; | ||
| 209 | |||
| 210 | /* representation of the CAN parameters for the SJA1000 controller */ | ||
| 211 | typedef struct CPC_SJA1000_PARAMS { | ||
| 212 | u8 mode; /* enables single or dual acceptance filtering */ | ||
| 213 | u8 acc_code0; /* Acceptance-code for receive, Standard: 0 */ | ||
| 214 | u8 acc_code1; | ||
| 215 | u8 acc_code2; | ||
| 216 | u8 acc_code3; | ||
| 217 | u8 acc_mask0; /* Acceptance-mask for receive, Standard: 0xff (everything) */ | ||
| 218 | u8 acc_mask1; | ||
| 219 | u8 acc_mask2; | ||
| 220 | u8 acc_mask3; | ||
| 221 | u8 btr0; /* Bus-timing register 0 */ | ||
| 222 | u8 btr1; /* Bus-timing register 1 */ | ||
| 223 | u8 outp_contr; /* Output-control register */ | ||
| 224 | } CPC_SJA1000_PARAMS_T; | ||
| 225 | |||
| 226 | /* | ||
| 227 | * representation of the CAN parameters for the M16C controller | ||
| 228 | * in basic CAN mode (means no full CAN) | ||
| 229 | */ | ||
| 230 | typedef struct CPC_M16C_BASIC_PARAMS { | ||
| 231 | u8 con0; | ||
| 232 | u8 con1; | ||
| 233 | u8 ctlr0; | ||
| 234 | u8 ctlr1; | ||
| 235 | u8 clk; | ||
| 236 | u8 acc_std_code0; | ||
| 237 | u8 acc_std_code1; | ||
| 238 | u8 acc_ext_code0; | ||
| 239 | u8 acc_ext_code1; | ||
| 240 | u8 acc_ext_code2; | ||
| 241 | u8 acc_ext_code3; | ||
| 242 | u8 acc_std_mask0; | ||
| 243 | u8 acc_std_mask1; | ||
| 244 | u8 acc_ext_mask0; | ||
| 245 | u8 acc_ext_mask1; | ||
| 246 | u8 acc_ext_mask2; | ||
| 247 | u8 acc_ext_mask3; | ||
| 248 | } CPC_M16C_BASIC_PARAMS_T; | ||
| 249 | |||
| 250 | /* CAN params message representation */ | ||
| 251 | typedef struct CPC_CAN_PARAMS { | ||
| 252 | u8 cc_type; /* represents the controller type */ | ||
| 253 | union { | ||
| 254 | CPC_M16C_BASIC_PARAMS_T m16c_basic; | ||
| 255 | CPC_SJA1000_PARAMS_T sja1000; | ||
| 256 | CPC_PCA82C200_PARAMS_T pca82c200; | ||
| 257 | } cc_params; | ||
| 258 | } CPC_CAN_PARAMS_T; | ||
| 259 | |||
| 260 | /* CHAN init params representation */ | ||
| 261 | typedef struct CPC_CHAN_PARAMS { | ||
| 262 | int fd; | ||
| 263 | } CPC_CHAN_PARAMS_T; | ||
| 264 | |||
| 265 | /* CAN init params message representation */ | ||
| 266 | typedef struct CPC_INIT_PARAMS { | ||
| 267 | CPC_CHAN_PARAMS_T chanparams; | ||
| 268 | CPC_CAN_PARAMS_T canparams; | ||
| 269 | } CPC_INIT_PARAMS_T; | ||
| 270 | |||
| 271 | /* structure for confirmed message handling */ | ||
| 272 | typedef struct CPC_CONFIRM { | ||
| 273 | u8 result; /* error code */ | ||
| 274 | } CPC_CONFIRM_T; | ||
| 275 | |||
| 276 | /* structure for information requests */ | ||
| 277 | typedef struct CPC_INFO { | ||
| 278 | u8 source; /* interface, driver or library */ | ||
| 279 | u8 type; /* version or serial number */ | ||
| 280 | char msg[CPC_MSG_LEN - 2]; /* string holding the requested information */ | ||
| 281 | } CPC_INFO_T; | ||
| 282 | |||
| 283 | /* | ||
| 284 | * OVERRUN | ||
| 285 | * In general two types of overrun may occur. | ||
| 286 | * A hardware overrun, where the CAN controller | ||
| 287 | * lost a message, because the interrupt was | ||
| 288 | * not handled before the next messgae comes in. | ||
| 289 | * Or a software overrun, where i.e. a received | ||
| 290 | * message could not be stored in the CPC_MSG | ||
| 291 | * buffer. | ||
| 292 | */ | ||
| 293 | |||
| 294 | /* After a software overrun has occurred | ||
| 295 | * we wait until we have CPC_OVR_GAP slots | ||
| 296 | * free in the CPC_MSG buffer. | ||
| 297 | */ | ||
| 298 | #define CPC_OVR_GAP 10 | ||
| 299 | |||
| 300 | /* | ||
| 301 | * Two types of software overrun may occur. | ||
| 302 | * A received CAN message or a CAN state event | ||
| 303 | * can cause an overrun. | ||
| 304 | * Note: A CPC_CMD which would normally store | ||
| 305 | * its result immediately in the CPC_MSG | ||
| 306 | * queue may fail, because the message queue is full. | ||
| 307 | * This will not generate an overrun message, but | ||
| 308 | * will halt command execution, until this command | ||
| 309 | * is able to store its message in the message queue. | ||
| 310 | */ | ||
| 311 | #define CPC_OVR_EVENT_CAN 0x01 | ||
| 312 | #define CPC_OVR_EVENT_CANSTATE 0x02 | ||
| 313 | #define CPC_OVR_EVENT_BUSERROR 0x04 | ||
| 314 | |||
| 315 | /* | ||
| 316 | * If the CAN controller lost a message | ||
| 317 | * we indicate it with the highest bit | ||
| 318 | * set in the count field. | ||
| 319 | */ | ||
| 320 | #define CPC_OVR_HW 0x80 | ||
| 321 | |||
| 322 | /* structure for overrun conditions */ | ||
| 323 | typedef struct { | ||
| 324 | u8 event; | ||
| 325 | u8 count; | ||
| 326 | } CPC_OVERRUN_T; | ||
| 327 | |||
| 328 | /* | ||
| 329 | * CAN errors | ||
| 330 | * Each CAN controller type has different | ||
| 331 | * registers to record errors. | ||
| 332 | * Therefor a structure containing the specific | ||
| 333 | * errors is set up for each controller here | ||
| 334 | */ | ||
| 335 | |||
| 336 | /* | ||
| 337 | * SJA1000 error structure | ||
| 338 | * see the SJA1000 datasheet for detailed | ||
| 339 | * explanation of the registers | ||
| 340 | */ | ||
| 341 | typedef struct CPC_SJA1000_CAN_ERROR { | ||
| 342 | u8 ecc; /* error capture code register */ | ||
| 343 | u8 rxerr; /* RX error counter register */ | ||
| 344 | u8 txerr; /* TX error counter register */ | ||
| 345 | } CPC_SJA1000_CAN_ERROR_T; | ||
| 346 | |||
| 347 | /* | ||
| 348 | * M16C error structure | ||
| 349 | * see the M16C datasheet for detailed | ||
| 350 | * explanation of the registers | ||
| 351 | */ | ||
| 352 | typedef struct CPC_M16C_CAN_ERROR { | ||
| 353 | u8 tbd; /* to be defined */ | ||
| 354 | } CPC_M16C_CAN_ERROR_T; | ||
| 355 | |||
| 356 | /* structure for CAN error conditions */ | ||
| 357 | #define CPC_CAN_ECODE_ERRFRAME 0x01 | ||
| 358 | typedef struct CPC_CAN_ERROR { | ||
| 359 | u8 ecode; | ||
| 360 | struct { | ||
| 361 | u8 cc_type; /* CAN controller type */ | ||
| 362 | union { | ||
| 363 | CPC_SJA1000_CAN_ERROR_T sja1000; | ||
| 364 | CPC_M16C_CAN_ERROR_T m16c; | ||
| 365 | } regs; | ||
| 366 | } cc; | ||
| 367 | } CPC_CAN_ERROR_T; | ||
| 368 | |||
| 369 | /* | ||
| 370 | * Structure containing RX/TX error counter. | ||
| 371 | * This structure is used to request the | ||
| 372 | * values of the CAN controllers TX and RX | ||
| 373 | * error counter. | ||
| 374 | */ | ||
| 375 | typedef struct CPC_CAN_ERR_COUNTER { | ||
| 376 | u8 rx; | ||
| 377 | u8 tx; | ||
| 378 | } CPC_CAN_ERR_COUNTER_T; | ||
| 379 | |||
| 380 | /* If this flag is set, transmissions from PC to CPC are protected against loss */ | ||
| 381 | #define CPC_SECURE_TO_CPC 0x01 | ||
| 382 | |||
| 383 | /* If this flag is set, transmissions from CPC to PC are protected against loss */ | ||
| 384 | #define CPC_SECURE_TO_PC 0x02 | ||
| 385 | |||
| 386 | /* If this flag is set, the CAN-transmit buffer is checked to be free before sending a message */ | ||
| 387 | #define CPC_SECURE_SEND 0x04 | ||
| 388 | |||
| 389 | /* | ||
| 390 | * If this flag is set, the transmission complete flag is checked | ||
| 391 | * after sending a message | ||
| 392 | * THIS IS CURRENTLY ONLY IMPLEMENTED IN THE PASSIVE INTERFACE DRIVERS | ||
| 393 | */ | ||
| 394 | #define CPC_SECURE_TRANSMIT 0x08 | ||
| 395 | |||
| 396 | /* main message type used between library and application */ | ||
| 397 | typedef struct CPC_MSG { | ||
| 398 | u8 type; /* type of message */ | ||
| 399 | u8 length; /* length of data within union 'msg' */ | ||
| 400 | u8 msgid; /* confirmation handle */ | ||
| 401 | u32 ts_sec; /* timestamp in seconds */ | ||
| 402 | u32 ts_nsec; /* timestamp in nano seconds */ | ||
| 403 | union { | ||
| 404 | u8 generic[CPC_MSG_LEN]; | ||
| 405 | CPC_CAN_MSG_T canmsg; | ||
| 406 | CPC_CAN_PARAMS_T canparams; | ||
| 407 | CPC_CONFIRM_T confirmation; | ||
| 408 | CPC_INFO_T info; | ||
| 409 | CPC_OVERRUN_T overrun; | ||
| 410 | CPC_CAN_ERROR_T error; | ||
| 411 | CPC_CAN_ERR_COUNTER_T err_counter; | ||
| 412 | u8 busload; | ||
| 413 | u8 canstate; | ||
| 414 | } msg; | ||
| 415 | } CPC_MSG_T; | ||
| 416 | |||
| 417 | #endif /* CPC_HEADER */ | ||
diff --git a/drivers/staging/cpc-usb/cpc_int.h b/drivers/staging/cpc-usb/cpc_int.h deleted file mode 100644 index 38674e9690a0..000000000000 --- a/drivers/staging/cpc-usb/cpc_int.h +++ /dev/null | |||
| @@ -1,83 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * CPCLIB | ||
| 3 | * | ||
| 4 | * Copyright (C) 2000-2008 EMS Dr. Thomas Wuensche | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, but | ||
| 7 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | #ifndef CPC_INT_H | ||
| 12 | #define CPC_INT_H | ||
| 13 | |||
| 14 | #include <linux/wait.h> | ||
| 15 | |||
| 16 | #define CPC_MSG_BUF_CNT 1500 | ||
| 17 | |||
| 18 | #define CPC_PROC_DIR "driver/" | ||
| 19 | |||
| 20 | #undef dbg | ||
| 21 | #undef err | ||
| 22 | #undef info | ||
| 23 | |||
| 24 | /* Use our own dbg macro */ | ||
| 25 | #define dbg(format, arg...) do { if (debug) printk( KERN_INFO format "\n" , ## arg); } while (0) | ||
| 26 | #define err(format, arg...) do { printk( KERN_INFO "ERROR " format "\n" , ## arg); } while (0) | ||
| 27 | #define info(format, arg...) do { printk( KERN_INFO format "\n" , ## arg); } while (0) | ||
| 28 | |||
| 29 | /* Macros help using of our buffers */ | ||
| 30 | #define IsBufferFull(x) (!(x)->WnR) && ((x)->iidx == (x)->oidx) | ||
| 31 | #define IsBufferEmpty(x) ((x)->WnR) && ((x)->iidx == (x)->oidx) | ||
| 32 | #define IsBufferNotEmpty(x) (!(x)->WnR) || ((x)->iidx != (x)->oidx) | ||
| 33 | #define ResetBuffer(x) do { (x)->oidx = (x)->iidx=0; (x)->WnR = 1; } while(0); | ||
| 34 | |||
| 35 | #define CPC_BufWriteAllowed ((chan->oidx != chan->iidx) || chan->WnR) | ||
| 36 | |||
| 37 | typedef void (*chan_write_byte_t) (void *chan, unsigned int reg, | ||
| 38 | unsigned char val); | ||
| 39 | typedef unsigned char (*chan_read_byte_t) (void *chan, unsigned int reg); | ||
| 40 | |||
| 41 | typedef struct CPC_CHAN { | ||
| 42 | void __iomem * canBase; /* base address of SJA1000 */ | ||
| 43 | chan_read_byte_t read_byte; /* CAN controller read access routine */ | ||
| 44 | chan_write_byte_t write_byte; /* CAN controller write access routine */ | ||
| 45 | CPC_MSG_T *buf; /* buffer for CPC msg */ | ||
| 46 | unsigned int iidx; | ||
| 47 | unsigned int oidx; | ||
| 48 | unsigned int WnR; | ||
| 49 | unsigned int minor; | ||
| 50 | unsigned int locked; | ||
| 51 | unsigned int irqDisabled; | ||
| 52 | |||
| 53 | unsigned char cpcCtrlCANMessage; | ||
| 54 | unsigned char cpcCtrlCANState; | ||
| 55 | unsigned char cpcCtrlBUSState; | ||
| 56 | |||
| 57 | unsigned char controllerType; | ||
| 58 | |||
| 59 | unsigned long ovrTimeSec; | ||
| 60 | unsigned long ovrTimeNSec; | ||
| 61 | unsigned long ovrLockedBuffer; | ||
| 62 | CPC_OVERRUN_T ovr; | ||
| 63 | |||
| 64 | /* for debugging only */ | ||
| 65 | unsigned int handledIrqs; | ||
| 66 | unsigned int lostMessages; | ||
| 67 | |||
| 68 | unsigned int sentStdCan; | ||
| 69 | unsigned int sentExtCan; | ||
| 70 | unsigned int sentStdRtr; | ||
| 71 | unsigned int sentExtRtr; | ||
| 72 | |||
| 73 | unsigned int recvStdCan; | ||
| 74 | unsigned int recvExtCan; | ||
| 75 | unsigned int recvStdRtr; | ||
| 76 | unsigned int recvExtRtr; | ||
| 77 | |||
| 78 | wait_queue_head_t *CPCWait_q; | ||
| 79 | |||
| 80 | void *private; | ||
| 81 | } CPC_CHAN_T; | ||
| 82 | |||
| 83 | #endif | ||
diff --git a/drivers/staging/cpc-usb/cpcusb.h b/drivers/staging/cpc-usb/cpcusb.h deleted file mode 100644 index 6bdf30be239f..000000000000 --- a/drivers/staging/cpc-usb/cpcusb.h +++ /dev/null | |||
| @@ -1,86 +0,0 @@ | |||
| 1 | /* Header for CPC-USB Driver ******************** | ||
| 2 | * Copyright 1999, 2000, 2001 | ||
| 3 | * | ||
| 4 | * Company: EMS Dr. Thomas Wuensche | ||
| 5 | * Sonnenhang 3 | ||
| 6 | * 85304 Ilmmuenster | ||
| 7 | * Phone: +49-8441-490260 | ||
| 8 | * Fax: +49-8441-81860 | ||
| 9 | * email: support@ems-wuensche.com | ||
| 10 | * WWW: www.ems-wuensche.com | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef CPCUSB_H | ||
| 14 | #define CPCUSB_H | ||
| 15 | |||
| 16 | #undef err | ||
| 17 | #undef dbg | ||
| 18 | #undef info | ||
| 19 | |||
| 20 | /* Use our own dbg macro */ | ||
| 21 | #define dbg(format, arg...) do { if (debug) printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0) | ||
| 22 | #define info(format, arg...) do { printk(KERN_INFO "CPC-USB: " format "\n" , ## arg); } while (0) | ||
| 23 | #define err(format, arg...) do { printk(KERN_INFO "CPC-USB(ERROR): " format "\n" , ## arg); } while (0) | ||
| 24 | |||
| 25 | #define CPC_USB_CARD_CNT 4 | ||
| 26 | |||
| 27 | typedef struct CPC_USB_READ_URB { | ||
| 28 | unsigned char *buffer; /* the buffer to send data */ | ||
| 29 | size_t size; /* the size of the send buffer */ | ||
| 30 | struct urb *urb; /* the urb used to send data */ | ||
| 31 | } CPC_USB_READ_URB_T; | ||
| 32 | |||
| 33 | typedef struct CPC_USB_WRITE_URB { | ||
| 34 | unsigned char *buffer; /* the buffer to send data */ | ||
| 35 | size_t size; /* the size of the send buffer */ | ||
| 36 | struct urb *urb; /* the urb used to send data */ | ||
| 37 | atomic_t busy; /* true if write urb is busy */ | ||
| 38 | struct completion finished; /* wait for the write to finish */ | ||
| 39 | } CPC_USB_WRITE_URB_T; | ||
| 40 | |||
| 41 | #define CPC_USB_URB_CNT 10 | ||
| 42 | |||
| 43 | typedef struct CPC_USB { | ||
| 44 | struct usb_device *udev; /* save off the usb device pointer */ | ||
| 45 | struct usb_interface *interface; /* the interface for this device */ | ||
| 46 | unsigned char minor; /* the starting minor number for this device */ | ||
| 47 | unsigned char num_ports; /* the number of ports this device has */ | ||
| 48 | int num_intr_in; /* number of interrupt in endpoints we have */ | ||
| 49 | int num_bulk_in; /* number of bulk in endpoints we have */ | ||
| 50 | int num_bulk_out; /* number of bulk out endpoints we have */ | ||
| 51 | |||
| 52 | CPC_USB_READ_URB_T urbs[CPC_USB_URB_CNT]; | ||
| 53 | |||
| 54 | unsigned char intr_in_buffer[4]; /* interrupt transfer buffer */ | ||
| 55 | struct urb *intr_in_urb; /* interrupt transfer urb */ | ||
| 56 | |||
| 57 | CPC_USB_WRITE_URB_T wrUrbs[CPC_USB_URB_CNT]; | ||
| 58 | |||
| 59 | int open; /* if the port is open or not */ | ||
| 60 | int present; /* if the device is not disconnected */ | ||
| 61 | struct semaphore sem; /* locks this structure */ | ||
| 62 | |||
| 63 | int free_slots; /* free send slots of CPC-USB */ | ||
| 64 | int idx; | ||
| 65 | |||
| 66 | spinlock_t slock; | ||
| 67 | |||
| 68 | char serialNumber[128]; /* serial number */ | ||
| 69 | int productId; /* product id to differ between M16C and LPC2119 */ | ||
| 70 | CPC_CHAN_T *chan; | ||
| 71 | } CPC_USB_T; | ||
| 72 | |||
| 73 | #define CPCTable CPCUSB_Table | ||
| 74 | |||
| 75 | #define CPC_DRIVER_VERSION "0.724" | ||
| 76 | #define CPC_DRIVER_SERIAL "not applicable" | ||
| 77 | |||
| 78 | #define OBUF_SIZE 255 /* 4096 */ | ||
| 79 | |||
| 80 | /* read timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */ | ||
| 81 | #define RD_NAK_TIMEOUT (10*HZ) /* Default number of X seconds to wait */ | ||
| 82 | #define RD_EXPIRE 12 /* Number of attempts to wait X seconds */ | ||
| 83 | |||
| 84 | #define CPC_USB_BASE_MNR 0 /* CPC-USB start at minor 0 */ | ||
| 85 | |||
| 86 | #endif | ||
diff --git a/drivers/staging/cpc-usb/sja2m16c.h b/drivers/staging/cpc-usb/sja2m16c.h deleted file mode 100644 index 654bd3fc91dc..000000000000 --- a/drivers/staging/cpc-usb/sja2m16c.h +++ /dev/null | |||
| @@ -1,41 +0,0 @@ | |||
| 1 | #ifndef _SJA2M16C_H | ||
| 2 | #define _SJA2M16C_H | ||
| 3 | |||
| 4 | #include "cpc.h" | ||
| 5 | |||
| 6 | #define BAUDRATE_TOLERANCE_PERCENT 1 | ||
| 7 | #define SAMPLEPOINT_TOLERANCE_PERCENT 5 | ||
| 8 | #define SAMPLEPOINT_UPPER_LIMIT 88 | ||
| 9 | |||
| 10 | /* M16C parameters */ | ||
| 11 | struct FIELD_C0CONR { | ||
| 12 | unsigned int brp:4; | ||
| 13 | unsigned int sam:1; | ||
| 14 | unsigned int pr:3; | ||
| 15 | unsigned int dummy:8; | ||
| 16 | }; | ||
| 17 | struct FIELD_C1CONR { | ||
| 18 | unsigned int ph1:3; | ||
| 19 | unsigned int ph2:3; | ||
| 20 | unsigned int sjw:2; | ||
| 21 | unsigned int dummy:8; | ||
| 22 | }; | ||
| 23 | typedef union C0CONR { | ||
| 24 | unsigned char c0con; | ||
| 25 | struct FIELD_C0CONR bc0con; | ||
| 26 | } C0CONR_T; | ||
| 27 | typedef union C1CONR { | ||
| 28 | unsigned char c1con; | ||
| 29 | struct FIELD_C1CONR bc1con; | ||
| 30 | } C1CONR_T; | ||
| 31 | |||
| 32 | #define SJA_TSEG1 ((pParams->btr1 & 0x0f)+1) | ||
| 33 | #define SJA_TSEG2 (((pParams->btr1 & 0x70)>>4)+1) | ||
| 34 | #define SJA_BRP ((pParams->btr0 & 0x3f)+1) | ||
| 35 | #define SJA_SJW ((pParams->btr0 & 0xc0)>>6) | ||
| 36 | #define SJA_SAM ((pParams->btr1 & 0x80)>>7) | ||
| 37 | int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2); | ||
| 38 | int samplepoint_m16c(int brp, int pr, int ph1, int ph2); | ||
| 39 | int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T *pMsg); | ||
| 40 | |||
| 41 | #endif | ||
diff --git a/drivers/staging/cpc-usb/sja2m16c_2.c b/drivers/staging/cpc-usb/sja2m16c_2.c deleted file mode 100644 index bf0230fb7780..000000000000 --- a/drivers/staging/cpc-usb/sja2m16c_2.c +++ /dev/null | |||
| @@ -1,452 +0,0 @@ | |||
| 1 | /**************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2003,2004 by EMS Dr. Thomas Wuensche | ||
| 4 | * | ||
| 5 | * - All rights reserved - | ||
| 6 | * | ||
| 7 | * This code is provided "as is" without warranty of any kind, either | ||
| 8 | * expressed or implied, including but not limited to the liability | ||
| 9 | * concerning the freedom from material defects, the fitness for parti- | ||
| 10 | * cular purposes or the freedom of proprietary rights of third parties. | ||
| 11 | * | ||
| 12 | ***************************************************************************** | ||
| 13 | * Module name.: cpcusb | ||
| 14 | ***************************************************************************** | ||
| 15 | * Include file: cpc.h | ||
| 16 | ***************************************************************************** | ||
| 17 | * Project.....: Windows Driver Development Kit | ||
| 18 | * Filename....: sja2m16c.cpp | ||
| 19 | * Authors.....: (GU) Gerhard Uttenthaler | ||
| 20 | * (CS) Christian Schoett | ||
| 21 | ***************************************************************************** | ||
| 22 | * Short descr.: converts baudrate between SJA1000 and M16C | ||
| 23 | ***************************************************************************** | ||
| 24 | * Description.: handles the baudrate conversion from SJA1000 parameters to | ||
| 25 | * M16C parameters | ||
| 26 | ***************************************************************************** | ||
| 27 | * Address : EMS Dr. Thomas Wuensche | ||
| 28 | * Sonnenhang 3 | ||
| 29 | * D-85304 Ilmmuenster | ||
| 30 | * Tel. : +49-8441-490260 | ||
| 31 | * Fax. : +49-8441-81860 | ||
| 32 | * email: support@ems-wuensche.com | ||
| 33 | ***************************************************************************** | ||
| 34 | * History | ||
| 35 | ***************************************************************************** | ||
| 36 | * Version Date Auth Remark | ||
| 37 | * | ||
| 38 | * 01.00 ?? GU - initial release | ||
| 39 | * 01.10 ?????????? CS - adapted to fit into the USB Windows driver | ||
| 40 | * 02.00 18.08.2004 GU - improved the baudrate calculating algorithm | ||
| 41 | * - implemented acceptance filtering | ||
| 42 | * 02.10 10.09.2004 CS - adapted to fit into the USB Windows driver | ||
| 43 | ***************************************************************************** | ||
| 44 | * ToDo's | ||
| 45 | ***************************************************************************** | ||
| 46 | */ | ||
| 47 | |||
| 48 | /****************************************************************************/ | ||
| 49 | /* I N C L U D E S | ||
| 50 | */ | ||
| 51 | #include <linux/kernel.h> | ||
| 52 | #include <linux/errno.h> | ||
| 53 | #include <linux/init.h> | ||
| 54 | #include <linux/slab.h> | ||
| 55 | #include <linux/vmalloc.h> | ||
| 56 | #include <linux/module.h> | ||
| 57 | #include <linux/poll.h> | ||
| 58 | #include <linux/smp_lock.h> | ||
| 59 | #include <linux/completion.h> | ||
| 60 | #include <asm/uaccess.h> | ||
| 61 | #include <linux/usb.h> | ||
| 62 | |||
| 63 | #include "cpc.h" | ||
| 64 | #include "cpc_int.h" | ||
| 65 | #include "cpcusb.h" | ||
| 66 | |||
| 67 | #include "sja2m16c.h" | ||
| 68 | |||
| 69 | /*********************************************************************/ | ||
| 70 | int baudrate_m16c(int clk, int brp, int pr, int ph1, int ph2) | ||
| 71 | { | ||
| 72 | return (16000000 / (1 << clk)) / 2 / (brp + 1) / (1 + pr + 1 + | ||
| 73 | ph1 + 1 + ph2 + | ||
| 74 | 1); | ||
| 75 | } | ||
| 76 | |||
| 77 | |||
| 78 | /*********************************************************************/ | ||
| 79 | int samplepoint_m16c(int brp, int pr, int ph1, int ph2) | ||
| 80 | { | ||
| 81 | return (100 * (1 + pr + 1 + ph1 + 1)) / (1 + pr + 1 + ph1 + 1 + | ||
| 82 | ph2 + 1); | ||
| 83 | } | ||
| 84 | |||
| 85 | |||
| 86 | /**************************************************************************** | ||
| 87 | * Function.....: SJA1000_TO_M16C_BASIC_Params | ||
| 88 | * | ||
| 89 | * Task.........: This routine converts SJA1000 CAN btr parameters into M16C | ||
| 90 | * parameters based on the sample point and the error. In | ||
| 91 | * addition it converts the acceptance filter parameters to | ||
| 92 | * suit the M16C parameters | ||
| 93 | * | ||
| 94 | * Parameters...: None | ||
| 95 | * | ||
| 96 | * Return values: None | ||
| 97 | * | ||
| 98 | * Comments.....: | ||
| 99 | ***************************************************************************** | ||
| 100 | * History | ||
| 101 | ***************************************************************************** | ||
| 102 | * 19.01.2005 CS - modifed the conversion of SJA1000 filter params into | ||
| 103 | * M16C params. Due to compatibility reasons with the | ||
| 104 | * older 82C200 CAN controller the SJA1000 | ||
| 105 | ****************************************************************************/ | ||
| 106 | int SJA1000_TO_M16C_BASIC_Params(CPC_MSG_T * in) | ||
| 107 | { | ||
| 108 | int sjaBaudrate; | ||
| 109 | int sjaSamplepoint; | ||
| 110 | int *baudrate_error; // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7] | ||
| 111 | int *samplepoint_error; // BRP[0..15], PR[0..7], PH1[0..7], PH2[0..7] | ||
| 112 | int baudrate_error_merk; | ||
| 113 | int clk, brp, pr, ph1, ph2; | ||
| 114 | int clk_merk, brp_merk, pr_merk, ph1_merk, ph2_merk; | ||
| 115 | int index; | ||
| 116 | unsigned char acc_code0, acc_code1, acc_code2, acc_code3; | ||
| 117 | unsigned char acc_mask0, acc_mask1, acc_mask2, acc_mask3; | ||
| 118 | CPC_MSG_T * out; | ||
| 119 | C0CONR_T c0con; | ||
| 120 | C1CONR_T c1con; | ||
| 121 | int tmpAccCode; | ||
| 122 | int tmpAccMask; | ||
| 123 | |||
| 124 | // we have to convert the parameters into M16C parameters | ||
| 125 | CPC_SJA1000_PARAMS_T * pParams; | ||
| 126 | |||
| 127 | // check if the type is CAN parameters and if we have to convert the given params | ||
| 128 | if (in->type != CPC_CMD_T_CAN_PRMS | ||
| 129 | || in->msg.canparams.cc_type != SJA1000) | ||
| 130 | return 0; | ||
| 131 | pParams = | ||
| 132 | (CPC_SJA1000_PARAMS_T *) & in->msg.canparams.cc_params.sja1000; | ||
| 133 | acc_code0 = pParams->acc_code0; | ||
| 134 | acc_code1 = pParams->acc_code1; | ||
| 135 | acc_code2 = pParams->acc_code2; | ||
| 136 | acc_code3 = pParams->acc_code3; | ||
| 137 | acc_mask0 = pParams->acc_mask0; | ||
| 138 | acc_mask1 = pParams->acc_mask1; | ||
| 139 | acc_mask2 = pParams->acc_mask2; | ||
| 140 | acc_mask3 = pParams->acc_mask3; | ||
| 141 | |||
| 142 | #ifdef _DEBUG_OUTPUT_CAN_PARAMS | ||
| 143 | info("acc_code0: %2.2Xh\n", acc_code0); | ||
| 144 | info("acc_code1: %2.2Xh\n", acc_code1); | ||
| 145 | info("acc_code2: %2.2Xh\n", acc_code2); | ||
| 146 | info("acc_code3: %2.2Xh\n", acc_code3); | ||
| 147 | info("acc_mask0: %2.2Xh\n", acc_mask0); | ||
| 148 | info("acc_mask1: %2.2Xh\n", acc_mask1); | ||
| 149 | info("acc_mask2: %2.2Xh\n", acc_mask2); | ||
| 150 | info("acc_mask3: %2.2Xh\n", acc_mask3); | ||
| 151 | |||
| 152 | #endif /* */ | ||
| 153 | if (! | ||
| 154 | (baudrate_error = | ||
| 155 | (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) { | ||
| 156 | err("Could not allocate memory\n"); | ||
| 157 | return -3; | ||
| 158 | } | ||
| 159 | if (! | ||
| 160 | (samplepoint_error = | ||
| 161 | (int *) vmalloc(sizeof(int) * 16 * 8 * 8 * 8 * 5))) { | ||
| 162 | err("Could not allocate memory\n"); | ||
| 163 | vfree(baudrate_error); | ||
| 164 | return -3; | ||
| 165 | } | ||
| 166 | memset(baudrate_error, 0xff, sizeof(baudrate_error)); | ||
| 167 | memset(samplepoint_error, 0xff, sizeof(baudrate_error)); | ||
| 168 | sjaBaudrate = | ||
| 169 | 16000000 / 2 / SJA_BRP / (1 + SJA_TSEG1 + SJA_TSEG2); | ||
| 170 | sjaSamplepoint = | ||
| 171 | 100 * (1 + SJA_TSEG1) / (1 + SJA_TSEG1 + SJA_TSEG2); | ||
| 172 | if (sjaBaudrate == 0) { | ||
| 173 | vfree(baudrate_error); | ||
| 174 | vfree(samplepoint_error); | ||
| 175 | return -2; | ||
| 176 | } | ||
| 177 | |||
| 178 | #ifdef _DEBUG_OUTPUT_CAN_PARAMS | ||
| 179 | info("\nStarting SJA CAN params\n"); | ||
| 180 | info("-------------------------\n"); | ||
| 181 | info("TS1 : %2.2Xh TS2 : %2.2Xh\n", SJA_TSEG1, SJA_TSEG2); | ||
| 182 | info("BTR0 : %2.2Xh BTR1: %2.2Xh\n", pParams->btr0, | ||
| 183 | pParams->btr1); | ||
| 184 | info("Baudrate: %d.%dkBaud\n", sjaBaudrate / 1000, | ||
| 185 | sjaBaudrate % 1000); | ||
| 186 | info("Sample P: 0.%d\n", sjaSamplepoint); | ||
| 187 | info("\n"); | ||
| 188 | |||
| 189 | #endif /* */ | ||
| 190 | c0con.bc0con.sam = SJA_SAM; | ||
| 191 | c1con.bc1con.sjw = SJA_SJW; | ||
| 192 | |||
| 193 | // calculate errors for all baudrates | ||
| 194 | index = 0; | ||
| 195 | for (clk = 0; clk < 5; clk++) { | ||
| 196 | for (brp = 0; brp < 16; brp++) { | ||
| 197 | for (pr = 0; pr < 8; pr++) { | ||
| 198 | for (ph1 = 0; ph1 < 8; ph1++) { | ||
| 199 | for (ph2 = 0; ph2 < 8; ph2++) { | ||
| 200 | baudrate_error[index] = | ||
| 201 | 100 * | ||
| 202 | abs(baudrate_m16c | ||
| 203 | (clk, brp, pr, ph1, | ||
| 204 | ph2) - | ||
| 205 | sjaBaudrate) / | ||
| 206 | sjaBaudrate; | ||
| 207 | samplepoint_error[index] = | ||
| 208 | abs(samplepoint_m16c | ||
| 209 | (brp, pr, ph1, | ||
| 210 | ph2) - | ||
| 211 | sjaSamplepoint); | ||
| 212 | |||
| 213 | #if 0 | ||
| 214 | info | ||
| 215 | ("Baudrate : %d kBaud\n", | ||
| 216 | baudrate_m16c(clk, | ||
| 217 | brp, pr, | ||
| 218 | ph1, | ||
| 219 | ph2)); | ||
| 220 | info | ||
| 221 | ("Baudrate Error: %d\n", | ||
| 222 | baudrate_error | ||
| 223 | [index]); | ||
| 224 | info | ||
| 225 | ("Sample P Error: %d\n", | ||
| 226 | samplepoint_error | ||
| 227 | [index]); | ||
| 228 | info | ||
| 229 | ("clk : %d\n", | ||
| 230 | clk); | ||
| 231 | |||
| 232 | #endif /* */ | ||
| 233 | index++; | ||
| 234 | } | ||
| 235 | } | ||
| 236 | } | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | // mark all baudrate_error entries which are outer limits | ||
| 241 | index = 0; | ||
| 242 | for (clk = 0; clk < 5; clk++) { | ||
| 243 | for (brp = 0; brp < 16; brp++) { | ||
| 244 | for (pr = 0; pr < 8; pr++) { | ||
| 245 | for (ph1 = 0; ph1 < 8; ph1++) { | ||
| 246 | for (ph2 = 0; ph2 < 8; ph2++) { | ||
| 247 | if ((baudrate_error[index] | ||
| 248 | > | ||
| 249 | BAUDRATE_TOLERANCE_PERCENT) | ||
| 250 | || | ||
| 251 | (samplepoint_error | ||
| 252 | [index] > | ||
| 253 | SAMPLEPOINT_TOLERANCE_PERCENT) | ||
| 254 | || | ||
| 255 | (samplepoint_m16c | ||
| 256 | (brp, pr, ph1, | ||
| 257 | ph2) > | ||
| 258 | SAMPLEPOINT_UPPER_LIMIT)) | ||
| 259 | { | ||
| 260 | baudrate_error | ||
| 261 | [index] = -1; | ||
| 262 | } else | ||
| 263 | if (((1 + pr + 1 + | ||
| 264 | ph1 + 1 + ph2 + | ||
| 265 | 1) < 8) | ||
| 266 | || | ||
| 267 | ((1 + pr + 1 + | ||
| 268 | ph1 + 1 + ph2 + | ||
| 269 | 1) > 25)) { | ||
| 270 | baudrate_error | ||
| 271 | [index] = -1; | ||
| 272 | } | ||
| 273 | |||
| 274 | #if 0 | ||
| 275 | else { | ||
| 276 | info | ||
| 277 | ("Baudrate : %d kBaud\n", | ||
| 278 | baudrate_m16c | ||
| 279 | (clk, brp, pr, | ||
| 280 | ph1, ph2)); | ||
| 281 | info | ||
| 282 | ("Baudrate Error: %d\n", | ||
| 283 | baudrate_error | ||
| 284 | [index]); | ||
| 285 | info | ||
| 286 | ("Sample P Error: %d\n", | ||
| 287 | samplepoint_error | ||
| 288 | [index]); | ||
| 289 | } | ||
| 290 | |||
| 291 | #endif /* */ | ||
| 292 | index++; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | } | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | // find list of minimum of baudrate_error within unmarked entries | ||
| 300 | clk_merk = brp_merk = pr_merk = ph1_merk = ph2_merk = 0; | ||
| 301 | baudrate_error_merk = 100; | ||
| 302 | index = 0; | ||
| 303 | for (clk = 0; clk < 5; clk++) { | ||
| 304 | for (brp = 0; brp < 16; brp++) { | ||
| 305 | for (pr = 0; pr < 8; pr++) { | ||
| 306 | for (ph1 = 0; ph1 < 8; ph1++) { | ||
| 307 | for (ph2 = 0; ph2 < 8; ph2++) { | ||
| 308 | if (baudrate_error[index] | ||
| 309 | != -1) { | ||
| 310 | if (baudrate_error | ||
| 311 | [index] < | ||
| 312 | baudrate_error_merk) | ||
| 313 | { | ||
| 314 | baudrate_error_merk | ||
| 315 | = | ||
| 316 | baudrate_error | ||
| 317 | [index]; | ||
| 318 | brp_merk = | ||
| 319 | brp; | ||
| 320 | pr_merk = | ||
| 321 | pr; | ||
| 322 | ph1_merk = | ||
| 323 | ph1; | ||
| 324 | ph2_merk = | ||
| 325 | ph2; | ||
| 326 | clk_merk = | ||
| 327 | clk; | ||
| 328 | |||
| 329 | #if 0 | ||
| 330 | info | ||
| 331 | ("brp: %2.2Xh pr: %2.2Xh ph1: %2.2Xh ph2: %2.2Xh\n", | ||
| 332 | brp, | ||
| 333 | pr, | ||
| 334 | ph1, | ||
| 335 | ph2); | ||
| 336 | info | ||
| 337 | ("Baudrate : %d kBaud\n", | ||
| 338 | baudrate_m16c | ||
| 339 | (clk, | ||
| 340 | brp, | ||
| 341 | pr, | ||
| 342 | ph1, | ||
| 343 | ph2)); | ||
| 344 | info | ||
| 345 | ("Baudrate Error: %d\n", | ||
| 346 | baudrate_error | ||
| 347 | [index]); | ||
| 348 | info | ||
| 349 | ("Sample P Error: %d\n", | ||
| 350 | samplepoint_error | ||
| 351 | [index]); | ||
| 352 | |||
| 353 | #endif /* */ | ||
| 354 | } | ||
| 355 | } | ||
| 356 | index++; | ||
| 357 | } | ||
| 358 | } | ||
| 359 | } | ||
| 360 | } | ||
| 361 | } | ||
| 362 | if (baudrate_error_merk == 100) { | ||
| 363 | info("ERROR: Could not convert CAN init parameter\n"); | ||
| 364 | vfree(baudrate_error); | ||
| 365 | vfree(samplepoint_error); | ||
| 366 | return -1; | ||
| 367 | } | ||
| 368 | |||
| 369 | // setting m16c CAN parameter | ||
| 370 | c0con.bc0con.brp = brp_merk; | ||
| 371 | c0con.bc0con.pr = pr_merk; | ||
| 372 | c1con.bc1con.ph1 = ph1_merk; | ||
| 373 | c1con.bc1con.ph2 = ph2_merk; | ||
| 374 | |||
| 375 | #ifdef _DEBUG_OUTPUT_CAN_PARAMS | ||
| 376 | info("\nResulting M16C CAN params\n"); | ||
| 377 | info("-------------------------\n"); | ||
| 378 | info("clk : %2.2Xh\n", clk_merk); | ||
| 379 | info("ph1 : %2.2Xh ph2: %2.2Xh\n", c1con.bc1con.ph1 + 1, | ||
| 380 | c1con.bc1con.ph2 + 1); | ||
| 381 | info("pr : %2.2Xh brp: %2.2Xh\n", c0con.bc0con.pr + 1, | ||
| 382 | c0con.bc0con.brp + 1); | ||
| 383 | info("sjw : %2.2Xh sam: %2.2Xh\n", c1con.bc1con.sjw, | ||
| 384 | c0con.bc0con.sam); | ||
| 385 | info("co1 : %2.2Xh co0: %2.2Xh\n", c1con.c1con, c0con.c0con); | ||
| 386 | info("Baudrate: %d.%dBaud\n", | ||
| 387 | baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr, | ||
| 388 | c1con.bc1con.ph1, c1con.bc1con.ph2) / 1000, | ||
| 389 | baudrate_m16c(clk_merk, c0con.bc0con.brp, c0con.bc0con.pr, | ||
| 390 | c1con.bc1con.ph1, c1con.bc1con.ph2) % 1000); | ||
| 391 | info("Sample P: 0.%d\n", | ||
| 392 | samplepoint_m16c(c0con.bc0con.brp, c0con.bc0con.pr, | ||
| 393 | c1con.bc1con.ph1, c1con.bc1con.ph2)); | ||
| 394 | info("\n"); | ||
| 395 | |||
| 396 | #endif /* */ | ||
| 397 | out = in; | ||
| 398 | out->type = 6; | ||
| 399 | out->length = sizeof(CPC_M16C_BASIC_PARAMS_T) + 1; | ||
| 400 | out->msg.canparams.cc_type = M16C_BASIC; | ||
| 401 | out->msg.canparams.cc_params.m16c_basic.con0 = c0con.c0con; | ||
| 402 | out->msg.canparams.cc_params.m16c_basic.con1 = c1con.c1con; | ||
| 403 | out->msg.canparams.cc_params.m16c_basic.ctlr0 = 0x4C; | ||
| 404 | out->msg.canparams.cc_params.m16c_basic.ctlr1 = 0x00; | ||
| 405 | out->msg.canparams.cc_params.m16c_basic.clk = clk_merk; | ||
| 406 | out->msg.canparams.cc_params.m16c_basic.acc_std_code0 = | ||
| 407 | acc_code0; | ||
| 408 | out->msg.canparams.cc_params.m16c_basic.acc_std_code1 = acc_code1; | ||
| 409 | |||
| 410 | // 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); | ||
| 411 | tmpAccCode = (acc_code1 >> 5) + (acc_code0 << 3); | ||
| 412 | out->msg.canparams.cc_params.m16c_basic.acc_std_code0 = | ||
| 413 | (unsigned char) tmpAccCode; | ||
| 414 | out->msg.canparams.cc_params.m16c_basic.acc_std_code1 = | ||
| 415 | (unsigned char) (tmpAccCode >> 8); | ||
| 416 | |||
| 417 | // 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); | ||
| 418 | out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 = | ||
| 419 | ~acc_mask0; | ||
| 420 | out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 = | ||
| 421 | ~acc_mask1; | ||
| 422 | |||
| 423 | // 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); | ||
| 424 | tmpAccMask = ((acc_mask1) >> 5) + ((acc_mask0) << 3); | ||
| 425 | |||
| 426 | // info("tmpAccMask: 0x%4.4X\n", tmpAccMask); | ||
| 427 | out->msg.canparams.cc_params.m16c_basic.acc_std_mask0 = | ||
| 428 | (unsigned char) ~tmpAccMask; | ||
| 429 | out->msg.canparams.cc_params.m16c_basic.acc_std_mask1 = | ||
| 430 | (unsigned char) ~(tmpAccMask >> 8); | ||
| 431 | |||
| 432 | // 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); | ||
| 433 | out->msg.canparams.cc_params.m16c_basic.acc_ext_code0 = | ||
| 434 | (unsigned char) tmpAccCode; | ||
| 435 | out->msg.canparams.cc_params.m16c_basic.acc_ext_code1 = | ||
| 436 | (unsigned char) (tmpAccCode >> 8); | ||
| 437 | out->msg.canparams.cc_params.m16c_basic.acc_ext_code2 = acc_code2; | ||
| 438 | out->msg.canparams.cc_params.m16c_basic.acc_ext_code3 = acc_code3; | ||
| 439 | out->msg.canparams.cc_params.m16c_basic.acc_ext_mask0 = | ||
| 440 | (unsigned char) ~tmpAccMask; | ||
| 441 | out->msg.canparams.cc_params.m16c_basic.acc_ext_mask1 = | ||
| 442 | (unsigned char) ~(tmpAccMask >> 8); | ||
| 443 | out->msg.canparams.cc_params.m16c_basic.acc_ext_mask2 = | ||
| 444 | ~acc_mask2; | ||
| 445 | out->msg.canparams.cc_params.m16c_basic.acc_ext_mask3 = | ||
| 446 | ~acc_mask3; | ||
| 447 | vfree(baudrate_error); | ||
| 448 | vfree(samplepoint_error); | ||
| 449 | return 0; | ||
| 450 | } | ||
| 451 | |||
| 452 | |||
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 080f6ba9e73a..ab5d3126831f 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h | |||
| @@ -187,6 +187,7 @@ extern struct sock *netlink_kernel_create(struct net *net, | |||
| 187 | extern void netlink_kernel_release(struct sock *sk); | 187 | extern void netlink_kernel_release(struct sock *sk); |
| 188 | extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups); | 188 | extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups); |
| 189 | extern int netlink_change_ngroups(struct sock *sk, unsigned int groups); | 189 | extern int netlink_change_ngroups(struct sock *sk, unsigned int groups); |
| 190 | extern void __netlink_clear_multicast_users(struct sock *sk, unsigned int group); | ||
| 190 | extern void netlink_clear_multicast_users(struct sock *sk, unsigned int group); | 191 | extern void netlink_clear_multicast_users(struct sock *sk, unsigned int group); |
| 191 | extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err); | 192 | extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err); |
| 192 | extern int netlink_has_listeners(struct sock *sk, unsigned int group); | 193 | extern int netlink_has_listeners(struct sock *sk, unsigned int group); |
diff --git a/include/linux/phonet.h b/include/linux/phonet.h index 1ef5a0781831..e5126cff9b2a 100644 --- a/include/linux/phonet.h +++ b/include/linux/phonet.h | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #define PNPIPE_IFINDEX 2 | 38 | #define PNPIPE_IFINDEX 2 |
| 39 | 39 | ||
| 40 | #define PNADDR_ANY 0 | 40 | #define PNADDR_ANY 0 |
| 41 | #define PNADDR_BROADCAST 0xFC | ||
| 41 | #define PNPORT_RESOURCE_ROUTING 0 | 42 | #define PNPORT_RESOURCE_ROUTING 0 |
| 42 | 43 | ||
| 43 | /* Values for PNPIPE_ENCAP option */ | 44 | /* Values for PNPIPE_ENCAP option */ |
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index bb69e256cd16..f81473052059 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h | |||
| @@ -89,6 +89,7 @@ struct driver_info { | |||
| 89 | #define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ | 89 | #define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ |
| 90 | #define FLAG_WLAN 0x0080 /* use "wlan%d" names */ | 90 | #define FLAG_WLAN 0x0080 /* use "wlan%d" names */ |
| 91 | #define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */ | 91 | #define FLAG_AVOID_UNLINK_URBS 0x0100 /* don't unlink urbs at usbnet_stop() */ |
| 92 | #define FLAG_SEND_ZLP 0x0200 /* hw requires ZLPs are sent */ | ||
| 92 | 93 | ||
| 93 | 94 | ||
| 94 | /* init device ... can sleep, or cause probe() failure */ | 95 | /* init device ... can sleep, or cause probe() failure */ |
diff --git a/include/net/ipip.h b/include/net/ipip.h index 5d3036fa1511..76e3ea6e2fe5 100644 --- a/include/net/ipip.h +++ b/include/net/ipip.h | |||
| @@ -12,7 +12,6 @@ struct ip_tunnel | |||
| 12 | struct ip_tunnel *next; | 12 | struct ip_tunnel *next; |
| 13 | struct net_device *dev; | 13 | struct net_device *dev; |
| 14 | 14 | ||
| 15 | int recursion; /* Depth of hard_start_xmit recursion */ | ||
| 16 | int err_count; /* Number of arrived ICMP errors */ | 15 | int err_count; /* Number of arrived ICMP errors */ |
| 17 | unsigned long err_time; /* Time when the last ICMP error arrived */ | 16 | unsigned long err_time; /* Time when the last ICMP error arrived */ |
| 18 | 17 | ||
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 515bc230ac2a..e06d0b8d1951 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
| @@ -49,6 +49,7 @@ cond_syscall(sys_sendmsg); | |||
| 49 | cond_syscall(compat_sys_sendmsg); | 49 | cond_syscall(compat_sys_sendmsg); |
| 50 | cond_syscall(sys_recvmsg); | 50 | cond_syscall(sys_recvmsg); |
| 51 | cond_syscall(compat_sys_recvmsg); | 51 | cond_syscall(compat_sys_recvmsg); |
| 52 | cond_syscall(compat_sys_recvfrom); | ||
| 52 | cond_syscall(sys_socketcall); | 53 | cond_syscall(sys_socketcall); |
| 53 | cond_syscall(sys_futex); | 54 | cond_syscall(sys_futex); |
| 54 | cond_syscall(compat_sys_futex); | 55 | cond_syscall(compat_sys_futex); |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 73a14b8c6d1f..b91839e9e892 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -671,7 +671,7 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros) | |||
| 671 | return p; | 671 | return p; |
| 672 | } | 672 | } |
| 673 | 673 | ||
| 674 | static char *ip6_compressed_string(char *p, const struct in6_addr *addr) | 674 | static char *ip6_compressed_string(char *p, const char *addr) |
| 675 | { | 675 | { |
| 676 | int i; | 676 | int i; |
| 677 | int j; | 677 | int j; |
| @@ -683,7 +683,12 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr) | |||
| 683 | u8 hi; | 683 | u8 hi; |
| 684 | u8 lo; | 684 | u8 lo; |
| 685 | bool needcolon = false; | 685 | bool needcolon = false; |
| 686 | bool useIPv4 = ipv6_addr_v4mapped(addr) || ipv6_addr_is_isatap(addr); | 686 | bool useIPv4; |
| 687 | struct in6_addr in6; | ||
| 688 | |||
| 689 | memcpy(&in6, addr, sizeof(struct in6_addr)); | ||
| 690 | |||
| 691 | useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6); | ||
| 687 | 692 | ||
| 688 | memset(zerolength, 0, sizeof(zerolength)); | 693 | memset(zerolength, 0, sizeof(zerolength)); |
| 689 | 694 | ||
| @@ -695,7 +700,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr) | |||
| 695 | /* find position of longest 0 run */ | 700 | /* find position of longest 0 run */ |
| 696 | for (i = 0; i < range; i++) { | 701 | for (i = 0; i < range; i++) { |
| 697 | for (j = i; j < range; j++) { | 702 | for (j = i; j < range; j++) { |
| 698 | if (addr->s6_addr16[j] != 0) | 703 | if (in6.s6_addr16[j] != 0) |
| 699 | break; | 704 | break; |
| 700 | zerolength[i]++; | 705 | zerolength[i]++; |
| 701 | } | 706 | } |
| @@ -722,7 +727,7 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr) | |||
| 722 | needcolon = false; | 727 | needcolon = false; |
| 723 | } | 728 | } |
| 724 | /* hex u16 without leading 0s */ | 729 | /* hex u16 without leading 0s */ |
| 725 | word = ntohs(addr->s6_addr16[i]); | 730 | word = ntohs(in6.s6_addr16[i]); |
| 726 | hi = word >> 8; | 731 | hi = word >> 8; |
| 727 | lo = word & 0xff; | 732 | lo = word & 0xff; |
| 728 | if (hi) { | 733 | if (hi) { |
| @@ -741,19 +746,19 @@ static char *ip6_compressed_string(char *p, const struct in6_addr *addr) | |||
| 741 | if (useIPv4) { | 746 | if (useIPv4) { |
| 742 | if (needcolon) | 747 | if (needcolon) |
| 743 | *p++ = ':'; | 748 | *p++ = ':'; |
| 744 | p = ip4_string(p, &addr->s6_addr[12], false); | 749 | p = ip4_string(p, &in6.s6_addr[12], false); |
| 745 | } | 750 | } |
| 746 | 751 | ||
| 747 | *p = '\0'; | 752 | *p = '\0'; |
| 748 | return p; | 753 | return p; |
| 749 | } | 754 | } |
| 750 | 755 | ||
| 751 | static char *ip6_string(char *p, const struct in6_addr *addr, const char *fmt) | 756 | static char *ip6_string(char *p, const char *addr, const char *fmt) |
| 752 | { | 757 | { |
| 753 | int i; | 758 | int i; |
| 754 | for (i = 0; i < 8; i++) { | 759 | for (i = 0; i < 8; i++) { |
| 755 | p = pack_hex_byte(p, addr->s6_addr[2 * i]); | 760 | p = pack_hex_byte(p, *addr++); |
| 756 | p = pack_hex_byte(p, addr->s6_addr[2 * i + 1]); | 761 | p = pack_hex_byte(p, *addr++); |
| 757 | if (fmt[0] == 'I' && i != 7) | 762 | if (fmt[0] == 'I' && i != 7) |
| 758 | *p++ = ':'; | 763 | *p++ = ':'; |
| 759 | } | 764 | } |
| @@ -768,9 +773,9 @@ static char *ip6_addr_string(char *buf, char *end, const u8 *addr, | |||
| 768 | char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; | 773 | char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; |
| 769 | 774 | ||
| 770 | if (fmt[0] == 'I' && fmt[2] == 'c') | 775 | if (fmt[0] == 'I' && fmt[2] == 'c') |
| 771 | ip6_compressed_string(ip6_addr, (const struct in6_addr *)addr); | 776 | ip6_compressed_string(ip6_addr, addr); |
| 772 | else | 777 | else |
| 773 | ip6_string(ip6_addr, (const struct in6_addr *)addr, fmt); | 778 | ip6_string(ip6_addr, addr, fmt); |
| 774 | 779 | ||
| 775 | return string(buf, end, ip6_addr, spec); | 780 | return string(buf, end, ip6_addr, spec); |
| 776 | } | 781 | } |
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index da0f64f82b57..d6b1b054e294 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
| @@ -1781,8 +1781,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 1781 | ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ); | 1781 | ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ); |
| 1782 | ax25_info.n2count = ax25->n2count; | 1782 | ax25_info.n2count = ax25->n2count; |
| 1783 | ax25_info.state = ax25->state; | 1783 | ax25_info.state = ax25->state; |
| 1784 | ax25_info.rcv_q = sk_wmem_alloc_get(sk); | 1784 | ax25_info.rcv_q = sk_rmem_alloc_get(sk); |
| 1785 | ax25_info.snd_q = sk_rmem_alloc_get(sk); | 1785 | ax25_info.snd_q = sk_wmem_alloc_get(sk); |
| 1786 | ax25_info.vs = ax25->vs; | 1786 | ax25_info.vs = ax25->vs; |
| 1787 | ax25_info.vr = ax25->vr; | 1787 | ax25_info.vr = ax25->vr; |
| 1788 | ax25_info.va = ax25->va; | 1788 | ax25_info.va = ax25->va; |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 0bcecbf06581..4d11c28ca8ca 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
| @@ -192,11 +192,10 @@ | |||
| 192 | #define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ | 192 | #define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ |
| 193 | 193 | ||
| 194 | /* Thread control flag bits */ | 194 | /* Thread control flag bits */ |
| 195 | #define T_TERMINATE (1<<0) | 195 | #define T_STOP (1<<0) /* Stop run */ |
| 196 | #define T_STOP (1<<1) /* Stop run */ | 196 | #define T_RUN (1<<1) /* Start run */ |
| 197 | #define T_RUN (1<<2) /* Start run */ | 197 | #define T_REMDEVALL (1<<2) /* Remove all devs */ |
| 198 | #define T_REMDEVALL (1<<3) /* Remove all devs */ | 198 | #define T_REMDEV (1<<3) /* Remove one dev */ |
| 199 | #define T_REMDEV (1<<4) /* Remove one dev */ | ||
| 200 | 199 | ||
| 201 | /* If lock -- can be removed after some work */ | 200 | /* If lock -- can be removed after some work */ |
| 202 | #define if_lock(t) spin_lock(&(t->if_lock)); | 201 | #define if_lock(t) spin_lock(&(t->if_lock)); |
| @@ -2105,7 +2104,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) | |||
| 2105 | 2104 | ||
| 2106 | static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) | 2105 | static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) |
| 2107 | { | 2106 | { |
| 2108 | ktime_t start; | 2107 | ktime_t start_time, end_time; |
| 2109 | s32 remaining; | 2108 | s32 remaining; |
| 2110 | struct hrtimer_sleeper t; | 2109 | struct hrtimer_sleeper t; |
| 2111 | 2110 | ||
| @@ -2116,7 +2115,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) | |||
| 2116 | if (remaining <= 0) | 2115 | if (remaining <= 0) |
| 2117 | return; | 2116 | return; |
| 2118 | 2117 | ||
| 2119 | start = ktime_now(); | 2118 | start_time = ktime_now(); |
| 2120 | if (remaining < 100) | 2119 | if (remaining < 100) |
| 2121 | udelay(remaining); /* really small just spin */ | 2120 | udelay(remaining); /* really small just spin */ |
| 2122 | else { | 2121 | else { |
| @@ -2135,7 +2134,10 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) | |||
| 2135 | } while (t.task && pkt_dev->running && !signal_pending(current)); | 2134 | } while (t.task && pkt_dev->running && !signal_pending(current)); |
| 2136 | __set_current_state(TASK_RUNNING); | 2135 | __set_current_state(TASK_RUNNING); |
| 2137 | } | 2136 | } |
| 2138 | pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), start)); | 2137 | end_time = ktime_now(); |
| 2138 | |||
| 2139 | pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time)); | ||
| 2140 | pkt_dev->next_tx = ktime_add_ns(end_time, pkt_dev->delay); | ||
| 2139 | } | 2141 | } |
| 2140 | 2142 | ||
| 2141 | static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) | 2143 | static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) |
| @@ -3365,19 +3367,29 @@ static void pktgen_rem_thread(struct pktgen_thread *t) | |||
| 3365 | mutex_unlock(&pktgen_thread_lock); | 3367 | mutex_unlock(&pktgen_thread_lock); |
| 3366 | } | 3368 | } |
| 3367 | 3369 | ||
| 3368 | static void idle(struct pktgen_dev *pkt_dev) | 3370 | static void pktgen_resched(struct pktgen_dev *pkt_dev) |
| 3369 | { | 3371 | { |
| 3370 | ktime_t idle_start = ktime_now(); | 3372 | ktime_t idle_start = ktime_now(); |
| 3373 | schedule(); | ||
| 3374 | pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start)); | ||
| 3375 | } | ||
| 3371 | 3376 | ||
| 3372 | if (need_resched()) | 3377 | static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev) |
| 3373 | schedule(); | 3378 | { |
| 3374 | else | 3379 | ktime_t idle_start = ktime_now(); |
| 3375 | cpu_relax(); | ||
| 3376 | 3380 | ||
| 3381 | while (atomic_read(&(pkt_dev->skb->users)) != 1) { | ||
| 3382 | if (signal_pending(current)) | ||
| 3383 | break; | ||
| 3384 | |||
| 3385 | if (need_resched()) | ||
| 3386 | pktgen_resched(pkt_dev); | ||
| 3387 | else | ||
| 3388 | cpu_relax(); | ||
| 3389 | } | ||
| 3377 | pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start)); | 3390 | pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start)); |
| 3378 | } | 3391 | } |
| 3379 | 3392 | ||
| 3380 | |||
| 3381 | static void pktgen_xmit(struct pktgen_dev *pkt_dev) | 3393 | static void pktgen_xmit(struct pktgen_dev *pkt_dev) |
| 3382 | { | 3394 | { |
| 3383 | struct net_device *odev = pkt_dev->odev; | 3395 | struct net_device *odev = pkt_dev->odev; |
| @@ -3387,36 +3399,21 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
| 3387 | u16 queue_map; | 3399 | u16 queue_map; |
| 3388 | int ret; | 3400 | int ret; |
| 3389 | 3401 | ||
| 3390 | if (pkt_dev->delay) { | 3402 | /* If device is offline, then don't send */ |
| 3391 | spin(pkt_dev, pkt_dev->next_tx); | 3403 | if (unlikely(!netif_running(odev) || !netif_carrier_ok(odev))) { |
| 3392 | 3404 | pktgen_stop_device(pkt_dev); | |
| 3393 | /* This is max DELAY, this has special meaning of | 3405 | return; |
| 3394 | * "never transmit" | ||
| 3395 | */ | ||
| 3396 | if (pkt_dev->delay == ULLONG_MAX) { | ||
| 3397 | pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX); | ||
| 3398 | return; | ||
| 3399 | } | ||
| 3400 | } | ||
| 3401 | |||
| 3402 | if (!pkt_dev->skb) { | ||
| 3403 | set_cur_queue_map(pkt_dev); | ||
| 3404 | queue_map = pkt_dev->cur_queue_map; | ||
| 3405 | } else { | ||
| 3406 | queue_map = skb_get_queue_mapping(pkt_dev->skb); | ||
| 3407 | } | 3406 | } |
| 3408 | 3407 | ||
| 3409 | txq = netdev_get_tx_queue(odev, queue_map); | 3408 | /* This is max DELAY, this has special meaning of |
| 3410 | /* Did we saturate the queue already? */ | 3409 | * "never transmit" |
| 3411 | if (netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq)) { | 3410 | */ |
| 3412 | /* If device is down, then all queues are permnantly frozen */ | 3411 | if (unlikely(pkt_dev->delay == ULLONG_MAX)) { |
| 3413 | if (netif_running(odev)) | 3412 | pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX); |
| 3414 | idle(pkt_dev); | ||
| 3415 | else | ||
| 3416 | pktgen_stop_device(pkt_dev); | ||
| 3417 | return; | 3413 | return; |
| 3418 | } | 3414 | } |
| 3419 | 3415 | ||
| 3416 | /* If no skb or clone count exhausted then get new one */ | ||
| 3420 | if (!pkt_dev->skb || (pkt_dev->last_ok && | 3417 | if (!pkt_dev->skb || (pkt_dev->last_ok && |
| 3421 | ++pkt_dev->clone_count >= pkt_dev->clone_skb)) { | 3418 | ++pkt_dev->clone_count >= pkt_dev->clone_skb)) { |
| 3422 | /* build a new pkt */ | 3419 | /* build a new pkt */ |
| @@ -3435,54 +3432,45 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
| 3435 | pkt_dev->clone_count = 0; /* reset counter */ | 3432 | pkt_dev->clone_count = 0; /* reset counter */ |
| 3436 | } | 3433 | } |
| 3437 | 3434 | ||
| 3438 | /* fill_packet() might have changed the queue */ | 3435 | if (pkt_dev->delay && pkt_dev->last_ok) |
| 3436 | spin(pkt_dev, pkt_dev->next_tx); | ||
| 3437 | |||
| 3439 | queue_map = skb_get_queue_mapping(pkt_dev->skb); | 3438 | queue_map = skb_get_queue_mapping(pkt_dev->skb); |
| 3440 | txq = netdev_get_tx_queue(odev, queue_map); | 3439 | txq = netdev_get_tx_queue(odev, queue_map); |
| 3441 | 3440 | ||
| 3442 | __netif_tx_lock_bh(txq); | 3441 | __netif_tx_lock_bh(txq); |
| 3443 | if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq))) | 3442 | atomic_inc(&(pkt_dev->skb->users)); |
| 3444 | pkt_dev->last_ok = 0; | ||
| 3445 | else { | ||
| 3446 | atomic_inc(&(pkt_dev->skb->users)); | ||
| 3447 | 3443 | ||
| 3448 | retry_now: | 3444 | if (unlikely(netif_tx_queue_stopped(txq) || netif_tx_queue_frozen(txq))) |
| 3445 | ret = NETDEV_TX_BUSY; | ||
| 3446 | else | ||
| 3449 | ret = (*xmit)(pkt_dev->skb, odev); | 3447 | ret = (*xmit)(pkt_dev->skb, odev); |
| 3450 | switch (ret) { | 3448 | |
| 3451 | case NETDEV_TX_OK: | 3449 | switch (ret) { |
| 3452 | txq_trans_update(txq); | 3450 | case NETDEV_TX_OK: |
| 3453 | pkt_dev->last_ok = 1; | 3451 | txq_trans_update(txq); |
| 3454 | pkt_dev->sofar++; | 3452 | pkt_dev->last_ok = 1; |
| 3455 | pkt_dev->seq_num++; | 3453 | pkt_dev->sofar++; |
| 3456 | pkt_dev->tx_bytes += pkt_dev->cur_pkt_size; | 3454 | pkt_dev->seq_num++; |
| 3457 | break; | 3455 | pkt_dev->tx_bytes += pkt_dev->cur_pkt_size; |
| 3458 | case NETDEV_TX_LOCKED: | 3456 | break; |
| 3459 | cpu_relax(); | 3457 | default: /* Drivers are not supposed to return other values! */ |
| 3460 | goto retry_now; | 3458 | if (net_ratelimit()) |
| 3461 | default: /* Drivers are not supposed to return other values! */ | 3459 | pr_info("pktgen: %s xmit error: %d\n", |
| 3462 | if (net_ratelimit()) | 3460 | odev->name, ret); |
| 3463 | pr_info("pktgen: %s xmit error: %d\n", | 3461 | pkt_dev->errors++; |
| 3464 | odev->name, ret); | 3462 | /* fallthru */ |
| 3465 | pkt_dev->errors++; | 3463 | case NETDEV_TX_LOCKED: |
| 3466 | /* fallthru */ | 3464 | case NETDEV_TX_BUSY: |
| 3467 | case NETDEV_TX_BUSY: | 3465 | /* Retry it next time */ |
| 3468 | /* Retry it next time */ | 3466 | atomic_dec(&(pkt_dev->skb->users)); |
| 3469 | atomic_dec(&(pkt_dev->skb->users)); | 3467 | pkt_dev->last_ok = 0; |
| 3470 | pkt_dev->last_ok = 0; | ||
| 3471 | } | ||
| 3472 | |||
| 3473 | if (pkt_dev->delay) | ||
| 3474 | pkt_dev->next_tx = ktime_add_ns(ktime_now(), | ||
| 3475 | pkt_dev->delay); | ||
| 3476 | } | 3468 | } |
| 3477 | __netif_tx_unlock_bh(txq); | 3469 | __netif_tx_unlock_bh(txq); |
| 3478 | 3470 | ||
| 3479 | /* If pkt_dev->count is zero, then run forever */ | 3471 | /* If pkt_dev->count is zero, then run forever */ |
| 3480 | if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { | 3472 | if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { |
| 3481 | while (atomic_read(&(pkt_dev->skb->users)) != 1) { | 3473 | pktgen_wait_for_skb(pkt_dev); |
| 3482 | if (signal_pending(current)) | ||
| 3483 | break; | ||
| 3484 | idle(pkt_dev); | ||
| 3485 | } | ||
| 3486 | 3474 | ||
| 3487 | /* Done with this */ | 3475 | /* Done with this */ |
| 3488 | pktgen_stop_device(pkt_dev); | 3476 | pktgen_stop_device(pkt_dev); |
| @@ -3515,20 +3503,24 @@ static int pktgen_thread_worker(void *arg) | |||
| 3515 | while (!kthread_should_stop()) { | 3503 | while (!kthread_should_stop()) { |
| 3516 | pkt_dev = next_to_run(t); | 3504 | pkt_dev = next_to_run(t); |
| 3517 | 3505 | ||
| 3518 | if (!pkt_dev && | 3506 | if (unlikely(!pkt_dev && t->control == 0)) { |
| 3519 | (t->control & (T_STOP | T_RUN | T_REMDEVALL | T_REMDEV)) | 3507 | wait_event_interruptible_timeout(t->queue, |
| 3520 | == 0) { | 3508 | t->control != 0, |
| 3521 | prepare_to_wait(&(t->queue), &wait, | 3509 | HZ/10); |
| 3522 | TASK_INTERRUPTIBLE); | 3510 | continue; |
| 3523 | schedule_timeout(HZ / 10); | ||
| 3524 | finish_wait(&(t->queue), &wait); | ||
| 3525 | } | 3511 | } |
| 3526 | 3512 | ||
| 3527 | __set_current_state(TASK_RUNNING); | 3513 | __set_current_state(TASK_RUNNING); |
| 3528 | 3514 | ||
| 3529 | if (pkt_dev) | 3515 | if (likely(pkt_dev)) { |
| 3530 | pktgen_xmit(pkt_dev); | 3516 | pktgen_xmit(pkt_dev); |
| 3531 | 3517 | ||
| 3518 | if (need_resched()) | ||
| 3519 | pktgen_resched(pkt_dev); | ||
| 3520 | else | ||
| 3521 | cpu_relax(); | ||
| 3522 | } | ||
| 3523 | |||
| 3532 | if (t->control & T_STOP) { | 3524 | if (t->control & T_STOP) { |
| 3533 | pktgen_stop(t); | 3525 | pktgen_stop(t); |
| 3534 | t->control &= ~(T_STOP); | 3526 | t->control &= ~(T_STOP); |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index d9645c94a067..41ada9904d31 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
| @@ -66,10 +66,7 @@ | |||
| 66 | solution, but it supposes maintaing new variable in ALL | 66 | solution, but it supposes maintaing new variable in ALL |
| 67 | skb, even if no tunneling is used. | 67 | skb, even if no tunneling is used. |
| 68 | 68 | ||
| 69 | Current solution: t->recursion lock breaks dead loops. It looks | 69 | Current solution: HARD_TX_LOCK lock breaks dead loops. |
| 70 | like dev->tbusy flag, but I preferred new variable, because | ||
| 71 | the semantics is different. One day, when hard_start_xmit | ||
| 72 | will be multithreaded we will have to use skb->encapsulation. | ||
| 73 | 70 | ||
| 74 | 71 | ||
| 75 | 72 | ||
| @@ -678,11 +675,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
| 678 | __be32 dst; | 675 | __be32 dst; |
| 679 | int mtu; | 676 | int mtu; |
| 680 | 677 | ||
| 681 | if (tunnel->recursion++) { | ||
| 682 | stats->collisions++; | ||
| 683 | goto tx_error; | ||
| 684 | } | ||
| 685 | |||
| 686 | if (dev->type == ARPHRD_ETHER) | 678 | if (dev->type == ARPHRD_ETHER) |
| 687 | IPCB(skb)->flags = 0; | 679 | IPCB(skb)->flags = 0; |
| 688 | 680 | ||
| @@ -820,7 +812,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
| 820 | ip_rt_put(rt); | 812 | ip_rt_put(rt); |
| 821 | stats->tx_dropped++; | 813 | stats->tx_dropped++; |
| 822 | dev_kfree_skb(skb); | 814 | dev_kfree_skb(skb); |
| 823 | tunnel->recursion--; | ||
| 824 | return NETDEV_TX_OK; | 815 | return NETDEV_TX_OK; |
| 825 | } | 816 | } |
| 826 | if (skb->sk) | 817 | if (skb->sk) |
| @@ -888,7 +879,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
| 888 | nf_reset(skb); | 879 | nf_reset(skb); |
| 889 | 880 | ||
| 890 | IPTUNNEL_XMIT(); | 881 | IPTUNNEL_XMIT(); |
| 891 | tunnel->recursion--; | ||
| 892 | return NETDEV_TX_OK; | 882 | return NETDEV_TX_OK; |
| 893 | 883 | ||
| 894 | tx_error_icmp: | 884 | tx_error_icmp: |
| @@ -897,7 +887,6 @@ tx_error_icmp: | |||
| 897 | tx_error: | 887 | tx_error: |
| 898 | stats->tx_errors++; | 888 | stats->tx_errors++; |
| 899 | dev_kfree_skb(skb); | 889 | dev_kfree_skb(skb); |
| 900 | tunnel->recursion--; | ||
| 901 | return NETDEV_TX_OK; | 890 | return NETDEV_TX_OK; |
| 902 | } | 891 | } |
| 903 | 892 | ||
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index fc7993e9061f..5a0693576e82 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
| @@ -611,6 +611,9 @@ static int do_ip_setsockopt(struct sock *sk, int level, | |||
| 611 | * Check the arguments are allowable | 611 | * Check the arguments are allowable |
| 612 | */ | 612 | */ |
| 613 | 613 | ||
| 614 | if (optlen < sizeof(struct in_addr)) | ||
| 615 | goto e_inval; | ||
| 616 | |||
| 614 | err = -EFAULT; | 617 | err = -EFAULT; |
| 615 | if (optlen >= sizeof(struct ip_mreqn)) { | 618 | if (optlen >= sizeof(struct ip_mreqn)) { |
| 616 | if (copy_from_user(&mreq, optval, sizeof(mreq))) | 619 | if (copy_from_user(&mreq, optval, sizeof(mreq))) |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 62548cb0923c..08ccd344de7a 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
| @@ -402,11 +402,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 402 | __be32 dst = tiph->daddr; | 402 | __be32 dst = tiph->daddr; |
| 403 | int mtu; | 403 | int mtu; |
| 404 | 404 | ||
| 405 | if (tunnel->recursion++) { | ||
| 406 | stats->collisions++; | ||
| 407 | goto tx_error; | ||
| 408 | } | ||
| 409 | |||
| 410 | if (skb->protocol != htons(ETH_P_IP)) | 405 | if (skb->protocol != htons(ETH_P_IP)) |
| 411 | goto tx_error; | 406 | goto tx_error; |
| 412 | 407 | ||
| @@ -485,7 +480,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 485 | ip_rt_put(rt); | 480 | ip_rt_put(rt); |
| 486 | stats->tx_dropped++; | 481 | stats->tx_dropped++; |
| 487 | dev_kfree_skb(skb); | 482 | dev_kfree_skb(skb); |
| 488 | tunnel->recursion--; | ||
| 489 | return NETDEV_TX_OK; | 483 | return NETDEV_TX_OK; |
| 490 | } | 484 | } |
| 491 | if (skb->sk) | 485 | if (skb->sk) |
| @@ -523,7 +517,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 523 | nf_reset(skb); | 517 | nf_reset(skb); |
| 524 | 518 | ||
| 525 | IPTUNNEL_XMIT(); | 519 | IPTUNNEL_XMIT(); |
| 526 | tunnel->recursion--; | ||
| 527 | return NETDEV_TX_OK; | 520 | return NETDEV_TX_OK; |
| 528 | 521 | ||
| 529 | tx_error_icmp: | 522 | tx_error_icmp: |
| @@ -531,7 +524,6 @@ tx_error_icmp: | |||
| 531 | tx_error: | 524 | tx_error: |
| 532 | stats->tx_errors++; | 525 | stats->tx_errors++; |
| 533 | dev_kfree_skb(skb); | 526 | dev_kfree_skb(skb); |
| 534 | tunnel->recursion--; | ||
| 535 | return NETDEV_TX_OK; | 527 | return NETDEV_TX_OK; |
| 536 | } | 528 | } |
| 537 | 529 | ||
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 7d25bbe32110..c595bbe1ed99 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
| @@ -1043,11 +1043,6 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1043 | struct net_device_stats *stats = &t->dev->stats; | 1043 | struct net_device_stats *stats = &t->dev->stats; |
| 1044 | int ret; | 1044 | int ret; |
| 1045 | 1045 | ||
| 1046 | if (t->recursion++) { | ||
| 1047 | stats->collisions++; | ||
| 1048 | goto tx_err; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | switch (skb->protocol) { | 1046 | switch (skb->protocol) { |
| 1052 | case htons(ETH_P_IP): | 1047 | case htons(ETH_P_IP): |
| 1053 | ret = ip4ip6_tnl_xmit(skb, dev); | 1048 | ret = ip4ip6_tnl_xmit(skb, dev); |
| @@ -1062,14 +1057,12 @@ ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1062 | if (ret < 0) | 1057 | if (ret < 0) |
| 1063 | goto tx_err; | 1058 | goto tx_err; |
| 1064 | 1059 | ||
| 1065 | t->recursion--; | ||
| 1066 | return NETDEV_TX_OK; | 1060 | return NETDEV_TX_OK; |
| 1067 | 1061 | ||
| 1068 | tx_err: | 1062 | tx_err: |
| 1069 | stats->tx_errors++; | 1063 | stats->tx_errors++; |
| 1070 | stats->tx_dropped++; | 1064 | stats->tx_dropped++; |
| 1071 | kfree_skb(skb); | 1065 | kfree_skb(skb); |
| 1072 | t->recursion--; | ||
| 1073 | return NETDEV_TX_OK; | 1066 | return NETDEV_TX_OK; |
| 1074 | } | 1067 | } |
| 1075 | 1068 | ||
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 0ae4f6448187..fcb539628847 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -626,11 +626,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
| 626 | struct in6_addr *addr6; | 626 | struct in6_addr *addr6; |
| 627 | int addr_type; | 627 | int addr_type; |
| 628 | 628 | ||
| 629 | if (tunnel->recursion++) { | ||
| 630 | stats->collisions++; | ||
| 631 | goto tx_error; | ||
| 632 | } | ||
| 633 | |||
| 634 | if (skb->protocol != htons(ETH_P_IPV6)) | 629 | if (skb->protocol != htons(ETH_P_IPV6)) |
| 635 | goto tx_error; | 630 | goto tx_error; |
| 636 | 631 | ||
| @@ -753,7 +748,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
| 753 | ip_rt_put(rt); | 748 | ip_rt_put(rt); |
| 754 | stats->tx_dropped++; | 749 | stats->tx_dropped++; |
| 755 | dev_kfree_skb(skb); | 750 | dev_kfree_skb(skb); |
| 756 | tunnel->recursion--; | ||
| 757 | return NETDEV_TX_OK; | 751 | return NETDEV_TX_OK; |
| 758 | } | 752 | } |
| 759 | if (skb->sk) | 753 | if (skb->sk) |
| @@ -794,7 +788,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
| 794 | nf_reset(skb); | 788 | nf_reset(skb); |
| 795 | 789 | ||
| 796 | IPTUNNEL_XMIT(); | 790 | IPTUNNEL_XMIT(); |
| 797 | tunnel->recursion--; | ||
| 798 | return NETDEV_TX_OK; | 791 | return NETDEV_TX_OK; |
| 799 | 792 | ||
| 800 | tx_error_icmp: | 793 | tx_error_icmp: |
| @@ -802,7 +795,6 @@ tx_error_icmp: | |||
| 802 | tx_error: | 795 | tx_error: |
| 803 | stats->tx_errors++; | 796 | stats->tx_errors++; |
| 804 | dev_kfree_skb(skb); | 797 | dev_kfree_skb(skb); |
| 805 | tunnel->recursion--; | ||
| 806 | return NETDEV_TX_OK; | 798 | return NETDEV_TX_OK; |
| 807 | } | 799 | } |
| 808 | 800 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 039901109fa1..71e10cabf811 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
| @@ -90,8 +90,8 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
| 90 | bss->dtim_period = tim_ie->dtim_period; | 90 | bss->dtim_period = tim_ie->dtim_period; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | /* set default value for buggy APs */ | 93 | /* set default value for buggy AP/no TIM element */ |
| 94 | if (!elems->tim || bss->dtim_period == 0) | 94 | if (bss->dtim_period == 0) |
| 95 | bss->dtim_period = 1; | 95 | bss->dtim_period = 1; |
| 96 | 96 | ||
| 97 | bss->supp_rates_len = 0; | 97 | bss->supp_rates_len = 0; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 55180b99562a..a4bafbf15097 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -1609,6 +1609,16 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups) | |||
| 1609 | return err; | 1609 | return err; |
| 1610 | } | 1610 | } |
| 1611 | 1611 | ||
| 1612 | void __netlink_clear_multicast_users(struct sock *ksk, unsigned int group) | ||
| 1613 | { | ||
| 1614 | struct sock *sk; | ||
| 1615 | struct hlist_node *node; | ||
| 1616 | struct netlink_table *tbl = &nl_table[ksk->sk_protocol]; | ||
| 1617 | |||
| 1618 | sk_for_each_bound(sk, node, &tbl->mc_list) | ||
| 1619 | netlink_update_socket_mc(nlk_sk(sk), group, 0); | ||
| 1620 | } | ||
| 1621 | |||
| 1612 | /** | 1622 | /** |
| 1613 | * netlink_clear_multicast_users - kick off multicast listeners | 1623 | * netlink_clear_multicast_users - kick off multicast listeners |
| 1614 | * | 1624 | * |
| @@ -1619,15 +1629,8 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups) | |||
| 1619 | */ | 1629 | */ |
| 1620 | void netlink_clear_multicast_users(struct sock *ksk, unsigned int group) | 1630 | void netlink_clear_multicast_users(struct sock *ksk, unsigned int group) |
| 1621 | { | 1631 | { |
| 1622 | struct sock *sk; | ||
| 1623 | struct hlist_node *node; | ||
| 1624 | struct netlink_table *tbl = &nl_table[ksk->sk_protocol]; | ||
| 1625 | |||
| 1626 | netlink_table_grab(); | 1632 | netlink_table_grab(); |
| 1627 | 1633 | __netlink_clear_multicast_users(ksk, group); | |
| 1628 | sk_for_each_bound(sk, node, &tbl->mc_list) | ||
| 1629 | netlink_update_socket_mc(nlk_sk(sk), group, 0); | ||
| 1630 | |||
| 1631 | netlink_table_ungrab(); | 1634 | netlink_table_ungrab(); |
| 1632 | } | 1635 | } |
| 1633 | 1636 | ||
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 566941e03363..44ff3f3810fa 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
| @@ -220,10 +220,12 @@ static void __genl_unregister_mc_group(struct genl_family *family, | |||
| 220 | struct net *net; | 220 | struct net *net; |
| 221 | BUG_ON(grp->family != family); | 221 | BUG_ON(grp->family != family); |
| 222 | 222 | ||
| 223 | netlink_table_grab(); | ||
| 223 | rcu_read_lock(); | 224 | rcu_read_lock(); |
| 224 | for_each_net_rcu(net) | 225 | for_each_net_rcu(net) |
| 225 | netlink_clear_multicast_users(net->genl_sock, grp->id); | 226 | __netlink_clear_multicast_users(net->genl_sock, grp->id); |
| 226 | rcu_read_unlock(); | 227 | rcu_read_unlock(); |
| 228 | netlink_table_ungrab(); | ||
| 227 | 229 | ||
| 228 | clear_bit(grp->id, mc_groups); | 230 | clear_bit(grp->id, mc_groups); |
| 229 | list_del(&grp->list); | 231 | list_del(&grp->list); |
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index a662e62a99cf..f60c0c2aacba 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c | |||
| @@ -168,6 +168,12 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev, | |||
| 168 | goto drop; | 168 | goto drop; |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | /* Broadcast sending is not implemented */ | ||
| 172 | if (pn_addr(dst) == PNADDR_BROADCAST) { | ||
| 173 | err = -EOPNOTSUPP; | ||
| 174 | goto drop; | ||
| 175 | } | ||
| 176 | |||
| 171 | skb_reset_transport_header(skb); | 177 | skb_reset_transport_header(skb); |
| 172 | WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */ | 178 | WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */ |
| 173 | skb_push(skb, sizeof(struct phonethdr)); | 179 | skb_push(skb, sizeof(struct phonethdr)); |
diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 7a4ee397d2f7..07aa9f08d5fb 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c | |||
| @@ -113,6 +113,8 @@ void pn_sock_unhash(struct sock *sk) | |||
| 113 | } | 113 | } |
| 114 | EXPORT_SYMBOL(pn_sock_unhash); | 114 | EXPORT_SYMBOL(pn_sock_unhash); |
| 115 | 115 | ||
| 116 | static DEFINE_MUTEX(port_mutex); | ||
| 117 | |||
| 116 | static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) | 118 | static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) |
| 117 | { | 119 | { |
| 118 | struct sock *sk = sock->sk; | 120 | struct sock *sk = sock->sk; |
| @@ -140,9 +142,11 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) | |||
| 140 | err = -EINVAL; /* attempt to rebind */ | 142 | err = -EINVAL; /* attempt to rebind */ |
| 141 | goto out; | 143 | goto out; |
| 142 | } | 144 | } |
| 145 | WARN_ON(sk_hashed(sk)); | ||
| 146 | mutex_lock(&port_mutex); | ||
| 143 | err = sk->sk_prot->get_port(sk, pn_port(handle)); | 147 | err = sk->sk_prot->get_port(sk, pn_port(handle)); |
| 144 | if (err) | 148 | if (err) |
| 145 | goto out; | 149 | goto out_port; |
| 146 | 150 | ||
| 147 | /* get_port() sets the port, bind() sets the address if applicable */ | 151 | /* get_port() sets the port, bind() sets the address if applicable */ |
| 148 | pn->sobject = pn_object(saddr, pn_port(pn->sobject)); | 152 | pn->sobject = pn_object(saddr, pn_port(pn->sobject)); |
| @@ -150,6 +154,8 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) | |||
| 150 | 154 | ||
| 151 | /* Enable RX on the socket */ | 155 | /* Enable RX on the socket */ |
| 152 | sk->sk_prot->hash(sk); | 156 | sk->sk_prot->hash(sk); |
| 157 | out_port: | ||
| 158 | mutex_unlock(&port_mutex); | ||
| 153 | out: | 159 | out: |
| 154 | release_sock(sk); | 160 | release_sock(sk); |
| 155 | return err; | 161 | return err; |
| @@ -357,8 +363,6 @@ const struct proto_ops phonet_stream_ops = { | |||
| 357 | }; | 363 | }; |
| 358 | EXPORT_SYMBOL(phonet_stream_ops); | 364 | EXPORT_SYMBOL(phonet_stream_ops); |
| 359 | 365 | ||
| 360 | static DEFINE_MUTEX(port_mutex); | ||
| 361 | |||
| 362 | /* allocate port for a socket */ | 366 | /* allocate port for a socket */ |
| 363 | int pn_sock_get_port(struct sock *sk, unsigned short sport) | 367 | int pn_sock_get_port(struct sock *sk, unsigned short sport) |
| 364 | { | 368 | { |
| @@ -370,9 +374,7 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport) | |||
| 370 | 374 | ||
| 371 | memset(&try_sa, 0, sizeof(struct sockaddr_pn)); | 375 | memset(&try_sa, 0, sizeof(struct sockaddr_pn)); |
| 372 | try_sa.spn_family = AF_PHONET; | 376 | try_sa.spn_family = AF_PHONET; |
| 373 | 377 | WARN_ON(!mutex_is_locked(&port_mutex)); | |
| 374 | mutex_lock(&port_mutex); | ||
| 375 | |||
| 376 | if (!sport) { | 378 | if (!sport) { |
| 377 | /* search free port */ | 379 | /* search free port */ |
| 378 | int port, pmin, pmax; | 380 | int port, pmin, pmax; |
| @@ -401,8 +403,6 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport) | |||
| 401 | else | 403 | else |
| 402 | sock_put(tmpsk); | 404 | sock_put(tmpsk); |
| 403 | } | 405 | } |
| 404 | mutex_unlock(&port_mutex); | ||
| 405 | |||
| 406 | /* the port must be in use already */ | 406 | /* the port must be in use already */ |
| 407 | return -EADDRINUSE; | 407 | return -EADDRINUSE; |
| 408 | 408 | ||
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index d16cd9ea4d00..bf725275eb8d 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
| @@ -26,11 +26,11 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | |||
| 26 | 26 | ||
| 27 | wdev->wext.connect.ie = wdev->wext.ie; | 27 | wdev->wext.connect.ie = wdev->wext.ie; |
| 28 | wdev->wext.connect.ie_len = wdev->wext.ie_len; | 28 | wdev->wext.connect.ie_len = wdev->wext.ie_len; |
| 29 | wdev->wext.connect.privacy = wdev->wext.default_key != -1; | ||
| 30 | 29 | ||
| 31 | if (wdev->wext.keys) { | 30 | if (wdev->wext.keys) { |
| 32 | wdev->wext.keys->def = wdev->wext.default_key; | 31 | wdev->wext.keys->def = wdev->wext.default_key; |
| 33 | wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key; | 32 | wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key; |
| 33 | wdev->wext.connect.privacy = true; | ||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | if (!wdev->wext.connect.ssid_len) | 36 | if (!wdev->wext.connect.ssid_len) |
