diff options
52 files changed, 545 insertions, 202 deletions
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index c909b7b7d5f1..d70abe77f737 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c | |||
| @@ -42,7 +42,8 @@ | |||
| 42 | #include <linux/swab.h> | 42 | #include <linux/swab.h> |
| 43 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
| 44 | 44 | ||
| 45 | #define VERSION "0.07" | 45 | #define VERSION "1.04" |
| 46 | #define DRIVER_VERSION 0x01 | ||
| 46 | #define PTAG "solos-pci" | 47 | #define PTAG "solos-pci" |
| 47 | 48 | ||
| 48 | #define CONFIG_RAM_SIZE 128 | 49 | #define CONFIG_RAM_SIZE 128 |
| @@ -56,16 +57,21 @@ | |||
| 56 | #define FLASH_BUSY 0x60 | 57 | #define FLASH_BUSY 0x60 |
| 57 | #define FPGA_MODE 0x5C | 58 | #define FPGA_MODE 0x5C |
| 58 | #define FLASH_MODE 0x58 | 59 | #define FLASH_MODE 0x58 |
| 60 | #define GPIO_STATUS 0x54 | ||
| 61 | #define DRIVER_VER 0x50 | ||
| 59 | #define TX_DMA_ADDR(port) (0x40 + (4 * (port))) | 62 | #define TX_DMA_ADDR(port) (0x40 + (4 * (port))) |
| 60 | #define RX_DMA_ADDR(port) (0x30 + (4 * (port))) | 63 | #define RX_DMA_ADDR(port) (0x30 + (4 * (port))) |
| 61 | 64 | ||
| 62 | #define DATA_RAM_SIZE 32768 | 65 | #define DATA_RAM_SIZE 32768 |
| 63 | #define BUF_SIZE 2048 | 66 | #define BUF_SIZE 2048 |
| 64 | #define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/ | 67 | #define OLD_BUF_SIZE 4096 /* For FPGA versions <= 2*/ |
| 65 | #define FPGA_PAGE 528 /* FPGA flash page size*/ | 68 | /* Old boards use ATMEL AD45DB161D flash */ |
| 66 | #define SOLOS_PAGE 512 /* Solos flash page size*/ | 69 | #define ATMEL_FPGA_PAGE 528 /* FPGA flash page size*/ |
| 67 | #define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/ | 70 | #define ATMEL_SOLOS_PAGE 512 /* Solos flash page size*/ |
| 68 | #define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/ | 71 | #define ATMEL_FPGA_BLOCK (ATMEL_FPGA_PAGE * 8) /* FPGA block size*/ |
| 72 | #define ATMEL_SOLOS_BLOCK (ATMEL_SOLOS_PAGE * 8) /* Solos block size*/ | ||
| 73 | /* Current boards use M25P/M25PE SPI flash */ | ||
| 74 | #define SPI_FLASH_BLOCK (256 * 64) | ||
| 69 | 75 | ||
| 70 | #define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2) | 76 | #define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2) |
| 71 | #define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size)) | 77 | #define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size)) |
| @@ -122,11 +128,14 @@ struct solos_card { | |||
| 122 | struct sk_buff_head cli_queue[4]; | 128 | struct sk_buff_head cli_queue[4]; |
| 123 | struct sk_buff *tx_skb[4]; | 129 | struct sk_buff *tx_skb[4]; |
| 124 | struct sk_buff *rx_skb[4]; | 130 | struct sk_buff *rx_skb[4]; |
| 131 | unsigned char *dma_bounce; | ||
| 125 | wait_queue_head_t param_wq; | 132 | wait_queue_head_t param_wq; |
| 126 | wait_queue_head_t fw_wq; | 133 | wait_queue_head_t fw_wq; |
| 127 | int using_dma; | 134 | int using_dma; |
| 135 | int dma_alignment; | ||
| 128 | int fpga_version; | 136 | int fpga_version; |
| 129 | int buffer_size; | 137 | int buffer_size; |
| 138 | int atmel_flash; | ||
| 130 | }; | 139 | }; |
| 131 | 140 | ||
| 132 | 141 | ||
| @@ -451,7 +460,6 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr, | |||
| 451 | 460 | ||
| 452 | len = skb->len; | 461 | len = skb->len; |
| 453 | memcpy(buf, skb->data, len); | 462 | memcpy(buf, skb->data, len); |
| 454 | dev_dbg(&card->dev->dev, "len: %d\n", len); | ||
| 455 | 463 | ||
| 456 | kfree_skb(skb); | 464 | kfree_skb(skb); |
| 457 | return len; | 465 | return len; |
| @@ -498,6 +506,78 @@ static ssize_t console_store(struct device *dev, struct device_attribute *attr, | |||
| 498 | return err?:count; | 506 | return err?:count; |
| 499 | } | 507 | } |
| 500 | 508 | ||
| 509 | struct geos_gpio_attr { | ||
| 510 | struct device_attribute attr; | ||
| 511 | int offset; | ||
| 512 | }; | ||
| 513 | |||
| 514 | #define SOLOS_GPIO_ATTR(_name, _mode, _show, _store, _offset) \ | ||
| 515 | struct geos_gpio_attr gpio_attr_##_name = { \ | ||
| 516 | .attr = __ATTR(_name, _mode, _show, _store), \ | ||
| 517 | .offset = _offset } | ||
| 518 | |||
| 519 | static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr, | ||
| 520 | const char *buf, size_t count) | ||
| 521 | { | ||
| 522 | struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); | ||
| 523 | struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); | ||
| 524 | struct solos_card *card = pci_get_drvdata(pdev); | ||
| 525 | uint32_t data32; | ||
| 526 | |||
| 527 | if (count != 1 && (count != 2 || buf[1] != '\n')) | ||
| 528 | return -EINVAL; | ||
| 529 | |||
| 530 | spin_lock_irq(&card->param_queue_lock); | ||
| 531 | data32 = ioread32(card->config_regs + GPIO_STATUS); | ||
| 532 | if (buf[0] == '1') { | ||
| 533 | data32 |= 1 << gattr->offset; | ||
| 534 | iowrite32(data32, card->config_regs + GPIO_STATUS); | ||
| 535 | } else if (buf[0] == '0') { | ||
| 536 | data32 &= ~(1 << gattr->offset); | ||
| 537 | iowrite32(data32, card->config_regs + GPIO_STATUS); | ||
| 538 | } else { | ||
| 539 | count = -EINVAL; | ||
| 540 | } | ||
| 541 | spin_lock_irq(&card->param_queue_lock); | ||
| 542 | return count; | ||
| 543 | } | ||
| 544 | |||
| 545 | static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr, | ||
| 546 | char *buf) | ||
| 547 | { | ||
| 548 | struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); | ||
| 549 | struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); | ||
| 550 | struct solos_card *card = pci_get_drvdata(pdev); | ||
| 551 | uint32_t data32; | ||
| 552 | |||
| 553 | data32 = ioread32(card->config_regs + GPIO_STATUS); | ||
| 554 | data32 = (data32 >> gattr->offset) & 1; | ||
| 555 | |||
| 556 | return sprintf(buf, "%d\n", data32); | ||
| 557 | } | ||
| 558 | |||
| 559 | static ssize_t hardware_show(struct device *dev, struct device_attribute *attr, | ||
| 560 | char *buf) | ||
| 561 | { | ||
| 562 | struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); | ||
| 563 | struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr); | ||
| 564 | struct solos_card *card = pci_get_drvdata(pdev); | ||
| 565 | uint32_t data32; | ||
| 566 | |||
| 567 | data32 = ioread32(card->config_regs + GPIO_STATUS); | ||
| 568 | switch (gattr->offset) { | ||
| 569 | case 0: | ||
| 570 | /* HardwareVersion */ | ||
| 571 | data32 = data32 & 0x1F; | ||
| 572 | break; | ||
| 573 | case 1: | ||
| 574 | /* HardwareVariant */ | ||
| 575 | data32 = (data32 >> 5) & 0x0F; | ||
| 576 | break; | ||
| 577 | } | ||
| 578 | return sprintf(buf, "%d\n", data32); | ||
| 579 | } | ||
| 580 | |||
| 501 | static DEVICE_ATTR(console, 0644, console_show, console_store); | 581 | static DEVICE_ATTR(console, 0644, console_show, console_store); |
| 502 | 582 | ||
| 503 | 583 | ||
| @@ -506,6 +586,14 @@ static DEVICE_ATTR(console, 0644, console_show, console_store); | |||
| 506 | 586 | ||
| 507 | #include "solos-attrlist.c" | 587 | #include "solos-attrlist.c" |
| 508 | 588 | ||
| 589 | static SOLOS_GPIO_ATTR(GPIO1, 0644, geos_gpio_show, geos_gpio_store, 9); | ||
| 590 | static SOLOS_GPIO_ATTR(GPIO2, 0644, geos_gpio_show, geos_gpio_store, 10); | ||
| 591 | static SOLOS_GPIO_ATTR(GPIO3, 0644, geos_gpio_show, geos_gpio_store, 11); | ||
| 592 | static SOLOS_GPIO_ATTR(GPIO4, 0644, geos_gpio_show, geos_gpio_store, 12); | ||
| 593 | static SOLOS_GPIO_ATTR(GPIO5, 0644, geos_gpio_show, geos_gpio_store, 13); | ||
| 594 | static SOLOS_GPIO_ATTR(PushButton, 0444, geos_gpio_show, NULL, 14); | ||
| 595 | static SOLOS_GPIO_ATTR(HardwareVersion, 0444, hardware_show, NULL, 0); | ||
| 596 | static SOLOS_GPIO_ATTR(HardwareVariant, 0444, hardware_show, NULL, 1); | ||
| 509 | #undef SOLOS_ATTR_RO | 597 | #undef SOLOS_ATTR_RO |
| 510 | #undef SOLOS_ATTR_RW | 598 | #undef SOLOS_ATTR_RW |
| 511 | 599 | ||
| @@ -522,6 +610,23 @@ static struct attribute_group solos_attr_group = { | |||
| 522 | .name = "parameters", | 610 | .name = "parameters", |
| 523 | }; | 611 | }; |
| 524 | 612 | ||
| 613 | static struct attribute *gpio_attrs[] = { | ||
| 614 | &gpio_attr_GPIO1.attr.attr, | ||
| 615 | &gpio_attr_GPIO2.attr.attr, | ||
| 616 | &gpio_attr_GPIO3.attr.attr, | ||
| 617 | &gpio_attr_GPIO4.attr.attr, | ||
| 618 | &gpio_attr_GPIO5.attr.attr, | ||
| 619 | &gpio_attr_PushButton.attr.attr, | ||
| 620 | &gpio_attr_HardwareVersion.attr.attr, | ||
| 621 | &gpio_attr_HardwareVariant.attr.attr, | ||
| 622 | NULL | ||
| 623 | }; | ||
| 624 | |||
| 625 | static struct attribute_group gpio_attr_group = { | ||
| 626 | .attrs = gpio_attrs, | ||
| 627 | .name = "gpio", | ||
| 628 | }; | ||
| 629 | |||
| 525 | static int flash_upgrade(struct solos_card *card, int chip) | 630 | static int flash_upgrade(struct solos_card *card, int chip) |
| 526 | { | 631 | { |
| 527 | const struct firmware *fw; | 632 | const struct firmware *fw; |
| @@ -533,16 +638,25 @@ static int flash_upgrade(struct solos_card *card, int chip) | |||
| 533 | switch (chip) { | 638 | switch (chip) { |
| 534 | case 0: | 639 | case 0: |
| 535 | fw_name = "solos-FPGA.bin"; | 640 | fw_name = "solos-FPGA.bin"; |
| 536 | blocksize = FPGA_BLOCK; | 641 | if (card->atmel_flash) |
| 642 | blocksize = ATMEL_FPGA_BLOCK; | ||
| 643 | else | ||
| 644 | blocksize = SPI_FLASH_BLOCK; | ||
| 537 | break; | 645 | break; |
| 538 | case 1: | 646 | case 1: |
| 539 | fw_name = "solos-Firmware.bin"; | 647 | fw_name = "solos-Firmware.bin"; |
| 540 | blocksize = SOLOS_BLOCK; | 648 | if (card->atmel_flash) |
| 649 | blocksize = ATMEL_SOLOS_BLOCK; | ||
| 650 | else | ||
| 651 | blocksize = SPI_FLASH_BLOCK; | ||
| 541 | break; | 652 | break; |
| 542 | case 2: | 653 | case 2: |
| 543 | if (card->fpga_version > LEGACY_BUFFERS){ | 654 | if (card->fpga_version > LEGACY_BUFFERS){ |
| 544 | fw_name = "solos-db-FPGA.bin"; | 655 | fw_name = "solos-db-FPGA.bin"; |
| 545 | blocksize = FPGA_BLOCK; | 656 | if (card->atmel_flash) |
| 657 | blocksize = ATMEL_FPGA_BLOCK; | ||
| 658 | else | ||
| 659 | blocksize = SPI_FLASH_BLOCK; | ||
| 546 | } else { | 660 | } else { |
| 547 | dev_info(&card->dev->dev, "FPGA version doesn't support" | 661 | dev_info(&card->dev->dev, "FPGA version doesn't support" |
| 548 | " daughter board upgrades\n"); | 662 | " daughter board upgrades\n"); |
| @@ -552,7 +666,10 @@ static int flash_upgrade(struct solos_card *card, int chip) | |||
| 552 | case 3: | 666 | case 3: |
| 553 | if (card->fpga_version > LEGACY_BUFFERS){ | 667 | if (card->fpga_version > LEGACY_BUFFERS){ |
| 554 | fw_name = "solos-Firmware.bin"; | 668 | fw_name = "solos-Firmware.bin"; |
| 555 | blocksize = SOLOS_BLOCK; | 669 | if (card->atmel_flash) |
| 670 | blocksize = ATMEL_SOLOS_BLOCK; | ||
| 671 | else | ||
| 672 | blocksize = SPI_FLASH_BLOCK; | ||
| 556 | } else { | 673 | } else { |
| 557 | dev_info(&card->dev->dev, "FPGA version doesn't support" | 674 | dev_info(&card->dev->dev, "FPGA version doesn't support" |
| 558 | " daughter board upgrades\n"); | 675 | " daughter board upgrades\n"); |
| @@ -568,6 +685,9 @@ static int flash_upgrade(struct solos_card *card, int chip) | |||
| 568 | 685 | ||
| 569 | dev_info(&card->dev->dev, "Flash upgrade starting\n"); | 686 | dev_info(&card->dev->dev, "Flash upgrade starting\n"); |
| 570 | 687 | ||
| 688 | /* New FPGAs require driver version before permitting flash upgrades */ | ||
| 689 | iowrite32(DRIVER_VERSION, card->config_regs + DRIVER_VER); | ||
| 690 | |||
| 571 | numblocks = fw->size / blocksize; | 691 | numblocks = fw->size / blocksize; |
| 572 | dev_info(&card->dev->dev, "Firmware size: %zd\n", fw->size); | 692 | dev_info(&card->dev->dev, "Firmware size: %zd\n", fw->size); |
| 573 | dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks); | 693 | dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks); |
| @@ -597,9 +717,13 @@ static int flash_upgrade(struct solos_card *card, int chip) | |||
| 597 | /* dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n"); */ | 717 | /* dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n"); */ |
| 598 | iowrite32(((chip * 2) + 1), card->config_regs + FLASH_MODE); | 718 | iowrite32(((chip * 2) + 1), card->config_regs + FLASH_MODE); |
| 599 | 719 | ||
| 600 | /* Copy block to buffer, swapping each 16 bits */ | 720 | /* Copy block to buffer, swapping each 16 bits for Atmel flash */ |
| 601 | for(i = 0; i < blocksize; i += 4) { | 721 | for(i = 0; i < blocksize; i += 4) { |
| 602 | uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i)); | 722 | uint32_t word; |
| 723 | if (card->atmel_flash) | ||
| 724 | word = swahb32p((uint32_t *)(fw->data + offset + i)); | ||
| 725 | else | ||
| 726 | word = *(uint32_t *)(fw->data + offset + i); | ||
| 603 | if(card->fpga_version > LEGACY_BUFFERS) | 727 | if(card->fpga_version > LEGACY_BUFFERS) |
| 604 | iowrite32(word, FLASH_BUF + i); | 728 | iowrite32(word, FLASH_BUF + i); |
| 605 | else | 729 | else |
| @@ -961,7 +1085,12 @@ static uint32_t fpga_tx(struct solos_card *card) | |||
| 961 | tx_started |= 1 << port; | 1085 | tx_started |= 1 << port; |
| 962 | oldskb = skb; /* We're done with this skb already */ | 1086 | oldskb = skb; /* We're done with this skb already */ |
| 963 | } else if (skb && card->using_dma) { | 1087 | } else if (skb && card->using_dma) { |
| 964 | SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data, | 1088 | unsigned char *data = skb->data; |
| 1089 | if ((unsigned long)data & card->dma_alignment) { | ||
| 1090 | data = card->dma_bounce + (BUF_SIZE * port); | ||
| 1091 | memcpy(data, skb->data, skb->len); | ||
| 1092 | } | ||
| 1093 | SKB_CB(skb)->dma_addr = pci_map_single(card->dev, data, | ||
| 965 | skb->len, PCI_DMA_TODEVICE); | 1094 | skb->len, PCI_DMA_TODEVICE); |
| 966 | card->tx_skb[port] = skb; | 1095 | card->tx_skb[port] = skb; |
| 967 | iowrite32(SKB_CB(skb)->dma_addr, | 1096 | iowrite32(SKB_CB(skb)->dma_addr, |
| @@ -1133,18 +1262,33 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 1133 | db_fpga_upgrade = db_firmware_upgrade = 0; | 1262 | db_fpga_upgrade = db_firmware_upgrade = 0; |
| 1134 | } | 1263 | } |
| 1135 | 1264 | ||
| 1265 | /* Stopped using Atmel flash after 0.03-38 */ | ||
| 1266 | if (fpga_ver < 39) | ||
| 1267 | card->atmel_flash = 1; | ||
| 1268 | else | ||
| 1269 | card->atmel_flash = 0; | ||
| 1270 | |||
| 1271 | data32 = ioread32(card->config_regs + PORTS); | ||
| 1272 | card->nr_ports = (data32 & 0x000000FF); | ||
| 1273 | |||
| 1136 | if (card->fpga_version >= DMA_SUPPORTED) { | 1274 | if (card->fpga_version >= DMA_SUPPORTED) { |
| 1137 | pci_set_master(dev); | 1275 | pci_set_master(dev); |
| 1138 | card->using_dma = 1; | 1276 | card->using_dma = 1; |
| 1277 | if (1) { /* All known FPGA versions so far */ | ||
| 1278 | card->dma_alignment = 3; | ||
| 1279 | card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL); | ||
| 1280 | if (!card->dma_bounce) { | ||
| 1281 | dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n"); | ||
| 1282 | /* Fallback to MMIO doesn't work */ | ||
| 1283 | goto out_unmap_both; | ||
| 1284 | } | ||
| 1285 | } | ||
| 1139 | } else { | 1286 | } else { |
| 1140 | card->using_dma = 0; | 1287 | card->using_dma = 0; |
| 1141 | /* Set RX empty flag for all ports */ | 1288 | /* Set RX empty flag for all ports */ |
| 1142 | iowrite32(0xF0, card->config_regs + FLAGS_ADDR); | 1289 | iowrite32(0xF0, card->config_regs + FLAGS_ADDR); |
| 1143 | } | 1290 | } |
| 1144 | 1291 | ||
| 1145 | data32 = ioread32(card->config_regs + PORTS); | ||
| 1146 | card->nr_ports = (data32 & 0x000000FF); | ||
| 1147 | |||
| 1148 | pci_set_drvdata(dev, card); | 1292 | pci_set_drvdata(dev, card); |
| 1149 | 1293 | ||
| 1150 | tasklet_init(&card->tlet, solos_bh, (unsigned long)card); | 1294 | tasklet_init(&card->tlet, solos_bh, (unsigned long)card); |
| @@ -1179,6 +1323,10 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 1179 | if (err) | 1323 | if (err) |
| 1180 | goto out_free_irq; | 1324 | goto out_free_irq; |
| 1181 | 1325 | ||
| 1326 | if (card->fpga_version >= DMA_SUPPORTED && | ||
| 1327 | sysfs_create_group(&card->dev->dev.kobj, &gpio_attr_group)) | ||
| 1328 | dev_err(&card->dev->dev, "Could not register parameter group for GPIOs\n"); | ||
| 1329 | |||
| 1182 | return 0; | 1330 | return 0; |
| 1183 | 1331 | ||
| 1184 | out_free_irq: | 1332 | out_free_irq: |
| @@ -1187,6 +1335,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 1187 | tasklet_kill(&card->tlet); | 1335 | tasklet_kill(&card->tlet); |
| 1188 | 1336 | ||
| 1189 | out_unmap_both: | 1337 | out_unmap_both: |
| 1338 | kfree(card->dma_bounce); | ||
| 1190 | pci_set_drvdata(dev, NULL); | 1339 | pci_set_drvdata(dev, NULL); |
| 1191 | pci_iounmap(dev, card->buffers); | 1340 | pci_iounmap(dev, card->buffers); |
| 1192 | out_unmap_config: | 1341 | out_unmap_config: |
| @@ -1289,11 +1438,16 @@ static void fpga_remove(struct pci_dev *dev) | |||
| 1289 | iowrite32(1, card->config_regs + FPGA_MODE); | 1438 | iowrite32(1, card->config_regs + FPGA_MODE); |
| 1290 | (void)ioread32(card->config_regs + FPGA_MODE); | 1439 | (void)ioread32(card->config_regs + FPGA_MODE); |
| 1291 | 1440 | ||
| 1441 | if (card->fpga_version >= DMA_SUPPORTED) | ||
| 1442 | sysfs_remove_group(&card->dev->dev.kobj, &gpio_attr_group); | ||
| 1443 | |||
| 1292 | atm_remove(card); | 1444 | atm_remove(card); |
| 1293 | 1445 | ||
| 1294 | free_irq(dev->irq, card); | 1446 | free_irq(dev->irq, card); |
| 1295 | tasklet_kill(&card->tlet); | 1447 | tasklet_kill(&card->tlet); |
| 1296 | 1448 | ||
| 1449 | kfree(card->dma_bounce); | ||
| 1450 | |||
| 1297 | /* Release device from reset */ | 1451 | /* Release device from reset */ |
| 1298 | iowrite32(0, card->config_regs + FPGA_MODE); | 1452 | iowrite32(0, card->config_regs + FPGA_MODE); |
| 1299 | (void)ioread32(card->config_regs + FPGA_MODE); | 1453 | (void)ioread32(card->config_regs + FPGA_MODE); |
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 28c99c623bcd..22b720ec80cb 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c | |||
| @@ -1217,8 +1217,7 @@ static void __exit dsp_cleanup(void) | |||
| 1217 | { | 1217 | { |
| 1218 | mISDN_unregister_Bprotocol(&DSP); | 1218 | mISDN_unregister_Bprotocol(&DSP); |
| 1219 | 1219 | ||
| 1220 | if (timer_pending(&dsp_spl_tl)) | 1220 | del_timer_sync(&dsp_spl_tl); |
| 1221 | del_timer(&dsp_spl_tl); | ||
| 1222 | 1221 | ||
| 1223 | if (!list_empty(&dsp_ilist)) { | 1222 | if (!list_empty(&dsp_ilist)) { |
| 1224 | printk(KERN_ERR "mISDN_dsp: Audio DSP object inst list not " | 1223 | printk(KERN_ERR "mISDN_dsp: Audio DSP object inst list not " |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index ef2cb2418535..b7d45f367d4a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
| @@ -4431,8 +4431,6 @@ static void bond_uninit(struct net_device *bond_dev) | |||
| 4431 | 4431 | ||
| 4432 | list_del(&bond->bond_list); | 4432 | list_del(&bond->bond_list); |
| 4433 | 4433 | ||
| 4434 | bond_work_cancel_all(bond); | ||
| 4435 | |||
| 4436 | bond_debug_unregister(bond); | 4434 | bond_debug_unregister(bond); |
| 4437 | 4435 | ||
| 4438 | __hw_addr_flush(&bond->mc_list); | 4436 | __hw_addr_flush(&bond->mc_list); |
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index 0f5917000aa2..6433b81256cd 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c | |||
| @@ -121,7 +121,7 @@ static int sja1000_ofp_probe(struct platform_device *ofdev) | |||
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | irq = irq_of_parse_and_map(np, 0); | 123 | irq = irq_of_parse_and_map(np, 0); |
| 124 | if (irq == NO_IRQ) { | 124 | if (irq == 0) { |
| 125 | dev_err(&ofdev->dev, "no irq found\n"); | 125 | dev_err(&ofdev->dev, "no irq found\n"); |
| 126 | err = -ENODEV; | 126 | err = -ENODEV; |
| 127 | goto exit_unmap_mem; | 127 | goto exit_unmap_mem; |
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index abf26c7c1d19..3bc1912afba9 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
| @@ -616,7 +616,7 @@ static inline bool be_error(struct be_adapter *adapter) | |||
| 616 | return adapter->eeh_error || adapter->hw_error || adapter->fw_timeout; | 616 | return adapter->eeh_error || adapter->hw_error || adapter->fw_timeout; |
| 617 | } | 617 | } |
| 618 | 618 | ||
| 619 | static inline bool be_crit_error(struct be_adapter *adapter) | 619 | static inline bool be_hw_error(struct be_adapter *adapter) |
| 620 | { | 620 | { |
| 621 | return adapter->eeh_error || adapter->hw_error; | 621 | return adapter->eeh_error || adapter->hw_error; |
| 622 | } | 622 | } |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index f2875aa47661..8a250c38fb82 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c | |||
| @@ -298,7 +298,12 @@ void be_async_mcc_enable(struct be_adapter *adapter) | |||
| 298 | 298 | ||
| 299 | void be_async_mcc_disable(struct be_adapter *adapter) | 299 | void be_async_mcc_disable(struct be_adapter *adapter) |
| 300 | { | 300 | { |
| 301 | spin_lock_bh(&adapter->mcc_cq_lock); | ||
| 302 | |||
| 301 | adapter->mcc_obj.rearm_cq = false; | 303 | adapter->mcc_obj.rearm_cq = false; |
| 304 | be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0); | ||
| 305 | |||
| 306 | spin_unlock_bh(&adapter->mcc_cq_lock); | ||
| 302 | } | 307 | } |
| 303 | 308 | ||
| 304 | int be_process_mcc(struct be_adapter *adapter) | 309 | int be_process_mcc(struct be_adapter *adapter) |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index f95612b907ae..9dca22be8125 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
| @@ -1689,15 +1689,41 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo) | |||
| 1689 | struct be_queue_info *rxq = &rxo->q; | 1689 | struct be_queue_info *rxq = &rxo->q; |
| 1690 | struct be_queue_info *rx_cq = &rxo->cq; | 1690 | struct be_queue_info *rx_cq = &rxo->cq; |
| 1691 | struct be_rx_compl_info *rxcp; | 1691 | struct be_rx_compl_info *rxcp; |
| 1692 | struct be_adapter *adapter = rxo->adapter; | ||
| 1693 | int flush_wait = 0; | ||
| 1692 | u16 tail; | 1694 | u16 tail; |
| 1693 | 1695 | ||
| 1694 | /* First cleanup pending rx completions */ | 1696 | /* Consume pending rx completions. |
| 1695 | while ((rxcp = be_rx_compl_get(rxo)) != NULL) { | 1697 | * Wait for the flush completion (identified by zero num_rcvd) |
| 1696 | be_rx_compl_discard(rxo, rxcp); | 1698 | * to arrive. Notify CQ even when there are no more CQ entries |
| 1697 | be_cq_notify(rxo->adapter, rx_cq->id, false, 1); | 1699 | * for HW to flush partially coalesced CQ entries. |
| 1700 | * In Lancer, there is no need to wait for flush compl. | ||
| 1701 | */ | ||
| 1702 | for (;;) { | ||
| 1703 | rxcp = be_rx_compl_get(rxo); | ||
| 1704 | if (rxcp == NULL) { | ||
| 1705 | if (lancer_chip(adapter)) | ||
| 1706 | break; | ||
| 1707 | |||
| 1708 | if (flush_wait++ > 10 || be_hw_error(adapter)) { | ||
| 1709 | dev_warn(&adapter->pdev->dev, | ||
| 1710 | "did not receive flush compl\n"); | ||
| 1711 | break; | ||
| 1712 | } | ||
| 1713 | be_cq_notify(adapter, rx_cq->id, true, 0); | ||
| 1714 | mdelay(1); | ||
| 1715 | } else { | ||
| 1716 | be_rx_compl_discard(rxo, rxcp); | ||
| 1717 | be_cq_notify(adapter, rx_cq->id, true, 1); | ||
| 1718 | if (rxcp->num_rcvd == 0) | ||
| 1719 | break; | ||
| 1720 | } | ||
| 1698 | } | 1721 | } |
| 1699 | 1722 | ||
| 1700 | /* Then free posted rx buffer that were not used */ | 1723 | /* After cleanup, leave the CQ in unarmed state */ |
| 1724 | be_cq_notify(adapter, rx_cq->id, false, 0); | ||
| 1725 | |||
| 1726 | /* Then free posted rx buffers that were not used */ | ||
| 1701 | tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len; | 1727 | tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len; |
| 1702 | for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) { | 1728 | for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) { |
| 1703 | page_info = get_rx_page_info(rxo, tail); | 1729 | page_info = get_rx_page_info(rxo, tail); |
| @@ -2157,7 +2183,7 @@ void be_detect_error(struct be_adapter *adapter) | |||
| 2157 | u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; | 2183 | u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; |
| 2158 | u32 i; | 2184 | u32 i; |
| 2159 | 2185 | ||
| 2160 | if (be_crit_error(adapter)) | 2186 | if (be_hw_error(adapter)) |
| 2161 | return; | 2187 | return; |
| 2162 | 2188 | ||
| 2163 | if (lancer_chip(adapter)) { | 2189 | if (lancer_chip(adapter)) { |
| @@ -2398,13 +2424,22 @@ static int be_close(struct net_device *netdev) | |||
| 2398 | 2424 | ||
| 2399 | be_roce_dev_close(adapter); | 2425 | be_roce_dev_close(adapter); |
| 2400 | 2426 | ||
| 2401 | be_async_mcc_disable(adapter); | ||
| 2402 | |||
| 2403 | if (!lancer_chip(adapter)) | 2427 | if (!lancer_chip(adapter)) |
| 2404 | be_intr_set(adapter, false); | 2428 | be_intr_set(adapter, false); |
| 2405 | 2429 | ||
| 2406 | for_all_evt_queues(adapter, eqo, i) { | 2430 | for_all_evt_queues(adapter, eqo, i) |
| 2407 | napi_disable(&eqo->napi); | 2431 | napi_disable(&eqo->napi); |
| 2432 | |||
| 2433 | be_async_mcc_disable(adapter); | ||
| 2434 | |||
| 2435 | /* Wait for all pending tx completions to arrive so that | ||
| 2436 | * all tx skbs are freed. | ||
| 2437 | */ | ||
| 2438 | be_tx_compl_clean(adapter); | ||
| 2439 | |||
| 2440 | be_rx_qs_destroy(adapter); | ||
| 2441 | |||
| 2442 | for_all_evt_queues(adapter, eqo, i) { | ||
| 2408 | if (msix_enabled(adapter)) | 2443 | if (msix_enabled(adapter)) |
| 2409 | synchronize_irq(be_msix_vec_get(adapter, eqo)); | 2444 | synchronize_irq(be_msix_vec_get(adapter, eqo)); |
| 2410 | else | 2445 | else |
| @@ -2414,12 +2449,6 @@ static int be_close(struct net_device *netdev) | |||
| 2414 | 2449 | ||
| 2415 | be_irq_unregister(adapter); | 2450 | be_irq_unregister(adapter); |
| 2416 | 2451 | ||
| 2417 | /* Wait for all pending tx completions to arrive so that | ||
| 2418 | * all tx skbs are freed. | ||
| 2419 | */ | ||
| 2420 | be_tx_compl_clean(adapter); | ||
| 2421 | |||
| 2422 | be_rx_qs_destroy(adapter); | ||
| 2423 | return 0; | 2452 | return 0; |
| 2424 | } | 2453 | } |
| 2425 | 2454 | ||
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index 5ba6e1cbd346..ec490d741fc0 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig | |||
| @@ -94,9 +94,8 @@ config GIANFAR | |||
| 94 | 94 | ||
| 95 | config FEC_PTP | 95 | config FEC_PTP |
| 96 | bool "PTP Hardware Clock (PHC)" | 96 | bool "PTP Hardware Clock (PHC)" |
| 97 | depends on FEC && ARCH_MXC | 97 | depends on FEC && ARCH_MXC && !SOC_IMX25 && !SOC_IMX27 && !SOC_IMX35 && !SOC_IMX5 |
| 98 | select PTP_1588_CLOCK | 98 | select PTP_1588_CLOCK |
| 99 | default y if SOC_IMX6Q | ||
| 100 | --help--- | 99 | --help--- |
| 101 | Say Y here if you want to use PTP Hardware Clock (PHC) in the | 100 | Say Y here if you want to use PTP Hardware Clock (PHC) in the |
| 102 | driver. Only the basic clock operations have been implemented. | 101 | driver. Only the basic clock operations have been implemented. |
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index 83f0ea929d3d..8ebc352bcbe6 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c | |||
| @@ -4761,7 +4761,7 @@ static void transmit_cleanup(struct dev_info *hw_priv, int normal) | |||
| 4761 | struct ksz_dma_buf *dma_buf; | 4761 | struct ksz_dma_buf *dma_buf; |
| 4762 | struct net_device *dev = NULL; | 4762 | struct net_device *dev = NULL; |
| 4763 | 4763 | ||
| 4764 | spin_lock(&hw_priv->hwlock); | 4764 | spin_lock_irq(&hw_priv->hwlock); |
| 4765 | last = info->last; | 4765 | last = info->last; |
| 4766 | 4766 | ||
| 4767 | while (info->avail < info->alloc) { | 4767 | while (info->avail < info->alloc) { |
| @@ -4795,7 +4795,7 @@ static void transmit_cleanup(struct dev_info *hw_priv, int normal) | |||
| 4795 | info->avail++; | 4795 | info->avail++; |
| 4796 | } | 4796 | } |
| 4797 | info->last = last; | 4797 | info->last = last; |
| 4798 | spin_unlock(&hw_priv->hwlock); | 4798 | spin_unlock_irq(&hw_priv->hwlock); |
| 4799 | 4799 | ||
| 4800 | /* Notify the network subsystem that the packet has been sent. */ | 4800 | /* Notify the network subsystem that the packet has been sent. */ |
| 4801 | if (dev) | 4801 | if (dev) |
| @@ -5259,11 +5259,15 @@ static irqreturn_t netdev_intr(int irq, void *dev_id) | |||
| 5259 | struct dev_info *hw_priv = priv->adapter; | 5259 | struct dev_info *hw_priv = priv->adapter; |
| 5260 | struct ksz_hw *hw = &hw_priv->hw; | 5260 | struct ksz_hw *hw = &hw_priv->hw; |
| 5261 | 5261 | ||
| 5262 | spin_lock(&hw_priv->hwlock); | ||
| 5263 | |||
| 5262 | hw_read_intr(hw, &int_enable); | 5264 | hw_read_intr(hw, &int_enable); |
| 5263 | 5265 | ||
| 5264 | /* Not our interrupt! */ | 5266 | /* Not our interrupt! */ |
| 5265 | if (!int_enable) | 5267 | if (!int_enable) { |
| 5268 | spin_unlock(&hw_priv->hwlock); | ||
| 5266 | return IRQ_NONE; | 5269 | return IRQ_NONE; |
| 5270 | } | ||
| 5267 | 5271 | ||
| 5268 | do { | 5272 | do { |
| 5269 | hw_ack_intr(hw, int_enable); | 5273 | hw_ack_intr(hw, int_enable); |
| @@ -5310,6 +5314,8 @@ static irqreturn_t netdev_intr(int irq, void *dev_id) | |||
| 5310 | 5314 | ||
| 5311 | hw_ena_intr(hw); | 5315 | hw_ena_intr(hw); |
| 5312 | 5316 | ||
| 5317 | spin_unlock(&hw_priv->hwlock); | ||
| 5318 | |||
| 5313 | return IRQ_HANDLED; | 5319 | return IRQ_HANDLED; |
| 5314 | } | 5320 | } |
| 5315 | 5321 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 537902479689..bc7ec64e9c7a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
| @@ -36,8 +36,8 @@ | |||
| 36 | 36 | ||
| 37 | #define _QLCNIC_LINUX_MAJOR 5 | 37 | #define _QLCNIC_LINUX_MAJOR 5 |
| 38 | #define _QLCNIC_LINUX_MINOR 0 | 38 | #define _QLCNIC_LINUX_MINOR 0 |
| 39 | #define _QLCNIC_LINUX_SUBVERSION 29 | 39 | #define _QLCNIC_LINUX_SUBVERSION 30 |
| 40 | #define QLCNIC_LINUX_VERSIONID "5.0.29" | 40 | #define QLCNIC_LINUX_VERSIONID "5.0.30" |
| 41 | #define QLCNIC_DRV_IDC_VER 0x01 | 41 | #define QLCNIC_DRV_IDC_VER 0x01 |
| 42 | #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ | 42 | #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ |
| 43 | (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) | 43 | (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 58f094ca052e..b14b8f0787ea 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | |||
| @@ -134,7 +134,7 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) | |||
| 134 | __le32 *tmp_buf; | 134 | __le32 *tmp_buf; |
| 135 | struct qlcnic_cmd_args cmd; | 135 | struct qlcnic_cmd_args cmd; |
| 136 | struct qlcnic_hardware_context *ahw; | 136 | struct qlcnic_hardware_context *ahw; |
| 137 | struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl; | 137 | struct qlcnic_dump_template_hdr *tmpl_hdr; |
| 138 | dma_addr_t tmp_addr_t = 0; | 138 | dma_addr_t tmp_addr_t = 0; |
| 139 | 139 | ||
| 140 | ahw = adapter->ahw; | 140 | ahw = adapter->ahw; |
| @@ -150,6 +150,8 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) | |||
| 150 | } | 150 | } |
| 151 | temp_size = cmd.rsp.arg2; | 151 | temp_size = cmd.rsp.arg2; |
| 152 | version = cmd.rsp.arg3; | 152 | version = cmd.rsp.arg3; |
| 153 | dev_info(&adapter->pdev->dev, | ||
| 154 | "minidump template version = 0x%x", version); | ||
| 153 | if (!temp_size) | 155 | if (!temp_size) |
| 154 | return -EIO; | 156 | return -EIO; |
| 155 | 157 | ||
| @@ -174,7 +176,6 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) | |||
| 174 | err = -EIO; | 176 | err = -EIO; |
| 175 | goto error; | 177 | goto error; |
| 176 | } | 178 | } |
| 177 | tmp_tmpl = tmp_addr; | ||
| 178 | ahw->fw_dump.tmpl_hdr = vzalloc(temp_size); | 179 | ahw->fw_dump.tmpl_hdr = vzalloc(temp_size); |
| 179 | if (!ahw->fw_dump.tmpl_hdr) { | 180 | if (!ahw->fw_dump.tmpl_hdr) { |
| 180 | err = -EIO; | 181 | err = -EIO; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index fc48e000f35f..7a6d5ebe4e0f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | |||
| @@ -365,7 +365,7 @@ static int | |||
| 365 | qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, | 365 | qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, |
| 366 | struct cmd_desc_type0 *cmd_desc_arr, int nr_desc) | 366 | struct cmd_desc_type0 *cmd_desc_arr, int nr_desc) |
| 367 | { | 367 | { |
| 368 | u32 i, producer, consumer; | 368 | u32 i, producer; |
| 369 | struct qlcnic_cmd_buffer *pbuf; | 369 | struct qlcnic_cmd_buffer *pbuf; |
| 370 | struct cmd_desc_type0 *cmd_desc; | 370 | struct cmd_desc_type0 *cmd_desc; |
| 371 | struct qlcnic_host_tx_ring *tx_ring; | 371 | struct qlcnic_host_tx_ring *tx_ring; |
| @@ -379,7 +379,6 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, | |||
| 379 | __netif_tx_lock_bh(tx_ring->txq); | 379 | __netif_tx_lock_bh(tx_ring->txq); |
| 380 | 380 | ||
| 381 | producer = tx_ring->producer; | 381 | producer = tx_ring->producer; |
| 382 | consumer = tx_ring->sw_consumer; | ||
| 383 | 382 | ||
| 384 | if (nr_desc >= qlcnic_tx_avail(tx_ring)) { | 383 | if (nr_desc >= qlcnic_tx_avail(tx_ring)) { |
| 385 | netif_tx_stop_queue(tx_ring->txq); | 384 | netif_tx_stop_queue(tx_ring->txq); |
| @@ -402,7 +401,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, | |||
| 402 | pbuf->frag_count = 0; | 401 | pbuf->frag_count = 0; |
| 403 | 402 | ||
| 404 | memcpy(&tx_ring->desc_head[producer], | 403 | memcpy(&tx_ring->desc_head[producer], |
| 405 | &cmd_desc_arr[i], sizeof(struct cmd_desc_type0)); | 404 | cmd_desc, sizeof(struct cmd_desc_type0)); |
| 406 | 405 | ||
| 407 | producer = get_next_index(producer, tx_ring->num_desc); | 406 | producer = get_next_index(producer, tx_ring->num_desc); |
| 408 | i++; | 407 | i++; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index a7554d9aab0c..d833f5927891 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
| @@ -445,13 +445,10 @@ static int | |||
| 445 | qlcnic_set_function_modes(struct qlcnic_adapter *adapter) | 445 | qlcnic_set_function_modes(struct qlcnic_adapter *adapter) |
| 446 | { | 446 | { |
| 447 | u8 id; | 447 | u8 id; |
| 448 | u32 ref_count; | ||
| 449 | int i, ret = 1; | 448 | int i, ret = 1; |
| 450 | u32 data = QLCNIC_MGMT_FUNC; | 449 | u32 data = QLCNIC_MGMT_FUNC; |
| 451 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 450 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
| 452 | 451 | ||
| 453 | /* If other drivers are not in use set their privilege level */ | ||
| 454 | ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); | ||
| 455 | ret = qlcnic_api_lock(adapter); | 452 | ret = qlcnic_api_lock(adapter); |
| 456 | if (ret) | 453 | if (ret) |
| 457 | goto err_lock; | 454 | goto err_lock; |
| @@ -531,11 +528,9 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev, | |||
| 531 | { | 528 | { |
| 532 | u32 offset; | 529 | u32 offset; |
| 533 | void __iomem *mem_ptr0 = NULL; | 530 | void __iomem *mem_ptr0 = NULL; |
| 534 | resource_size_t mem_base; | ||
| 535 | unsigned long mem_len, pci_len0 = 0, bar0_len; | 531 | unsigned long mem_len, pci_len0 = 0, bar0_len; |
| 536 | 532 | ||
| 537 | /* remap phys address */ | 533 | /* remap phys address */ |
| 538 | mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ | ||
| 539 | mem_len = pci_resource_len(pdev, 0); | 534 | mem_len = pci_resource_len(pdev, 0); |
| 540 | 535 | ||
| 541 | qlcnic_get_bar_length(pdev->device, &bar0_len); | 536 | qlcnic_get_bar_length(pdev->device, &bar0_len); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c index 12ff29270745..0b8d8625834c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | |||
| @@ -197,7 +197,7 @@ static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, | |||
| 197 | int i, k, timeout = 0; | 197 | int i, k, timeout = 0; |
| 198 | void __iomem *base = adapter->ahw->pci_base0; | 198 | void __iomem *base = adapter->ahw->pci_base0; |
| 199 | u32 addr, data; | 199 | u32 addr, data; |
| 200 | u8 opcode, no_ops; | 200 | u8 no_ops; |
| 201 | struct __ctrl *ctr = &entry->region.ctrl; | 201 | struct __ctrl *ctr = &entry->region.ctrl; |
| 202 | struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr; | 202 | struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr; |
| 203 | 203 | ||
| @@ -206,7 +206,6 @@ static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, | |||
| 206 | 206 | ||
| 207 | for (i = 0; i < no_ops; i++) { | 207 | for (i = 0; i < no_ops; i++) { |
| 208 | k = 0; | 208 | k = 0; |
| 209 | opcode = 0; | ||
| 210 | for (k = 0; k < 8; k++) { | 209 | for (k = 0; k < 8; k++) { |
| 211 | if (!(ctr->opcode & (1 << k))) | 210 | if (!(ctr->opcode & (1 << k))) |
| 212 | continue; | 211 | continue; |
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index cb6fc5a743ca..5ac93323a40c 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c | |||
| @@ -577,28 +577,30 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) | |||
| 577 | { | 577 | { |
| 578 | struct net_device *dev = dev_instance; | 578 | struct net_device *dev = dev_instance; |
| 579 | struct cp_private *cp; | 579 | struct cp_private *cp; |
| 580 | int handled = 0; | ||
| 580 | u16 status; | 581 | u16 status; |
| 581 | 582 | ||
| 582 | if (unlikely(dev == NULL)) | 583 | if (unlikely(dev == NULL)) |
| 583 | return IRQ_NONE; | 584 | return IRQ_NONE; |
| 584 | cp = netdev_priv(dev); | 585 | cp = netdev_priv(dev); |
| 585 | 586 | ||
| 587 | spin_lock(&cp->lock); | ||
| 588 | |||
| 586 | status = cpr16(IntrStatus); | 589 | status = cpr16(IntrStatus); |
| 587 | if (!status || (status == 0xFFFF)) | 590 | if (!status || (status == 0xFFFF)) |
| 588 | return IRQ_NONE; | 591 | goto out_unlock; |
| 592 | |||
| 593 | handled = 1; | ||
| 589 | 594 | ||
| 590 | netif_dbg(cp, intr, dev, "intr, status %04x cmd %02x cpcmd %04x\n", | 595 | netif_dbg(cp, intr, dev, "intr, status %04x cmd %02x cpcmd %04x\n", |
| 591 | status, cpr8(Cmd), cpr16(CpCmd)); | 596 | status, cpr8(Cmd), cpr16(CpCmd)); |
| 592 | 597 | ||
| 593 | cpw16(IntrStatus, status & ~cp_rx_intr_mask); | 598 | cpw16(IntrStatus, status & ~cp_rx_intr_mask); |
| 594 | 599 | ||
| 595 | spin_lock(&cp->lock); | ||
| 596 | |||
| 597 | /* close possible race's with dev_close */ | 600 | /* close possible race's with dev_close */ |
| 598 | if (unlikely(!netif_running(dev))) { | 601 | if (unlikely(!netif_running(dev))) { |
| 599 | cpw16(IntrMask, 0); | 602 | cpw16(IntrMask, 0); |
| 600 | spin_unlock(&cp->lock); | 603 | goto out_unlock; |
| 601 | return IRQ_HANDLED; | ||
| 602 | } | 604 | } |
| 603 | 605 | ||
| 604 | if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) | 606 | if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) |
| @@ -612,7 +614,6 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) | |||
| 612 | if (status & LinkChg) | 614 | if (status & LinkChg) |
| 613 | mii_check_media(&cp->mii_if, netif_msg_link(cp), false); | 615 | mii_check_media(&cp->mii_if, netif_msg_link(cp), false); |
| 614 | 616 | ||
| 615 | spin_unlock(&cp->lock); | ||
| 616 | 617 | ||
| 617 | if (status & PciErr) { | 618 | if (status & PciErr) { |
| 618 | u16 pci_status; | 619 | u16 pci_status; |
| @@ -625,7 +626,10 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) | |||
| 625 | /* TODO: reset hardware */ | 626 | /* TODO: reset hardware */ |
| 626 | } | 627 | } |
| 627 | 628 | ||
| 628 | return IRQ_HANDLED; | 629 | out_unlock: |
| 630 | spin_unlock(&cp->lock); | ||
| 631 | |||
| 632 | return IRQ_RETVAL(handled); | ||
| 629 | } | 633 | } |
| 630 | 634 | ||
| 631 | #ifdef CONFIG_NET_POLL_CONTROLLER | 635 | #ifdef CONFIG_NET_POLL_CONTROLLER |
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 022b45bc14ff..a670d23d9340 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c | |||
| @@ -2386,8 +2386,6 @@ static const struct of_device_id smc91x_match[] = { | |||
| 2386 | {}, | 2386 | {}, |
| 2387 | }; | 2387 | }; |
| 2388 | MODULE_DEVICE_TABLE(of, smc91x_match); | 2388 | MODULE_DEVICE_TABLE(of, smc91x_match); |
| 2389 | #else | ||
| 2390 | #define smc91x_match NULL | ||
| 2391 | #endif | 2389 | #endif |
| 2392 | 2390 | ||
| 2393 | static struct dev_pm_ops smc_drv_pm_ops = { | 2391 | static struct dev_pm_ops smc_drv_pm_ops = { |
| @@ -2402,7 +2400,7 @@ static struct platform_driver smc_driver = { | |||
| 2402 | .name = CARDNAME, | 2400 | .name = CARDNAME, |
| 2403 | .owner = THIS_MODULE, | 2401 | .owner = THIS_MODULE, |
| 2404 | .pm = &smc_drv_pm_ops, | 2402 | .pm = &smc_drv_pm_ops, |
| 2405 | .of_match_table = smc91x_match, | 2403 | .of_match_table = of_match_ptr(smc91x_match), |
| 2406 | }, | 2404 | }, |
| 2407 | }; | 2405 | }; |
| 2408 | 2406 | ||
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 4616bf27d515..e112877d15d3 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c | |||
| @@ -2575,11 +2575,13 @@ static const struct dev_pm_ops smsc911x_pm_ops = { | |||
| 2575 | #define SMSC911X_PM_OPS NULL | 2575 | #define SMSC911X_PM_OPS NULL |
| 2576 | #endif | 2576 | #endif |
| 2577 | 2577 | ||
| 2578 | #ifdef CONFIG_OF | ||
| 2578 | static const struct of_device_id smsc911x_dt_ids[] = { | 2579 | static const struct of_device_id smsc911x_dt_ids[] = { |
| 2579 | { .compatible = "smsc,lan9115", }, | 2580 | { .compatible = "smsc,lan9115", }, |
| 2580 | { /* sentinel */ } | 2581 | { /* sentinel */ } |
| 2581 | }; | 2582 | }; |
| 2582 | MODULE_DEVICE_TABLE(of, smsc911x_dt_ids); | 2583 | MODULE_DEVICE_TABLE(of, smsc911x_dt_ids); |
| 2584 | #endif | ||
| 2583 | 2585 | ||
| 2584 | static struct platform_driver smsc911x_driver = { | 2586 | static struct platform_driver smsc911x_driver = { |
| 2585 | .probe = smsc911x_drv_probe, | 2587 | .probe = smsc911x_drv_probe, |
| @@ -2588,7 +2590,7 @@ static struct platform_driver smsc911x_driver = { | |||
| 2588 | .name = SMSC_CHIPNAME, | 2590 | .name = SMSC_CHIPNAME, |
| 2589 | .owner = THIS_MODULE, | 2591 | .owner = THIS_MODULE, |
| 2590 | .pm = SMSC911X_PM_OPS, | 2592 | .pm = SMSC911X_PM_OPS, |
| 2591 | .of_match_table = smsc911x_dt_ids, | 2593 | .of_match_table = of_match_ptr(smsc911x_dt_ids), |
| 2592 | }, | 2594 | }, |
| 2593 | }; | 2595 | }; |
| 2594 | 2596 | ||
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 023a4fb4efa5..b05df8983be5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h | |||
| @@ -127,14 +127,14 @@ static inline int stmmac_register_platform(void) | |||
| 127 | } | 127 | } |
| 128 | static inline void stmmac_unregister_platform(void) | 128 | static inline void stmmac_unregister_platform(void) |
| 129 | { | 129 | { |
| 130 | platform_driver_register(&stmmac_pltfr_driver); | 130 | platform_driver_unregister(&stmmac_pltfr_driver); |
| 131 | } | 131 | } |
| 132 | #else | 132 | #else |
| 133 | static inline int stmmac_register_platform(void) | 133 | static inline int stmmac_register_platform(void) |
| 134 | { | 134 | { |
| 135 | pr_debug("stmmac: do not register the platf driver\n"); | 135 | pr_debug("stmmac: do not register the platf driver\n"); |
| 136 | 136 | ||
| 137 | return -EINVAL; | 137 | return 0; |
| 138 | } | 138 | } |
| 139 | static inline void stmmac_unregister_platform(void) | 139 | static inline void stmmac_unregister_platform(void) |
| 140 | { | 140 | { |
| @@ -162,7 +162,7 @@ static inline int stmmac_register_pci(void) | |||
| 162 | { | 162 | { |
| 163 | pr_debug("stmmac: do not register the PCI driver\n"); | 163 | pr_debug("stmmac: do not register the PCI driver\n"); |
| 164 | 164 | ||
| 165 | return -EINVAL; | 165 | return 0; |
| 166 | } | 166 | } |
| 167 | static inline void stmmac_unregister_pci(void) | 167 | static inline void stmmac_unregister_pci(void) |
| 168 | { | 168 | { |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 542edbcd92c7..f07c0612abf6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | |||
| @@ -2194,18 +2194,20 @@ int stmmac_restore(struct net_device *ndev) | |||
| 2194 | */ | 2194 | */ |
| 2195 | static int __init stmmac_init(void) | 2195 | static int __init stmmac_init(void) |
| 2196 | { | 2196 | { |
| 2197 | int err_plt = 0; | 2197 | int ret; |
| 2198 | int err_pci = 0; | ||
| 2199 | |||
| 2200 | err_plt = stmmac_register_platform(); | ||
| 2201 | err_pci = stmmac_register_pci(); | ||
| 2202 | |||
| 2203 | if ((err_pci) && (err_plt)) { | ||
| 2204 | pr_err("stmmac: driver registration failed\n"); | ||
| 2205 | return -EINVAL; | ||
| 2206 | } | ||
| 2207 | 2198 | ||
| 2199 | ret = stmmac_register_platform(); | ||
| 2200 | if (ret) | ||
| 2201 | goto err; | ||
| 2202 | ret = stmmac_register_pci(); | ||
| 2203 | if (ret) | ||
| 2204 | goto err_pci; | ||
| 2208 | return 0; | 2205 | return 0; |
| 2206 | err_pci: | ||
| 2207 | stmmac_unregister_platform(); | ||
| 2208 | err: | ||
| 2209 | pr_err("stmmac: driver registration failed\n"); | ||
| 2210 | return ret; | ||
| 2209 | } | 2211 | } |
| 2210 | 2212 | ||
| 2211 | static void __exit stmmac_exit(void) | 2213 | static void __exit stmmac_exit(void) |
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c index 337766738eca..5e62c1aeeffb 100644 --- a/drivers/net/ethernet/ti/cpts.c +++ b/drivers/net/ethernet/ti/cpts.c | |||
| @@ -27,8 +27,6 @@ | |||
| 27 | #include <linux/uaccess.h> | 27 | #include <linux/uaccess.h> |
| 28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
| 29 | 29 | ||
| 30 | #include <plat/clock.h> | ||
| 31 | |||
| 32 | #include "cpts.h" | 30 | #include "cpts.h" |
| 33 | 31 | ||
| 34 | #ifdef CONFIG_TI_CPTS | 32 | #ifdef CONFIG_TI_CPTS |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 40b426edc9e6..504f7f1cad94 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
| @@ -138,6 +138,8 @@ struct tun_file { | |||
| 138 | /* only used for fasnyc */ | 138 | /* only used for fasnyc */ |
| 139 | unsigned int flags; | 139 | unsigned int flags; |
| 140 | u16 queue_index; | 140 | u16 queue_index; |
| 141 | struct list_head next; | ||
| 142 | struct tun_struct *detached; | ||
| 141 | }; | 143 | }; |
| 142 | 144 | ||
| 143 | struct tun_flow_entry { | 145 | struct tun_flow_entry { |
| @@ -182,6 +184,8 @@ struct tun_struct { | |||
| 182 | struct hlist_head flows[TUN_NUM_FLOW_ENTRIES]; | 184 | struct hlist_head flows[TUN_NUM_FLOW_ENTRIES]; |
| 183 | struct timer_list flow_gc_timer; | 185 | struct timer_list flow_gc_timer; |
| 184 | unsigned long ageing_time; | 186 | unsigned long ageing_time; |
| 187 | unsigned int numdisabled; | ||
| 188 | struct list_head disabled; | ||
| 185 | }; | 189 | }; |
| 186 | 190 | ||
| 187 | static inline u32 tun_hashfn(u32 rxhash) | 191 | static inline u32 tun_hashfn(u32 rxhash) |
| @@ -385,6 +389,23 @@ static void tun_set_real_num_queues(struct tun_struct *tun) | |||
| 385 | netif_set_real_num_rx_queues(tun->dev, tun->numqueues); | 389 | netif_set_real_num_rx_queues(tun->dev, tun->numqueues); |
| 386 | } | 390 | } |
| 387 | 391 | ||
| 392 | static void tun_disable_queue(struct tun_struct *tun, struct tun_file *tfile) | ||
| 393 | { | ||
| 394 | tfile->detached = tun; | ||
| 395 | list_add_tail(&tfile->next, &tun->disabled); | ||
| 396 | ++tun->numdisabled; | ||
| 397 | } | ||
| 398 | |||
| 399 | static struct tun_struct *tun_enable_queue(struct tun_file *tfile) | ||
| 400 | { | ||
| 401 | struct tun_struct *tun = tfile->detached; | ||
| 402 | |||
| 403 | tfile->detached = NULL; | ||
| 404 | list_del_init(&tfile->next); | ||
| 405 | --tun->numdisabled; | ||
| 406 | return tun; | ||
| 407 | } | ||
| 408 | |||
| 388 | static void __tun_detach(struct tun_file *tfile, bool clean) | 409 | static void __tun_detach(struct tun_file *tfile, bool clean) |
| 389 | { | 410 | { |
| 390 | struct tun_file *ntfile; | 411 | struct tun_file *ntfile; |
| @@ -406,20 +427,25 @@ static void __tun_detach(struct tun_file *tfile, bool clean) | |||
| 406 | ntfile->queue_index = index; | 427 | ntfile->queue_index = index; |
| 407 | 428 | ||
| 408 | --tun->numqueues; | 429 | --tun->numqueues; |
| 409 | sock_put(&tfile->sk); | 430 | if (clean) |
| 431 | sock_put(&tfile->sk); | ||
| 432 | else | ||
| 433 | tun_disable_queue(tun, tfile); | ||
| 410 | 434 | ||
| 411 | synchronize_net(); | 435 | synchronize_net(); |
| 412 | tun_flow_delete_by_queue(tun, tun->numqueues + 1); | 436 | tun_flow_delete_by_queue(tun, tun->numqueues + 1); |
| 413 | /* Drop read queue */ | 437 | /* Drop read queue */ |
| 414 | skb_queue_purge(&tfile->sk.sk_receive_queue); | 438 | skb_queue_purge(&tfile->sk.sk_receive_queue); |
| 415 | tun_set_real_num_queues(tun); | 439 | tun_set_real_num_queues(tun); |
| 416 | 440 | } else if (tfile->detached && clean) | |
| 417 | if (tun->numqueues == 0 && !(tun->flags & TUN_PERSIST)) | 441 | tun = tun_enable_queue(tfile); |
| 418 | if (dev->reg_state == NETREG_REGISTERED) | ||
| 419 | unregister_netdevice(dev); | ||
| 420 | } | ||
| 421 | 442 | ||
| 422 | if (clean) { | 443 | if (clean) { |
| 444 | if (tun && tun->numqueues == 0 && tun->numdisabled == 0 && | ||
| 445 | !(tun->flags & TUN_PERSIST)) | ||
| 446 | if (tun->dev->reg_state == NETREG_REGISTERED) | ||
| 447 | unregister_netdevice(tun->dev); | ||
| 448 | |||
| 423 | BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED, | 449 | BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED, |
| 424 | &tfile->socket.flags)); | 450 | &tfile->socket.flags)); |
| 425 | sk_release_kernel(&tfile->sk); | 451 | sk_release_kernel(&tfile->sk); |
| @@ -436,7 +462,7 @@ static void tun_detach(struct tun_file *tfile, bool clean) | |||
| 436 | static void tun_detach_all(struct net_device *dev) | 462 | static void tun_detach_all(struct net_device *dev) |
| 437 | { | 463 | { |
| 438 | struct tun_struct *tun = netdev_priv(dev); | 464 | struct tun_struct *tun = netdev_priv(dev); |
| 439 | struct tun_file *tfile; | 465 | struct tun_file *tfile, *tmp; |
| 440 | int i, n = tun->numqueues; | 466 | int i, n = tun->numqueues; |
| 441 | 467 | ||
| 442 | for (i = 0; i < n; i++) { | 468 | for (i = 0; i < n; i++) { |
| @@ -457,6 +483,12 @@ static void tun_detach_all(struct net_device *dev) | |||
| 457 | skb_queue_purge(&tfile->sk.sk_receive_queue); | 483 | skb_queue_purge(&tfile->sk.sk_receive_queue); |
| 458 | sock_put(&tfile->sk); | 484 | sock_put(&tfile->sk); |
| 459 | } | 485 | } |
| 486 | list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) { | ||
| 487 | tun_enable_queue(tfile); | ||
| 488 | skb_queue_purge(&tfile->sk.sk_receive_queue); | ||
| 489 | sock_put(&tfile->sk); | ||
| 490 | } | ||
| 491 | BUG_ON(tun->numdisabled != 0); | ||
| 460 | } | 492 | } |
| 461 | 493 | ||
| 462 | static int tun_attach(struct tun_struct *tun, struct file *file) | 494 | static int tun_attach(struct tun_struct *tun, struct file *file) |
| @@ -473,7 +505,8 @@ static int tun_attach(struct tun_struct *tun, struct file *file) | |||
| 473 | goto out; | 505 | goto out; |
| 474 | 506 | ||
| 475 | err = -E2BIG; | 507 | err = -E2BIG; |
| 476 | if (tun->numqueues == MAX_TAP_QUEUES) | 508 | if (!tfile->detached && |
| 509 | tun->numqueues + tun->numdisabled == MAX_TAP_QUEUES) | ||
| 477 | goto out; | 510 | goto out; |
| 478 | 511 | ||
| 479 | err = 0; | 512 | err = 0; |
| @@ -487,9 +520,13 @@ static int tun_attach(struct tun_struct *tun, struct file *file) | |||
| 487 | tfile->queue_index = tun->numqueues; | 520 | tfile->queue_index = tun->numqueues; |
| 488 | rcu_assign_pointer(tfile->tun, tun); | 521 | rcu_assign_pointer(tfile->tun, tun); |
| 489 | rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile); | 522 | rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile); |
| 490 | sock_hold(&tfile->sk); | ||
| 491 | tun->numqueues++; | 523 | tun->numqueues++; |
| 492 | 524 | ||
| 525 | if (tfile->detached) | ||
| 526 | tun_enable_queue(tfile); | ||
| 527 | else | ||
| 528 | sock_hold(&tfile->sk); | ||
| 529 | |||
| 493 | tun_set_real_num_queues(tun); | 530 | tun_set_real_num_queues(tun); |
| 494 | 531 | ||
| 495 | /* device is allowed to go away first, so no need to hold extra | 532 | /* device is allowed to go away first, so no need to hold extra |
| @@ -1162,6 +1199,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
| 1162 | skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; | 1199 | skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; |
| 1163 | } | 1200 | } |
| 1164 | 1201 | ||
| 1202 | skb_reset_network_header(skb); | ||
| 1165 | rxhash = skb_get_rxhash(skb); | 1203 | rxhash = skb_get_rxhash(skb); |
| 1166 | netif_rx_ni(skb); | 1204 | netif_rx_ni(skb); |
| 1167 | 1205 | ||
| @@ -1349,6 +1387,7 @@ static void tun_free_netdev(struct net_device *dev) | |||
| 1349 | { | 1387 | { |
| 1350 | struct tun_struct *tun = netdev_priv(dev); | 1388 | struct tun_struct *tun = netdev_priv(dev); |
| 1351 | 1389 | ||
| 1390 | BUG_ON(!(list_empty(&tun->disabled))); | ||
| 1352 | tun_flow_uninit(tun); | 1391 | tun_flow_uninit(tun); |
| 1353 | free_netdev(dev); | 1392 | free_netdev(dev); |
| 1354 | } | 1393 | } |
| @@ -1543,6 +1582,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
| 1543 | err = tun_attach(tun, file); | 1582 | err = tun_attach(tun, file); |
| 1544 | if (err < 0) | 1583 | if (err < 0) |
| 1545 | return err; | 1584 | return err; |
| 1585 | |||
| 1586 | if (tun->flags & TUN_TAP_MQ && | ||
| 1587 | (tun->numqueues + tun->numdisabled > 1)) | ||
| 1588 | return err; | ||
| 1546 | } | 1589 | } |
| 1547 | else { | 1590 | else { |
| 1548 | char *name; | 1591 | char *name; |
| @@ -1601,6 +1644,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
| 1601 | TUN_USER_FEATURES; | 1644 | TUN_USER_FEATURES; |
| 1602 | dev->features = dev->hw_features; | 1645 | dev->features = dev->hw_features; |
| 1603 | 1646 | ||
| 1647 | INIT_LIST_HEAD(&tun->disabled); | ||
| 1604 | err = tun_attach(tun, file); | 1648 | err = tun_attach(tun, file); |
| 1605 | if (err < 0) | 1649 | if (err < 0) |
| 1606 | goto err_free_dev; | 1650 | goto err_free_dev; |
| @@ -1755,32 +1799,28 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr) | |||
| 1755 | { | 1799 | { |
| 1756 | struct tun_file *tfile = file->private_data; | 1800 | struct tun_file *tfile = file->private_data; |
| 1757 | struct tun_struct *tun; | 1801 | struct tun_struct *tun; |
| 1758 | struct net_device *dev; | ||
| 1759 | int ret = 0; | 1802 | int ret = 0; |
| 1760 | 1803 | ||
| 1761 | rtnl_lock(); | 1804 | rtnl_lock(); |
| 1762 | 1805 | ||
| 1763 | if (ifr->ifr_flags & IFF_ATTACH_QUEUE) { | 1806 | if (ifr->ifr_flags & IFF_ATTACH_QUEUE) { |
| 1764 | dev = __dev_get_by_name(tfile->net, ifr->ifr_name); | 1807 | tun = tfile->detached; |
| 1765 | if (!dev) { | 1808 | if (!tun) |
| 1766 | ret = -EINVAL; | ||
| 1767 | goto unlock; | ||
| 1768 | } | ||
| 1769 | |||
| 1770 | tun = netdev_priv(dev); | ||
| 1771 | if (dev->netdev_ops != &tap_netdev_ops && | ||
| 1772 | dev->netdev_ops != &tun_netdev_ops) | ||
| 1773 | ret = -EINVAL; | 1809 | ret = -EINVAL; |
| 1774 | else if (tun_not_capable(tun)) | 1810 | else if (tun_not_capable(tun)) |
| 1775 | ret = -EPERM; | 1811 | ret = -EPERM; |
| 1776 | else | 1812 | else |
| 1777 | ret = tun_attach(tun, file); | 1813 | ret = tun_attach(tun, file); |
| 1778 | } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) | 1814 | } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { |
| 1779 | __tun_detach(tfile, false); | 1815 | tun = rcu_dereference_protected(tfile->tun, |
| 1780 | else | 1816 | lockdep_rtnl_is_held()); |
| 1817 | if (!tun || !(tun->flags & TUN_TAP_MQ)) | ||
| 1818 | ret = -EINVAL; | ||
| 1819 | else | ||
| 1820 | __tun_detach(tfile, false); | ||
| 1821 | } else | ||
| 1781 | ret = -EINVAL; | 1822 | ret = -EINVAL; |
| 1782 | 1823 | ||
| 1783 | unlock: | ||
| 1784 | rtnl_unlock(); | 1824 | rtnl_unlock(); |
| 1785 | return ret; | 1825 | return ret; |
| 1786 | } | 1826 | } |
| @@ -2092,6 +2132,7 @@ static int tun_chr_open(struct inode *inode, struct file * file) | |||
| 2092 | 2132 | ||
| 2093 | file->private_data = tfile; | 2133 | file->private_data = tfile; |
| 2094 | set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags); | 2134 | set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags); |
| 2135 | INIT_LIST_HEAD(&tfile->next); | ||
| 2095 | 2136 | ||
| 2096 | return 0; | 2137 | return 0; |
| 2097 | } | 2138 | } |
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index d0129827602b..3f3d12d766e7 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c | |||
| @@ -457,12 +457,6 @@ int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf) | |||
| 457 | } | 457 | } |
| 458 | EXPORT_SYMBOL_GPL(usbnet_cdc_bind); | 458 | EXPORT_SYMBOL_GPL(usbnet_cdc_bind); |
| 459 | 459 | ||
| 460 | static int cdc_manage_power(struct usbnet *dev, int on) | ||
| 461 | { | ||
| 462 | dev->intf->needs_remote_wakeup = on; | ||
| 463 | return 0; | ||
| 464 | } | ||
| 465 | |||
| 466 | static const struct driver_info cdc_info = { | 460 | static const struct driver_info cdc_info = { |
| 467 | .description = "CDC Ethernet Device", | 461 | .description = "CDC Ethernet Device", |
| 468 | .flags = FLAG_ETHER | FLAG_POINTTOPOINT, | 462 | .flags = FLAG_ETHER | FLAG_POINTTOPOINT, |
| @@ -470,7 +464,7 @@ static const struct driver_info cdc_info = { | |||
| 470 | .bind = usbnet_cdc_bind, | 464 | .bind = usbnet_cdc_bind, |
| 471 | .unbind = usbnet_cdc_unbind, | 465 | .unbind = usbnet_cdc_unbind, |
| 472 | .status = usbnet_cdc_status, | 466 | .status = usbnet_cdc_status, |
| 473 | .manage_power = cdc_manage_power, | 467 | .manage_power = usbnet_manage_power, |
| 474 | }; | 468 | }; |
| 475 | 469 | ||
| 476 | static const struct driver_info wwan_info = { | 470 | static const struct driver_info wwan_info = { |
| @@ -479,7 +473,7 @@ static const struct driver_info wwan_info = { | |||
| 479 | .bind = usbnet_cdc_bind, | 473 | .bind = usbnet_cdc_bind, |
| 480 | .unbind = usbnet_cdc_unbind, | 474 | .unbind = usbnet_cdc_unbind, |
| 481 | .status = usbnet_cdc_status, | 475 | .status = usbnet_cdc_status, |
| 482 | .manage_power = cdc_manage_power, | 476 | .manage_power = usbnet_manage_power, |
| 483 | }; | 477 | }; |
| 484 | 478 | ||
| 485 | /*-------------------------------------------------------------------------*/ | 479 | /*-------------------------------------------------------------------------*/ |
| @@ -487,6 +481,7 @@ static const struct driver_info wwan_info = { | |||
| 487 | #define HUAWEI_VENDOR_ID 0x12D1 | 481 | #define HUAWEI_VENDOR_ID 0x12D1 |
| 488 | #define NOVATEL_VENDOR_ID 0x1410 | 482 | #define NOVATEL_VENDOR_ID 0x1410 |
| 489 | #define ZTE_VENDOR_ID 0x19D2 | 483 | #define ZTE_VENDOR_ID 0x19D2 |
| 484 | #define DELL_VENDOR_ID 0x413C | ||
| 490 | 485 | ||
| 491 | static const struct usb_device_id products [] = { | 486 | static const struct usb_device_id products [] = { |
| 492 | /* | 487 | /* |
| @@ -594,27 +589,29 @@ static const struct usb_device_id products [] = { | |||
| 594 | 589 | ||
| 595 | /* Novatel USB551L and MC551 - handled by qmi_wwan */ | 590 | /* Novatel USB551L and MC551 - handled by qmi_wwan */ |
| 596 | { | 591 | { |
| 597 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | 592 | USB_DEVICE_AND_INTERFACE_INFO(NOVATEL_VENDOR_ID, 0xB001, USB_CLASS_COMM, |
| 598 | | USB_DEVICE_ID_MATCH_PRODUCT | 593 | USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), |
| 599 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 600 | .idVendor = NOVATEL_VENDOR_ID, | ||
| 601 | .idProduct = 0xB001, | ||
| 602 | .bInterfaceClass = USB_CLASS_COMM, | ||
| 603 | .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, | ||
| 604 | .bInterfaceProtocol = USB_CDC_PROTO_NONE, | ||
| 605 | .driver_info = 0, | 594 | .driver_info = 0, |
| 606 | }, | 595 | }, |
| 607 | 596 | ||
| 608 | /* Novatel E362 - handled by qmi_wwan */ | 597 | /* Novatel E362 - handled by qmi_wwan */ |
| 609 | { | 598 | { |
| 610 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | 599 | USB_DEVICE_AND_INTERFACE_INFO(NOVATEL_VENDOR_ID, 0x9010, USB_CLASS_COMM, |
| 611 | | USB_DEVICE_ID_MATCH_PRODUCT | 600 | USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), |
| 612 | | USB_DEVICE_ID_MATCH_INT_INFO, | 601 | .driver_info = 0, |
| 613 | .idVendor = NOVATEL_VENDOR_ID, | 602 | }, |
| 614 | .idProduct = 0x9010, | 603 | |
| 615 | .bInterfaceClass = USB_CLASS_COMM, | 604 | /* Dell Wireless 5800 (Novatel E362) - handled by qmi_wwan */ |
| 616 | .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, | 605 | { |
| 617 | .bInterfaceProtocol = USB_CDC_PROTO_NONE, | 606 | USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x8195, USB_CLASS_COMM, |
| 607 | USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), | ||
| 608 | .driver_info = 0, | ||
| 609 | }, | ||
| 610 | |||
| 611 | /* Dell Wireless 5800 (Novatel E362) - handled by qmi_wwan */ | ||
| 612 | { | ||
| 613 | USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x8196, USB_CLASS_COMM, | ||
| 614 | USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), | ||
| 618 | .driver_info = 0, | 615 | .driver_info = 0, |
| 619 | }, | 616 | }, |
| 620 | 617 | ||
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index d38bc20a60e2..71b6e92b8e9b 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c | |||
| @@ -1129,19 +1129,13 @@ static void cdc_ncm_disconnect(struct usb_interface *intf) | |||
| 1129 | usbnet_disconnect(intf); | 1129 | usbnet_disconnect(intf); |
| 1130 | } | 1130 | } |
| 1131 | 1131 | ||
| 1132 | static int cdc_ncm_manage_power(struct usbnet *dev, int status) | ||
| 1133 | { | ||
| 1134 | dev->intf->needs_remote_wakeup = status; | ||
| 1135 | return 0; | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | static const struct driver_info cdc_ncm_info = { | 1132 | static const struct driver_info cdc_ncm_info = { |
| 1139 | .description = "CDC NCM", | 1133 | .description = "CDC NCM", |
| 1140 | .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET, | 1134 | .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET, |
| 1141 | .bind = cdc_ncm_bind, | 1135 | .bind = cdc_ncm_bind, |
| 1142 | .unbind = cdc_ncm_unbind, | 1136 | .unbind = cdc_ncm_unbind, |
| 1143 | .check_connect = cdc_ncm_check_connect, | 1137 | .check_connect = cdc_ncm_check_connect, |
| 1144 | .manage_power = cdc_ncm_manage_power, | 1138 | .manage_power = usbnet_manage_power, |
| 1145 | .status = cdc_ncm_status, | 1139 | .status = cdc_ncm_status, |
| 1146 | .rx_fixup = cdc_ncm_rx_fixup, | 1140 | .rx_fixup = cdc_ncm_rx_fixup, |
| 1147 | .tx_fixup = cdc_ncm_tx_fixup, | 1141 | .tx_fixup = cdc_ncm_tx_fixup, |
| @@ -1155,7 +1149,7 @@ static const struct driver_info wwan_info = { | |||
| 1155 | .bind = cdc_ncm_bind, | 1149 | .bind = cdc_ncm_bind, |
| 1156 | .unbind = cdc_ncm_unbind, | 1150 | .unbind = cdc_ncm_unbind, |
| 1157 | .check_connect = cdc_ncm_check_connect, | 1151 | .check_connect = cdc_ncm_check_connect, |
| 1158 | .manage_power = cdc_ncm_manage_power, | 1152 | .manage_power = usbnet_manage_power, |
| 1159 | .status = cdc_ncm_status, | 1153 | .status = cdc_ncm_status, |
| 1160 | .rx_fixup = cdc_ncm_rx_fixup, | 1154 | .rx_fixup = cdc_ncm_rx_fixup, |
| 1161 | .tx_fixup = cdc_ncm_tx_fixup, | 1155 | .tx_fixup = cdc_ncm_tx_fixup, |
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 1ea91f4237f0..91d7cb9728eb 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c | |||
| @@ -383,6 +383,20 @@ static const struct usb_device_id products[] = { | |||
| 383 | USB_CDC_PROTO_NONE), | 383 | USB_CDC_PROTO_NONE), |
| 384 | .driver_info = (unsigned long)&qmi_wwan_info, | 384 | .driver_info = (unsigned long)&qmi_wwan_info, |
| 385 | }, | 385 | }, |
| 386 | { /* Dell Wireless 5800 (Novatel E362) */ | ||
| 387 | USB_DEVICE_AND_INTERFACE_INFO(0x413C, 0x8195, | ||
| 388 | USB_CLASS_COMM, | ||
| 389 | USB_CDC_SUBCLASS_ETHERNET, | ||
| 390 | USB_CDC_PROTO_NONE), | ||
| 391 | .driver_info = (unsigned long)&qmi_wwan_info, | ||
| 392 | }, | ||
| 393 | { /* Dell Wireless 5800 V2 (Novatel E362) */ | ||
| 394 | USB_DEVICE_AND_INTERFACE_INFO(0x413C, 0x8196, | ||
| 395 | USB_CLASS_COMM, | ||
| 396 | USB_CDC_SUBCLASS_ETHERNET, | ||
| 397 | USB_CDC_PROTO_NONE), | ||
| 398 | .driver_info = (unsigned long)&qmi_wwan_info, | ||
| 399 | }, | ||
| 386 | 400 | ||
| 387 | /* 3. Combined interface devices matching on interface number */ | 401 | /* 3. Combined interface devices matching on interface number */ |
| 388 | {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */ | 402 | {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */ |
| @@ -419,6 +433,7 @@ static const struct usb_device_id products[] = { | |||
| 419 | {QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */ | 433 | {QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */ |
| 420 | {QMI_FIXED_INTF(0x19d2, 0x0200, 1)}, | 434 | {QMI_FIXED_INTF(0x19d2, 0x0200, 1)}, |
| 421 | {QMI_FIXED_INTF(0x19d2, 0x0257, 3)}, /* ZTE MF821 */ | 435 | {QMI_FIXED_INTF(0x19d2, 0x0257, 3)}, /* ZTE MF821 */ |
| 436 | {QMI_FIXED_INTF(0x19d2, 0x0284, 4)}, /* ZTE MF880 */ | ||
| 422 | {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ | 437 | {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ |
| 423 | {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ | 438 | {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ |
| 424 | {QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */ | 439 | {QMI_FIXED_INTF(0x19d2, 0x1010, 4)}, /* ZTE (Vodafone) K3571-Z */ |
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index c04110ba677f..3d4bf01641b4 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
| @@ -719,7 +719,8 @@ int usbnet_stop (struct net_device *net) | |||
| 719 | dev->flags = 0; | 719 | dev->flags = 0; |
| 720 | del_timer_sync (&dev->delay); | 720 | del_timer_sync (&dev->delay); |
| 721 | tasklet_kill (&dev->bh); | 721 | tasklet_kill (&dev->bh); |
| 722 | if (info->manage_power) | 722 | if (info->manage_power && |
| 723 | !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags)) | ||
| 723 | info->manage_power(dev, 0); | 724 | info->manage_power(dev, 0); |
| 724 | else | 725 | else |
| 725 | usb_autopm_put_interface(dev->intf); | 726 | usb_autopm_put_interface(dev->intf); |
| @@ -794,14 +795,14 @@ int usbnet_open (struct net_device *net) | |||
| 794 | tasklet_schedule (&dev->bh); | 795 | tasklet_schedule (&dev->bh); |
| 795 | if (info->manage_power) { | 796 | if (info->manage_power) { |
| 796 | retval = info->manage_power(dev, 1); | 797 | retval = info->manage_power(dev, 1); |
| 797 | if (retval < 0) | 798 | if (retval < 0) { |
| 798 | goto done_manage_power_error; | 799 | retval = 0; |
| 799 | usb_autopm_put_interface(dev->intf); | 800 | set_bit(EVENT_NO_RUNTIME_PM, &dev->flags); |
| 801 | } else { | ||
| 802 | usb_autopm_put_interface(dev->intf); | ||
| 803 | } | ||
| 800 | } | 804 | } |
| 801 | return retval; | 805 | return retval; |
| 802 | |||
| 803 | done_manage_power_error: | ||
| 804 | clear_bit(EVENT_DEV_OPEN, &dev->flags); | ||
| 805 | done: | 806 | done: |
| 806 | usb_autopm_put_interface(dev->intf); | 807 | usb_autopm_put_interface(dev->intf); |
| 807 | done_nopm: | 808 | done_nopm: |
| @@ -1615,6 +1616,16 @@ void usbnet_device_suggests_idle(struct usbnet *dev) | |||
| 1615 | } | 1616 | } |
| 1616 | EXPORT_SYMBOL(usbnet_device_suggests_idle); | 1617 | EXPORT_SYMBOL(usbnet_device_suggests_idle); |
| 1617 | 1618 | ||
| 1619 | /* | ||
| 1620 | * For devices that can do without special commands | ||
| 1621 | */ | ||
| 1622 | int usbnet_manage_power(struct usbnet *dev, int on) | ||
| 1623 | { | ||
| 1624 | dev->intf->needs_remote_wakeup = on; | ||
| 1625 | return 0; | ||
| 1626 | } | ||
| 1627 | EXPORT_SYMBOL(usbnet_manage_power); | ||
| 1628 | |||
| 1618 | /*-------------------------------------------------------------------------*/ | 1629 | /*-------------------------------------------------------------------------*/ |
| 1619 | static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, | 1630 | static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, |
| 1620 | u16 value, u16 index, void *data, u16 size) | 1631 | u16 value, u16 index, void *data, u16 size) |
diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h index 6650fde99e1d..9f1e947f3557 100644 --- a/drivers/net/wimax/i2400m/i2400m-usb.h +++ b/drivers/net/wimax/i2400m/i2400m-usb.h | |||
| @@ -152,6 +152,9 @@ enum { | |||
| 152 | /* Device IDs */ | 152 | /* Device IDs */ |
| 153 | USB_DEVICE_ID_I6050 = 0x0186, | 153 | USB_DEVICE_ID_I6050 = 0x0186, |
| 154 | USB_DEVICE_ID_I6050_2 = 0x0188, | 154 | USB_DEVICE_ID_I6050_2 = 0x0188, |
| 155 | USB_DEVICE_ID_I6150 = 0x07d6, | ||
| 156 | USB_DEVICE_ID_I6150_2 = 0x07d7, | ||
| 157 | USB_DEVICE_ID_I6150_3 = 0x07d9, | ||
| 155 | USB_DEVICE_ID_I6250 = 0x0187, | 158 | USB_DEVICE_ID_I6250 = 0x0187, |
| 156 | }; | 159 | }; |
| 157 | 160 | ||
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 713d033891e6..080f36303a4f 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c | |||
| @@ -510,6 +510,9 @@ int i2400mu_probe(struct usb_interface *iface, | |||
| 510 | switch (id->idProduct) { | 510 | switch (id->idProduct) { |
| 511 | case USB_DEVICE_ID_I6050: | 511 | case USB_DEVICE_ID_I6050: |
| 512 | case USB_DEVICE_ID_I6050_2: | 512 | case USB_DEVICE_ID_I6050_2: |
| 513 | case USB_DEVICE_ID_I6150: | ||
| 514 | case USB_DEVICE_ID_I6150_2: | ||
| 515 | case USB_DEVICE_ID_I6150_3: | ||
| 513 | case USB_DEVICE_ID_I6250: | 516 | case USB_DEVICE_ID_I6250: |
| 514 | i2400mu->i6050 = 1; | 517 | i2400mu->i6050 = 1; |
| 515 | break; | 518 | break; |
| @@ -759,6 +762,9 @@ static | |||
| 759 | struct usb_device_id i2400mu_id_table[] = { | 762 | struct usb_device_id i2400mu_id_table[] = { |
| 760 | { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, | 763 | { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, |
| 761 | { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, | 764 | { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, |
| 765 | { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150) }, | ||
| 766 | { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_2) }, | ||
| 767 | { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_3) }, | ||
| 762 | { USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) }, | 768 | { USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) }, |
| 763 | { USB_DEVICE(0x8086, 0x0181) }, | 769 | { USB_DEVICE(0x8086, 0x0181) }, |
| 764 | { USB_DEVICE(0x8086, 0x1403) }, | 770 | { USB_DEVICE(0x8086, 0x1403) }, |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 062dfdff6364..67156efe14c4 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
| @@ -47,7 +47,7 @@ obj-$(CONFIG_RT2X00) += rt2x00/ | |||
| 47 | 47 | ||
| 48 | obj-$(CONFIG_P54_COMMON) += p54/ | 48 | obj-$(CONFIG_P54_COMMON) += p54/ |
| 49 | 49 | ||
| 50 | obj-$(CONFIG_ATH_COMMON) += ath/ | 50 | obj-$(CONFIG_ATH_CARDS) += ath/ |
| 51 | 51 | ||
| 52 | obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o | 52 | obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o |
| 53 | 53 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 4ffb6a584cd0..44f8b3f3cbed 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
| @@ -685,6 +685,14 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp) | |||
| 685 | * to mac80211. | 685 | * to mac80211. |
| 686 | */ | 686 | */ |
| 687 | rx_status = IEEE80211_SKB_RXCB(entry->skb); | 687 | rx_status = IEEE80211_SKB_RXCB(entry->skb); |
| 688 | |||
| 689 | /* Ensure that all fields of rx_status are initialized | ||
| 690 | * properly. The skb->cb array was used for driver | ||
| 691 | * specific informations, so rx_status might contain | ||
| 692 | * garbage. | ||
| 693 | */ | ||
| 694 | memset(rx_status, 0, sizeof(*rx_status)); | ||
| 695 | |||
| 688 | rx_status->mactime = rxdesc.timestamp; | 696 | rx_status->mactime = rxdesc.timestamp; |
| 689 | rx_status->band = rt2x00dev->curr_band; | 697 | rx_status->band = rt2x00dev->curr_band; |
| 690 | rx_status->freq = rt2x00dev->curr_freq; | 698 | rx_status->freq = rt2x00dev->curr_freq; |
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 9bbeabf66c54..bd45eb7bedc8 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h | |||
| @@ -69,6 +69,7 @@ struct usbnet { | |||
| 69 | # define EVENT_DEV_ASLEEP 6 | 69 | # define EVENT_DEV_ASLEEP 6 |
| 70 | # define EVENT_DEV_OPEN 7 | 70 | # define EVENT_DEV_OPEN 7 |
| 71 | # define EVENT_DEVICE_REPORT_IDLE 8 | 71 | # define EVENT_DEVICE_REPORT_IDLE 8 |
| 72 | # define EVENT_NO_RUNTIME_PM 9 | ||
| 72 | }; | 73 | }; |
| 73 | 74 | ||
| 74 | static inline struct usb_driver *driver_of(struct usb_interface *intf) | 75 | static inline struct usb_driver *driver_of(struct usb_interface *intf) |
| @@ -240,4 +241,6 @@ extern void usbnet_set_msglevel(struct net_device *, u32); | |||
| 240 | extern void usbnet_get_drvinfo(struct net_device *, struct ethtool_drvinfo *); | 241 | extern void usbnet_get_drvinfo(struct net_device *, struct ethtool_drvinfo *); |
| 241 | extern int usbnet_nway_reset(struct net_device *net); | 242 | extern int usbnet_nway_reset(struct net_device *net); |
| 242 | 243 | ||
| 244 | extern int usbnet_manage_power(struct usbnet *, int); | ||
| 245 | |||
| 243 | #endif /* __LINUX_USB_USBNET_H */ | 246 | #endif /* __LINUX_USB_USBNET_H */ |
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index ba1d3615acbb..183292722f6e 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h | |||
| @@ -318,6 +318,7 @@ extern void inet_csk_reqsk_queue_prune(struct sock *parent, | |||
| 318 | const unsigned long max_rto); | 318 | const unsigned long max_rto); |
| 319 | 319 | ||
| 320 | extern void inet_csk_destroy_sock(struct sock *sk); | 320 | extern void inet_csk_destroy_sock(struct sock *sk); |
| 321 | extern void inet_csk_prepare_forced_close(struct sock *sk); | ||
| 321 | 322 | ||
| 322 | /* | 323 | /* |
| 323 | * LISTEN is a special case for poll.. | 324 | * LISTEN is a special case for poll.. |
diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 7af1ea893038..23b3a7c58783 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h | |||
| @@ -78,6 +78,13 @@ struct ra_msg { | |||
| 78 | __be32 retrans_timer; | 78 | __be32 retrans_timer; |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | struct rd_msg { | ||
| 82 | struct icmp6hdr icmph; | ||
| 83 | struct in6_addr target; | ||
| 84 | struct in6_addr dest; | ||
| 85 | __u8 opt[0]; | ||
| 86 | }; | ||
| 87 | |||
| 81 | struct nd_opt_hdr { | 88 | struct nd_opt_hdr { |
| 82 | __u8 nd_opt_type; | 89 | __u8 nd_opt_type; |
| 83 | __u8 nd_opt_len; | 90 | __u8 nd_opt_len; |
diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index afbb18a0227c..5db297514aec 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h | |||
| @@ -163,6 +163,9 @@ struct br_port_msg { | |||
| 163 | 163 | ||
| 164 | struct br_mdb_entry { | 164 | struct br_mdb_entry { |
| 165 | __u32 ifindex; | 165 | __u32 ifindex; |
| 166 | #define MDB_TEMPORARY 0 | ||
| 167 | #define MDB_PERMANENT 1 | ||
| 168 | __u8 state; | ||
| 166 | struct { | 169 | struct { |
| 167 | union { | 170 | union { |
| 168 | __be32 ip4; | 171 | __be32 ip4; |
diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c index f49da5814bc3..350bf62b2ae3 100644 --- a/net/atm/atm_sysfs.c +++ b/net/atm/atm_sysfs.c | |||
| @@ -14,49 +14,45 @@ static ssize_t show_type(struct device *cdev, | |||
| 14 | struct device_attribute *attr, char *buf) | 14 | struct device_attribute *attr, char *buf) |
| 15 | { | 15 | { |
| 16 | struct atm_dev *adev = to_atm_dev(cdev); | 16 | struct atm_dev *adev = to_atm_dev(cdev); |
| 17 | return sprintf(buf, "%s\n", adev->type); | 17 | |
| 18 | return scnprintf(buf, PAGE_SIZE, "%s\n", adev->type); | ||
| 18 | } | 19 | } |
| 19 | 20 | ||
| 20 | static ssize_t show_address(struct device *cdev, | 21 | static ssize_t show_address(struct device *cdev, |
| 21 | struct device_attribute *attr, char *buf) | 22 | struct device_attribute *attr, char *buf) |
| 22 | { | 23 | { |
| 23 | char *pos = buf; | ||
| 24 | struct atm_dev *adev = to_atm_dev(cdev); | 24 | struct atm_dev *adev = to_atm_dev(cdev); |
| 25 | int i; | ||
| 26 | |||
| 27 | for (i = 0; i < (ESI_LEN - 1); i++) | ||
| 28 | pos += sprintf(pos, "%02x:", adev->esi[i]); | ||
| 29 | pos += sprintf(pos, "%02x\n", adev->esi[i]); | ||
| 30 | 25 | ||
| 31 | return pos - buf; | 26 | return scnprintf(buf, PAGE_SIZE, "%pM\n", adev->esi); |
| 32 | } | 27 | } |
| 33 | 28 | ||
| 34 | static ssize_t show_atmaddress(struct device *cdev, | 29 | static ssize_t show_atmaddress(struct device *cdev, |
| 35 | struct device_attribute *attr, char *buf) | 30 | struct device_attribute *attr, char *buf) |
| 36 | { | 31 | { |
| 37 | unsigned long flags; | 32 | unsigned long flags; |
| 38 | char *pos = buf; | ||
| 39 | struct atm_dev *adev = to_atm_dev(cdev); | 33 | struct atm_dev *adev = to_atm_dev(cdev); |
| 40 | struct atm_dev_addr *aaddr; | 34 | struct atm_dev_addr *aaddr; |
| 41 | int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin; | 35 | int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin; |
| 42 | int i, j; | 36 | int i, j, count = 0; |
| 43 | 37 | ||
| 44 | spin_lock_irqsave(&adev->lock, flags); | 38 | spin_lock_irqsave(&adev->lock, flags); |
| 45 | list_for_each_entry(aaddr, &adev->local, entry) { | 39 | list_for_each_entry(aaddr, &adev->local, entry) { |
| 46 | for (i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) { | 40 | for (i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) { |
| 47 | if (j == *fmt) { | 41 | if (j == *fmt) { |
| 48 | pos += sprintf(pos, "."); | 42 | count += scnprintf(buf + count, |
| 43 | PAGE_SIZE - count, "."); | ||
| 49 | ++fmt; | 44 | ++fmt; |
| 50 | j = 0; | 45 | j = 0; |
| 51 | } | 46 | } |
| 52 | pos += sprintf(pos, "%02x", | 47 | count += scnprintf(buf + count, |
| 53 | aaddr->addr.sas_addr.prv[i]); | 48 | PAGE_SIZE - count, "%02x", |
| 49 | aaddr->addr.sas_addr.prv[i]); | ||
| 54 | } | 50 | } |
| 55 | pos += sprintf(pos, "\n"); | 51 | count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); |
| 56 | } | 52 | } |
| 57 | spin_unlock_irqrestore(&adev->lock, flags); | 53 | spin_unlock_irqrestore(&adev->lock, flags); |
| 58 | 54 | ||
| 59 | return pos - buf; | 55 | return count; |
| 60 | } | 56 | } |
| 61 | 57 | ||
| 62 | static ssize_t show_atmindex(struct device *cdev, | 58 | static ssize_t show_atmindex(struct device *cdev, |
| @@ -64,25 +60,21 @@ static ssize_t show_atmindex(struct device *cdev, | |||
| 64 | { | 60 | { |
| 65 | struct atm_dev *adev = to_atm_dev(cdev); | 61 | struct atm_dev *adev = to_atm_dev(cdev); |
| 66 | 62 | ||
| 67 | return sprintf(buf, "%d\n", adev->number); | 63 | return scnprintf(buf, PAGE_SIZE, "%d\n", adev->number); |
| 68 | } | 64 | } |
| 69 | 65 | ||
| 70 | static ssize_t show_carrier(struct device *cdev, | 66 | static ssize_t show_carrier(struct device *cdev, |
| 71 | struct device_attribute *attr, char *buf) | 67 | struct device_attribute *attr, char *buf) |
| 72 | { | 68 | { |
| 73 | char *pos = buf; | ||
| 74 | struct atm_dev *adev = to_atm_dev(cdev); | 69 | struct atm_dev *adev = to_atm_dev(cdev); |
| 75 | 70 | ||
| 76 | pos += sprintf(pos, "%d\n", | 71 | return scnprintf(buf, PAGE_SIZE, "%d\n", |
| 77 | adev->signal == ATM_PHY_SIG_LOST ? 0 : 1); | 72 | adev->signal == ATM_PHY_SIG_LOST ? 0 : 1); |
| 78 | |||
| 79 | return pos - buf; | ||
| 80 | } | 73 | } |
| 81 | 74 | ||
| 82 | static ssize_t show_link_rate(struct device *cdev, | 75 | static ssize_t show_link_rate(struct device *cdev, |
| 83 | struct device_attribute *attr, char *buf) | 76 | struct device_attribute *attr, char *buf) |
| 84 | { | 77 | { |
| 85 | char *pos = buf; | ||
| 86 | struct atm_dev *adev = to_atm_dev(cdev); | 78 | struct atm_dev *adev = to_atm_dev(cdev); |
| 87 | int link_rate; | 79 | int link_rate; |
| 88 | 80 | ||
| @@ -100,9 +92,7 @@ static ssize_t show_link_rate(struct device *cdev, | |||
| 100 | default: | 92 | default: |
| 101 | link_rate = adev->link_rate * 8 * 53; | 93 | link_rate = adev->link_rate * 8 * 53; |
| 102 | } | 94 | } |
| 103 | pos += sprintf(pos, "%d\n", link_rate); | 95 | return scnprintf(buf, PAGE_SIZE, "%d\n", link_rate); |
| 104 | |||
| 105 | return pos - buf; | ||
| 106 | } | 96 | } |
| 107 | 97 | ||
| 108 | static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); | 98 | static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); |
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 6f0a2eebcb27..acc9f4cc18f7 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c | |||
| @@ -83,9 +83,12 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, | |||
| 83 | if (port) { | 83 | if (port) { |
| 84 | struct br_mdb_entry e; | 84 | struct br_mdb_entry e; |
| 85 | e.ifindex = port->dev->ifindex; | 85 | e.ifindex = port->dev->ifindex; |
| 86 | e.addr.u.ip4 = p->addr.u.ip4; | 86 | e.state = p->state; |
| 87 | if (p->addr.proto == htons(ETH_P_IP)) | ||
| 88 | e.addr.u.ip4 = p->addr.u.ip4; | ||
| 87 | #if IS_ENABLED(CONFIG_IPV6) | 89 | #if IS_ENABLED(CONFIG_IPV6) |
| 88 | e.addr.u.ip6 = p->addr.u.ip6; | 90 | if (p->addr.proto == htons(ETH_P_IPV6)) |
| 91 | e.addr.u.ip6 = p->addr.u.ip6; | ||
| 89 | #endif | 92 | #endif |
| 90 | e.addr.proto = p->addr.proto; | 93 | e.addr.proto = p->addr.proto; |
| 91 | if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(e), &e)) { | 94 | if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(e), &e)) { |
| @@ -253,6 +256,8 @@ static bool is_valid_mdb_entry(struct br_mdb_entry *entry) | |||
| 253 | #endif | 256 | #endif |
| 254 | } else | 257 | } else |
| 255 | return false; | 258 | return false; |
| 259 | if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY) | ||
| 260 | return false; | ||
| 256 | 261 | ||
| 257 | return true; | 262 | return true; |
| 258 | } | 263 | } |
| @@ -310,7 +315,7 @@ static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 310 | } | 315 | } |
| 311 | 316 | ||
| 312 | static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, | 317 | static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, |
| 313 | struct br_ip *group) | 318 | struct br_ip *group, unsigned char state) |
| 314 | { | 319 | { |
| 315 | struct net_bridge_mdb_entry *mp; | 320 | struct net_bridge_mdb_entry *mp; |
| 316 | struct net_bridge_port_group *p; | 321 | struct net_bridge_port_group *p; |
| @@ -336,7 +341,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, | |||
| 336 | break; | 341 | break; |
| 337 | } | 342 | } |
| 338 | 343 | ||
| 339 | p = br_multicast_new_port_group(port, group, *pp); | 344 | p = br_multicast_new_port_group(port, group, *pp, state); |
| 340 | if (unlikely(!p)) | 345 | if (unlikely(!p)) |
| 341 | return -ENOMEM; | 346 | return -ENOMEM; |
| 342 | rcu_assign_pointer(*pp, p); | 347 | rcu_assign_pointer(*pp, p); |
| @@ -373,7 +378,7 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br, | |||
| 373 | #endif | 378 | #endif |
| 374 | 379 | ||
| 375 | spin_lock_bh(&br->multicast_lock); | 380 | spin_lock_bh(&br->multicast_lock); |
| 376 | ret = br_mdb_add_group(br, p, &ip); | 381 | ret = br_mdb_add_group(br, p, &ip, entry->state); |
| 377 | spin_unlock_bh(&br->multicast_lock); | 382 | spin_unlock_bh(&br->multicast_lock); |
| 378 | return ret; | 383 | return ret; |
| 379 | } | 384 | } |
| @@ -479,3 +484,10 @@ void br_mdb_init(void) | |||
| 479 | rtnl_register(PF_BRIDGE, RTM_NEWMDB, br_mdb_add, NULL, NULL); | 484 | rtnl_register(PF_BRIDGE, RTM_NEWMDB, br_mdb_add, NULL, NULL); |
| 480 | rtnl_register(PF_BRIDGE, RTM_DELMDB, br_mdb_del, NULL, NULL); | 485 | rtnl_register(PF_BRIDGE, RTM_DELMDB, br_mdb_del, NULL, NULL); |
| 481 | } | 486 | } |
| 487 | |||
| 488 | void br_mdb_uninit(void) | ||
| 489 | { | ||
| 490 | rtnl_unregister(PF_BRIDGE, RTM_GETMDB); | ||
| 491 | rtnl_unregister(PF_BRIDGE, RTM_NEWMDB); | ||
| 492 | rtnl_unregister(PF_BRIDGE, RTM_DELMDB); | ||
| 493 | } | ||
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 1093c89095d8..5391ca43336a 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -279,7 +279,7 @@ static void br_multicast_port_group_expired(unsigned long data) | |||
| 279 | 279 | ||
| 280 | spin_lock(&br->multicast_lock); | 280 | spin_lock(&br->multicast_lock); |
| 281 | if (!netif_running(br->dev) || timer_pending(&pg->timer) || | 281 | if (!netif_running(br->dev) || timer_pending(&pg->timer) || |
| 282 | hlist_unhashed(&pg->mglist)) | 282 | hlist_unhashed(&pg->mglist) || pg->state & MDB_PERMANENT) |
| 283 | goto out; | 283 | goto out; |
| 284 | 284 | ||
| 285 | br_multicast_del_pg(br, pg); | 285 | br_multicast_del_pg(br, pg); |
| @@ -622,7 +622,8 @@ out: | |||
| 622 | struct net_bridge_port_group *br_multicast_new_port_group( | 622 | struct net_bridge_port_group *br_multicast_new_port_group( |
| 623 | struct net_bridge_port *port, | 623 | struct net_bridge_port *port, |
| 624 | struct br_ip *group, | 624 | struct br_ip *group, |
| 625 | struct net_bridge_port_group __rcu *next) | 625 | struct net_bridge_port_group __rcu *next, |
| 626 | unsigned char state) | ||
| 626 | { | 627 | { |
| 627 | struct net_bridge_port_group *p; | 628 | struct net_bridge_port_group *p; |
| 628 | 629 | ||
| @@ -632,6 +633,7 @@ struct net_bridge_port_group *br_multicast_new_port_group( | |||
| 632 | 633 | ||
| 633 | p->addr = *group; | 634 | p->addr = *group; |
| 634 | p->port = port; | 635 | p->port = port; |
| 636 | p->state = state; | ||
| 635 | rcu_assign_pointer(p->next, next); | 637 | rcu_assign_pointer(p->next, next); |
| 636 | hlist_add_head(&p->mglist, &port->mglist); | 638 | hlist_add_head(&p->mglist, &port->mglist); |
| 637 | setup_timer(&p->timer, br_multicast_port_group_expired, | 639 | setup_timer(&p->timer, br_multicast_port_group_expired, |
| @@ -674,7 +676,7 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
| 674 | break; | 676 | break; |
| 675 | } | 677 | } |
| 676 | 678 | ||
| 677 | p = br_multicast_new_port_group(port, group, *pp); | 679 | p = br_multicast_new_port_group(port, group, *pp, MDB_TEMPORARY); |
| 678 | if (unlikely(!p)) | 680 | if (unlikely(!p)) |
| 679 | goto err; | 681 | goto err; |
| 680 | rcu_assign_pointer(*pp, p); | 682 | rcu_assign_pointer(*pp, p); |
| @@ -1165,7 +1167,6 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
| 1165 | if (max_delay) | 1167 | if (max_delay) |
| 1166 | group = &mld->mld_mca; | 1168 | group = &mld->mld_mca; |
| 1167 | } else if (skb->len >= sizeof(*mld2q)) { | 1169 | } else if (skb->len >= sizeof(*mld2q)) { |
| 1168 | u16 mrc; | ||
| 1169 | if (!pskb_may_pull(skb, sizeof(*mld2q))) { | 1170 | if (!pskb_may_pull(skb, sizeof(*mld2q))) { |
| 1170 | err = -EINVAL; | 1171 | err = -EINVAL; |
| 1171 | goto out; | 1172 | goto out; |
| @@ -1173,8 +1174,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
| 1173 | mld2q = (struct mld2_query *)icmp6_hdr(skb); | 1174 | mld2q = (struct mld2_query *)icmp6_hdr(skb); |
| 1174 | if (!mld2q->mld2q_nsrcs) | 1175 | if (!mld2q->mld2q_nsrcs) |
| 1175 | group = &mld2q->mld2q_mca; | 1176 | group = &mld2q->mld2q_mca; |
| 1176 | mrc = ntohs(mld2q->mld2q_mrc); | 1177 | max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(ntohs(mld2q->mld2q_mrc)) : 1; |
| 1177 | max_delay = mrc ? MLDV2_MRC(mrc) : 1; | ||
| 1178 | } | 1178 | } |
| 1179 | 1179 | ||
| 1180 | if (!group) | 1180 | if (!group) |
| @@ -1633,6 +1633,7 @@ void br_multicast_stop(struct net_bridge *br) | |||
| 1633 | del_timer_sync(&br->multicast_querier_timer); | 1633 | del_timer_sync(&br->multicast_querier_timer); |
| 1634 | del_timer_sync(&br->multicast_query_timer); | 1634 | del_timer_sync(&br->multicast_query_timer); |
| 1635 | 1635 | ||
| 1636 | br_mdb_uninit(); | ||
| 1636 | spin_lock_bh(&br->multicast_lock); | 1637 | spin_lock_bh(&br->multicast_lock); |
| 1637 | mdb = mlock_dereference(br->mdb, br); | 1638 | mdb = mlock_dereference(br->mdb, br); |
| 1638 | if (!mdb) | 1639 | if (!mdb) |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index dead9dfe865b..97ba0189c6f7 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
| @@ -305,5 +305,4 @@ int __init br_netlink_init(void) | |||
| 305 | void __exit br_netlink_fini(void) | 305 | void __exit br_netlink_fini(void) |
| 306 | { | 306 | { |
| 307 | rtnl_link_unregister(&br_link_ops); | 307 | rtnl_link_unregister(&br_link_ops); |
| 308 | rtnl_unregister_all(PF_BRIDGE); | ||
| 309 | } | 308 | } |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index f21a739a6186..8d83be5ffedc 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -83,6 +83,7 @@ struct net_bridge_port_group { | |||
| 83 | struct rcu_head rcu; | 83 | struct rcu_head rcu; |
| 84 | struct timer_list timer; | 84 | struct timer_list timer; |
| 85 | struct br_ip addr; | 85 | struct br_ip addr; |
| 86 | unsigned char state; | ||
| 86 | }; | 87 | }; |
| 87 | 88 | ||
| 88 | struct net_bridge_mdb_entry | 89 | struct net_bridge_mdb_entry |
| @@ -443,8 +444,10 @@ extern void br_multicast_free_pg(struct rcu_head *head); | |||
| 443 | extern struct net_bridge_port_group *br_multicast_new_port_group( | 444 | extern struct net_bridge_port_group *br_multicast_new_port_group( |
| 444 | struct net_bridge_port *port, | 445 | struct net_bridge_port *port, |
| 445 | struct br_ip *group, | 446 | struct br_ip *group, |
| 446 | struct net_bridge_port_group *next); | 447 | struct net_bridge_port_group *next, |
| 448 | unsigned char state); | ||
| 447 | extern void br_mdb_init(void); | 449 | extern void br_mdb_init(void); |
| 450 | extern void br_mdb_uninit(void); | ||
| 448 | extern void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, | 451 | extern void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, |
| 449 | struct br_ip *group, int type); | 452 | struct br_ip *group, int type); |
| 450 | 453 | ||
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 176ecdba4a22..4f9f5eb478f1 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
| @@ -439,8 +439,8 @@ exit: | |||
| 439 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 439 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); |
| 440 | return NULL; | 440 | return NULL; |
| 441 | put_and_exit: | 441 | put_and_exit: |
| 442 | bh_unlock_sock(newsk); | 442 | inet_csk_prepare_forced_close(newsk); |
| 443 | sock_put(newsk); | 443 | dccp_done(newsk); |
| 444 | goto exit; | 444 | goto exit; |
| 445 | } | 445 | } |
| 446 | 446 | ||
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 56840b249f3b..6e05981f271e 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
| @@ -585,7 +585,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, | |||
| 585 | newinet->inet_rcv_saddr = LOOPBACK4_IPV6; | 585 | newinet->inet_rcv_saddr = LOOPBACK4_IPV6; |
| 586 | 586 | ||
| 587 | if (__inet_inherit_port(sk, newsk) < 0) { | 587 | if (__inet_inherit_port(sk, newsk) < 0) { |
| 588 | sock_put(newsk); | 588 | inet_csk_prepare_forced_close(newsk); |
| 589 | dccp_done(newsk); | ||
| 589 | goto out; | 590 | goto out; |
| 590 | } | 591 | } |
| 591 | __inet6_hash(newsk, NULL); | 592 | __inet6_hash(newsk, NULL); |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 2026542d6836..d0670f00d524 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
| @@ -710,6 +710,22 @@ void inet_csk_destroy_sock(struct sock *sk) | |||
| 710 | } | 710 | } |
| 711 | EXPORT_SYMBOL(inet_csk_destroy_sock); | 711 | EXPORT_SYMBOL(inet_csk_destroy_sock); |
| 712 | 712 | ||
| 713 | /* This function allows to force a closure of a socket after the call to | ||
| 714 | * tcp/dccp_create_openreq_child(). | ||
| 715 | */ | ||
| 716 | void inet_csk_prepare_forced_close(struct sock *sk) | ||
| 717 | { | ||
| 718 | /* sk_clone_lock locked the socket and set refcnt to 2 */ | ||
| 719 | bh_unlock_sock(sk); | ||
| 720 | sock_put(sk); | ||
| 721 | |||
| 722 | /* The below has to be done to allow calling inet_csk_destroy_sock */ | ||
| 723 | sock_set_flag(sk, SOCK_DEAD); | ||
| 724 | percpu_counter_inc(sk->sk_prot->orphan_count); | ||
| 725 | inet_sk(sk)->inet_num = 0; | ||
| 726 | } | ||
| 727 | EXPORT_SYMBOL(inet_csk_prepare_forced_close); | ||
| 728 | |||
| 713 | int inet_csk_listen_start(struct sock *sk, const int nr_table_entries) | 729 | int inet_csk_listen_start(struct sock *sk, const int nr_table_entries) |
| 714 | { | 730 | { |
| 715 | struct inet_sock *inet = inet_sk(sk); | 731 | struct inet_sock *inet = inet_sk(sk); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1ed230716d51..54139fa514e6 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -1767,10 +1767,8 @@ exit: | |||
| 1767 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 1767 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); |
| 1768 | return NULL; | 1768 | return NULL; |
| 1769 | put_and_exit: | 1769 | put_and_exit: |
| 1770 | tcp_clear_xmit_timers(newsk); | 1770 | inet_csk_prepare_forced_close(newsk); |
| 1771 | tcp_cleanup_congestion_control(newsk); | 1771 | tcp_done(newsk); |
| 1772 | bh_unlock_sock(newsk); | ||
| 1773 | sock_put(newsk); | ||
| 1774 | goto exit; | 1772 | goto exit; |
| 1775 | } | 1773 | } |
| 1776 | EXPORT_SYMBOL(tcp_v4_syn_recv_sock); | 1774 | EXPORT_SYMBOL(tcp_v4_syn_recv_sock); |
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 2068ac4fbdad..4ea244891b58 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
| @@ -41,6 +41,6 @@ obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o | |||
| 41 | obj-$(CONFIG_IPV6_GRE) += ip6_gre.o | 41 | obj-$(CONFIG_IPV6_GRE) += ip6_gre.o |
| 42 | 42 | ||
| 43 | obj-y += addrconf_core.o exthdrs_core.o | 43 | obj-y += addrconf_core.o exthdrs_core.o |
| 44 | obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6_offload) | 44 | obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload) |
| 45 | 45 | ||
| 46 | obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o | 46 | obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 6fca01f136ad..408cac4ae00a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -534,8 +534,7 @@ void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex, | |||
| 534 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_ATOMIC); | 534 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_ATOMIC); |
| 535 | return; | 535 | return; |
| 536 | errout: | 536 | errout: |
| 537 | if (err < 0) | 537 | rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err); |
| 538 | rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err); | ||
| 539 | } | 538 | } |
| 540 | 539 | ||
| 541 | static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = { | 540 | static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = { |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index f2a007b7bde3..6574175795df 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
| @@ -1314,6 +1314,12 @@ out: | |||
| 1314 | 1314 | ||
| 1315 | static void ndisc_redirect_rcv(struct sk_buff *skb) | 1315 | static void ndisc_redirect_rcv(struct sk_buff *skb) |
| 1316 | { | 1316 | { |
| 1317 | u8 *hdr; | ||
| 1318 | struct ndisc_options ndopts; | ||
| 1319 | struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb); | ||
| 1320 | u32 ndoptlen = skb->tail - (skb->transport_header + | ||
| 1321 | offsetof(struct rd_msg, opt)); | ||
| 1322 | |||
| 1317 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | 1323 | #ifdef CONFIG_IPV6_NDISC_NODETYPE |
| 1318 | switch (skb->ndisc_nodetype) { | 1324 | switch (skb->ndisc_nodetype) { |
| 1319 | case NDISC_NODETYPE_HOST: | 1325 | case NDISC_NODETYPE_HOST: |
| @@ -1330,6 +1336,17 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
| 1330 | return; | 1336 | return; |
| 1331 | } | 1337 | } |
| 1332 | 1338 | ||
| 1339 | if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) | ||
| 1340 | return; | ||
| 1341 | |||
| 1342 | if (!ndopts.nd_opts_rh) | ||
| 1343 | return; | ||
| 1344 | |||
| 1345 | hdr = (u8 *)ndopts.nd_opts_rh; | ||
| 1346 | hdr += 8; | ||
| 1347 | if (!pskb_pull(skb, hdr - skb_transport_header(skb))) | ||
| 1348 | return; | ||
| 1349 | |||
| 1333 | icmpv6_notify(skb, NDISC_REDIRECT, 0, 0); | 1350 | icmpv6_notify(skb, NDISC_REDIRECT, 0, 0); |
| 1334 | } | 1351 | } |
| 1335 | 1352 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 6565cf55eb1e..93825dd3a7c0 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -1288,7 +1288,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
| 1288 | #endif | 1288 | #endif |
| 1289 | 1289 | ||
| 1290 | if (__inet_inherit_port(sk, newsk) < 0) { | 1290 | if (__inet_inherit_port(sk, newsk) < 0) { |
| 1291 | sock_put(newsk); | 1291 | inet_csk_prepare_forced_close(newsk); |
| 1292 | tcp_done(newsk); | ||
| 1292 | goto out; | 1293 | goto out; |
| 1293 | } | 1294 | } |
| 1294 | __inet6_hash(newsk, NULL); | 1295 | __inet6_hash(newsk, NULL); |
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c index e748aed290aa..b7c7f815deae 100644 --- a/net/mac802154/ieee802154_dev.c +++ b/net/mac802154/ieee802154_dev.c | |||
| @@ -224,9 +224,9 @@ void ieee802154_free_device(struct ieee802154_dev *hw) | |||
| 224 | 224 | ||
| 225 | BUG_ON(!list_empty(&priv->slaves)); | 225 | BUG_ON(!list_empty(&priv->slaves)); |
| 226 | 226 | ||
| 227 | wpan_phy_free(priv->phy); | ||
| 228 | |||
| 229 | mutex_destroy(&priv->slaves_mtx); | 227 | mutex_destroy(&priv->slaves_mtx); |
| 228 | |||
| 229 | wpan_phy_free(priv->phy); | ||
| 230 | } | 230 | } |
| 231 | EXPORT_SYMBOL(ieee802154_free_device); | 231 | EXPORT_SYMBOL(ieee802154_free_device); |
| 232 | 232 | ||
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index c8a1eb6eca2d..c0353d55d56f 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -669,6 +669,9 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, | |||
| 669 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; | 669 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; |
| 670 | int err; | 670 | int err; |
| 671 | 671 | ||
| 672 | if (addr_len < sizeof(struct sockaddr_nl)) | ||
| 673 | return -EINVAL; | ||
| 674 | |||
| 672 | if (nladdr->nl_family != AF_NETLINK) | 675 | if (nladdr->nl_family != AF_NETLINK) |
| 673 | return -EINVAL; | 676 | return -EINVAL; |
| 674 | 677 | ||
| @@ -2059,7 +2062,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v) | |||
| 2059 | struct sock *s = v; | 2062 | struct sock *s = v; |
| 2060 | struct netlink_sock *nlk = nlk_sk(s); | 2063 | struct netlink_sock *nlk = nlk_sk(s); |
| 2061 | 2064 | ||
| 2062 | seq_printf(seq, "%pK %-3d %-6d %08x %-8d %-8d %pK %-8d %-8d %-8lu\n", | 2065 | seq_printf(seq, "%pK %-3d %-6u %08x %-8d %-8d %pK %-8d %-8d %-8lu\n", |
| 2063 | s, | 2066 | s, |
| 2064 | s->sk_protocol, | 2067 | s->sk_protocol, |
| 2065 | nlk->portid, | 2068 | nlk->portid, |
diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index a9edd2e205f4..c26210618e14 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig | |||
| @@ -66,12 +66,36 @@ config SCTP_DBG_OBJCNT | |||
| 66 | 'cat /proc/net/sctp/sctp_dbg_objcnt' | 66 | 'cat /proc/net/sctp/sctp_dbg_objcnt' |
| 67 | 67 | ||
| 68 | If unsure, say N | 68 | If unsure, say N |
| 69 | choice | ||
| 70 | prompt "Default SCTP cookie HMAC encoding" | ||
| 71 | default SCTP_COOKIE_HMAC_MD5 | ||
| 72 | help | ||
| 73 | This option sets the default sctp cookie hmac algorithm | ||
| 74 | when in doubt select 'md5' | ||
| 75 | |||
| 76 | config SCTP_DEFAULT_COOKIE_HMAC_MD5 | ||
| 77 | bool "Enable optional MD5 hmac cookie generation" | ||
| 78 | help | ||
| 79 | Enable optional MD5 hmac based SCTP cookie generation | ||
| 80 | select SCTP_COOKIE_HMAC_MD5 | ||
| 81 | |||
| 82 | config SCTP_DEFAULT_COOKIE_HMAC_SHA1 | ||
| 83 | bool "Enable optional SHA1 hmac cookie generation" | ||
| 84 | help | ||
| 85 | Enable optional SHA1 hmac based SCTP cookie generation | ||
| 86 | select SCTP_COOKIE_HMAC_SHA1 | ||
| 87 | |||
| 88 | config SCTP_DEFAULT_COOKIE_HMAC_NONE | ||
| 89 | bool "Use no hmac alg in SCTP cookie generation" | ||
| 90 | help | ||
| 91 | Use no hmac algorithm in SCTP cookie generation | ||
| 92 | |||
| 93 | endchoice | ||
| 69 | 94 | ||
| 70 | config SCTP_COOKIE_HMAC_MD5 | 95 | config SCTP_COOKIE_HMAC_MD5 |
| 71 | bool "Enable optional MD5 hmac cookie generation" | 96 | bool "Enable optional MD5 hmac cookie generation" |
| 72 | help | 97 | help |
| 73 | Enable optional MD5 hmac based SCTP cookie generation | 98 | Enable optional MD5 hmac based SCTP cookie generation |
| 74 | default y | ||
| 75 | select CRYPTO_HMAC if SCTP_COOKIE_HMAC_MD5 | 99 | select CRYPTO_HMAC if SCTP_COOKIE_HMAC_MD5 |
| 76 | select CRYPTO_MD5 if SCTP_COOKIE_HMAC_MD5 | 100 | select CRYPTO_MD5 if SCTP_COOKIE_HMAC_MD5 |
| 77 | 101 | ||
| @@ -79,7 +103,6 @@ config SCTP_COOKIE_HMAC_SHA1 | |||
| 79 | bool "Enable optional SHA1 hmac cookie generation" | 103 | bool "Enable optional SHA1 hmac cookie generation" |
| 80 | help | 104 | help |
| 81 | Enable optional SHA1 hmac based SCTP cookie generation | 105 | Enable optional SHA1 hmac based SCTP cookie generation |
| 82 | default y | ||
| 83 | select CRYPTO_HMAC if SCTP_COOKIE_HMAC_SHA1 | 106 | select CRYPTO_HMAC if SCTP_COOKIE_HMAC_SHA1 |
| 84 | select CRYPTO_SHA1 if SCTP_COOKIE_HMAC_SHA1 | 107 | select CRYPTO_SHA1 if SCTP_COOKIE_HMAC_SHA1 |
| 85 | 108 | ||
diff --git a/net/sctp/probe.c b/net/sctp/probe.c index bc6cd75cc1dc..5f7518de2fd1 100644 --- a/net/sctp/probe.c +++ b/net/sctp/probe.c | |||
| @@ -122,7 +122,8 @@ static const struct file_operations sctpprobe_fops = { | |||
| 122 | .llseek = noop_llseek, | 122 | .llseek = noop_llseek, |
| 123 | }; | 123 | }; |
| 124 | 124 | ||
| 125 | sctp_disposition_t jsctp_sf_eat_sack(const struct sctp_endpoint *ep, | 125 | sctp_disposition_t jsctp_sf_eat_sack(struct net *net, |
| 126 | const struct sctp_endpoint *ep, | ||
| 126 | const struct sctp_association *asoc, | 127 | const struct sctp_association *asoc, |
| 127 | const sctp_subtype_t type, | 128 | const sctp_subtype_t type, |
| 128 | void *arg, | 129 | void *arg, |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 2c7785bacf74..f898b1c58bd2 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
| @@ -1191,9 +1191,9 @@ static int __net_init sctp_net_init(struct net *net) | |||
| 1191 | net->sctp.cookie_preserve_enable = 1; | 1191 | net->sctp.cookie_preserve_enable = 1; |
| 1192 | 1192 | ||
| 1193 | /* Default sctp sockets to use md5 as their hmac alg */ | 1193 | /* Default sctp sockets to use md5 as their hmac alg */ |
| 1194 | #if defined (CONFIG_CRYPTO_MD5) | 1194 | #if defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5) |
| 1195 | net->sctp.sctp_hmac_alg = "md5"; | 1195 | net->sctp.sctp_hmac_alg = "md5"; |
| 1196 | #elif defined (CONFIG_CRYPTO_SHA1) | 1196 | #elif defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1) |
| 1197 | net->sctp.sctp_hmac_alg = "sha1"; | 1197 | net->sctp.sctp_hmac_alg = "sha1"; |
| 1198 | #else | 1198 | #else |
| 1199 | net->sctp.sctp_hmac_alg = NULL; | 1199 | net->sctp.sctp_hmac_alg = NULL; |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 370a6468b3ba..855e464e92ef 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
| @@ -69,6 +69,8 @@ static struct nlmsg_perm nlmsg_route_perms[] = | |||
| 69 | { RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, | 69 | { RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, |
| 70 | { RTM_NEWNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, | 70 | { RTM_NEWNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, |
| 71 | { RTM_GETNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_READ }, | 71 | { RTM_GETNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_READ }, |
| 72 | { RTM_NEWMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, | ||
| 73 | { RTM_DELMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, | ||
| 72 | { RTM_GETMDB, NETLINK_ROUTE_SOCKET__NLMSG_READ }, | 74 | { RTM_GETMDB, NETLINK_ROUTE_SOCKET__NLMSG_READ }, |
| 73 | }; | 75 | }; |
| 74 | 76 | ||
