diff options
Diffstat (limited to 'drivers')
139 files changed, 5624 insertions, 2282 deletions
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c index bd5de08ad6fd..0576a7dd32a5 100644 --- a/drivers/amba/tegra-ahb.c +++ b/drivers/amba/tegra-ahb.c | |||
| @@ -157,6 +157,7 @@ int tegra_ahb_enable_smmu(struct device_node *dn) | |||
| 157 | EXPORT_SYMBOL(tegra_ahb_enable_smmu); | 157 | EXPORT_SYMBOL(tegra_ahb_enable_smmu); |
| 158 | #endif | 158 | #endif |
| 159 | 159 | ||
| 160 | #ifdef CONFIG_PM_SLEEP | ||
| 160 | static int tegra_ahb_suspend(struct device *dev) | 161 | static int tegra_ahb_suspend(struct device *dev) |
| 161 | { | 162 | { |
| 162 | int i; | 163 | int i; |
| @@ -176,6 +177,7 @@ static int tegra_ahb_resume(struct device *dev) | |||
| 176 | gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]); | 177 | gizmo_writel(ahb, ahb->ctx[i], tegra_ahb_gizmo[i]); |
| 177 | return 0; | 178 | return 0; |
| 178 | } | 179 | } |
| 180 | #endif | ||
| 179 | 181 | ||
| 180 | static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm, | 182 | static UNIVERSAL_DEV_PM_OPS(tegra_ahb_pm, |
| 181 | tegra_ahb_suspend, | 183 | tegra_ahb_suspend, |
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/base/devtmpfs.c b/drivers/base/devtmpfs.c index 147d1a4dd269..17cf7cad601e 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c | |||
| @@ -148,7 +148,7 @@ static int dev_mkdir(const char *name, umode_t mode) | |||
| 148 | struct path path; | 148 | struct path path; |
| 149 | int err; | 149 | int err; |
| 150 | 150 | ||
| 151 | dentry = kern_path_create(AT_FDCWD, name, &path, 1); | 151 | dentry = kern_path_create(AT_FDCWD, name, &path, LOOKUP_DIRECTORY); |
| 152 | if (IS_ERR(dentry)) | 152 | if (IS_ERR(dentry)) |
| 153 | return PTR_ERR(dentry); | 153 | return PTR_ERR(dentry); |
| 154 | 154 | ||
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 460e22dee36d..a3f79c495a41 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c | |||
| @@ -298,6 +298,8 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, | |||
| 298 | struct sg_table *sg_table, | 298 | struct sg_table *sg_table, |
| 299 | enum dma_data_direction direction) | 299 | enum dma_data_direction direction) |
| 300 | { | 300 | { |
| 301 | might_sleep(); | ||
| 302 | |||
| 301 | if (WARN_ON(!attach || !attach->dmabuf || !sg_table)) | 303 | if (WARN_ON(!attach || !attach->dmabuf || !sg_table)) |
| 302 | return; | 304 | return; |
| 303 | 305 | ||
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index bb3d9be3b1b4..89576a0b3f2e 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
| @@ -61,15 +61,29 @@ | |||
| 61 | 61 | ||
| 62 | #define RBD_MINORS_PER_MAJOR 256 /* max minors per blkdev */ | 62 | #define RBD_MINORS_PER_MAJOR 256 /* max minors per blkdev */ |
| 63 | 63 | ||
| 64 | #define RBD_MAX_SNAP_NAME_LEN 32 | 64 | #define RBD_SNAP_DEV_NAME_PREFIX "snap_" |
| 65 | #define RBD_MAX_SNAP_NAME_LEN \ | ||
| 66 | (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1)) | ||
| 67 | |||
| 65 | #define RBD_MAX_SNAP_COUNT 510 /* allows max snapc to fit in 4KB */ | 68 | #define RBD_MAX_SNAP_COUNT 510 /* allows max snapc to fit in 4KB */ |
| 66 | #define RBD_MAX_OPT_LEN 1024 | 69 | #define RBD_MAX_OPT_LEN 1024 |
| 67 | 70 | ||
| 68 | #define RBD_SNAP_HEAD_NAME "-" | 71 | #define RBD_SNAP_HEAD_NAME "-" |
| 69 | 72 | ||
| 73 | /* This allows a single page to hold an image name sent by OSD */ | ||
| 74 | #define RBD_IMAGE_NAME_LEN_MAX (PAGE_SIZE - sizeof (__le32) - 1) | ||
| 70 | #define RBD_IMAGE_ID_LEN_MAX 64 | 75 | #define RBD_IMAGE_ID_LEN_MAX 64 |
| 76 | |||
| 71 | #define RBD_OBJ_PREFIX_LEN_MAX 64 | 77 | #define RBD_OBJ_PREFIX_LEN_MAX 64 |
| 72 | 78 | ||
| 79 | /* Feature bits */ | ||
| 80 | |||
| 81 | #define RBD_FEATURE_LAYERING 1 | ||
| 82 | |||
| 83 | /* Features supported by this (client software) implementation. */ | ||
| 84 | |||
| 85 | #define RBD_FEATURES_ALL (0) | ||
| 86 | |||
| 73 | /* | 87 | /* |
| 74 | * An RBD device name will be "rbd#", where the "rbd" comes from | 88 | * An RBD device name will be "rbd#", where the "rbd" comes from |
| 75 | * RBD_DRV_NAME above, and # is a unique integer identifier. | 89 | * RBD_DRV_NAME above, and # is a unique integer identifier. |
| @@ -101,6 +115,27 @@ struct rbd_image_header { | |||
| 101 | u64 obj_version; | 115 | u64 obj_version; |
| 102 | }; | 116 | }; |
| 103 | 117 | ||
| 118 | /* | ||
| 119 | * An rbd image specification. | ||
| 120 | * | ||
| 121 | * The tuple (pool_id, image_id, snap_id) is sufficient to uniquely | ||
| 122 | * identify an image. | ||
| 123 | */ | ||
| 124 | struct rbd_spec { | ||
| 125 | u64 pool_id; | ||
| 126 | char *pool_name; | ||
| 127 | |||
| 128 | char *image_id; | ||
| 129 | size_t image_id_len; | ||
| 130 | char *image_name; | ||
| 131 | size_t image_name_len; | ||
| 132 | |||
| 133 | u64 snap_id; | ||
| 134 | char *snap_name; | ||
| 135 | |||
| 136 | struct kref kref; | ||
| 137 | }; | ||
| 138 | |||
| 104 | struct rbd_options { | 139 | struct rbd_options { |
| 105 | bool read_only; | 140 | bool read_only; |
| 106 | }; | 141 | }; |
| @@ -155,11 +190,8 @@ struct rbd_snap { | |||
| 155 | }; | 190 | }; |
| 156 | 191 | ||
| 157 | struct rbd_mapping { | 192 | struct rbd_mapping { |
| 158 | char *snap_name; | ||
| 159 | u64 snap_id; | ||
| 160 | u64 size; | 193 | u64 size; |
| 161 | u64 features; | 194 | u64 features; |
| 162 | bool snap_exists; | ||
| 163 | bool read_only; | 195 | bool read_only; |
| 164 | }; | 196 | }; |
| 165 | 197 | ||
| @@ -173,7 +205,6 @@ struct rbd_device { | |||
| 173 | struct gendisk *disk; /* blkdev's gendisk and rq */ | 205 | struct gendisk *disk; /* blkdev's gendisk and rq */ |
| 174 | 206 | ||
| 175 | u32 image_format; /* Either 1 or 2 */ | 207 | u32 image_format; /* Either 1 or 2 */ |
| 176 | struct rbd_options rbd_opts; | ||
| 177 | struct rbd_client *rbd_client; | 208 | struct rbd_client *rbd_client; |
| 178 | 209 | ||
| 179 | char name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */ | 210 | char name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */ |
| @@ -181,17 +212,17 @@ struct rbd_device { | |||
| 181 | spinlock_t lock; /* queue lock */ | 212 | spinlock_t lock; /* queue lock */ |
| 182 | 213 | ||
| 183 | struct rbd_image_header header; | 214 | struct rbd_image_header header; |
| 184 | char *image_id; | 215 | bool exists; |
| 185 | size_t image_id_len; | 216 | struct rbd_spec *spec; |
| 186 | char *image_name; | 217 | |
| 187 | size_t image_name_len; | ||
| 188 | char *header_name; | 218 | char *header_name; |
| 189 | char *pool_name; | ||
| 190 | int pool_id; | ||
| 191 | 219 | ||
| 192 | struct ceph_osd_event *watch_event; | 220 | struct ceph_osd_event *watch_event; |
| 193 | struct ceph_osd_request *watch_request; | 221 | struct ceph_osd_request *watch_request; |
| 194 | 222 | ||
| 223 | struct rbd_spec *parent_spec; | ||
| 224 | u64 parent_overlap; | ||
| 225 | |||
| 195 | /* protects updating the header */ | 226 | /* protects updating the header */ |
| 196 | struct rw_semaphore header_rwsem; | 227 | struct rw_semaphore header_rwsem; |
| 197 | 228 | ||
| @@ -204,6 +235,7 @@ struct rbd_device { | |||
| 204 | 235 | ||
| 205 | /* sysfs related */ | 236 | /* sysfs related */ |
| 206 | struct device dev; | 237 | struct device dev; |
| 238 | unsigned long open_count; | ||
| 207 | }; | 239 | }; |
| 208 | 240 | ||
| 209 | static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ | 241 | static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ |
| @@ -218,7 +250,7 @@ static int rbd_dev_snaps_update(struct rbd_device *rbd_dev); | |||
| 218 | static int rbd_dev_snaps_register(struct rbd_device *rbd_dev); | 250 | static int rbd_dev_snaps_register(struct rbd_device *rbd_dev); |
| 219 | 251 | ||
| 220 | static void rbd_dev_release(struct device *dev); | 252 | static void rbd_dev_release(struct device *dev); |
| 221 | static void __rbd_remove_snap_dev(struct rbd_snap *snap); | 253 | static void rbd_remove_snap_dev(struct rbd_snap *snap); |
| 222 | 254 | ||
| 223 | static ssize_t rbd_add(struct bus_type *bus, const char *buf, | 255 | static ssize_t rbd_add(struct bus_type *bus, const char *buf, |
| 224 | size_t count); | 256 | size_t count); |
| @@ -258,17 +290,8 @@ static struct device rbd_root_dev = { | |||
| 258 | # define rbd_assert(expr) ((void) 0) | 290 | # define rbd_assert(expr) ((void) 0) |
| 259 | #endif /* !RBD_DEBUG */ | 291 | #endif /* !RBD_DEBUG */ |
| 260 | 292 | ||
| 261 | static struct device *rbd_get_dev(struct rbd_device *rbd_dev) | 293 | static int rbd_dev_refresh(struct rbd_device *rbd_dev, u64 *hver); |
| 262 | { | 294 | static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev, u64 *hver); |
| 263 | return get_device(&rbd_dev->dev); | ||
| 264 | } | ||
| 265 | |||
| 266 | static void rbd_put_dev(struct rbd_device *rbd_dev) | ||
| 267 | { | ||
| 268 | put_device(&rbd_dev->dev); | ||
| 269 | } | ||
| 270 | |||
| 271 | static int rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver); | ||
| 272 | 295 | ||
| 273 | static int rbd_open(struct block_device *bdev, fmode_t mode) | 296 | static int rbd_open(struct block_device *bdev, fmode_t mode) |
| 274 | { | 297 | { |
| @@ -277,8 +300,11 @@ static int rbd_open(struct block_device *bdev, fmode_t mode) | |||
| 277 | if ((mode & FMODE_WRITE) && rbd_dev->mapping.read_only) | 300 | if ((mode & FMODE_WRITE) && rbd_dev->mapping.read_only) |
| 278 | return -EROFS; | 301 | return -EROFS; |
| 279 | 302 | ||
| 280 | rbd_get_dev(rbd_dev); | 303 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); |
| 304 | (void) get_device(&rbd_dev->dev); | ||
| 281 | set_device_ro(bdev, rbd_dev->mapping.read_only); | 305 | set_device_ro(bdev, rbd_dev->mapping.read_only); |
| 306 | rbd_dev->open_count++; | ||
| 307 | mutex_unlock(&ctl_mutex); | ||
| 282 | 308 | ||
| 283 | return 0; | 309 | return 0; |
| 284 | } | 310 | } |
| @@ -287,7 +313,11 @@ static int rbd_release(struct gendisk *disk, fmode_t mode) | |||
| 287 | { | 313 | { |
| 288 | struct rbd_device *rbd_dev = disk->private_data; | 314 | struct rbd_device *rbd_dev = disk->private_data; |
| 289 | 315 | ||
| 290 | rbd_put_dev(rbd_dev); | 316 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); |
| 317 | rbd_assert(rbd_dev->open_count > 0); | ||
| 318 | rbd_dev->open_count--; | ||
| 319 | put_device(&rbd_dev->dev); | ||
| 320 | mutex_unlock(&ctl_mutex); | ||
| 291 | 321 | ||
| 292 | return 0; | 322 | return 0; |
| 293 | } | 323 | } |
| @@ -388,7 +418,7 @@ enum { | |||
| 388 | static match_table_t rbd_opts_tokens = { | 418 | static match_table_t rbd_opts_tokens = { |
| 389 | /* int args above */ | 419 | /* int args above */ |
| 390 | /* string args above */ | 420 | /* string args above */ |
| 391 | {Opt_read_only, "mapping.read_only"}, | 421 | {Opt_read_only, "read_only"}, |
| 392 | {Opt_read_only, "ro"}, /* Alternate spelling */ | 422 | {Opt_read_only, "ro"}, /* Alternate spelling */ |
| 393 | {Opt_read_write, "read_write"}, | 423 | {Opt_read_write, "read_write"}, |
| 394 | {Opt_read_write, "rw"}, /* Alternate spelling */ | 424 | {Opt_read_write, "rw"}, /* Alternate spelling */ |
| @@ -441,33 +471,17 @@ static int parse_rbd_opts_token(char *c, void *private) | |||
| 441 | * Get a ceph client with specific addr and configuration, if one does | 471 | * Get a ceph client with specific addr and configuration, if one does |
| 442 | * not exist create it. | 472 | * not exist create it. |
| 443 | */ | 473 | */ |
| 444 | static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr, | 474 | static struct rbd_client *rbd_get_client(struct ceph_options *ceph_opts) |
| 445 | size_t mon_addr_len, char *options) | ||
| 446 | { | 475 | { |
| 447 | struct rbd_options *rbd_opts = &rbd_dev->rbd_opts; | ||
| 448 | struct ceph_options *ceph_opts; | ||
| 449 | struct rbd_client *rbdc; | 476 | struct rbd_client *rbdc; |
| 450 | 477 | ||
| 451 | rbd_opts->read_only = RBD_READ_ONLY_DEFAULT; | ||
| 452 | |||
| 453 | ceph_opts = ceph_parse_options(options, mon_addr, | ||
| 454 | mon_addr + mon_addr_len, | ||
| 455 | parse_rbd_opts_token, rbd_opts); | ||
| 456 | if (IS_ERR(ceph_opts)) | ||
| 457 | return PTR_ERR(ceph_opts); | ||
| 458 | |||
| 459 | rbdc = rbd_client_find(ceph_opts); | 478 | rbdc = rbd_client_find(ceph_opts); |
| 460 | if (rbdc) { | 479 | if (rbdc) /* using an existing client */ |
| 461 | /* using an existing client */ | ||
| 462 | ceph_destroy_options(ceph_opts); | 480 | ceph_destroy_options(ceph_opts); |
| 463 | } else { | 481 | else |
| 464 | rbdc = rbd_client_create(ceph_opts); | 482 | rbdc = rbd_client_create(ceph_opts); |
| 465 | if (IS_ERR(rbdc)) | ||
| 466 | return PTR_ERR(rbdc); | ||
| 467 | } | ||
| 468 | rbd_dev->rbd_client = rbdc; | ||
| 469 | 483 | ||
| 470 | return 0; | 484 | return rbdc; |
| 471 | } | 485 | } |
| 472 | 486 | ||
| 473 | /* | 487 | /* |
| @@ -492,10 +506,10 @@ static void rbd_client_release(struct kref *kref) | |||
| 492 | * Drop reference to ceph client node. If it's not referenced anymore, release | 506 | * Drop reference to ceph client node. If it's not referenced anymore, release |
| 493 | * it. | 507 | * it. |
| 494 | */ | 508 | */ |
| 495 | static void rbd_put_client(struct rbd_device *rbd_dev) | 509 | static void rbd_put_client(struct rbd_client *rbdc) |
| 496 | { | 510 | { |
| 497 | kref_put(&rbd_dev->rbd_client->kref, rbd_client_release); | 511 | if (rbdc) |
| 498 | rbd_dev->rbd_client = NULL; | 512 | kref_put(&rbdc->kref, rbd_client_release); |
| 499 | } | 513 | } |
| 500 | 514 | ||
| 501 | /* | 515 | /* |
| @@ -524,6 +538,16 @@ static bool rbd_dev_ondisk_valid(struct rbd_image_header_ondisk *ondisk) | |||
| 524 | if (memcmp(&ondisk->text, RBD_HEADER_TEXT, sizeof (RBD_HEADER_TEXT))) | 538 | if (memcmp(&ondisk->text, RBD_HEADER_TEXT, sizeof (RBD_HEADER_TEXT))) |
| 525 | return false; | 539 | return false; |
| 526 | 540 | ||
| 541 | /* The bio layer requires at least sector-sized I/O */ | ||
| 542 | |||
| 543 | if (ondisk->options.order < SECTOR_SHIFT) | ||
| 544 | return false; | ||
| 545 | |||
| 546 | /* If we use u64 in a few spots we may be able to loosen this */ | ||
| 547 | |||
| 548 | if (ondisk->options.order > 8 * sizeof (int) - 1) | ||
| 549 | return false; | ||
| 550 | |||
| 527 | /* | 551 | /* |
| 528 | * The size of a snapshot header has to fit in a size_t, and | 552 | * The size of a snapshot header has to fit in a size_t, and |
| 529 | * that limits the number of snapshots. | 553 | * that limits the number of snapshots. |
| @@ -635,6 +659,20 @@ out_err: | |||
| 635 | return -ENOMEM; | 659 | return -ENOMEM; |
| 636 | } | 660 | } |
| 637 | 661 | ||
| 662 | static const char *rbd_snap_name(struct rbd_device *rbd_dev, u64 snap_id) | ||
| 663 | { | ||
| 664 | struct rbd_snap *snap; | ||
| 665 | |||
| 666 | if (snap_id == CEPH_NOSNAP) | ||
| 667 | return RBD_SNAP_HEAD_NAME; | ||
| 668 | |||
| 669 | list_for_each_entry(snap, &rbd_dev->snaps, node) | ||
| 670 | if (snap_id == snap->id) | ||
| 671 | return snap->name; | ||
| 672 | |||
| 673 | return NULL; | ||
| 674 | } | ||
| 675 | |||
| 638 | static int snap_by_name(struct rbd_device *rbd_dev, const char *snap_name) | 676 | static int snap_by_name(struct rbd_device *rbd_dev, const char *snap_name) |
| 639 | { | 677 | { |
| 640 | 678 | ||
| @@ -642,7 +680,7 @@ static int snap_by_name(struct rbd_device *rbd_dev, const char *snap_name) | |||
| 642 | 680 | ||
| 643 | list_for_each_entry(snap, &rbd_dev->snaps, node) { | 681 | list_for_each_entry(snap, &rbd_dev->snaps, node) { |
| 644 | if (!strcmp(snap_name, snap->name)) { | 682 | if (!strcmp(snap_name, snap->name)) { |
| 645 | rbd_dev->mapping.snap_id = snap->id; | 683 | rbd_dev->spec->snap_id = snap->id; |
| 646 | rbd_dev->mapping.size = snap->size; | 684 | rbd_dev->mapping.size = snap->size; |
| 647 | rbd_dev->mapping.features = snap->features; | 685 | rbd_dev->mapping.features = snap->features; |
| 648 | 686 | ||
| @@ -653,26 +691,23 @@ static int snap_by_name(struct rbd_device *rbd_dev, const char *snap_name) | |||
| 653 | return -ENOENT; | 691 | return -ENOENT; |
| 654 | } | 692 | } |
| 655 | 693 | ||
| 656 | static int rbd_dev_set_mapping(struct rbd_device *rbd_dev, char *snap_name) | 694 | static int rbd_dev_set_mapping(struct rbd_device *rbd_dev) |
| 657 | { | 695 | { |
| 658 | int ret; | 696 | int ret; |
| 659 | 697 | ||
| 660 | if (!memcmp(snap_name, RBD_SNAP_HEAD_NAME, | 698 | if (!memcmp(rbd_dev->spec->snap_name, RBD_SNAP_HEAD_NAME, |
| 661 | sizeof (RBD_SNAP_HEAD_NAME))) { | 699 | sizeof (RBD_SNAP_HEAD_NAME))) { |
| 662 | rbd_dev->mapping.snap_id = CEPH_NOSNAP; | 700 | rbd_dev->spec->snap_id = CEPH_NOSNAP; |
| 663 | rbd_dev->mapping.size = rbd_dev->header.image_size; | 701 | rbd_dev->mapping.size = rbd_dev->header.image_size; |
| 664 | rbd_dev->mapping.features = rbd_dev->header.features; | 702 | rbd_dev->mapping.features = rbd_dev->header.features; |
| 665 | rbd_dev->mapping.snap_exists = false; | ||
| 666 | rbd_dev->mapping.read_only = rbd_dev->rbd_opts.read_only; | ||
| 667 | ret = 0; | 703 | ret = 0; |
| 668 | } else { | 704 | } else { |
| 669 | ret = snap_by_name(rbd_dev, snap_name); | 705 | ret = snap_by_name(rbd_dev, rbd_dev->spec->snap_name); |
| 670 | if (ret < 0) | 706 | if (ret < 0) |
| 671 | goto done; | 707 | goto done; |
| 672 | rbd_dev->mapping.snap_exists = true; | ||
| 673 | rbd_dev->mapping.read_only = true; | 708 | rbd_dev->mapping.read_only = true; |
| 674 | } | 709 | } |
| 675 | rbd_dev->mapping.snap_name = snap_name; | 710 | rbd_dev->exists = true; |
| 676 | done: | 711 | done: |
| 677 | return ret; | 712 | return ret; |
| 678 | } | 713 | } |
| @@ -695,13 +730,13 @@ static char *rbd_segment_name(struct rbd_device *rbd_dev, u64 offset) | |||
| 695 | u64 segment; | 730 | u64 segment; |
| 696 | int ret; | 731 | int ret; |
| 697 | 732 | ||
| 698 | name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO); | 733 | name = kmalloc(MAX_OBJ_NAME_SIZE + 1, GFP_NOIO); |
| 699 | if (!name) | 734 | if (!name) |
| 700 | return NULL; | 735 | return NULL; |
| 701 | segment = offset >> rbd_dev->header.obj_order; | 736 | segment = offset >> rbd_dev->header.obj_order; |
| 702 | ret = snprintf(name, RBD_MAX_SEG_NAME_LEN, "%s.%012llx", | 737 | ret = snprintf(name, MAX_OBJ_NAME_SIZE + 1, "%s.%012llx", |
| 703 | rbd_dev->header.object_prefix, segment); | 738 | rbd_dev->header.object_prefix, segment); |
| 704 | if (ret < 0 || ret >= RBD_MAX_SEG_NAME_LEN) { | 739 | if (ret < 0 || ret > MAX_OBJ_NAME_SIZE) { |
| 705 | pr_err("error formatting segment name for #%llu (%d)\n", | 740 | pr_err("error formatting segment name for #%llu (%d)\n", |
| 706 | segment, ret); | 741 | segment, ret); |
| 707 | kfree(name); | 742 | kfree(name); |
| @@ -800,77 +835,144 @@ static void zero_bio_chain(struct bio *chain, int start_ofs) | |||
| 800 | } | 835 | } |
| 801 | 836 | ||
| 802 | /* | 837 | /* |
| 803 | * bio_chain_clone - clone a chain of bios up to a certain length. | 838 | * Clone a portion of a bio, starting at the given byte offset |
| 804 | * might return a bio_pair that will need to be released. | 839 | * and continuing for the number of bytes indicated. |
| 805 | */ | 840 | */ |
| 806 | static struct bio *bio_chain_clone(struct bio **old, struct bio **next, | 841 | static struct bio *bio_clone_range(struct bio *bio_src, |
| 807 | struct bio_pair **bp, | 842 | unsigned int offset, |
| 808 | int len, gfp_t gfpmask) | 843 | unsigned int len, |
| 809 | { | 844 | gfp_t gfpmask) |
| 810 | struct bio *old_chain = *old; | 845 | { |
| 811 | struct bio *new_chain = NULL; | 846 | struct bio_vec *bv; |
| 812 | struct bio *tail; | 847 | unsigned int resid; |
| 813 | int total = 0; | 848 | unsigned short idx; |
| 814 | 849 | unsigned int voff; | |
| 815 | if (*bp) { | 850 | unsigned short end_idx; |
| 816 | bio_pair_release(*bp); | 851 | unsigned short vcnt; |
| 817 | *bp = NULL; | 852 | struct bio *bio; |
| 818 | } | ||
| 819 | 853 | ||
| 820 | while (old_chain && (total < len)) { | 854 | /* Handle the easy case for the caller */ |
| 821 | struct bio *tmp; | ||
| 822 | 855 | ||
| 823 | tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs); | 856 | if (!offset && len == bio_src->bi_size) |
| 824 | if (!tmp) | 857 | return bio_clone(bio_src, gfpmask); |
| 825 | goto err_out; | ||
| 826 | gfpmask &= ~__GFP_WAIT; /* can't wait after the first */ | ||
| 827 | 858 | ||
| 828 | if (total + old_chain->bi_size > len) { | 859 | if (WARN_ON_ONCE(!len)) |
| 829 | struct bio_pair *bp; | 860 | return NULL; |
| 861 | if (WARN_ON_ONCE(len > bio_src->bi_size)) | ||
| 862 | return NULL; | ||
| 863 | if (WARN_ON_ONCE(offset > bio_src->bi_size - len)) | ||
| 864 | return NULL; | ||
| 830 | 865 | ||
| 831 | /* | 866 | /* Find first affected segment... */ |
| 832 | * this split can only happen with a single paged bio, | ||
| 833 | * split_bio will BUG_ON if this is not the case | ||
| 834 | */ | ||
| 835 | dout("bio_chain_clone split! total=%d remaining=%d" | ||
| 836 | "bi_size=%u\n", | ||
| 837 | total, len - total, old_chain->bi_size); | ||
| 838 | 867 | ||
| 839 | /* split the bio. We'll release it either in the next | 868 | resid = offset; |
| 840 | call, or it will have to be released outside */ | 869 | __bio_for_each_segment(bv, bio_src, idx, 0) { |
| 841 | bp = bio_split(old_chain, (len - total) / SECTOR_SIZE); | 870 | if (resid < bv->bv_len) |
| 842 | if (!bp) | 871 | break; |
| 843 | goto err_out; | 872 | resid -= bv->bv_len; |
| 873 | } | ||
| 874 | voff = resid; | ||
| 844 | 875 | ||
| 845 | __bio_clone(tmp, &bp->bio1); | 876 | /* ...and the last affected segment */ |
| 846 | 877 | ||
| 847 | *next = &bp->bio2; | 878 | resid += len; |
| 848 | } else { | 879 | __bio_for_each_segment(bv, bio_src, end_idx, idx) { |
| 849 | __bio_clone(tmp, old_chain); | 880 | if (resid <= bv->bv_len) |
| 850 | *next = old_chain->bi_next; | 881 | break; |
| 851 | } | 882 | resid -= bv->bv_len; |
| 883 | } | ||
| 884 | vcnt = end_idx - idx + 1; | ||
| 885 | |||
| 886 | /* Build the clone */ | ||
| 852 | 887 | ||
| 853 | tmp->bi_bdev = NULL; | 888 | bio = bio_alloc(gfpmask, (unsigned int) vcnt); |
| 854 | tmp->bi_next = NULL; | 889 | if (!bio) |
| 855 | if (new_chain) | 890 | return NULL; /* ENOMEM */ |
| 856 | tail->bi_next = tmp; | ||
| 857 | else | ||
| 858 | new_chain = tmp; | ||
| 859 | tail = tmp; | ||
| 860 | old_chain = old_chain->bi_next; | ||
| 861 | 891 | ||
| 862 | total += tmp->bi_size; | 892 | bio->bi_bdev = bio_src->bi_bdev; |
| 893 | bio->bi_sector = bio_src->bi_sector + (offset >> SECTOR_SHIFT); | ||
| 894 | bio->bi_rw = bio_src->bi_rw; | ||
| 895 | bio->bi_flags |= 1 << BIO_CLONED; | ||
| 896 | |||
| 897 | /* | ||
| 898 | * Copy over our part of the bio_vec, then update the first | ||
| 899 | * and last (or only) entries. | ||
| 900 | */ | ||
| 901 | memcpy(&bio->bi_io_vec[0], &bio_src->bi_io_vec[idx], | ||
| 902 | vcnt * sizeof (struct bio_vec)); | ||
| 903 | bio->bi_io_vec[0].bv_offset += voff; | ||
| 904 | if (vcnt > 1) { | ||
| 905 | bio->bi_io_vec[0].bv_len -= voff; | ||
| 906 | bio->bi_io_vec[vcnt - 1].bv_len = resid; | ||
| 907 | } else { | ||
| 908 | bio->bi_io_vec[0].bv_len = len; | ||
| 863 | } | 909 | } |
| 864 | 910 | ||
| 865 | rbd_assert(total == len); | 911 | bio->bi_vcnt = vcnt; |
| 912 | bio->bi_size = len; | ||
| 913 | bio->bi_idx = 0; | ||
| 914 | |||
| 915 | return bio; | ||
| 916 | } | ||
| 917 | |||
| 918 | /* | ||
| 919 | * Clone a portion of a bio chain, starting at the given byte offset | ||
| 920 | * into the first bio in the source chain and continuing for the | ||
| 921 | * number of bytes indicated. The result is another bio chain of | ||
| 922 | * exactly the given length, or a null pointer on error. | ||
| 923 | * | ||
| 924 | * The bio_src and offset parameters are both in-out. On entry they | ||
| 925 | * refer to the first source bio and the offset into that bio where | ||
| 926 | * the start of data to be cloned is located. | ||
| 927 | * | ||
| 928 | * On return, bio_src is updated to refer to the bio in the source | ||
| 929 | * chain that contains first un-cloned byte, and *offset will | ||
| 930 | * contain the offset of that byte within that bio. | ||
| 931 | */ | ||
| 932 | static struct bio *bio_chain_clone_range(struct bio **bio_src, | ||
| 933 | unsigned int *offset, | ||
| 934 | unsigned int len, | ||
| 935 | gfp_t gfpmask) | ||
| 936 | { | ||
| 937 | struct bio *bi = *bio_src; | ||
| 938 | unsigned int off = *offset; | ||
| 939 | struct bio *chain = NULL; | ||
| 940 | struct bio **end; | ||
| 941 | |||
| 942 | /* Build up a chain of clone bios up to the limit */ | ||
| 943 | |||
| 944 | if (!bi || off >= bi->bi_size || !len) | ||
| 945 | return NULL; /* Nothing to clone */ | ||
| 866 | 946 | ||
| 867 | *old = old_chain; | 947 | end = &chain; |
| 948 | while (len) { | ||
| 949 | unsigned int bi_size; | ||
| 950 | struct bio *bio; | ||
| 951 | |||
| 952 | if (!bi) | ||
| 953 | goto out_err; /* EINVAL; ran out of bio's */ | ||
| 954 | bi_size = min_t(unsigned int, bi->bi_size - off, len); | ||
| 955 | bio = bio_clone_range(bi, off, bi_size, gfpmask); | ||
| 956 | if (!bio) | ||
| 957 | goto out_err; /* ENOMEM */ | ||
| 958 | |||
| 959 | *end = bio; | ||
| 960 | end = &bio->bi_next; | ||
| 961 | |||
| 962 | off += bi_size; | ||
| 963 | if (off == bi->bi_size) { | ||
| 964 | bi = bi->bi_next; | ||
| 965 | off = 0; | ||
| 966 | } | ||
| 967 | len -= bi_size; | ||
| 968 | } | ||
| 969 | *bio_src = bi; | ||
| 970 | *offset = off; | ||
| 868 | 971 | ||
| 869 | return new_chain; | 972 | return chain; |
| 973 | out_err: | ||
| 974 | bio_chain_put(chain); | ||
| 870 | 975 | ||
| 871 | err_out: | ||
| 872 | dout("bio_chain_clone with err\n"); | ||
| 873 | bio_chain_put(new_chain); | ||
| 874 | return NULL; | 976 | return NULL; |
| 875 | } | 977 | } |
| 876 | 978 | ||
| @@ -988,8 +1090,9 @@ static int rbd_do_request(struct request *rq, | |||
| 988 | req_data->coll_index = coll_index; | 1090 | req_data->coll_index = coll_index; |
| 989 | } | 1091 | } |
| 990 | 1092 | ||
| 991 | dout("rbd_do_request object_name=%s ofs=%llu len=%llu\n", object_name, | 1093 | dout("rbd_do_request object_name=%s ofs=%llu len=%llu coll=%p[%d]\n", |
| 992 | (unsigned long long) ofs, (unsigned long long) len); | 1094 | object_name, (unsigned long long) ofs, |
| 1095 | (unsigned long long) len, coll, coll_index); | ||
| 993 | 1096 | ||
| 994 | osdc = &rbd_dev->rbd_client->client->osdc; | 1097 | osdc = &rbd_dev->rbd_client->client->osdc; |
| 995 | req = ceph_osdc_alloc_request(osdc, flags, snapc, ops, | 1098 | req = ceph_osdc_alloc_request(osdc, flags, snapc, ops, |
| @@ -1019,7 +1122,7 @@ static int rbd_do_request(struct request *rq, | |||
| 1019 | layout->fl_stripe_unit = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); | 1122 | layout->fl_stripe_unit = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); |
| 1020 | layout->fl_stripe_count = cpu_to_le32(1); | 1123 | layout->fl_stripe_count = cpu_to_le32(1); |
| 1021 | layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); | 1124 | layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); |
| 1022 | layout->fl_pg_pool = cpu_to_le32(rbd_dev->pool_id); | 1125 | layout->fl_pg_pool = cpu_to_le32((int) rbd_dev->spec->pool_id); |
| 1023 | ret = ceph_calc_raw_layout(osdc, layout, snapid, ofs, &len, &bno, | 1126 | ret = ceph_calc_raw_layout(osdc, layout, snapid, ofs, &len, &bno, |
| 1024 | req, ops); | 1127 | req, ops); |
| 1025 | rbd_assert(ret == 0); | 1128 | rbd_assert(ret == 0); |
| @@ -1154,8 +1257,6 @@ done: | |||
| 1154 | static int rbd_do_op(struct request *rq, | 1257 | static int rbd_do_op(struct request *rq, |
| 1155 | struct rbd_device *rbd_dev, | 1258 | struct rbd_device *rbd_dev, |
| 1156 | struct ceph_snap_context *snapc, | 1259 | struct ceph_snap_context *snapc, |
| 1157 | u64 snapid, | ||
| 1158 | int opcode, int flags, | ||
| 1159 | u64 ofs, u64 len, | 1260 | u64 ofs, u64 len, |
| 1160 | struct bio *bio, | 1261 | struct bio *bio, |
| 1161 | struct rbd_req_coll *coll, | 1262 | struct rbd_req_coll *coll, |
| @@ -1167,6 +1268,9 @@ static int rbd_do_op(struct request *rq, | |||
| 1167 | int ret; | 1268 | int ret; |
| 1168 | struct ceph_osd_req_op *ops; | 1269 | struct ceph_osd_req_op *ops; |
| 1169 | u32 payload_len; | 1270 | u32 payload_len; |
| 1271 | int opcode; | ||
| 1272 | int flags; | ||
| 1273 | u64 snapid; | ||
| 1170 | 1274 | ||
| 1171 | seg_name = rbd_segment_name(rbd_dev, ofs); | 1275 | seg_name = rbd_segment_name(rbd_dev, ofs); |
| 1172 | if (!seg_name) | 1276 | if (!seg_name) |
| @@ -1174,7 +1278,18 @@ static int rbd_do_op(struct request *rq, | |||
| 1174 | seg_len = rbd_segment_length(rbd_dev, ofs, len); | 1278 | seg_len = rbd_segment_length(rbd_dev, ofs, len); |
| 1175 | seg_ofs = rbd_segment_offset(rbd_dev, ofs); | 1279 | seg_ofs = rbd_segment_offset(rbd_dev, ofs); |
| 1176 | 1280 | ||
| 1177 | payload_len = (flags & CEPH_OSD_FLAG_WRITE ? seg_len : 0); | 1281 | if (rq_data_dir(rq) == WRITE) { |
| 1282 | opcode = CEPH_OSD_OP_WRITE; | ||
| 1283 | flags = CEPH_OSD_FLAG_WRITE|CEPH_OSD_FLAG_ONDISK; | ||
| 1284 | snapid = CEPH_NOSNAP; | ||
| 1285 | payload_len = seg_len; | ||
| 1286 | } else { | ||
| 1287 | opcode = CEPH_OSD_OP_READ; | ||
| 1288 | flags = CEPH_OSD_FLAG_READ; | ||
| 1289 | snapc = NULL; | ||
| 1290 | snapid = rbd_dev->spec->snap_id; | ||
| 1291 | payload_len = 0; | ||
| 1292 | } | ||
| 1178 | 1293 | ||
| 1179 | ret = -ENOMEM; | 1294 | ret = -ENOMEM; |
| 1180 | ops = rbd_create_rw_ops(1, opcode, payload_len); | 1295 | ops = rbd_create_rw_ops(1, opcode, payload_len); |
| @@ -1202,41 +1317,6 @@ done: | |||
| 1202 | } | 1317 | } |
| 1203 | 1318 | ||
| 1204 | /* | 1319 | /* |
| 1205 | * Request async osd write | ||
| 1206 | */ | ||
| 1207 | static int rbd_req_write(struct request *rq, | ||
| 1208 | struct rbd_device *rbd_dev, | ||
| 1209 | struct ceph_snap_context *snapc, | ||
| 1210 | u64 ofs, u64 len, | ||
| 1211 | struct bio *bio, | ||
| 1212 | struct rbd_req_coll *coll, | ||
| 1213 | int coll_index) | ||
| 1214 | { | ||
| 1215 | return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP, | ||
| 1216 | CEPH_OSD_OP_WRITE, | ||
| 1217 | CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, | ||
| 1218 | ofs, len, bio, coll, coll_index); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | /* | ||
| 1222 | * Request async osd read | ||
| 1223 | */ | ||
| 1224 | static int rbd_req_read(struct request *rq, | ||
| 1225 | struct rbd_device *rbd_dev, | ||
| 1226 | u64 snapid, | ||
| 1227 | u64 ofs, u64 len, | ||
| 1228 | struct bio *bio, | ||
| 1229 | struct rbd_req_coll *coll, | ||
| 1230 | int coll_index) | ||
| 1231 | { | ||
| 1232 | return rbd_do_op(rq, rbd_dev, NULL, | ||
| 1233 | snapid, | ||
| 1234 | CEPH_OSD_OP_READ, | ||
| 1235 | CEPH_OSD_FLAG_READ, | ||
| 1236 | ofs, len, bio, coll, coll_index); | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | /* | ||
| 1240 | * Request sync osd read | 1320 | * Request sync osd read |
| 1241 | */ | 1321 | */ |
| 1242 | static int rbd_req_sync_read(struct rbd_device *rbd_dev, | 1322 | static int rbd_req_sync_read(struct rbd_device *rbd_dev, |
| @@ -1304,7 +1384,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) | |||
| 1304 | dout("rbd_watch_cb %s notify_id=%llu opcode=%u\n", | 1384 | dout("rbd_watch_cb %s notify_id=%llu opcode=%u\n", |
| 1305 | rbd_dev->header_name, (unsigned long long) notify_id, | 1385 | rbd_dev->header_name, (unsigned long long) notify_id, |
| 1306 | (unsigned int) opcode); | 1386 | (unsigned int) opcode); |
| 1307 | rc = rbd_refresh_header(rbd_dev, &hver); | 1387 | rc = rbd_dev_refresh(rbd_dev, &hver); |
| 1308 | if (rc) | 1388 | if (rc) |
| 1309 | pr_warning(RBD_DRV_NAME "%d got notification but failed to " | 1389 | pr_warning(RBD_DRV_NAME "%d got notification but failed to " |
| 1310 | " update snaps: %d\n", rbd_dev->major, rc); | 1390 | " update snaps: %d\n", rbd_dev->major, rc); |
| @@ -1460,18 +1540,16 @@ static void rbd_rq_fn(struct request_queue *q) | |||
| 1460 | { | 1540 | { |
| 1461 | struct rbd_device *rbd_dev = q->queuedata; | 1541 | struct rbd_device *rbd_dev = q->queuedata; |
| 1462 | struct request *rq; | 1542 | struct request *rq; |
| 1463 | struct bio_pair *bp = NULL; | ||
| 1464 | 1543 | ||
| 1465 | while ((rq = blk_fetch_request(q))) { | 1544 | while ((rq = blk_fetch_request(q))) { |
| 1466 | struct bio *bio; | 1545 | struct bio *bio; |
| 1467 | struct bio *rq_bio, *next_bio = NULL; | ||
| 1468 | bool do_write; | 1546 | bool do_write; |
| 1469 | unsigned int size; | 1547 | unsigned int size; |
| 1470 | u64 op_size = 0; | ||
| 1471 | u64 ofs; | 1548 | u64 ofs; |
| 1472 | int num_segs, cur_seg = 0; | 1549 | int num_segs, cur_seg = 0; |
| 1473 | struct rbd_req_coll *coll; | 1550 | struct rbd_req_coll *coll; |
| 1474 | struct ceph_snap_context *snapc; | 1551 | struct ceph_snap_context *snapc; |
| 1552 | unsigned int bio_offset; | ||
| 1475 | 1553 | ||
| 1476 | dout("fetched request\n"); | 1554 | dout("fetched request\n"); |
| 1477 | 1555 | ||
| @@ -1483,10 +1561,6 @@ static void rbd_rq_fn(struct request_queue *q) | |||
| 1483 | 1561 | ||
| 1484 | /* deduce our operation (read, write) */ | 1562 | /* deduce our operation (read, write) */ |
| 1485 | do_write = (rq_data_dir(rq) == WRITE); | 1563 | do_write = (rq_data_dir(rq) == WRITE); |
| 1486 | |||
| 1487 | size = blk_rq_bytes(rq); | ||
| 1488 | ofs = blk_rq_pos(rq) * SECTOR_SIZE; | ||
| 1489 | rq_bio = rq->bio; | ||
| 1490 | if (do_write && rbd_dev->mapping.read_only) { | 1564 | if (do_write && rbd_dev->mapping.read_only) { |
| 1491 | __blk_end_request_all(rq, -EROFS); | 1565 | __blk_end_request_all(rq, -EROFS); |
| 1492 | continue; | 1566 | continue; |
| @@ -1496,8 +1570,8 @@ static void rbd_rq_fn(struct request_queue *q) | |||
| 1496 | 1570 | ||
| 1497 | down_read(&rbd_dev->header_rwsem); | 1571 | down_read(&rbd_dev->header_rwsem); |
| 1498 | 1572 | ||
| 1499 | if (rbd_dev->mapping.snap_id != CEPH_NOSNAP && | 1573 | if (!rbd_dev->exists) { |
| 1500 | !rbd_dev->mapping.snap_exists) { | 1574 | rbd_assert(rbd_dev->spec->snap_id != CEPH_NOSNAP); |
| 1501 | up_read(&rbd_dev->header_rwsem); | 1575 | up_read(&rbd_dev->header_rwsem); |
| 1502 | dout("request for non-existent snapshot"); | 1576 | dout("request for non-existent snapshot"); |
| 1503 | spin_lock_irq(q->queue_lock); | 1577 | spin_lock_irq(q->queue_lock); |
| @@ -1509,6 +1583,10 @@ static void rbd_rq_fn(struct request_queue *q) | |||
| 1509 | 1583 | ||
| 1510 | up_read(&rbd_dev->header_rwsem); | 1584 | up_read(&rbd_dev->header_rwsem); |
| 1511 | 1585 | ||
| 1586 | size = blk_rq_bytes(rq); | ||
| 1587 | ofs = blk_rq_pos(rq) * SECTOR_SIZE; | ||
| 1588 | bio = rq->bio; | ||
| 1589 | |||
| 1512 | dout("%s 0x%x bytes at 0x%llx\n", | 1590 | dout("%s 0x%x bytes at 0x%llx\n", |
| 1513 | do_write ? "write" : "read", | 1591 | do_write ? "write" : "read", |
| 1514 | size, (unsigned long long) blk_rq_pos(rq) * SECTOR_SIZE); | 1592 | size, (unsigned long long) blk_rq_pos(rq) * SECTOR_SIZE); |
| @@ -1528,45 +1606,37 @@ static void rbd_rq_fn(struct request_queue *q) | |||
| 1528 | continue; | 1606 | continue; |
| 1529 | } | 1607 | } |
| 1530 | 1608 | ||
| 1609 | bio_offset = 0; | ||
| 1531 | do { | 1610 | do { |
| 1532 | /* a bio clone to be passed down to OSD req */ | 1611 | u64 limit = rbd_segment_length(rbd_dev, ofs, size); |
| 1612 | unsigned int chain_size; | ||
| 1613 | struct bio *bio_chain; | ||
| 1614 | |||
| 1615 | BUG_ON(limit > (u64) UINT_MAX); | ||
| 1616 | chain_size = (unsigned int) limit; | ||
| 1533 | dout("rq->bio->bi_vcnt=%hu\n", rq->bio->bi_vcnt); | 1617 | dout("rq->bio->bi_vcnt=%hu\n", rq->bio->bi_vcnt); |
| 1534 | op_size = rbd_segment_length(rbd_dev, ofs, size); | 1618 | |
| 1535 | kref_get(&coll->kref); | 1619 | kref_get(&coll->kref); |
| 1536 | bio = bio_chain_clone(&rq_bio, &next_bio, &bp, | ||
| 1537 | op_size, GFP_ATOMIC); | ||
| 1538 | if (!bio) { | ||
| 1539 | rbd_coll_end_req_index(rq, coll, cur_seg, | ||
| 1540 | -ENOMEM, op_size); | ||
| 1541 | goto next_seg; | ||
| 1542 | } | ||
| 1543 | 1620 | ||
| 1621 | /* Pass a cloned bio chain via an osd request */ | ||
| 1544 | 1622 | ||
| 1545 | /* init OSD command: write or read */ | 1623 | bio_chain = bio_chain_clone_range(&bio, |
| 1546 | if (do_write) | 1624 | &bio_offset, chain_size, |
| 1547 | rbd_req_write(rq, rbd_dev, | 1625 | GFP_ATOMIC); |
| 1548 | snapc, | 1626 | if (bio_chain) |
| 1549 | ofs, | 1627 | (void) rbd_do_op(rq, rbd_dev, snapc, |
| 1550 | op_size, bio, | 1628 | ofs, chain_size, |
| 1551 | coll, cur_seg); | 1629 | bio_chain, coll, cur_seg); |
| 1552 | else | 1630 | else |
| 1553 | rbd_req_read(rq, rbd_dev, | 1631 | rbd_coll_end_req_index(rq, coll, cur_seg, |
| 1554 | rbd_dev->mapping.snap_id, | 1632 | -ENOMEM, chain_size); |
| 1555 | ofs, | 1633 | size -= chain_size; |
| 1556 | op_size, bio, | 1634 | ofs += chain_size; |
| 1557 | coll, cur_seg); | ||
| 1558 | |||
| 1559 | next_seg: | ||
| 1560 | size -= op_size; | ||
| 1561 | ofs += op_size; | ||
| 1562 | 1635 | ||
| 1563 | cur_seg++; | 1636 | cur_seg++; |
| 1564 | rq_bio = next_bio; | ||
| 1565 | } while (size > 0); | 1637 | } while (size > 0); |
| 1566 | kref_put(&coll->kref, rbd_coll_release); | 1638 | kref_put(&coll->kref, rbd_coll_release); |
| 1567 | 1639 | ||
| 1568 | if (bp) | ||
| 1569 | bio_pair_release(bp); | ||
| 1570 | spin_lock_irq(q->queue_lock); | 1640 | spin_lock_irq(q->queue_lock); |
| 1571 | 1641 | ||
| 1572 | ceph_put_snap_context(snapc); | 1642 | ceph_put_snap_context(snapc); |
| @@ -1576,28 +1646,47 @@ next_seg: | |||
| 1576 | /* | 1646 | /* |
| 1577 | * a queue callback. Makes sure that we don't create a bio that spans across | 1647 | * a queue callback. Makes sure that we don't create a bio that spans across |
| 1578 | * multiple osd objects. One exception would be with a single page bios, | 1648 | * multiple osd objects. One exception would be with a single page bios, |
| 1579 | * which we handle later at bio_chain_clone | 1649 | * which we handle later at bio_chain_clone_range() |
| 1580 | */ | 1650 | */ |
| 1581 | static int rbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd, | 1651 | static int rbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd, |
| 1582 | struct bio_vec *bvec) | 1652 | struct bio_vec *bvec) |
| 1583 | { | 1653 | { |
| 1584 | struct rbd_device *rbd_dev = q->queuedata; | 1654 | struct rbd_device *rbd_dev = q->queuedata; |
| 1585 | unsigned int chunk_sectors; | 1655 | sector_t sector_offset; |
| 1586 | sector_t sector; | 1656 | sector_t sectors_per_obj; |
| 1587 | unsigned int bio_sectors; | 1657 | sector_t obj_sector_offset; |
| 1588 | int max; | 1658 | int ret; |
| 1589 | 1659 | ||
| 1590 | chunk_sectors = 1 << (rbd_dev->header.obj_order - SECTOR_SHIFT); | 1660 | /* |
| 1591 | sector = bmd->bi_sector + get_start_sect(bmd->bi_bdev); | 1661 | * Find how far into its rbd object the partition-relative |
| 1592 | bio_sectors = bmd->bi_size >> SECTOR_SHIFT; | 1662 | * bio start sector is to offset relative to the enclosing |
| 1663 | * device. | ||
| 1664 | */ | ||
| 1665 | sector_offset = get_start_sect(bmd->bi_bdev) + bmd->bi_sector; | ||
| 1666 | sectors_per_obj = 1 << (rbd_dev->header.obj_order - SECTOR_SHIFT); | ||
| 1667 | obj_sector_offset = sector_offset & (sectors_per_obj - 1); | ||
| 1668 | |||
| 1669 | /* | ||
| 1670 | * Compute the number of bytes from that offset to the end | ||
| 1671 | * of the object. Account for what's already used by the bio. | ||
| 1672 | */ | ||
| 1673 | ret = (int) (sectors_per_obj - obj_sector_offset) << SECTOR_SHIFT; | ||
| 1674 | if (ret > bmd->bi_size) | ||
| 1675 | ret -= bmd->bi_size; | ||
| 1676 | else | ||
| 1677 | ret = 0; | ||
| 1593 | 1678 | ||
| 1594 | max = (chunk_sectors - ((sector & (chunk_sectors - 1)) | 1679 | /* |
| 1595 | + bio_sectors)) << SECTOR_SHIFT; | 1680 | * Don't send back more than was asked for. And if the bio |
| 1596 | if (max < 0) | 1681 | * was empty, let the whole thing through because: "Note |
| 1597 | max = 0; /* bio_add cannot handle a negative return */ | 1682 | * that a block device *must* allow a single page to be |
| 1598 | if (max <= bvec->bv_len && bio_sectors == 0) | 1683 | * added to an empty bio." |
| 1599 | return bvec->bv_len; | 1684 | */ |
| 1600 | return max; | 1685 | rbd_assert(bvec->bv_len <= PAGE_SIZE); |
| 1686 | if (ret > (int) bvec->bv_len || !bmd->bi_size) | ||
| 1687 | ret = (int) bvec->bv_len; | ||
| 1688 | |||
| 1689 | return ret; | ||
| 1601 | } | 1690 | } |
| 1602 | 1691 | ||
| 1603 | static void rbd_free_disk(struct rbd_device *rbd_dev) | 1692 | static void rbd_free_disk(struct rbd_device *rbd_dev) |
| @@ -1663,13 +1752,13 @@ rbd_dev_v1_header_read(struct rbd_device *rbd_dev, u64 *version) | |||
| 1663 | ret = -ENXIO; | 1752 | ret = -ENXIO; |
| 1664 | pr_warning("short header read for image %s" | 1753 | pr_warning("short header read for image %s" |
| 1665 | " (want %zd got %d)\n", | 1754 | " (want %zd got %d)\n", |
| 1666 | rbd_dev->image_name, size, ret); | 1755 | rbd_dev->spec->image_name, size, ret); |
| 1667 | goto out_err; | 1756 | goto out_err; |
| 1668 | } | 1757 | } |
| 1669 | if (!rbd_dev_ondisk_valid(ondisk)) { | 1758 | if (!rbd_dev_ondisk_valid(ondisk)) { |
| 1670 | ret = -ENXIO; | 1759 | ret = -ENXIO; |
| 1671 | pr_warning("invalid header for image %s\n", | 1760 | pr_warning("invalid header for image %s\n", |
| 1672 | rbd_dev->image_name); | 1761 | rbd_dev->spec->image_name); |
| 1673 | goto out_err; | 1762 | goto out_err; |
| 1674 | } | 1763 | } |
| 1675 | 1764 | ||
| @@ -1707,19 +1796,32 @@ static int rbd_read_header(struct rbd_device *rbd_dev, | |||
| 1707 | return ret; | 1796 | return ret; |
| 1708 | } | 1797 | } |
| 1709 | 1798 | ||
| 1710 | static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev) | 1799 | static void rbd_remove_all_snaps(struct rbd_device *rbd_dev) |
| 1711 | { | 1800 | { |
| 1712 | struct rbd_snap *snap; | 1801 | struct rbd_snap *snap; |
| 1713 | struct rbd_snap *next; | 1802 | struct rbd_snap *next; |
| 1714 | 1803 | ||
| 1715 | list_for_each_entry_safe(snap, next, &rbd_dev->snaps, node) | 1804 | list_for_each_entry_safe(snap, next, &rbd_dev->snaps, node) |
| 1716 | __rbd_remove_snap_dev(snap); | 1805 | rbd_remove_snap_dev(snap); |
| 1806 | } | ||
| 1807 | |||
| 1808 | static void rbd_update_mapping_size(struct rbd_device *rbd_dev) | ||
| 1809 | { | ||
| 1810 | sector_t size; | ||
| 1811 | |||
| 1812 | if (rbd_dev->spec->snap_id != CEPH_NOSNAP) | ||
| 1813 | return; | ||
| 1814 | |||
| 1815 | size = (sector_t) rbd_dev->header.image_size / SECTOR_SIZE; | ||
| 1816 | dout("setting size to %llu sectors", (unsigned long long) size); | ||
| 1817 | rbd_dev->mapping.size = (u64) size; | ||
| 1818 | set_capacity(rbd_dev->disk, size); | ||
| 1717 | } | 1819 | } |
| 1718 | 1820 | ||
| 1719 | /* | 1821 | /* |
| 1720 | * only read the first part of the ondisk header, without the snaps info | 1822 | * only read the first part of the ondisk header, without the snaps info |
| 1721 | */ | 1823 | */ |
| 1722 | static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver) | 1824 | static int rbd_dev_v1_refresh(struct rbd_device *rbd_dev, u64 *hver) |
| 1723 | { | 1825 | { |
| 1724 | int ret; | 1826 | int ret; |
| 1725 | struct rbd_image_header h; | 1827 | struct rbd_image_header h; |
| @@ -1730,17 +1832,9 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver) | |||
| 1730 | 1832 | ||
| 1731 | down_write(&rbd_dev->header_rwsem); | 1833 | down_write(&rbd_dev->header_rwsem); |
| 1732 | 1834 | ||
| 1733 | /* resized? */ | 1835 | /* Update image size, and check for resize of mapped image */ |
| 1734 | if (rbd_dev->mapping.snap_id == CEPH_NOSNAP) { | 1836 | rbd_dev->header.image_size = h.image_size; |
| 1735 | sector_t size = (sector_t) h.image_size / SECTOR_SIZE; | 1837 | rbd_update_mapping_size(rbd_dev); |
| 1736 | |||
| 1737 | if (size != (sector_t) rbd_dev->mapping.size) { | ||
| 1738 | dout("setting size to %llu sectors", | ||
| 1739 | (unsigned long long) size); | ||
| 1740 | rbd_dev->mapping.size = (u64) size; | ||
| 1741 | set_capacity(rbd_dev->disk, size); | ||
| 1742 | } | ||
| 1743 | } | ||
| 1744 | 1838 | ||
| 1745 | /* rbd_dev->header.object_prefix shouldn't change */ | 1839 | /* rbd_dev->header.object_prefix shouldn't change */ |
| 1746 | kfree(rbd_dev->header.snap_sizes); | 1840 | kfree(rbd_dev->header.snap_sizes); |
| @@ -1768,12 +1862,16 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver) | |||
| 1768 | return ret; | 1862 | return ret; |
| 1769 | } | 1863 | } |
| 1770 | 1864 | ||
| 1771 | static int rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver) | 1865 | static int rbd_dev_refresh(struct rbd_device *rbd_dev, u64 *hver) |
| 1772 | { | 1866 | { |
| 1773 | int ret; | 1867 | int ret; |
| 1774 | 1868 | ||
| 1869 | rbd_assert(rbd_image_format_valid(rbd_dev->image_format)); | ||
| 1775 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | 1870 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); |
| 1776 | ret = __rbd_refresh_header(rbd_dev, hver); | 1871 | if (rbd_dev->image_format == 1) |
| 1872 | ret = rbd_dev_v1_refresh(rbd_dev, hver); | ||
| 1873 | else | ||
| 1874 | ret = rbd_dev_v2_refresh(rbd_dev, hver); | ||
| 1777 | mutex_unlock(&ctl_mutex); | 1875 | mutex_unlock(&ctl_mutex); |
| 1778 | 1876 | ||
| 1779 | return ret; | 1877 | return ret; |
| @@ -1885,7 +1983,7 @@ static ssize_t rbd_pool_show(struct device *dev, | |||
| 1885 | { | 1983 | { |
| 1886 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); | 1984 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); |
| 1887 | 1985 | ||
| 1888 | return sprintf(buf, "%s\n", rbd_dev->pool_name); | 1986 | return sprintf(buf, "%s\n", rbd_dev->spec->pool_name); |
| 1889 | } | 1987 | } |
| 1890 | 1988 | ||
| 1891 | static ssize_t rbd_pool_id_show(struct device *dev, | 1989 | static ssize_t rbd_pool_id_show(struct device *dev, |
| @@ -1893,7 +1991,8 @@ static ssize_t rbd_pool_id_show(struct device *dev, | |||
| 1893 | { | 1991 | { |
| 1894 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); | 1992 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); |
| 1895 | 1993 | ||
| 1896 | return sprintf(buf, "%d\n", rbd_dev->pool_id); | 1994 | return sprintf(buf, "%llu\n", |
| 1995 | (unsigned long long) rbd_dev->spec->pool_id); | ||
| 1897 | } | 1996 | } |
| 1898 | 1997 | ||
| 1899 | static ssize_t rbd_name_show(struct device *dev, | 1998 | static ssize_t rbd_name_show(struct device *dev, |
| @@ -1901,7 +2000,10 @@ static ssize_t rbd_name_show(struct device *dev, | |||
| 1901 | { | 2000 | { |
| 1902 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); | 2001 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); |
| 1903 | 2002 | ||
| 1904 | return sprintf(buf, "%s\n", rbd_dev->image_name); | 2003 | if (rbd_dev->spec->image_name) |
| 2004 | return sprintf(buf, "%s\n", rbd_dev->spec->image_name); | ||
| 2005 | |||
| 2006 | return sprintf(buf, "(unknown)\n"); | ||
| 1905 | } | 2007 | } |
| 1906 | 2008 | ||
| 1907 | static ssize_t rbd_image_id_show(struct device *dev, | 2009 | static ssize_t rbd_image_id_show(struct device *dev, |
| @@ -1909,7 +2011,7 @@ static ssize_t rbd_image_id_show(struct device *dev, | |||
| 1909 | { | 2011 | { |
| 1910 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); | 2012 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); |
| 1911 | 2013 | ||
| 1912 | return sprintf(buf, "%s\n", rbd_dev->image_id); | 2014 | return sprintf(buf, "%s\n", rbd_dev->spec->image_id); |
| 1913 | } | 2015 | } |
| 1914 | 2016 | ||
| 1915 | /* | 2017 | /* |
| @@ -1922,7 +2024,50 @@ static ssize_t rbd_snap_show(struct device *dev, | |||
| 1922 | { | 2024 | { |
| 1923 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); | 2025 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); |
| 1924 | 2026 | ||
| 1925 | return sprintf(buf, "%s\n", rbd_dev->mapping.snap_name); | 2027 | return sprintf(buf, "%s\n", rbd_dev->spec->snap_name); |
| 2028 | } | ||
| 2029 | |||
| 2030 | /* | ||
| 2031 | * For an rbd v2 image, shows the pool id, image id, and snapshot id | ||
| 2032 | * for the parent image. If there is no parent, simply shows | ||
| 2033 | * "(no parent image)". | ||
| 2034 | */ | ||
| 2035 | static ssize_t rbd_parent_show(struct device *dev, | ||
| 2036 | struct device_attribute *attr, | ||
| 2037 | char *buf) | ||
| 2038 | { | ||
| 2039 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); | ||
| 2040 | struct rbd_spec *spec = rbd_dev->parent_spec; | ||
| 2041 | int count; | ||
| 2042 | char *bufp = buf; | ||
| 2043 | |||
| 2044 | if (!spec) | ||
| 2045 | return sprintf(buf, "(no parent image)\n"); | ||
| 2046 | |||
| 2047 | count = sprintf(bufp, "pool_id %llu\npool_name %s\n", | ||
| 2048 | (unsigned long long) spec->pool_id, spec->pool_name); | ||
| 2049 | if (count < 0) | ||
| 2050 | return count; | ||
| 2051 | bufp += count; | ||
| 2052 | |||
| 2053 | count = sprintf(bufp, "image_id %s\nimage_name %s\n", spec->image_id, | ||
| 2054 | spec->image_name ? spec->image_name : "(unknown)"); | ||
| 2055 | if (count < 0) | ||
| 2056 | return count; | ||
| 2057 | bufp += count; | ||
| 2058 | |||
| 2059 | count = sprintf(bufp, "snap_id %llu\nsnap_name %s\n", | ||
| 2060 | (unsigned long long) spec->snap_id, spec->snap_name); | ||
| 2061 | if (count < 0) | ||
| 2062 | return count; | ||
| 2063 | bufp += count; | ||
| 2064 | |||
| 2065 | count = sprintf(bufp, "overlap %llu\n", rbd_dev->parent_overlap); | ||
| 2066 | if (count < 0) | ||
| 2067 | return count; | ||
| 2068 | bufp += count; | ||
| 2069 | |||
| 2070 | return (ssize_t) (bufp - buf); | ||
| 1926 | } | 2071 | } |
| 1927 | 2072 | ||
| 1928 | static ssize_t rbd_image_refresh(struct device *dev, | 2073 | static ssize_t rbd_image_refresh(struct device *dev, |
| @@ -1933,7 +2078,7 @@ static ssize_t rbd_image_refresh(struct device *dev, | |||
| 1933 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); | 2078 | struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); |
| 1934 | int ret; | 2079 | int ret; |
| 1935 | 2080 | ||
| 1936 | ret = rbd_refresh_header(rbd_dev, NULL); | 2081 | ret = rbd_dev_refresh(rbd_dev, NULL); |
| 1937 | 2082 | ||
| 1938 | return ret < 0 ? ret : size; | 2083 | return ret < 0 ? ret : size; |
| 1939 | } | 2084 | } |
| @@ -1948,6 +2093,7 @@ static DEVICE_ATTR(name, S_IRUGO, rbd_name_show, NULL); | |||
| 1948 | static DEVICE_ATTR(image_id, S_IRUGO, rbd_image_id_show, NULL); | 2093 | static DEVICE_ATTR(image_id, S_IRUGO, rbd_image_id_show, NULL); |
| 1949 | static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh); | 2094 | static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh); |
| 1950 | static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL); | 2095 | static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL); |
| 2096 | static DEVICE_ATTR(parent, S_IRUGO, rbd_parent_show, NULL); | ||
| 1951 | 2097 | ||
| 1952 | static struct attribute *rbd_attrs[] = { | 2098 | static struct attribute *rbd_attrs[] = { |
| 1953 | &dev_attr_size.attr, | 2099 | &dev_attr_size.attr, |
| @@ -1959,6 +2105,7 @@ static struct attribute *rbd_attrs[] = { | |||
| 1959 | &dev_attr_name.attr, | 2105 | &dev_attr_name.attr, |
| 1960 | &dev_attr_image_id.attr, | 2106 | &dev_attr_image_id.attr, |
| 1961 | &dev_attr_current_snap.attr, | 2107 | &dev_attr_current_snap.attr, |
| 2108 | &dev_attr_parent.attr, | ||
| 1962 | &dev_attr_refresh.attr, | 2109 | &dev_attr_refresh.attr, |
| 1963 | NULL | 2110 | NULL |
| 1964 | }; | 2111 | }; |
| @@ -2047,6 +2194,74 @@ static struct device_type rbd_snap_device_type = { | |||
| 2047 | .release = rbd_snap_dev_release, | 2194 | .release = rbd_snap_dev_release, |
| 2048 | }; | 2195 | }; |
| 2049 | 2196 | ||
| 2197 | static struct rbd_spec *rbd_spec_get(struct rbd_spec *spec) | ||
| 2198 | { | ||
| 2199 | kref_get(&spec->kref); | ||
| 2200 | |||
| 2201 | return spec; | ||
| 2202 | } | ||
| 2203 | |||
| 2204 | static void rbd_spec_free(struct kref *kref); | ||
| 2205 | static void rbd_spec_put(struct rbd_spec *spec) | ||
| 2206 | { | ||
| 2207 | if (spec) | ||
| 2208 | kref_put(&spec->kref, rbd_spec_free); | ||
| 2209 | } | ||
| 2210 | |||
| 2211 | static struct rbd_spec *rbd_spec_alloc(void) | ||
| 2212 | { | ||
| 2213 | struct rbd_spec *spec; | ||
| 2214 | |||
| 2215 | spec = kzalloc(sizeof (*spec), GFP_KERNEL); | ||
| 2216 | if (!spec) | ||
| 2217 | return NULL; | ||
| 2218 | kref_init(&spec->kref); | ||
| 2219 | |||
| 2220 | rbd_spec_put(rbd_spec_get(spec)); /* TEMPORARY */ | ||
| 2221 | |||
| 2222 | return spec; | ||
| 2223 | } | ||
| 2224 | |||
| 2225 | static void rbd_spec_free(struct kref *kref) | ||
| 2226 | { | ||
| 2227 | struct rbd_spec *spec = container_of(kref, struct rbd_spec, kref); | ||
| 2228 | |||
| 2229 | kfree(spec->pool_name); | ||
| 2230 | kfree(spec->image_id); | ||
| 2231 | kfree(spec->image_name); | ||
| 2232 | kfree(spec->snap_name); | ||
| 2233 | kfree(spec); | ||
| 2234 | } | ||
| 2235 | |||
| 2236 | struct rbd_device *rbd_dev_create(struct rbd_client *rbdc, | ||
| 2237 | struct rbd_spec *spec) | ||
| 2238 | { | ||
| 2239 | struct rbd_device *rbd_dev; | ||
| 2240 | |||
| 2241 | rbd_dev = kzalloc(sizeof (*rbd_dev), GFP_KERNEL); | ||
| 2242 | if (!rbd_dev) | ||
| 2243 | return NULL; | ||
| 2244 | |||
| 2245 | spin_lock_init(&rbd_dev->lock); | ||
| 2246 | INIT_LIST_HEAD(&rbd_dev->node); | ||
| 2247 | INIT_LIST_HEAD(&rbd_dev->snaps); | ||
| 2248 | init_rwsem(&rbd_dev->header_rwsem); | ||
| 2249 | |||
| 2250 | rbd_dev->spec = spec; | ||
| 2251 | rbd_dev->rbd_client = rbdc; | ||
| 2252 | |||
| 2253 | return rbd_dev; | ||
| 2254 | } | ||
| 2255 | |||
| 2256 | static void rbd_dev_destroy(struct rbd_device *rbd_dev) | ||
| 2257 | { | ||
| 2258 | rbd_spec_put(rbd_dev->parent_spec); | ||
| 2259 | kfree(rbd_dev->header_name); | ||
| 2260 | rbd_put_client(rbd_dev->rbd_client); | ||
| 2261 | rbd_spec_put(rbd_dev->spec); | ||
| 2262 | kfree(rbd_dev); | ||
| 2263 | } | ||
| 2264 | |||
| 2050 | static bool rbd_snap_registered(struct rbd_snap *snap) | 2265 | static bool rbd_snap_registered(struct rbd_snap *snap) |
| 2051 | { | 2266 | { |
| 2052 | bool ret = snap->dev.type == &rbd_snap_device_type; | 2267 | bool ret = snap->dev.type == &rbd_snap_device_type; |
| @@ -2057,7 +2272,7 @@ static bool rbd_snap_registered(struct rbd_snap *snap) | |||
| 2057 | return ret; | 2272 | return ret; |
| 2058 | } | 2273 | } |
| 2059 | 2274 | ||
| 2060 | static void __rbd_remove_snap_dev(struct rbd_snap *snap) | 2275 | static void rbd_remove_snap_dev(struct rbd_snap *snap) |
| 2061 | { | 2276 | { |
| 2062 | list_del(&snap->node); | 2277 | list_del(&snap->node); |
| 2063 | if (device_is_registered(&snap->dev)) | 2278 | if (device_is_registered(&snap->dev)) |
| @@ -2073,7 +2288,7 @@ static int rbd_register_snap_dev(struct rbd_snap *snap, | |||
| 2073 | dev->type = &rbd_snap_device_type; | 2288 | dev->type = &rbd_snap_device_type; |
| 2074 | dev->parent = parent; | 2289 | dev->parent = parent; |
| 2075 | dev->release = rbd_snap_dev_release; | 2290 | dev->release = rbd_snap_dev_release; |
| 2076 | dev_set_name(dev, "snap_%s", snap->name); | 2291 | dev_set_name(dev, "%s%s", RBD_SNAP_DEV_NAME_PREFIX, snap->name); |
| 2077 | dout("%s: registering device for snapshot %s\n", __func__, snap->name); | 2292 | dout("%s: registering device for snapshot %s\n", __func__, snap->name); |
| 2078 | 2293 | ||
| 2079 | ret = device_register(dev); | 2294 | ret = device_register(dev); |
| @@ -2189,6 +2404,7 @@ static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev) | |||
| 2189 | dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); | 2404 | dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); |
| 2190 | if (ret < 0) | 2405 | if (ret < 0) |
| 2191 | goto out; | 2406 | goto out; |
| 2407 | ret = 0; /* rbd_req_sync_exec() can return positive */ | ||
| 2192 | 2408 | ||
| 2193 | p = reply_buf; | 2409 | p = reply_buf; |
| 2194 | rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p, | 2410 | rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p, |
| @@ -2216,6 +2432,7 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id, | |||
| 2216 | __le64 features; | 2432 | __le64 features; |
| 2217 | __le64 incompat; | 2433 | __le64 incompat; |
| 2218 | } features_buf = { 0 }; | 2434 | } features_buf = { 0 }; |
| 2435 | u64 incompat; | ||
| 2219 | int ret; | 2436 | int ret; |
| 2220 | 2437 | ||
| 2221 | ret = rbd_req_sync_exec(rbd_dev, rbd_dev->header_name, | 2438 | ret = rbd_req_sync_exec(rbd_dev, rbd_dev->header_name, |
| @@ -2226,6 +2443,11 @@ static int _rbd_dev_v2_snap_features(struct rbd_device *rbd_dev, u64 snap_id, | |||
| 2226 | dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); | 2443 | dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); |
| 2227 | if (ret < 0) | 2444 | if (ret < 0) |
| 2228 | return ret; | 2445 | return ret; |
| 2446 | |||
| 2447 | incompat = le64_to_cpu(features_buf.incompat); | ||
| 2448 | if (incompat & ~RBD_FEATURES_ALL) | ||
| 2449 | return -ENXIO; | ||
| 2450 | |||
| 2229 | *snap_features = le64_to_cpu(features_buf.features); | 2451 | *snap_features = le64_to_cpu(features_buf.features); |
| 2230 | 2452 | ||
| 2231 | dout(" snap_id 0x%016llx features = 0x%016llx incompat = 0x%016llx\n", | 2453 | dout(" snap_id 0x%016llx features = 0x%016llx incompat = 0x%016llx\n", |
| @@ -2242,6 +2464,183 @@ static int rbd_dev_v2_features(struct rbd_device *rbd_dev) | |||
| 2242 | &rbd_dev->header.features); | 2464 | &rbd_dev->header.features); |
| 2243 | } | 2465 | } |
| 2244 | 2466 | ||
| 2467 | static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) | ||
| 2468 | { | ||
| 2469 | struct rbd_spec *parent_spec; | ||
| 2470 | size_t size; | ||
| 2471 | void *reply_buf = NULL; | ||
| 2472 | __le64 snapid; | ||
| 2473 | void *p; | ||
| 2474 | void *end; | ||
| 2475 | char *image_id; | ||
| 2476 | u64 overlap; | ||
| 2477 | size_t len = 0; | ||
| 2478 | int ret; | ||
| 2479 | |||
| 2480 | parent_spec = rbd_spec_alloc(); | ||
| 2481 | if (!parent_spec) | ||
| 2482 | return -ENOMEM; | ||
| 2483 | |||
| 2484 | size = sizeof (__le64) + /* pool_id */ | ||
| 2485 | sizeof (__le32) + RBD_IMAGE_ID_LEN_MAX + /* image_id */ | ||
| 2486 | sizeof (__le64) + /* snap_id */ | ||
| 2487 | sizeof (__le64); /* overlap */ | ||
| 2488 | reply_buf = kmalloc(size, GFP_KERNEL); | ||
| 2489 | if (!reply_buf) { | ||
| 2490 | ret = -ENOMEM; | ||
| 2491 | goto out_err; | ||
| 2492 | } | ||
| 2493 | |||
| 2494 | snapid = cpu_to_le64(CEPH_NOSNAP); | ||
| 2495 | ret = rbd_req_sync_exec(rbd_dev, rbd_dev->header_name, | ||
| 2496 | "rbd", "get_parent", | ||
| 2497 | (char *) &snapid, sizeof (snapid), | ||
| 2498 | (char *) reply_buf, size, | ||
| 2499 | CEPH_OSD_FLAG_READ, NULL); | ||
| 2500 | dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); | ||
| 2501 | if (ret < 0) | ||
| 2502 | goto out_err; | ||
| 2503 | |||
| 2504 | ret = -ERANGE; | ||
| 2505 | p = reply_buf; | ||
| 2506 | end = (char *) reply_buf + size; | ||
| 2507 | ceph_decode_64_safe(&p, end, parent_spec->pool_id, out_err); | ||
| 2508 | if (parent_spec->pool_id == CEPH_NOPOOL) | ||
| 2509 | goto out; /* No parent? No problem. */ | ||
| 2510 | |||
| 2511 | image_id = ceph_extract_encoded_string(&p, end, &len, GFP_KERNEL); | ||
| 2512 | if (IS_ERR(image_id)) { | ||
| 2513 | ret = PTR_ERR(image_id); | ||
| 2514 | goto out_err; | ||
| 2515 | } | ||
| 2516 | parent_spec->image_id = image_id; | ||
| 2517 | parent_spec->image_id_len = len; | ||
| 2518 | ceph_decode_64_safe(&p, end, parent_spec->snap_id, out_err); | ||
| 2519 | ceph_decode_64_safe(&p, end, overlap, out_err); | ||
| 2520 | |||
| 2521 | rbd_dev->parent_overlap = overlap; | ||
| 2522 | rbd_dev->parent_spec = parent_spec; | ||
| 2523 | parent_spec = NULL; /* rbd_dev now owns this */ | ||
| 2524 | out: | ||
| 2525 | ret = 0; | ||
| 2526 | out_err: | ||
| 2527 | kfree(reply_buf); | ||
| 2528 | rbd_spec_put(parent_spec); | ||
| 2529 | |||
| 2530 | return ret; | ||
| 2531 | } | ||
| 2532 | |||
| 2533 | static char *rbd_dev_image_name(struct rbd_device *rbd_dev) | ||
| 2534 | { | ||
| 2535 | size_t image_id_size; | ||
| 2536 | char *image_id; | ||
| 2537 | void *p; | ||
| 2538 | void *end; | ||
| 2539 | size_t size; | ||
| 2540 | void *reply_buf = NULL; | ||
| 2541 | size_t len = 0; | ||
| 2542 | char *image_name = NULL; | ||
| 2543 | int ret; | ||
| 2544 | |||
| 2545 | rbd_assert(!rbd_dev->spec->image_name); | ||
| 2546 | |||
| 2547 | image_id_size = sizeof (__le32) + rbd_dev->spec->image_id_len; | ||
| 2548 | image_id = kmalloc(image_id_size, GFP_KERNEL); | ||
| 2549 | if (!image_id) | ||
| 2550 | return NULL; | ||
| 2551 | |||
| 2552 | p = image_id; | ||
| 2553 | end = (char *) image_id + image_id_size; | ||
| 2554 | ceph_encode_string(&p, end, rbd_dev->spec->image_id, | ||
| 2555 | (u32) rbd_dev->spec->image_id_len); | ||
| 2556 | |||
| 2557 | size = sizeof (__le32) + RBD_IMAGE_NAME_LEN_MAX; | ||
| 2558 | reply_buf = kmalloc(size, GFP_KERNEL); | ||
| 2559 | if (!reply_buf) | ||
| 2560 | goto out; | ||
| 2561 | |||
| 2562 | ret = rbd_req_sync_exec(rbd_dev, RBD_DIRECTORY, | ||
| 2563 | "rbd", "dir_get_name", | ||
| 2564 | image_id, image_id_size, | ||
| 2565 | (char *) reply_buf, size, | ||
| 2566 | CEPH_OSD_FLAG_READ, NULL); | ||
| 2567 | if (ret < 0) | ||
| 2568 | goto out; | ||
| 2569 | p = reply_buf; | ||
| 2570 | end = (char *) reply_buf + size; | ||
| 2571 | image_name = ceph_extract_encoded_string(&p, end, &len, GFP_KERNEL); | ||
| 2572 | if (IS_ERR(image_name)) | ||
| 2573 | image_name = NULL; | ||
| 2574 | else | ||
| 2575 | dout("%s: name is %s len is %zd\n", __func__, image_name, len); | ||
| 2576 | out: | ||
| 2577 | kfree(reply_buf); | ||
| 2578 | kfree(image_id); | ||
| 2579 | |||
| 2580 | return image_name; | ||
| 2581 | } | ||
| 2582 | |||
| 2583 | /* | ||
| 2584 | * When a parent image gets probed, we only have the pool, image, | ||
| 2585 | * and snapshot ids but not the names of any of them. This call | ||
| 2586 | * is made later to fill in those names. It has to be done after | ||
| 2587 | * rbd_dev_snaps_update() has completed because some of the | ||
| 2588 | * information (in particular, snapshot name) is not available | ||
| 2589 | * until then. | ||
| 2590 | */ | ||
| 2591 | static int rbd_dev_probe_update_spec(struct rbd_device *rbd_dev) | ||
| 2592 | { | ||
| 2593 | struct ceph_osd_client *osdc; | ||
| 2594 | const char *name; | ||
| 2595 | void *reply_buf = NULL; | ||
| 2596 | int ret; | ||
| 2597 | |||
| 2598 | if (rbd_dev->spec->pool_name) | ||
| 2599 | return 0; /* Already have the names */ | ||
| 2600 | |||
| 2601 | /* Look up the pool name */ | ||
| 2602 | |||
| 2603 | osdc = &rbd_dev->rbd_client->client->osdc; | ||
| 2604 | name = ceph_pg_pool_name_by_id(osdc->osdmap, rbd_dev->spec->pool_id); | ||
| 2605 | if (!name) | ||
| 2606 | return -EIO; /* pool id too large (>= 2^31) */ | ||
| 2607 | |||
| 2608 | rbd_dev->spec->pool_name = kstrdup(name, GFP_KERNEL); | ||
| 2609 | if (!rbd_dev->spec->pool_name) | ||
| 2610 | return -ENOMEM; | ||
| 2611 | |||
| 2612 | /* Fetch the image name; tolerate failure here */ | ||
| 2613 | |||
| 2614 | name = rbd_dev_image_name(rbd_dev); | ||
| 2615 | if (name) { | ||
| 2616 | rbd_dev->spec->image_name_len = strlen(name); | ||
| 2617 | rbd_dev->spec->image_name = (char *) name; | ||
| 2618 | } else { | ||
| 2619 | pr_warning(RBD_DRV_NAME "%d " | ||
| 2620 | "unable to get image name for image id %s\n", | ||
| 2621 | rbd_dev->major, rbd_dev->spec->image_id); | ||
| 2622 | } | ||
| 2623 | |||
| 2624 | /* Look up the snapshot name. */ | ||
| 2625 | |||
| 2626 | name = rbd_snap_name(rbd_dev, rbd_dev->spec->snap_id); | ||
| 2627 | if (!name) { | ||
| 2628 | ret = -EIO; | ||
| 2629 | goto out_err; | ||
| 2630 | } | ||
| 2631 | rbd_dev->spec->snap_name = kstrdup(name, GFP_KERNEL); | ||
| 2632 | if(!rbd_dev->spec->snap_name) | ||
| 2633 | goto out_err; | ||
| 2634 | |||
| 2635 | return 0; | ||
| 2636 | out_err: | ||
| 2637 | kfree(reply_buf); | ||
| 2638 | kfree(rbd_dev->spec->pool_name); | ||
| 2639 | rbd_dev->spec->pool_name = NULL; | ||
| 2640 | |||
| 2641 | return ret; | ||
| 2642 | } | ||
| 2643 | |||
| 2245 | static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, u64 *ver) | 2644 | static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev, u64 *ver) |
| 2246 | { | 2645 | { |
| 2247 | size_t size; | 2646 | size_t size; |
| @@ -2328,7 +2727,6 @@ static char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, u32 which) | |||
| 2328 | int ret; | 2727 | int ret; |
| 2329 | void *p; | 2728 | void *p; |
| 2330 | void *end; | 2729 | void *end; |
| 2331 | size_t snap_name_len; | ||
| 2332 | char *snap_name; | 2730 | char *snap_name; |
| 2333 | 2731 | ||
| 2334 | size = sizeof (__le32) + RBD_MAX_SNAP_NAME_LEN; | 2732 | size = sizeof (__le32) + RBD_MAX_SNAP_NAME_LEN; |
| @@ -2348,9 +2746,7 @@ static char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev, u32 which) | |||
| 2348 | 2746 | ||
| 2349 | p = reply_buf; | 2747 | p = reply_buf; |
| 2350 | end = (char *) reply_buf + size; | 2748 | end = (char *) reply_buf + size; |
| 2351 | snap_name_len = 0; | 2749 | snap_name = ceph_extract_encoded_string(&p, end, NULL, GFP_KERNEL); |
| 2352 | snap_name = ceph_extract_encoded_string(&p, end, &snap_name_len, | ||
| 2353 | GFP_KERNEL); | ||
| 2354 | if (IS_ERR(snap_name)) { | 2750 | if (IS_ERR(snap_name)) { |
| 2355 | ret = PTR_ERR(snap_name); | 2751 | ret = PTR_ERR(snap_name); |
| 2356 | goto out; | 2752 | goto out; |
| @@ -2397,6 +2793,41 @@ static char *rbd_dev_snap_info(struct rbd_device *rbd_dev, u32 which, | |||
| 2397 | return ERR_PTR(-EINVAL); | 2793 | return ERR_PTR(-EINVAL); |
| 2398 | } | 2794 | } |
| 2399 | 2795 | ||
| 2796 | static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev, u64 *hver) | ||
| 2797 | { | ||
| 2798 | int ret; | ||
| 2799 | __u8 obj_order; | ||
| 2800 | |||
| 2801 | down_write(&rbd_dev->header_rwsem); | ||
| 2802 | |||
| 2803 | /* Grab old order first, to see if it changes */ | ||
| 2804 | |||
| 2805 | obj_order = rbd_dev->header.obj_order, | ||
| 2806 | ret = rbd_dev_v2_image_size(rbd_dev); | ||
| 2807 | if (ret) | ||
| 2808 | goto out; | ||
| 2809 | if (rbd_dev->header.obj_order != obj_order) { | ||
| 2810 | ret = -EIO; | ||
| 2811 | goto out; | ||
| 2812 | } | ||
| 2813 | rbd_update_mapping_size(rbd_dev); | ||
| 2814 | |||
| 2815 | ret = rbd_dev_v2_snap_context(rbd_dev, hver); | ||
| 2816 | dout("rbd_dev_v2_snap_context returned %d\n", ret); | ||
| 2817 | if (ret) | ||
| 2818 | goto out; | ||
| 2819 | ret = rbd_dev_snaps_update(rbd_dev); | ||
| 2820 | dout("rbd_dev_snaps_update returned %d\n", ret); | ||
| 2821 | if (ret) | ||
| 2822 | goto out; | ||
| 2823 | ret = rbd_dev_snaps_register(rbd_dev); | ||
| 2824 | dout("rbd_dev_snaps_register returned %d\n", ret); | ||
| 2825 | out: | ||
| 2826 | up_write(&rbd_dev->header_rwsem); | ||
| 2827 | |||
| 2828 | return ret; | ||
| 2829 | } | ||
| 2830 | |||
| 2400 | /* | 2831 | /* |
| 2401 | * Scan the rbd device's current snapshot list and compare it to the | 2832 | * Scan the rbd device's current snapshot list and compare it to the |
| 2402 | * newly-received snapshot context. Remove any existing snapshots | 2833 | * newly-received snapshot context. Remove any existing snapshots |
| @@ -2436,12 +2867,12 @@ static int rbd_dev_snaps_update(struct rbd_device *rbd_dev) | |||
| 2436 | 2867 | ||
| 2437 | /* Existing snapshot not in the new snap context */ | 2868 | /* Existing snapshot not in the new snap context */ |
| 2438 | 2869 | ||
| 2439 | if (rbd_dev->mapping.snap_id == snap->id) | 2870 | if (rbd_dev->spec->snap_id == snap->id) |
| 2440 | rbd_dev->mapping.snap_exists = false; | 2871 | rbd_dev->exists = false; |
| 2441 | __rbd_remove_snap_dev(snap); | 2872 | rbd_remove_snap_dev(snap); |
| 2442 | dout("%ssnap id %llu has been removed\n", | 2873 | dout("%ssnap id %llu has been removed\n", |
| 2443 | rbd_dev->mapping.snap_id == snap->id ? | 2874 | rbd_dev->spec->snap_id == snap->id ? |
| 2444 | "mapped " : "", | 2875 | "mapped " : "", |
| 2445 | (unsigned long long) snap->id); | 2876 | (unsigned long long) snap->id); |
| 2446 | 2877 | ||
| 2447 | /* Done with this list entry; advance */ | 2878 | /* Done with this list entry; advance */ |
| @@ -2559,7 +2990,7 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev) | |||
| 2559 | do { | 2990 | do { |
| 2560 | ret = rbd_req_sync_watch(rbd_dev); | 2991 | ret = rbd_req_sync_watch(rbd_dev); |
| 2561 | if (ret == -ERANGE) { | 2992 | if (ret == -ERANGE) { |
| 2562 | rc = rbd_refresh_header(rbd_dev, NULL); | 2993 | rc = rbd_dev_refresh(rbd_dev, NULL); |
| 2563 | if (rc < 0) | 2994 | if (rc < 0) |
| 2564 | return rc; | 2995 | return rc; |
| 2565 | } | 2996 | } |
| @@ -2621,8 +3052,8 @@ static void rbd_dev_id_put(struct rbd_device *rbd_dev) | |||
| 2621 | struct rbd_device *rbd_dev; | 3052 | struct rbd_device *rbd_dev; |
| 2622 | 3053 | ||
| 2623 | rbd_dev = list_entry(tmp, struct rbd_device, node); | 3054 | rbd_dev = list_entry(tmp, struct rbd_device, node); |
| 2624 | if (rbd_id > max_id) | 3055 | if (rbd_dev->dev_id > max_id) |
| 2625 | max_id = rbd_id; | 3056 | max_id = rbd_dev->dev_id; |
| 2626 | } | 3057 | } |
| 2627 | spin_unlock(&rbd_dev_list_lock); | 3058 | spin_unlock(&rbd_dev_list_lock); |
| 2628 | 3059 | ||
| @@ -2722,73 +3153,140 @@ static inline char *dup_token(const char **buf, size_t *lenp) | |||
| 2722 | } | 3153 | } |
| 2723 | 3154 | ||
| 2724 | /* | 3155 | /* |
| 2725 | * This fills in the pool_name, image_name, image_name_len, rbd_dev, | 3156 | * Parse the options provided for an "rbd add" (i.e., rbd image |
| 2726 | * rbd_md_name, and name fields of the given rbd_dev, based on the | 3157 | * mapping) request. These arrive via a write to /sys/bus/rbd/add, |
| 2727 | * list of monitor addresses and other options provided via | 3158 | * and the data written is passed here via a NUL-terminated buffer. |
| 2728 | * /sys/bus/rbd/add. Returns a pointer to a dynamically-allocated | 3159 | * Returns 0 if successful or an error code otherwise. |
| 2729 | * copy of the snapshot name to map if successful, or a | 3160 | * |
| 2730 | * pointer-coded error otherwise. | 3161 | * The information extracted from these options is recorded in |
| 3162 | * the other parameters which return dynamically-allocated | ||
| 3163 | * structures: | ||
| 3164 | * ceph_opts | ||
| 3165 | * The address of a pointer that will refer to a ceph options | ||
| 3166 | * structure. Caller must release the returned pointer using | ||
| 3167 | * ceph_destroy_options() when it is no longer needed. | ||
| 3168 | * rbd_opts | ||
| 3169 | * Address of an rbd options pointer. Fully initialized by | ||
| 3170 | * this function; caller must release with kfree(). | ||
| 3171 | * spec | ||
| 3172 | * Address of an rbd image specification pointer. Fully | ||
| 3173 | * initialized by this function based on parsed options. | ||
| 3174 | * Caller must release with rbd_spec_put(). | ||
| 2731 | * | 3175 | * |
| 2732 | * Note: rbd_dev is assumed to have been initially zero-filled. | 3176 | * The options passed take this form: |
| 3177 | * <mon_addrs> <options> <pool_name> <image_name> [<snap_id>] | ||
| 3178 | * where: | ||
| 3179 | * <mon_addrs> | ||
| 3180 | * A comma-separated list of one or more monitor addresses. | ||
| 3181 | * A monitor address is an ip address, optionally followed | ||
| 3182 | * by a port number (separated by a colon). | ||
| 3183 | * I.e.: ip1[:port1][,ip2[:port2]...] | ||
| 3184 | * <options> | ||
| 3185 | * A comma-separated list of ceph and/or rbd options. | ||
| 3186 | * <pool_name> | ||
| 3187 | * The name of the rados pool containing the rbd image. | ||
| 3188 | * <image_name> | ||
| 3189 | * The name of the image in that pool to map. | ||
| 3190 | * <snap_id> | ||
| 3191 | * An optional snapshot id. If provided, the mapping will | ||
| 3192 | * present data from the image at the time that snapshot was | ||
| 3193 | * created. The image head is used if no snapshot id is | ||
| 3194 | * provided. Snapshot mappings are always read-only. | ||
| 2733 | */ | 3195 | */ |
| 2734 | static char *rbd_add_parse_args(struct rbd_device *rbd_dev, | 3196 | static int rbd_add_parse_args(const char *buf, |
| 2735 | const char *buf, | 3197 | struct ceph_options **ceph_opts, |
| 2736 | const char **mon_addrs, | 3198 | struct rbd_options **opts, |
| 2737 | size_t *mon_addrs_size, | 3199 | struct rbd_spec **rbd_spec) |
| 2738 | char *options, | ||
| 2739 | size_t options_size) | ||
| 2740 | { | 3200 | { |
| 2741 | size_t len; | 3201 | size_t len; |
| 2742 | char *err_ptr = ERR_PTR(-EINVAL); | 3202 | char *options; |
| 2743 | char *snap_name; | 3203 | const char *mon_addrs; |
| 3204 | size_t mon_addrs_size; | ||
| 3205 | struct rbd_spec *spec = NULL; | ||
| 3206 | struct rbd_options *rbd_opts = NULL; | ||
| 3207 | struct ceph_options *copts; | ||
| 3208 | int ret; | ||
| 2744 | 3209 | ||
| 2745 | /* The first four tokens are required */ | 3210 | /* The first four tokens are required */ |
| 2746 | 3211 | ||
| 2747 | len = next_token(&buf); | 3212 | len = next_token(&buf); |
| 2748 | if (!len) | 3213 | if (!len) |
| 2749 | return err_ptr; | 3214 | return -EINVAL; /* Missing monitor address(es) */ |
| 2750 | *mon_addrs_size = len + 1; | 3215 | mon_addrs = buf; |
| 2751 | *mon_addrs = buf; | 3216 | mon_addrs_size = len + 1; |
| 2752 | |||
| 2753 | buf += len; | 3217 | buf += len; |
| 2754 | 3218 | ||
| 2755 | len = copy_token(&buf, options, options_size); | 3219 | ret = -EINVAL; |
| 2756 | if (!len || len >= options_size) | 3220 | options = dup_token(&buf, NULL); |
| 2757 | return err_ptr; | 3221 | if (!options) |
| 3222 | return -ENOMEM; | ||
| 3223 | if (!*options) | ||
| 3224 | goto out_err; /* Missing options */ | ||
| 2758 | 3225 | ||
| 2759 | err_ptr = ERR_PTR(-ENOMEM); | 3226 | spec = rbd_spec_alloc(); |
| 2760 | rbd_dev->pool_name = dup_token(&buf, NULL); | 3227 | if (!spec) |
| 2761 | if (!rbd_dev->pool_name) | 3228 | goto out_mem; |
| 2762 | goto out_err; | ||
| 2763 | 3229 | ||
| 2764 | rbd_dev->image_name = dup_token(&buf, &rbd_dev->image_name_len); | 3230 | spec->pool_name = dup_token(&buf, NULL); |
| 2765 | if (!rbd_dev->image_name) | 3231 | if (!spec->pool_name) |
| 2766 | goto out_err; | 3232 | goto out_mem; |
| 3233 | if (!*spec->pool_name) | ||
| 3234 | goto out_err; /* Missing pool name */ | ||
| 2767 | 3235 | ||
| 2768 | /* Snapshot name is optional */ | 3236 | spec->image_name = dup_token(&buf, &spec->image_name_len); |
| 3237 | if (!spec->image_name) | ||
| 3238 | goto out_mem; | ||
| 3239 | if (!*spec->image_name) | ||
| 3240 | goto out_err; /* Missing image name */ | ||
| 3241 | |||
| 3242 | /* | ||
| 3243 | * Snapshot name is optional; default is to use "-" | ||
| 3244 | * (indicating the head/no snapshot). | ||
| 3245 | */ | ||
| 2769 | len = next_token(&buf); | 3246 | len = next_token(&buf); |
| 2770 | if (!len) { | 3247 | if (!len) { |
| 2771 | buf = RBD_SNAP_HEAD_NAME; /* No snapshot supplied */ | 3248 | buf = RBD_SNAP_HEAD_NAME; /* No snapshot supplied */ |
| 2772 | len = sizeof (RBD_SNAP_HEAD_NAME) - 1; | 3249 | len = sizeof (RBD_SNAP_HEAD_NAME) - 1; |
| 2773 | } | 3250 | } else if (len > RBD_MAX_SNAP_NAME_LEN) { |
| 2774 | snap_name = kmalloc(len + 1, GFP_KERNEL); | 3251 | ret = -ENAMETOOLONG; |
| 2775 | if (!snap_name) | ||
| 2776 | goto out_err; | 3252 | goto out_err; |
| 2777 | memcpy(snap_name, buf, len); | 3253 | } |
| 2778 | *(snap_name + len) = '\0'; | 3254 | spec->snap_name = kmalloc(len + 1, GFP_KERNEL); |
| 3255 | if (!spec->snap_name) | ||
| 3256 | goto out_mem; | ||
| 3257 | memcpy(spec->snap_name, buf, len); | ||
| 3258 | *(spec->snap_name + len) = '\0'; | ||
| 2779 | 3259 | ||
| 2780 | dout(" SNAP_NAME is <%s>, len is %zd\n", snap_name, len); | 3260 | /* Initialize all rbd options to the defaults */ |
| 2781 | 3261 | ||
| 2782 | return snap_name; | 3262 | rbd_opts = kzalloc(sizeof (*rbd_opts), GFP_KERNEL); |
| 3263 | if (!rbd_opts) | ||
| 3264 | goto out_mem; | ||
| 3265 | |||
| 3266 | rbd_opts->read_only = RBD_READ_ONLY_DEFAULT; | ||
| 3267 | |||
| 3268 | copts = ceph_parse_options(options, mon_addrs, | ||
| 3269 | mon_addrs + mon_addrs_size - 1, | ||
| 3270 | parse_rbd_opts_token, rbd_opts); | ||
| 3271 | if (IS_ERR(copts)) { | ||
| 3272 | ret = PTR_ERR(copts); | ||
| 3273 | goto out_err; | ||
| 3274 | } | ||
| 3275 | kfree(options); | ||
| 2783 | 3276 | ||
| 3277 | *ceph_opts = copts; | ||
| 3278 | *opts = rbd_opts; | ||
| 3279 | *rbd_spec = spec; | ||
| 3280 | |||
| 3281 | return 0; | ||
| 3282 | out_mem: | ||
| 3283 | ret = -ENOMEM; | ||
| 2784 | out_err: | 3284 | out_err: |
| 2785 | kfree(rbd_dev->image_name); | 3285 | kfree(rbd_opts); |
| 2786 | rbd_dev->image_name = NULL; | 3286 | rbd_spec_put(spec); |
| 2787 | rbd_dev->image_name_len = 0; | 3287 | kfree(options); |
| 2788 | kfree(rbd_dev->pool_name); | ||
| 2789 | rbd_dev->pool_name = NULL; | ||
| 2790 | 3288 | ||
| 2791 | return err_ptr; | 3289 | return ret; |
| 2792 | } | 3290 | } |
| 2793 | 3291 | ||
| 2794 | /* | 3292 | /* |
| @@ -2814,14 +3312,22 @@ static int rbd_dev_image_id(struct rbd_device *rbd_dev) | |||
| 2814 | void *p; | 3312 | void *p; |
| 2815 | 3313 | ||
| 2816 | /* | 3314 | /* |
| 3315 | * When probing a parent image, the image id is already | ||
| 3316 | * known (and the image name likely is not). There's no | ||
| 3317 | * need to fetch the image id again in this case. | ||
| 3318 | */ | ||
| 3319 | if (rbd_dev->spec->image_id) | ||
| 3320 | return 0; | ||
| 3321 | |||
| 3322 | /* | ||
| 2817 | * First, see if the format 2 image id file exists, and if | 3323 | * First, see if the format 2 image id file exists, and if |
| 2818 | * so, get the image's persistent id from it. | 3324 | * so, get the image's persistent id from it. |
| 2819 | */ | 3325 | */ |
| 2820 | size = sizeof (RBD_ID_PREFIX) + rbd_dev->image_name_len; | 3326 | size = sizeof (RBD_ID_PREFIX) + rbd_dev->spec->image_name_len; |
| 2821 | object_name = kmalloc(size, GFP_NOIO); | 3327 | object_name = kmalloc(size, GFP_NOIO); |
| 2822 | if (!object_name) | 3328 | if (!object_name) |
| 2823 | return -ENOMEM; | 3329 | return -ENOMEM; |
| 2824 | sprintf(object_name, "%s%s", RBD_ID_PREFIX, rbd_dev->image_name); | 3330 | sprintf(object_name, "%s%s", RBD_ID_PREFIX, rbd_dev->spec->image_name); |
| 2825 | dout("rbd id object name is %s\n", object_name); | 3331 | dout("rbd id object name is %s\n", object_name); |
| 2826 | 3332 | ||
| 2827 | /* Response will be an encoded string, which includes a length */ | 3333 | /* Response will be an encoded string, which includes a length */ |
| @@ -2841,17 +3347,18 @@ static int rbd_dev_image_id(struct rbd_device *rbd_dev) | |||
| 2841 | dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); | 3347 | dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); |
| 2842 | if (ret < 0) | 3348 | if (ret < 0) |
| 2843 | goto out; | 3349 | goto out; |
| 3350 | ret = 0; /* rbd_req_sync_exec() can return positive */ | ||
| 2844 | 3351 | ||
| 2845 | p = response; | 3352 | p = response; |
| 2846 | rbd_dev->image_id = ceph_extract_encoded_string(&p, | 3353 | rbd_dev->spec->image_id = ceph_extract_encoded_string(&p, |
| 2847 | p + RBD_IMAGE_ID_LEN_MAX, | 3354 | p + RBD_IMAGE_ID_LEN_MAX, |
| 2848 | &rbd_dev->image_id_len, | 3355 | &rbd_dev->spec->image_id_len, |
| 2849 | GFP_NOIO); | 3356 | GFP_NOIO); |
| 2850 | if (IS_ERR(rbd_dev->image_id)) { | 3357 | if (IS_ERR(rbd_dev->spec->image_id)) { |
| 2851 | ret = PTR_ERR(rbd_dev->image_id); | 3358 | ret = PTR_ERR(rbd_dev->spec->image_id); |
| 2852 | rbd_dev->image_id = NULL; | 3359 | rbd_dev->spec->image_id = NULL; |
| 2853 | } else { | 3360 | } else { |
| 2854 | dout("image_id is %s\n", rbd_dev->image_id); | 3361 | dout("image_id is %s\n", rbd_dev->spec->image_id); |
| 2855 | } | 3362 | } |
| 2856 | out: | 3363 | out: |
| 2857 | kfree(response); | 3364 | kfree(response); |
| @@ -2867,26 +3374,33 @@ static int rbd_dev_v1_probe(struct rbd_device *rbd_dev) | |||
| 2867 | 3374 | ||
| 2868 | /* Version 1 images have no id; empty string is used */ | 3375 | /* Version 1 images have no id; empty string is used */ |
| 2869 | 3376 | ||
| 2870 | rbd_dev->image_id = kstrdup("", GFP_KERNEL); | 3377 | rbd_dev->spec->image_id = kstrdup("", GFP_KERNEL); |
| 2871 | if (!rbd_dev->image_id) | 3378 | if (!rbd_dev->spec->image_id) |
| 2872 | return -ENOMEM; | 3379 | return -ENOMEM; |
| 2873 | rbd_dev->image_id_len = 0; | 3380 | rbd_dev->spec->image_id_len = 0; |
| 2874 | 3381 | ||
| 2875 | /* Record the header object name for this rbd image. */ | 3382 | /* Record the header object name for this rbd image. */ |
| 2876 | 3383 | ||
| 2877 | size = rbd_dev->image_name_len + sizeof (RBD_SUFFIX); | 3384 | size = rbd_dev->spec->image_name_len + sizeof (RBD_SUFFIX); |
| 2878 | rbd_dev->header_name = kmalloc(size, GFP_KERNEL); | 3385 | rbd_dev->header_name = kmalloc(size, GFP_KERNEL); |
| 2879 | if (!rbd_dev->header_name) { | 3386 | if (!rbd_dev->header_name) { |
| 2880 | ret = -ENOMEM; | 3387 | ret = -ENOMEM; |
| 2881 | goto out_err; | 3388 | goto out_err; |
| 2882 | } | 3389 | } |
| 2883 | sprintf(rbd_dev->header_name, "%s%s", rbd_dev->image_name, RBD_SUFFIX); | 3390 | sprintf(rbd_dev->header_name, "%s%s", |
| 3391 | rbd_dev->spec->image_name, RBD_SUFFIX); | ||
| 2884 | 3392 | ||
| 2885 | /* Populate rbd image metadata */ | 3393 | /* Populate rbd image metadata */ |
| 2886 | 3394 | ||
| 2887 | ret = rbd_read_header(rbd_dev, &rbd_dev->header); | 3395 | ret = rbd_read_header(rbd_dev, &rbd_dev->header); |
| 2888 | if (ret < 0) | 3396 | if (ret < 0) |
| 2889 | goto out_err; | 3397 | goto out_err; |
| 3398 | |||
| 3399 | /* Version 1 images have no parent (no layering) */ | ||
| 3400 | |||
| 3401 | rbd_dev->parent_spec = NULL; | ||
| 3402 | rbd_dev->parent_overlap = 0; | ||
| 3403 | |||
| 2890 | rbd_dev->image_format = 1; | 3404 | rbd_dev->image_format = 1; |
| 2891 | 3405 | ||
| 2892 | dout("discovered version 1 image, header name is %s\n", | 3406 | dout("discovered version 1 image, header name is %s\n", |
| @@ -2897,8 +3411,8 @@ static int rbd_dev_v1_probe(struct rbd_device *rbd_dev) | |||
| 2897 | out_err: | 3411 | out_err: |
| 2898 | kfree(rbd_dev->header_name); | 3412 | kfree(rbd_dev->header_name); |
| 2899 | rbd_dev->header_name = NULL; | 3413 | rbd_dev->header_name = NULL; |
| 2900 | kfree(rbd_dev->image_id); | 3414 | kfree(rbd_dev->spec->image_id); |
| 2901 | rbd_dev->image_id = NULL; | 3415 | rbd_dev->spec->image_id = NULL; |
| 2902 | 3416 | ||
| 2903 | return ret; | 3417 | return ret; |
| 2904 | } | 3418 | } |
| @@ -2913,12 +3427,12 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev) | |||
| 2913 | * Image id was filled in by the caller. Record the header | 3427 | * Image id was filled in by the caller. Record the header |
| 2914 | * object name for this rbd image. | 3428 | * object name for this rbd image. |
| 2915 | */ | 3429 | */ |
| 2916 | size = sizeof (RBD_HEADER_PREFIX) + rbd_dev->image_id_len; | 3430 | size = sizeof (RBD_HEADER_PREFIX) + rbd_dev->spec->image_id_len; |
| 2917 | rbd_dev->header_name = kmalloc(size, GFP_KERNEL); | 3431 | rbd_dev->header_name = kmalloc(size, GFP_KERNEL); |
| 2918 | if (!rbd_dev->header_name) | 3432 | if (!rbd_dev->header_name) |
| 2919 | return -ENOMEM; | 3433 | return -ENOMEM; |
| 2920 | sprintf(rbd_dev->header_name, "%s%s", | 3434 | sprintf(rbd_dev->header_name, "%s%s", |
| 2921 | RBD_HEADER_PREFIX, rbd_dev->image_id); | 3435 | RBD_HEADER_PREFIX, rbd_dev->spec->image_id); |
| 2922 | 3436 | ||
| 2923 | /* Get the size and object order for the image */ | 3437 | /* Get the size and object order for the image */ |
| 2924 | 3438 | ||
| @@ -2932,12 +3446,20 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev) | |||
| 2932 | if (ret < 0) | 3446 | if (ret < 0) |
| 2933 | goto out_err; | 3447 | goto out_err; |
| 2934 | 3448 | ||
| 2935 | /* Get the features for the image */ | 3449 | /* Get the and check features for the image */ |
| 2936 | 3450 | ||
| 2937 | ret = rbd_dev_v2_features(rbd_dev); | 3451 | ret = rbd_dev_v2_features(rbd_dev); |
| 2938 | if (ret < 0) | 3452 | if (ret < 0) |
| 2939 | goto out_err; | 3453 | goto out_err; |
| 2940 | 3454 | ||
| 3455 | /* If the image supports layering, get the parent info */ | ||
| 3456 | |||
| 3457 | if (rbd_dev->header.features & RBD_FEATURE_LAYERING) { | ||
| 3458 | ret = rbd_dev_v2_parent_info(rbd_dev); | ||
| 3459 | if (ret < 0) | ||
| 3460 | goto out_err; | ||
| 3461 | } | ||
| 3462 | |||
| 2941 | /* crypto and compression type aren't (yet) supported for v2 images */ | 3463 | /* crypto and compression type aren't (yet) supported for v2 images */ |
| 2942 | 3464 | ||
| 2943 | rbd_dev->header.crypt_type = 0; | 3465 | rbd_dev->header.crypt_type = 0; |
| @@ -2955,8 +3477,11 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev) | |||
| 2955 | dout("discovered version 2 image, header name is %s\n", | 3477 | dout("discovered version 2 image, header name is %s\n", |
| 2956 | rbd_dev->header_name); | 3478 | rbd_dev->header_name); |
| 2957 | 3479 | ||
| 2958 | return -ENOTSUPP; | 3480 | return 0; |
| 2959 | out_err: | 3481 | out_err: |
| 3482 | rbd_dev->parent_overlap = 0; | ||
| 3483 | rbd_spec_put(rbd_dev->parent_spec); | ||
| 3484 | rbd_dev->parent_spec = NULL; | ||
| 2960 | kfree(rbd_dev->header_name); | 3485 | kfree(rbd_dev->header_name); |
| 2961 | rbd_dev->header_name = NULL; | 3486 | rbd_dev->header_name = NULL; |
| 2962 | kfree(rbd_dev->header.object_prefix); | 3487 | kfree(rbd_dev->header.object_prefix); |
| @@ -2965,91 +3490,22 @@ out_err: | |||
| 2965 | return ret; | 3490 | return ret; |
| 2966 | } | 3491 | } |
| 2967 | 3492 | ||
| 2968 | /* | 3493 | static int rbd_dev_probe_finish(struct rbd_device *rbd_dev) |
| 2969 | * Probe for the existence of the header object for the given rbd | ||
| 2970 | * device. For format 2 images this includes determining the image | ||
| 2971 | * id. | ||
| 2972 | */ | ||
| 2973 | static int rbd_dev_probe(struct rbd_device *rbd_dev) | ||
| 2974 | { | 3494 | { |
| 2975 | int ret; | 3495 | int ret; |
| 2976 | 3496 | ||
| 2977 | /* | 3497 | /* no need to lock here, as rbd_dev is not registered yet */ |
| 2978 | * Get the id from the image id object. If it's not a | 3498 | ret = rbd_dev_snaps_update(rbd_dev); |
| 2979 | * format 2 image, we'll get ENOENT back, and we'll assume | ||
| 2980 | * it's a format 1 image. | ||
| 2981 | */ | ||
| 2982 | ret = rbd_dev_image_id(rbd_dev); | ||
| 2983 | if (ret) | ||
| 2984 | ret = rbd_dev_v1_probe(rbd_dev); | ||
| 2985 | else | ||
| 2986 | ret = rbd_dev_v2_probe(rbd_dev); | ||
| 2987 | if (ret) | 3499 | if (ret) |
| 2988 | dout("probe failed, returning %d\n", ret); | 3500 | return ret; |
| 2989 | |||
| 2990 | return ret; | ||
| 2991 | } | ||
| 2992 | |||
| 2993 | static ssize_t rbd_add(struct bus_type *bus, | ||
| 2994 | const char *buf, | ||
| 2995 | size_t count) | ||
| 2996 | { | ||
| 2997 | char *options; | ||
| 2998 | struct rbd_device *rbd_dev = NULL; | ||
| 2999 | const char *mon_addrs = NULL; | ||
| 3000 | size_t mon_addrs_size = 0; | ||
| 3001 | struct ceph_osd_client *osdc; | ||
| 3002 | int rc = -ENOMEM; | ||
| 3003 | char *snap_name; | ||
| 3004 | |||
| 3005 | if (!try_module_get(THIS_MODULE)) | ||
| 3006 | return -ENODEV; | ||
| 3007 | |||
| 3008 | options = kmalloc(count, GFP_KERNEL); | ||
| 3009 | if (!options) | ||
| 3010 | goto err_out_mem; | ||
| 3011 | rbd_dev = kzalloc(sizeof(*rbd_dev), GFP_KERNEL); | ||
| 3012 | if (!rbd_dev) | ||
| 3013 | goto err_out_mem; | ||
| 3014 | |||
| 3015 | /* static rbd_device initialization */ | ||
| 3016 | spin_lock_init(&rbd_dev->lock); | ||
| 3017 | INIT_LIST_HEAD(&rbd_dev->node); | ||
| 3018 | INIT_LIST_HEAD(&rbd_dev->snaps); | ||
| 3019 | init_rwsem(&rbd_dev->header_rwsem); | ||
| 3020 | |||
| 3021 | /* parse add command */ | ||
| 3022 | snap_name = rbd_add_parse_args(rbd_dev, buf, | ||
| 3023 | &mon_addrs, &mon_addrs_size, options, count); | ||
| 3024 | if (IS_ERR(snap_name)) { | ||
| 3025 | rc = PTR_ERR(snap_name); | ||
| 3026 | goto err_out_mem; | ||
| 3027 | } | ||
| 3028 | |||
| 3029 | rc = rbd_get_client(rbd_dev, mon_addrs, mon_addrs_size - 1, options); | ||
| 3030 | if (rc < 0) | ||
| 3031 | goto err_out_args; | ||
| 3032 | |||
| 3033 | /* pick the pool */ | ||
| 3034 | osdc = &rbd_dev->rbd_client->client->osdc; | ||
| 3035 | rc = ceph_pg_poolid_by_name(osdc->osdmap, rbd_dev->pool_name); | ||
| 3036 | if (rc < 0) | ||
| 3037 | goto err_out_client; | ||
| 3038 | rbd_dev->pool_id = rc; | ||
| 3039 | |||
| 3040 | rc = rbd_dev_probe(rbd_dev); | ||
| 3041 | if (rc < 0) | ||
| 3042 | goto err_out_client; | ||
| 3043 | rbd_assert(rbd_image_format_valid(rbd_dev->image_format)); | ||
| 3044 | 3501 | ||
| 3045 | /* no need to lock here, as rbd_dev is not registered yet */ | 3502 | ret = rbd_dev_probe_update_spec(rbd_dev); |
| 3046 | rc = rbd_dev_snaps_update(rbd_dev); | 3503 | if (ret) |
| 3047 | if (rc) | 3504 | goto err_out_snaps; |
| 3048 | goto err_out_header; | ||
| 3049 | 3505 | ||
| 3050 | rc = rbd_dev_set_mapping(rbd_dev, snap_name); | 3506 | ret = rbd_dev_set_mapping(rbd_dev); |
| 3051 | if (rc) | 3507 | if (ret) |
| 3052 | goto err_out_header; | 3508 | goto err_out_snaps; |
| 3053 | 3509 | ||
| 3054 | /* generate unique id: find highest unique id, add one */ | 3510 | /* generate unique id: find highest unique id, add one */ |
| 3055 | rbd_dev_id_get(rbd_dev); | 3511 | rbd_dev_id_get(rbd_dev); |
| @@ -3061,34 +3517,33 @@ static ssize_t rbd_add(struct bus_type *bus, | |||
| 3061 | 3517 | ||
| 3062 | /* Get our block major device number. */ | 3518 | /* Get our block major device number. */ |
| 3063 | 3519 | ||
| 3064 | rc = register_blkdev(0, rbd_dev->name); | 3520 | ret = register_blkdev(0, rbd_dev->name); |
| 3065 | if (rc < 0) | 3521 | if (ret < 0) |
| 3066 | goto err_out_id; | 3522 | goto err_out_id; |
| 3067 | rbd_dev->major = rc; | 3523 | rbd_dev->major = ret; |
| 3068 | 3524 | ||
| 3069 | /* Set up the blkdev mapping. */ | 3525 | /* Set up the blkdev mapping. */ |
| 3070 | 3526 | ||
| 3071 | rc = rbd_init_disk(rbd_dev); | 3527 | ret = rbd_init_disk(rbd_dev); |
| 3072 | if (rc) | 3528 | if (ret) |
| 3073 | goto err_out_blkdev; | 3529 | goto err_out_blkdev; |
| 3074 | 3530 | ||
| 3075 | rc = rbd_bus_add_dev(rbd_dev); | 3531 | ret = rbd_bus_add_dev(rbd_dev); |
| 3076 | if (rc) | 3532 | if (ret) |
| 3077 | goto err_out_disk; | 3533 | goto err_out_disk; |
| 3078 | 3534 | ||
| 3079 | /* | 3535 | /* |
| 3080 | * At this point cleanup in the event of an error is the job | 3536 | * At this point cleanup in the event of an error is the job |
| 3081 | * of the sysfs code (initiated by rbd_bus_del_dev()). | 3537 | * of the sysfs code (initiated by rbd_bus_del_dev()). |
| 3082 | */ | 3538 | */ |
| 3083 | |||
| 3084 | down_write(&rbd_dev->header_rwsem); | 3539 | down_write(&rbd_dev->header_rwsem); |
| 3085 | rc = rbd_dev_snaps_register(rbd_dev); | 3540 | ret = rbd_dev_snaps_register(rbd_dev); |
| 3086 | up_write(&rbd_dev->header_rwsem); | 3541 | up_write(&rbd_dev->header_rwsem); |
| 3087 | if (rc) | 3542 | if (ret) |
| 3088 | goto err_out_bus; | 3543 | goto err_out_bus; |
| 3089 | 3544 | ||
| 3090 | rc = rbd_init_watch_dev(rbd_dev); | 3545 | ret = rbd_init_watch_dev(rbd_dev); |
| 3091 | if (rc) | 3546 | if (ret) |
| 3092 | goto err_out_bus; | 3547 | goto err_out_bus; |
| 3093 | 3548 | ||
| 3094 | /* Everything's ready. Announce the disk to the world. */ | 3549 | /* Everything's ready. Announce the disk to the world. */ |
| @@ -3098,37 +3553,119 @@ static ssize_t rbd_add(struct bus_type *bus, | |||
| 3098 | pr_info("%s: added with size 0x%llx\n", rbd_dev->disk->disk_name, | 3553 | pr_info("%s: added with size 0x%llx\n", rbd_dev->disk->disk_name, |
| 3099 | (unsigned long long) rbd_dev->mapping.size); | 3554 | (unsigned long long) rbd_dev->mapping.size); |
| 3100 | 3555 | ||
| 3101 | return count; | 3556 | return ret; |
| 3102 | |||
| 3103 | err_out_bus: | 3557 | err_out_bus: |
| 3104 | /* this will also clean up rest of rbd_dev stuff */ | 3558 | /* this will also clean up rest of rbd_dev stuff */ |
| 3105 | 3559 | ||
| 3106 | rbd_bus_del_dev(rbd_dev); | 3560 | rbd_bus_del_dev(rbd_dev); |
| 3107 | kfree(options); | ||
| 3108 | return rc; | ||
| 3109 | 3561 | ||
| 3562 | return ret; | ||
| 3110 | err_out_disk: | 3563 | err_out_disk: |
| 3111 | rbd_free_disk(rbd_dev); | 3564 | rbd_free_disk(rbd_dev); |
| 3112 | err_out_blkdev: | 3565 | err_out_blkdev: |
| 3113 | unregister_blkdev(rbd_dev->major, rbd_dev->name); | 3566 | unregister_blkdev(rbd_dev->major, rbd_dev->name); |
| 3114 | err_out_id: | 3567 | err_out_id: |
| 3115 | rbd_dev_id_put(rbd_dev); | 3568 | rbd_dev_id_put(rbd_dev); |
| 3116 | err_out_header: | 3569 | err_out_snaps: |
| 3117 | rbd_header_free(&rbd_dev->header); | 3570 | rbd_remove_all_snaps(rbd_dev); |
| 3571 | |||
| 3572 | return ret; | ||
| 3573 | } | ||
| 3574 | |||
| 3575 | /* | ||
| 3576 | * Probe for the existence of the header object for the given rbd | ||
| 3577 | * device. For format 2 images this includes determining the image | ||
| 3578 | * id. | ||
| 3579 | */ | ||
| 3580 | static int rbd_dev_probe(struct rbd_device *rbd_dev) | ||
| 3581 | { | ||
| 3582 | int ret; | ||
| 3583 | |||
| 3584 | /* | ||
| 3585 | * Get the id from the image id object. If it's not a | ||
| 3586 | * format 2 image, we'll get ENOENT back, and we'll assume | ||
| 3587 | * it's a format 1 image. | ||
| 3588 | */ | ||
| 3589 | ret = rbd_dev_image_id(rbd_dev); | ||
| 3590 | if (ret) | ||
| 3591 | ret = rbd_dev_v1_probe(rbd_dev); | ||
| 3592 | else | ||
| 3593 | ret = rbd_dev_v2_probe(rbd_dev); | ||
| 3594 | if (ret) { | ||
| 3595 | dout("probe failed, returning %d\n", ret); | ||
| 3596 | |||
| 3597 | return ret; | ||
| 3598 | } | ||
| 3599 | |||
| 3600 | ret = rbd_dev_probe_finish(rbd_dev); | ||
| 3601 | if (ret) | ||
| 3602 | rbd_header_free(&rbd_dev->header); | ||
| 3603 | |||
| 3604 | return ret; | ||
| 3605 | } | ||
| 3606 | |||
| 3607 | static ssize_t rbd_add(struct bus_type *bus, | ||
| 3608 | const char *buf, | ||
| 3609 | size_t count) | ||
| 3610 | { | ||
| 3611 | struct rbd_device *rbd_dev = NULL; | ||
| 3612 | struct ceph_options *ceph_opts = NULL; | ||
| 3613 | struct rbd_options *rbd_opts = NULL; | ||
| 3614 | struct rbd_spec *spec = NULL; | ||
| 3615 | struct rbd_client *rbdc; | ||
| 3616 | struct ceph_osd_client *osdc; | ||
| 3617 | int rc = -ENOMEM; | ||
| 3618 | |||
| 3619 | if (!try_module_get(THIS_MODULE)) | ||
| 3620 | return -ENODEV; | ||
| 3621 | |||
| 3622 | /* parse add command */ | ||
| 3623 | rc = rbd_add_parse_args(buf, &ceph_opts, &rbd_opts, &spec); | ||
| 3624 | if (rc < 0) | ||
| 3625 | goto err_out_module; | ||
| 3626 | |||
| 3627 | rbdc = rbd_get_client(ceph_opts); | ||
| 3628 | if (IS_ERR(rbdc)) { | ||
| 3629 | rc = PTR_ERR(rbdc); | ||
| 3630 | goto err_out_args; | ||
| 3631 | } | ||
| 3632 | ceph_opts = NULL; /* rbd_dev client now owns this */ | ||
| 3633 | |||
| 3634 | /* pick the pool */ | ||
| 3635 | osdc = &rbdc->client->osdc; | ||
| 3636 | rc = ceph_pg_poolid_by_name(osdc->osdmap, spec->pool_name); | ||
| 3637 | if (rc < 0) | ||
| 3638 | goto err_out_client; | ||
| 3639 | spec->pool_id = (u64) rc; | ||
| 3640 | |||
| 3641 | rbd_dev = rbd_dev_create(rbdc, spec); | ||
| 3642 | if (!rbd_dev) | ||
| 3643 | goto err_out_client; | ||
| 3644 | rbdc = NULL; /* rbd_dev now owns this */ | ||
| 3645 | spec = NULL; /* rbd_dev now owns this */ | ||
| 3646 | |||
| 3647 | rbd_dev->mapping.read_only = rbd_opts->read_only; | ||
| 3648 | kfree(rbd_opts); | ||
| 3649 | rbd_opts = NULL; /* done with this */ | ||
| 3650 | |||
| 3651 | rc = rbd_dev_probe(rbd_dev); | ||
| 3652 | if (rc < 0) | ||
| 3653 | goto err_out_rbd_dev; | ||
| 3654 | |||
| 3655 | return count; | ||
| 3656 | err_out_rbd_dev: | ||
| 3657 | rbd_dev_destroy(rbd_dev); | ||
| 3118 | err_out_client: | 3658 | err_out_client: |
| 3119 | kfree(rbd_dev->header_name); | 3659 | rbd_put_client(rbdc); |
| 3120 | rbd_put_client(rbd_dev); | ||
| 3121 | kfree(rbd_dev->image_id); | ||
| 3122 | err_out_args: | 3660 | err_out_args: |
| 3123 | kfree(rbd_dev->mapping.snap_name); | 3661 | if (ceph_opts) |
| 3124 | kfree(rbd_dev->image_name); | 3662 | ceph_destroy_options(ceph_opts); |
| 3125 | kfree(rbd_dev->pool_name); | 3663 | kfree(rbd_opts); |
| 3126 | err_out_mem: | 3664 | rbd_spec_put(spec); |
| 3127 | kfree(rbd_dev); | 3665 | err_out_module: |
| 3128 | kfree(options); | 3666 | module_put(THIS_MODULE); |
| 3129 | 3667 | ||
| 3130 | dout("Error adding device %s\n", buf); | 3668 | dout("Error adding device %s\n", buf); |
| 3131 | module_put(THIS_MODULE); | ||
| 3132 | 3669 | ||
| 3133 | return (ssize_t) rc; | 3670 | return (ssize_t) rc; |
| 3134 | } | 3671 | } |
| @@ -3163,7 +3700,6 @@ static void rbd_dev_release(struct device *dev) | |||
| 3163 | if (rbd_dev->watch_event) | 3700 | if (rbd_dev->watch_event) |
| 3164 | rbd_req_sync_unwatch(rbd_dev); | 3701 | rbd_req_sync_unwatch(rbd_dev); |
| 3165 | 3702 | ||
| 3166 | rbd_put_client(rbd_dev); | ||
| 3167 | 3703 | ||
| 3168 | /* clean up and free blkdev */ | 3704 | /* clean up and free blkdev */ |
| 3169 | rbd_free_disk(rbd_dev); | 3705 | rbd_free_disk(rbd_dev); |
| @@ -3173,13 +3709,9 @@ static void rbd_dev_release(struct device *dev) | |||
| 3173 | rbd_header_free(&rbd_dev->header); | 3709 | rbd_header_free(&rbd_dev->header); |
| 3174 | 3710 | ||
| 3175 | /* done with the id, and with the rbd_dev */ | 3711 | /* done with the id, and with the rbd_dev */ |
| 3176 | kfree(rbd_dev->mapping.snap_name); | ||
| 3177 | kfree(rbd_dev->image_id); | ||
| 3178 | kfree(rbd_dev->header_name); | ||
| 3179 | kfree(rbd_dev->pool_name); | ||
| 3180 | kfree(rbd_dev->image_name); | ||
| 3181 | rbd_dev_id_put(rbd_dev); | 3712 | rbd_dev_id_put(rbd_dev); |
| 3182 | kfree(rbd_dev); | 3713 | rbd_assert(rbd_dev->rbd_client != NULL); |
| 3714 | rbd_dev_destroy(rbd_dev); | ||
| 3183 | 3715 | ||
| 3184 | /* release module ref */ | 3716 | /* release module ref */ |
| 3185 | module_put(THIS_MODULE); | 3717 | module_put(THIS_MODULE); |
| @@ -3211,7 +3743,12 @@ static ssize_t rbd_remove(struct bus_type *bus, | |||
| 3211 | goto done; | 3743 | goto done; |
| 3212 | } | 3744 | } |
| 3213 | 3745 | ||
| 3214 | __rbd_remove_all_snaps(rbd_dev); | 3746 | if (rbd_dev->open_count) { |
| 3747 | ret = -EBUSY; | ||
| 3748 | goto done; | ||
| 3749 | } | ||
| 3750 | |||
| 3751 | rbd_remove_all_snaps(rbd_dev); | ||
| 3215 | rbd_bus_del_dev(rbd_dev); | 3752 | rbd_bus_del_dev(rbd_dev); |
| 3216 | 3753 | ||
| 3217 | done: | 3754 | done: |
diff --git a/drivers/block/rbd_types.h b/drivers/block/rbd_types.h index cbe77fa105ba..49d77cbcf8bd 100644 --- a/drivers/block/rbd_types.h +++ b/drivers/block/rbd_types.h | |||
| @@ -46,8 +46,6 @@ | |||
| 46 | #define RBD_MIN_OBJ_ORDER 16 | 46 | #define RBD_MIN_OBJ_ORDER 16 |
| 47 | #define RBD_MAX_OBJ_ORDER 30 | 47 | #define RBD_MAX_OBJ_ORDER 30 |
| 48 | 48 | ||
| 49 | #define RBD_MAX_SEG_NAME_LEN 128 | ||
| 50 | |||
| 51 | #define RBD_COMP_NONE 0 | 49 | #define RBD_COMP_NONE 0 |
| 52 | #define RBD_CRYPT_NONE 0 | 50 | #define RBD_CRYPT_NONE 0 |
| 53 | 51 | ||
diff --git a/drivers/char/random.c b/drivers/char/random.c index b86eae9b77df..85e81ec1451e 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -399,7 +399,6 @@ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait); | |||
| 399 | static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); | 399 | static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); |
| 400 | static struct fasync_struct *fasync; | 400 | static struct fasync_struct *fasync; |
| 401 | 401 | ||
| 402 | #if 0 | ||
| 403 | static bool debug; | 402 | static bool debug; |
| 404 | module_param(debug, bool, 0644); | 403 | module_param(debug, bool, 0644); |
| 405 | #define DEBUG_ENT(fmt, arg...) do { \ | 404 | #define DEBUG_ENT(fmt, arg...) do { \ |
| @@ -410,9 +409,6 @@ module_param(debug, bool, 0644); | |||
| 410 | blocking_pool.entropy_count,\ | 409 | blocking_pool.entropy_count,\ |
| 411 | nonblocking_pool.entropy_count,\ | 410 | nonblocking_pool.entropy_count,\ |
| 412 | ## arg); } while (0) | 411 | ## arg); } while (0) |
| 413 | #else | ||
| 414 | #define DEBUG_ENT(fmt, arg...) do {} while (0) | ||
| 415 | #endif | ||
| 416 | 412 | ||
| 417 | /********************************************************************** | 413 | /********************************************************************** |
| 418 | * | 414 | * |
| @@ -437,6 +433,7 @@ struct entropy_store { | |||
| 437 | int entropy_count; | 433 | int entropy_count; |
| 438 | int entropy_total; | 434 | int entropy_total; |
| 439 | unsigned int initialized:1; | 435 | unsigned int initialized:1; |
| 436 | bool last_data_init; | ||
| 440 | __u8 last_data[EXTRACT_SIZE]; | 437 | __u8 last_data[EXTRACT_SIZE]; |
| 441 | }; | 438 | }; |
| 442 | 439 | ||
| @@ -829,7 +826,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) | |||
| 829 | bytes = min_t(int, bytes, sizeof(tmp)); | 826 | bytes = min_t(int, bytes, sizeof(tmp)); |
| 830 | 827 | ||
| 831 | DEBUG_ENT("going to reseed %s with %d bits " | 828 | DEBUG_ENT("going to reseed %s with %d bits " |
| 832 | "(%d of %d requested)\n", | 829 | "(%zu of %d requested)\n", |
| 833 | r->name, bytes * 8, nbytes * 8, r->entropy_count); | 830 | r->name, bytes * 8, nbytes * 8, r->entropy_count); |
| 834 | 831 | ||
| 835 | bytes = extract_entropy(r->pull, tmp, bytes, | 832 | bytes = extract_entropy(r->pull, tmp, bytes, |
| @@ -860,7 +857,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
| 860 | spin_lock_irqsave(&r->lock, flags); | 857 | spin_lock_irqsave(&r->lock, flags); |
| 861 | 858 | ||
| 862 | BUG_ON(r->entropy_count > r->poolinfo->POOLBITS); | 859 | BUG_ON(r->entropy_count > r->poolinfo->POOLBITS); |
| 863 | DEBUG_ENT("trying to extract %d bits from %s\n", | 860 | DEBUG_ENT("trying to extract %zu bits from %s\n", |
| 864 | nbytes * 8, r->name); | 861 | nbytes * 8, r->name); |
| 865 | 862 | ||
| 866 | /* Can we pull enough? */ | 863 | /* Can we pull enough? */ |
| @@ -882,7 +879,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
| 882 | } | 879 | } |
| 883 | } | 880 | } |
| 884 | 881 | ||
| 885 | DEBUG_ENT("debiting %d entropy credits from %s%s\n", | 882 | DEBUG_ENT("debiting %zu entropy credits from %s%s\n", |
| 886 | nbytes * 8, r->name, r->limit ? "" : " (unlimited)"); | 883 | nbytes * 8, r->name, r->limit ? "" : " (unlimited)"); |
| 887 | 884 | ||
| 888 | spin_unlock_irqrestore(&r->lock, flags); | 885 | spin_unlock_irqrestore(&r->lock, flags); |
| @@ -957,6 +954,10 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
| 957 | ssize_t ret = 0, i; | 954 | ssize_t ret = 0, i; |
| 958 | __u8 tmp[EXTRACT_SIZE]; | 955 | __u8 tmp[EXTRACT_SIZE]; |
| 959 | 956 | ||
| 957 | /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ | ||
| 958 | if (fips_enabled && !r->last_data_init) | ||
| 959 | nbytes += EXTRACT_SIZE; | ||
| 960 | |||
| 960 | trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); | 961 | trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); |
| 961 | xfer_secondary_pool(r, nbytes); | 962 | xfer_secondary_pool(r, nbytes); |
| 962 | nbytes = account(r, nbytes, min, reserved); | 963 | nbytes = account(r, nbytes, min, reserved); |
| @@ -967,6 +968,17 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
| 967 | if (fips_enabled) { | 968 | if (fips_enabled) { |
| 968 | unsigned long flags; | 969 | unsigned long flags; |
| 969 | 970 | ||
| 971 | |||
| 972 | /* prime last_data value if need be, per fips 140-2 */ | ||
| 973 | if (!r->last_data_init) { | ||
| 974 | spin_lock_irqsave(&r->lock, flags); | ||
| 975 | memcpy(r->last_data, tmp, EXTRACT_SIZE); | ||
| 976 | r->last_data_init = true; | ||
| 977 | nbytes -= EXTRACT_SIZE; | ||
| 978 | spin_unlock_irqrestore(&r->lock, flags); | ||
| 979 | extract_buf(r, tmp); | ||
| 980 | } | ||
| 981 | |||
| 970 | spin_lock_irqsave(&r->lock, flags); | 982 | spin_lock_irqsave(&r->lock, flags); |
| 971 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) | 983 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) |
| 972 | panic("Hardware RNG duplicated output!\n"); | 984 | panic("Hardware RNG duplicated output!\n"); |
| @@ -1086,6 +1098,7 @@ static void init_std_data(struct entropy_store *r) | |||
| 1086 | 1098 | ||
| 1087 | r->entropy_count = 0; | 1099 | r->entropy_count = 0; |
| 1088 | r->entropy_total = 0; | 1100 | r->entropy_total = 0; |
| 1101 | r->last_data_init = false; | ||
| 1089 | mix_pool_bytes(r, &now, sizeof(now), NULL); | 1102 | mix_pool_bytes(r, &now, sizeof(now), NULL); |
| 1090 | for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { | 1103 | for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { |
| 1091 | if (!arch_get_random_long(&rv)) | 1104 | if (!arch_get_random_long(&rv)) |
| @@ -1142,11 +1155,16 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
| 1142 | if (n > SEC_XFER_SIZE) | 1155 | if (n > SEC_XFER_SIZE) |
| 1143 | n = SEC_XFER_SIZE; | 1156 | n = SEC_XFER_SIZE; |
| 1144 | 1157 | ||
| 1145 | DEBUG_ENT("reading %d bits\n", n*8); | 1158 | DEBUG_ENT("reading %zu bits\n", n*8); |
| 1146 | 1159 | ||
| 1147 | n = extract_entropy_user(&blocking_pool, buf, n); | 1160 | n = extract_entropy_user(&blocking_pool, buf, n); |
| 1148 | 1161 | ||
| 1149 | DEBUG_ENT("read got %d bits (%d still needed)\n", | 1162 | if (n < 0) { |
| 1163 | retval = n; | ||
| 1164 | break; | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | DEBUG_ENT("read got %zd bits (%zd still needed)\n", | ||
| 1150 | n*8, (nbytes-n)*8); | 1168 | n*8, (nbytes-n)*8); |
| 1151 | 1169 | ||
| 1152 | if (n == 0) { | 1170 | if (n == 0) { |
| @@ -1171,10 +1189,6 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
| 1171 | continue; | 1189 | continue; |
| 1172 | } | 1190 | } |
| 1173 | 1191 | ||
| 1174 | if (n < 0) { | ||
| 1175 | retval = n; | ||
| 1176 | break; | ||
| 1177 | } | ||
| 1178 | count += n; | 1192 | count += n; |
| 1179 | buf += n; | 1193 | buf += n; |
| 1180 | nbytes -= n; | 1194 | nbytes -= n; |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 90493d4ead1f..c594cb16c37b 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
| @@ -37,8 +37,12 @@ | |||
| 37 | #include <linux/wait.h> | 37 | #include <linux/wait.h> |
| 38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
| 39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
| 40 | #include <linux/dma-mapping.h> | ||
| 41 | #include <linux/kconfig.h> | ||
| 40 | #include "../tty/hvc/hvc_console.h" | 42 | #include "../tty/hvc/hvc_console.h" |
| 41 | 43 | ||
| 44 | #define is_rproc_enabled IS_ENABLED(CONFIG_REMOTEPROC) | ||
| 45 | |||
| 42 | /* | 46 | /* |
| 43 | * This is a global struct for storing common data for all the devices | 47 | * This is a global struct for storing common data for all the devices |
| 44 | * this driver handles. | 48 | * this driver handles. |
| @@ -111,6 +115,21 @@ struct port_buffer { | |||
| 111 | size_t len; | 115 | size_t len; |
| 112 | /* offset in the buf from which to consume data */ | 116 | /* offset in the buf from which to consume data */ |
| 113 | size_t offset; | 117 | size_t offset; |
| 118 | |||
| 119 | /* DMA address of buffer */ | ||
| 120 | dma_addr_t dma; | ||
| 121 | |||
| 122 | /* Device we got DMA memory from */ | ||
| 123 | struct device *dev; | ||
| 124 | |||
| 125 | /* List of pending dma buffers to free */ | ||
| 126 | struct list_head list; | ||
| 127 | |||
| 128 | /* If sgpages == 0 then buf is used */ | ||
| 129 | unsigned int sgpages; | ||
| 130 | |||
| 131 | /* sg is used if spages > 0. sg must be the last in is struct */ | ||
| 132 | struct scatterlist sg[0]; | ||
| 114 | }; | 133 | }; |
| 115 | 134 | ||
| 116 | /* | 135 | /* |
| @@ -325,6 +344,11 @@ static bool is_console_port(struct port *port) | |||
| 325 | return false; | 344 | return false; |
| 326 | } | 345 | } |
| 327 | 346 | ||
| 347 | static bool is_rproc_serial(const struct virtio_device *vdev) | ||
| 348 | { | ||
| 349 | return is_rproc_enabled && vdev->id.device == VIRTIO_ID_RPROC_SERIAL; | ||
| 350 | } | ||
| 351 | |||
| 328 | static inline bool use_multiport(struct ports_device *portdev) | 352 | static inline bool use_multiport(struct ports_device *portdev) |
| 329 | { | 353 | { |
| 330 | /* | 354 | /* |
| @@ -336,20 +360,110 @@ static inline bool use_multiport(struct ports_device *portdev) | |||
| 336 | return portdev->vdev->features[0] & (1 << VIRTIO_CONSOLE_F_MULTIPORT); | 360 | return portdev->vdev->features[0] & (1 << VIRTIO_CONSOLE_F_MULTIPORT); |
| 337 | } | 361 | } |
| 338 | 362 | ||
| 339 | static void free_buf(struct port_buffer *buf) | 363 | static DEFINE_SPINLOCK(dma_bufs_lock); |
| 364 | static LIST_HEAD(pending_free_dma_bufs); | ||
| 365 | |||
| 366 | static void free_buf(struct port_buffer *buf, bool can_sleep) | ||
| 340 | { | 367 | { |
| 341 | kfree(buf->buf); | 368 | unsigned int i; |
| 369 | |||
| 370 | for (i = 0; i < buf->sgpages; i++) { | ||
| 371 | struct page *page = sg_page(&buf->sg[i]); | ||
| 372 | if (!page) | ||
| 373 | break; | ||
| 374 | put_page(page); | ||
| 375 | } | ||
| 376 | |||
| 377 | if (!buf->dev) { | ||
| 378 | kfree(buf->buf); | ||
| 379 | } else if (is_rproc_enabled) { | ||
| 380 | unsigned long flags; | ||
| 381 | |||
| 382 | /* dma_free_coherent requires interrupts to be enabled. */ | ||
| 383 | if (!can_sleep) { | ||
| 384 | /* queue up dma-buffers to be freed later */ | ||
| 385 | spin_lock_irqsave(&dma_bufs_lock, flags); | ||
| 386 | list_add_tail(&buf->list, &pending_free_dma_bufs); | ||
| 387 | spin_unlock_irqrestore(&dma_bufs_lock, flags); | ||
| 388 | return; | ||
| 389 | } | ||
| 390 | dma_free_coherent(buf->dev, buf->size, buf->buf, buf->dma); | ||
| 391 | |||
| 392 | /* Release device refcnt and allow it to be freed */ | ||
| 393 | put_device(buf->dev); | ||
| 394 | } | ||
| 395 | |||
| 342 | kfree(buf); | 396 | kfree(buf); |
| 343 | } | 397 | } |
| 344 | 398 | ||
| 345 | static struct port_buffer *alloc_buf(size_t buf_size) | 399 | static void reclaim_dma_bufs(void) |
| 400 | { | ||
| 401 | unsigned long flags; | ||
| 402 | struct port_buffer *buf, *tmp; | ||
| 403 | LIST_HEAD(tmp_list); | ||
| 404 | |||
| 405 | if (list_empty(&pending_free_dma_bufs)) | ||
| 406 | return; | ||
| 407 | |||
| 408 | /* Create a copy of the pending_free_dma_bufs while holding the lock */ | ||
| 409 | spin_lock_irqsave(&dma_bufs_lock, flags); | ||
| 410 | list_cut_position(&tmp_list, &pending_free_dma_bufs, | ||
| 411 | pending_free_dma_bufs.prev); | ||
| 412 | spin_unlock_irqrestore(&dma_bufs_lock, flags); | ||
| 413 | |||
| 414 | /* Release the dma buffers, without irqs enabled */ | ||
| 415 | list_for_each_entry_safe(buf, tmp, &tmp_list, list) { | ||
| 416 | list_del(&buf->list); | ||
| 417 | free_buf(buf, true); | ||
| 418 | } | ||
| 419 | } | ||
| 420 | |||
| 421 | static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size, | ||
| 422 | int pages) | ||
| 346 | { | 423 | { |
| 347 | struct port_buffer *buf; | 424 | struct port_buffer *buf; |
| 348 | 425 | ||
| 349 | buf = kmalloc(sizeof(*buf), GFP_KERNEL); | 426 | reclaim_dma_bufs(); |
| 427 | |||
| 428 | /* | ||
| 429 | * Allocate buffer and the sg list. The sg list array is allocated | ||
| 430 | * directly after the port_buffer struct. | ||
| 431 | */ | ||
| 432 | buf = kmalloc(sizeof(*buf) + sizeof(struct scatterlist) * pages, | ||
| 433 | GFP_KERNEL); | ||
| 350 | if (!buf) | 434 | if (!buf) |
| 351 | goto fail; | 435 | goto fail; |
| 352 | buf->buf = kzalloc(buf_size, GFP_KERNEL); | 436 | |
| 437 | buf->sgpages = pages; | ||
| 438 | if (pages > 0) { | ||
| 439 | buf->dev = NULL; | ||
| 440 | buf->buf = NULL; | ||
| 441 | return buf; | ||
| 442 | } | ||
| 443 | |||
| 444 | if (is_rproc_serial(vq->vdev)) { | ||
| 445 | /* | ||
| 446 | * Allocate DMA memory from ancestor. When a virtio | ||
| 447 | * device is created by remoteproc, the DMA memory is | ||
| 448 | * associated with the grandparent device: | ||
| 449 | * vdev => rproc => platform-dev. | ||
| 450 | * The code here would have been less quirky if | ||
| 451 | * DMA_MEMORY_INCLUDES_CHILDREN had been supported | ||
| 452 | * in dma-coherent.c | ||
| 453 | */ | ||
| 454 | if (!vq->vdev->dev.parent || !vq->vdev->dev.parent->parent) | ||
| 455 | goto free_buf; | ||
| 456 | buf->dev = vq->vdev->dev.parent->parent; | ||
| 457 | |||
| 458 | /* Increase device refcnt to avoid freeing it */ | ||
| 459 | get_device(buf->dev); | ||
| 460 | buf->buf = dma_alloc_coherent(buf->dev, buf_size, &buf->dma, | ||
| 461 | GFP_KERNEL); | ||
| 462 | } else { | ||
| 463 | buf->dev = NULL; | ||
| 464 | buf->buf = kmalloc(buf_size, GFP_KERNEL); | ||
| 465 | } | ||
| 466 | |||
| 353 | if (!buf->buf) | 467 | if (!buf->buf) |
| 354 | goto free_buf; | 468 | goto free_buf; |
| 355 | buf->len = 0; | 469 | buf->len = 0; |
| @@ -396,6 +510,8 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf) | |||
| 396 | 510 | ||
| 397 | ret = virtqueue_add_buf(vq, sg, 0, 1, buf, GFP_ATOMIC); | 511 | ret = virtqueue_add_buf(vq, sg, 0, 1, buf, GFP_ATOMIC); |
| 398 | virtqueue_kick(vq); | 512 | virtqueue_kick(vq); |
| 513 | if (!ret) | ||
| 514 | ret = vq->num_free; | ||
| 399 | return ret; | 515 | return ret; |
| 400 | } | 516 | } |
| 401 | 517 | ||
| @@ -416,7 +532,7 @@ static void discard_port_data(struct port *port) | |||
| 416 | port->stats.bytes_discarded += buf->len - buf->offset; | 532 | port->stats.bytes_discarded += buf->len - buf->offset; |
| 417 | if (add_inbuf(port->in_vq, buf) < 0) { | 533 | if (add_inbuf(port->in_vq, buf) < 0) { |
| 418 | err++; | 534 | err++; |
| 419 | free_buf(buf); | 535 | free_buf(buf, false); |
| 420 | } | 536 | } |
| 421 | port->inbuf = NULL; | 537 | port->inbuf = NULL; |
| 422 | buf = get_inbuf(port); | 538 | buf = get_inbuf(port); |
| @@ -459,7 +575,7 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id, | |||
| 459 | vq = portdev->c_ovq; | 575 | vq = portdev->c_ovq; |
| 460 | 576 | ||
| 461 | sg_init_one(sg, &cpkt, sizeof(cpkt)); | 577 | sg_init_one(sg, &cpkt, sizeof(cpkt)); |
| 462 | if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) >= 0) { | 578 | if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) == 0) { |
| 463 | virtqueue_kick(vq); | 579 | virtqueue_kick(vq); |
| 464 | while (!virtqueue_get_buf(vq, &len)) | 580 | while (!virtqueue_get_buf(vq, &len)) |
| 465 | cpu_relax(); | 581 | cpu_relax(); |
| @@ -476,55 +592,29 @@ static ssize_t send_control_msg(struct port *port, unsigned int event, | |||
| 476 | return 0; | 592 | return 0; |
| 477 | } | 593 | } |
| 478 | 594 | ||
| 479 | struct buffer_token { | ||
| 480 | union { | ||
| 481 | void *buf; | ||
| 482 | struct scatterlist *sg; | ||
| 483 | } u; | ||
| 484 | /* If sgpages == 0 then buf is used, else sg is used */ | ||
| 485 | unsigned int sgpages; | ||
| 486 | }; | ||
| 487 | |||
| 488 | static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages) | ||
| 489 | { | ||
| 490 | int i; | ||
| 491 | struct page *page; | ||
| 492 | |||
| 493 | for (i = 0; i < nrpages; i++) { | ||
| 494 | page = sg_page(&sg[i]); | ||
| 495 | if (!page) | ||
| 496 | break; | ||
| 497 | put_page(page); | ||
| 498 | } | ||
| 499 | kfree(sg); | ||
| 500 | } | ||
| 501 | 595 | ||
| 502 | /* Callers must take the port->outvq_lock */ | 596 | /* Callers must take the port->outvq_lock */ |
| 503 | static void reclaim_consumed_buffers(struct port *port) | 597 | static void reclaim_consumed_buffers(struct port *port) |
| 504 | { | 598 | { |
| 505 | struct buffer_token *tok; | 599 | struct port_buffer *buf; |
| 506 | unsigned int len; | 600 | unsigned int len; |
| 507 | 601 | ||
| 508 | if (!port->portdev) { | 602 | if (!port->portdev) { |
| 509 | /* Device has been unplugged. vqs are already gone. */ | 603 | /* Device has been unplugged. vqs are already gone. */ |
| 510 | return; | 604 | return; |
| 511 | } | 605 | } |
| 512 | while ((tok = virtqueue_get_buf(port->out_vq, &len))) { | 606 | while ((buf = virtqueue_get_buf(port->out_vq, &len))) { |
| 513 | if (tok->sgpages) | 607 | free_buf(buf, false); |
| 514 | reclaim_sg_pages(tok->u.sg, tok->sgpages); | ||
| 515 | else | ||
| 516 | kfree(tok->u.buf); | ||
| 517 | kfree(tok); | ||
| 518 | port->outvq_full = false; | 608 | port->outvq_full = false; |
| 519 | } | 609 | } |
| 520 | } | 610 | } |
| 521 | 611 | ||
| 522 | static ssize_t __send_to_port(struct port *port, struct scatterlist *sg, | 612 | static ssize_t __send_to_port(struct port *port, struct scatterlist *sg, |
| 523 | int nents, size_t in_count, | 613 | int nents, size_t in_count, |
| 524 | struct buffer_token *tok, bool nonblock) | 614 | void *data, bool nonblock) |
| 525 | { | 615 | { |
| 526 | struct virtqueue *out_vq; | 616 | struct virtqueue *out_vq; |
| 527 | ssize_t ret; | 617 | int err; |
| 528 | unsigned long flags; | 618 | unsigned long flags; |
| 529 | unsigned int len; | 619 | unsigned int len; |
| 530 | 620 | ||
| @@ -534,17 +624,17 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg, | |||
| 534 | 624 | ||
| 535 | reclaim_consumed_buffers(port); | 625 | reclaim_consumed_buffers(port); |
| 536 | 626 | ||
| 537 | ret = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC); | 627 | err = virtqueue_add_buf(out_vq, sg, nents, 0, data, GFP_ATOMIC); |
| 538 | 628 | ||
| 539 | /* Tell Host to go! */ | 629 | /* Tell Host to go! */ |
| 540 | virtqueue_kick(out_vq); | 630 | virtqueue_kick(out_vq); |
| 541 | 631 | ||
| 542 | if (ret < 0) { | 632 | if (err) { |
| 543 | in_count = 0; | 633 | in_count = 0; |
| 544 | goto done; | 634 | goto done; |
| 545 | } | 635 | } |
| 546 | 636 | ||
| 547 | if (ret == 0) | 637 | if (out_vq->num_free == 0) |
| 548 | port->outvq_full = true; | 638 | port->outvq_full = true; |
| 549 | 639 | ||
| 550 | if (nonblock) | 640 | if (nonblock) |
| @@ -572,37 +662,6 @@ done: | |||
| 572 | return in_count; | 662 | return in_count; |
| 573 | } | 663 | } |
| 574 | 664 | ||
| 575 | static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, | ||
| 576 | bool nonblock) | ||
| 577 | { | ||
| 578 | struct scatterlist sg[1]; | ||
| 579 | struct buffer_token *tok; | ||
| 580 | |||
| 581 | tok = kmalloc(sizeof(*tok), GFP_ATOMIC); | ||
| 582 | if (!tok) | ||
| 583 | return -ENOMEM; | ||
| 584 | tok->sgpages = 0; | ||
| 585 | tok->u.buf = in_buf; | ||
| 586 | |||
| 587 | sg_init_one(sg, in_buf, in_count); | ||
| 588 | |||
| 589 | return __send_to_port(port, sg, 1, in_count, tok, nonblock); | ||
| 590 | } | ||
| 591 | |||
| 592 | static ssize_t send_pages(struct port *port, struct scatterlist *sg, int nents, | ||
| 593 | size_t in_count, bool nonblock) | ||
| 594 | { | ||
| 595 | struct buffer_token *tok; | ||
| 596 | |||
| 597 | tok = kmalloc(sizeof(*tok), GFP_ATOMIC); | ||
| 598 | if (!tok) | ||
| 599 | return -ENOMEM; | ||
| 600 | tok->sgpages = nents; | ||
| 601 | tok->u.sg = sg; | ||
| 602 | |||
| 603 | return __send_to_port(port, sg, nents, in_count, tok, nonblock); | ||
| 604 | } | ||
| 605 | |||
| 606 | /* | 665 | /* |
| 607 | * Give out the data that's requested from the buffer that we have | 666 | * Give out the data that's requested from the buffer that we have |
| 608 | * queued up. | 667 | * queued up. |
| @@ -748,9 +807,10 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
| 748 | size_t count, loff_t *offp) | 807 | size_t count, loff_t *offp) |
| 749 | { | 808 | { |
| 750 | struct port *port; | 809 | struct port *port; |
| 751 | char *buf; | 810 | struct port_buffer *buf; |
| 752 | ssize_t ret; | 811 | ssize_t ret; |
| 753 | bool nonblock; | 812 | bool nonblock; |
| 813 | struct scatterlist sg[1]; | ||
| 754 | 814 | ||
| 755 | /* Userspace could be out to fool us */ | 815 | /* Userspace could be out to fool us */ |
| 756 | if (!count) | 816 | if (!count) |
| @@ -766,11 +826,11 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
| 766 | 826 | ||
| 767 | count = min((size_t)(32 * 1024), count); | 827 | count = min((size_t)(32 * 1024), count); |
| 768 | 828 | ||
| 769 | buf = kmalloc(count, GFP_KERNEL); | 829 | buf = alloc_buf(port->out_vq, count, 0); |
| 770 | if (!buf) | 830 | if (!buf) |
| 771 | return -ENOMEM; | 831 | return -ENOMEM; |
| 772 | 832 | ||
| 773 | ret = copy_from_user(buf, ubuf, count); | 833 | ret = copy_from_user(buf->buf, ubuf, count); |
| 774 | if (ret) { | 834 | if (ret) { |
| 775 | ret = -EFAULT; | 835 | ret = -EFAULT; |
| 776 | goto free_buf; | 836 | goto free_buf; |
| @@ -784,13 +844,14 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
| 784 | * through to the host. | 844 | * through to the host. |
| 785 | */ | 845 | */ |
| 786 | nonblock = true; | 846 | nonblock = true; |
| 787 | ret = send_buf(port, buf, count, nonblock); | 847 | sg_init_one(sg, buf->buf, count); |
| 848 | ret = __send_to_port(port, sg, 1, count, buf, nonblock); | ||
| 788 | 849 | ||
| 789 | if (nonblock && ret > 0) | 850 | if (nonblock && ret > 0) |
| 790 | goto out; | 851 | goto out; |
| 791 | 852 | ||
| 792 | free_buf: | 853 | free_buf: |
| 793 | kfree(buf); | 854 | free_buf(buf, true); |
| 794 | out: | 855 | out: |
| 795 | return ret; | 856 | return ret; |
| 796 | } | 857 | } |
| @@ -856,6 +917,7 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, | |||
| 856 | struct port *port = filp->private_data; | 917 | struct port *port = filp->private_data; |
| 857 | struct sg_list sgl; | 918 | struct sg_list sgl; |
| 858 | ssize_t ret; | 919 | ssize_t ret; |
| 920 | struct port_buffer *buf; | ||
| 859 | struct splice_desc sd = { | 921 | struct splice_desc sd = { |
| 860 | .total_len = len, | 922 | .total_len = len, |
| 861 | .flags = flags, | 923 | .flags = flags, |
| @@ -863,22 +925,34 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, | |||
| 863 | .u.data = &sgl, | 925 | .u.data = &sgl, |
| 864 | }; | 926 | }; |
| 865 | 927 | ||
| 928 | /* | ||
| 929 | * Rproc_serial does not yet support splice. To support splice | ||
| 930 | * pipe_to_sg() must allocate dma-buffers and copy content from | ||
| 931 | * regular pages to dma pages. And alloc_buf and free_buf must | ||
| 932 | * support allocating and freeing such a list of dma-buffers. | ||
| 933 | */ | ||
| 934 | if (is_rproc_serial(port->out_vq->vdev)) | ||
| 935 | return -EINVAL; | ||
| 936 | |||
| 866 | ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK); | 937 | ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK); |
| 867 | if (ret < 0) | 938 | if (ret < 0) |
| 868 | return ret; | 939 | return ret; |
| 869 | 940 | ||
| 941 | buf = alloc_buf(port->out_vq, 0, pipe->nrbufs); | ||
| 942 | if (!buf) | ||
| 943 | return -ENOMEM; | ||
| 944 | |||
| 870 | sgl.n = 0; | 945 | sgl.n = 0; |
| 871 | sgl.len = 0; | 946 | sgl.len = 0; |
| 872 | sgl.size = pipe->nrbufs; | 947 | sgl.size = pipe->nrbufs; |
| 873 | sgl.sg = kmalloc(sizeof(struct scatterlist) * sgl.size, GFP_KERNEL); | 948 | sgl.sg = buf->sg; |
| 874 | if (unlikely(!sgl.sg)) | ||
| 875 | return -ENOMEM; | ||
| 876 | |||
| 877 | sg_init_table(sgl.sg, sgl.size); | 949 | sg_init_table(sgl.sg, sgl.size); |
| 878 | ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); | 950 | ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); |
| 879 | if (likely(ret > 0)) | 951 | if (likely(ret > 0)) |
| 880 | ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true); | 952 | ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true); |
| 881 | 953 | ||
| 954 | if (unlikely(ret <= 0)) | ||
| 955 | free_buf(buf, true); | ||
| 882 | return ret; | 956 | return ret; |
| 883 | } | 957 | } |
| 884 | 958 | ||
| @@ -927,6 +1001,7 @@ static int port_fops_release(struct inode *inode, struct file *filp) | |||
| 927 | reclaim_consumed_buffers(port); | 1001 | reclaim_consumed_buffers(port); |
| 928 | spin_unlock_irq(&port->outvq_lock); | 1002 | spin_unlock_irq(&port->outvq_lock); |
| 929 | 1003 | ||
| 1004 | reclaim_dma_bufs(); | ||
| 930 | /* | 1005 | /* |
| 931 | * Locks aren't necessary here as a port can't be opened after | 1006 | * Locks aren't necessary here as a port can't be opened after |
| 932 | * unplug, and if a port isn't unplugged, a kref would already | 1007 | * unplug, and if a port isn't unplugged, a kref would already |
| @@ -1031,6 +1106,7 @@ static const struct file_operations port_fops = { | |||
| 1031 | static int put_chars(u32 vtermno, const char *buf, int count) | 1106 | static int put_chars(u32 vtermno, const char *buf, int count) |
| 1032 | { | 1107 | { |
| 1033 | struct port *port; | 1108 | struct port *port; |
| 1109 | struct scatterlist sg[1]; | ||
| 1034 | 1110 | ||
| 1035 | if (unlikely(early_put_chars)) | 1111 | if (unlikely(early_put_chars)) |
| 1036 | return early_put_chars(vtermno, buf, count); | 1112 | return early_put_chars(vtermno, buf, count); |
| @@ -1039,7 +1115,8 @@ static int put_chars(u32 vtermno, const char *buf, int count) | |||
| 1039 | if (!port) | 1115 | if (!port) |
| 1040 | return -EPIPE; | 1116 | return -EPIPE; |
| 1041 | 1117 | ||
| 1042 | return send_buf(port, (void *)buf, count, false); | 1118 | sg_init_one(sg, buf, count); |
| 1119 | return __send_to_port(port, sg, 1, count, (void *)buf, false); | ||
| 1043 | } | 1120 | } |
| 1044 | 1121 | ||
| 1045 | /* | 1122 | /* |
| @@ -1076,7 +1153,10 @@ static void resize_console(struct port *port) | |||
| 1076 | return; | 1153 | return; |
| 1077 | 1154 | ||
| 1078 | vdev = port->portdev->vdev; | 1155 | vdev = port->portdev->vdev; |
| 1079 | if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) | 1156 | |
| 1157 | /* Don't test F_SIZE at all if we're rproc: not a valid feature! */ | ||
| 1158 | if (!is_rproc_serial(vdev) && | ||
| 1159 | virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) | ||
| 1080 | hvc_resize(port->cons.hvc, port->cons.ws); | 1160 | hvc_resize(port->cons.hvc, port->cons.ws); |
| 1081 | } | 1161 | } |
| 1082 | 1162 | ||
| @@ -1260,7 +1340,7 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) | |||
| 1260 | 1340 | ||
| 1261 | nr_added_bufs = 0; | 1341 | nr_added_bufs = 0; |
| 1262 | do { | 1342 | do { |
| 1263 | buf = alloc_buf(PAGE_SIZE); | 1343 | buf = alloc_buf(vq, PAGE_SIZE, 0); |
| 1264 | if (!buf) | 1344 | if (!buf) |
| 1265 | break; | 1345 | break; |
| 1266 | 1346 | ||
| @@ -1268,7 +1348,7 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) | |||
| 1268 | ret = add_inbuf(vq, buf); | 1348 | ret = add_inbuf(vq, buf); |
| 1269 | if (ret < 0) { | 1349 | if (ret < 0) { |
| 1270 | spin_unlock_irq(lock); | 1350 | spin_unlock_irq(lock); |
| 1271 | free_buf(buf); | 1351 | free_buf(buf, true); |
| 1272 | break; | 1352 | break; |
| 1273 | } | 1353 | } |
| 1274 | nr_added_bufs++; | 1354 | nr_added_bufs++; |
| @@ -1356,10 +1436,18 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
| 1356 | goto free_device; | 1436 | goto free_device; |
| 1357 | } | 1437 | } |
| 1358 | 1438 | ||
| 1359 | /* | 1439 | if (is_rproc_serial(port->portdev->vdev)) |
| 1360 | * If we're not using multiport support, this has to be a console port | 1440 | /* |
| 1361 | */ | 1441 | * For rproc_serial assume remote processor is connected. |
| 1362 | if (!use_multiport(port->portdev)) { | 1442 | * rproc_serial does not want the console port, only |
| 1443 | * the generic port implementation. | ||
| 1444 | */ | ||
| 1445 | port->host_connected = true; | ||
| 1446 | else if (!use_multiport(port->portdev)) { | ||
| 1447 | /* | ||
| 1448 | * If we're not using multiport support, | ||
| 1449 | * this has to be a console port. | ||
| 1450 | */ | ||
| 1363 | err = init_port_console(port); | 1451 | err = init_port_console(port); |
| 1364 | if (err) | 1452 | if (err) |
| 1365 | goto free_inbufs; | 1453 | goto free_inbufs; |
| @@ -1392,7 +1480,7 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
| 1392 | 1480 | ||
| 1393 | free_inbufs: | 1481 | free_inbufs: |
| 1394 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | 1482 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) |
| 1395 | free_buf(buf); | 1483 | free_buf(buf, true); |
| 1396 | free_device: | 1484 | free_device: |
| 1397 | device_destroy(pdrvdata.class, port->dev->devt); | 1485 | device_destroy(pdrvdata.class, port->dev->devt); |
| 1398 | free_cdev: | 1486 | free_cdev: |
| @@ -1434,7 +1522,11 @@ static void remove_port_data(struct port *port) | |||
| 1434 | 1522 | ||
| 1435 | /* Remove buffers we queued up for the Host to send us data in. */ | 1523 | /* Remove buffers we queued up for the Host to send us data in. */ |
| 1436 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | 1524 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) |
| 1437 | free_buf(buf); | 1525 | free_buf(buf, true); |
| 1526 | |||
| 1527 | /* Free pending buffers from the out-queue. */ | ||
| 1528 | while ((buf = virtqueue_detach_unused_buf(port->out_vq))) | ||
| 1529 | free_buf(buf, true); | ||
| 1438 | } | 1530 | } |
| 1439 | 1531 | ||
| 1440 | /* | 1532 | /* |
| @@ -1636,7 +1728,7 @@ static void control_work_handler(struct work_struct *work) | |||
| 1636 | if (add_inbuf(portdev->c_ivq, buf) < 0) { | 1728 | if (add_inbuf(portdev->c_ivq, buf) < 0) { |
| 1637 | dev_warn(&portdev->vdev->dev, | 1729 | dev_warn(&portdev->vdev->dev, |
| 1638 | "Error adding buffer to queue\n"); | 1730 | "Error adding buffer to queue\n"); |
| 1639 | free_buf(buf); | 1731 | free_buf(buf, false); |
| 1640 | } | 1732 | } |
| 1641 | } | 1733 | } |
| 1642 | spin_unlock(&portdev->cvq_lock); | 1734 | spin_unlock(&portdev->cvq_lock); |
| @@ -1832,10 +1924,10 @@ static void remove_controlq_data(struct ports_device *portdev) | |||
| 1832 | return; | 1924 | return; |
| 1833 | 1925 | ||
| 1834 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) | 1926 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) |
| 1835 | free_buf(buf); | 1927 | free_buf(buf, true); |
| 1836 | 1928 | ||
| 1837 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) | 1929 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) |
| 1838 | free_buf(buf); | 1930 | free_buf(buf, true); |
| 1839 | } | 1931 | } |
| 1840 | 1932 | ||
| 1841 | /* | 1933 | /* |
| @@ -1882,11 +1974,15 @@ static int virtcons_probe(struct virtio_device *vdev) | |||
| 1882 | 1974 | ||
| 1883 | multiport = false; | 1975 | multiport = false; |
| 1884 | portdev->config.max_nr_ports = 1; | 1976 | portdev->config.max_nr_ports = 1; |
| 1885 | if (virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT, | 1977 | |
| 1886 | offsetof(struct virtio_console_config, | 1978 | /* Don't test MULTIPORT at all if we're rproc: not a valid feature! */ |
| 1887 | max_nr_ports), | 1979 | if (!is_rproc_serial(vdev) && |
| 1888 | &portdev->config.max_nr_ports) == 0) | 1980 | virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT, |
| 1981 | offsetof(struct virtio_console_config, | ||
| 1982 | max_nr_ports), | ||
| 1983 | &portdev->config.max_nr_ports) == 0) { | ||
| 1889 | multiport = true; | 1984 | multiport = true; |
| 1985 | } | ||
| 1890 | 1986 | ||
| 1891 | err = init_vqs(portdev); | 1987 | err = init_vqs(portdev); |
| 1892 | if (err < 0) { | 1988 | if (err < 0) { |
| @@ -1996,6 +2092,16 @@ static unsigned int features[] = { | |||
| 1996 | VIRTIO_CONSOLE_F_MULTIPORT, | 2092 | VIRTIO_CONSOLE_F_MULTIPORT, |
| 1997 | }; | 2093 | }; |
| 1998 | 2094 | ||
| 2095 | static struct virtio_device_id rproc_serial_id_table[] = { | ||
| 2096 | #if IS_ENABLED(CONFIG_REMOTEPROC) | ||
| 2097 | { VIRTIO_ID_RPROC_SERIAL, VIRTIO_DEV_ANY_ID }, | ||
| 2098 | #endif | ||
| 2099 | { 0 }, | ||
| 2100 | }; | ||
| 2101 | |||
| 2102 | static unsigned int rproc_serial_features[] = { | ||
| 2103 | }; | ||
| 2104 | |||
| 1999 | #ifdef CONFIG_PM | 2105 | #ifdef CONFIG_PM |
| 2000 | static int virtcons_freeze(struct virtio_device *vdev) | 2106 | static int virtcons_freeze(struct virtio_device *vdev) |
| 2001 | { | 2107 | { |
| @@ -2080,6 +2186,20 @@ static struct virtio_driver virtio_console = { | |||
| 2080 | #endif | 2186 | #endif |
| 2081 | }; | 2187 | }; |
| 2082 | 2188 | ||
| 2189 | /* | ||
| 2190 | * virtio_rproc_serial refers to __devinit function which causes | ||
| 2191 | * section mismatch warnings. So use __refdata to silence warnings. | ||
| 2192 | */ | ||
| 2193 | static struct virtio_driver __refdata virtio_rproc_serial = { | ||
| 2194 | .feature_table = rproc_serial_features, | ||
| 2195 | .feature_table_size = ARRAY_SIZE(rproc_serial_features), | ||
| 2196 | .driver.name = "virtio_rproc_serial", | ||
| 2197 | .driver.owner = THIS_MODULE, | ||
| 2198 | .id_table = rproc_serial_id_table, | ||
| 2199 | .probe = virtcons_probe, | ||
| 2200 | .remove = virtcons_remove, | ||
| 2201 | }; | ||
| 2202 | |||
| 2083 | static int __init init(void) | 2203 | static int __init init(void) |
| 2084 | { | 2204 | { |
| 2085 | int err; | 2205 | int err; |
| @@ -2104,7 +2224,15 @@ static int __init init(void) | |||
| 2104 | pr_err("Error %d registering virtio driver\n", err); | 2224 | pr_err("Error %d registering virtio driver\n", err); |
| 2105 | goto free; | 2225 | goto free; |
| 2106 | } | 2226 | } |
| 2227 | err = register_virtio_driver(&virtio_rproc_serial); | ||
| 2228 | if (err < 0) { | ||
| 2229 | pr_err("Error %d registering virtio rproc serial driver\n", | ||
| 2230 | err); | ||
| 2231 | goto unregister; | ||
| 2232 | } | ||
| 2107 | return 0; | 2233 | return 0; |
| 2234 | unregister: | ||
| 2235 | unregister_virtio_driver(&virtio_console); | ||
| 2108 | free: | 2236 | free: |
| 2109 | if (pdrvdata.debugfs_dir) | 2237 | if (pdrvdata.debugfs_dir) |
| 2110 | debugfs_remove_recursive(pdrvdata.debugfs_dir); | 2238 | debugfs_remove_recursive(pdrvdata.debugfs_dir); |
| @@ -2114,7 +2242,10 @@ free: | |||
| 2114 | 2242 | ||
| 2115 | static void __exit fini(void) | 2243 | static void __exit fini(void) |
| 2116 | { | 2244 | { |
| 2245 | reclaim_dma_bufs(); | ||
| 2246 | |||
| 2117 | unregister_virtio_driver(&virtio_console); | 2247 | unregister_virtio_driver(&virtio_console); |
| 2248 | unregister_virtio_driver(&virtio_rproc_serial); | ||
| 2118 | 2249 | ||
| 2119 | class_destroy(pdrvdata.class); | 2250 | class_destroy(pdrvdata.class); |
| 2120 | if (pdrvdata.debugfs_dir) | 2251 | if (pdrvdata.debugfs_dir) |
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index b298158cb922..fd3ae6290d71 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | */ | 16 | */ |
| 17 | static char dmi_empty_string[] = " "; | 17 | static char dmi_empty_string[] = " "; |
| 18 | 18 | ||
| 19 | static u16 __initdata dmi_ver; | ||
| 19 | /* | 20 | /* |
| 20 | * Catch too early calls to dmi_check_system(): | 21 | * Catch too early calls to dmi_check_system(): |
| 21 | */ | 22 | */ |
| @@ -118,12 +119,12 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, | |||
| 118 | return 0; | 119 | return 0; |
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | static int __init dmi_checksum(const u8 *buf) | 122 | static int __init dmi_checksum(const u8 *buf, u8 len) |
| 122 | { | 123 | { |
| 123 | u8 sum = 0; | 124 | u8 sum = 0; |
| 124 | int a; | 125 | int a; |
| 125 | 126 | ||
| 126 | for (a = 0; a < 15; a++) | 127 | for (a = 0; a < len; a++) |
| 127 | sum += buf[a]; | 128 | sum += buf[a]; |
| 128 | 129 | ||
| 129 | return sum == 0; | 130 | return sum == 0; |
| @@ -161,8 +162,10 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde | |||
| 161 | return; | 162 | return; |
| 162 | 163 | ||
| 163 | for (i = 0; i < 16 && (is_ff || is_00); i++) { | 164 | for (i = 0; i < 16 && (is_ff || is_00); i++) { |
| 164 | if(d[i] != 0x00) is_ff = 0; | 165 | if (d[i] != 0x00) |
| 165 | if(d[i] != 0xFF) is_00 = 0; | 166 | is_00 = 0; |
| 167 | if (d[i] != 0xFF) | ||
| 168 | is_ff = 0; | ||
| 166 | } | 169 | } |
| 167 | 170 | ||
| 168 | if (is_ff || is_00) | 171 | if (is_ff || is_00) |
| @@ -172,7 +175,15 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde | |||
| 172 | if (!s) | 175 | if (!s) |
| 173 | return; | 176 | return; |
| 174 | 177 | ||
| 175 | sprintf(s, "%pUB", d); | 178 | /* |
| 179 | * As of version 2.6 of the SMBIOS specification, the first 3 fields of | ||
| 180 | * the UUID are supposed to be little-endian encoded. The specification | ||
| 181 | * says that this is the defacto standard. | ||
| 182 | */ | ||
| 183 | if (dmi_ver >= 0x0206) | ||
| 184 | sprintf(s, "%pUL", d); | ||
| 185 | else | ||
| 186 | sprintf(s, "%pUB", d); | ||
| 176 | 187 | ||
| 177 | dmi_ident[slot] = s; | 188 | dmi_ident[slot] = s; |
| 178 | } | 189 | } |
| @@ -404,29 +415,57 @@ static int __init dmi_present(const char __iomem *p) | |||
| 404 | u8 buf[15]; | 415 | u8 buf[15]; |
| 405 | 416 | ||
| 406 | memcpy_fromio(buf, p, 15); | 417 | memcpy_fromio(buf, p, 15); |
| 407 | if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) { | 418 | if (dmi_checksum(buf, 15)) { |
| 408 | dmi_num = (buf[13] << 8) | buf[12]; | 419 | dmi_num = (buf[13] << 8) | buf[12]; |
| 409 | dmi_len = (buf[7] << 8) | buf[6]; | 420 | dmi_len = (buf[7] << 8) | buf[6]; |
| 410 | dmi_base = (buf[11] << 24) | (buf[10] << 16) | | 421 | dmi_base = (buf[11] << 24) | (buf[10] << 16) | |
| 411 | (buf[9] << 8) | buf[8]; | 422 | (buf[9] << 8) | buf[8]; |
| 412 | 423 | ||
| 413 | /* | ||
| 414 | * DMI version 0.0 means that the real version is taken from | ||
| 415 | * the SMBIOS version, which we don't know at this point. | ||
| 416 | */ | ||
| 417 | if (buf[14] != 0) | ||
| 418 | printk(KERN_INFO "DMI %d.%d present.\n", | ||
| 419 | buf[14] >> 4, buf[14] & 0xF); | ||
| 420 | else | ||
| 421 | printk(KERN_INFO "DMI present.\n"); | ||
| 422 | if (dmi_walk_early(dmi_decode) == 0) { | 424 | if (dmi_walk_early(dmi_decode) == 0) { |
| 425 | if (dmi_ver) | ||
| 426 | pr_info("SMBIOS %d.%d present.\n", | ||
| 427 | dmi_ver >> 8, dmi_ver & 0xFF); | ||
| 428 | else { | ||
| 429 | dmi_ver = (buf[14] & 0xF0) << 4 | | ||
| 430 | (buf[14] & 0x0F); | ||
| 431 | pr_info("Legacy DMI %d.%d present.\n", | ||
| 432 | dmi_ver >> 8, dmi_ver & 0xFF); | ||
| 433 | } | ||
| 423 | dmi_dump_ids(); | 434 | dmi_dump_ids(); |
| 424 | return 0; | 435 | return 0; |
| 425 | } | 436 | } |
| 426 | } | 437 | } |
| 438 | dmi_ver = 0; | ||
| 427 | return 1; | 439 | return 1; |
| 428 | } | 440 | } |
| 429 | 441 | ||
| 442 | static int __init smbios_present(const char __iomem *p) | ||
| 443 | { | ||
| 444 | u8 buf[32]; | ||
| 445 | int offset = 0; | ||
| 446 | |||
| 447 | memcpy_fromio(buf, p, 32); | ||
| 448 | if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { | ||
| 449 | dmi_ver = (buf[6] << 8) + buf[7]; | ||
| 450 | |||
| 451 | /* Some BIOS report weird SMBIOS version, fix that up */ | ||
| 452 | switch (dmi_ver) { | ||
| 453 | case 0x021F: | ||
| 454 | case 0x0221: | ||
| 455 | pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", | ||
| 456 | dmi_ver & 0xFF, 3); | ||
| 457 | dmi_ver = 0x0203; | ||
| 458 | break; | ||
| 459 | case 0x0233: | ||
| 460 | pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6); | ||
| 461 | dmi_ver = 0x0206; | ||
| 462 | break; | ||
| 463 | } | ||
| 464 | offset = 16; | ||
| 465 | } | ||
| 466 | return dmi_present(buf + offset); | ||
| 467 | } | ||
| 468 | |||
| 430 | void __init dmi_scan_machine(void) | 469 | void __init dmi_scan_machine(void) |
| 431 | { | 470 | { |
| 432 | char __iomem *p, *q; | 471 | char __iomem *p, *q; |
| @@ -444,7 +483,7 @@ void __init dmi_scan_machine(void) | |||
| 444 | if (p == NULL) | 483 | if (p == NULL) |
| 445 | goto error; | 484 | goto error; |
| 446 | 485 | ||
| 447 | rc = dmi_present(p + 0x10); /* offset of _DMI_ string */ | 486 | rc = smbios_present(p); |
| 448 | dmi_iounmap(p, 32); | 487 | dmi_iounmap(p, 32); |
| 449 | if (!rc) { | 488 | if (!rc) { |
| 450 | dmi_available = 1; | 489 | dmi_available = 1; |
| @@ -462,7 +501,12 @@ void __init dmi_scan_machine(void) | |||
| 462 | goto error; | 501 | goto error; |
| 463 | 502 | ||
| 464 | for (q = p; q < p + 0x10000; q += 16) { | 503 | for (q = p; q < p + 0x10000; q += 16) { |
| 465 | rc = dmi_present(q); | 504 | if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0) |
| 505 | rc = smbios_present(q); | ||
| 506 | else if (memcmp(q, "_DMI_", 5) == 0) | ||
| 507 | rc = dmi_present(q); | ||
| 508 | else | ||
| 509 | continue; | ||
| 466 | if (!rc) { | 510 | if (!rc) { |
| 467 | dmi_available = 1; | 511 | dmi_available = 1; |
| 468 | dmi_iounmap(p, 0x10000); | 512 | dmi_iounmap(p, 0x10000); |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8ae1f5b19669..682de754d63f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -172,6 +172,7 @@ config GPIO_MSM_V2 | |||
| 172 | config GPIO_MVEBU | 172 | config GPIO_MVEBU |
| 173 | def_bool y | 173 | def_bool y |
| 174 | depends on PLAT_ORION | 174 | depends on PLAT_ORION |
| 175 | depends on OF | ||
| 175 | select GPIO_GENERIC | 176 | select GPIO_GENERIC |
| 176 | select GENERIC_IRQ_CHIP | 177 | select GENERIC_IRQ_CHIP |
| 177 | 178 | ||
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index 6cc87ac8e019..6f2306db8591 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c | |||
| @@ -390,6 +390,7 @@ static int ichx_gpio_probe(struct platform_device *pdev) | |||
| 390 | return -ENODEV; | 390 | return -ENODEV; |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | spin_lock_init(&ichx_priv.lock); | ||
| 393 | res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); | 394 | res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); |
| 394 | ichx_priv.use_gpio = ich_info->use_gpio; | 395 | ichx_priv.use_gpio = ich_info->use_gpio; |
| 395 | err = ichx_gpio_request_regions(res_base, pdev->name, | 396 | err = ichx_gpio_request_regions(res_base, pdev->name, |
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index d767b534c4af..7d9bd94be8d2 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c | |||
| @@ -41,7 +41,6 @@ | |||
| 41 | #include <linux/io.h> | 41 | #include <linux/io.h> |
| 42 | #include <linux/of_irq.h> | 42 | #include <linux/of_irq.h> |
| 43 | #include <linux/of_device.h> | 43 | #include <linux/of_device.h> |
| 44 | #include <linux/platform_device.h> | ||
| 45 | #include <linux/pinctrl/consumer.h> | 44 | #include <linux/pinctrl/consumer.h> |
| 46 | 45 | ||
| 47 | /* | 46 | /* |
| @@ -469,19 +468,6 @@ static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
| 469 | } | 468 | } |
| 470 | } | 469 | } |
| 471 | 470 | ||
| 472 | static struct platform_device_id mvebu_gpio_ids[] = { | ||
| 473 | { | ||
| 474 | .name = "orion-gpio", | ||
| 475 | }, { | ||
| 476 | .name = "mv78200-gpio", | ||
| 477 | }, { | ||
| 478 | .name = "armadaxp-gpio", | ||
| 479 | }, { | ||
| 480 | /* sentinel */ | ||
| 481 | }, | ||
| 482 | }; | ||
| 483 | MODULE_DEVICE_TABLE(platform, mvebu_gpio_ids); | ||
| 484 | |||
| 485 | static struct of_device_id mvebu_gpio_of_match[] = { | 471 | static struct of_device_id mvebu_gpio_of_match[] = { |
| 486 | { | 472 | { |
| 487 | .compatible = "marvell,orion-gpio", | 473 | .compatible = "marvell,orion-gpio", |
| @@ -555,9 +541,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
| 555 | mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK; | 541 | mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK; |
| 556 | mvchip->chip.ngpio = ngpios; | 542 | mvchip->chip.ngpio = ngpios; |
| 557 | mvchip->chip.can_sleep = 0; | 543 | mvchip->chip.can_sleep = 0; |
| 558 | #ifdef CONFIG_OF | ||
| 559 | mvchip->chip.of_node = np; | 544 | mvchip->chip.of_node = np; |
| 560 | #endif | ||
| 561 | 545 | ||
| 562 | spin_lock_init(&mvchip->lock); | 546 | spin_lock_init(&mvchip->lock); |
| 563 | mvchip->membase = devm_request_and_ioremap(&pdev->dev, res); | 547 | mvchip->membase = devm_request_and_ioremap(&pdev->dev, res); |
| @@ -698,7 +682,6 @@ static struct platform_driver mvebu_gpio_driver = { | |||
| 698 | .of_match_table = mvebu_gpio_of_match, | 682 | .of_match_table = mvebu_gpio_of_match, |
| 699 | }, | 683 | }, |
| 700 | .probe = mvebu_gpio_probe, | 684 | .probe = mvebu_gpio_probe, |
| 701 | .id_table = mvebu_gpio_ids, | ||
| 702 | }; | 685 | }; |
| 703 | 686 | ||
| 704 | static int __init mvebu_gpio_init(void) | 687 | static int __init mvebu_gpio_init(void) |
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index a9151337d5b9..33d20be87db5 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
| @@ -579,7 +579,7 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo, | |||
| 579 | * at this point the buffer should be dead, so | 579 | * at this point the buffer should be dead, so |
| 580 | * no new sync objects can be attached. | 580 | * no new sync objects can be attached. |
| 581 | */ | 581 | */ |
| 582 | sync_obj = driver->sync_obj_ref(&bo->sync_obj); | 582 | sync_obj = driver->sync_obj_ref(bo->sync_obj); |
| 583 | spin_unlock(&bdev->fence_lock); | 583 | spin_unlock(&bdev->fence_lock); |
| 584 | 584 | ||
| 585 | atomic_set(&bo->reserved, 0); | 585 | atomic_set(&bo->reserved, 0); |
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index 9f26400713f0..89cfd64b3373 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c | |||
| @@ -115,6 +115,12 @@ int vid_from_reg(int val, u8 vrm) | |||
| 115 | return (val < 32) ? 1550 - 25 * val | 115 | return (val < 32) ? 1550 - 25 * val |
| 116 | : 775 - (25 * (val - 31)) / 2; | 116 | : 775 - (25 * (val - 31)) / 2; |
| 117 | 117 | ||
| 118 | case 26: /* AMD family 10h to 15h, serial VID */ | ||
| 119 | val &= 0x7f; | ||
| 120 | if (val >= 0x7c) | ||
| 121 | return 0; | ||
| 122 | return DIV_ROUND_CLOSEST(15500 - 125 * val, 10); | ||
| 123 | |||
| 118 | case 91: /* VRM 9.1 */ | 124 | case 91: /* VRM 9.1 */ |
| 119 | case 90: /* VRM 9.0 */ | 125 | case 90: /* VRM 9.0 */ |
| 120 | val &= 0x1f; | 126 | val &= 0x1f; |
| @@ -195,6 +201,10 @@ static struct vrm_model vrm_models[] = { | |||
| 195 | {X86_VENDOR_AMD, 0xF, 0x40, 0x7F, ANY, 24}, /* NPT family 0Fh */ | 201 | {X86_VENDOR_AMD, 0xF, 0x40, 0x7F, ANY, 24}, /* NPT family 0Fh */ |
| 196 | {X86_VENDOR_AMD, 0xF, 0x80, ANY, ANY, 25}, /* future fam. 0Fh */ | 202 | {X86_VENDOR_AMD, 0xF, 0x80, ANY, ANY, 25}, /* future fam. 0Fh */ |
| 197 | {X86_VENDOR_AMD, 0x10, 0x0, ANY, ANY, 25}, /* NPT family 10h */ | 203 | {X86_VENDOR_AMD, 0x10, 0x0, ANY, ANY, 25}, /* NPT family 10h */ |
| 204 | {X86_VENDOR_AMD, 0x11, 0x0, ANY, ANY, 26}, /* family 11h */ | ||
| 205 | {X86_VENDOR_AMD, 0x12, 0x0, ANY, ANY, 26}, /* family 12h */ | ||
| 206 | {X86_VENDOR_AMD, 0x14, 0x0, ANY, ANY, 26}, /* family 14h */ | ||
| 207 | {X86_VENDOR_AMD, 0x15, 0x0, ANY, ANY, 26}, /* family 15h */ | ||
| 198 | 208 | ||
| 199 | {X86_VENDOR_INTEL, 0x6, 0x0, 0x6, ANY, 82}, /* Pentium Pro, | 209 | {X86_VENDOR_INTEL, 0x6, 0x0, 0x6, ANY, 82}, /* Pentium Pro, |
| 200 | * Pentium II, Xeon, | 210 | * Pentium II, Xeon, |
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index c3c471ca202f..646314f7c839 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c | |||
| @@ -84,19 +84,21 @@ static void __init hwmon_pci_quirks(void) | |||
| 84 | 84 | ||
| 85 | /* Open access to 0x295-0x296 on MSI MS-7031 */ | 85 | /* Open access to 0x295-0x296 on MSI MS-7031 */ |
| 86 | sb = pci_get_device(PCI_VENDOR_ID_ATI, 0x436c, NULL); | 86 | sb = pci_get_device(PCI_VENDOR_ID_ATI, 0x436c, NULL); |
| 87 | if (sb && | 87 | if (sb) { |
| 88 | (sb->subsystem_vendor == 0x1462 && /* MSI */ | 88 | if (sb->subsystem_vendor == 0x1462 && /* MSI */ |
| 89 | sb->subsystem_device == 0x0031)) { /* MS-7031 */ | 89 | sb->subsystem_device == 0x0031) { /* MS-7031 */ |
| 90 | 90 | pci_read_config_byte(sb, 0x48, &enable); | |
| 91 | pci_read_config_byte(sb, 0x48, &enable); | 91 | pci_read_config_word(sb, 0x64, &base); |
| 92 | pci_read_config_word(sb, 0x64, &base); | 92 | |
| 93 | 93 | if (base == 0 && !(enable & BIT(2))) { | |
| 94 | if (base == 0 && !(enable & BIT(2))) { | 94 | dev_info(&sb->dev, |
| 95 | dev_info(&sb->dev, | 95 | "Opening wide generic port at 0x295\n"); |
| 96 | "Opening wide generic port at 0x295\n"); | 96 | pci_write_config_word(sb, 0x64, 0x295); |
| 97 | pci_write_config_word(sb, 0x64, 0x295); | 97 | pci_write_config_byte(sb, 0x48, |
| 98 | pci_write_config_byte(sb, 0x48, enable | BIT(2)); | 98 | enable | BIT(2)); |
| 99 | } | ||
| 99 | } | 100 | } |
| 101 | pci_dev_put(sb); | ||
| 100 | } | 102 | } |
| 101 | #endif | 103 | #endif |
| 102 | } | 104 | } |
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index d32aa354cbdf..117d66fcded6 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
| @@ -203,6 +203,8 @@ static const u8 IT87_REG_FAN[] = { 0x0d, 0x0e, 0x0f, 0x80, 0x82 }; | |||
| 203 | static const u8 IT87_REG_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86 }; | 203 | static const u8 IT87_REG_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86 }; |
| 204 | static const u8 IT87_REG_FANX[] = { 0x18, 0x19, 0x1a, 0x81, 0x83 }; | 204 | static const u8 IT87_REG_FANX[] = { 0x18, 0x19, 0x1a, 0x81, 0x83 }; |
| 205 | static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; | 205 | static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; |
| 206 | static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 }; | ||
| 207 | |||
| 206 | #define IT87_REG_FAN_MAIN_CTRL 0x13 | 208 | #define IT87_REG_FAN_MAIN_CTRL 0x13 |
| 207 | #define IT87_REG_FAN_CTL 0x14 | 209 | #define IT87_REG_FAN_CTL 0x14 |
| 208 | #define IT87_REG_PWM(nr) (0x15 + (nr)) | 210 | #define IT87_REG_PWM(nr) (0x15 + (nr)) |
| @@ -226,6 +228,83 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; | |||
| 226 | #define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i)) | 228 | #define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i)) |
| 227 | #define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i)) | 229 | #define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i)) |
| 228 | 230 | ||
| 231 | struct it87_devices { | ||
| 232 | const char *name; | ||
| 233 | u16 features; | ||
| 234 | u8 peci_mask; | ||
| 235 | u8 old_peci_mask; | ||
| 236 | }; | ||
| 237 | |||
| 238 | #define FEAT_12MV_ADC (1 << 0) | ||
| 239 | #define FEAT_NEWER_AUTOPWM (1 << 1) | ||
| 240 | #define FEAT_OLD_AUTOPWM (1 << 2) | ||
| 241 | #define FEAT_16BIT_FANS (1 << 3) | ||
| 242 | #define FEAT_TEMP_OFFSET (1 << 4) | ||
| 243 | #define FEAT_TEMP_PECI (1 << 5) | ||
| 244 | #define FEAT_TEMP_OLD_PECI (1 << 6) | ||
| 245 | |||
| 246 | static const struct it87_devices it87_devices[] = { | ||
| 247 | [it87] = { | ||
| 248 | .name = "it87", | ||
| 249 | .features = FEAT_OLD_AUTOPWM, /* may need to overwrite */ | ||
| 250 | }, | ||
| 251 | [it8712] = { | ||
| 252 | .name = "it8712", | ||
| 253 | .features = FEAT_OLD_AUTOPWM, /* may need to overwrite */ | ||
| 254 | }, | ||
| 255 | [it8716] = { | ||
| 256 | .name = "it8716", | ||
| 257 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET, | ||
| 258 | }, | ||
| 259 | [it8718] = { | ||
| 260 | .name = "it8718", | ||
| 261 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | ||
| 262 | | FEAT_TEMP_OLD_PECI, | ||
| 263 | .old_peci_mask = 0x4, | ||
| 264 | }, | ||
| 265 | [it8720] = { | ||
| 266 | .name = "it8720", | ||
| 267 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | ||
| 268 | | FEAT_TEMP_OLD_PECI, | ||
| 269 | .old_peci_mask = 0x4, | ||
| 270 | }, | ||
| 271 | [it8721] = { | ||
| 272 | .name = "it8721", | ||
| 273 | .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | ||
| 274 | | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI, | ||
| 275 | .peci_mask = 0x05, | ||
| 276 | .old_peci_mask = 0x02, /* Actually reports PCH */ | ||
| 277 | }, | ||
| 278 | [it8728] = { | ||
| 279 | .name = "it8728", | ||
| 280 | .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | ||
| 281 | | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI, | ||
| 282 | .peci_mask = 0x07, | ||
| 283 | }, | ||
| 284 | [it8782] = { | ||
| 285 | .name = "it8782", | ||
| 286 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | ||
| 287 | | FEAT_TEMP_OLD_PECI, | ||
| 288 | .old_peci_mask = 0x4, | ||
| 289 | }, | ||
| 290 | [it8783] = { | ||
| 291 | .name = "it8783", | ||
| 292 | .features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | ||
| 293 | | FEAT_TEMP_OLD_PECI, | ||
| 294 | .old_peci_mask = 0x4, | ||
| 295 | }, | ||
| 296 | }; | ||
| 297 | |||
| 298 | #define has_16bit_fans(data) ((data)->features & FEAT_16BIT_FANS) | ||
| 299 | #define has_12mv_adc(data) ((data)->features & FEAT_12MV_ADC) | ||
| 300 | #define has_newer_autopwm(data) ((data)->features & FEAT_NEWER_AUTOPWM) | ||
| 301 | #define has_old_autopwm(data) ((data)->features & FEAT_OLD_AUTOPWM) | ||
| 302 | #define has_temp_offset(data) ((data)->features & FEAT_TEMP_OFFSET) | ||
| 303 | #define has_temp_peci(data, nr) (((data)->features & FEAT_TEMP_PECI) && \ | ||
| 304 | ((data)->peci_mask & (1 << nr))) | ||
| 305 | #define has_temp_old_peci(data, nr) \ | ||
| 306 | (((data)->features & FEAT_TEMP_OLD_PECI) && \ | ||
| 307 | ((data)->old_peci_mask & (1 << nr))) | ||
| 229 | 308 | ||
| 230 | struct it87_sio_data { | 309 | struct it87_sio_data { |
| 231 | enum chips type; | 310 | enum chips type; |
| @@ -249,7 +328,9 @@ struct it87_sio_data { | |||
| 249 | struct it87_data { | 328 | struct it87_data { |
| 250 | struct device *hwmon_dev; | 329 | struct device *hwmon_dev; |
| 251 | enum chips type; | 330 | enum chips type; |
| 252 | u8 revision; | 331 | u16 features; |
| 332 | u8 peci_mask; | ||
| 333 | u8 old_peci_mask; | ||
| 253 | 334 | ||
| 254 | unsigned short addr; | 335 | unsigned short addr; |
| 255 | const char *name; | 336 | const char *name; |
| @@ -258,17 +339,13 @@ struct it87_data { | |||
| 258 | unsigned long last_updated; /* In jiffies */ | 339 | unsigned long last_updated; /* In jiffies */ |
| 259 | 340 | ||
| 260 | u16 in_scaled; /* Internal voltage sensors are scaled */ | 341 | u16 in_scaled; /* Internal voltage sensors are scaled */ |
| 261 | u8 in[9]; /* Register value */ | 342 | u8 in[9][3]; /* [nr][0]=in, [1]=min, [2]=max */ |
| 262 | u8 in_max[8]; /* Register value */ | ||
| 263 | u8 in_min[8]; /* Register value */ | ||
| 264 | u8 has_fan; /* Bitfield, fans enabled */ | 343 | u8 has_fan; /* Bitfield, fans enabled */ |
| 265 | u16 fan[5]; /* Register values, possibly combined */ | 344 | u16 fan[5][2]; /* Register values, [nr][0]=fan, [1]=min */ |
| 266 | u16 fan_min[5]; /* Register values, possibly combined */ | ||
| 267 | u8 has_temp; /* Bitfield, temp sensors enabled */ | 345 | u8 has_temp; /* Bitfield, temp sensors enabled */ |
| 268 | s8 temp[3]; /* Register value */ | 346 | s8 temp[3][4]; /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */ |
| 269 | s8 temp_high[3]; /* Register value */ | 347 | u8 sensor; /* Register value (IT87_REG_TEMP_ENABLE) */ |
| 270 | s8 temp_low[3]; /* Register value */ | 348 | u8 extra; /* Register value (IT87_REG_TEMP_EXTRA) */ |
| 271 | u8 sensor; /* Register value */ | ||
| 272 | u8 fan_div[3]; /* Register encoding, shifted right */ | 349 | u8 fan_div[3]; /* Register encoding, shifted right */ |
| 273 | u8 vid; /* Register encoding, combined */ | 350 | u8 vid; /* Register encoding, combined */ |
| 274 | u8 vrm; | 351 | u8 vrm; |
| @@ -296,26 +373,6 @@ struct it87_data { | |||
| 296 | s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ | 373 | s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ |
| 297 | }; | 374 | }; |
| 298 | 375 | ||
| 299 | static inline int has_12mv_adc(const struct it87_data *data) | ||
| 300 | { | ||
| 301 | /* | ||
| 302 | * IT8721F and later have a 12 mV ADC, also with internal scaling | ||
| 303 | * on selected inputs. | ||
| 304 | */ | ||
| 305 | return data->type == it8721 | ||
| 306 | || data->type == it8728; | ||
| 307 | } | ||
| 308 | |||
| 309 | static inline int has_newer_autopwm(const struct it87_data *data) | ||
| 310 | { | ||
| 311 | /* | ||
| 312 | * IT8721F and later have separate registers for the temperature | ||
| 313 | * mapping and the manual duty cycle. | ||
| 314 | */ | ||
| 315 | return data->type == it8721 | ||
| 316 | || data->type == it8728; | ||
| 317 | } | ||
| 318 | |||
| 319 | static int adc_lsb(const struct it87_data *data, int nr) | 376 | static int adc_lsb(const struct it87_data *data, int nr) |
| 320 | { | 377 | { |
| 321 | int lsb = has_12mv_adc(data) ? 12 : 16; | 378 | int lsb = has_12mv_adc(data) ? 12 : 16; |
| @@ -398,35 +455,6 @@ static const unsigned int pwm_freq[8] = { | |||
| 398 | 750000 / 128, | 455 | 750000 / 128, |
| 399 | }; | 456 | }; |
| 400 | 457 | ||
| 401 | static inline int has_16bit_fans(const struct it87_data *data) | ||
| 402 | { | ||
| 403 | /* | ||
| 404 | * IT8705F Datasheet 0.4.1, 3h == Version G. | ||
| 405 | * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J. | ||
| 406 | * These are the first revisions with 16-bit tachometer support. | ||
| 407 | */ | ||
| 408 | return (data->type == it87 && data->revision >= 0x03) | ||
| 409 | || (data->type == it8712 && data->revision >= 0x08) | ||
| 410 | || data->type == it8716 | ||
| 411 | || data->type == it8718 | ||
| 412 | || data->type == it8720 | ||
| 413 | || data->type == it8721 | ||
| 414 | || data->type == it8728 | ||
| 415 | || data->type == it8782 | ||
| 416 | || data->type == it8783; | ||
| 417 | } | ||
| 418 | |||
| 419 | static inline int has_old_autopwm(const struct it87_data *data) | ||
| 420 | { | ||
| 421 | /* | ||
| 422 | * The old automatic fan speed control interface is implemented | ||
| 423 | * by IT8705F chips up to revision F and IT8712F chips up to | ||
| 424 | * revision G. | ||
| 425 | */ | ||
| 426 | return (data->type == it87 && data->revision < 0x03) | ||
| 427 | || (data->type == it8712 && data->revision < 0x08); | ||
| 428 | } | ||
| 429 | |||
| 430 | static int it87_probe(struct platform_device *pdev); | 458 | static int it87_probe(struct platform_device *pdev); |
| 431 | static int it87_remove(struct platform_device *pdev); | 459 | static int it87_remove(struct platform_device *pdev); |
| 432 | 460 | ||
| @@ -447,59 +475,22 @@ static struct platform_driver it87_driver = { | |||
| 447 | }; | 475 | }; |
| 448 | 476 | ||
| 449 | static ssize_t show_in(struct device *dev, struct device_attribute *attr, | 477 | static ssize_t show_in(struct device *dev, struct device_attribute *attr, |
| 450 | char *buf) | 478 | char *buf) |
| 451 | { | ||
| 452 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
| 453 | int nr = sensor_attr->index; | ||
| 454 | |||
| 455 | struct it87_data *data = it87_update_device(dev); | ||
| 456 | return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in[nr])); | ||
| 457 | } | ||
| 458 | |||
| 459 | static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, | ||
| 460 | char *buf) | ||
| 461 | { | 479 | { |
| 462 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 480 | struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); |
| 463 | int nr = sensor_attr->index; | 481 | int nr = sattr->nr; |
| 482 | int index = sattr->index; | ||
| 464 | 483 | ||
| 465 | struct it87_data *data = it87_update_device(dev); | 484 | struct it87_data *data = it87_update_device(dev); |
| 466 | return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in_min[nr])); | 485 | return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in[nr][index])); |
| 467 | } | 486 | } |
| 468 | 487 | ||
| 469 | static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, | 488 | static ssize_t set_in(struct device *dev, struct device_attribute *attr, |
| 470 | char *buf) | 489 | const char *buf, size_t count) |
| 471 | { | ||
| 472 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
| 473 | int nr = sensor_attr->index; | ||
| 474 | |||
| 475 | struct it87_data *data = it87_update_device(dev); | ||
| 476 | return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in_max[nr])); | ||
| 477 | } | ||
| 478 | |||
| 479 | static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, | ||
| 480 | const char *buf, size_t count) | ||
| 481 | { | ||
| 482 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
| 483 | int nr = sensor_attr->index; | ||
| 484 | |||
| 485 | struct it87_data *data = dev_get_drvdata(dev); | ||
| 486 | unsigned long val; | ||
| 487 | |||
| 488 | if (kstrtoul(buf, 10, &val) < 0) | ||
| 489 | return -EINVAL; | ||
| 490 | |||
| 491 | mutex_lock(&data->update_lock); | ||
| 492 | data->in_min[nr] = in_to_reg(data, nr, val); | ||
| 493 | it87_write_value(data, IT87_REG_VIN_MIN(nr), | ||
| 494 | data->in_min[nr]); | ||
| 495 | mutex_unlock(&data->update_lock); | ||
| 496 | return count; | ||
| 497 | } | ||
| 498 | static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, | ||
| 499 | const char *buf, size_t count) | ||
| 500 | { | 490 | { |
| 501 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 491 | struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); |
| 502 | int nr = sensor_attr->index; | 492 | int nr = sattr->nr; |
| 493 | int index = sattr->index; | ||
| 503 | 494 | ||
| 504 | struct it87_data *data = dev_get_drvdata(dev); | 495 | struct it87_data *data = dev_get_drvdata(dev); |
| 505 | unsigned long val; | 496 | unsigned long val; |
| @@ -508,140 +499,167 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, | |||
| 508 | return -EINVAL; | 499 | return -EINVAL; |
| 509 | 500 | ||
| 510 | mutex_lock(&data->update_lock); | 501 | mutex_lock(&data->update_lock); |
| 511 | data->in_max[nr] = in_to_reg(data, nr, val); | 502 | data->in[nr][index] = in_to_reg(data, nr, val); |
| 512 | it87_write_value(data, IT87_REG_VIN_MAX(nr), | 503 | it87_write_value(data, |
| 513 | data->in_max[nr]); | 504 | index == 1 ? IT87_REG_VIN_MIN(nr) |
| 505 | : IT87_REG_VIN_MAX(nr), | ||
| 506 | data->in[nr][index]); | ||
| 514 | mutex_unlock(&data->update_lock); | 507 | mutex_unlock(&data->update_lock); |
| 515 | return count; | 508 | return count; |
| 516 | } | 509 | } |
| 517 | 510 | ||
| 518 | #define show_in_offset(offset) \ | 511 | static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0); |
| 519 | static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ | 512 | static SENSOR_DEVICE_ATTR_2(in0_min, S_IRUGO | S_IWUSR, show_in, set_in, |
| 520 | show_in, NULL, offset); | 513 | 0, 1); |
| 521 | 514 | static SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_in, set_in, | |
| 522 | #define limit_in_offset(offset) \ | 515 | 0, 2); |
| 523 | static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ | 516 | |
| 524 | show_in_min, set_in_min, offset); \ | 517 | static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 1, 0); |
| 525 | static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ | 518 | static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_in, set_in, |
| 526 | show_in_max, set_in_max, offset); | 519 | 1, 1); |
| 527 | 520 | static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_in, set_in, | |
| 528 | show_in_offset(0); | 521 | 1, 2); |
| 529 | limit_in_offset(0); | 522 | |
| 530 | show_in_offset(1); | 523 | static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 2, 0); |
| 531 | limit_in_offset(1); | 524 | static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_in, set_in, |
| 532 | show_in_offset(2); | 525 | 2, 1); |
| 533 | limit_in_offset(2); | 526 | static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_in, set_in, |
| 534 | show_in_offset(3); | 527 | 2, 2); |
| 535 | limit_in_offset(3); | 528 | |
| 536 | show_in_offset(4); | 529 | static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 3, 0); |
| 537 | limit_in_offset(4); | 530 | static SENSOR_DEVICE_ATTR_2(in3_min, S_IRUGO | S_IWUSR, show_in, set_in, |
| 538 | show_in_offset(5); | 531 | 3, 1); |
| 539 | limit_in_offset(5); | 532 | static SENSOR_DEVICE_ATTR_2(in3_max, S_IRUGO | S_IWUSR, show_in, set_in, |
| 540 | show_in_offset(6); | 533 | 3, 2); |
| 541 | limit_in_offset(6); | 534 | |
| 542 | show_in_offset(7); | 535 | static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 4, 0); |
| 543 | limit_in_offset(7); | 536 | static SENSOR_DEVICE_ATTR_2(in4_min, S_IRUGO | S_IWUSR, show_in, set_in, |
| 544 | show_in_offset(8); | 537 | 4, 1); |
| 538 | static SENSOR_DEVICE_ATTR_2(in4_max, S_IRUGO | S_IWUSR, show_in, set_in, | ||
| 539 | 4, 2); | ||
| 540 | |||
| 541 | static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 5, 0); | ||
| 542 | static SENSOR_DEVICE_ATTR_2(in5_min, S_IRUGO | S_IWUSR, show_in, set_in, | ||
| 543 | 5, 1); | ||
| 544 | static SENSOR_DEVICE_ATTR_2(in5_max, S_IRUGO | S_IWUSR, show_in, set_in, | ||
| 545 | 5, 2); | ||
| 546 | |||
| 547 | static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 6, 0); | ||
| 548 | static SENSOR_DEVICE_ATTR_2(in6_min, S_IRUGO | S_IWUSR, show_in, set_in, | ||
| 549 | 6, 1); | ||
| 550 | static SENSOR_DEVICE_ATTR_2(in6_max, S_IRUGO | S_IWUSR, show_in, set_in, | ||
| 551 | 6, 2); | ||
| 552 | |||
| 553 | static SENSOR_DEVICE_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 7, 0); | ||
| 554 | static SENSOR_DEVICE_ATTR_2(in7_min, S_IRUGO | S_IWUSR, show_in, set_in, | ||
| 555 | 7, 1); | ||
| 556 | static SENSOR_DEVICE_ATTR_2(in7_max, S_IRUGO | S_IWUSR, show_in, set_in, | ||
| 557 | 7, 2); | ||
| 558 | |||
| 559 | static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 8, 0); | ||
| 545 | 560 | ||
| 546 | /* 3 temperatures */ | 561 | /* 3 temperatures */ |
| 547 | static ssize_t show_temp(struct device *dev, struct device_attribute *attr, | 562 | static ssize_t show_temp(struct device *dev, struct device_attribute *attr, |
| 548 | char *buf) | 563 | char *buf) |
| 549 | { | 564 | { |
| 550 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 565 | struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); |
| 551 | int nr = sensor_attr->index; | 566 | int nr = sattr->nr; |
| 552 | 567 | int index = sattr->index; | |
| 553 | struct it87_data *data = it87_update_device(dev); | 568 | struct it87_data *data = it87_update_device(dev); |
| 554 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); | ||
| 555 | } | ||
| 556 | static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, | ||
| 557 | char *buf) | ||
| 558 | { | ||
| 559 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
| 560 | int nr = sensor_attr->index; | ||
| 561 | 569 | ||
| 562 | struct it87_data *data = it87_update_device(dev); | 570 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr][index])); |
| 563 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])); | ||
| 564 | } | 571 | } |
| 565 | static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, | ||
| 566 | char *buf) | ||
| 567 | { | ||
| 568 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
| 569 | int nr = sensor_attr->index; | ||
| 570 | 572 | ||
| 571 | struct it87_data *data = it87_update_device(dev); | 573 | static ssize_t set_temp(struct device *dev, struct device_attribute *attr, |
| 572 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])); | 574 | const char *buf, size_t count) |
| 573 | } | ||
| 574 | static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, | ||
| 575 | const char *buf, size_t count) | ||
| 576 | { | 575 | { |
| 577 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 576 | struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); |
| 578 | int nr = sensor_attr->index; | 577 | int nr = sattr->nr; |
| 579 | 578 | int index = sattr->index; | |
| 580 | struct it87_data *data = dev_get_drvdata(dev); | 579 | struct it87_data *data = dev_get_drvdata(dev); |
| 581 | long val; | 580 | long val; |
| 581 | u8 reg, regval; | ||
| 582 | 582 | ||
| 583 | if (kstrtol(buf, 10, &val) < 0) | 583 | if (kstrtol(buf, 10, &val) < 0) |
| 584 | return -EINVAL; | 584 | return -EINVAL; |
| 585 | 585 | ||
| 586 | mutex_lock(&data->update_lock); | 586 | mutex_lock(&data->update_lock); |
| 587 | data->temp_high[nr] = TEMP_TO_REG(val); | ||
| 588 | it87_write_value(data, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]); | ||
| 589 | mutex_unlock(&data->update_lock); | ||
| 590 | return count; | ||
| 591 | } | ||
| 592 | static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, | ||
| 593 | const char *buf, size_t count) | ||
| 594 | { | ||
| 595 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
| 596 | int nr = sensor_attr->index; | ||
| 597 | 587 | ||
| 598 | struct it87_data *data = dev_get_drvdata(dev); | 588 | switch (index) { |
| 599 | long val; | 589 | default: |
| 600 | 590 | case 1: | |
| 601 | if (kstrtol(buf, 10, &val) < 0) | 591 | reg = IT87_REG_TEMP_LOW(nr); |
| 602 | return -EINVAL; | 592 | break; |
| 593 | case 2: | ||
| 594 | reg = IT87_REG_TEMP_HIGH(nr); | ||
| 595 | break; | ||
| 596 | case 3: | ||
| 597 | regval = it87_read_value(data, IT87_REG_BEEP_ENABLE); | ||
| 598 | if (!(regval & 0x80)) { | ||
| 599 | regval |= 0x80; | ||
| 600 | it87_write_value(data, IT87_REG_BEEP_ENABLE, regval); | ||
| 601 | } | ||
| 602 | data->valid = 0; | ||
| 603 | reg = IT87_REG_TEMP_OFFSET[nr]; | ||
| 604 | break; | ||
| 605 | } | ||
| 603 | 606 | ||
| 604 | mutex_lock(&data->update_lock); | 607 | data->temp[nr][index] = TEMP_TO_REG(val); |
| 605 | data->temp_low[nr] = TEMP_TO_REG(val); | 608 | it87_write_value(data, reg, data->temp[nr][index]); |
| 606 | it87_write_value(data, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]); | ||
| 607 | mutex_unlock(&data->update_lock); | 609 | mutex_unlock(&data->update_lock); |
| 608 | return count; | 610 | return count; |
| 609 | } | 611 | } |
| 610 | #define show_temp_offset(offset) \ | 612 | |
| 611 | static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ | 613 | static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0); |
| 612 | show_temp, NULL, offset - 1); \ | 614 | static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp, |
| 613 | static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ | 615 | 0, 1); |
| 614 | show_temp_max, set_temp_max, offset - 1); \ | 616 | static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, |
| 615 | static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ | 617 | 0, 2); |
| 616 | show_temp_min, set_temp_min, offset - 1); | 618 | static SENSOR_DEVICE_ATTR_2(temp1_offset, S_IRUGO | S_IWUSR, show_temp, |
| 617 | 619 | set_temp, 0, 3); | |
| 618 | show_temp_offset(1); | 620 | static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0); |
| 619 | show_temp_offset(2); | 621 | static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp, |
| 620 | show_temp_offset(3); | 622 | 1, 1); |
| 621 | 623 | static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | |
| 622 | static ssize_t show_sensor(struct device *dev, struct device_attribute *attr, | 624 | 1, 2); |
| 623 | char *buf) | 625 | static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IRUGO | S_IWUSR, show_temp, |
| 626 | set_temp, 1, 3); | ||
| 627 | static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0); | ||
| 628 | static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
| 629 | 2, 1); | ||
| 630 | static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | ||
| 631 | 2, 2); | ||
| 632 | static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp, | ||
| 633 | set_temp, 2, 3); | ||
| 634 | |||
| 635 | static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr, | ||
| 636 | char *buf) | ||
| 624 | { | 637 | { |
| 625 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 638 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
| 626 | int nr = sensor_attr->index; | 639 | int nr = sensor_attr->index; |
| 627 | struct it87_data *data = it87_update_device(dev); | 640 | struct it87_data *data = it87_update_device(dev); |
| 628 | u8 reg = data->sensor; /* In case value is updated while used */ | 641 | u8 reg = data->sensor; /* In case value is updated while used */ |
| 642 | u8 extra = data->extra; | ||
| 629 | 643 | ||
| 644 | if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1)) | ||
| 645 | || (has_temp_old_peci(data, nr) && (extra & 0x80))) | ||
| 646 | return sprintf(buf, "6\n"); /* Intel PECI */ | ||
| 630 | if (reg & (1 << nr)) | 647 | if (reg & (1 << nr)) |
| 631 | return sprintf(buf, "3\n"); /* thermal diode */ | 648 | return sprintf(buf, "3\n"); /* thermal diode */ |
| 632 | if (reg & (8 << nr)) | 649 | if (reg & (8 << nr)) |
| 633 | return sprintf(buf, "4\n"); /* thermistor */ | 650 | return sprintf(buf, "4\n"); /* thermistor */ |
| 634 | return sprintf(buf, "0\n"); /* disabled */ | 651 | return sprintf(buf, "0\n"); /* disabled */ |
| 635 | } | 652 | } |
| 636 | static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, | 653 | |
| 637 | const char *buf, size_t count) | 654 | static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr, |
| 655 | const char *buf, size_t count) | ||
| 638 | { | 656 | { |
| 639 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 657 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
| 640 | int nr = sensor_attr->index; | 658 | int nr = sensor_attr->index; |
| 641 | 659 | ||
| 642 | struct it87_data *data = dev_get_drvdata(dev); | 660 | struct it87_data *data = dev_get_drvdata(dev); |
| 643 | long val; | 661 | long val; |
| 644 | u8 reg; | 662 | u8 reg, extra; |
| 645 | 663 | ||
| 646 | if (kstrtol(buf, 10, &val) < 0) | 664 | if (kstrtol(buf, 10, &val) < 0) |
| 647 | return -EINVAL; | 665 | return -EINVAL; |
| @@ -649,33 +667,45 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, | |||
| 649 | reg = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 667 | reg = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
| 650 | reg &= ~(1 << nr); | 668 | reg &= ~(1 << nr); |
| 651 | reg &= ~(8 << nr); | 669 | reg &= ~(8 << nr); |
| 670 | if (has_temp_peci(data, nr) && (reg >> 6 == nr + 1 || val == 6)) | ||
| 671 | reg &= 0x3f; | ||
| 672 | extra = it87_read_value(data, IT87_REG_TEMP_EXTRA); | ||
| 673 | if (has_temp_old_peci(data, nr) && ((extra & 0x80) || val == 6)) | ||
| 674 | extra &= 0x7f; | ||
| 652 | if (val == 2) { /* backwards compatibility */ | 675 | if (val == 2) { /* backwards compatibility */ |
| 653 | dev_warn(dev, "Sensor type 2 is deprecated, please use 4 " | 676 | dev_warn(dev, |
| 654 | "instead\n"); | 677 | "Sensor type 2 is deprecated, please use 4 instead\n"); |
| 655 | val = 4; | 678 | val = 4; |
| 656 | } | 679 | } |
| 657 | /* 3 = thermal diode; 4 = thermistor; 0 = disabled */ | 680 | /* 3 = thermal diode; 4 = thermistor; 6 = Intel PECI; 0 = disabled */ |
| 658 | if (val == 3) | 681 | if (val == 3) |
| 659 | reg |= 1 << nr; | 682 | reg |= 1 << nr; |
| 660 | else if (val == 4) | 683 | else if (val == 4) |
| 661 | reg |= 8 << nr; | 684 | reg |= 8 << nr; |
| 685 | else if (has_temp_peci(data, nr) && val == 6) | ||
| 686 | reg |= (nr + 1) << 6; | ||
| 687 | else if (has_temp_old_peci(data, nr) && val == 6) | ||
| 688 | extra |= 0x80; | ||
| 662 | else if (val != 0) | 689 | else if (val != 0) |
| 663 | return -EINVAL; | 690 | return -EINVAL; |
| 664 | 691 | ||
| 665 | mutex_lock(&data->update_lock); | 692 | mutex_lock(&data->update_lock); |
| 666 | data->sensor = reg; | 693 | data->sensor = reg; |
| 694 | data->extra = extra; | ||
| 667 | it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); | 695 | it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); |
| 696 | if (has_temp_old_peci(data, nr)) | ||
| 697 | it87_write_value(data, IT87_REG_TEMP_EXTRA, data->extra); | ||
| 668 | data->valid = 0; /* Force cache refresh */ | 698 | data->valid = 0; /* Force cache refresh */ |
| 669 | mutex_unlock(&data->update_lock); | 699 | mutex_unlock(&data->update_lock); |
| 670 | return count; | 700 | return count; |
| 671 | } | 701 | } |
| 672 | #define show_sensor_offset(offset) \ | ||
| 673 | static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \ | ||
| 674 | show_sensor, set_sensor, offset - 1); | ||
| 675 | 702 | ||
| 676 | show_sensor_offset(1); | 703 | static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR, show_temp_type, |
| 677 | show_sensor_offset(2); | 704 | set_temp_type, 0); |
| 678 | show_sensor_offset(3); | 705 | static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR, show_temp_type, |
| 706 | set_temp_type, 1); | ||
| 707 | static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type, | ||
| 708 | set_temp_type, 2); | ||
| 679 | 709 | ||
| 680 | /* 3 Fans */ | 710 | /* 3 Fans */ |
| 681 | 711 | ||
| @@ -692,25 +722,21 @@ static int pwm_mode(const struct it87_data *data, int nr) | |||
| 692 | } | 722 | } |
| 693 | 723 | ||
| 694 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, | 724 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, |
| 695 | char *buf) | 725 | char *buf) |
| 696 | { | 726 | { |
| 697 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 727 | struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); |
| 698 | int nr = sensor_attr->index; | 728 | int nr = sattr->nr; |
| 699 | 729 | int index = sattr->index; | |
| 730 | int speed; | ||
| 700 | struct it87_data *data = it87_update_device(dev); | 731 | struct it87_data *data = it87_update_device(dev); |
| 701 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], | ||
| 702 | DIV_FROM_REG(data->fan_div[nr]))); | ||
| 703 | } | ||
| 704 | static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, | ||
| 705 | char *buf) | ||
| 706 | { | ||
| 707 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
| 708 | int nr = sensor_attr->index; | ||
| 709 | 732 | ||
| 710 | struct it87_data *data = it87_update_device(dev); | 733 | speed = has_16bit_fans(data) ? |
| 711 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], | 734 | FAN16_FROM_REG(data->fan[nr][index]) : |
| 712 | DIV_FROM_REG(data->fan_div[nr]))); | 735 | FAN_FROM_REG(data->fan[nr][index], |
| 736 | DIV_FROM_REG(data->fan_div[nr])); | ||
| 737 | return sprintf(buf, "%d\n", speed); | ||
| 713 | } | 738 | } |
| 739 | |||
| 714 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, | 740 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, |
| 715 | char *buf) | 741 | char *buf) |
| 716 | { | 742 | { |
| @@ -747,11 +773,13 @@ static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, | |||
| 747 | 773 | ||
| 748 | return sprintf(buf, "%u\n", pwm_freq[index]); | 774 | return sprintf(buf, "%u\n", pwm_freq[index]); |
| 749 | } | 775 | } |
| 750 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | 776 | |
| 751 | const char *buf, size_t count) | 777 | static ssize_t set_fan(struct device *dev, struct device_attribute *attr, |
| 778 | const char *buf, size_t count) | ||
| 752 | { | 779 | { |
| 753 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 780 | struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); |
| 754 | int nr = sensor_attr->index; | 781 | int nr = sattr->nr; |
| 782 | int index = sattr->index; | ||
| 755 | 783 | ||
| 756 | struct it87_data *data = dev_get_drvdata(dev); | 784 | struct it87_data *data = dev_get_drvdata(dev); |
| 757 | long val; | 785 | long val; |
| @@ -761,24 +789,36 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | |||
| 761 | return -EINVAL; | 789 | return -EINVAL; |
| 762 | 790 | ||
| 763 | mutex_lock(&data->update_lock); | 791 | mutex_lock(&data->update_lock); |
| 764 | reg = it87_read_value(data, IT87_REG_FAN_DIV); | 792 | |
| 765 | switch (nr) { | 793 | if (has_16bit_fans(data)) { |
| 766 | case 0: | 794 | data->fan[nr][index] = FAN16_TO_REG(val); |
| 767 | data->fan_div[nr] = reg & 0x07; | 795 | it87_write_value(data, IT87_REG_FAN_MIN[nr], |
| 768 | break; | 796 | data->fan[nr][index] & 0xff); |
| 769 | case 1: | 797 | it87_write_value(data, IT87_REG_FANX_MIN[nr], |
| 770 | data->fan_div[nr] = (reg >> 3) & 0x07; | 798 | data->fan[nr][index] >> 8); |
| 771 | break; | 799 | } else { |
| 772 | case 2: | 800 | reg = it87_read_value(data, IT87_REG_FAN_DIV); |
| 773 | data->fan_div[nr] = (reg & 0x40) ? 3 : 1; | 801 | switch (nr) { |
| 774 | break; | 802 | case 0: |
| 803 | data->fan_div[nr] = reg & 0x07; | ||
| 804 | break; | ||
| 805 | case 1: | ||
| 806 | data->fan_div[nr] = (reg >> 3) & 0x07; | ||
| 807 | break; | ||
| 808 | case 2: | ||
| 809 | data->fan_div[nr] = (reg & 0x40) ? 3 : 1; | ||
| 810 | break; | ||
| 811 | } | ||
| 812 | data->fan[nr][index] = | ||
| 813 | FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); | ||
| 814 | it87_write_value(data, IT87_REG_FAN_MIN[nr], | ||
| 815 | data->fan[nr][index]); | ||
| 775 | } | 816 | } |
| 776 | 817 | ||
| 777 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); | ||
| 778 | it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]); | ||
| 779 | mutex_unlock(&data->update_lock); | 818 | mutex_unlock(&data->update_lock); |
| 780 | return count; | 819 | return count; |
| 781 | } | 820 | } |
| 821 | |||
| 782 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | 822 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, |
| 783 | const char *buf, size_t count) | 823 | const char *buf, size_t count) |
| 784 | { | 824 | { |
| @@ -797,7 +837,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | |||
| 797 | old = it87_read_value(data, IT87_REG_FAN_DIV); | 837 | old = it87_read_value(data, IT87_REG_FAN_DIV); |
| 798 | 838 | ||
| 799 | /* Save fan min limit */ | 839 | /* Save fan min limit */ |
| 800 | min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); | 840 | min = FAN_FROM_REG(data->fan[nr][1], DIV_FROM_REG(data->fan_div[nr])); |
| 801 | 841 | ||
| 802 | switch (nr) { | 842 | switch (nr) { |
| 803 | case 0: | 843 | case 0: |
| @@ -818,8 +858,8 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | |||
| 818 | it87_write_value(data, IT87_REG_FAN_DIV, val); | 858 | it87_write_value(data, IT87_REG_FAN_DIV, val); |
| 819 | 859 | ||
| 820 | /* Restore fan min limit */ | 860 | /* Restore fan min limit */ |
| 821 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); | 861 | data->fan[nr][1] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); |
| 822 | it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]); | 862 | it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan[nr][1]); |
| 823 | 863 | ||
| 824 | mutex_unlock(&data->update_lock); | 864 | mutex_unlock(&data->update_lock); |
| 825 | return count; | 865 | return count; |
| @@ -843,8 +883,8 @@ static int check_trip_points(struct device *dev, int nr) | |||
| 843 | } | 883 | } |
| 844 | 884 | ||
| 845 | if (err) { | 885 | if (err) { |
| 846 | dev_err(dev, "Inconsistent trip points, not switching to " | 886 | dev_err(dev, |
| 847 | "automatic mode\n"); | 887 | "Inconsistent trip points, not switching to automatic mode\n"); |
| 848 | dev_err(dev, "Adjust the trip points and try again\n"); | 888 | dev_err(dev, "Adjust the trip points and try again\n"); |
| 849 | } | 889 | } |
| 850 | return err; | 890 | return err; |
| @@ -1092,118 +1132,106 @@ static ssize_t set_auto_temp(struct device *dev, | |||
| 1092 | return count; | 1132 | return count; |
| 1093 | } | 1133 | } |
| 1094 | 1134 | ||
| 1095 | #define show_fan_offset(offset) \ | 1135 | static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0); |
| 1096 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ | 1136 | static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_fan, set_fan, |
| 1097 | show_fan, NULL, offset - 1); \ | 1137 | 0, 1); |
| 1098 | static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | 1138 | static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, show_fan_div, |
| 1099 | show_fan_min, set_fan_min, offset - 1); \ | 1139 | set_fan_div, 0); |
| 1100 | static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ | 1140 | |
| 1101 | show_fan_div, set_fan_div, offset - 1); | 1141 | static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 1, 0); |
| 1102 | 1142 | static SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_fan, set_fan, | |
| 1103 | show_fan_offset(1); | 1143 | 1, 1); |
| 1104 | show_fan_offset(2); | 1144 | static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, show_fan_div, |
| 1105 | show_fan_offset(3); | 1145 | set_fan_div, 1); |
| 1106 | 1146 | ||
| 1107 | #define show_pwm_offset(offset) \ | 1147 | static SENSOR_DEVICE_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 2, 0); |
| 1108 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ | 1148 | static SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_fan, set_fan, |
| 1109 | show_pwm_enable, set_pwm_enable, offset - 1); \ | 1149 | 2, 1); |
| 1110 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | 1150 | static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO | S_IWUSR, show_fan_div, |
| 1111 | show_pwm, set_pwm, offset - 1); \ | 1151 | set_fan_div, 2); |
| 1112 | static DEVICE_ATTR(pwm##offset##_freq, \ | 1152 | |
| 1113 | (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ | 1153 | static SENSOR_DEVICE_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 3, 0); |
| 1114 | show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); \ | 1154 | static SENSOR_DEVICE_ATTR_2(fan4_min, S_IRUGO | S_IWUSR, show_fan, set_fan, |
| 1115 | static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels_temp, \ | 1155 | 3, 1); |
| 1116 | S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, \ | 1156 | |
| 1117 | offset - 1); \ | 1157 | static SENSOR_DEVICE_ATTR_2(fan5_input, S_IRUGO, show_fan, NULL, 4, 0); |
| 1118 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_pwm, \ | 1158 | static SENSOR_DEVICE_ATTR_2(fan5_min, S_IRUGO | S_IWUSR, show_fan, set_fan, |
| 1119 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | 1159 | 4, 1); |
| 1120 | offset - 1, 0); \ | 1160 | |
| 1121 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_pwm, \ | 1161 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, |
| 1122 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | 1162 | show_pwm_enable, set_pwm_enable, 0); |
| 1123 | offset - 1, 1); \ | 1163 | static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0); |
| 1124 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_pwm, \ | 1164 | static DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq); |
| 1125 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | 1165 | static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO | S_IWUSR, |
| 1126 | offset - 1, 2); \ | 1166 | show_pwm_temp_map, set_pwm_temp_map, 0); |
| 1127 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_pwm, \ | 1167 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR, |
| 1128 | S_IRUGO, show_auto_pwm, NULL, offset - 1, 3); \ | 1168 | show_auto_pwm, set_auto_pwm, 0, 0); |
| 1129 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp, \ | 1169 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR, |
| 1130 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | 1170 | show_auto_pwm, set_auto_pwm, 0, 1); |
| 1131 | offset - 1, 1); \ | 1171 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO | S_IWUSR, |
| 1132 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp_hyst, \ | 1172 | show_auto_pwm, set_auto_pwm, 0, 2); |
| 1133 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | 1173 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO, |
| 1134 | offset - 1, 0); \ | 1174 | show_auto_pwm, NULL, 0, 3); |
| 1135 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_temp, \ | 1175 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR, |
| 1136 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | 1176 | show_auto_temp, set_auto_temp, 0, 1); |
| 1137 | offset - 1, 2); \ | 1177 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO | S_IWUSR, |
| 1138 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_temp, \ | 1178 | show_auto_temp, set_auto_temp, 0, 0); |
| 1139 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | 1179 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR, |
| 1140 | offset - 1, 3); \ | 1180 | show_auto_temp, set_auto_temp, 0, 2); |
| 1141 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_temp, \ | 1181 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR, |
| 1142 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | 1182 | show_auto_temp, set_auto_temp, 0, 3); |
| 1143 | offset - 1, 4); | 1183 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_temp, S_IRUGO | S_IWUSR, |
| 1144 | 1184 | show_auto_temp, set_auto_temp, 0, 4); | |
| 1145 | show_pwm_offset(1); | 1185 | |
| 1146 | show_pwm_offset(2); | 1186 | static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, |
| 1147 | show_pwm_offset(3); | 1187 | show_pwm_enable, set_pwm_enable, 1); |
| 1148 | 1188 | static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1); | |
| 1149 | /* A different set of callbacks for 16-bit fans */ | 1189 | static DEVICE_ATTR(pwm2_freq, S_IRUGO, show_pwm_freq, NULL); |
| 1150 | static ssize_t show_fan16(struct device *dev, struct device_attribute *attr, | 1190 | static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IRUGO | S_IWUSR, |
| 1151 | char *buf) | 1191 | show_pwm_temp_map, set_pwm_temp_map, 1); |
| 1152 | { | 1192 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR, |
| 1153 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 1193 | show_auto_pwm, set_auto_pwm, 1, 0); |
| 1154 | int nr = sensor_attr->index; | 1194 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR, |
| 1155 | struct it87_data *data = it87_update_device(dev); | 1195 | show_auto_pwm, set_auto_pwm, 1, 1); |
| 1156 | return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan[nr])); | 1196 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO | S_IWUSR, |
| 1157 | } | 1197 | show_auto_pwm, set_auto_pwm, 1, 2); |
| 1158 | 1198 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO, | |
| 1159 | static ssize_t show_fan16_min(struct device *dev, struct device_attribute *attr, | 1199 | show_auto_pwm, NULL, 1, 3); |
| 1160 | char *buf) | 1200 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp, S_IRUGO | S_IWUSR, |
| 1161 | { | 1201 | show_auto_temp, set_auto_temp, 1, 1); |
| 1162 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 1202 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO | S_IWUSR, |
| 1163 | int nr = sensor_attr->index; | 1203 | show_auto_temp, set_auto_temp, 1, 0); |
| 1164 | struct it87_data *data = it87_update_device(dev); | 1204 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_temp, S_IRUGO | S_IWUSR, |
| 1165 | return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan_min[nr])); | 1205 | show_auto_temp, set_auto_temp, 1, 2); |
| 1166 | } | 1206 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR, |
| 1167 | 1207 | show_auto_temp, set_auto_temp, 1, 3); | |
| 1168 | static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr, | 1208 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point4_temp, S_IRUGO | S_IWUSR, |
| 1169 | const char *buf, size_t count) | 1209 | show_auto_temp, set_auto_temp, 1, 4); |
| 1170 | { | 1210 | |
| 1171 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 1211 | static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, |
| 1172 | int nr = sensor_attr->index; | 1212 | show_pwm_enable, set_pwm_enable, 2); |
| 1173 | struct it87_data *data = dev_get_drvdata(dev); | 1213 | static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 2); |
| 1174 | long val; | 1214 | static DEVICE_ATTR(pwm3_freq, S_IRUGO, show_pwm_freq, NULL); |
| 1175 | 1215 | static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IRUGO | S_IWUSR, | |
| 1176 | if (kstrtol(buf, 10, &val) < 0) | 1216 | show_pwm_temp_map, set_pwm_temp_map, 2); |
| 1177 | return -EINVAL; | 1217 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR, |
| 1178 | 1218 | show_auto_pwm, set_auto_pwm, 2, 0); | |
| 1179 | mutex_lock(&data->update_lock); | 1219 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR, |
| 1180 | data->fan_min[nr] = FAN16_TO_REG(val); | 1220 | show_auto_pwm, set_auto_pwm, 2, 1); |
| 1181 | it87_write_value(data, IT87_REG_FAN_MIN[nr], | 1221 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO | S_IWUSR, |
| 1182 | data->fan_min[nr] & 0xff); | 1222 | show_auto_pwm, set_auto_pwm, 2, 2); |
| 1183 | it87_write_value(data, IT87_REG_FANX_MIN[nr], | 1223 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO, |
| 1184 | data->fan_min[nr] >> 8); | 1224 | show_auto_pwm, NULL, 2, 3); |
| 1185 | mutex_unlock(&data->update_lock); | 1225 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp, S_IRUGO | S_IWUSR, |
| 1186 | return count; | 1226 | show_auto_temp, set_auto_temp, 2, 1); |
| 1187 | } | 1227 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO | S_IWUSR, |
| 1188 | 1228 | show_auto_temp, set_auto_temp, 2, 0); | |
| 1189 | /* | 1229 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_temp, S_IRUGO | S_IWUSR, |
| 1190 | * We want to use the same sysfs file names as 8-bit fans, but we need | 1230 | show_auto_temp, set_auto_temp, 2, 2); |
| 1191 | * different variable names, so we have to use SENSOR_ATTR instead of | 1231 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR, |
| 1192 | * SENSOR_DEVICE_ATTR. | 1232 | show_auto_temp, set_auto_temp, 2, 3); |
| 1193 | */ | 1233 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_temp, S_IRUGO | S_IWUSR, |
| 1194 | #define show_fan16_offset(offset) \ | 1234 | show_auto_temp, set_auto_temp, 2, 4); |
| 1195 | static struct sensor_device_attribute sensor_dev_attr_fan##offset##_input16 \ | ||
| 1196 | = SENSOR_ATTR(fan##offset##_input, S_IRUGO, \ | ||
| 1197 | show_fan16, NULL, offset - 1); \ | ||
| 1198 | static struct sensor_device_attribute sensor_dev_attr_fan##offset##_min16 \ | ||
| 1199 | = SENSOR_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | ||
| 1200 | show_fan16_min, set_fan16_min, offset - 1) | ||
| 1201 | |||
| 1202 | show_fan16_offset(1); | ||
| 1203 | show_fan16_offset(2); | ||
| 1204 | show_fan16_offset(3); | ||
| 1205 | show_fan16_offset(4); | ||
| 1206 | show_fan16_offset(5); | ||
| 1207 | 1235 | ||
| 1208 | /* Alarms */ | 1236 | /* Alarms */ |
| 1209 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, | 1237 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, |
| @@ -1471,6 +1499,12 @@ static const struct attribute_group it87_group_temp[3] = { | |||
| 1471 | { .attrs = it87_attributes_temp[2] }, | 1499 | { .attrs = it87_attributes_temp[2] }, |
| 1472 | }; | 1500 | }; |
| 1473 | 1501 | ||
| 1502 | static struct attribute *it87_attributes_temp_offset[] = { | ||
| 1503 | &sensor_dev_attr_temp1_offset.dev_attr.attr, | ||
| 1504 | &sensor_dev_attr_temp2_offset.dev_attr.attr, | ||
| 1505 | &sensor_dev_attr_temp3_offset.dev_attr.attr, | ||
| 1506 | }; | ||
| 1507 | |||
| 1474 | static struct attribute *it87_attributes[] = { | 1508 | static struct attribute *it87_attributes[] = { |
| 1475 | &dev_attr_alarms.attr, | 1509 | &dev_attr_alarms.attr, |
| 1476 | &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, | 1510 | &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, |
| @@ -1500,73 +1534,47 @@ static struct attribute *it87_attributes_temp_beep[] = { | |||
| 1500 | &sensor_dev_attr_temp3_beep.dev_attr.attr, | 1534 | &sensor_dev_attr_temp3_beep.dev_attr.attr, |
| 1501 | }; | 1535 | }; |
| 1502 | 1536 | ||
| 1503 | static struct attribute *it87_attributes_fan16[5][3+1] = { { | 1537 | static struct attribute *it87_attributes_fan[5][3+1] = { { |
| 1504 | &sensor_dev_attr_fan1_input16.dev_attr.attr, | 1538 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
| 1505 | &sensor_dev_attr_fan1_min16.dev_attr.attr, | 1539 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
| 1506 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | 1540 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, |
| 1507 | NULL | 1541 | NULL |
| 1508 | }, { | 1542 | }, { |
| 1509 | &sensor_dev_attr_fan2_input16.dev_attr.attr, | 1543 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
| 1510 | &sensor_dev_attr_fan2_min16.dev_attr.attr, | 1544 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
| 1511 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | 1545 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, |
| 1512 | NULL | 1546 | NULL |
| 1513 | }, { | 1547 | }, { |
| 1514 | &sensor_dev_attr_fan3_input16.dev_attr.attr, | 1548 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
| 1515 | &sensor_dev_attr_fan3_min16.dev_attr.attr, | 1549 | &sensor_dev_attr_fan3_min.dev_attr.attr, |
| 1516 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | 1550 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, |
| 1517 | NULL | 1551 | NULL |
| 1518 | }, { | 1552 | }, { |
| 1519 | &sensor_dev_attr_fan4_input16.dev_attr.attr, | 1553 | &sensor_dev_attr_fan4_input.dev_attr.attr, |
| 1520 | &sensor_dev_attr_fan4_min16.dev_attr.attr, | 1554 | &sensor_dev_attr_fan4_min.dev_attr.attr, |
| 1521 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, | 1555 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, |
| 1522 | NULL | 1556 | NULL |
| 1523 | }, { | 1557 | }, { |
| 1524 | &sensor_dev_attr_fan5_input16.dev_attr.attr, | 1558 | &sensor_dev_attr_fan5_input.dev_attr.attr, |
| 1525 | &sensor_dev_attr_fan5_min16.dev_attr.attr, | 1559 | &sensor_dev_attr_fan5_min.dev_attr.attr, |
| 1526 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, | 1560 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, |
| 1527 | NULL | 1561 | NULL |
| 1528 | } }; | 1562 | } }; |
| 1529 | 1563 | ||
| 1530 | static const struct attribute_group it87_group_fan16[5] = { | 1564 | static const struct attribute_group it87_group_fan[5] = { |
| 1531 | { .attrs = it87_attributes_fan16[0] }, | 1565 | { .attrs = it87_attributes_fan[0] }, |
| 1532 | { .attrs = it87_attributes_fan16[1] }, | 1566 | { .attrs = it87_attributes_fan[1] }, |
| 1533 | { .attrs = it87_attributes_fan16[2] }, | 1567 | { .attrs = it87_attributes_fan[2] }, |
| 1534 | { .attrs = it87_attributes_fan16[3] }, | 1568 | { .attrs = it87_attributes_fan[3] }, |
| 1535 | { .attrs = it87_attributes_fan16[4] }, | 1569 | { .attrs = it87_attributes_fan[4] }, |
| 1536 | }; | 1570 | }; |
| 1537 | 1571 | ||
| 1538 | static struct attribute *it87_attributes_fan[3][4+1] = { { | 1572 | static const struct attribute *it87_attributes_fan_div[] = { |
| 1539 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
| 1540 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
| 1541 | &sensor_dev_attr_fan1_div.dev_attr.attr, | 1573 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
| 1542 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
| 1543 | NULL | ||
| 1544 | }, { | ||
| 1545 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
| 1546 | &sensor_dev_attr_fan2_min.dev_attr.attr, | ||
| 1547 | &sensor_dev_attr_fan2_div.dev_attr.attr, | 1574 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
| 1548 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
| 1549 | NULL | ||
| 1550 | }, { | ||
| 1551 | &sensor_dev_attr_fan3_input.dev_attr.attr, | ||
| 1552 | &sensor_dev_attr_fan3_min.dev_attr.attr, | ||
| 1553 | &sensor_dev_attr_fan3_div.dev_attr.attr, | 1575 | &sensor_dev_attr_fan3_div.dev_attr.attr, |
| 1554 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | ||
| 1555 | NULL | ||
| 1556 | } }; | ||
| 1557 | |||
| 1558 | static const struct attribute_group it87_group_fan[3] = { | ||
| 1559 | { .attrs = it87_attributes_fan[0] }, | ||
| 1560 | { .attrs = it87_attributes_fan[1] }, | ||
| 1561 | { .attrs = it87_attributes_fan[2] }, | ||
| 1562 | }; | 1576 | }; |
| 1563 | 1577 | ||
| 1564 | static const struct attribute_group * | ||
| 1565 | it87_get_fan_group(const struct it87_data *data) | ||
| 1566 | { | ||
| 1567 | return has_16bit_fans(data) ? it87_group_fan16 : it87_group_fan; | ||
| 1568 | } | ||
| 1569 | |||
| 1570 | static struct attribute *it87_attributes_pwm[3][4+1] = { { | 1578 | static struct attribute *it87_attributes_pwm[3][4+1] = { { |
| 1571 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | 1579 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, |
| 1572 | &sensor_dev_attr_pwm1.dev_attr.attr, | 1580 | &sensor_dev_attr_pwm1.dev_attr.attr, |
| @@ -1925,7 +1933,6 @@ static void it87_remove_files(struct device *dev) | |||
| 1925 | { | 1933 | { |
| 1926 | struct it87_data *data = platform_get_drvdata(pdev); | 1934 | struct it87_data *data = platform_get_drvdata(pdev); |
| 1927 | struct it87_sio_data *sio_data = dev->platform_data; | 1935 | struct it87_sio_data *sio_data = dev->platform_data; |
| 1928 | const struct attribute_group *fan_group = it87_get_fan_group(data); | ||
| 1929 | int i; | 1936 | int i; |
| 1930 | 1937 | ||
| 1931 | sysfs_remove_group(&dev->kobj, &it87_group); | 1938 | sysfs_remove_group(&dev->kobj, &it87_group); |
| @@ -1941,6 +1948,9 @@ static void it87_remove_files(struct device *dev) | |||
| 1941 | if (!(data->has_temp & (1 << i))) | 1948 | if (!(data->has_temp & (1 << i))) |
| 1942 | continue; | 1949 | continue; |
| 1943 | sysfs_remove_group(&dev->kobj, &it87_group_temp[i]); | 1950 | sysfs_remove_group(&dev->kobj, &it87_group_temp[i]); |
| 1951 | if (has_temp_offset(data)) | ||
| 1952 | sysfs_remove_file(&dev->kobj, | ||
| 1953 | it87_attributes_temp_offset[i]); | ||
| 1944 | if (sio_data->beep_pin) | 1954 | if (sio_data->beep_pin) |
| 1945 | sysfs_remove_file(&dev->kobj, | 1955 | sysfs_remove_file(&dev->kobj, |
| 1946 | it87_attributes_temp_beep[i]); | 1956 | it87_attributes_temp_beep[i]); |
| @@ -1948,10 +1958,13 @@ static void it87_remove_files(struct device *dev) | |||
| 1948 | for (i = 0; i < 5; i++) { | 1958 | for (i = 0; i < 5; i++) { |
| 1949 | if (!(data->has_fan & (1 << i))) | 1959 | if (!(data->has_fan & (1 << i))) |
| 1950 | continue; | 1960 | continue; |
| 1951 | sysfs_remove_group(&dev->kobj, &fan_group[i]); | 1961 | sysfs_remove_group(&dev->kobj, &it87_group_fan[i]); |
| 1952 | if (sio_data->beep_pin) | 1962 | if (sio_data->beep_pin) |
| 1953 | sysfs_remove_file(&dev->kobj, | 1963 | sysfs_remove_file(&dev->kobj, |
| 1954 | it87_attributes_fan_beep[i]); | 1964 | it87_attributes_fan_beep[i]); |
| 1965 | if (i < 3 && !has_16bit_fans(data)) | ||
| 1966 | sysfs_remove_file(&dev->kobj, | ||
| 1967 | it87_attributes_fan_div[i]); | ||
| 1955 | } | 1968 | } |
| 1956 | for (i = 0; i < 3; i++) { | 1969 | for (i = 0; i < 3; i++) { |
| 1957 | if (sio_data->skip_pwm & (1 << 0)) | 1970 | if (sio_data->skip_pwm & (1 << 0)) |
| @@ -1972,21 +1985,9 @@ static int it87_probe(struct platform_device *pdev) | |||
| 1972 | struct resource *res; | 1985 | struct resource *res; |
| 1973 | struct device *dev = &pdev->dev; | 1986 | struct device *dev = &pdev->dev; |
| 1974 | struct it87_sio_data *sio_data = dev->platform_data; | 1987 | struct it87_sio_data *sio_data = dev->platform_data; |
| 1975 | const struct attribute_group *fan_group; | ||
| 1976 | int err = 0, i; | 1988 | int err = 0, i; |
| 1977 | int enable_pwm_interface; | 1989 | int enable_pwm_interface; |
| 1978 | int fan_beep_need_rw; | 1990 | int fan_beep_need_rw; |
| 1979 | static const char * const names[] = { | ||
| 1980 | "it87", | ||
| 1981 | "it8712", | ||
| 1982 | "it8716", | ||
| 1983 | "it8718", | ||
| 1984 | "it8720", | ||
| 1985 | "it8721", | ||
| 1986 | "it8728", | ||
| 1987 | "it8782", | ||
| 1988 | "it8783", | ||
| 1989 | }; | ||
| 1990 | 1991 | ||
| 1991 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1992 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
| 1992 | if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT, | 1993 | if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT, |
| @@ -2003,8 +2004,31 @@ static int it87_probe(struct platform_device *pdev) | |||
| 2003 | 2004 | ||
| 2004 | data->addr = res->start; | 2005 | data->addr = res->start; |
| 2005 | data->type = sio_data->type; | 2006 | data->type = sio_data->type; |
| 2006 | data->revision = sio_data->revision; | 2007 | data->features = it87_devices[sio_data->type].features; |
| 2007 | data->name = names[sio_data->type]; | 2008 | data->peci_mask = it87_devices[sio_data->type].peci_mask; |
| 2009 | data->old_peci_mask = it87_devices[sio_data->type].old_peci_mask; | ||
| 2010 | data->name = it87_devices[sio_data->type].name; | ||
| 2011 | /* | ||
| 2012 | * IT8705F Datasheet 0.4.1, 3h == Version G. | ||
| 2013 | * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J. | ||
| 2014 | * These are the first revisions with 16-bit tachometer support. | ||
| 2015 | */ | ||
| 2016 | switch (data->type) { | ||
| 2017 | case it87: | ||
| 2018 | if (sio_data->revision >= 0x03) { | ||
| 2019 | data->features &= ~FEAT_OLD_AUTOPWM; | ||
| 2020 | data->features |= FEAT_16BIT_FANS; | ||
| 2021 | } | ||
| 2022 | break; | ||
| 2023 | case it8712: | ||
| 2024 | if (sio_data->revision >= 0x08) { | ||
| 2025 | data->features &= ~FEAT_OLD_AUTOPWM; | ||
| 2026 | data->features |= FEAT_16BIT_FANS; | ||
| 2027 | } | ||
| 2028 | break; | ||
| 2029 | default: | ||
| 2030 | break; | ||
| 2031 | } | ||
| 2008 | 2032 | ||
| 2009 | /* Now, we do the remaining detection. */ | 2033 | /* Now, we do the remaining detection. */ |
| 2010 | if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) | 2034 | if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) |
| @@ -2068,6 +2092,12 @@ static int it87_probe(struct platform_device *pdev) | |||
| 2068 | err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]); | 2092 | err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]); |
| 2069 | if (err) | 2093 | if (err) |
| 2070 | goto error; | 2094 | goto error; |
| 2095 | if (has_temp_offset(data)) { | ||
| 2096 | err = sysfs_create_file(&dev->kobj, | ||
| 2097 | it87_attributes_temp_offset[i]); | ||
| 2098 | if (err) | ||
| 2099 | goto error; | ||
| 2100 | } | ||
| 2071 | if (sio_data->beep_pin) { | 2101 | if (sio_data->beep_pin) { |
| 2072 | err = sysfs_create_file(&dev->kobj, | 2102 | err = sysfs_create_file(&dev->kobj, |
| 2073 | it87_attributes_temp_beep[i]); | 2103 | it87_attributes_temp_beep[i]); |
| @@ -2077,15 +2107,21 @@ static int it87_probe(struct platform_device *pdev) | |||
| 2077 | } | 2107 | } |
| 2078 | 2108 | ||
| 2079 | /* Do not create fan files for disabled fans */ | 2109 | /* Do not create fan files for disabled fans */ |
| 2080 | fan_group = it87_get_fan_group(data); | ||
| 2081 | fan_beep_need_rw = 1; | 2110 | fan_beep_need_rw = 1; |
| 2082 | for (i = 0; i < 5; i++) { | 2111 | for (i = 0; i < 5; i++) { |
| 2083 | if (!(data->has_fan & (1 << i))) | 2112 | if (!(data->has_fan & (1 << i))) |
| 2084 | continue; | 2113 | continue; |
| 2085 | err = sysfs_create_group(&dev->kobj, &fan_group[i]); | 2114 | err = sysfs_create_group(&dev->kobj, &it87_group_fan[i]); |
| 2086 | if (err) | 2115 | if (err) |
| 2087 | goto error; | 2116 | goto error; |
| 2088 | 2117 | ||
| 2118 | if (i < 3 && !has_16bit_fans(data)) { | ||
| 2119 | err = sysfs_create_file(&dev->kobj, | ||
| 2120 | it87_attributes_fan_div[i]); | ||
| 2121 | if (err) | ||
| 2122 | goto error; | ||
| 2123 | } | ||
| 2124 | |||
| 2089 | if (sio_data->beep_pin) { | 2125 | if (sio_data->beep_pin) { |
| 2090 | err = sysfs_create_file(&dev->kobj, | 2126 | err = sysfs_create_file(&dev->kobj, |
| 2091 | it87_attributes_fan_beep[i]); | 2127 | it87_attributes_fan_beep[i]); |
| @@ -2221,8 +2257,8 @@ static int it87_check_pwm(struct device *dev) | |||
| 2221 | * PWM interface). | 2257 | * PWM interface). |
| 2222 | */ | 2258 | */ |
| 2223 | if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) { | 2259 | if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) { |
| 2224 | dev_info(dev, "Reconfiguring PWM to " | 2260 | dev_info(dev, |
| 2225 | "active high polarity\n"); | 2261 | "Reconfiguring PWM to active high polarity\n"); |
| 2226 | it87_write_value(data, IT87_REG_FAN_CTL, | 2262 | it87_write_value(data, IT87_REG_FAN_CTL, |
| 2227 | tmp | 0x87); | 2263 | tmp | 0x87); |
| 2228 | for (i = 0; i < 3; i++) | 2264 | for (i = 0; i < 3; i++) |
| @@ -2232,16 +2268,16 @@ static int it87_check_pwm(struct device *dev) | |||
| 2232 | return 1; | 2268 | return 1; |
| 2233 | } | 2269 | } |
| 2234 | 2270 | ||
| 2235 | dev_info(dev, "PWM configuration is " | 2271 | dev_info(dev, |
| 2236 | "too broken to be fixed\n"); | 2272 | "PWM configuration is too broken to be fixed\n"); |
| 2237 | } | 2273 | } |
| 2238 | 2274 | ||
| 2239 | dev_info(dev, "Detected broken BIOS " | 2275 | dev_info(dev, |
| 2240 | "defaults, disabling PWM interface\n"); | 2276 | "Detected broken BIOS defaults, disabling PWM interface\n"); |
| 2241 | return 0; | 2277 | return 0; |
| 2242 | } else if (fix_pwm_polarity) { | 2278 | } else if (fix_pwm_polarity) { |
| 2243 | dev_info(dev, "PWM configuration looks " | 2279 | dev_info(dev, |
| 2244 | "sane, won't touch\n"); | 2280 | "PWM configuration looks sane, won't touch\n"); |
| 2245 | } | 2281 | } |
| 2246 | 2282 | ||
| 2247 | return 1; | 2283 | return 1; |
| @@ -2389,42 +2425,46 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
| 2389 | it87_read_value(data, IT87_REG_CONFIG) | 0x40); | 2425 | it87_read_value(data, IT87_REG_CONFIG) | 0x40); |
| 2390 | } | 2426 | } |
| 2391 | for (i = 0; i <= 7; i++) { | 2427 | for (i = 0; i <= 7; i++) { |
| 2392 | data->in[i] = | 2428 | data->in[i][0] = |
| 2393 | it87_read_value(data, IT87_REG_VIN(i)); | 2429 | it87_read_value(data, IT87_REG_VIN(i)); |
| 2394 | data->in_min[i] = | 2430 | data->in[i][1] = |
| 2395 | it87_read_value(data, IT87_REG_VIN_MIN(i)); | 2431 | it87_read_value(data, IT87_REG_VIN_MIN(i)); |
| 2396 | data->in_max[i] = | 2432 | data->in[i][2] = |
| 2397 | it87_read_value(data, IT87_REG_VIN_MAX(i)); | 2433 | it87_read_value(data, IT87_REG_VIN_MAX(i)); |
| 2398 | } | 2434 | } |
| 2399 | /* in8 (battery) has no limit registers */ | 2435 | /* in8 (battery) has no limit registers */ |
| 2400 | data->in[8] = it87_read_value(data, IT87_REG_VIN(8)); | 2436 | data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8)); |
| 2401 | 2437 | ||
| 2402 | for (i = 0; i < 5; i++) { | 2438 | for (i = 0; i < 5; i++) { |
| 2403 | /* Skip disabled fans */ | 2439 | /* Skip disabled fans */ |
| 2404 | if (!(data->has_fan & (1 << i))) | 2440 | if (!(data->has_fan & (1 << i))) |
| 2405 | continue; | 2441 | continue; |
| 2406 | 2442 | ||
| 2407 | data->fan_min[i] = | 2443 | data->fan[i][1] = |
| 2408 | it87_read_value(data, IT87_REG_FAN_MIN[i]); | 2444 | it87_read_value(data, IT87_REG_FAN_MIN[i]); |
| 2409 | data->fan[i] = it87_read_value(data, | 2445 | data->fan[i][0] = it87_read_value(data, |
| 2410 | IT87_REG_FAN[i]); | 2446 | IT87_REG_FAN[i]); |
| 2411 | /* Add high byte if in 16-bit mode */ | 2447 | /* Add high byte if in 16-bit mode */ |
| 2412 | if (has_16bit_fans(data)) { | 2448 | if (has_16bit_fans(data)) { |
| 2413 | data->fan[i] |= it87_read_value(data, | 2449 | data->fan[i][0] |= it87_read_value(data, |
| 2414 | IT87_REG_FANX[i]) << 8; | 2450 | IT87_REG_FANX[i]) << 8; |
| 2415 | data->fan_min[i] |= it87_read_value(data, | 2451 | data->fan[i][1] |= it87_read_value(data, |
| 2416 | IT87_REG_FANX_MIN[i]) << 8; | 2452 | IT87_REG_FANX_MIN[i]) << 8; |
| 2417 | } | 2453 | } |
| 2418 | } | 2454 | } |
| 2419 | for (i = 0; i < 3; i++) { | 2455 | for (i = 0; i < 3; i++) { |
| 2420 | if (!(data->has_temp & (1 << i))) | 2456 | if (!(data->has_temp & (1 << i))) |
| 2421 | continue; | 2457 | continue; |
| 2422 | data->temp[i] = | 2458 | data->temp[i][0] = |
| 2423 | it87_read_value(data, IT87_REG_TEMP(i)); | 2459 | it87_read_value(data, IT87_REG_TEMP(i)); |
| 2424 | data->temp_high[i] = | 2460 | data->temp[i][1] = |
| 2425 | it87_read_value(data, IT87_REG_TEMP_HIGH(i)); | ||
| 2426 | data->temp_low[i] = | ||
| 2427 | it87_read_value(data, IT87_REG_TEMP_LOW(i)); | 2461 | it87_read_value(data, IT87_REG_TEMP_LOW(i)); |
| 2462 | data->temp[i][2] = | ||
| 2463 | it87_read_value(data, IT87_REG_TEMP_HIGH(i)); | ||
| 2464 | if (has_temp_offset(data)) | ||
| 2465 | data->temp[i][3] = | ||
| 2466 | it87_read_value(data, | ||
| 2467 | IT87_REG_TEMP_OFFSET[i]); | ||
| 2428 | } | 2468 | } |
| 2429 | 2469 | ||
| 2430 | /* Newer chips don't have clock dividers */ | 2470 | /* Newer chips don't have clock dividers */ |
| @@ -2448,6 +2488,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
| 2448 | it87_update_pwm_ctrl(data, i); | 2488 | it87_update_pwm_ctrl(data, i); |
| 2449 | 2489 | ||
| 2450 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 2490 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
| 2491 | data->extra = it87_read_value(data, IT87_REG_TEMP_EXTRA); | ||
| 2451 | /* | 2492 | /* |
| 2452 | * The IT8705F does not have VID capability. | 2493 | * The IT8705F does not have VID capability. |
| 2453 | * The IT8718F and later don't use IT87_REG_VID for the | 2494 | * The IT8718F and later don't use IT87_REG_VID for the |
| @@ -2549,8 +2590,7 @@ static void __exit sm_it87_exit(void) | |||
| 2549 | } | 2590 | } |
| 2550 | 2591 | ||
| 2551 | 2592 | ||
| 2552 | MODULE_AUTHOR("Chris Gauthron, " | 2593 | MODULE_AUTHOR("Chris Gauthron, Jean Delvare <khali@linux-fr.org>"); |
| 2553 | "Jean Delvare <khali@linux-fr.org>"); | ||
| 2554 | MODULE_DESCRIPTION("IT8705F/IT871xF/IT872xF hardware monitoring driver"); | 2594 | MODULE_DESCRIPTION("IT8705F/IT871xF/IT872xF hardware monitoring driver"); |
| 2555 | module_param(update_vbat, bool, 0); | 2595 | module_param(update_vbat, bool, 0); |
| 2556 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); | 2596 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); |
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 55ac41c05561..0e8ffd6059a0 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * w83627ehf - Driver for the hardware monitoring functionality of | 2 | * w83627ehf - Driver for the hardware monitoring functionality of |
| 3 | * the Winbond W83627EHF Super-I/O chip | 3 | * the Winbond W83627EHF Super-I/O chip |
| 4 | * Copyright (C) 2005-2011 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2005-2012 Jean Delvare <khali@linux-fr.org> |
| 5 | * Copyright (C) 2006 Yuan Mu (Winbond), | 5 | * Copyright (C) 2006 Yuan Mu (Winbond), |
| 6 | * Rudolf Marek <r.marek@assembler.cz> | 6 | * Rudolf Marek <r.marek@assembler.cz> |
| 7 | * David Hubbard <david.c.hubbard@gmail.com> | 7 | * David Hubbard <david.c.hubbard@gmail.com> |
| @@ -502,6 +502,13 @@ struct w83627ehf_data { | |||
| 502 | u16 have_temp_offset; | 502 | u16 have_temp_offset; |
| 503 | u8 in6_skip:1; | 503 | u8 in6_skip:1; |
| 504 | u8 temp3_val_only:1; | 504 | u8 temp3_val_only:1; |
| 505 | |||
| 506 | #ifdef CONFIG_PM | ||
| 507 | /* Remember extra register values over suspend/resume */ | ||
| 508 | u8 vbat; | ||
| 509 | u8 fandiv1; | ||
| 510 | u8 fandiv2; | ||
| 511 | #endif | ||
| 505 | }; | 512 | }; |
| 506 | 513 | ||
| 507 | struct w83627ehf_sio_data { | 514 | struct w83627ehf_sio_data { |
| @@ -898,6 +905,8 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | |||
| 898 | data->temp_max_hyst[i] | 905 | data->temp_max_hyst[i] |
| 899 | = w83627ehf_read_temp(data, | 906 | = w83627ehf_read_temp(data, |
| 900 | data->reg_temp_hyst[i]); | 907 | data->reg_temp_hyst[i]); |
| 908 | if (i > 2) | ||
| 909 | continue; | ||
| 901 | if (data->have_temp_offset & (1 << i)) | 910 | if (data->have_temp_offset & (1 << i)) |
| 902 | data->temp_offset[i] | 911 | data->temp_offset[i] |
| 903 | = w83627ehf_read_value(data, | 912 | = w83627ehf_read_value(data, |
| @@ -2608,10 +2617,98 @@ static int w83627ehf_remove(struct platform_device *pdev) | |||
| 2608 | return 0; | 2617 | return 0; |
| 2609 | } | 2618 | } |
| 2610 | 2619 | ||
| 2620 | #ifdef CONFIG_PM | ||
| 2621 | static int w83627ehf_suspend(struct device *dev) | ||
| 2622 | { | ||
| 2623 | struct w83627ehf_data *data = w83627ehf_update_device(dev); | ||
| 2624 | struct w83627ehf_sio_data *sio_data = dev->platform_data; | ||
| 2625 | |||
| 2626 | mutex_lock(&data->update_lock); | ||
| 2627 | data->vbat = w83627ehf_read_value(data, W83627EHF_REG_VBAT); | ||
| 2628 | if (sio_data->kind == nct6775) { | ||
| 2629 | data->fandiv1 = w83627ehf_read_value(data, NCT6775_REG_FANDIV1); | ||
| 2630 | data->fandiv2 = w83627ehf_read_value(data, NCT6775_REG_FANDIV2); | ||
| 2631 | } | ||
| 2632 | mutex_unlock(&data->update_lock); | ||
| 2633 | |||
| 2634 | return 0; | ||
| 2635 | } | ||
| 2636 | |||
| 2637 | static int w83627ehf_resume(struct device *dev) | ||
| 2638 | { | ||
| 2639 | struct w83627ehf_data *data = dev_get_drvdata(dev); | ||
| 2640 | struct w83627ehf_sio_data *sio_data = dev->platform_data; | ||
| 2641 | int i; | ||
| 2642 | |||
| 2643 | mutex_lock(&data->update_lock); | ||
| 2644 | data->bank = 0xff; /* Force initial bank selection */ | ||
| 2645 | |||
| 2646 | /* Restore limits */ | ||
| 2647 | for (i = 0; i < data->in_num; i++) { | ||
| 2648 | if ((i == 6) && data->in6_skip) | ||
| 2649 | continue; | ||
| 2650 | |||
| 2651 | w83627ehf_write_value(data, W83627EHF_REG_IN_MIN(i), | ||
| 2652 | data->in_min[i]); | ||
| 2653 | w83627ehf_write_value(data, W83627EHF_REG_IN_MAX(i), | ||
| 2654 | data->in_max[i]); | ||
| 2655 | } | ||
| 2656 | |||
| 2657 | for (i = 0; i < 5; i++) { | ||
| 2658 | if (!(data->has_fan_min & (1 << i))) | ||
| 2659 | continue; | ||
| 2660 | |||
| 2661 | w83627ehf_write_value(data, data->REG_FAN_MIN[i], | ||
| 2662 | data->fan_min[i]); | ||
| 2663 | } | ||
| 2664 | |||
| 2665 | for (i = 0; i < NUM_REG_TEMP; i++) { | ||
| 2666 | if (!(data->have_temp & (1 << i))) | ||
| 2667 | continue; | ||
| 2668 | |||
| 2669 | if (data->reg_temp_over[i]) | ||
| 2670 | w83627ehf_write_temp(data, data->reg_temp_over[i], | ||
| 2671 | data->temp_max[i]); | ||
| 2672 | if (data->reg_temp_hyst[i]) | ||
| 2673 | w83627ehf_write_temp(data, data->reg_temp_hyst[i], | ||
| 2674 | data->temp_max_hyst[i]); | ||
| 2675 | if (i > 2) | ||
| 2676 | continue; | ||
| 2677 | if (data->have_temp_offset & (1 << i)) | ||
| 2678 | w83627ehf_write_value(data, | ||
| 2679 | W83627EHF_REG_TEMP_OFFSET[i], | ||
| 2680 | data->temp_offset[i]); | ||
| 2681 | } | ||
| 2682 | |||
| 2683 | /* Restore other settings */ | ||
| 2684 | w83627ehf_write_value(data, W83627EHF_REG_VBAT, data->vbat); | ||
| 2685 | if (sio_data->kind == nct6775) { | ||
| 2686 | w83627ehf_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1); | ||
| 2687 | w83627ehf_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2); | ||
| 2688 | } | ||
| 2689 | |||
| 2690 | /* Force re-reading all values */ | ||
| 2691 | data->valid = 0; | ||
| 2692 | mutex_unlock(&data->update_lock); | ||
| 2693 | |||
| 2694 | return 0; | ||
| 2695 | } | ||
| 2696 | |||
| 2697 | static const struct dev_pm_ops w83627ehf_dev_pm_ops = { | ||
| 2698 | .suspend = w83627ehf_suspend, | ||
| 2699 | .resume = w83627ehf_resume, | ||
| 2700 | }; | ||
| 2701 | |||
| 2702 | #define W83627EHF_DEV_PM_OPS (&w83627ehf_dev_pm_ops) | ||
| 2703 | #else | ||
| 2704 | #define W83627EHF_DEV_PM_OPS NULL | ||
| 2705 | #endif /* CONFIG_PM */ | ||
| 2706 | |||
| 2611 | static struct platform_driver w83627ehf_driver = { | 2707 | static struct platform_driver w83627ehf_driver = { |
| 2612 | .driver = { | 2708 | .driver = { |
| 2613 | .owner = THIS_MODULE, | 2709 | .owner = THIS_MODULE, |
| 2614 | .name = DRVNAME, | 2710 | .name = DRVNAME, |
| 2711 | .pm = W83627EHF_DEV_PM_OPS, | ||
| 2615 | }, | 2712 | }, |
| 2616 | .probe = w83627ehf_probe, | 2713 | .probe = w83627ehf_probe, |
| 2617 | .remove = w83627ehf_remove, | 2714 | .remove = w83627ehf_remove, |
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 7f68b8309d10..81f486520cea 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | * Philip Edelbrock <phil@netroedge.com>, | 5 | * Philip Edelbrock <phil@netroedge.com>, |
| 6 | * and Mark Studebaker <mdsxyz123@yahoo.com> | 6 | * and Mark Studebaker <mdsxyz123@yahoo.com> |
| 7 | * Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org> | 7 | * Ported to 2.6 by Bernhard C. Schrenk <clemy@clemy.org> |
| 8 | * Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> | 8 | * Copyright (c) 2007 - 1012 Jean Delvare <khali@linux-fr.org> |
| 9 | * | 9 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
| @@ -389,6 +389,12 @@ struct w83627hf_data { | |||
| 389 | */ | 389 | */ |
| 390 | u8 vrm; | 390 | u8 vrm; |
| 391 | u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ | 391 | u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ |
| 392 | |||
| 393 | #ifdef CONFIG_PM | ||
| 394 | /* Remember extra register values over suspend/resume */ | ||
| 395 | u8 scfg1; | ||
| 396 | u8 scfg2; | ||
| 397 | #endif | ||
| 392 | }; | 398 | }; |
| 393 | 399 | ||
| 394 | 400 | ||
| @@ -401,10 +407,77 @@ static void w83627hf_update_fan_div(struct w83627hf_data *data); | |||
| 401 | static struct w83627hf_data *w83627hf_update_device(struct device *dev); | 407 | static struct w83627hf_data *w83627hf_update_device(struct device *dev); |
| 402 | static void w83627hf_init_device(struct platform_device *pdev); | 408 | static void w83627hf_init_device(struct platform_device *pdev); |
| 403 | 409 | ||
| 410 | #ifdef CONFIG_PM | ||
| 411 | static int w83627hf_suspend(struct device *dev) | ||
| 412 | { | ||
| 413 | struct w83627hf_data *data = w83627hf_update_device(dev); | ||
| 414 | |||
| 415 | mutex_lock(&data->update_lock); | ||
| 416 | data->scfg1 = w83627hf_read_value(data, W83781D_REG_SCFG1); | ||
| 417 | data->scfg2 = w83627hf_read_value(data, W83781D_REG_SCFG2); | ||
| 418 | mutex_unlock(&data->update_lock); | ||
| 419 | |||
| 420 | return 0; | ||
| 421 | } | ||
| 422 | |||
| 423 | static int w83627hf_resume(struct device *dev) | ||
| 424 | { | ||
| 425 | struct w83627hf_data *data = dev_get_drvdata(dev); | ||
| 426 | int i, num_temps = (data->type == w83697hf) ? 2 : 3; | ||
| 427 | |||
| 428 | /* Restore limits */ | ||
| 429 | mutex_lock(&data->update_lock); | ||
| 430 | for (i = 0; i <= 8; i++) { | ||
| 431 | /* skip missing sensors */ | ||
| 432 | if (((data->type == w83697hf) && (i == 1)) || | ||
| 433 | ((data->type != w83627hf && data->type != w83697hf) | ||
| 434 | && (i == 5 || i == 6))) | ||
| 435 | continue; | ||
| 436 | w83627hf_write_value(data, W83781D_REG_IN_MAX(i), | ||
| 437 | data->in_max[i]); | ||
| 438 | w83627hf_write_value(data, W83781D_REG_IN_MIN(i), | ||
| 439 | data->in_min[i]); | ||
| 440 | } | ||
| 441 | for (i = 0; i <= 2; i++) | ||
| 442 | w83627hf_write_value(data, W83627HF_REG_FAN_MIN(i), | ||
| 443 | data->fan_min[i]); | ||
| 444 | for (i = 0; i < num_temps; i++) { | ||
| 445 | w83627hf_write_value(data, w83627hf_reg_temp_over[i], | ||
| 446 | data->temp_max[i]); | ||
| 447 | w83627hf_write_value(data, w83627hf_reg_temp_hyst[i], | ||
| 448 | data->temp_max_hyst[i]); | ||
| 449 | } | ||
| 450 | |||
| 451 | /* Fixup BIOS bugs */ | ||
| 452 | if (data->type == w83627thf || data->type == w83637hf || | ||
| 453 | data->type == w83687thf) | ||
| 454 | w83627hf_write_value(data, W83627THF_REG_VRM_OVT_CFG, | ||
| 455 | data->vrm_ovt); | ||
| 456 | w83627hf_write_value(data, W83781D_REG_SCFG1, data->scfg1); | ||
| 457 | w83627hf_write_value(data, W83781D_REG_SCFG2, data->scfg2); | ||
| 458 | |||
| 459 | /* Force re-reading all values */ | ||
| 460 | data->valid = 0; | ||
| 461 | mutex_unlock(&data->update_lock); | ||
| 462 | |||
| 463 | return 0; | ||
| 464 | } | ||
| 465 | |||
| 466 | static const struct dev_pm_ops w83627hf_dev_pm_ops = { | ||
| 467 | .suspend = w83627hf_suspend, | ||
| 468 | .resume = w83627hf_resume, | ||
| 469 | }; | ||
| 470 | |||
| 471 | #define W83627HF_DEV_PM_OPS (&w83627hf_dev_pm_ops) | ||
| 472 | #else | ||
| 473 | #define W83627HF_DEV_PM_OPS NULL | ||
| 474 | #endif /* CONFIG_PM */ | ||
| 475 | |||
| 404 | static struct platform_driver w83627hf_driver = { | 476 | static struct platform_driver w83627hf_driver = { |
| 405 | .driver = { | 477 | .driver = { |
| 406 | .owner = THIS_MODULE, | 478 | .owner = THIS_MODULE, |
| 407 | .name = DRVNAME, | 479 | .name = DRVNAME, |
| 480 | .pm = W83627HF_DEV_PM_OPS, | ||
| 408 | }, | 481 | }, |
| 409 | .probe = w83627hf_probe, | 482 | .probe = w83627hf_probe, |
| 410 | .remove = w83627hf_remove, | 483 | .remove = w83627hf_remove, |
| @@ -1659,8 +1732,10 @@ static void w83627hf_init_device(struct platform_device *pdev) | |||
| 1659 | /* Minimize conflicts with other winbond i2c-only clients... */ | 1732 | /* Minimize conflicts with other winbond i2c-only clients... */ |
| 1660 | /* disable i2c subclients... how to disable main i2c client?? */ | 1733 | /* disable i2c subclients... how to disable main i2c client?? */ |
| 1661 | /* force i2c address to relatively uncommon address */ | 1734 | /* force i2c address to relatively uncommon address */ |
| 1662 | w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89); | 1735 | if (type == w83627hf) { |
| 1663 | w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c); | 1736 | w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89); |
| 1737 | w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c); | ||
| 1738 | } | ||
| 1664 | 1739 | ||
| 1665 | /* Read VID only once */ | 1740 | /* Read VID only once */ |
| 1666 | if (type == w83627hf || type == w83637hf) { | 1741 | if (type == w83627hf || type == w83637hf) { |
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 5de86968379d..c13745cde7fa 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c | |||
| @@ -38,10 +38,12 @@ | |||
| 38 | #include <linux/inetdevice.h> | 38 | #include <linux/inetdevice.h> |
| 39 | #include <linux/ip.h> | 39 | #include <linux/ip.h> |
| 40 | #include <linux/tcp.h> | 40 | #include <linux/tcp.h> |
| 41 | #include <linux/if_vlan.h> | ||
| 41 | 42 | ||
| 42 | #include <net/neighbour.h> | 43 | #include <net/neighbour.h> |
| 43 | #include <net/netevent.h> | 44 | #include <net/netevent.h> |
| 44 | #include <net/route.h> | 45 | #include <net/route.h> |
| 46 | #include <net/tcp.h> | ||
| 45 | 47 | ||
| 46 | #include "iw_cxgb4.h" | 48 | #include "iw_cxgb4.h" |
| 47 | 49 | ||
| @@ -61,6 +63,14 @@ static char *states[] = { | |||
| 61 | NULL, | 63 | NULL, |
| 62 | }; | 64 | }; |
| 63 | 65 | ||
| 66 | static int nocong; | ||
| 67 | module_param(nocong, int, 0644); | ||
| 68 | MODULE_PARM_DESC(nocong, "Turn of congestion control (default=0)"); | ||
| 69 | |||
| 70 | static int enable_ecn; | ||
| 71 | module_param(enable_ecn, int, 0644); | ||
| 72 | MODULE_PARM_DESC(enable_ecn, "Enable ECN (default=0/disabled)"); | ||
| 73 | |||
| 64 | static int dack_mode = 1; | 74 | static int dack_mode = 1; |
| 65 | module_param(dack_mode, int, 0644); | 75 | module_param(dack_mode, int, 0644); |
| 66 | MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)"); | 76 | MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)"); |
| @@ -265,6 +275,7 @@ void _c4iw_free_ep(struct kref *kref) | |||
| 265 | cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid); | 275 | cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid); |
| 266 | dst_release(ep->dst); | 276 | dst_release(ep->dst); |
| 267 | cxgb4_l2t_release(ep->l2t); | 277 | cxgb4_l2t_release(ep->l2t); |
| 278 | remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid); | ||
| 268 | } | 279 | } |
| 269 | kfree(ep); | 280 | kfree(ep); |
| 270 | } | 281 | } |
| @@ -441,6 +452,50 @@ static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp) | |||
| 441 | return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); | 452 | return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); |
| 442 | } | 453 | } |
| 443 | 454 | ||
| 455 | #define VLAN_NONE 0xfff | ||
| 456 | #define FILTER_SEL_VLAN_NONE 0xffff | ||
| 457 | #define FILTER_SEL_WIDTH_P_FC (3+1) /* port uses 3 bits, FCoE one bit */ | ||
| 458 | #define FILTER_SEL_WIDTH_VIN_P_FC \ | ||
| 459 | (6 + 7 + FILTER_SEL_WIDTH_P_FC) /* 6 bits are unused, VF uses 7 bits*/ | ||
| 460 | #define FILTER_SEL_WIDTH_TAG_P_FC \ | ||
| 461 | (3 + FILTER_SEL_WIDTH_VIN_P_FC) /* PF uses 3 bits */ | ||
| 462 | #define FILTER_SEL_WIDTH_VLD_TAG_P_FC (1 + FILTER_SEL_WIDTH_TAG_P_FC) | ||
| 463 | |||
| 464 | static unsigned int select_ntuple(struct c4iw_dev *dev, struct dst_entry *dst, | ||
| 465 | struct l2t_entry *l2t) | ||
| 466 | { | ||
| 467 | unsigned int ntuple = 0; | ||
| 468 | u32 viid; | ||
| 469 | |||
| 470 | switch (dev->rdev.lldi.filt_mode) { | ||
| 471 | |||
| 472 | /* default filter mode */ | ||
| 473 | case HW_TPL_FR_MT_PR_IV_P_FC: | ||
| 474 | if (l2t->vlan == VLAN_NONE) | ||
| 475 | ntuple |= FILTER_SEL_VLAN_NONE << FILTER_SEL_WIDTH_P_FC; | ||
| 476 | else { | ||
| 477 | ntuple |= l2t->vlan << FILTER_SEL_WIDTH_P_FC; | ||
| 478 | ntuple |= 1 << FILTER_SEL_WIDTH_VLD_TAG_P_FC; | ||
| 479 | } | ||
| 480 | ntuple |= l2t->lport << S_PORT | IPPROTO_TCP << | ||
| 481 | FILTER_SEL_WIDTH_VLD_TAG_P_FC; | ||
| 482 | break; | ||
| 483 | case HW_TPL_FR_MT_PR_OV_P_FC: { | ||
| 484 | viid = cxgb4_port_viid(l2t->neigh->dev); | ||
| 485 | |||
| 486 | ntuple |= FW_VIID_VIN_GET(viid) << FILTER_SEL_WIDTH_P_FC; | ||
| 487 | ntuple |= FW_VIID_PFN_GET(viid) << FILTER_SEL_WIDTH_VIN_P_FC; | ||
| 488 | ntuple |= FW_VIID_VIVLD_GET(viid) << FILTER_SEL_WIDTH_TAG_P_FC; | ||
| 489 | ntuple |= l2t->lport << S_PORT | IPPROTO_TCP << | ||
| 490 | FILTER_SEL_WIDTH_VLD_TAG_P_FC; | ||
| 491 | break; | ||
| 492 | } | ||
| 493 | default: | ||
| 494 | break; | ||
| 495 | } | ||
| 496 | return ntuple; | ||
| 497 | } | ||
| 498 | |||
| 444 | static int send_connect(struct c4iw_ep *ep) | 499 | static int send_connect(struct c4iw_ep *ep) |
| 445 | { | 500 | { |
| 446 | struct cpl_act_open_req *req; | 501 | struct cpl_act_open_req *req; |
| @@ -463,7 +518,8 @@ static int send_connect(struct c4iw_ep *ep) | |||
| 463 | 518 | ||
| 464 | cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx); | 519 | cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx); |
| 465 | wscale = compute_wscale(rcv_win); | 520 | wscale = compute_wscale(rcv_win); |
| 466 | opt0 = KEEP_ALIVE(1) | | 521 | opt0 = (nocong ? NO_CONG(1) : 0) | |
| 522 | KEEP_ALIVE(1) | | ||
| 467 | DELACK(1) | | 523 | DELACK(1) | |
| 468 | WND_SCALE(wscale) | | 524 | WND_SCALE(wscale) | |
| 469 | MSS_IDX(mtu_idx) | | 525 | MSS_IDX(mtu_idx) | |
| @@ -474,6 +530,7 @@ static int send_connect(struct c4iw_ep *ep) | |||
| 474 | ULP_MODE(ULP_MODE_TCPDDP) | | 530 | ULP_MODE(ULP_MODE_TCPDDP) | |
| 475 | RCV_BUFSIZ(rcv_win>>10); | 531 | RCV_BUFSIZ(rcv_win>>10); |
| 476 | opt2 = RX_CHANNEL(0) | | 532 | opt2 = RX_CHANNEL(0) | |
| 533 | CCTRL_ECN(enable_ecn) | | ||
| 477 | RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid); | 534 | RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid); |
| 478 | if (enable_tcp_timestamps) | 535 | if (enable_tcp_timestamps) |
| 479 | opt2 |= TSTAMPS_EN(1); | 536 | opt2 |= TSTAMPS_EN(1); |
| @@ -492,8 +549,9 @@ static int send_connect(struct c4iw_ep *ep) | |||
| 492 | req->local_ip = ep->com.local_addr.sin_addr.s_addr; | 549 | req->local_ip = ep->com.local_addr.sin_addr.s_addr; |
| 493 | req->peer_ip = ep->com.remote_addr.sin_addr.s_addr; | 550 | req->peer_ip = ep->com.remote_addr.sin_addr.s_addr; |
| 494 | req->opt0 = cpu_to_be64(opt0); | 551 | req->opt0 = cpu_to_be64(opt0); |
| 495 | req->params = 0; | 552 | req->params = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst, ep->l2t)); |
| 496 | req->opt2 = cpu_to_be32(opt2); | 553 | req->opt2 = cpu_to_be32(opt2); |
| 554 | set_bit(ACT_OPEN_REQ, &ep->com.history); | ||
| 497 | return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); | 555 | return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); |
| 498 | } | 556 | } |
| 499 | 557 | ||
| @@ -770,6 +828,7 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 770 | /* setup the hwtid for this connection */ | 828 | /* setup the hwtid for this connection */ |
| 771 | ep->hwtid = tid; | 829 | ep->hwtid = tid; |
| 772 | cxgb4_insert_tid(t, ep, tid); | 830 | cxgb4_insert_tid(t, ep, tid); |
| 831 | insert_handle(dev, &dev->hwtid_idr, ep, ep->hwtid); | ||
| 773 | 832 | ||
| 774 | ep->snd_seq = be32_to_cpu(req->snd_isn); | 833 | ep->snd_seq = be32_to_cpu(req->snd_isn); |
| 775 | ep->rcv_seq = be32_to_cpu(req->rcv_isn); | 834 | ep->rcv_seq = be32_to_cpu(req->rcv_isn); |
| @@ -777,7 +836,9 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 777 | set_emss(ep, ntohs(req->tcp_opt)); | 836 | set_emss(ep, ntohs(req->tcp_opt)); |
| 778 | 837 | ||
| 779 | /* dealloc the atid */ | 838 | /* dealloc the atid */ |
| 839 | remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid); | ||
| 780 | cxgb4_free_atid(t, atid); | 840 | cxgb4_free_atid(t, atid); |
| 841 | set_bit(ACT_ESTAB, &ep->com.history); | ||
| 781 | 842 | ||
| 782 | /* start MPA negotiation */ | 843 | /* start MPA negotiation */ |
| 783 | send_flowc(ep, NULL); | 844 | send_flowc(ep, NULL); |
| @@ -803,6 +864,7 @@ static void close_complete_upcall(struct c4iw_ep *ep) | |||
| 803 | ep->com.cm_id->rem_ref(ep->com.cm_id); | 864 | ep->com.cm_id->rem_ref(ep->com.cm_id); |
| 804 | ep->com.cm_id = NULL; | 865 | ep->com.cm_id = NULL; |
| 805 | ep->com.qp = NULL; | 866 | ep->com.qp = NULL; |
| 867 | set_bit(CLOSE_UPCALL, &ep->com.history); | ||
| 806 | } | 868 | } |
| 807 | } | 869 | } |
| 808 | 870 | ||
| @@ -811,6 +873,7 @@ static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp) | |||
| 811 | PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); | 873 | PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); |
| 812 | close_complete_upcall(ep); | 874 | close_complete_upcall(ep); |
| 813 | state_set(&ep->com, ABORTING); | 875 | state_set(&ep->com, ABORTING); |
| 876 | set_bit(ABORT_CONN, &ep->com.history); | ||
| 814 | return send_abort(ep, skb, gfp); | 877 | return send_abort(ep, skb, gfp); |
| 815 | } | 878 | } |
| 816 | 879 | ||
| @@ -825,6 +888,7 @@ static void peer_close_upcall(struct c4iw_ep *ep) | |||
| 825 | PDBG("peer close delivered ep %p cm_id %p tid %u\n", | 888 | PDBG("peer close delivered ep %p cm_id %p tid %u\n", |
| 826 | ep, ep->com.cm_id, ep->hwtid); | 889 | ep, ep->com.cm_id, ep->hwtid); |
| 827 | ep->com.cm_id->event_handler(ep->com.cm_id, &event); | 890 | ep->com.cm_id->event_handler(ep->com.cm_id, &event); |
| 891 | set_bit(DISCONN_UPCALL, &ep->com.history); | ||
| 828 | } | 892 | } |
| 829 | } | 893 | } |
| 830 | 894 | ||
| @@ -843,6 +907,7 @@ static void peer_abort_upcall(struct c4iw_ep *ep) | |||
| 843 | ep->com.cm_id->rem_ref(ep->com.cm_id); | 907 | ep->com.cm_id->rem_ref(ep->com.cm_id); |
| 844 | ep->com.cm_id = NULL; | 908 | ep->com.cm_id = NULL; |
| 845 | ep->com.qp = NULL; | 909 | ep->com.qp = NULL; |
| 910 | set_bit(ABORT_UPCALL, &ep->com.history); | ||
| 846 | } | 911 | } |
| 847 | } | 912 | } |
| 848 | 913 | ||
| @@ -875,6 +940,7 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status) | |||
| 875 | 940 | ||
| 876 | PDBG("%s ep %p tid %u status %d\n", __func__, ep, | 941 | PDBG("%s ep %p tid %u status %d\n", __func__, ep, |
| 877 | ep->hwtid, status); | 942 | ep->hwtid, status); |
| 943 | set_bit(CONN_RPL_UPCALL, &ep->com.history); | ||
| 878 | ep->com.cm_id->event_handler(ep->com.cm_id, &event); | 944 | ep->com.cm_id->event_handler(ep->com.cm_id, &event); |
| 879 | 945 | ||
| 880 | if (status < 0) { | 946 | if (status < 0) { |
| @@ -915,6 +981,7 @@ static void connect_request_upcall(struct c4iw_ep *ep) | |||
| 915 | ep->parent_ep->com.cm_id, | 981 | ep->parent_ep->com.cm_id, |
| 916 | &event); | 982 | &event); |
| 917 | } | 983 | } |
| 984 | set_bit(CONNREQ_UPCALL, &ep->com.history); | ||
| 918 | c4iw_put_ep(&ep->parent_ep->com); | 985 | c4iw_put_ep(&ep->parent_ep->com); |
| 919 | ep->parent_ep = NULL; | 986 | ep->parent_ep = NULL; |
| 920 | } | 987 | } |
| @@ -931,6 +998,7 @@ static void established_upcall(struct c4iw_ep *ep) | |||
| 931 | if (ep->com.cm_id) { | 998 | if (ep->com.cm_id) { |
| 932 | PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); | 999 | PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); |
| 933 | ep->com.cm_id->event_handler(ep->com.cm_id, &event); | 1000 | ep->com.cm_id->event_handler(ep->com.cm_id, &event); |
| 1001 | set_bit(ESTAB_UPCALL, &ep->com.history); | ||
| 934 | } | 1002 | } |
| 935 | } | 1003 | } |
| 936 | 1004 | ||
| @@ -1316,6 +1384,7 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1316 | unsigned int dlen = ntohs(hdr->len); | 1384 | unsigned int dlen = ntohs(hdr->len); |
| 1317 | unsigned int tid = GET_TID(hdr); | 1385 | unsigned int tid = GET_TID(hdr); |
| 1318 | struct tid_info *t = dev->rdev.lldi.tids; | 1386 | struct tid_info *t = dev->rdev.lldi.tids; |
| 1387 | __u8 status = hdr->status; | ||
| 1319 | 1388 | ||
| 1320 | ep = lookup_tid(t, tid); | 1389 | ep = lookup_tid(t, tid); |
| 1321 | PDBG("%s ep %p tid %u dlen %u\n", __func__, ep, ep->hwtid, dlen); | 1390 | PDBG("%s ep %p tid %u dlen %u\n", __func__, ep, ep->hwtid, dlen); |
| @@ -1338,9 +1407,9 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1338 | case MPA_REP_SENT: | 1407 | case MPA_REP_SENT: |
| 1339 | break; | 1408 | break; |
| 1340 | default: | 1409 | default: |
| 1341 | printk(KERN_ERR MOD "%s Unexpected streaming data." | 1410 | pr_err("%s Unexpected streaming data." \ |
| 1342 | " ep %p state %d tid %u\n", | 1411 | " ep %p state %d tid %u status %d\n", |
| 1343 | __func__, ep, state_read(&ep->com), ep->hwtid); | 1412 | __func__, ep, state_read(&ep->com), ep->hwtid, status); |
| 1344 | 1413 | ||
| 1345 | /* | 1414 | /* |
| 1346 | * The ep will timeout and inform the ULP of the failure. | 1415 | * The ep will timeout and inform the ULP of the failure. |
| @@ -1383,6 +1452,63 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1383 | return 0; | 1452 | return 0; |
| 1384 | } | 1453 | } |
| 1385 | 1454 | ||
| 1455 | static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) | ||
| 1456 | { | ||
| 1457 | struct sk_buff *skb; | ||
| 1458 | struct fw_ofld_connection_wr *req; | ||
| 1459 | unsigned int mtu_idx; | ||
| 1460 | int wscale; | ||
| 1461 | |||
| 1462 | skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); | ||
| 1463 | req = (struct fw_ofld_connection_wr *)__skb_put(skb, sizeof(*req)); | ||
| 1464 | memset(req, 0, sizeof(*req)); | ||
| 1465 | req->op_compl = htonl(V_WR_OP(FW_OFLD_CONNECTION_WR)); | ||
| 1466 | req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16))); | ||
| 1467 | req->le.filter = cpu_to_be32(select_ntuple(ep->com.dev, ep->dst, | ||
| 1468 | ep->l2t)); | ||
| 1469 | req->le.lport = ep->com.local_addr.sin_port; | ||
| 1470 | req->le.pport = ep->com.remote_addr.sin_port; | ||
| 1471 | req->le.u.ipv4.lip = ep->com.local_addr.sin_addr.s_addr; | ||
| 1472 | req->le.u.ipv4.pip = ep->com.remote_addr.sin_addr.s_addr; | ||
| 1473 | req->tcb.t_state_to_astid = | ||
| 1474 | htonl(V_FW_OFLD_CONNECTION_WR_T_STATE(TCP_SYN_SENT) | | ||
| 1475 | V_FW_OFLD_CONNECTION_WR_ASTID(atid)); | ||
| 1476 | req->tcb.cplrxdataack_cplpassacceptrpl = | ||
| 1477 | htons(F_FW_OFLD_CONNECTION_WR_CPLRXDATAACK); | ||
| 1478 | req->tcb.tx_max = jiffies; | ||
| 1479 | req->tcb.rcv_adv = htons(1); | ||
| 1480 | cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx); | ||
| 1481 | wscale = compute_wscale(rcv_win); | ||
| 1482 | req->tcb.opt0 = TCAM_BYPASS(1) | | ||
| 1483 | (nocong ? NO_CONG(1) : 0) | | ||
| 1484 | KEEP_ALIVE(1) | | ||
| 1485 | DELACK(1) | | ||
| 1486 | WND_SCALE(wscale) | | ||
| 1487 | MSS_IDX(mtu_idx) | | ||
| 1488 | L2T_IDX(ep->l2t->idx) | | ||
| 1489 | TX_CHAN(ep->tx_chan) | | ||
| 1490 | SMAC_SEL(ep->smac_idx) | | ||
| 1491 | DSCP(ep->tos) | | ||
| 1492 | ULP_MODE(ULP_MODE_TCPDDP) | | ||
| 1493 | RCV_BUFSIZ(rcv_win >> 10); | ||
| 1494 | req->tcb.opt2 = PACE(1) | | ||
| 1495 | TX_QUEUE(ep->com.dev->rdev.lldi.tx_modq[ep->tx_chan]) | | ||
| 1496 | RX_CHANNEL(0) | | ||
| 1497 | CCTRL_ECN(enable_ecn) | | ||
| 1498 | RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid); | ||
| 1499 | if (enable_tcp_timestamps) | ||
| 1500 | req->tcb.opt2 |= TSTAMPS_EN(1); | ||
| 1501 | if (enable_tcp_sack) | ||
| 1502 | req->tcb.opt2 |= SACK_EN(1); | ||
| 1503 | if (wscale && enable_tcp_window_scaling) | ||
| 1504 | req->tcb.opt2 |= WND_SCALE_EN(1); | ||
| 1505 | req->tcb.opt0 = cpu_to_be64(req->tcb.opt0); | ||
| 1506 | req->tcb.opt2 = cpu_to_be32(req->tcb.opt2); | ||
| 1507 | set_wr_txq(skb, CPL_PRIORITY_CONTROL, ep->ctrlq_idx); | ||
| 1508 | set_bit(ACT_OFLD_CONN, &ep->com.history); | ||
| 1509 | c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t); | ||
| 1510 | } | ||
| 1511 | |||
| 1386 | /* | 1512 | /* |
| 1387 | * Return whether a failed active open has allocated a TID | 1513 | * Return whether a failed active open has allocated a TID |
| 1388 | */ | 1514 | */ |
| @@ -1392,6 +1518,111 @@ static inline int act_open_has_tid(int status) | |||
| 1392 | status != CPL_ERR_ARP_MISS; | 1518 | status != CPL_ERR_ARP_MISS; |
| 1393 | } | 1519 | } |
| 1394 | 1520 | ||
| 1521 | #define ACT_OPEN_RETRY_COUNT 2 | ||
| 1522 | |||
| 1523 | static int c4iw_reconnect(struct c4iw_ep *ep) | ||
| 1524 | { | ||
| 1525 | int err = 0; | ||
| 1526 | struct rtable *rt; | ||
| 1527 | struct port_info *pi; | ||
| 1528 | struct net_device *pdev; | ||
| 1529 | int step; | ||
| 1530 | struct neighbour *neigh; | ||
| 1531 | |||
| 1532 | PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id); | ||
| 1533 | init_timer(&ep->timer); | ||
| 1534 | |||
| 1535 | /* | ||
| 1536 | * Allocate an active TID to initiate a TCP connection. | ||
| 1537 | */ | ||
| 1538 | ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep); | ||
| 1539 | if (ep->atid == -1) { | ||
| 1540 | pr_err("%s - cannot alloc atid.\n", __func__); | ||
| 1541 | err = -ENOMEM; | ||
| 1542 | goto fail2; | ||
| 1543 | } | ||
| 1544 | insert_handle(ep->com.dev, &ep->com.dev->atid_idr, ep, ep->atid); | ||
| 1545 | |||
| 1546 | /* find a route */ | ||
| 1547 | rt = find_route(ep->com.dev, | ||
| 1548 | ep->com.cm_id->local_addr.sin_addr.s_addr, | ||
| 1549 | ep->com.cm_id->remote_addr.sin_addr.s_addr, | ||
| 1550 | ep->com.cm_id->local_addr.sin_port, | ||
| 1551 | ep->com.cm_id->remote_addr.sin_port, 0); | ||
| 1552 | if (!rt) { | ||
| 1553 | pr_err("%s - cannot find route.\n", __func__); | ||
| 1554 | err = -EHOSTUNREACH; | ||
| 1555 | goto fail3; | ||
| 1556 | } | ||
| 1557 | ep->dst = &rt->dst; | ||
| 1558 | |||
| 1559 | neigh = dst_neigh_lookup(ep->dst, | ||
| 1560 | &ep->com.cm_id->remote_addr.sin_addr.s_addr); | ||
| 1561 | /* get a l2t entry */ | ||
| 1562 | if (neigh->dev->flags & IFF_LOOPBACK) { | ||
| 1563 | PDBG("%s LOOPBACK\n", __func__); | ||
| 1564 | pdev = ip_dev_find(&init_net, | ||
| 1565 | ep->com.cm_id->remote_addr.sin_addr.s_addr); | ||
| 1566 | ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t, | ||
| 1567 | neigh, pdev, 0); | ||
| 1568 | pi = (struct port_info *)netdev_priv(pdev); | ||
| 1569 | ep->mtu = pdev->mtu; | ||
| 1570 | ep->tx_chan = cxgb4_port_chan(pdev); | ||
| 1571 | ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; | ||
| 1572 | dev_put(pdev); | ||
| 1573 | } else { | ||
| 1574 | ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t, | ||
| 1575 | neigh, neigh->dev, 0); | ||
| 1576 | pi = (struct port_info *)netdev_priv(neigh->dev); | ||
| 1577 | ep->mtu = dst_mtu(ep->dst); | ||
| 1578 | ep->tx_chan = cxgb4_port_chan(neigh->dev); | ||
| 1579 | ep->smac_idx = (cxgb4_port_viid(neigh->dev) & | ||
| 1580 | 0x7F) << 1; | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | step = ep->com.dev->rdev.lldi.ntxq / ep->com.dev->rdev.lldi.nchan; | ||
| 1584 | ep->txq_idx = pi->port_id * step; | ||
| 1585 | ep->ctrlq_idx = pi->port_id; | ||
| 1586 | step = ep->com.dev->rdev.lldi.nrxq / ep->com.dev->rdev.lldi.nchan; | ||
| 1587 | ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[pi->port_id * step]; | ||
| 1588 | |||
| 1589 | if (!ep->l2t) { | ||
| 1590 | pr_err("%s - cannot alloc l2e.\n", __func__); | ||
| 1591 | err = -ENOMEM; | ||
| 1592 | goto fail4; | ||
| 1593 | } | ||
| 1594 | |||
| 1595 | PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", | ||
| 1596 | __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, | ||
| 1597 | ep->l2t->idx); | ||
| 1598 | |||
| 1599 | state_set(&ep->com, CONNECTING); | ||
| 1600 | ep->tos = 0; | ||
| 1601 | |||
| 1602 | /* send connect request to rnic */ | ||
| 1603 | err = send_connect(ep); | ||
| 1604 | if (!err) | ||
| 1605 | goto out; | ||
| 1606 | |||
| 1607 | cxgb4_l2t_release(ep->l2t); | ||
| 1608 | fail4: | ||
| 1609 | dst_release(ep->dst); | ||
| 1610 | fail3: | ||
| 1611 | remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); | ||
| 1612 | cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); | ||
| 1613 | fail2: | ||
| 1614 | /* | ||
| 1615 | * remember to send notification to upper layer. | ||
| 1616 | * We are in here so the upper layer is not aware that this is | ||
| 1617 | * re-connect attempt and so, upper layer is still waiting for | ||
| 1618 | * response of 1st connect request. | ||
| 1619 | */ | ||
| 1620 | connect_reply_upcall(ep, -ECONNRESET); | ||
| 1621 | c4iw_put_ep(&ep->com); | ||
| 1622 | out: | ||
| 1623 | return err; | ||
| 1624 | } | ||
| 1625 | |||
| 1395 | static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | 1626 | static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) |
| 1396 | { | 1627 | { |
| 1397 | struct c4iw_ep *ep; | 1628 | struct c4iw_ep *ep; |
| @@ -1412,6 +1643,8 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1412 | return 0; | 1643 | return 0; |
| 1413 | } | 1644 | } |
| 1414 | 1645 | ||
| 1646 | set_bit(ACT_OPEN_RPL, &ep->com.history); | ||
| 1647 | |||
| 1415 | /* | 1648 | /* |
| 1416 | * Log interesting failures. | 1649 | * Log interesting failures. |
| 1417 | */ | 1650 | */ |
| @@ -1419,6 +1652,29 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1419 | case CPL_ERR_CONN_RESET: | 1652 | case CPL_ERR_CONN_RESET: |
| 1420 | case CPL_ERR_CONN_TIMEDOUT: | 1653 | case CPL_ERR_CONN_TIMEDOUT: |
| 1421 | break; | 1654 | break; |
| 1655 | case CPL_ERR_TCAM_FULL: | ||
| 1656 | if (dev->rdev.lldi.enable_fw_ofld_conn) { | ||
| 1657 | mutex_lock(&dev->rdev.stats.lock); | ||
| 1658 | dev->rdev.stats.tcam_full++; | ||
| 1659 | mutex_unlock(&dev->rdev.stats.lock); | ||
| 1660 | send_fw_act_open_req(ep, | ||
| 1661 | GET_TID_TID(GET_AOPEN_ATID( | ||
| 1662 | ntohl(rpl->atid_status)))); | ||
| 1663 | return 0; | ||
| 1664 | } | ||
| 1665 | break; | ||
| 1666 | case CPL_ERR_CONN_EXIST: | ||
| 1667 | if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { | ||
| 1668 | set_bit(ACT_RETRY_INUSE, &ep->com.history); | ||
| 1669 | remove_handle(ep->com.dev, &ep->com.dev->atid_idr, | ||
| 1670 | atid); | ||
| 1671 | cxgb4_free_atid(t, atid); | ||
| 1672 | dst_release(ep->dst); | ||
| 1673 | cxgb4_l2t_release(ep->l2t); | ||
| 1674 | c4iw_reconnect(ep); | ||
| 1675 | return 0; | ||
| 1676 | } | ||
| 1677 | break; | ||
| 1422 | default: | 1678 | default: |
| 1423 | printk(KERN_INFO MOD "Active open failure - " | 1679 | printk(KERN_INFO MOD "Active open failure - " |
| 1424 | "atid %u status %u errno %d %pI4:%u->%pI4:%u\n", | 1680 | "atid %u status %u errno %d %pI4:%u->%pI4:%u\n", |
| @@ -1436,6 +1692,7 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1436 | if (status && act_open_has_tid(status)) | 1692 | if (status && act_open_has_tid(status)) |
| 1437 | cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, GET_TID(rpl)); | 1693 | cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, GET_TID(rpl)); |
| 1438 | 1694 | ||
| 1695 | remove_handle(ep->com.dev, &ep->com.dev->atid_idr, atid); | ||
| 1439 | cxgb4_free_atid(t, atid); | 1696 | cxgb4_free_atid(t, atid); |
| 1440 | dst_release(ep->dst); | 1697 | dst_release(ep->dst); |
| 1441 | cxgb4_l2t_release(ep->l2t); | 1698 | cxgb4_l2t_release(ep->l2t); |
| @@ -1452,13 +1709,14 @@ static int pass_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1452 | struct c4iw_listen_ep *ep = lookup_stid(t, stid); | 1709 | struct c4iw_listen_ep *ep = lookup_stid(t, stid); |
| 1453 | 1710 | ||
| 1454 | if (!ep) { | 1711 | if (!ep) { |
| 1455 | printk(KERN_ERR MOD "stid %d lookup failure!\n", stid); | 1712 | PDBG("%s stid %d lookup failure!\n", __func__, stid); |
| 1456 | return 0; | 1713 | goto out; |
| 1457 | } | 1714 | } |
| 1458 | PDBG("%s ep %p status %d error %d\n", __func__, ep, | 1715 | PDBG("%s ep %p status %d error %d\n", __func__, ep, |
| 1459 | rpl->status, status2errno(rpl->status)); | 1716 | rpl->status, status2errno(rpl->status)); |
| 1460 | c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status)); | 1717 | c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status)); |
| 1461 | 1718 | ||
| 1719 | out: | ||
| 1462 | return 0; | 1720 | return 0; |
| 1463 | } | 1721 | } |
| 1464 | 1722 | ||
| @@ -1510,14 +1768,15 @@ static void accept_cr(struct c4iw_ep *ep, __be32 peer_ip, struct sk_buff *skb, | |||
| 1510 | skb_get(skb); | 1768 | skb_get(skb); |
| 1511 | cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx); | 1769 | cxgb4_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx); |
| 1512 | wscale = compute_wscale(rcv_win); | 1770 | wscale = compute_wscale(rcv_win); |
| 1513 | opt0 = KEEP_ALIVE(1) | | 1771 | opt0 = (nocong ? NO_CONG(1) : 0) | |
| 1772 | KEEP_ALIVE(1) | | ||
| 1514 | DELACK(1) | | 1773 | DELACK(1) | |
| 1515 | WND_SCALE(wscale) | | 1774 | WND_SCALE(wscale) | |
| 1516 | MSS_IDX(mtu_idx) | | 1775 | MSS_IDX(mtu_idx) | |
| 1517 | L2T_IDX(ep->l2t->idx) | | 1776 | L2T_IDX(ep->l2t->idx) | |
| 1518 | TX_CHAN(ep->tx_chan) | | 1777 | TX_CHAN(ep->tx_chan) | |
| 1519 | SMAC_SEL(ep->smac_idx) | | 1778 | SMAC_SEL(ep->smac_idx) | |
| 1520 | DSCP(ep->tos) | | 1779 | DSCP(ep->tos >> 2) | |
| 1521 | ULP_MODE(ULP_MODE_TCPDDP) | | 1780 | ULP_MODE(ULP_MODE_TCPDDP) | |
| 1522 | RCV_BUFSIZ(rcv_win>>10); | 1781 | RCV_BUFSIZ(rcv_win>>10); |
| 1523 | opt2 = RX_CHANNEL(0) | | 1782 | opt2 = RX_CHANNEL(0) | |
| @@ -1529,6 +1788,15 @@ static void accept_cr(struct c4iw_ep *ep, __be32 peer_ip, struct sk_buff *skb, | |||
| 1529 | opt2 |= SACK_EN(1); | 1788 | opt2 |= SACK_EN(1); |
| 1530 | if (wscale && enable_tcp_window_scaling) | 1789 | if (wscale && enable_tcp_window_scaling) |
| 1531 | opt2 |= WND_SCALE_EN(1); | 1790 | opt2 |= WND_SCALE_EN(1); |
| 1791 | if (enable_ecn) { | ||
| 1792 | const struct tcphdr *tcph; | ||
| 1793 | u32 hlen = ntohl(req->hdr_len); | ||
| 1794 | |||
| 1795 | tcph = (const void *)(req + 1) + G_ETH_HDR_LEN(hlen) + | ||
| 1796 | G_IP_HDR_LEN(hlen); | ||
| 1797 | if (tcph->ece && tcph->cwr) | ||
| 1798 | opt2 |= CCTRL_ECN(1); | ||
| 1799 | } | ||
| 1532 | 1800 | ||
| 1533 | rpl = cplhdr(skb); | 1801 | rpl = cplhdr(skb); |
| 1534 | INIT_TP_WR(rpl, ep->hwtid); | 1802 | INIT_TP_WR(rpl, ep->hwtid); |
| @@ -1645,22 +1913,30 @@ out: | |||
| 1645 | 1913 | ||
| 1646 | static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) | 1914 | static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) |
| 1647 | { | 1915 | { |
| 1648 | struct c4iw_ep *child_ep, *parent_ep; | 1916 | struct c4iw_ep *child_ep = NULL, *parent_ep; |
| 1649 | struct cpl_pass_accept_req *req = cplhdr(skb); | 1917 | struct cpl_pass_accept_req *req = cplhdr(skb); |
| 1650 | unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid)); | 1918 | unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid)); |
| 1651 | struct tid_info *t = dev->rdev.lldi.tids; | 1919 | struct tid_info *t = dev->rdev.lldi.tids; |
| 1652 | unsigned int hwtid = GET_TID(req); | 1920 | unsigned int hwtid = GET_TID(req); |
| 1653 | struct dst_entry *dst; | 1921 | struct dst_entry *dst; |
| 1654 | struct rtable *rt; | 1922 | struct rtable *rt; |
| 1655 | __be32 local_ip, peer_ip; | 1923 | __be32 local_ip, peer_ip = 0; |
| 1656 | __be16 local_port, peer_port; | 1924 | __be16 local_port, peer_port; |
| 1657 | int err; | 1925 | int err; |
| 1926 | u16 peer_mss = ntohs(req->tcpopt.mss); | ||
| 1658 | 1927 | ||
| 1659 | parent_ep = lookup_stid(t, stid); | 1928 | parent_ep = lookup_stid(t, stid); |
| 1660 | PDBG("%s parent ep %p tid %u\n", __func__, parent_ep, hwtid); | 1929 | if (!parent_ep) { |
| 1661 | 1930 | PDBG("%s connect request on invalid stid %d\n", __func__, stid); | |
| 1931 | goto reject; | ||
| 1932 | } | ||
| 1662 | get_4tuple(req, &local_ip, &peer_ip, &local_port, &peer_port); | 1933 | get_4tuple(req, &local_ip, &peer_ip, &local_port, &peer_port); |
| 1663 | 1934 | ||
| 1935 | PDBG("%s parent ep %p hwtid %u laddr 0x%x raddr 0x%x lport %d " \ | ||
| 1936 | "rport %d peer_mss %d\n", __func__, parent_ep, hwtid, | ||
| 1937 | ntohl(local_ip), ntohl(peer_ip), ntohs(local_port), | ||
| 1938 | ntohs(peer_port), peer_mss); | ||
| 1939 | |||
| 1664 | if (state_read(&parent_ep->com) != LISTEN) { | 1940 | if (state_read(&parent_ep->com) != LISTEN) { |
| 1665 | printk(KERN_ERR "%s - listening ep not in LISTEN\n", | 1941 | printk(KERN_ERR "%s - listening ep not in LISTEN\n", |
| 1666 | __func__); | 1942 | __func__); |
| @@ -1694,6 +1970,9 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1694 | goto reject; | 1970 | goto reject; |
| 1695 | } | 1971 | } |
| 1696 | 1972 | ||
| 1973 | if (peer_mss && child_ep->mtu > (peer_mss + 40)) | ||
| 1974 | child_ep->mtu = peer_mss + 40; | ||
| 1975 | |||
| 1697 | state_set(&child_ep->com, CONNECTING); | 1976 | state_set(&child_ep->com, CONNECTING); |
| 1698 | child_ep->com.dev = dev; | 1977 | child_ep->com.dev = dev; |
| 1699 | child_ep->com.cm_id = NULL; | 1978 | child_ep->com.cm_id = NULL; |
| @@ -1715,6 +1994,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1715 | init_timer(&child_ep->timer); | 1994 | init_timer(&child_ep->timer); |
| 1716 | cxgb4_insert_tid(t, child_ep, hwtid); | 1995 | cxgb4_insert_tid(t, child_ep, hwtid); |
| 1717 | accept_cr(child_ep, peer_ip, skb, req); | 1996 | accept_cr(child_ep, peer_ip, skb, req); |
| 1997 | set_bit(PASS_ACCEPT_REQ, &child_ep->com.history); | ||
| 1718 | goto out; | 1998 | goto out; |
| 1719 | reject: | 1999 | reject: |
| 1720 | reject_cr(dev, hwtid, peer_ip, skb); | 2000 | reject_cr(dev, hwtid, peer_ip, skb); |
| @@ -1734,12 +2014,17 @@ static int pass_establish(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1734 | ep->snd_seq = be32_to_cpu(req->snd_isn); | 2014 | ep->snd_seq = be32_to_cpu(req->snd_isn); |
| 1735 | ep->rcv_seq = be32_to_cpu(req->rcv_isn); | 2015 | ep->rcv_seq = be32_to_cpu(req->rcv_isn); |
| 1736 | 2016 | ||
| 2017 | PDBG("%s ep %p hwtid %u tcp_opt 0x%02x\n", __func__, ep, tid, | ||
| 2018 | ntohs(req->tcp_opt)); | ||
| 2019 | |||
| 1737 | set_emss(ep, ntohs(req->tcp_opt)); | 2020 | set_emss(ep, ntohs(req->tcp_opt)); |
| 2021 | insert_handle(dev, &dev->hwtid_idr, ep, ep->hwtid); | ||
| 1738 | 2022 | ||
| 1739 | dst_confirm(ep->dst); | 2023 | dst_confirm(ep->dst); |
| 1740 | state_set(&ep->com, MPA_REQ_WAIT); | 2024 | state_set(&ep->com, MPA_REQ_WAIT); |
| 1741 | start_ep_timer(ep); | 2025 | start_ep_timer(ep); |
| 1742 | send_flowc(ep, skb); | 2026 | send_flowc(ep, skb); |
| 2027 | set_bit(PASS_ESTAB, &ep->com.history); | ||
| 1743 | 2028 | ||
| 1744 | return 0; | 2029 | return 0; |
| 1745 | } | 2030 | } |
| @@ -1759,6 +2044,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1759 | PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); | 2044 | PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); |
| 1760 | dst_confirm(ep->dst); | 2045 | dst_confirm(ep->dst); |
| 1761 | 2046 | ||
| 2047 | set_bit(PEER_CLOSE, &ep->com.history); | ||
| 1762 | mutex_lock(&ep->com.mutex); | 2048 | mutex_lock(&ep->com.mutex); |
| 1763 | switch (ep->com.state) { | 2049 | switch (ep->com.state) { |
| 1764 | case MPA_REQ_WAIT: | 2050 | case MPA_REQ_WAIT: |
| @@ -1838,74 +2124,6 @@ static int is_neg_adv_abort(unsigned int status) | |||
| 1838 | status == CPL_ERR_PERSIST_NEG_ADVICE; | 2124 | status == CPL_ERR_PERSIST_NEG_ADVICE; |
| 1839 | } | 2125 | } |
| 1840 | 2126 | ||
| 1841 | static int c4iw_reconnect(struct c4iw_ep *ep) | ||
| 1842 | { | ||
| 1843 | struct rtable *rt; | ||
| 1844 | int err = 0; | ||
| 1845 | |||
| 1846 | PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id); | ||
| 1847 | init_timer(&ep->timer); | ||
| 1848 | |||
| 1849 | /* | ||
| 1850 | * Allocate an active TID to initiate a TCP connection. | ||
| 1851 | */ | ||
| 1852 | ep->atid = cxgb4_alloc_atid(ep->com.dev->rdev.lldi.tids, ep); | ||
| 1853 | if (ep->atid == -1) { | ||
| 1854 | printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__); | ||
| 1855 | err = -ENOMEM; | ||
| 1856 | goto fail2; | ||
| 1857 | } | ||
| 1858 | |||
| 1859 | /* find a route */ | ||
| 1860 | rt = find_route(ep->com.dev, | ||
| 1861 | ep->com.cm_id->local_addr.sin_addr.s_addr, | ||
| 1862 | ep->com.cm_id->remote_addr.sin_addr.s_addr, | ||
| 1863 | ep->com.cm_id->local_addr.sin_port, | ||
| 1864 | ep->com.cm_id->remote_addr.sin_port, 0); | ||
| 1865 | if (!rt) { | ||
| 1866 | printk(KERN_ERR MOD "%s - cannot find route.\n", __func__); | ||
| 1867 | err = -EHOSTUNREACH; | ||
| 1868 | goto fail3; | ||
| 1869 | } | ||
| 1870 | ep->dst = &rt->dst; | ||
| 1871 | |||
| 1872 | err = import_ep(ep, ep->com.cm_id->remote_addr.sin_addr.s_addr, | ||
| 1873 | ep->dst, ep->com.dev, false); | ||
| 1874 | if (err) { | ||
| 1875 | printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); | ||
| 1876 | goto fail4; | ||
| 1877 | } | ||
| 1878 | |||
| 1879 | PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n", | ||
| 1880 | __func__, ep->txq_idx, ep->tx_chan, ep->smac_idx, ep->rss_qid, | ||
| 1881 | ep->l2t->idx); | ||
| 1882 | |||
| 1883 | state_set(&ep->com, CONNECTING); | ||
| 1884 | ep->tos = 0; | ||
| 1885 | |||
| 1886 | /* send connect request to rnic */ | ||
| 1887 | err = send_connect(ep); | ||
| 1888 | if (!err) | ||
| 1889 | goto out; | ||
| 1890 | |||
| 1891 | cxgb4_l2t_release(ep->l2t); | ||
| 1892 | fail4: | ||
| 1893 | dst_release(ep->dst); | ||
| 1894 | fail3: | ||
| 1895 | cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); | ||
| 1896 | fail2: | ||
| 1897 | /* | ||
| 1898 | * remember to send notification to upper layer. | ||
| 1899 | * We are in here so the upper layer is not aware that this is | ||
| 1900 | * re-connect attempt and so, upper layer is still waiting for | ||
| 1901 | * response of 1st connect request. | ||
| 1902 | */ | ||
| 1903 | connect_reply_upcall(ep, -ECONNRESET); | ||
| 1904 | c4iw_put_ep(&ep->com); | ||
| 1905 | out: | ||
| 1906 | return err; | ||
| 1907 | } | ||
| 1908 | |||
| 1909 | static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) | 2127 | static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) |
| 1910 | { | 2128 | { |
| 1911 | struct cpl_abort_req_rss *req = cplhdr(skb); | 2129 | struct cpl_abort_req_rss *req = cplhdr(skb); |
| @@ -1926,6 +2144,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 1926 | } | 2144 | } |
| 1927 | PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, | 2145 | PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid, |
| 1928 | ep->com.state); | 2146 | ep->com.state); |
| 2147 | set_bit(PEER_ABORT, &ep->com.history); | ||
| 1929 | 2148 | ||
| 1930 | /* | 2149 | /* |
| 1931 | * Wake up any threads in rdma_init() or rdma_fini(). | 2150 | * Wake up any threads in rdma_init() or rdma_fini(). |
| @@ -2140,6 +2359,7 @@ int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) | |||
| 2140 | c4iw_put_ep(&ep->com); | 2359 | c4iw_put_ep(&ep->com); |
| 2141 | return -ECONNRESET; | 2360 | return -ECONNRESET; |
| 2142 | } | 2361 | } |
| 2362 | set_bit(ULP_REJECT, &ep->com.history); | ||
| 2143 | BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD); | 2363 | BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD); |
| 2144 | if (mpa_rev == 0) | 2364 | if (mpa_rev == 0) |
| 2145 | abort_connection(ep, NULL, GFP_KERNEL); | 2365 | abort_connection(ep, NULL, GFP_KERNEL); |
| @@ -2169,6 +2389,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
| 2169 | BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD); | 2389 | BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD); |
| 2170 | BUG_ON(!qp); | 2390 | BUG_ON(!qp); |
| 2171 | 2391 | ||
| 2392 | set_bit(ULP_ACCEPT, &ep->com.history); | ||
| 2172 | if ((conn_param->ord > c4iw_max_read_depth) || | 2393 | if ((conn_param->ord > c4iw_max_read_depth) || |
| 2173 | (conn_param->ird > c4iw_max_read_depth)) { | 2394 | (conn_param->ird > c4iw_max_read_depth)) { |
| 2174 | abort_connection(ep, NULL, GFP_KERNEL); | 2395 | abort_connection(ep, NULL, GFP_KERNEL); |
| @@ -2292,6 +2513,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
| 2292 | err = -ENOMEM; | 2513 | err = -ENOMEM; |
| 2293 | goto fail2; | 2514 | goto fail2; |
| 2294 | } | 2515 | } |
| 2516 | insert_handle(dev, &dev->atid_idr, ep, ep->atid); | ||
| 2295 | 2517 | ||
| 2296 | PDBG("%s saddr 0x%x sport 0x%x raddr 0x%x rport 0x%x\n", __func__, | 2518 | PDBG("%s saddr 0x%x sport 0x%x raddr 0x%x rport 0x%x\n", __func__, |
| 2297 | ntohl(cm_id->local_addr.sin_addr.s_addr), | 2519 | ntohl(cm_id->local_addr.sin_addr.s_addr), |
| @@ -2337,6 +2559,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) | |||
| 2337 | fail4: | 2559 | fail4: |
| 2338 | dst_release(ep->dst); | 2560 | dst_release(ep->dst); |
| 2339 | fail3: | 2561 | fail3: |
| 2562 | remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid); | ||
| 2340 | cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); | 2563 | cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid); |
| 2341 | fail2: | 2564 | fail2: |
| 2342 | cm_id->rem_ref(cm_id); | 2565 | cm_id->rem_ref(cm_id); |
| @@ -2351,7 +2574,6 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) | |||
| 2351 | struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); | 2574 | struct c4iw_dev *dev = to_c4iw_dev(cm_id->device); |
| 2352 | struct c4iw_listen_ep *ep; | 2575 | struct c4iw_listen_ep *ep; |
| 2353 | 2576 | ||
| 2354 | |||
| 2355 | might_sleep(); | 2577 | might_sleep(); |
| 2356 | 2578 | ||
| 2357 | ep = alloc_ep(sizeof(*ep), GFP_KERNEL); | 2579 | ep = alloc_ep(sizeof(*ep), GFP_KERNEL); |
| @@ -2370,30 +2592,54 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog) | |||
| 2370 | /* | 2592 | /* |
| 2371 | * Allocate a server TID. | 2593 | * Allocate a server TID. |
| 2372 | */ | 2594 | */ |
| 2373 | ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids, PF_INET, ep); | 2595 | if (dev->rdev.lldi.enable_fw_ofld_conn) |
| 2596 | ep->stid = cxgb4_alloc_sftid(dev->rdev.lldi.tids, PF_INET, ep); | ||
| 2597 | else | ||
| 2598 | ep->stid = cxgb4_alloc_stid(dev->rdev.lldi.tids, PF_INET, ep); | ||
| 2599 | |||
| 2374 | if (ep->stid == -1) { | 2600 | if (ep->stid == -1) { |
| 2375 | printk(KERN_ERR MOD "%s - cannot alloc stid.\n", __func__); | 2601 | printk(KERN_ERR MOD "%s - cannot alloc stid.\n", __func__); |
| 2376 | err = -ENOMEM; | 2602 | err = -ENOMEM; |
| 2377 | goto fail2; | 2603 | goto fail2; |
| 2378 | } | 2604 | } |
| 2379 | 2605 | insert_handle(dev, &dev->stid_idr, ep, ep->stid); | |
| 2380 | state_set(&ep->com, LISTEN); | 2606 | state_set(&ep->com, LISTEN); |
| 2381 | c4iw_init_wr_wait(&ep->com.wr_wait); | 2607 | if (dev->rdev.lldi.enable_fw_ofld_conn) { |
| 2382 | err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], ep->stid, | 2608 | do { |
| 2383 | ep->com.local_addr.sin_addr.s_addr, | 2609 | err = cxgb4_create_server_filter( |
| 2384 | ep->com.local_addr.sin_port, | 2610 | ep->com.dev->rdev.lldi.ports[0], ep->stid, |
| 2385 | ep->com.dev->rdev.lldi.rxq_ids[0]); | 2611 | ep->com.local_addr.sin_addr.s_addr, |
| 2386 | if (err) | 2612 | ep->com.local_addr.sin_port, |
| 2387 | goto fail3; | 2613 | 0, |
| 2388 | 2614 | ep->com.dev->rdev.lldi.rxq_ids[0], | |
| 2389 | /* wait for pass_open_rpl */ | 2615 | 0, |
| 2390 | err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 0, 0, | 2616 | 0); |
| 2391 | __func__); | 2617 | if (err == -EBUSY) { |
| 2618 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
| 2619 | schedule_timeout(usecs_to_jiffies(100)); | ||
| 2620 | } | ||
| 2621 | } while (err == -EBUSY); | ||
| 2622 | } else { | ||
| 2623 | c4iw_init_wr_wait(&ep->com.wr_wait); | ||
| 2624 | err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], | ||
| 2625 | ep->stid, ep->com.local_addr.sin_addr.s_addr, | ||
| 2626 | ep->com.local_addr.sin_port, | ||
| 2627 | 0, | ||
| 2628 | ep->com.dev->rdev.lldi.rxq_ids[0]); | ||
| 2629 | if (!err) | ||
| 2630 | err = c4iw_wait_for_reply(&ep->com.dev->rdev, | ||
| 2631 | &ep->com.wr_wait, | ||
| 2632 | 0, 0, __func__); | ||
| 2633 | } | ||
| 2392 | if (!err) { | 2634 | if (!err) { |
| 2393 | cm_id->provider_data = ep; | 2635 | cm_id->provider_data = ep; |
| 2394 | goto out; | 2636 | goto out; |
| 2395 | } | 2637 | } |
| 2396 | fail3: | 2638 | pr_err("%s cxgb4_create_server/filter failed err %d " \ |
| 2639 | "stid %d laddr %08x lport %d\n", \ | ||
| 2640 | __func__, err, ep->stid, | ||
| 2641 | ntohl(ep->com.local_addr.sin_addr.s_addr), | ||
| 2642 | ntohs(ep->com.local_addr.sin_port)); | ||
| 2397 | cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, PF_INET); | 2643 | cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, PF_INET); |
| 2398 | fail2: | 2644 | fail2: |
| 2399 | cm_id->rem_ref(cm_id); | 2645 | cm_id->rem_ref(cm_id); |
| @@ -2412,12 +2658,19 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id) | |||
| 2412 | 2658 | ||
| 2413 | might_sleep(); | 2659 | might_sleep(); |
| 2414 | state_set(&ep->com, DEAD); | 2660 | state_set(&ep->com, DEAD); |
| 2415 | c4iw_init_wr_wait(&ep->com.wr_wait); | 2661 | if (ep->com.dev->rdev.lldi.enable_fw_ofld_conn) { |
| 2416 | err = listen_stop(ep); | 2662 | err = cxgb4_remove_server_filter( |
| 2417 | if (err) | 2663 | ep->com.dev->rdev.lldi.ports[0], ep->stid, |
| 2418 | goto done; | 2664 | ep->com.dev->rdev.lldi.rxq_ids[0], 0); |
| 2419 | err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 0, 0, | 2665 | } else { |
| 2420 | __func__); | 2666 | c4iw_init_wr_wait(&ep->com.wr_wait); |
| 2667 | err = listen_stop(ep); | ||
| 2668 | if (err) | ||
| 2669 | goto done; | ||
| 2670 | err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, | ||
| 2671 | 0, 0, __func__); | ||
| 2672 | } | ||
| 2673 | remove_handle(ep->com.dev, &ep->com.dev->stid_idr, ep->stid); | ||
| 2421 | cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, PF_INET); | 2674 | cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, PF_INET); |
| 2422 | done: | 2675 | done: |
| 2423 | cm_id->rem_ref(cm_id); | 2676 | cm_id->rem_ref(cm_id); |
| @@ -2481,10 +2734,13 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) | |||
| 2481 | 2734 | ||
| 2482 | if (close) { | 2735 | if (close) { |
| 2483 | if (abrupt) { | 2736 | if (abrupt) { |
| 2737 | set_bit(EP_DISC_ABORT, &ep->com.history); | ||
| 2484 | close_complete_upcall(ep); | 2738 | close_complete_upcall(ep); |
| 2485 | ret = send_abort(ep, NULL, gfp); | 2739 | ret = send_abort(ep, NULL, gfp); |
| 2486 | } else | 2740 | } else { |
| 2741 | set_bit(EP_DISC_CLOSE, &ep->com.history); | ||
| 2487 | ret = send_halfclose(ep, gfp); | 2742 | ret = send_halfclose(ep, gfp); |
| 2743 | } | ||
| 2488 | if (ret) | 2744 | if (ret) |
| 2489 | fatal = 1; | 2745 | fatal = 1; |
| 2490 | } | 2746 | } |
| @@ -2494,10 +2750,323 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) | |||
| 2494 | return ret; | 2750 | return ret; |
| 2495 | } | 2751 | } |
| 2496 | 2752 | ||
| 2497 | static int async_event(struct c4iw_dev *dev, struct sk_buff *skb) | 2753 | static void active_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, |
| 2754 | struct cpl_fw6_msg_ofld_connection_wr_rpl *req) | ||
| 2755 | { | ||
| 2756 | struct c4iw_ep *ep; | ||
| 2757 | int atid = be32_to_cpu(req->tid); | ||
| 2758 | |||
| 2759 | ep = (struct c4iw_ep *)lookup_atid(dev->rdev.lldi.tids, req->tid); | ||
| 2760 | if (!ep) | ||
| 2761 | return; | ||
| 2762 | |||
| 2763 | switch (req->retval) { | ||
| 2764 | case FW_ENOMEM: | ||
| 2765 | set_bit(ACT_RETRY_NOMEM, &ep->com.history); | ||
| 2766 | if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { | ||
| 2767 | send_fw_act_open_req(ep, atid); | ||
| 2768 | return; | ||
| 2769 | } | ||
| 2770 | case FW_EADDRINUSE: | ||
| 2771 | set_bit(ACT_RETRY_INUSE, &ep->com.history); | ||
| 2772 | if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { | ||
| 2773 | send_fw_act_open_req(ep, atid); | ||
| 2774 | return; | ||
| 2775 | } | ||
| 2776 | break; | ||
| 2777 | default: | ||
| 2778 | pr_info("%s unexpected ofld conn wr retval %d\n", | ||
| 2779 | __func__, req->retval); | ||
| 2780 | break; | ||
| 2781 | } | ||
| 2782 | pr_err("active ofld_connect_wr failure %d atid %d\n", | ||
| 2783 | req->retval, atid); | ||
| 2784 | mutex_lock(&dev->rdev.stats.lock); | ||
| 2785 | dev->rdev.stats.act_ofld_conn_fails++; | ||
| 2786 | mutex_unlock(&dev->rdev.stats.lock); | ||
| 2787 | connect_reply_upcall(ep, status2errno(req->retval)); | ||
| 2788 | state_set(&ep->com, DEAD); | ||
| 2789 | remove_handle(dev, &dev->atid_idr, atid); | ||
| 2790 | cxgb4_free_atid(dev->rdev.lldi.tids, atid); | ||
| 2791 | dst_release(ep->dst); | ||
| 2792 | cxgb4_l2t_release(ep->l2t); | ||
| 2793 | c4iw_put_ep(&ep->com); | ||
| 2794 | } | ||
| 2795 | |||
| 2796 | static void passive_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, | ||
| 2797 | struct cpl_fw6_msg_ofld_connection_wr_rpl *req) | ||
| 2798 | { | ||
| 2799 | struct sk_buff *rpl_skb; | ||
| 2800 | struct cpl_pass_accept_req *cpl; | ||
| 2801 | int ret; | ||
| 2802 | |||
| 2803 | rpl_skb = (struct sk_buff *)cpu_to_be64(req->cookie); | ||
| 2804 | BUG_ON(!rpl_skb); | ||
| 2805 | if (req->retval) { | ||
| 2806 | PDBG("%s passive open failure %d\n", __func__, req->retval); | ||
| 2807 | mutex_lock(&dev->rdev.stats.lock); | ||
| 2808 | dev->rdev.stats.pas_ofld_conn_fails++; | ||
| 2809 | mutex_unlock(&dev->rdev.stats.lock); | ||
| 2810 | kfree_skb(rpl_skb); | ||
| 2811 | } else { | ||
| 2812 | cpl = (struct cpl_pass_accept_req *)cplhdr(rpl_skb); | ||
| 2813 | OPCODE_TID(cpl) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, | ||
| 2814 | htonl(req->tid))); | ||
| 2815 | ret = pass_accept_req(dev, rpl_skb); | ||
| 2816 | if (!ret) | ||
| 2817 | kfree_skb(rpl_skb); | ||
| 2818 | } | ||
| 2819 | return; | ||
| 2820 | } | ||
| 2821 | |||
| 2822 | static int deferred_fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) | ||
| 2498 | { | 2823 | { |
| 2499 | struct cpl_fw6_msg *rpl = cplhdr(skb); | 2824 | struct cpl_fw6_msg *rpl = cplhdr(skb); |
| 2500 | c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]); | 2825 | struct cpl_fw6_msg_ofld_connection_wr_rpl *req; |
| 2826 | |||
| 2827 | switch (rpl->type) { | ||
| 2828 | case FW6_TYPE_CQE: | ||
| 2829 | c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]); | ||
| 2830 | break; | ||
| 2831 | case FW6_TYPE_OFLD_CONNECTION_WR_RPL: | ||
| 2832 | req = (struct cpl_fw6_msg_ofld_connection_wr_rpl *)rpl->data; | ||
| 2833 | switch (req->t_state) { | ||
| 2834 | case TCP_SYN_SENT: | ||
| 2835 | active_ofld_conn_reply(dev, skb, req); | ||
| 2836 | break; | ||
| 2837 | case TCP_SYN_RECV: | ||
| 2838 | passive_ofld_conn_reply(dev, skb, req); | ||
| 2839 | break; | ||
| 2840 | default: | ||
| 2841 | pr_err("%s unexpected ofld conn wr state %d\n", | ||
| 2842 | __func__, req->t_state); | ||
| 2843 | break; | ||
| 2844 | } | ||
| 2845 | break; | ||
| 2846 | } | ||
| 2847 | return 0; | ||
| 2848 | } | ||
| 2849 | |||
| 2850 | static void build_cpl_pass_accept_req(struct sk_buff *skb, int stid , u8 tos) | ||
| 2851 | { | ||
| 2852 | u32 l2info; | ||
| 2853 | u16 vlantag, len, hdr_len; | ||
| 2854 | u8 intf; | ||
| 2855 | struct cpl_rx_pkt *cpl = cplhdr(skb); | ||
| 2856 | struct cpl_pass_accept_req *req; | ||
| 2857 | struct tcp_options_received tmp_opt; | ||
| 2858 | |||
| 2859 | /* Store values from cpl_rx_pkt in temporary location. */ | ||
| 2860 | vlantag = cpl->vlan; | ||
| 2861 | len = cpl->len; | ||
| 2862 | l2info = cpl->l2info; | ||
| 2863 | hdr_len = cpl->hdr_len; | ||
| 2864 | intf = cpl->iff; | ||
| 2865 | |||
| 2866 | __skb_pull(skb, sizeof(*req) + sizeof(struct rss_header)); | ||
| 2867 | |||
| 2868 | /* | ||
| 2869 | * We need to parse the TCP options from SYN packet. | ||
| 2870 | * to generate cpl_pass_accept_req. | ||
| 2871 | */ | ||
| 2872 | memset(&tmp_opt, 0, sizeof(tmp_opt)); | ||
| 2873 | tcp_clear_options(&tmp_opt); | ||
| 2874 | tcp_parse_options(skb, &tmp_opt, 0, 0, NULL); | ||
| 2875 | |||
| 2876 | req = (struct cpl_pass_accept_req *)__skb_push(skb, sizeof(*req)); | ||
| 2877 | memset(req, 0, sizeof(*req)); | ||
| 2878 | req->l2info = cpu_to_be16(V_SYN_INTF(intf) | | ||
| 2879 | V_SYN_MAC_IDX(G_RX_MACIDX(htonl(l2info))) | | ||
| 2880 | F_SYN_XACT_MATCH); | ||
| 2881 | req->hdr_len = cpu_to_be32(V_SYN_RX_CHAN(G_RX_CHAN(htonl(l2info))) | | ||
| 2882 | V_TCP_HDR_LEN(G_RX_TCPHDR_LEN(htons(hdr_len))) | | ||
| 2883 | V_IP_HDR_LEN(G_RX_IPHDR_LEN(htons(hdr_len))) | | ||
| 2884 | V_ETH_HDR_LEN(G_RX_ETHHDR_LEN(htonl(l2info)))); | ||
| 2885 | req->vlan = vlantag; | ||
| 2886 | req->len = len; | ||
| 2887 | req->tos_stid = cpu_to_be32(PASS_OPEN_TID(stid) | | ||
| 2888 | PASS_OPEN_TOS(tos)); | ||
| 2889 | req->tcpopt.mss = htons(tmp_opt.mss_clamp); | ||
| 2890 | if (tmp_opt.wscale_ok) | ||
| 2891 | req->tcpopt.wsf = tmp_opt.snd_wscale; | ||
| 2892 | req->tcpopt.tstamp = tmp_opt.saw_tstamp; | ||
| 2893 | if (tmp_opt.sack_ok) | ||
| 2894 | req->tcpopt.sack = 1; | ||
| 2895 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_ACCEPT_REQ, 0)); | ||
| 2896 | return; | ||
| 2897 | } | ||
| 2898 | |||
| 2899 | static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb, | ||
| 2900 | __be32 laddr, __be16 lport, | ||
| 2901 | __be32 raddr, __be16 rport, | ||
| 2902 | u32 rcv_isn, u32 filter, u16 window, | ||
| 2903 | u32 rss_qid, u8 port_id) | ||
| 2904 | { | ||
| 2905 | struct sk_buff *req_skb; | ||
| 2906 | struct fw_ofld_connection_wr *req; | ||
| 2907 | struct cpl_pass_accept_req *cpl = cplhdr(skb); | ||
| 2908 | |||
| 2909 | req_skb = alloc_skb(sizeof(struct fw_ofld_connection_wr), GFP_KERNEL); | ||
| 2910 | req = (struct fw_ofld_connection_wr *)__skb_put(req_skb, sizeof(*req)); | ||
| 2911 | memset(req, 0, sizeof(*req)); | ||
| 2912 | req->op_compl = htonl(V_WR_OP(FW_OFLD_CONNECTION_WR) | FW_WR_COMPL(1)); | ||
| 2913 | req->len16_pkd = htonl(FW_WR_LEN16(DIV_ROUND_UP(sizeof(*req), 16))); | ||
| 2914 | req->le.version_cpl = htonl(F_FW_OFLD_CONNECTION_WR_CPL); | ||
| 2915 | req->le.filter = filter; | ||
| 2916 | req->le.lport = lport; | ||
| 2917 | req->le.pport = rport; | ||
| 2918 | req->le.u.ipv4.lip = laddr; | ||
| 2919 | req->le.u.ipv4.pip = raddr; | ||
| 2920 | req->tcb.rcv_nxt = htonl(rcv_isn + 1); | ||
| 2921 | req->tcb.rcv_adv = htons(window); | ||
| 2922 | req->tcb.t_state_to_astid = | ||
| 2923 | htonl(V_FW_OFLD_CONNECTION_WR_T_STATE(TCP_SYN_RECV) | | ||
| 2924 | V_FW_OFLD_CONNECTION_WR_RCV_SCALE(cpl->tcpopt.wsf) | | ||
| 2925 | V_FW_OFLD_CONNECTION_WR_ASTID( | ||
| 2926 | GET_PASS_OPEN_TID(ntohl(cpl->tos_stid)))); | ||
| 2927 | |||
| 2928 | /* | ||
| 2929 | * We store the qid in opt2 which will be used by the firmware | ||
| 2930 | * to send us the wr response. | ||
| 2931 | */ | ||
| 2932 | req->tcb.opt2 = htonl(V_RSS_QUEUE(rss_qid)); | ||
| 2933 | |||
| 2934 | /* | ||
| 2935 | * We initialize the MSS index in TCB to 0xF. | ||
| 2936 | * So that when driver sends cpl_pass_accept_rpl | ||
| 2937 | * TCB picks up the correct value. If this was 0 | ||
| 2938 | * TP will ignore any value > 0 for MSS index. | ||
| 2939 | */ | ||
| 2940 | req->tcb.opt0 = cpu_to_be64(V_MSS_IDX(0xF)); | ||
| 2941 | req->cookie = cpu_to_be64((u64)skb); | ||
| 2942 | |||
| 2943 | set_wr_txq(req_skb, CPL_PRIORITY_CONTROL, port_id); | ||
| 2944 | cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb); | ||
| 2945 | } | ||
| 2946 | |||
| 2947 | /* | ||
| 2948 | * Handler for CPL_RX_PKT message. Need to handle cpl_rx_pkt | ||
| 2949 | * messages when a filter is being used instead of server to | ||
| 2950 | * redirect a syn packet. When packets hit filter they are redirected | ||
| 2951 | * to the offload queue and driver tries to establish the connection | ||
| 2952 | * using firmware work request. | ||
| 2953 | */ | ||
| 2954 | static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb) | ||
| 2955 | { | ||
| 2956 | int stid; | ||
| 2957 | unsigned int filter; | ||
| 2958 | struct ethhdr *eh = NULL; | ||
| 2959 | struct vlan_ethhdr *vlan_eh = NULL; | ||
| 2960 | struct iphdr *iph; | ||
| 2961 | struct tcphdr *tcph; | ||
| 2962 | struct rss_header *rss = (void *)skb->data; | ||
| 2963 | struct cpl_rx_pkt *cpl = (void *)skb->data; | ||
| 2964 | struct cpl_pass_accept_req *req = (void *)(rss + 1); | ||
| 2965 | struct l2t_entry *e; | ||
| 2966 | struct dst_entry *dst; | ||
| 2967 | struct rtable *rt; | ||
| 2968 | struct c4iw_ep *lep; | ||
| 2969 | u16 window; | ||
| 2970 | struct port_info *pi; | ||
| 2971 | struct net_device *pdev; | ||
| 2972 | u16 rss_qid; | ||
| 2973 | int step; | ||
| 2974 | u32 tx_chan; | ||
| 2975 | struct neighbour *neigh; | ||
| 2976 | |||
| 2977 | /* Drop all non-SYN packets */ | ||
| 2978 | if (!(cpl->l2info & cpu_to_be32(F_RXF_SYN))) | ||
| 2979 | goto reject; | ||
| 2980 | |||
| 2981 | /* | ||
| 2982 | * Drop all packets which did not hit the filter. | ||
| 2983 | * Unlikely to happen. | ||
| 2984 | */ | ||
| 2985 | if (!(rss->filter_hit && rss->filter_tid)) | ||
| 2986 | goto reject; | ||
| 2987 | |||
| 2988 | /* | ||
| 2989 | * Calculate the server tid from filter hit index from cpl_rx_pkt. | ||
| 2990 | */ | ||
| 2991 | stid = cpu_to_be32(rss->hash_val) - dev->rdev.lldi.tids->sftid_base | ||
| 2992 | + dev->rdev.lldi.tids->nstids; | ||
| 2993 | |||
| 2994 | lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid); | ||
| 2995 | if (!lep) { | ||
| 2996 | PDBG("%s connect request on invalid stid %d\n", __func__, stid); | ||
| 2997 | goto reject; | ||
| 2998 | } | ||
| 2999 | |||
| 3000 | if (G_RX_ETHHDR_LEN(ntohl(cpl->l2info)) == ETH_HLEN) { | ||
| 3001 | eh = (struct ethhdr *)(req + 1); | ||
| 3002 | iph = (struct iphdr *)(eh + 1); | ||
| 3003 | } else { | ||
| 3004 | vlan_eh = (struct vlan_ethhdr *)(req + 1); | ||
| 3005 | iph = (struct iphdr *)(vlan_eh + 1); | ||
| 3006 | skb->vlan_tci = ntohs(cpl->vlan); | ||
| 3007 | } | ||
| 3008 | |||
| 3009 | if (iph->version != 0x4) | ||
| 3010 | goto reject; | ||
| 3011 | |||
| 3012 | tcph = (struct tcphdr *)(iph + 1); | ||
| 3013 | skb_set_network_header(skb, (void *)iph - (void *)rss); | ||
| 3014 | skb_set_transport_header(skb, (void *)tcph - (void *)rss); | ||
| 3015 | skb_get(skb); | ||
| 3016 | |||
| 3017 | PDBG("%s lip 0x%x lport %u pip 0x%x pport %u tos %d\n", __func__, | ||
| 3018 | ntohl(iph->daddr), ntohs(tcph->dest), ntohl(iph->saddr), | ||
| 3019 | ntohs(tcph->source), iph->tos); | ||
| 3020 | |||
| 3021 | rt = find_route(dev, iph->daddr, iph->saddr, tcph->dest, tcph->source, | ||
| 3022 | iph->tos); | ||
| 3023 | if (!rt) { | ||
| 3024 | pr_err("%s - failed to find dst entry!\n", | ||
| 3025 | __func__); | ||
| 3026 | goto reject; | ||
| 3027 | } | ||
| 3028 | dst = &rt->dst; | ||
| 3029 | neigh = dst_neigh_lookup_skb(dst, skb); | ||
| 3030 | |||
| 3031 | if (neigh->dev->flags & IFF_LOOPBACK) { | ||
| 3032 | pdev = ip_dev_find(&init_net, iph->daddr); | ||
| 3033 | e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, | ||
| 3034 | pdev, 0); | ||
| 3035 | pi = (struct port_info *)netdev_priv(pdev); | ||
| 3036 | tx_chan = cxgb4_port_chan(pdev); | ||
| 3037 | dev_put(pdev); | ||
| 3038 | } else { | ||
| 3039 | e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, | ||
| 3040 | neigh->dev, 0); | ||
| 3041 | pi = (struct port_info *)netdev_priv(neigh->dev); | ||
| 3042 | tx_chan = cxgb4_port_chan(neigh->dev); | ||
| 3043 | } | ||
| 3044 | if (!e) { | ||
| 3045 | pr_err("%s - failed to allocate l2t entry!\n", | ||
| 3046 | __func__); | ||
| 3047 | goto free_dst; | ||
| 3048 | } | ||
| 3049 | |||
| 3050 | step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan; | ||
| 3051 | rss_qid = dev->rdev.lldi.rxq_ids[pi->port_id * step]; | ||
| 3052 | window = htons(tcph->window); | ||
| 3053 | |||
| 3054 | /* Calcuate filter portion for LE region. */ | ||
| 3055 | filter = cpu_to_be32(select_ntuple(dev, dst, e)); | ||
| 3056 | |||
| 3057 | /* | ||
| 3058 | * Synthesize the cpl_pass_accept_req. We have everything except the | ||
| 3059 | * TID. Once firmware sends a reply with TID we update the TID field | ||
| 3060 | * in cpl and pass it through the regular cpl_pass_accept_req path. | ||
| 3061 | */ | ||
| 3062 | build_cpl_pass_accept_req(skb, stid, iph->tos); | ||
| 3063 | send_fw_pass_open_req(dev, skb, iph->daddr, tcph->dest, iph->saddr, | ||
| 3064 | tcph->source, ntohl(tcph->seq), filter, window, | ||
| 3065 | rss_qid, pi->port_id); | ||
| 3066 | cxgb4_l2t_release(e); | ||
| 3067 | free_dst: | ||
| 3068 | dst_release(dst); | ||
| 3069 | reject: | ||
| 2501 | return 0; | 3070 | return 0; |
| 2502 | } | 3071 | } |
| 2503 | 3072 | ||
| @@ -2520,7 +3089,8 @@ static c4iw_handler_func work_handlers[NUM_CPL_CMDS] = { | |||
| 2520 | [CPL_CLOSE_CON_RPL] = close_con_rpl, | 3089 | [CPL_CLOSE_CON_RPL] = close_con_rpl, |
| 2521 | [CPL_RDMA_TERMINATE] = terminate, | 3090 | [CPL_RDMA_TERMINATE] = terminate, |
| 2522 | [CPL_FW4_ACK] = fw4_ack, | 3091 | [CPL_FW4_ACK] = fw4_ack, |
| 2523 | [CPL_FW6_MSG] = async_event | 3092 | [CPL_FW6_MSG] = deferred_fw6_msg, |
| 3093 | [CPL_RX_PKT] = rx_pkt | ||
| 2524 | }; | 3094 | }; |
| 2525 | 3095 | ||
| 2526 | static void process_timeout(struct c4iw_ep *ep) | 3096 | static void process_timeout(struct c4iw_ep *ep) |
| @@ -2531,6 +3101,7 @@ static void process_timeout(struct c4iw_ep *ep) | |||
| 2531 | mutex_lock(&ep->com.mutex); | 3101 | mutex_lock(&ep->com.mutex); |
| 2532 | PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid, | 3102 | PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid, |
| 2533 | ep->com.state); | 3103 | ep->com.state); |
| 3104 | set_bit(TIMEDOUT, &ep->com.history); | ||
| 2534 | switch (ep->com.state) { | 3105 | switch (ep->com.state) { |
| 2535 | case MPA_REQ_SENT: | 3106 | case MPA_REQ_SENT: |
| 2536 | __state_set(&ep->com, ABORTING); | 3107 | __state_set(&ep->com, ABORTING); |
| @@ -2651,7 +3222,7 @@ static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 2651 | PDBG("%s type %u\n", __func__, rpl->type); | 3222 | PDBG("%s type %u\n", __func__, rpl->type); |
| 2652 | 3223 | ||
| 2653 | switch (rpl->type) { | 3224 | switch (rpl->type) { |
| 2654 | case 1: | 3225 | case FW6_TYPE_WR_RPL: |
| 2655 | ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff); | 3226 | ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff); |
| 2656 | wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1]; | 3227 | wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1]; |
| 2657 | PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret); | 3228 | PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret); |
| @@ -2659,7 +3230,8 @@ static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb) | |||
| 2659 | c4iw_wake_up(wr_waitp, ret ? -ret : 0); | 3230 | c4iw_wake_up(wr_waitp, ret ? -ret : 0); |
| 2660 | kfree_skb(skb); | 3231 | kfree_skb(skb); |
| 2661 | break; | 3232 | break; |
| 2662 | case 2: | 3233 | case FW6_TYPE_CQE: |
| 3234 | case FW6_TYPE_OFLD_CONNECTION_WR_RPL: | ||
| 2663 | sched(dev, skb); | 3235 | sched(dev, skb); |
| 2664 | break; | 3236 | break; |
| 2665 | default: | 3237 | default: |
| @@ -2722,7 +3294,8 @@ c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS] = { | |||
| 2722 | [CPL_RDMA_TERMINATE] = sched, | 3294 | [CPL_RDMA_TERMINATE] = sched, |
| 2723 | [CPL_FW4_ACK] = sched, | 3295 | [CPL_FW4_ACK] = sched, |
| 2724 | [CPL_SET_TCB_RPL] = set_tcb_rpl, | 3296 | [CPL_SET_TCB_RPL] = set_tcb_rpl, |
| 2725 | [CPL_FW6_MSG] = fw6_msg | 3297 | [CPL_FW6_MSG] = fw6_msg, |
| 3298 | [CPL_RX_PKT] = sched | ||
| 2726 | }; | 3299 | }; |
| 2727 | 3300 | ||
| 2728 | int __init c4iw_cm_init(void) | 3301 | int __init c4iw_cm_init(void) |
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index cb4ecd783700..ba11c76c0b5a 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c | |||
| @@ -279,6 +279,11 @@ static int stats_show(struct seq_file *seq, void *v) | |||
| 279 | seq_printf(seq, " DB State: %s Transitions %llu\n", | 279 | seq_printf(seq, " DB State: %s Transitions %llu\n", |
| 280 | db_state_str[dev->db_state], | 280 | db_state_str[dev->db_state], |
| 281 | dev->rdev.stats.db_state_transitions); | 281 | dev->rdev.stats.db_state_transitions); |
| 282 | seq_printf(seq, "TCAM_FULL: %10llu\n", dev->rdev.stats.tcam_full); | ||
| 283 | seq_printf(seq, "ACT_OFLD_CONN_FAILS: %10llu\n", | ||
| 284 | dev->rdev.stats.act_ofld_conn_fails); | ||
| 285 | seq_printf(seq, "PAS_OFLD_CONN_FAILS: %10llu\n", | ||
| 286 | dev->rdev.stats.pas_ofld_conn_fails); | ||
| 282 | return 0; | 287 | return 0; |
| 283 | } | 288 | } |
| 284 | 289 | ||
| @@ -309,6 +314,9 @@ static ssize_t stats_clear(struct file *file, const char __user *buf, | |||
| 309 | dev->rdev.stats.db_empty = 0; | 314 | dev->rdev.stats.db_empty = 0; |
| 310 | dev->rdev.stats.db_drop = 0; | 315 | dev->rdev.stats.db_drop = 0; |
| 311 | dev->rdev.stats.db_state_transitions = 0; | 316 | dev->rdev.stats.db_state_transitions = 0; |
| 317 | dev->rdev.stats.tcam_full = 0; | ||
| 318 | dev->rdev.stats.act_ofld_conn_fails = 0; | ||
| 319 | dev->rdev.stats.pas_ofld_conn_fails = 0; | ||
| 312 | mutex_unlock(&dev->rdev.stats.lock); | 320 | mutex_unlock(&dev->rdev.stats.lock); |
| 313 | return count; | 321 | return count; |
| 314 | } | 322 | } |
| @@ -322,6 +330,113 @@ static const struct file_operations stats_debugfs_fops = { | |||
| 322 | .write = stats_clear, | 330 | .write = stats_clear, |
| 323 | }; | 331 | }; |
| 324 | 332 | ||
| 333 | static int dump_ep(int id, void *p, void *data) | ||
| 334 | { | ||
| 335 | struct c4iw_ep *ep = p; | ||
| 336 | struct c4iw_debugfs_data *epd = data; | ||
| 337 | int space; | ||
| 338 | int cc; | ||
| 339 | |||
| 340 | space = epd->bufsize - epd->pos - 1; | ||
| 341 | if (space == 0) | ||
| 342 | return 1; | ||
| 343 | |||
| 344 | cc = snprintf(epd->buf + epd->pos, space, | ||
| 345 | "ep %p cm_id %p qp %p state %d flags 0x%lx history 0x%lx " | ||
| 346 | "hwtid %d atid %d %pI4:%d <-> %pI4:%d\n", | ||
| 347 | ep, ep->com.cm_id, ep->com.qp, (int)ep->com.state, | ||
| 348 | ep->com.flags, ep->com.history, ep->hwtid, ep->atid, | ||
| 349 | &ep->com.local_addr.sin_addr.s_addr, | ||
| 350 | ntohs(ep->com.local_addr.sin_port), | ||
| 351 | &ep->com.remote_addr.sin_addr.s_addr, | ||
| 352 | ntohs(ep->com.remote_addr.sin_port)); | ||
| 353 | if (cc < space) | ||
| 354 | epd->pos += cc; | ||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static int dump_listen_ep(int id, void *p, void *data) | ||
| 359 | { | ||
| 360 | struct c4iw_listen_ep *ep = p; | ||
| 361 | struct c4iw_debugfs_data *epd = data; | ||
| 362 | int space; | ||
| 363 | int cc; | ||
| 364 | |||
| 365 | space = epd->bufsize - epd->pos - 1; | ||
| 366 | if (space == 0) | ||
| 367 | return 1; | ||
| 368 | |||
| 369 | cc = snprintf(epd->buf + epd->pos, space, | ||
| 370 | "ep %p cm_id %p state %d flags 0x%lx stid %d backlog %d " | ||
| 371 | "%pI4:%d\n", ep, ep->com.cm_id, (int)ep->com.state, | ||
| 372 | ep->com.flags, ep->stid, ep->backlog, | ||
| 373 | &ep->com.local_addr.sin_addr.s_addr, | ||
| 374 | ntohs(ep->com.local_addr.sin_port)); | ||
| 375 | if (cc < space) | ||
| 376 | epd->pos += cc; | ||
| 377 | return 0; | ||
| 378 | } | ||
| 379 | |||
| 380 | static int ep_release(struct inode *inode, struct file *file) | ||
| 381 | { | ||
| 382 | struct c4iw_debugfs_data *epd = file->private_data; | ||
| 383 | if (!epd) { | ||
| 384 | pr_info("%s null qpd?\n", __func__); | ||
| 385 | return 0; | ||
| 386 | } | ||
| 387 | vfree(epd->buf); | ||
| 388 | kfree(epd); | ||
| 389 | return 0; | ||
| 390 | } | ||
| 391 | |||
| 392 | static int ep_open(struct inode *inode, struct file *file) | ||
| 393 | { | ||
| 394 | struct c4iw_debugfs_data *epd; | ||
| 395 | int ret = 0; | ||
| 396 | int count = 1; | ||
| 397 | |||
| 398 | epd = kmalloc(sizeof(*epd), GFP_KERNEL); | ||
| 399 | if (!epd) { | ||
| 400 | ret = -ENOMEM; | ||
| 401 | goto out; | ||
| 402 | } | ||
| 403 | epd->devp = inode->i_private; | ||
| 404 | epd->pos = 0; | ||
| 405 | |||
| 406 | spin_lock_irq(&epd->devp->lock); | ||
| 407 | idr_for_each(&epd->devp->hwtid_idr, count_idrs, &count); | ||
| 408 | idr_for_each(&epd->devp->atid_idr, count_idrs, &count); | ||
| 409 | idr_for_each(&epd->devp->stid_idr, count_idrs, &count); | ||
| 410 | spin_unlock_irq(&epd->devp->lock); | ||
| 411 | |||
| 412 | epd->bufsize = count * 160; | ||
| 413 | epd->buf = vmalloc(epd->bufsize); | ||
| 414 | if (!epd->buf) { | ||
| 415 | ret = -ENOMEM; | ||
| 416 | goto err1; | ||
| 417 | } | ||
| 418 | |||
| 419 | spin_lock_irq(&epd->devp->lock); | ||
| 420 | idr_for_each(&epd->devp->hwtid_idr, dump_ep, epd); | ||
| 421 | idr_for_each(&epd->devp->atid_idr, dump_ep, epd); | ||
| 422 | idr_for_each(&epd->devp->stid_idr, dump_listen_ep, epd); | ||
| 423 | spin_unlock_irq(&epd->devp->lock); | ||
| 424 | |||
| 425 | file->private_data = epd; | ||
| 426 | goto out; | ||
| 427 | err1: | ||
| 428 | kfree(epd); | ||
| 429 | out: | ||
| 430 | return ret; | ||
| 431 | } | ||
| 432 | |||
| 433 | static const struct file_operations ep_debugfs_fops = { | ||
| 434 | .owner = THIS_MODULE, | ||
| 435 | .open = ep_open, | ||
| 436 | .release = ep_release, | ||
| 437 | .read = debugfs_read, | ||
| 438 | }; | ||
| 439 | |||
| 325 | static int setup_debugfs(struct c4iw_dev *devp) | 440 | static int setup_debugfs(struct c4iw_dev *devp) |
| 326 | { | 441 | { |
| 327 | struct dentry *de; | 442 | struct dentry *de; |
| @@ -344,6 +459,11 @@ static int setup_debugfs(struct c4iw_dev *devp) | |||
| 344 | if (de && de->d_inode) | 459 | if (de && de->d_inode) |
| 345 | de->d_inode->i_size = 4096; | 460 | de->d_inode->i_size = 4096; |
| 346 | 461 | ||
| 462 | de = debugfs_create_file("eps", S_IWUSR, devp->debugfs_root, | ||
| 463 | (void *)devp, &ep_debugfs_fops); | ||
| 464 | if (de && de->d_inode) | ||
| 465 | de->d_inode->i_size = 4096; | ||
| 466 | |||
| 347 | return 0; | 467 | return 0; |
| 348 | } | 468 | } |
| 349 | 469 | ||
| @@ -475,6 +595,9 @@ static void c4iw_dealloc(struct uld_ctx *ctx) | |||
| 475 | idr_destroy(&ctx->dev->cqidr); | 595 | idr_destroy(&ctx->dev->cqidr); |
| 476 | idr_destroy(&ctx->dev->qpidr); | 596 | idr_destroy(&ctx->dev->qpidr); |
| 477 | idr_destroy(&ctx->dev->mmidr); | 597 | idr_destroy(&ctx->dev->mmidr); |
| 598 | idr_destroy(&ctx->dev->hwtid_idr); | ||
| 599 | idr_destroy(&ctx->dev->stid_idr); | ||
| 600 | idr_destroy(&ctx->dev->atid_idr); | ||
| 478 | iounmap(ctx->dev->rdev.oc_mw_kva); | 601 | iounmap(ctx->dev->rdev.oc_mw_kva); |
| 479 | ib_dealloc_device(&ctx->dev->ibdev); | 602 | ib_dealloc_device(&ctx->dev->ibdev); |
| 480 | ctx->dev = NULL; | 603 | ctx->dev = NULL; |
| @@ -532,6 +655,9 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop) | |||
| 532 | idr_init(&devp->cqidr); | 655 | idr_init(&devp->cqidr); |
| 533 | idr_init(&devp->qpidr); | 656 | idr_init(&devp->qpidr); |
| 534 | idr_init(&devp->mmidr); | 657 | idr_init(&devp->mmidr); |
| 658 | idr_init(&devp->hwtid_idr); | ||
| 659 | idr_init(&devp->stid_idr); | ||
| 660 | idr_init(&devp->atid_idr); | ||
| 535 | spin_lock_init(&devp->lock); | 661 | spin_lock_init(&devp->lock); |
| 536 | mutex_init(&devp->rdev.stats.lock); | 662 | mutex_init(&devp->rdev.stats.lock); |
| 537 | mutex_init(&devp->db_mutex); | 663 | mutex_init(&devp->db_mutex); |
| @@ -577,14 +703,76 @@ out: | |||
| 577 | return ctx; | 703 | return ctx; |
| 578 | } | 704 | } |
| 579 | 705 | ||
| 706 | static inline struct sk_buff *copy_gl_to_skb_pkt(const struct pkt_gl *gl, | ||
| 707 | const __be64 *rsp, | ||
| 708 | u32 pktshift) | ||
| 709 | { | ||
| 710 | struct sk_buff *skb; | ||
| 711 | |||
| 712 | /* | ||
| 713 | * Allocate space for cpl_pass_accept_req which will be synthesized by | ||
| 714 | * driver. Once the driver synthesizes the request the skb will go | ||
| 715 | * through the regular cpl_pass_accept_req processing. | ||
| 716 | * The math here assumes sizeof cpl_pass_accept_req >= sizeof | ||
| 717 | * cpl_rx_pkt. | ||
| 718 | */ | ||
| 719 | skb = alloc_skb(gl->tot_len + sizeof(struct cpl_pass_accept_req) + | ||
| 720 | sizeof(struct rss_header) - pktshift, GFP_ATOMIC); | ||
| 721 | if (unlikely(!skb)) | ||
| 722 | return NULL; | ||
| 723 | |||
| 724 | __skb_put(skb, gl->tot_len + sizeof(struct cpl_pass_accept_req) + | ||
| 725 | sizeof(struct rss_header) - pktshift); | ||
| 726 | |||
| 727 | /* | ||
| 728 | * This skb will contain: | ||
| 729 | * rss_header from the rspq descriptor (1 flit) | ||
| 730 | * cpl_rx_pkt struct from the rspq descriptor (2 flits) | ||
| 731 | * space for the difference between the size of an | ||
| 732 | * rx_pkt and pass_accept_req cpl (1 flit) | ||
| 733 | * the packet data from the gl | ||
| 734 | */ | ||
| 735 | skb_copy_to_linear_data(skb, rsp, sizeof(struct cpl_pass_accept_req) + | ||
| 736 | sizeof(struct rss_header)); | ||
| 737 | skb_copy_to_linear_data_offset(skb, sizeof(struct rss_header) + | ||
| 738 | sizeof(struct cpl_pass_accept_req), | ||
| 739 | gl->va + pktshift, | ||
| 740 | gl->tot_len - pktshift); | ||
| 741 | return skb; | ||
| 742 | } | ||
| 743 | |||
| 744 | static inline int recv_rx_pkt(struct c4iw_dev *dev, const struct pkt_gl *gl, | ||
| 745 | const __be64 *rsp) | ||
| 746 | { | ||
| 747 | unsigned int opcode = *(u8 *)rsp; | ||
| 748 | struct sk_buff *skb; | ||
| 749 | |||
| 750 | if (opcode != CPL_RX_PKT) | ||
| 751 | goto out; | ||
| 752 | |||
| 753 | skb = copy_gl_to_skb_pkt(gl , rsp, dev->rdev.lldi.sge_pktshift); | ||
| 754 | if (skb == NULL) | ||
| 755 | goto out; | ||
| 756 | |||
| 757 | if (c4iw_handlers[opcode] == NULL) { | ||
| 758 | pr_info("%s no handler opcode 0x%x...\n", __func__, | ||
| 759 | opcode); | ||
| 760 | kfree_skb(skb); | ||
| 761 | goto out; | ||
| 762 | } | ||
| 763 | c4iw_handlers[opcode](dev, skb); | ||
| 764 | return 1; | ||
| 765 | out: | ||
| 766 | return 0; | ||
| 767 | } | ||
| 768 | |||
| 580 | static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp, | 769 | static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp, |
| 581 | const struct pkt_gl *gl) | 770 | const struct pkt_gl *gl) |
| 582 | { | 771 | { |
| 583 | struct uld_ctx *ctx = handle; | 772 | struct uld_ctx *ctx = handle; |
| 584 | struct c4iw_dev *dev = ctx->dev; | 773 | struct c4iw_dev *dev = ctx->dev; |
| 585 | struct sk_buff *skb; | 774 | struct sk_buff *skb; |
| 586 | const struct cpl_act_establish *rpl; | 775 | u8 opcode; |
| 587 | unsigned int opcode; | ||
| 588 | 776 | ||
| 589 | if (gl == NULL) { | 777 | if (gl == NULL) { |
| 590 | /* omit RSS and rsp_ctrl at end of descriptor */ | 778 | /* omit RSS and rsp_ctrl at end of descriptor */ |
| @@ -601,19 +789,29 @@ static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp, | |||
| 601 | u32 qid = be32_to_cpu(rc->pldbuflen_qid); | 789 | u32 qid = be32_to_cpu(rc->pldbuflen_qid); |
| 602 | c4iw_ev_handler(dev, qid); | 790 | c4iw_ev_handler(dev, qid); |
| 603 | return 0; | 791 | return 0; |
| 792 | } else if (unlikely(*(u8 *)rsp != *(u8 *)gl->va)) { | ||
| 793 | if (recv_rx_pkt(dev, gl, rsp)) | ||
| 794 | return 0; | ||
| 795 | |||
| 796 | pr_info("%s: unexpected FL contents at %p, " \ | ||
| 797 | "RSS %#llx, FL %#llx, len %u\n", | ||
| 798 | pci_name(ctx->lldi.pdev), gl->va, | ||
| 799 | (unsigned long long)be64_to_cpu(*rsp), | ||
| 800 | (unsigned long long)be64_to_cpu(*(u64 *)gl->va), | ||
| 801 | gl->tot_len); | ||
| 802 | |||
| 803 | return 0; | ||
| 604 | } else { | 804 | } else { |
| 605 | skb = cxgb4_pktgl_to_skb(gl, 128, 128); | 805 | skb = cxgb4_pktgl_to_skb(gl, 128, 128); |
| 606 | if (unlikely(!skb)) | 806 | if (unlikely(!skb)) |
| 607 | goto nomem; | 807 | goto nomem; |
| 608 | } | 808 | } |
| 609 | 809 | ||
| 610 | rpl = cplhdr(skb); | 810 | opcode = *(u8 *)rsp; |
| 611 | opcode = rpl->ot.opcode; | ||
| 612 | |||
| 613 | if (c4iw_handlers[opcode]) | 811 | if (c4iw_handlers[opcode]) |
| 614 | c4iw_handlers[opcode](dev, skb); | 812 | c4iw_handlers[opcode](dev, skb); |
| 615 | else | 813 | else |
| 616 | printk(KERN_INFO "%s no handler opcode 0x%x...\n", __func__, | 814 | pr_info("%s no handler opcode 0x%x...\n", __func__, |
| 617 | opcode); | 815 | opcode); |
| 618 | 816 | ||
| 619 | return 0; | 817 | return 0; |
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index 9beb3a9f0336..9c1644fb0259 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h | |||
| @@ -130,6 +130,9 @@ struct c4iw_stats { | |||
| 130 | u64 db_empty; | 130 | u64 db_empty; |
| 131 | u64 db_drop; | 131 | u64 db_drop; |
| 132 | u64 db_state_transitions; | 132 | u64 db_state_transitions; |
| 133 | u64 tcam_full; | ||
| 134 | u64 act_ofld_conn_fails; | ||
| 135 | u64 pas_ofld_conn_fails; | ||
| 133 | }; | 136 | }; |
| 134 | 137 | ||
| 135 | struct c4iw_rdev { | 138 | struct c4iw_rdev { |
| @@ -223,6 +226,9 @@ struct c4iw_dev { | |||
| 223 | struct dentry *debugfs_root; | 226 | struct dentry *debugfs_root; |
| 224 | enum db_state db_state; | 227 | enum db_state db_state; |
| 225 | int qpcnt; | 228 | int qpcnt; |
| 229 | struct idr hwtid_idr; | ||
| 230 | struct idr atid_idr; | ||
| 231 | struct idr stid_idr; | ||
| 226 | }; | 232 | }; |
| 227 | 233 | ||
| 228 | static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev) | 234 | static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev) |
| @@ -712,6 +718,31 @@ enum c4iw_ep_flags { | |||
| 712 | CLOSE_SENT = 3, | 718 | CLOSE_SENT = 3, |
| 713 | }; | 719 | }; |
| 714 | 720 | ||
| 721 | enum c4iw_ep_history { | ||
| 722 | ACT_OPEN_REQ = 0, | ||
| 723 | ACT_OFLD_CONN = 1, | ||
| 724 | ACT_OPEN_RPL = 2, | ||
| 725 | ACT_ESTAB = 3, | ||
| 726 | PASS_ACCEPT_REQ = 4, | ||
| 727 | PASS_ESTAB = 5, | ||
| 728 | ABORT_UPCALL = 6, | ||
| 729 | ESTAB_UPCALL = 7, | ||
| 730 | CLOSE_UPCALL = 8, | ||
| 731 | ULP_ACCEPT = 9, | ||
| 732 | ULP_REJECT = 10, | ||
| 733 | TIMEDOUT = 11, | ||
| 734 | PEER_ABORT = 12, | ||
| 735 | PEER_CLOSE = 13, | ||
| 736 | CONNREQ_UPCALL = 14, | ||
| 737 | ABORT_CONN = 15, | ||
| 738 | DISCONN_UPCALL = 16, | ||
| 739 | EP_DISC_CLOSE = 17, | ||
| 740 | EP_DISC_ABORT = 18, | ||
| 741 | CONN_RPL_UPCALL = 19, | ||
| 742 | ACT_RETRY_NOMEM = 20, | ||
| 743 | ACT_RETRY_INUSE = 21 | ||
| 744 | }; | ||
| 745 | |||
| 715 | struct c4iw_ep_common { | 746 | struct c4iw_ep_common { |
| 716 | struct iw_cm_id *cm_id; | 747 | struct iw_cm_id *cm_id; |
| 717 | struct c4iw_qp *qp; | 748 | struct c4iw_qp *qp; |
| @@ -723,6 +754,7 @@ struct c4iw_ep_common { | |||
| 723 | struct sockaddr_in remote_addr; | 754 | struct sockaddr_in remote_addr; |
| 724 | struct c4iw_wr_wait wr_wait; | 755 | struct c4iw_wr_wait wr_wait; |
| 725 | unsigned long flags; | 756 | unsigned long flags; |
| 757 | unsigned long history; | ||
| 726 | }; | 758 | }; |
| 727 | 759 | ||
| 728 | struct c4iw_listen_ep { | 760 | struct c4iw_listen_ep { |
| @@ -760,6 +792,7 @@ struct c4iw_ep { | |||
| 760 | u8 tos; | 792 | u8 tos; |
| 761 | u8 retry_with_mpa_v1; | 793 | u8 retry_with_mpa_v1; |
| 762 | u8 tried_with_mpa_v1; | 794 | u8 tried_with_mpa_v1; |
| 795 | unsigned int retry_count; | ||
| 763 | }; | 796 | }; |
| 764 | 797 | ||
| 765 | static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id) | 798 | static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id) |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 72ae63f0072d..03103d2bd641 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
| @@ -752,6 +752,9 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ | |||
| 752 | dev->trans_start = jiffies; | 752 | dev->trans_start = jiffies; |
| 753 | ++tx->tx_head; | 753 | ++tx->tx_head; |
| 754 | 754 | ||
| 755 | skb_orphan(skb); | ||
| 756 | skb_dst_drop(skb); | ||
| 757 | |||
| 755 | if (++priv->tx_outstanding == ipoib_sendq_size) { | 758 | if (++priv->tx_outstanding == ipoib_sendq_size) { |
| 756 | ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n", | 759 | ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n", |
| 757 | tx->qp->qp_num); | 760 | tx->qp->qp_num); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index f10221f40803..a1bca70e20aa 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
| @@ -615,8 +615,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, | |||
| 615 | 615 | ||
| 616 | address->last_send = priv->tx_head; | 616 | address->last_send = priv->tx_head; |
| 617 | ++priv->tx_head; | 617 | ++priv->tx_head; |
| 618 | skb_orphan(skb); | ||
| 619 | 618 | ||
| 619 | skb_orphan(skb); | ||
| 620 | skb_dst_drop(skb); | ||
| 620 | } | 621 | } |
| 621 | 622 | ||
| 622 | if (unlikely(priv->tx_outstanding > MAX_SEND_CQE)) | 623 | if (unlikely(priv->tx_outstanding > MAX_SEND_CQE)) |
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 55074cba20eb..c1c74e030a58 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
| @@ -57,17 +57,9 @@ | |||
| 57 | * physically contiguous memory regions it is mapping into page sizes | 57 | * physically contiguous memory regions it is mapping into page sizes |
| 58 | * that we support. | 58 | * that we support. |
| 59 | * | 59 | * |
| 60 | * Traditionally the IOMMU core just handed us the mappings directly, | 60 | * 512GB Pages are not supported due to a hardware bug |
| 61 | * after making sure the size is an order of a 4KiB page and that the | ||
| 62 | * mapping has natural alignment. | ||
| 63 | * | ||
| 64 | * To retain this behavior, we currently advertise that we support | ||
| 65 | * all page sizes that are an order of 4KiB. | ||
| 66 | * | ||
| 67 | * If at some point we'd like to utilize the IOMMU core's new behavior, | ||
| 68 | * we could change this to advertise the real page sizes we support. | ||
| 69 | */ | 61 | */ |
| 70 | #define AMD_IOMMU_PGSIZES (~0xFFFUL) | 62 | #define AMD_IOMMU_PGSIZES ((~0xFFFUL) & ~(2ULL << 38)) |
| 71 | 63 | ||
| 72 | static DEFINE_RWLOCK(amd_iommu_devtable_lock); | 64 | static DEFINE_RWLOCK(amd_iommu_devtable_lock); |
| 73 | 65 | ||
| @@ -140,6 +132,9 @@ static void free_dev_data(struct iommu_dev_data *dev_data) | |||
| 140 | list_del(&dev_data->dev_data_list); | 132 | list_del(&dev_data->dev_data_list); |
| 141 | spin_unlock_irqrestore(&dev_data_list_lock, flags); | 133 | spin_unlock_irqrestore(&dev_data_list_lock, flags); |
| 142 | 134 | ||
| 135 | if (dev_data->group) | ||
| 136 | iommu_group_put(dev_data->group); | ||
| 137 | |||
| 143 | kfree(dev_data); | 138 | kfree(dev_data); |
| 144 | } | 139 | } |
| 145 | 140 | ||
| @@ -274,41 +269,23 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to) | |||
| 274 | *from = to; | 269 | *from = to; |
| 275 | } | 270 | } |
| 276 | 271 | ||
| 277 | #define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) | 272 | static struct pci_bus *find_hosted_bus(struct pci_bus *bus) |
| 278 | |||
| 279 | static int iommu_init_device(struct device *dev) | ||
| 280 | { | 273 | { |
| 281 | struct pci_dev *dma_pdev = NULL, *pdev = to_pci_dev(dev); | 274 | while (!bus->self) { |
| 282 | struct iommu_dev_data *dev_data; | 275 | if (!pci_is_root_bus(bus)) |
| 283 | struct iommu_group *group; | 276 | bus = bus->parent; |
| 284 | u16 alias; | 277 | else |
| 285 | int ret; | 278 | return ERR_PTR(-ENODEV); |
| 286 | 279 | } | |
| 287 | if (dev->archdata.iommu) | ||
| 288 | return 0; | ||
| 289 | |||
| 290 | dev_data = find_dev_data(get_device_id(dev)); | ||
| 291 | if (!dev_data) | ||
| 292 | return -ENOMEM; | ||
| 293 | |||
| 294 | alias = amd_iommu_alias_table[dev_data->devid]; | ||
| 295 | if (alias != dev_data->devid) { | ||
| 296 | struct iommu_dev_data *alias_data; | ||
| 297 | 280 | ||
| 298 | alias_data = find_dev_data(alias); | 281 | return bus; |
| 299 | if (alias_data == NULL) { | 282 | } |
| 300 | pr_err("AMD-Vi: Warning: Unhandled device %s\n", | ||
| 301 | dev_name(dev)); | ||
| 302 | free_dev_data(dev_data); | ||
| 303 | return -ENOTSUPP; | ||
| 304 | } | ||
| 305 | dev_data->alias_data = alias_data; | ||
| 306 | 283 | ||
| 307 | dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff); | 284 | #define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) |
| 308 | } | ||
| 309 | 285 | ||
| 310 | if (dma_pdev == NULL) | 286 | static struct pci_dev *get_isolation_root(struct pci_dev *pdev) |
| 311 | dma_pdev = pci_dev_get(pdev); | 287 | { |
| 288 | struct pci_dev *dma_pdev = pdev; | ||
| 312 | 289 | ||
| 313 | /* Account for quirked devices */ | 290 | /* Account for quirked devices */ |
| 314 | swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); | 291 | swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); |
| @@ -330,14 +307,9 @@ static int iommu_init_device(struct device *dev) | |||
| 330 | * Finding the next device may require skipping virtual buses. | 307 | * Finding the next device may require skipping virtual buses. |
| 331 | */ | 308 | */ |
| 332 | while (!pci_is_root_bus(dma_pdev->bus)) { | 309 | while (!pci_is_root_bus(dma_pdev->bus)) { |
| 333 | struct pci_bus *bus = dma_pdev->bus; | 310 | struct pci_bus *bus = find_hosted_bus(dma_pdev->bus); |
| 334 | 311 | if (IS_ERR(bus)) | |
| 335 | while (!bus->self) { | 312 | break; |
| 336 | if (!pci_is_root_bus(bus)) | ||
| 337 | bus = bus->parent; | ||
| 338 | else | ||
| 339 | goto root_bus; | ||
| 340 | } | ||
| 341 | 313 | ||
| 342 | if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) | 314 | if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS)) |
| 343 | break; | 315 | break; |
| @@ -345,19 +317,137 @@ static int iommu_init_device(struct device *dev) | |||
| 345 | swap_pci_ref(&dma_pdev, pci_dev_get(bus->self)); | 317 | swap_pci_ref(&dma_pdev, pci_dev_get(bus->self)); |
| 346 | } | 318 | } |
| 347 | 319 | ||
| 348 | root_bus: | 320 | return dma_pdev; |
| 349 | group = iommu_group_get(&dma_pdev->dev); | 321 | } |
| 350 | pci_dev_put(dma_pdev); | 322 | |
| 323 | static int use_pdev_iommu_group(struct pci_dev *pdev, struct device *dev) | ||
| 324 | { | ||
| 325 | struct iommu_group *group = iommu_group_get(&pdev->dev); | ||
| 326 | int ret; | ||
| 327 | |||
| 351 | if (!group) { | 328 | if (!group) { |
| 352 | group = iommu_group_alloc(); | 329 | group = iommu_group_alloc(); |
| 353 | if (IS_ERR(group)) | 330 | if (IS_ERR(group)) |
| 354 | return PTR_ERR(group); | 331 | return PTR_ERR(group); |
| 332 | |||
| 333 | WARN_ON(&pdev->dev != dev); | ||
| 355 | } | 334 | } |
| 356 | 335 | ||
| 357 | ret = iommu_group_add_device(group, dev); | 336 | ret = iommu_group_add_device(group, dev); |
| 358 | |||
| 359 | iommu_group_put(group); | 337 | iommu_group_put(group); |
| 338 | return ret; | ||
| 339 | } | ||
| 340 | |||
| 341 | static int use_dev_data_iommu_group(struct iommu_dev_data *dev_data, | ||
| 342 | struct device *dev) | ||
| 343 | { | ||
| 344 | if (!dev_data->group) { | ||
| 345 | struct iommu_group *group = iommu_group_alloc(); | ||
| 346 | if (IS_ERR(group)) | ||
| 347 | return PTR_ERR(group); | ||
| 348 | |||
| 349 | dev_data->group = group; | ||
| 350 | } | ||
| 351 | |||
| 352 | return iommu_group_add_device(dev_data->group, dev); | ||
| 353 | } | ||
| 354 | |||
| 355 | static int init_iommu_group(struct device *dev) | ||
| 356 | { | ||
| 357 | struct iommu_dev_data *dev_data; | ||
| 358 | struct iommu_group *group; | ||
| 359 | struct pci_dev *dma_pdev; | ||
| 360 | int ret; | ||
| 361 | |||
| 362 | group = iommu_group_get(dev); | ||
| 363 | if (group) { | ||
| 364 | iommu_group_put(group); | ||
| 365 | return 0; | ||
| 366 | } | ||
| 367 | |||
| 368 | dev_data = find_dev_data(get_device_id(dev)); | ||
| 369 | if (!dev_data) | ||
| 370 | return -ENOMEM; | ||
| 371 | |||
| 372 | if (dev_data->alias_data) { | ||
| 373 | u16 alias; | ||
| 374 | struct pci_bus *bus; | ||
| 375 | |||
| 376 | if (dev_data->alias_data->group) | ||
| 377 | goto use_group; | ||
| 378 | |||
| 379 | /* | ||
| 380 | * If the alias device exists, it's effectively just a first | ||
| 381 | * level quirk for finding the DMA source. | ||
| 382 | */ | ||
| 383 | alias = amd_iommu_alias_table[dev_data->devid]; | ||
| 384 | dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff); | ||
| 385 | if (dma_pdev) { | ||
| 386 | dma_pdev = get_isolation_root(dma_pdev); | ||
| 387 | goto use_pdev; | ||
| 388 | } | ||
| 389 | |||
| 390 | /* | ||
| 391 | * If the alias is virtual, try to find a parent device | ||
| 392 | * and test whether the IOMMU group is actualy rooted above | ||
| 393 | * the alias. Be careful to also test the parent device if | ||
| 394 | * we think the alias is the root of the group. | ||
| 395 | */ | ||
| 396 | bus = pci_find_bus(0, alias >> 8); | ||
| 397 | if (!bus) | ||
| 398 | goto use_group; | ||
| 399 | |||
| 400 | bus = find_hosted_bus(bus); | ||
| 401 | if (IS_ERR(bus) || !bus->self) | ||
| 402 | goto use_group; | ||
| 403 | |||
| 404 | dma_pdev = get_isolation_root(pci_dev_get(bus->self)); | ||
| 405 | if (dma_pdev != bus->self || (dma_pdev->multifunction && | ||
| 406 | !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS))) | ||
| 407 | goto use_pdev; | ||
| 408 | |||
| 409 | pci_dev_put(dma_pdev); | ||
| 410 | goto use_group; | ||
| 411 | } | ||
| 412 | |||
| 413 | dma_pdev = get_isolation_root(pci_dev_get(to_pci_dev(dev))); | ||
| 414 | use_pdev: | ||
| 415 | ret = use_pdev_iommu_group(dma_pdev, dev); | ||
| 416 | pci_dev_put(dma_pdev); | ||
| 417 | return ret; | ||
| 418 | use_group: | ||
| 419 | return use_dev_data_iommu_group(dev_data->alias_data, dev); | ||
| 420 | } | ||
| 421 | |||
| 422 | static int iommu_init_device(struct device *dev) | ||
| 423 | { | ||
| 424 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 425 | struct iommu_dev_data *dev_data; | ||
| 426 | u16 alias; | ||
| 427 | int ret; | ||
| 428 | |||
| 429 | if (dev->archdata.iommu) | ||
| 430 | return 0; | ||
| 431 | |||
| 432 | dev_data = find_dev_data(get_device_id(dev)); | ||
| 433 | if (!dev_data) | ||
| 434 | return -ENOMEM; | ||
| 435 | |||
| 436 | alias = amd_iommu_alias_table[dev_data->devid]; | ||
| 437 | if (alias != dev_data->devid) { | ||
| 438 | struct iommu_dev_data *alias_data; | ||
| 439 | |||
| 440 | alias_data = find_dev_data(alias); | ||
| 441 | if (alias_data == NULL) { | ||
| 442 | pr_err("AMD-Vi: Warning: Unhandled device %s\n", | ||
| 443 | dev_name(dev)); | ||
| 444 | free_dev_data(dev_data); | ||
| 445 | return -ENOTSUPP; | ||
| 446 | } | ||
| 447 | dev_data->alias_data = alias_data; | ||
| 448 | } | ||
| 360 | 449 | ||
| 450 | ret = init_iommu_group(dev); | ||
| 361 | if (ret) | 451 | if (ret) |
| 362 | return ret; | 452 | return ret; |
| 363 | 453 | ||
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index c9aa3d079ff0..e38ab438bb34 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h | |||
| @@ -426,6 +426,7 @@ struct iommu_dev_data { | |||
| 426 | struct iommu_dev_data *alias_data;/* The alias dev_data */ | 426 | struct iommu_dev_data *alias_data;/* The alias dev_data */ |
| 427 | struct protection_domain *domain; /* Domain the device is bound to */ | 427 | struct protection_domain *domain; /* Domain the device is bound to */ |
| 428 | atomic_t bind; /* Domain attach reference count */ | 428 | atomic_t bind; /* Domain attach reference count */ |
| 429 | struct iommu_group *group; /* IOMMU group for virtual aliases */ | ||
| 429 | u16 devid; /* PCI Device ID */ | 430 | u16 devid; /* PCI Device ID */ |
| 430 | bool iommu_v2; /* Device can make use of IOMMUv2 */ | 431 | bool iommu_v2; /* Device can make use of IOMMUv2 */ |
| 431 | bool passthrough; /* Default for device is pt_domain */ | 432 | bool passthrough; /* Default for device is pt_domain */ |
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 0badfa48b32b..c2c07a4a7f21 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
| @@ -1827,10 +1827,17 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, | |||
| 1827 | if (!pte) | 1827 | if (!pte) |
| 1828 | return -ENOMEM; | 1828 | return -ENOMEM; |
| 1829 | /* It is large page*/ | 1829 | /* It is large page*/ |
| 1830 | if (largepage_lvl > 1) | 1830 | if (largepage_lvl > 1) { |
| 1831 | pteval |= DMA_PTE_LARGE_PAGE; | 1831 | pteval |= DMA_PTE_LARGE_PAGE; |
| 1832 | else | 1832 | /* Ensure that old small page tables are removed to make room |
| 1833 | for superpage, if they exist. */ | ||
| 1834 | dma_pte_clear_range(domain, iov_pfn, | ||
| 1835 | iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); | ||
| 1836 | dma_pte_free_pagetable(domain, iov_pfn, | ||
| 1837 | iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); | ||
| 1838 | } else { | ||
| 1833 | pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE; | 1839 | pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE; |
| 1840 | } | ||
| 1834 | 1841 | ||
| 1835 | } | 1842 | } |
| 1836 | /* We don't need lock here, nobody else | 1843 | /* We don't need lock here, nobody else |
| @@ -2320,8 +2327,39 @@ static int domain_add_dev_info(struct dmar_domain *domain, | |||
| 2320 | return 0; | 2327 | return 0; |
| 2321 | } | 2328 | } |
| 2322 | 2329 | ||
| 2330 | static bool device_has_rmrr(struct pci_dev *dev) | ||
| 2331 | { | ||
| 2332 | struct dmar_rmrr_unit *rmrr; | ||
| 2333 | int i; | ||
| 2334 | |||
| 2335 | for_each_rmrr_units(rmrr) { | ||
| 2336 | for (i = 0; i < rmrr->devices_cnt; i++) { | ||
| 2337 | /* | ||
| 2338 | * Return TRUE if this RMRR contains the device that | ||
| 2339 | * is passed in. | ||
| 2340 | */ | ||
| 2341 | if (rmrr->devices[i] == dev) | ||
| 2342 | return true; | ||
| 2343 | } | ||
| 2344 | } | ||
| 2345 | return false; | ||
| 2346 | } | ||
| 2347 | |||
| 2323 | static int iommu_should_identity_map(struct pci_dev *pdev, int startup) | 2348 | static int iommu_should_identity_map(struct pci_dev *pdev, int startup) |
| 2324 | { | 2349 | { |
| 2350 | |||
| 2351 | /* | ||
| 2352 | * We want to prevent any device associated with an RMRR from | ||
| 2353 | * getting placed into the SI Domain. This is done because | ||
| 2354 | * problems exist when devices are moved in and out of domains | ||
| 2355 | * and their respective RMRR info is lost. We exempt USB devices | ||
| 2356 | * from this process due to their usage of RMRRs that are known | ||
| 2357 | * to not be needed after BIOS hand-off to OS. | ||
| 2358 | */ | ||
| 2359 | if (device_has_rmrr(pdev) && | ||
| 2360 | (pdev->class >> 8) != PCI_CLASS_SERIAL_USB) | ||
| 2361 | return 0; | ||
| 2362 | |||
| 2325 | if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev)) | 2363 | if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev)) |
| 2326 | return 1; | 2364 | return 1; |
| 2327 | 2365 | ||
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index badc17c2bcb4..18108c1405e2 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c | |||
| @@ -16,13 +16,13 @@ | |||
| 16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| 18 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
| 19 | #include <linux/clk.h> | ||
| 20 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 21 | #include <linux/iommu.h> | 20 | #include <linux/iommu.h> |
| 22 | #include <linux/omap-iommu.h> | 21 | #include <linux/omap-iommu.h> |
| 23 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
| 24 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
| 25 | #include <linux/io.h> | 24 | #include <linux/io.h> |
| 25 | #include <linux/pm_runtime.h> | ||
| 26 | 26 | ||
| 27 | #include <asm/cacheflush.h> | 27 | #include <asm/cacheflush.h> |
| 28 | 28 | ||
| @@ -143,31 +143,44 @@ EXPORT_SYMBOL_GPL(omap_iommu_arch_version); | |||
| 143 | static int iommu_enable(struct omap_iommu *obj) | 143 | static int iommu_enable(struct omap_iommu *obj) |
| 144 | { | 144 | { |
| 145 | int err; | 145 | int err; |
| 146 | struct platform_device *pdev = to_platform_device(obj->dev); | ||
| 147 | struct iommu_platform_data *pdata = pdev->dev.platform_data; | ||
| 146 | 148 | ||
| 147 | if (!obj) | 149 | if (!obj || !pdata) |
| 148 | return -EINVAL; | 150 | return -EINVAL; |
| 149 | 151 | ||
| 150 | if (!arch_iommu) | 152 | if (!arch_iommu) |
| 151 | return -ENODEV; | 153 | return -ENODEV; |
| 152 | 154 | ||
| 153 | clk_enable(obj->clk); | 155 | if (pdata->deassert_reset) { |
| 156 | err = pdata->deassert_reset(pdev, pdata->reset_name); | ||
| 157 | if (err) { | ||
| 158 | dev_err(obj->dev, "deassert_reset failed: %d\n", err); | ||
| 159 | return err; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | pm_runtime_get_sync(obj->dev); | ||
| 154 | 164 | ||
| 155 | err = arch_iommu->enable(obj); | 165 | err = arch_iommu->enable(obj); |
| 156 | 166 | ||
| 157 | clk_disable(obj->clk); | ||
| 158 | return err; | 167 | return err; |
| 159 | } | 168 | } |
| 160 | 169 | ||
| 161 | static void iommu_disable(struct omap_iommu *obj) | 170 | static void iommu_disable(struct omap_iommu *obj) |
| 162 | { | 171 | { |
| 163 | if (!obj) | 172 | struct platform_device *pdev = to_platform_device(obj->dev); |
| 164 | return; | 173 | struct iommu_platform_data *pdata = pdev->dev.platform_data; |
| 165 | 174 | ||
| 166 | clk_enable(obj->clk); | 175 | if (!obj || !pdata) |
| 176 | return; | ||
| 167 | 177 | ||
| 168 | arch_iommu->disable(obj); | 178 | arch_iommu->disable(obj); |
| 169 | 179 | ||
| 170 | clk_disable(obj->clk); | 180 | pm_runtime_put_sync(obj->dev); |
| 181 | |||
| 182 | if (pdata->assert_reset) | ||
| 183 | pdata->assert_reset(pdev, pdata->reset_name); | ||
| 171 | } | 184 | } |
| 172 | 185 | ||
| 173 | /* | 186 | /* |
| @@ -290,7 +303,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e) | |||
| 290 | if (!obj || !obj->nr_tlb_entries || !e) | 303 | if (!obj || !obj->nr_tlb_entries || !e) |
| 291 | return -EINVAL; | 304 | return -EINVAL; |
| 292 | 305 | ||
| 293 | clk_enable(obj->clk); | 306 | pm_runtime_get_sync(obj->dev); |
| 294 | 307 | ||
| 295 | iotlb_lock_get(obj, &l); | 308 | iotlb_lock_get(obj, &l); |
| 296 | if (l.base == obj->nr_tlb_entries) { | 309 | if (l.base == obj->nr_tlb_entries) { |
| @@ -320,7 +333,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e) | |||
| 320 | 333 | ||
| 321 | cr = iotlb_alloc_cr(obj, e); | 334 | cr = iotlb_alloc_cr(obj, e); |
| 322 | if (IS_ERR(cr)) { | 335 | if (IS_ERR(cr)) { |
| 323 | clk_disable(obj->clk); | 336 | pm_runtime_put_sync(obj->dev); |
| 324 | return PTR_ERR(cr); | 337 | return PTR_ERR(cr); |
| 325 | } | 338 | } |
| 326 | 339 | ||
| @@ -334,7 +347,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e) | |||
| 334 | l.vict = l.base; | 347 | l.vict = l.base; |
| 335 | iotlb_lock_set(obj, &l); | 348 | iotlb_lock_set(obj, &l); |
| 336 | out: | 349 | out: |
| 337 | clk_disable(obj->clk); | 350 | pm_runtime_put_sync(obj->dev); |
| 338 | return err; | 351 | return err; |
| 339 | } | 352 | } |
| 340 | 353 | ||
| @@ -364,7 +377,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da) | |||
| 364 | int i; | 377 | int i; |
| 365 | struct cr_regs cr; | 378 | struct cr_regs cr; |
| 366 | 379 | ||
| 367 | clk_enable(obj->clk); | 380 | pm_runtime_get_sync(obj->dev); |
| 368 | 381 | ||
| 369 | for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) { | 382 | for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) { |
| 370 | u32 start; | 383 | u32 start; |
| @@ -383,7 +396,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da) | |||
| 383 | iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); | 396 | iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); |
| 384 | } | 397 | } |
| 385 | } | 398 | } |
| 386 | clk_disable(obj->clk); | 399 | pm_runtime_put_sync(obj->dev); |
| 387 | 400 | ||
| 388 | if (i == obj->nr_tlb_entries) | 401 | if (i == obj->nr_tlb_entries) |
| 389 | dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da); | 402 | dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da); |
| @@ -397,7 +410,7 @@ static void flush_iotlb_all(struct omap_iommu *obj) | |||
| 397 | { | 410 | { |
| 398 | struct iotlb_lock l; | 411 | struct iotlb_lock l; |
| 399 | 412 | ||
| 400 | clk_enable(obj->clk); | 413 | pm_runtime_get_sync(obj->dev); |
| 401 | 414 | ||
| 402 | l.base = 0; | 415 | l.base = 0; |
| 403 | l.vict = 0; | 416 | l.vict = 0; |
| @@ -405,7 +418,7 @@ static void flush_iotlb_all(struct omap_iommu *obj) | |||
| 405 | 418 | ||
| 406 | iommu_write_reg(obj, 1, MMU_GFLUSH); | 419 | iommu_write_reg(obj, 1, MMU_GFLUSH); |
| 407 | 420 | ||
| 408 | clk_disable(obj->clk); | 421 | pm_runtime_put_sync(obj->dev); |
| 409 | } | 422 | } |
| 410 | 423 | ||
| 411 | #if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE) | 424 | #if defined(CONFIG_OMAP_IOMMU_DEBUG) || defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE) |
| @@ -415,11 +428,11 @@ ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t bytes) | |||
| 415 | if (!obj || !buf) | 428 | if (!obj || !buf) |
| 416 | return -EINVAL; | 429 | return -EINVAL; |
| 417 | 430 | ||
| 418 | clk_enable(obj->clk); | 431 | pm_runtime_get_sync(obj->dev); |
| 419 | 432 | ||
| 420 | bytes = arch_iommu->dump_ctx(obj, buf, bytes); | 433 | bytes = arch_iommu->dump_ctx(obj, buf, bytes); |
| 421 | 434 | ||
| 422 | clk_disable(obj->clk); | 435 | pm_runtime_put_sync(obj->dev); |
| 423 | 436 | ||
| 424 | return bytes; | 437 | return bytes; |
| 425 | } | 438 | } |
| @@ -433,7 +446,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num) | |||
| 433 | struct cr_regs tmp; | 446 | struct cr_regs tmp; |
| 434 | struct cr_regs *p = crs; | 447 | struct cr_regs *p = crs; |
| 435 | 448 | ||
| 436 | clk_enable(obj->clk); | 449 | pm_runtime_get_sync(obj->dev); |
| 437 | iotlb_lock_get(obj, &saved); | 450 | iotlb_lock_get(obj, &saved); |
| 438 | 451 | ||
| 439 | for_each_iotlb_cr(obj, num, i, tmp) { | 452 | for_each_iotlb_cr(obj, num, i, tmp) { |
| @@ -443,7 +456,7 @@ __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num) | |||
| 443 | } | 456 | } |
| 444 | 457 | ||
| 445 | iotlb_lock_set(obj, &saved); | 458 | iotlb_lock_set(obj, &saved); |
| 446 | clk_disable(obj->clk); | 459 | pm_runtime_put_sync(obj->dev); |
| 447 | 460 | ||
| 448 | return p - crs; | 461 | return p - crs; |
| 449 | } | 462 | } |
| @@ -807,9 +820,7 @@ static irqreturn_t iommu_fault_handler(int irq, void *data) | |||
| 807 | if (!obj->refcount) | 820 | if (!obj->refcount) |
| 808 | return IRQ_NONE; | 821 | return IRQ_NONE; |
| 809 | 822 | ||
| 810 | clk_enable(obj->clk); | ||
| 811 | errs = iommu_report_fault(obj, &da); | 823 | errs = iommu_report_fault(obj, &da); |
| 812 | clk_disable(obj->clk); | ||
| 813 | if (errs == 0) | 824 | if (errs == 0) |
| 814 | return IRQ_HANDLED; | 825 | return IRQ_HANDLED; |
| 815 | 826 | ||
| @@ -931,17 +942,10 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) | |||
| 931 | struct resource *res; | 942 | struct resource *res; |
| 932 | struct iommu_platform_data *pdata = pdev->dev.platform_data; | 943 | struct iommu_platform_data *pdata = pdev->dev.platform_data; |
| 933 | 944 | ||
| 934 | if (pdev->num_resources != 2) | ||
| 935 | return -EINVAL; | ||
| 936 | |||
| 937 | obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL); | 945 | obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL); |
| 938 | if (!obj) | 946 | if (!obj) |
| 939 | return -ENOMEM; | 947 | return -ENOMEM; |
| 940 | 948 | ||
| 941 | obj->clk = clk_get(&pdev->dev, pdata->clk_name); | ||
| 942 | if (IS_ERR(obj->clk)) | ||
| 943 | goto err_clk; | ||
| 944 | |||
| 945 | obj->nr_tlb_entries = pdata->nr_tlb_entries; | 949 | obj->nr_tlb_entries = pdata->nr_tlb_entries; |
| 946 | obj->name = pdata->name; | 950 | obj->name = pdata->name; |
| 947 | obj->dev = &pdev->dev; | 951 | obj->dev = &pdev->dev; |
| @@ -984,6 +988,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) | |||
| 984 | goto err_irq; | 988 | goto err_irq; |
| 985 | platform_set_drvdata(pdev, obj); | 989 | platform_set_drvdata(pdev, obj); |
| 986 | 990 | ||
| 991 | pm_runtime_irq_safe(obj->dev); | ||
| 992 | pm_runtime_enable(obj->dev); | ||
| 993 | |||
| 987 | dev_info(&pdev->dev, "%s registered\n", obj->name); | 994 | dev_info(&pdev->dev, "%s registered\n", obj->name); |
| 988 | return 0; | 995 | return 0; |
| 989 | 996 | ||
| @@ -992,8 +999,6 @@ err_irq: | |||
| 992 | err_ioremap: | 999 | err_ioremap: |
| 993 | release_mem_region(res->start, resource_size(res)); | 1000 | release_mem_region(res->start, resource_size(res)); |
| 994 | err_mem: | 1001 | err_mem: |
| 995 | clk_put(obj->clk); | ||
| 996 | err_clk: | ||
| 997 | kfree(obj); | 1002 | kfree(obj); |
| 998 | return err; | 1003 | return err; |
| 999 | } | 1004 | } |
| @@ -1014,7 +1019,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev) | |||
| 1014 | release_mem_region(res->start, resource_size(res)); | 1019 | release_mem_region(res->start, resource_size(res)); |
| 1015 | iounmap(obj->regbase); | 1020 | iounmap(obj->regbase); |
| 1016 | 1021 | ||
| 1017 | clk_put(obj->clk); | 1022 | pm_runtime_disable(obj->dev); |
| 1023 | |||
| 1018 | dev_info(&pdev->dev, "%s removed\n", obj->name); | 1024 | dev_info(&pdev->dev, "%s removed\n", obj->name); |
| 1019 | kfree(obj); | 1025 | kfree(obj); |
| 1020 | return 0; | 1026 | return 0; |
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h index 2b5f3c04d167..120084206602 100644 --- a/drivers/iommu/omap-iommu.h +++ b/drivers/iommu/omap-iommu.h | |||
| @@ -29,7 +29,6 @@ struct iotlb_entry { | |||
| 29 | struct omap_iommu { | 29 | struct omap_iommu { |
| 30 | const char *name; | 30 | const char *name; |
| 31 | struct module *owner; | 31 | struct module *owner; |
| 32 | struct clk *clk; | ||
| 33 | void __iomem *regbase; | 32 | void __iomem *regbase; |
| 34 | struct device *dev; | 33 | struct device *dev; |
| 35 | void *isr_priv; | 34 | void *isr_priv; |
| @@ -116,8 +115,6 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct device *dev) | |||
| 116 | * MMU Register offsets | 115 | * MMU Register offsets |
| 117 | */ | 116 | */ |
| 118 | #define MMU_REVISION 0x00 | 117 | #define MMU_REVISION 0x00 |
| 119 | #define MMU_SYSCONFIG 0x10 | ||
| 120 | #define MMU_SYSSTATUS 0x14 | ||
| 121 | #define MMU_IRQSTATUS 0x18 | 118 | #define MMU_IRQSTATUS 0x18 |
| 122 | #define MMU_IRQENABLE 0x1c | 119 | #define MMU_IRQENABLE 0x1c |
| 123 | #define MMU_WALKING_ST 0x40 | 120 | #define MMU_WALKING_ST 0x40 |
diff --git a/drivers/iommu/omap-iommu2.c b/drivers/iommu/omap-iommu2.c index c02020292377..d745094a69dd 100644 --- a/drivers/iommu/omap-iommu2.c +++ b/drivers/iommu/omap-iommu2.c | |||
| @@ -28,19 +28,6 @@ | |||
| 28 | */ | 28 | */ |
| 29 | #define IOMMU_ARCH_VERSION 0x00000011 | 29 | #define IOMMU_ARCH_VERSION 0x00000011 |
| 30 | 30 | ||
| 31 | /* SYSCONF */ | ||
| 32 | #define MMU_SYS_IDLE_SHIFT 3 | ||
| 33 | #define MMU_SYS_IDLE_FORCE (0 << MMU_SYS_IDLE_SHIFT) | ||
| 34 | #define MMU_SYS_IDLE_NONE (1 << MMU_SYS_IDLE_SHIFT) | ||
| 35 | #define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT) | ||
| 36 | #define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT) | ||
| 37 | |||
| 38 | #define MMU_SYS_SOFTRESET (1 << 1) | ||
| 39 | #define MMU_SYS_AUTOIDLE 1 | ||
| 40 | |||
| 41 | /* SYSSTATUS */ | ||
| 42 | #define MMU_SYS_RESETDONE 1 | ||
| 43 | |||
| 44 | /* IRQSTATUS & IRQENABLE */ | 31 | /* IRQSTATUS & IRQENABLE */ |
| 45 | #define MMU_IRQ_MULTIHITFAULT (1 << 4) | 32 | #define MMU_IRQ_MULTIHITFAULT (1 << 4) |
| 46 | #define MMU_IRQ_TABLEWALKFAULT (1 << 3) | 33 | #define MMU_IRQ_TABLEWALKFAULT (1 << 3) |
| @@ -97,7 +84,6 @@ static void __iommu_set_twl(struct omap_iommu *obj, bool on) | |||
| 97 | static int omap2_iommu_enable(struct omap_iommu *obj) | 84 | static int omap2_iommu_enable(struct omap_iommu *obj) |
| 98 | { | 85 | { |
| 99 | u32 l, pa; | 86 | u32 l, pa; |
| 100 | unsigned long timeout; | ||
| 101 | 87 | ||
| 102 | if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K)) | 88 | if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K)) |
| 103 | return -EINVAL; | 89 | return -EINVAL; |
| @@ -106,29 +92,10 @@ static int omap2_iommu_enable(struct omap_iommu *obj) | |||
| 106 | if (!IS_ALIGNED(pa, SZ_16K)) | 92 | if (!IS_ALIGNED(pa, SZ_16K)) |
| 107 | return -EINVAL; | 93 | return -EINVAL; |
| 108 | 94 | ||
| 109 | iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG); | ||
| 110 | |||
| 111 | timeout = jiffies + msecs_to_jiffies(20); | ||
| 112 | do { | ||
| 113 | l = iommu_read_reg(obj, MMU_SYSSTATUS); | ||
| 114 | if (l & MMU_SYS_RESETDONE) | ||
| 115 | break; | ||
| 116 | } while (!time_after(jiffies, timeout)); | ||
| 117 | |||
| 118 | if (!(l & MMU_SYS_RESETDONE)) { | ||
| 119 | dev_err(obj->dev, "can't take mmu out of reset\n"); | ||
| 120 | return -ENODEV; | ||
| 121 | } | ||
| 122 | |||
| 123 | l = iommu_read_reg(obj, MMU_REVISION); | 95 | l = iommu_read_reg(obj, MMU_REVISION); |
| 124 | dev_info(obj->dev, "%s: version %d.%d\n", obj->name, | 96 | dev_info(obj->dev, "%s: version %d.%d\n", obj->name, |
| 125 | (l >> 4) & 0xf, l & 0xf); | 97 | (l >> 4) & 0xf, l & 0xf); |
| 126 | 98 | ||
| 127 | l = iommu_read_reg(obj, MMU_SYSCONFIG); | ||
| 128 | l &= ~MMU_SYS_IDLE_MASK; | ||
| 129 | l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE); | ||
| 130 | iommu_write_reg(obj, l, MMU_SYSCONFIG); | ||
| 131 | |||
| 132 | iommu_write_reg(obj, pa, MMU_TTB); | 99 | iommu_write_reg(obj, pa, MMU_TTB); |
| 133 | 100 | ||
| 134 | __iommu_set_twl(obj, true); | 101 | __iommu_set_twl(obj, true); |
| @@ -142,7 +109,6 @@ static void omap2_iommu_disable(struct omap_iommu *obj) | |||
| 142 | 109 | ||
| 143 | l &= ~MMU_CNTL_MASK; | 110 | l &= ~MMU_CNTL_MASK; |
| 144 | iommu_write_reg(obj, l, MMU_CNTL); | 111 | iommu_write_reg(obj, l, MMU_CNTL); |
| 145 | iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG); | ||
| 146 | 112 | ||
| 147 | dev_dbg(obj->dev, "%s is shutting down\n", obj->name); | 113 | dev_dbg(obj->dev, "%s is shutting down\n", obj->name); |
| 148 | } | 114 | } |
| @@ -271,8 +237,6 @@ omap2_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len) | |||
| 271 | char *p = buf; | 237 | char *p = buf; |
| 272 | 238 | ||
| 273 | pr_reg(REVISION); | 239 | pr_reg(REVISION); |
| 274 | pr_reg(SYSCONFIG); | ||
| 275 | pr_reg(SYSSTATUS); | ||
| 276 | pr_reg(IRQSTATUS); | 240 | pr_reg(IRQSTATUS); |
| 277 | pr_reg(IRQENABLE); | 241 | pr_reg(IRQENABLE); |
| 278 | pr_reg(WALKING_ST); | 242 | pr_reg(WALKING_ST); |
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index c16e8fc8a4bd..4c9db62814ff 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c | |||
| @@ -398,6 +398,7 @@ static int tegra_gart_probe(struct platform_device *pdev) | |||
| 398 | do_gart_setup(gart, NULL); | 398 | do_gart_setup(gart, NULL); |
| 399 | 399 | ||
| 400 | gart_handle = gart; | 400 | gart_handle = gart; |
| 401 | bus_set_iommu(&platform_bus_type, &gart_iommu_ops); | ||
| 401 | return 0; | 402 | return 0; |
| 402 | 403 | ||
| 403 | fail: | 404 | fail: |
| @@ -450,7 +451,6 @@ static struct platform_driver tegra_gart_driver = { | |||
| 450 | 451 | ||
| 451 | static int __devinit tegra_gart_init(void) | 452 | static int __devinit tegra_gart_init(void) |
| 452 | { | 453 | { |
| 453 | bus_set_iommu(&platform_bus_type, &gart_iommu_ops); | ||
| 454 | return platform_driver_register(&tegra_gart_driver); | 454 | return platform_driver_register(&tegra_gart_driver); |
| 455 | } | 455 | } |
| 456 | 456 | ||
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 4252d743963d..25c1210c0832 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c | |||
| @@ -694,10 +694,8 @@ static void __smmu_iommu_unmap(struct smmu_as *as, dma_addr_t iova) | |||
| 694 | *pte = _PTE_VACANT(iova); | 694 | *pte = _PTE_VACANT(iova); |
| 695 | FLUSH_CPU_DCACHE(pte, page, sizeof(*pte)); | 695 | FLUSH_CPU_DCACHE(pte, page, sizeof(*pte)); |
| 696 | flush_ptc_and_tlb(as->smmu, as, iova, pte, page, 0); | 696 | flush_ptc_and_tlb(as->smmu, as, iova, pte, page, 0); |
| 697 | if (!--(*count)) { | 697 | if (!--(*count)) |
| 698 | free_ptbl(as, iova); | 698 | free_ptbl(as, iova); |
| 699 | smmu_flush_regs(as->smmu, 0); | ||
| 700 | } | ||
| 701 | } | 699 | } |
| 702 | 700 | ||
| 703 | static void __smmu_iommu_map_pfn(struct smmu_as *as, dma_addr_t iova, | 701 | static void __smmu_iommu_map_pfn(struct smmu_as *as, dma_addr_t iova, |
| @@ -1232,6 +1230,7 @@ static int tegra_smmu_probe(struct platform_device *pdev) | |||
| 1232 | 1230 | ||
| 1233 | smmu_debugfs_create(smmu); | 1231 | smmu_debugfs_create(smmu); |
| 1234 | smmu_handle = smmu; | 1232 | smmu_handle = smmu; |
| 1233 | bus_set_iommu(&platform_bus_type, &smmu_iommu_ops); | ||
| 1235 | return 0; | 1234 | return 0; |
| 1236 | } | 1235 | } |
| 1237 | 1236 | ||
| @@ -1276,7 +1275,6 @@ static struct platform_driver tegra_smmu_driver = { | |||
| 1276 | 1275 | ||
| 1277 | static int __devinit tegra_smmu_init(void) | 1276 | static int __devinit tegra_smmu_init(void) |
| 1278 | { | 1277 | { |
| 1279 | bus_set_iommu(&platform_bus_type, &smmu_iommu_ops); | ||
| 1280 | return platform_driver_register(&tegra_smmu_driver); | 1278 | return platform_driver_register(&tegra_smmu_driver); |
| 1281 | } | 1279 | } |
| 1282 | 1280 | ||
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/lguest/core.c b/drivers/lguest/core.c index b5fdcb78a75b..a5ebc0083d87 100644 --- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c | |||
| @@ -225,7 +225,7 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user) | |||
| 225 | * eventfd (ie. the appropriate virtqueue thread)? | 225 | * eventfd (ie. the appropriate virtqueue thread)? |
| 226 | */ | 226 | */ |
| 227 | if (!send_notify_to_eventfd(cpu)) { | 227 | if (!send_notify_to_eventfd(cpu)) { |
| 228 | /* OK, we tell the main Laucher. */ | 228 | /* OK, we tell the main Launcher. */ |
| 229 | if (put_user(cpu->pending_notify, user)) | 229 | if (put_user(cpu->pending_notify, user)) |
| 230 | return -EFAULT; | 230 | return -EFAULT; |
| 231 | return sizeof(cpu->pending_notify); | 231 | return sizeof(cpu->pending_notify); |
diff --git a/drivers/md/dm-bio-prison.c b/drivers/md/dm-bio-prison.c index e4e841567459..aefb78e3cbf9 100644 --- a/drivers/md/dm-bio-prison.c +++ b/drivers/md/dm-bio-prison.c | |||
| @@ -208,31 +208,6 @@ void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios) | |||
| 208 | EXPORT_SYMBOL_GPL(dm_cell_release); | 208 | EXPORT_SYMBOL_GPL(dm_cell_release); |
| 209 | 209 | ||
| 210 | /* | 210 | /* |
| 211 | * There are a couple of places where we put a bio into a cell briefly | ||
| 212 | * before taking it out again. In these situations we know that no other | ||
| 213 | * bio may be in the cell. This function releases the cell, and also does | ||
| 214 | * a sanity check. | ||
| 215 | */ | ||
| 216 | static void __cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) | ||
| 217 | { | ||
| 218 | BUG_ON(cell->holder != bio); | ||
| 219 | BUG_ON(!bio_list_empty(&cell->bios)); | ||
| 220 | |||
| 221 | __cell_release(cell, NULL); | ||
| 222 | } | ||
| 223 | |||
| 224 | void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) | ||
| 225 | { | ||
| 226 | unsigned long flags; | ||
| 227 | struct dm_bio_prison *prison = cell->prison; | ||
| 228 | |||
| 229 | spin_lock_irqsave(&prison->lock, flags); | ||
| 230 | __cell_release_singleton(cell, bio); | ||
| 231 | spin_unlock_irqrestore(&prison->lock, flags); | ||
| 232 | } | ||
| 233 | EXPORT_SYMBOL_GPL(dm_cell_release_singleton); | ||
| 234 | |||
| 235 | /* | ||
| 236 | * Sometimes we don't want the holder, just the additional bios. | 211 | * Sometimes we don't want the holder, just the additional bios. |
| 237 | */ | 212 | */ |
| 238 | static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates) | 213 | static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates) |
diff --git a/drivers/md/dm-bio-prison.h b/drivers/md/dm-bio-prison.h index 4e0ac376700a..53d1a7a84e2f 100644 --- a/drivers/md/dm-bio-prison.h +++ b/drivers/md/dm-bio-prison.h | |||
| @@ -44,7 +44,6 @@ int dm_bio_detain(struct dm_bio_prison *prison, struct dm_cell_key *key, | |||
| 44 | struct bio *inmate, struct dm_bio_prison_cell **ref); | 44 | struct bio *inmate, struct dm_bio_prison_cell **ref); |
| 45 | 45 | ||
| 46 | void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios); | 46 | void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios); |
| 47 | void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio); // FIXME: bio arg not needed | ||
| 48 | void dm_cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates); | 47 | void dm_cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates); |
| 49 | void dm_cell_error(struct dm_bio_prison_cell *cell); | 48 | void dm_cell_error(struct dm_bio_prison_cell *cell); |
| 50 | 49 | ||
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index bbf459bca61d..f7369f9d8595 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
| @@ -1689,8 +1689,7 @@ bad: | |||
| 1689 | return ret; | 1689 | return ret; |
| 1690 | } | 1690 | } |
| 1691 | 1691 | ||
| 1692 | static int crypt_map(struct dm_target *ti, struct bio *bio, | 1692 | static int crypt_map(struct dm_target *ti, struct bio *bio) |
| 1693 | union map_info *map_context) | ||
| 1694 | { | 1693 | { |
| 1695 | struct dm_crypt_io *io; | 1694 | struct dm_crypt_io *io; |
| 1696 | struct crypt_config *cc = ti->private; | 1695 | struct crypt_config *cc = ti->private; |
| @@ -1846,7 +1845,7 @@ static int crypt_iterate_devices(struct dm_target *ti, | |||
| 1846 | 1845 | ||
| 1847 | static struct target_type crypt_target = { | 1846 | static struct target_type crypt_target = { |
| 1848 | .name = "crypt", | 1847 | .name = "crypt", |
| 1849 | .version = {1, 11, 0}, | 1848 | .version = {1, 12, 0}, |
| 1850 | .module = THIS_MODULE, | 1849 | .module = THIS_MODULE, |
| 1851 | .ctr = crypt_ctr, | 1850 | .ctr = crypt_ctr, |
| 1852 | .dtr = crypt_dtr, | 1851 | .dtr = crypt_dtr, |
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index f53846f9ab50..cc1bd048acb2 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c | |||
| @@ -274,8 +274,7 @@ static void delay_resume(struct dm_target *ti) | |||
| 274 | atomic_set(&dc->may_delay, 1); | 274 | atomic_set(&dc->may_delay, 1); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | static int delay_map(struct dm_target *ti, struct bio *bio, | 277 | static int delay_map(struct dm_target *ti, struct bio *bio) |
| 278 | union map_info *map_context) | ||
| 279 | { | 278 | { |
| 280 | struct delay_c *dc = ti->private; | 279 | struct delay_c *dc = ti->private; |
| 281 | 280 | ||
| @@ -338,7 +337,7 @@ out: | |||
| 338 | 337 | ||
| 339 | static struct target_type delay_target = { | 338 | static struct target_type delay_target = { |
| 340 | .name = "delay", | 339 | .name = "delay", |
| 341 | .version = {1, 1, 0}, | 340 | .version = {1, 2, 0}, |
| 342 | .module = THIS_MODULE, | 341 | .module = THIS_MODULE, |
| 343 | .ctr = delay_ctr, | 342 | .ctr = delay_ctr, |
| 344 | .dtr = delay_dtr, | 343 | .dtr = delay_dtr, |
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index cc15543a6ad7..9721f2ffb1a2 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c | |||
| @@ -39,6 +39,10 @@ enum feature_flag_bits { | |||
| 39 | DROP_WRITES | 39 | DROP_WRITES |
| 40 | }; | 40 | }; |
| 41 | 41 | ||
| 42 | struct per_bio_data { | ||
| 43 | bool bio_submitted; | ||
| 44 | }; | ||
| 45 | |||
| 42 | static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, | 46 | static int parse_features(struct dm_arg_set *as, struct flakey_c *fc, |
| 43 | struct dm_target *ti) | 47 | struct dm_target *ti) |
| 44 | { | 48 | { |
| @@ -214,6 +218,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 214 | 218 | ||
| 215 | ti->num_flush_requests = 1; | 219 | ti->num_flush_requests = 1; |
| 216 | ti->num_discard_requests = 1; | 220 | ti->num_discard_requests = 1; |
| 221 | ti->per_bio_data_size = sizeof(struct per_bio_data); | ||
| 217 | ti->private = fc; | 222 | ti->private = fc; |
| 218 | return 0; | 223 | return 0; |
| 219 | 224 | ||
| @@ -265,11 +270,12 @@ static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc) | |||
| 265 | } | 270 | } |
| 266 | } | 271 | } |
| 267 | 272 | ||
| 268 | static int flakey_map(struct dm_target *ti, struct bio *bio, | 273 | static int flakey_map(struct dm_target *ti, struct bio *bio) |
| 269 | union map_info *map_context) | ||
| 270 | { | 274 | { |
| 271 | struct flakey_c *fc = ti->private; | 275 | struct flakey_c *fc = ti->private; |
| 272 | unsigned elapsed; | 276 | unsigned elapsed; |
| 277 | struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data)); | ||
| 278 | pb->bio_submitted = false; | ||
| 273 | 279 | ||
| 274 | /* Are we alive ? */ | 280 | /* Are we alive ? */ |
| 275 | elapsed = (jiffies - fc->start_time) / HZ; | 281 | elapsed = (jiffies - fc->start_time) / HZ; |
| @@ -277,7 +283,7 @@ static int flakey_map(struct dm_target *ti, struct bio *bio, | |||
| 277 | /* | 283 | /* |
| 278 | * Flag this bio as submitted while down. | 284 | * Flag this bio as submitted while down. |
| 279 | */ | 285 | */ |
| 280 | map_context->ll = 1; | 286 | pb->bio_submitted = true; |
| 281 | 287 | ||
| 282 | /* | 288 | /* |
| 283 | * Map reads as normal. | 289 | * Map reads as normal. |
| @@ -314,17 +320,16 @@ map_bio: | |||
| 314 | return DM_MAPIO_REMAPPED; | 320 | return DM_MAPIO_REMAPPED; |
| 315 | } | 321 | } |
| 316 | 322 | ||
| 317 | static int flakey_end_io(struct dm_target *ti, struct bio *bio, | 323 | static int flakey_end_io(struct dm_target *ti, struct bio *bio, int error) |
| 318 | int error, union map_info *map_context) | ||
| 319 | { | 324 | { |
| 320 | struct flakey_c *fc = ti->private; | 325 | struct flakey_c *fc = ti->private; |
| 321 | unsigned bio_submitted_while_down = map_context->ll; | 326 | struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data)); |
| 322 | 327 | ||
| 323 | /* | 328 | /* |
| 324 | * Corrupt successful READs while in down state. | 329 | * Corrupt successful READs while in down state. |
| 325 | * If flags were specified, only corrupt those that match. | 330 | * If flags were specified, only corrupt those that match. |
| 326 | */ | 331 | */ |
| 327 | if (fc->corrupt_bio_byte && !error && bio_submitted_while_down && | 332 | if (fc->corrupt_bio_byte && !error && pb->bio_submitted && |
| 328 | (bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) && | 333 | (bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) && |
| 329 | all_corrupt_bio_flags_match(bio, fc)) | 334 | all_corrupt_bio_flags_match(bio, fc)) |
| 330 | corrupt_bio_data(bio, fc); | 335 | corrupt_bio_data(bio, fc); |
| @@ -406,7 +411,7 @@ static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_ | |||
| 406 | 411 | ||
| 407 | static struct target_type flakey_target = { | 412 | static struct target_type flakey_target = { |
| 408 | .name = "flakey", | 413 | .name = "flakey", |
| 409 | .version = {1, 2, 0}, | 414 | .version = {1, 3, 0}, |
| 410 | .module = THIS_MODULE, | 415 | .module = THIS_MODULE, |
| 411 | .ctr = flakey_ctr, | 416 | .ctr = flakey_ctr, |
| 412 | .dtr = flakey_dtr, | 417 | .dtr = flakey_dtr, |
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 1c46f97d6664..ea49834377c8 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c | |||
| @@ -287,7 +287,8 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, | |||
| 287 | unsigned num_bvecs; | 287 | unsigned num_bvecs; |
| 288 | sector_t remaining = where->count; | 288 | sector_t remaining = where->count; |
| 289 | struct request_queue *q = bdev_get_queue(where->bdev); | 289 | struct request_queue *q = bdev_get_queue(where->bdev); |
| 290 | sector_t discard_sectors; | 290 | unsigned short logical_block_size = queue_logical_block_size(q); |
| 291 | sector_t num_sectors; | ||
| 291 | 292 | ||
| 292 | /* | 293 | /* |
| 293 | * where->count may be zero if rw holds a flush and we need to | 294 | * where->count may be zero if rw holds a flush and we need to |
| @@ -297,7 +298,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, | |||
| 297 | /* | 298 | /* |
| 298 | * Allocate a suitably sized-bio. | 299 | * Allocate a suitably sized-bio. |
| 299 | */ | 300 | */ |
| 300 | if (rw & REQ_DISCARD) | 301 | if ((rw & REQ_DISCARD) || (rw & REQ_WRITE_SAME)) |
| 301 | num_bvecs = 1; | 302 | num_bvecs = 1; |
| 302 | else | 303 | else |
| 303 | num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev), | 304 | num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev), |
| @@ -310,9 +311,21 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, | |||
| 310 | store_io_and_region_in_bio(bio, io, region); | 311 | store_io_and_region_in_bio(bio, io, region); |
| 311 | 312 | ||
| 312 | if (rw & REQ_DISCARD) { | 313 | if (rw & REQ_DISCARD) { |
| 313 | discard_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining); | 314 | num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining); |
| 314 | bio->bi_size = discard_sectors << SECTOR_SHIFT; | 315 | bio->bi_size = num_sectors << SECTOR_SHIFT; |
| 315 | remaining -= discard_sectors; | 316 | remaining -= num_sectors; |
| 317 | } else if (rw & REQ_WRITE_SAME) { | ||
| 318 | /* | ||
| 319 | * WRITE SAME only uses a single page. | ||
| 320 | */ | ||
| 321 | dp->get_page(dp, &page, &len, &offset); | ||
| 322 | bio_add_page(bio, page, logical_block_size, offset); | ||
| 323 | num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining); | ||
| 324 | bio->bi_size = num_sectors << SECTOR_SHIFT; | ||
| 325 | |||
| 326 | offset = 0; | ||
| 327 | remaining -= num_sectors; | ||
| 328 | dp->next_page(dp); | ||
| 316 | } else while (remaining) { | 329 | } else while (remaining) { |
| 317 | /* | 330 | /* |
| 318 | * Try and add as many pages as possible. | 331 | * Try and add as many pages as possible. |
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index afd95986d099..0666b5d14b88 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
| @@ -1543,7 +1543,21 @@ static int check_version(unsigned int cmd, struct dm_ioctl __user *user) | |||
| 1543 | return r; | 1543 | return r; |
| 1544 | } | 1544 | } |
| 1545 | 1545 | ||
| 1546 | static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) | 1546 | #define DM_PARAMS_VMALLOC 0x0001 /* Params alloced with vmalloc not kmalloc */ |
| 1547 | #define DM_WIPE_BUFFER 0x0010 /* Wipe input buffer before returning from ioctl */ | ||
| 1548 | |||
| 1549 | static void free_params(struct dm_ioctl *param, size_t param_size, int param_flags) | ||
| 1550 | { | ||
| 1551 | if (param_flags & DM_WIPE_BUFFER) | ||
| 1552 | memset(param, 0, param_size); | ||
| 1553 | |||
| 1554 | if (param_flags & DM_PARAMS_VMALLOC) | ||
| 1555 | vfree(param); | ||
| 1556 | else | ||
| 1557 | kfree(param); | ||
| 1558 | } | ||
| 1559 | |||
| 1560 | static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param, int *param_flags) | ||
| 1547 | { | 1561 | { |
| 1548 | struct dm_ioctl tmp, *dmi; | 1562 | struct dm_ioctl tmp, *dmi; |
| 1549 | int secure_data; | 1563 | int secure_data; |
| @@ -1556,7 +1570,21 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) | |||
| 1556 | 1570 | ||
| 1557 | secure_data = tmp.flags & DM_SECURE_DATA_FLAG; | 1571 | secure_data = tmp.flags & DM_SECURE_DATA_FLAG; |
| 1558 | 1572 | ||
| 1559 | dmi = vmalloc(tmp.data_size); | 1573 | *param_flags = secure_data ? DM_WIPE_BUFFER : 0; |
| 1574 | |||
| 1575 | /* | ||
| 1576 | * Try to avoid low memory issues when a device is suspended. | ||
| 1577 | * Use kmalloc() rather than vmalloc() when we can. | ||
| 1578 | */ | ||
| 1579 | dmi = NULL; | ||
| 1580 | if (tmp.data_size <= KMALLOC_MAX_SIZE) | ||
| 1581 | dmi = kmalloc(tmp.data_size, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); | ||
| 1582 | |||
| 1583 | if (!dmi) { | ||
| 1584 | dmi = __vmalloc(tmp.data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH, PAGE_KERNEL); | ||
| 1585 | *param_flags |= DM_PARAMS_VMALLOC; | ||
| 1586 | } | ||
| 1587 | |||
| 1560 | if (!dmi) { | 1588 | if (!dmi) { |
| 1561 | if (secure_data && clear_user(user, tmp.data_size)) | 1589 | if (secure_data && clear_user(user, tmp.data_size)) |
| 1562 | return -EFAULT; | 1590 | return -EFAULT; |
| @@ -1566,6 +1594,14 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) | |||
| 1566 | if (copy_from_user(dmi, user, tmp.data_size)) | 1594 | if (copy_from_user(dmi, user, tmp.data_size)) |
| 1567 | goto bad; | 1595 | goto bad; |
| 1568 | 1596 | ||
| 1597 | /* | ||
| 1598 | * Abort if something changed the ioctl data while it was being copied. | ||
| 1599 | */ | ||
| 1600 | if (dmi->data_size != tmp.data_size) { | ||
| 1601 | DMERR("rejecting ioctl: data size modified while processing parameters"); | ||
| 1602 | goto bad; | ||
| 1603 | } | ||
| 1604 | |||
| 1569 | /* Wipe the user buffer so we do not return it to userspace */ | 1605 | /* Wipe the user buffer so we do not return it to userspace */ |
| 1570 | if (secure_data && clear_user(user, tmp.data_size)) | 1606 | if (secure_data && clear_user(user, tmp.data_size)) |
| 1571 | goto bad; | 1607 | goto bad; |
| @@ -1574,9 +1610,8 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param) | |||
| 1574 | return 0; | 1610 | return 0; |
| 1575 | 1611 | ||
| 1576 | bad: | 1612 | bad: |
| 1577 | if (secure_data) | 1613 | free_params(dmi, tmp.data_size, *param_flags); |
| 1578 | memset(dmi, 0, tmp.data_size); | 1614 | |
| 1579 | vfree(dmi); | ||
| 1580 | return -EFAULT; | 1615 | return -EFAULT; |
| 1581 | } | 1616 | } |
| 1582 | 1617 | ||
| @@ -1613,7 +1648,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param) | |||
| 1613 | static int ctl_ioctl(uint command, struct dm_ioctl __user *user) | 1648 | static int ctl_ioctl(uint command, struct dm_ioctl __user *user) |
| 1614 | { | 1649 | { |
| 1615 | int r = 0; | 1650 | int r = 0; |
| 1616 | int wipe_buffer; | 1651 | int param_flags; |
| 1617 | unsigned int cmd; | 1652 | unsigned int cmd; |
| 1618 | struct dm_ioctl *uninitialized_var(param); | 1653 | struct dm_ioctl *uninitialized_var(param); |
| 1619 | ioctl_fn fn = NULL; | 1654 | ioctl_fn fn = NULL; |
| @@ -1649,24 +1684,14 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user) | |||
| 1649 | } | 1684 | } |
| 1650 | 1685 | ||
| 1651 | /* | 1686 | /* |
| 1652 | * Trying to avoid low memory issues when a device is | ||
| 1653 | * suspended. | ||
| 1654 | */ | ||
| 1655 | current->flags |= PF_MEMALLOC; | ||
| 1656 | |||
| 1657 | /* | ||
| 1658 | * Copy the parameters into kernel space. | 1687 | * Copy the parameters into kernel space. |
| 1659 | */ | 1688 | */ |
| 1660 | r = copy_params(user, ¶m); | 1689 | r = copy_params(user, ¶m, ¶m_flags); |
| 1661 | |||
| 1662 | current->flags &= ~PF_MEMALLOC; | ||
| 1663 | 1690 | ||
| 1664 | if (r) | 1691 | if (r) |
| 1665 | return r; | 1692 | return r; |
| 1666 | 1693 | ||
| 1667 | input_param_size = param->data_size; | 1694 | input_param_size = param->data_size; |
| 1668 | wipe_buffer = param->flags & DM_SECURE_DATA_FLAG; | ||
| 1669 | |||
| 1670 | r = validate_params(cmd, param); | 1695 | r = validate_params(cmd, param); |
| 1671 | if (r) | 1696 | if (r) |
| 1672 | goto out; | 1697 | goto out; |
| @@ -1681,10 +1706,7 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user) | |||
| 1681 | r = -EFAULT; | 1706 | r = -EFAULT; |
| 1682 | 1707 | ||
| 1683 | out: | 1708 | out: |
| 1684 | if (wipe_buffer) | 1709 | free_params(param, input_param_size, param_flags); |
| 1685 | memset(param, 0, input_param_size); | ||
| 1686 | |||
| 1687 | vfree(param); | ||
| 1688 | return r; | 1710 | return r; |
| 1689 | } | 1711 | } |
| 1690 | 1712 | ||
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c index bed444c93d8d..68c02673263b 100644 --- a/drivers/md/dm-kcopyd.c +++ b/drivers/md/dm-kcopyd.c | |||
| @@ -349,7 +349,7 @@ static void complete_io(unsigned long error, void *context) | |||
| 349 | struct dm_kcopyd_client *kc = job->kc; | 349 | struct dm_kcopyd_client *kc = job->kc; |
| 350 | 350 | ||
| 351 | if (error) { | 351 | if (error) { |
| 352 | if (job->rw == WRITE) | 352 | if (job->rw & WRITE) |
| 353 | job->write_err |= error; | 353 | job->write_err |= error; |
| 354 | else | 354 | else |
| 355 | job->read_err = 1; | 355 | job->read_err = 1; |
| @@ -361,7 +361,7 @@ static void complete_io(unsigned long error, void *context) | |||
| 361 | } | 361 | } |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | if (job->rw == WRITE) | 364 | if (job->rw & WRITE) |
| 365 | push(&kc->complete_jobs, job); | 365 | push(&kc->complete_jobs, job); |
| 366 | 366 | ||
| 367 | else { | 367 | else { |
| @@ -432,7 +432,7 @@ static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc, | |||
| 432 | 432 | ||
| 433 | if (r < 0) { | 433 | if (r < 0) { |
| 434 | /* error this rogue job */ | 434 | /* error this rogue job */ |
| 435 | if (job->rw == WRITE) | 435 | if (job->rw & WRITE) |
| 436 | job->write_err = (unsigned long) -1L; | 436 | job->write_err = (unsigned long) -1L; |
| 437 | else | 437 | else |
| 438 | job->read_err = 1; | 438 | job->read_err = 1; |
| @@ -585,6 +585,7 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from, | |||
| 585 | unsigned int flags, dm_kcopyd_notify_fn fn, void *context) | 585 | unsigned int flags, dm_kcopyd_notify_fn fn, void *context) |
| 586 | { | 586 | { |
| 587 | struct kcopyd_job *job; | 587 | struct kcopyd_job *job; |
| 588 | int i; | ||
| 588 | 589 | ||
| 589 | /* | 590 | /* |
| 590 | * Allocate an array of jobs consisting of one master job | 591 | * Allocate an array of jobs consisting of one master job |
| @@ -611,7 +612,16 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from, | |||
| 611 | memset(&job->source, 0, sizeof job->source); | 612 | memset(&job->source, 0, sizeof job->source); |
| 612 | job->source.count = job->dests[0].count; | 613 | job->source.count = job->dests[0].count; |
| 613 | job->pages = &zero_page_list; | 614 | job->pages = &zero_page_list; |
| 614 | job->rw = WRITE; | 615 | |
| 616 | /* | ||
| 617 | * Use WRITE SAME to optimize zeroing if all dests support it. | ||
| 618 | */ | ||
| 619 | job->rw = WRITE | REQ_WRITE_SAME; | ||
| 620 | for (i = 0; i < job->num_dests; i++) | ||
| 621 | if (!bdev_write_same(job->dests[i].bdev)) { | ||
| 622 | job->rw = WRITE; | ||
| 623 | break; | ||
| 624 | } | ||
| 615 | } | 625 | } |
| 616 | 626 | ||
| 617 | job->fn = fn; | 627 | job->fn = fn; |
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 1bf19a93eef0..328cad5617ab 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c | |||
| @@ -55,6 +55,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 55 | 55 | ||
| 56 | ti->num_flush_requests = 1; | 56 | ti->num_flush_requests = 1; |
| 57 | ti->num_discard_requests = 1; | 57 | ti->num_discard_requests = 1; |
| 58 | ti->num_write_same_requests = 1; | ||
| 58 | ti->private = lc; | 59 | ti->private = lc; |
| 59 | return 0; | 60 | return 0; |
| 60 | 61 | ||
| @@ -87,8 +88,7 @@ static void linear_map_bio(struct dm_target *ti, struct bio *bio) | |||
| 87 | bio->bi_sector = linear_map_sector(ti, bio->bi_sector); | 88 | bio->bi_sector = linear_map_sector(ti, bio->bi_sector); |
| 88 | } | 89 | } |
| 89 | 90 | ||
| 90 | static int linear_map(struct dm_target *ti, struct bio *bio, | 91 | static int linear_map(struct dm_target *ti, struct bio *bio) |
| 91 | union map_info *map_context) | ||
| 92 | { | 92 | { |
| 93 | linear_map_bio(ti, bio); | 93 | linear_map_bio(ti, bio); |
| 94 | 94 | ||
| @@ -155,7 +155,7 @@ static int linear_iterate_devices(struct dm_target *ti, | |||
| 155 | 155 | ||
| 156 | static struct target_type linear_target = { | 156 | static struct target_type linear_target = { |
| 157 | .name = "linear", | 157 | .name = "linear", |
| 158 | .version = {1, 1, 0}, | 158 | .version = {1, 2, 0}, |
| 159 | .module = THIS_MODULE, | 159 | .module = THIS_MODULE, |
| 160 | .ctr = linear_ctr, | 160 | .ctr = linear_ctr, |
| 161 | .dtr = linear_dtr, | 161 | .dtr = linear_dtr, |
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 45d94a7e7f6d..3d8984edeff7 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
| @@ -295,9 +295,11 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size) | |||
| 295 | * Choose a reasonable default. All figures in sectors. | 295 | * Choose a reasonable default. All figures in sectors. |
| 296 | */ | 296 | */ |
| 297 | if (min_region_size > (1 << 13)) { | 297 | if (min_region_size > (1 << 13)) { |
| 298 | /* If not a power of 2, make it the next power of 2 */ | ||
| 299 | if (min_region_size & (min_region_size - 1)) | ||
| 300 | region_size = 1 << fls(region_size); | ||
| 298 | DMINFO("Choosing default region size of %lu sectors", | 301 | DMINFO("Choosing default region size of %lu sectors", |
| 299 | region_size); | 302 | region_size); |
| 300 | region_size = min_region_size; | ||
| 301 | } else { | 303 | } else { |
| 302 | DMINFO("Choosing default region size of 4MiB"); | 304 | DMINFO("Choosing default region size of 4MiB"); |
| 303 | region_size = 1 << 13; /* sectors */ | 305 | region_size = 1 << 13; /* sectors */ |
| @@ -1216,7 +1218,7 @@ static void raid_dtr(struct dm_target *ti) | |||
| 1216 | context_free(rs); | 1218 | context_free(rs); |
| 1217 | } | 1219 | } |
| 1218 | 1220 | ||
| 1219 | static int raid_map(struct dm_target *ti, struct bio *bio, union map_info *map_context) | 1221 | static int raid_map(struct dm_target *ti, struct bio *bio) |
| 1220 | { | 1222 | { |
| 1221 | struct raid_set *rs = ti->private; | 1223 | struct raid_set *rs = ti->private; |
| 1222 | struct mddev *mddev = &rs->md; | 1224 | struct mddev *mddev = &rs->md; |
| @@ -1430,7 +1432,7 @@ static void raid_resume(struct dm_target *ti) | |||
| 1430 | 1432 | ||
| 1431 | static struct target_type raid_target = { | 1433 | static struct target_type raid_target = { |
| 1432 | .name = "raid", | 1434 | .name = "raid", |
| 1433 | .version = {1, 3, 1}, | 1435 | .version = {1, 4, 0}, |
| 1434 | .module = THIS_MODULE, | 1436 | .module = THIS_MODULE, |
| 1435 | .ctr = raid_ctr, | 1437 | .ctr = raid_ctr, |
| 1436 | .dtr = raid_dtr, | 1438 | .dtr = raid_dtr, |
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index fd61f98ee1f6..fa519185ebba 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
| @@ -61,7 +61,6 @@ struct mirror_set { | |||
| 61 | struct dm_region_hash *rh; | 61 | struct dm_region_hash *rh; |
| 62 | struct dm_kcopyd_client *kcopyd_client; | 62 | struct dm_kcopyd_client *kcopyd_client; |
| 63 | struct dm_io_client *io_client; | 63 | struct dm_io_client *io_client; |
| 64 | mempool_t *read_record_pool; | ||
| 65 | 64 | ||
| 66 | /* recovery */ | 65 | /* recovery */ |
| 67 | region_t nr_regions; | 66 | region_t nr_regions; |
| @@ -139,14 +138,13 @@ static void dispatch_bios(void *context, struct bio_list *bio_list) | |||
| 139 | queue_bio(ms, bio, WRITE); | 138 | queue_bio(ms, bio, WRITE); |
| 140 | } | 139 | } |
| 141 | 140 | ||
| 142 | #define MIN_READ_RECORDS 20 | 141 | struct dm_raid1_bio_record { |
| 143 | struct dm_raid1_read_record { | ||
| 144 | struct mirror *m; | 142 | struct mirror *m; |
| 143 | /* if details->bi_bdev == NULL, details were not saved */ | ||
| 145 | struct dm_bio_details details; | 144 | struct dm_bio_details details; |
| 145 | region_t write_region; | ||
| 146 | }; | 146 | }; |
| 147 | 147 | ||
| 148 | static struct kmem_cache *_dm_raid1_read_record_cache; | ||
| 149 | |||
| 150 | /* | 148 | /* |
| 151 | * Every mirror should look like this one. | 149 | * Every mirror should look like this one. |
| 152 | */ | 150 | */ |
| @@ -876,19 +874,9 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, | |||
| 876 | atomic_set(&ms->suspend, 0); | 874 | atomic_set(&ms->suspend, 0); |
| 877 | atomic_set(&ms->default_mirror, DEFAULT_MIRROR); | 875 | atomic_set(&ms->default_mirror, DEFAULT_MIRROR); |
| 878 | 876 | ||
| 879 | ms->read_record_pool = mempool_create_slab_pool(MIN_READ_RECORDS, | ||
| 880 | _dm_raid1_read_record_cache); | ||
| 881 | |||
| 882 | if (!ms->read_record_pool) { | ||
| 883 | ti->error = "Error creating mirror read_record_pool"; | ||
| 884 | kfree(ms); | ||
| 885 | return NULL; | ||
| 886 | } | ||
| 887 | |||
| 888 | ms->io_client = dm_io_client_create(); | 877 | ms->io_client = dm_io_client_create(); |
| 889 | if (IS_ERR(ms->io_client)) { | 878 | if (IS_ERR(ms->io_client)) { |
| 890 | ti->error = "Error creating dm_io client"; | 879 | ti->error = "Error creating dm_io client"; |
| 891 | mempool_destroy(ms->read_record_pool); | ||
| 892 | kfree(ms); | 880 | kfree(ms); |
| 893 | return NULL; | 881 | return NULL; |
| 894 | } | 882 | } |
| @@ -900,7 +888,6 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, | |||
| 900 | if (IS_ERR(ms->rh)) { | 888 | if (IS_ERR(ms->rh)) { |
| 901 | ti->error = "Error creating dirty region hash"; | 889 | ti->error = "Error creating dirty region hash"; |
| 902 | dm_io_client_destroy(ms->io_client); | 890 | dm_io_client_destroy(ms->io_client); |
| 903 | mempool_destroy(ms->read_record_pool); | ||
| 904 | kfree(ms); | 891 | kfree(ms); |
| 905 | return NULL; | 892 | return NULL; |
| 906 | } | 893 | } |
| @@ -916,7 +903,6 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti, | |||
| 916 | 903 | ||
| 917 | dm_io_client_destroy(ms->io_client); | 904 | dm_io_client_destroy(ms->io_client); |
| 918 | dm_region_hash_destroy(ms->rh); | 905 | dm_region_hash_destroy(ms->rh); |
| 919 | mempool_destroy(ms->read_record_pool); | ||
| 920 | kfree(ms); | 906 | kfree(ms); |
| 921 | } | 907 | } |
| 922 | 908 | ||
| @@ -1088,6 +1074,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 1088 | 1074 | ||
| 1089 | ti->num_flush_requests = 1; | 1075 | ti->num_flush_requests = 1; |
| 1090 | ti->num_discard_requests = 1; | 1076 | ti->num_discard_requests = 1; |
| 1077 | ti->per_bio_data_size = sizeof(struct dm_raid1_bio_record); | ||
| 1091 | ti->discard_zeroes_data_unsupported = true; | 1078 | ti->discard_zeroes_data_unsupported = true; |
| 1092 | 1079 | ||
| 1093 | ms->kmirrord_wq = alloc_workqueue("kmirrord", | 1080 | ms->kmirrord_wq = alloc_workqueue("kmirrord", |
| @@ -1155,18 +1142,20 @@ static void mirror_dtr(struct dm_target *ti) | |||
| 1155 | /* | 1142 | /* |
| 1156 | * Mirror mapping function | 1143 | * Mirror mapping function |
| 1157 | */ | 1144 | */ |
| 1158 | static int mirror_map(struct dm_target *ti, struct bio *bio, | 1145 | static int mirror_map(struct dm_target *ti, struct bio *bio) |
| 1159 | union map_info *map_context) | ||
| 1160 | { | 1146 | { |
| 1161 | int r, rw = bio_rw(bio); | 1147 | int r, rw = bio_rw(bio); |
| 1162 | struct mirror *m; | 1148 | struct mirror *m; |
| 1163 | struct mirror_set *ms = ti->private; | 1149 | struct mirror_set *ms = ti->private; |
| 1164 | struct dm_raid1_read_record *read_record = NULL; | ||
| 1165 | struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); | 1150 | struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); |
| 1151 | struct dm_raid1_bio_record *bio_record = | ||
| 1152 | dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record)); | ||
| 1153 | |||
| 1154 | bio_record->details.bi_bdev = NULL; | ||
| 1166 | 1155 | ||
| 1167 | if (rw == WRITE) { | 1156 | if (rw == WRITE) { |
| 1168 | /* Save region for mirror_end_io() handler */ | 1157 | /* Save region for mirror_end_io() handler */ |
| 1169 | map_context->ll = dm_rh_bio_to_region(ms->rh, bio); | 1158 | bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio); |
| 1170 | queue_bio(ms, bio, rw); | 1159 | queue_bio(ms, bio, rw); |
| 1171 | return DM_MAPIO_SUBMITTED; | 1160 | return DM_MAPIO_SUBMITTED; |
| 1172 | } | 1161 | } |
| @@ -1194,33 +1183,29 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, | |||
| 1194 | if (unlikely(!m)) | 1183 | if (unlikely(!m)) |
| 1195 | return -EIO; | 1184 | return -EIO; |
| 1196 | 1185 | ||
| 1197 | read_record = mempool_alloc(ms->read_record_pool, GFP_NOIO); | 1186 | dm_bio_record(&bio_record->details, bio); |
| 1198 | if (likely(read_record)) { | 1187 | bio_record->m = m; |
| 1199 | dm_bio_record(&read_record->details, bio); | ||
| 1200 | map_context->ptr = read_record; | ||
| 1201 | read_record->m = m; | ||
| 1202 | } | ||
| 1203 | 1188 | ||
| 1204 | map_bio(m, bio); | 1189 | map_bio(m, bio); |
| 1205 | 1190 | ||
| 1206 | return DM_MAPIO_REMAPPED; | 1191 | return DM_MAPIO_REMAPPED; |
| 1207 | } | 1192 | } |
| 1208 | 1193 | ||
| 1209 | static int mirror_end_io(struct dm_target *ti, struct bio *bio, | 1194 | static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error) |
| 1210 | int error, union map_info *map_context) | ||
| 1211 | { | 1195 | { |
| 1212 | int rw = bio_rw(bio); | 1196 | int rw = bio_rw(bio); |
| 1213 | struct mirror_set *ms = (struct mirror_set *) ti->private; | 1197 | struct mirror_set *ms = (struct mirror_set *) ti->private; |
| 1214 | struct mirror *m = NULL; | 1198 | struct mirror *m = NULL; |
| 1215 | struct dm_bio_details *bd = NULL; | 1199 | struct dm_bio_details *bd = NULL; |
| 1216 | struct dm_raid1_read_record *read_record = map_context->ptr; | 1200 | struct dm_raid1_bio_record *bio_record = |
| 1201 | dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record)); | ||
| 1217 | 1202 | ||
| 1218 | /* | 1203 | /* |
| 1219 | * We need to dec pending if this was a write. | 1204 | * We need to dec pending if this was a write. |
| 1220 | */ | 1205 | */ |
| 1221 | if (rw == WRITE) { | 1206 | if (rw == WRITE) { |
| 1222 | if (!(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) | 1207 | if (!(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) |
| 1223 | dm_rh_dec(ms->rh, map_context->ll); | 1208 | dm_rh_dec(ms->rh, bio_record->write_region); |
| 1224 | return error; | 1209 | return error; |
| 1225 | } | 1210 | } |
| 1226 | 1211 | ||
| @@ -1231,7 +1216,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, | |||
| 1231 | goto out; | 1216 | goto out; |
| 1232 | 1217 | ||
| 1233 | if (unlikely(error)) { | 1218 | if (unlikely(error)) { |
| 1234 | if (!read_record) { | 1219 | if (!bio_record->details.bi_bdev) { |
| 1235 | /* | 1220 | /* |
| 1236 | * There wasn't enough memory to record necessary | 1221 | * There wasn't enough memory to record necessary |
| 1237 | * information for a retry or there was no other | 1222 | * information for a retry or there was no other |
| @@ -1241,7 +1226,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, | |||
| 1241 | return -EIO; | 1226 | return -EIO; |
| 1242 | } | 1227 | } |
| 1243 | 1228 | ||
| 1244 | m = read_record->m; | 1229 | m = bio_record->m; |
| 1245 | 1230 | ||
| 1246 | DMERR("Mirror read failed from %s. Trying alternative device.", | 1231 | DMERR("Mirror read failed from %s. Trying alternative device.", |
| 1247 | m->dev->name); | 1232 | m->dev->name); |
| @@ -1253,22 +1238,18 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, | |||
| 1253 | * mirror. | 1238 | * mirror. |
| 1254 | */ | 1239 | */ |
| 1255 | if (default_ok(m) || mirror_available(ms, bio)) { | 1240 | if (default_ok(m) || mirror_available(ms, bio)) { |
| 1256 | bd = &read_record->details; | 1241 | bd = &bio_record->details; |
| 1257 | 1242 | ||
| 1258 | dm_bio_restore(bd, bio); | 1243 | dm_bio_restore(bd, bio); |
| 1259 | mempool_free(read_record, ms->read_record_pool); | 1244 | bio_record->details.bi_bdev = NULL; |
| 1260 | map_context->ptr = NULL; | ||
| 1261 | queue_bio(ms, bio, rw); | 1245 | queue_bio(ms, bio, rw); |
| 1262 | return 1; | 1246 | return DM_ENDIO_INCOMPLETE; |
| 1263 | } | 1247 | } |
| 1264 | DMERR("All replicated volumes dead, failing I/O"); | 1248 | DMERR("All replicated volumes dead, failing I/O"); |
| 1265 | } | 1249 | } |
| 1266 | 1250 | ||
| 1267 | out: | 1251 | out: |
| 1268 | if (read_record) { | 1252 | bio_record->details.bi_bdev = NULL; |
| 1269 | mempool_free(read_record, ms->read_record_pool); | ||
| 1270 | map_context->ptr = NULL; | ||
| 1271 | } | ||
| 1272 | 1253 | ||
| 1273 | return error; | 1254 | return error; |
| 1274 | } | 1255 | } |
| @@ -1422,7 +1403,7 @@ static int mirror_iterate_devices(struct dm_target *ti, | |||
| 1422 | 1403 | ||
| 1423 | static struct target_type mirror_target = { | 1404 | static struct target_type mirror_target = { |
| 1424 | .name = "mirror", | 1405 | .name = "mirror", |
| 1425 | .version = {1, 12, 1}, | 1406 | .version = {1, 13, 1}, |
| 1426 | .module = THIS_MODULE, | 1407 | .module = THIS_MODULE, |
| 1427 | .ctr = mirror_ctr, | 1408 | .ctr = mirror_ctr, |
| 1428 | .dtr = mirror_dtr, | 1409 | .dtr = mirror_dtr, |
| @@ -1439,13 +1420,6 @@ static int __init dm_mirror_init(void) | |||
| 1439 | { | 1420 | { |
| 1440 | int r; | 1421 | int r; |
| 1441 | 1422 | ||
| 1442 | _dm_raid1_read_record_cache = KMEM_CACHE(dm_raid1_read_record, 0); | ||
| 1443 | if (!_dm_raid1_read_record_cache) { | ||
| 1444 | DMERR("Can't allocate dm_raid1_read_record cache"); | ||
| 1445 | r = -ENOMEM; | ||
| 1446 | goto bad_cache; | ||
| 1447 | } | ||
| 1448 | |||
| 1449 | r = dm_register_target(&mirror_target); | 1423 | r = dm_register_target(&mirror_target); |
| 1450 | if (r < 0) { | 1424 | if (r < 0) { |
| 1451 | DMERR("Failed to register mirror target"); | 1425 | DMERR("Failed to register mirror target"); |
| @@ -1455,15 +1429,12 @@ static int __init dm_mirror_init(void) | |||
| 1455 | return 0; | 1429 | return 0; |
| 1456 | 1430 | ||
| 1457 | bad_target: | 1431 | bad_target: |
| 1458 | kmem_cache_destroy(_dm_raid1_read_record_cache); | ||
| 1459 | bad_cache: | ||
| 1460 | return r; | 1432 | return r; |
| 1461 | } | 1433 | } |
| 1462 | 1434 | ||
| 1463 | static void __exit dm_mirror_exit(void) | 1435 | static void __exit dm_mirror_exit(void) |
| 1464 | { | 1436 | { |
| 1465 | dm_unregister_target(&mirror_target); | 1437 | dm_unregister_target(&mirror_target); |
| 1466 | kmem_cache_destroy(_dm_raid1_read_record_cache); | ||
| 1467 | } | 1438 | } |
| 1468 | 1439 | ||
| 1469 | /* Module hooks */ | 1440 | /* Module hooks */ |
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index a143921feaf6..59fc18ae52c2 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
| @@ -79,7 +79,6 @@ struct dm_snapshot { | |||
| 79 | 79 | ||
| 80 | /* Chunks with outstanding reads */ | 80 | /* Chunks with outstanding reads */ |
| 81 | spinlock_t tracked_chunk_lock; | 81 | spinlock_t tracked_chunk_lock; |
| 82 | mempool_t *tracked_chunk_pool; | ||
| 83 | struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE]; | 82 | struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE]; |
| 84 | 83 | ||
| 85 | /* The on disk metadata handler */ | 84 | /* The on disk metadata handler */ |
| @@ -191,35 +190,38 @@ struct dm_snap_tracked_chunk { | |||
| 191 | chunk_t chunk; | 190 | chunk_t chunk; |
| 192 | }; | 191 | }; |
| 193 | 192 | ||
| 194 | static struct kmem_cache *tracked_chunk_cache; | 193 | static void init_tracked_chunk(struct bio *bio) |
| 194 | { | ||
| 195 | struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk)); | ||
| 196 | INIT_HLIST_NODE(&c->node); | ||
| 197 | } | ||
| 195 | 198 | ||
| 196 | static struct dm_snap_tracked_chunk *track_chunk(struct dm_snapshot *s, | 199 | static bool is_bio_tracked(struct bio *bio) |
| 197 | chunk_t chunk) | ||
| 198 | { | 200 | { |
| 199 | struct dm_snap_tracked_chunk *c = mempool_alloc(s->tracked_chunk_pool, | 201 | struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk)); |
| 200 | GFP_NOIO); | 202 | return !hlist_unhashed(&c->node); |
| 201 | unsigned long flags; | 203 | } |
| 204 | |||
| 205 | static void track_chunk(struct dm_snapshot *s, struct bio *bio, chunk_t chunk) | ||
| 206 | { | ||
| 207 | struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk)); | ||
| 202 | 208 | ||
| 203 | c->chunk = chunk; | 209 | c->chunk = chunk; |
| 204 | 210 | ||
| 205 | spin_lock_irqsave(&s->tracked_chunk_lock, flags); | 211 | spin_lock_irq(&s->tracked_chunk_lock); |
| 206 | hlist_add_head(&c->node, | 212 | hlist_add_head(&c->node, |
| 207 | &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]); | 213 | &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]); |
| 208 | spin_unlock_irqrestore(&s->tracked_chunk_lock, flags); | 214 | spin_unlock_irq(&s->tracked_chunk_lock); |
| 209 | |||
| 210 | return c; | ||
| 211 | } | 215 | } |
| 212 | 216 | ||
| 213 | static void stop_tracking_chunk(struct dm_snapshot *s, | 217 | static void stop_tracking_chunk(struct dm_snapshot *s, struct bio *bio) |
| 214 | struct dm_snap_tracked_chunk *c) | ||
| 215 | { | 218 | { |
| 219 | struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk)); | ||
| 216 | unsigned long flags; | 220 | unsigned long flags; |
| 217 | 221 | ||
| 218 | spin_lock_irqsave(&s->tracked_chunk_lock, flags); | 222 | spin_lock_irqsave(&s->tracked_chunk_lock, flags); |
| 219 | hlist_del(&c->node); | 223 | hlist_del(&c->node); |
| 220 | spin_unlock_irqrestore(&s->tracked_chunk_lock, flags); | 224 | spin_unlock_irqrestore(&s->tracked_chunk_lock, flags); |
| 221 | |||
| 222 | mempool_free(c, s->tracked_chunk_pool); | ||
| 223 | } | 225 | } |
| 224 | 226 | ||
| 225 | static int __chunk_is_tracked(struct dm_snapshot *s, chunk_t chunk) | 227 | static int __chunk_is_tracked(struct dm_snapshot *s, chunk_t chunk) |
| @@ -1120,14 +1122,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 1120 | goto bad_pending_pool; | 1122 | goto bad_pending_pool; |
| 1121 | } | 1123 | } |
| 1122 | 1124 | ||
| 1123 | s->tracked_chunk_pool = mempool_create_slab_pool(MIN_IOS, | ||
| 1124 | tracked_chunk_cache); | ||
| 1125 | if (!s->tracked_chunk_pool) { | ||
| 1126 | ti->error = "Could not allocate tracked_chunk mempool for " | ||
| 1127 | "tracking reads"; | ||
| 1128 | goto bad_tracked_chunk_pool; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) | 1125 | for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) |
| 1132 | INIT_HLIST_HEAD(&s->tracked_chunk_hash[i]); | 1126 | INIT_HLIST_HEAD(&s->tracked_chunk_hash[i]); |
| 1133 | 1127 | ||
| @@ -1135,6 +1129,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 1135 | 1129 | ||
| 1136 | ti->private = s; | 1130 | ti->private = s; |
| 1137 | ti->num_flush_requests = num_flush_requests; | 1131 | ti->num_flush_requests = num_flush_requests; |
| 1132 | ti->per_bio_data_size = sizeof(struct dm_snap_tracked_chunk); | ||
| 1138 | 1133 | ||
| 1139 | /* Add snapshot to the list of snapshots for this origin */ | 1134 | /* Add snapshot to the list of snapshots for this origin */ |
| 1140 | /* Exceptions aren't triggered till snapshot_resume() is called */ | 1135 | /* Exceptions aren't triggered till snapshot_resume() is called */ |
| @@ -1183,9 +1178,6 @@ bad_read_metadata: | |||
| 1183 | unregister_snapshot(s); | 1178 | unregister_snapshot(s); |
| 1184 | 1179 | ||
| 1185 | bad_load_and_register: | 1180 | bad_load_and_register: |
| 1186 | mempool_destroy(s->tracked_chunk_pool); | ||
| 1187 | |||
| 1188 | bad_tracked_chunk_pool: | ||
| 1189 | mempool_destroy(s->pending_pool); | 1181 | mempool_destroy(s->pending_pool); |
| 1190 | 1182 | ||
| 1191 | bad_pending_pool: | 1183 | bad_pending_pool: |
| @@ -1290,8 +1282,6 @@ static void snapshot_dtr(struct dm_target *ti) | |||
| 1290 | BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i])); | 1282 | BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i])); |
| 1291 | #endif | 1283 | #endif |
| 1292 | 1284 | ||
| 1293 | mempool_destroy(s->tracked_chunk_pool); | ||
| 1294 | |||
| 1295 | __free_exceptions(s); | 1285 | __free_exceptions(s); |
| 1296 | 1286 | ||
| 1297 | mempool_destroy(s->pending_pool); | 1287 | mempool_destroy(s->pending_pool); |
| @@ -1577,8 +1567,7 @@ static void remap_exception(struct dm_snapshot *s, struct dm_exception *e, | |||
| 1577 | s->store->chunk_mask); | 1567 | s->store->chunk_mask); |
| 1578 | } | 1568 | } |
| 1579 | 1569 | ||
| 1580 | static int snapshot_map(struct dm_target *ti, struct bio *bio, | 1570 | static int snapshot_map(struct dm_target *ti, struct bio *bio) |
| 1581 | union map_info *map_context) | ||
| 1582 | { | 1571 | { |
| 1583 | struct dm_exception *e; | 1572 | struct dm_exception *e; |
| 1584 | struct dm_snapshot *s = ti->private; | 1573 | struct dm_snapshot *s = ti->private; |
| @@ -1586,6 +1575,8 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
| 1586 | chunk_t chunk; | 1575 | chunk_t chunk; |
| 1587 | struct dm_snap_pending_exception *pe = NULL; | 1576 | struct dm_snap_pending_exception *pe = NULL; |
| 1588 | 1577 | ||
| 1578 | init_tracked_chunk(bio); | ||
| 1579 | |||
| 1589 | if (bio->bi_rw & REQ_FLUSH) { | 1580 | if (bio->bi_rw & REQ_FLUSH) { |
| 1590 | bio->bi_bdev = s->cow->bdev; | 1581 | bio->bi_bdev = s->cow->bdev; |
| 1591 | return DM_MAPIO_REMAPPED; | 1582 | return DM_MAPIO_REMAPPED; |
| @@ -1670,7 +1661,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
| 1670 | } | 1661 | } |
| 1671 | } else { | 1662 | } else { |
| 1672 | bio->bi_bdev = s->origin->bdev; | 1663 | bio->bi_bdev = s->origin->bdev; |
| 1673 | map_context->ptr = track_chunk(s, chunk); | 1664 | track_chunk(s, bio, chunk); |
| 1674 | } | 1665 | } |
| 1675 | 1666 | ||
| 1676 | out_unlock: | 1667 | out_unlock: |
| @@ -1691,20 +1682,20 @@ out: | |||
| 1691 | * If merging is currently taking place on the chunk in question, the | 1682 | * If merging is currently taking place on the chunk in question, the |
| 1692 | * I/O is deferred by adding it to s->bios_queued_during_merge. | 1683 | * I/O is deferred by adding it to s->bios_queued_during_merge. |
| 1693 | */ | 1684 | */ |
| 1694 | static int snapshot_merge_map(struct dm_target *ti, struct bio *bio, | 1685 | static int snapshot_merge_map(struct dm_target *ti, struct bio *bio) |
| 1695 | union map_info *map_context) | ||
| 1696 | { | 1686 | { |
| 1697 | struct dm_exception *e; | 1687 | struct dm_exception *e; |
| 1698 | struct dm_snapshot *s = ti->private; | 1688 | struct dm_snapshot *s = ti->private; |
| 1699 | int r = DM_MAPIO_REMAPPED; | 1689 | int r = DM_MAPIO_REMAPPED; |
| 1700 | chunk_t chunk; | 1690 | chunk_t chunk; |
| 1701 | 1691 | ||
| 1692 | init_tracked_chunk(bio); | ||
| 1693 | |||
| 1702 | if (bio->bi_rw & REQ_FLUSH) { | 1694 | if (bio->bi_rw & REQ_FLUSH) { |
| 1703 | if (!map_context->target_request_nr) | 1695 | if (!dm_bio_get_target_request_nr(bio)) |
| 1704 | bio->bi_bdev = s->origin->bdev; | 1696 | bio->bi_bdev = s->origin->bdev; |
| 1705 | else | 1697 | else |
| 1706 | bio->bi_bdev = s->cow->bdev; | 1698 | bio->bi_bdev = s->cow->bdev; |
| 1707 | map_context->ptr = NULL; | ||
| 1708 | return DM_MAPIO_REMAPPED; | 1699 | return DM_MAPIO_REMAPPED; |
| 1709 | } | 1700 | } |
| 1710 | 1701 | ||
| @@ -1733,7 +1724,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio, | |||
| 1733 | remap_exception(s, e, bio, chunk); | 1724 | remap_exception(s, e, bio, chunk); |
| 1734 | 1725 | ||
| 1735 | if (bio_rw(bio) == WRITE) | 1726 | if (bio_rw(bio) == WRITE) |
| 1736 | map_context->ptr = track_chunk(s, chunk); | 1727 | track_chunk(s, bio, chunk); |
| 1737 | goto out_unlock; | 1728 | goto out_unlock; |
| 1738 | } | 1729 | } |
| 1739 | 1730 | ||
| @@ -1751,14 +1742,12 @@ out_unlock: | |||
| 1751 | return r; | 1742 | return r; |
| 1752 | } | 1743 | } |
| 1753 | 1744 | ||
| 1754 | static int snapshot_end_io(struct dm_target *ti, struct bio *bio, | 1745 | static int snapshot_end_io(struct dm_target *ti, struct bio *bio, int error) |
| 1755 | int error, union map_info *map_context) | ||
| 1756 | { | 1746 | { |
| 1757 | struct dm_snapshot *s = ti->private; | 1747 | struct dm_snapshot *s = ti->private; |
| 1758 | struct dm_snap_tracked_chunk *c = map_context->ptr; | ||
| 1759 | 1748 | ||
| 1760 | if (c) | 1749 | if (is_bio_tracked(bio)) |
| 1761 | stop_tracking_chunk(s, c); | 1750 | stop_tracking_chunk(s, bio); |
| 1762 | 1751 | ||
| 1763 | return 0; | 1752 | return 0; |
| 1764 | } | 1753 | } |
| @@ -2127,8 +2116,7 @@ static void origin_dtr(struct dm_target *ti) | |||
| 2127 | dm_put_device(ti, dev); | 2116 | dm_put_device(ti, dev); |
| 2128 | } | 2117 | } |
| 2129 | 2118 | ||
| 2130 | static int origin_map(struct dm_target *ti, struct bio *bio, | 2119 | static int origin_map(struct dm_target *ti, struct bio *bio) |
| 2131 | union map_info *map_context) | ||
| 2132 | { | 2120 | { |
| 2133 | struct dm_dev *dev = ti->private; | 2121 | struct dm_dev *dev = ti->private; |
| 2134 | bio->bi_bdev = dev->bdev; | 2122 | bio->bi_bdev = dev->bdev; |
| @@ -2193,7 +2181,7 @@ static int origin_iterate_devices(struct dm_target *ti, | |||
| 2193 | 2181 | ||
| 2194 | static struct target_type origin_target = { | 2182 | static struct target_type origin_target = { |
| 2195 | .name = "snapshot-origin", | 2183 | .name = "snapshot-origin", |
| 2196 | .version = {1, 7, 1}, | 2184 | .version = {1, 8, 0}, |
| 2197 | .module = THIS_MODULE, | 2185 | .module = THIS_MODULE, |
| 2198 | .ctr = origin_ctr, | 2186 | .ctr = origin_ctr, |
| 2199 | .dtr = origin_dtr, | 2187 | .dtr = origin_dtr, |
| @@ -2206,7 +2194,7 @@ static struct target_type origin_target = { | |||
| 2206 | 2194 | ||
| 2207 | static struct target_type snapshot_target = { | 2195 | static struct target_type snapshot_target = { |
| 2208 | .name = "snapshot", | 2196 | .name = "snapshot", |
| 2209 | .version = {1, 10, 0}, | 2197 | .version = {1, 11, 0}, |
| 2210 | .module = THIS_MODULE, | 2198 | .module = THIS_MODULE, |
| 2211 | .ctr = snapshot_ctr, | 2199 | .ctr = snapshot_ctr, |
| 2212 | .dtr = snapshot_dtr, | 2200 | .dtr = snapshot_dtr, |
| @@ -2220,7 +2208,7 @@ static struct target_type snapshot_target = { | |||
| 2220 | 2208 | ||
| 2221 | static struct target_type merge_target = { | 2209 | static struct target_type merge_target = { |
| 2222 | .name = dm_snapshot_merge_target_name, | 2210 | .name = dm_snapshot_merge_target_name, |
| 2223 | .version = {1, 1, 0}, | 2211 | .version = {1, 2, 0}, |
| 2224 | .module = THIS_MODULE, | 2212 | .module = THIS_MODULE, |
| 2225 | .ctr = snapshot_ctr, | 2213 | .ctr = snapshot_ctr, |
| 2226 | .dtr = snapshot_dtr, | 2214 | .dtr = snapshot_dtr, |
| @@ -2281,17 +2269,8 @@ static int __init dm_snapshot_init(void) | |||
| 2281 | goto bad_pending_cache; | 2269 | goto bad_pending_cache; |
| 2282 | } | 2270 | } |
| 2283 | 2271 | ||
| 2284 | tracked_chunk_cache = KMEM_CACHE(dm_snap_tracked_chunk, 0); | ||
| 2285 | if (!tracked_chunk_cache) { | ||
| 2286 | DMERR("Couldn't create cache to track chunks in use."); | ||
| 2287 | r = -ENOMEM; | ||
| 2288 | goto bad_tracked_chunk_cache; | ||
| 2289 | } | ||
| 2290 | |||
| 2291 | return 0; | 2272 | return 0; |
| 2292 | 2273 | ||
| 2293 | bad_tracked_chunk_cache: | ||
| 2294 | kmem_cache_destroy(pending_cache); | ||
| 2295 | bad_pending_cache: | 2274 | bad_pending_cache: |
| 2296 | kmem_cache_destroy(exception_cache); | 2275 | kmem_cache_destroy(exception_cache); |
| 2297 | bad_exception_cache: | 2276 | bad_exception_cache: |
| @@ -2317,7 +2296,6 @@ static void __exit dm_snapshot_exit(void) | |||
| 2317 | exit_origin_hash(); | 2296 | exit_origin_hash(); |
| 2318 | kmem_cache_destroy(pending_cache); | 2297 | kmem_cache_destroy(pending_cache); |
| 2319 | kmem_cache_destroy(exception_cache); | 2298 | kmem_cache_destroy(exception_cache); |
| 2320 | kmem_cache_destroy(tracked_chunk_cache); | ||
| 2321 | 2299 | ||
| 2322 | dm_exception_store_exit(); | 2300 | dm_exception_store_exit(); |
| 2323 | } | 2301 | } |
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index e2f876539743..c89cde86d400 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
| @@ -162,6 +162,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 162 | 162 | ||
| 163 | ti->num_flush_requests = stripes; | 163 | ti->num_flush_requests = stripes; |
| 164 | ti->num_discard_requests = stripes; | 164 | ti->num_discard_requests = stripes; |
| 165 | ti->num_write_same_requests = stripes; | ||
| 165 | 166 | ||
| 166 | sc->chunk_size = chunk_size; | 167 | sc->chunk_size = chunk_size; |
| 167 | if (chunk_size & (chunk_size - 1)) | 168 | if (chunk_size & (chunk_size - 1)) |
| @@ -251,8 +252,8 @@ static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector, | |||
| 251 | *result += sc->chunk_size; /* next chunk */ | 252 | *result += sc->chunk_size; /* next chunk */ |
| 252 | } | 253 | } |
| 253 | 254 | ||
| 254 | static int stripe_map_discard(struct stripe_c *sc, struct bio *bio, | 255 | static int stripe_map_range(struct stripe_c *sc, struct bio *bio, |
| 255 | uint32_t target_stripe) | 256 | uint32_t target_stripe) |
| 256 | { | 257 | { |
| 257 | sector_t begin, end; | 258 | sector_t begin, end; |
| 258 | 259 | ||
| @@ -271,23 +272,23 @@ static int stripe_map_discard(struct stripe_c *sc, struct bio *bio, | |||
| 271 | } | 272 | } |
| 272 | } | 273 | } |
| 273 | 274 | ||
| 274 | static int stripe_map(struct dm_target *ti, struct bio *bio, | 275 | static int stripe_map(struct dm_target *ti, struct bio *bio) |
| 275 | union map_info *map_context) | ||
| 276 | { | 276 | { |
| 277 | struct stripe_c *sc = ti->private; | 277 | struct stripe_c *sc = ti->private; |
| 278 | uint32_t stripe; | 278 | uint32_t stripe; |
| 279 | unsigned target_request_nr; | 279 | unsigned target_request_nr; |
| 280 | 280 | ||
| 281 | if (bio->bi_rw & REQ_FLUSH) { | 281 | if (bio->bi_rw & REQ_FLUSH) { |
| 282 | target_request_nr = map_context->target_request_nr; | 282 | target_request_nr = dm_bio_get_target_request_nr(bio); |
| 283 | BUG_ON(target_request_nr >= sc->stripes); | 283 | BUG_ON(target_request_nr >= sc->stripes); |
| 284 | bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev; | 284 | bio->bi_bdev = sc->stripe[target_request_nr].dev->bdev; |
| 285 | return DM_MAPIO_REMAPPED; | 285 | return DM_MAPIO_REMAPPED; |
| 286 | } | 286 | } |
| 287 | if (unlikely(bio->bi_rw & REQ_DISCARD)) { | 287 | if (unlikely(bio->bi_rw & REQ_DISCARD) || |
| 288 | target_request_nr = map_context->target_request_nr; | 288 | unlikely(bio->bi_rw & REQ_WRITE_SAME)) { |
| 289 | target_request_nr = dm_bio_get_target_request_nr(bio); | ||
| 289 | BUG_ON(target_request_nr >= sc->stripes); | 290 | BUG_ON(target_request_nr >= sc->stripes); |
| 290 | return stripe_map_discard(sc, bio, target_request_nr); | 291 | return stripe_map_range(sc, bio, target_request_nr); |
| 291 | } | 292 | } |
| 292 | 293 | ||
| 293 | stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector); | 294 | stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector); |
| @@ -342,8 +343,7 @@ static int stripe_status(struct dm_target *ti, status_type_t type, | |||
| 342 | return 0; | 343 | return 0; |
| 343 | } | 344 | } |
| 344 | 345 | ||
| 345 | static int stripe_end_io(struct dm_target *ti, struct bio *bio, | 346 | static int stripe_end_io(struct dm_target *ti, struct bio *bio, int error) |
| 346 | int error, union map_info *map_context) | ||
| 347 | { | 347 | { |
| 348 | unsigned i; | 348 | unsigned i; |
| 349 | char major_minor[16]; | 349 | char major_minor[16]; |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 100368eb7991..daf25d0890b3 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
| @@ -967,13 +967,22 @@ bool dm_table_request_based(struct dm_table *t) | |||
| 967 | int dm_table_alloc_md_mempools(struct dm_table *t) | 967 | int dm_table_alloc_md_mempools(struct dm_table *t) |
| 968 | { | 968 | { |
| 969 | unsigned type = dm_table_get_type(t); | 969 | unsigned type = dm_table_get_type(t); |
| 970 | unsigned per_bio_data_size = 0; | ||
| 971 | struct dm_target *tgt; | ||
| 972 | unsigned i; | ||
| 970 | 973 | ||
| 971 | if (unlikely(type == DM_TYPE_NONE)) { | 974 | if (unlikely(type == DM_TYPE_NONE)) { |
| 972 | DMWARN("no table type is set, can't allocate mempools"); | 975 | DMWARN("no table type is set, can't allocate mempools"); |
| 973 | return -EINVAL; | 976 | return -EINVAL; |
| 974 | } | 977 | } |
| 975 | 978 | ||
| 976 | t->mempools = dm_alloc_md_mempools(type, t->integrity_supported); | 979 | if (type == DM_TYPE_BIO_BASED) |
| 980 | for (i = 0; i < t->num_targets; i++) { | ||
| 981 | tgt = t->targets + i; | ||
| 982 | per_bio_data_size = max(per_bio_data_size, tgt->per_bio_data_size); | ||
| 983 | } | ||
| 984 | |||
| 985 | t->mempools = dm_alloc_md_mempools(type, t->integrity_supported, per_bio_data_size); | ||
| 977 | if (!t->mempools) | 986 | if (!t->mempools) |
| 978 | return -ENOMEM; | 987 | return -ENOMEM; |
| 979 | 988 | ||
| @@ -1414,6 +1423,33 @@ static bool dm_table_all_devices_attribute(struct dm_table *t, | |||
| 1414 | return 1; | 1423 | return 1; |
| 1415 | } | 1424 | } |
| 1416 | 1425 | ||
| 1426 | static int device_not_write_same_capable(struct dm_target *ti, struct dm_dev *dev, | ||
| 1427 | sector_t start, sector_t len, void *data) | ||
| 1428 | { | ||
| 1429 | struct request_queue *q = bdev_get_queue(dev->bdev); | ||
| 1430 | |||
| 1431 | return q && !q->limits.max_write_same_sectors; | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | static bool dm_table_supports_write_same(struct dm_table *t) | ||
| 1435 | { | ||
| 1436 | struct dm_target *ti; | ||
| 1437 | unsigned i = 0; | ||
| 1438 | |||
| 1439 | while (i < dm_table_get_num_targets(t)) { | ||
| 1440 | ti = dm_table_get_target(t, i++); | ||
| 1441 | |||
| 1442 | if (!ti->num_write_same_requests) | ||
| 1443 | return false; | ||
| 1444 | |||
| 1445 | if (!ti->type->iterate_devices || | ||
| 1446 | !ti->type->iterate_devices(ti, device_not_write_same_capable, NULL)) | ||
| 1447 | return false; | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | return true; | ||
| 1451 | } | ||
| 1452 | |||
| 1417 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, | 1453 | void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, |
| 1418 | struct queue_limits *limits) | 1454 | struct queue_limits *limits) |
| 1419 | { | 1455 | { |
| @@ -1445,6 +1481,9 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, | |||
| 1445 | else | 1481 | else |
| 1446 | queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q); | 1482 | queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q); |
| 1447 | 1483 | ||
| 1484 | if (!dm_table_supports_write_same(t)) | ||
| 1485 | q->limits.max_write_same_sectors = 0; | ||
| 1486 | |||
| 1448 | dm_table_set_integrity(t); | 1487 | dm_table_set_integrity(t); |
| 1449 | 1488 | ||
| 1450 | /* | 1489 | /* |
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c index 8da366cf381c..617d21a77256 100644 --- a/drivers/md/dm-target.c +++ b/drivers/md/dm-target.c | |||
| @@ -126,15 +126,14 @@ static void io_err_dtr(struct dm_target *tt) | |||
| 126 | /* empty */ | 126 | /* empty */ |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | static int io_err_map(struct dm_target *tt, struct bio *bio, | 129 | static int io_err_map(struct dm_target *tt, struct bio *bio) |
| 130 | union map_info *map_context) | ||
| 131 | { | 130 | { |
| 132 | return -EIO; | 131 | return -EIO; |
| 133 | } | 132 | } |
| 134 | 133 | ||
| 135 | static struct target_type error_target = { | 134 | static struct target_type error_target = { |
| 136 | .name = "error", | 135 | .name = "error", |
| 137 | .version = {1, 0, 1}, | 136 | .version = {1, 1, 0}, |
| 138 | .ctr = io_err_ctr, | 137 | .ctr = io_err_ctr, |
| 139 | .dtr = io_err_dtr, | 138 | .dtr = io_err_dtr, |
| 140 | .map = io_err_map, | 139 | .map = io_err_map, |
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 693e149e9727..4d6e85367b84 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c | |||
| @@ -408,7 +408,7 @@ static void __setup_btree_details(struct dm_pool_metadata *pmd) | |||
| 408 | 408 | ||
| 409 | pmd->tl_info.tm = pmd->tm; | 409 | pmd->tl_info.tm = pmd->tm; |
| 410 | pmd->tl_info.levels = 1; | 410 | pmd->tl_info.levels = 1; |
| 411 | pmd->tl_info.value_type.context = &pmd->info; | 411 | pmd->tl_info.value_type.context = &pmd->bl_info; |
| 412 | pmd->tl_info.value_type.size = sizeof(__le64); | 412 | pmd->tl_info.value_type.size = sizeof(__le64); |
| 413 | pmd->tl_info.value_type.inc = subtree_inc; | 413 | pmd->tl_info.value_type.inc = subtree_inc; |
| 414 | pmd->tl_info.value_type.dec = subtree_dec; | 414 | pmd->tl_info.value_type.dec = subtree_dec; |
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 058acf3a5ba7..675ae5274016 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
| @@ -186,7 +186,6 @@ struct pool { | |||
| 186 | 186 | ||
| 187 | struct dm_thin_new_mapping *next_mapping; | 187 | struct dm_thin_new_mapping *next_mapping; |
| 188 | mempool_t *mapping_pool; | 188 | mempool_t *mapping_pool; |
| 189 | mempool_t *endio_hook_pool; | ||
| 190 | 189 | ||
| 191 | process_bio_fn process_bio; | 190 | process_bio_fn process_bio; |
| 192 | process_bio_fn process_discard; | 191 | process_bio_fn process_discard; |
| @@ -304,7 +303,7 @@ static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master) | |||
| 304 | bio_list_init(master); | 303 | bio_list_init(master); |
| 305 | 304 | ||
| 306 | while ((bio = bio_list_pop(&bios))) { | 305 | while ((bio = bio_list_pop(&bios))) { |
| 307 | struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; | 306 | struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); |
| 308 | 307 | ||
| 309 | if (h->tc == tc) | 308 | if (h->tc == tc) |
| 310 | bio_endio(bio, DM_ENDIO_REQUEUE); | 309 | bio_endio(bio, DM_ENDIO_REQUEUE); |
| @@ -368,6 +367,17 @@ static int bio_triggers_commit(struct thin_c *tc, struct bio *bio) | |||
| 368 | dm_thin_changed_this_transaction(tc->td); | 367 | dm_thin_changed_this_transaction(tc->td); |
| 369 | } | 368 | } |
| 370 | 369 | ||
| 370 | static void inc_all_io_entry(struct pool *pool, struct bio *bio) | ||
| 371 | { | ||
| 372 | struct dm_thin_endio_hook *h; | ||
| 373 | |||
| 374 | if (bio->bi_rw & REQ_DISCARD) | ||
| 375 | return; | ||
| 376 | |||
| 377 | h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); | ||
| 378 | h->all_io_entry = dm_deferred_entry_inc(pool->all_io_ds); | ||
| 379 | } | ||
| 380 | |||
| 371 | static void issue(struct thin_c *tc, struct bio *bio) | 381 | static void issue(struct thin_c *tc, struct bio *bio) |
| 372 | { | 382 | { |
| 373 | struct pool *pool = tc->pool; | 383 | struct pool *pool = tc->pool; |
| @@ -474,7 +484,7 @@ static void copy_complete(int read_err, unsigned long write_err, void *context) | |||
| 474 | static void overwrite_endio(struct bio *bio, int err) | 484 | static void overwrite_endio(struct bio *bio, int err) |
| 475 | { | 485 | { |
| 476 | unsigned long flags; | 486 | unsigned long flags; |
| 477 | struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; | 487 | struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); |
| 478 | struct dm_thin_new_mapping *m = h->overwrite_mapping; | 488 | struct dm_thin_new_mapping *m = h->overwrite_mapping; |
| 479 | struct pool *pool = m->tc->pool; | 489 | struct pool *pool = m->tc->pool; |
| 480 | 490 | ||
| @@ -499,8 +509,7 @@ static void overwrite_endio(struct bio *bio, int err) | |||
| 499 | /* | 509 | /* |
| 500 | * This sends the bios in the cell back to the deferred_bios list. | 510 | * This sends the bios in the cell back to the deferred_bios list. |
| 501 | */ | 511 | */ |
| 502 | static void cell_defer(struct thin_c *tc, struct dm_bio_prison_cell *cell, | 512 | static void cell_defer(struct thin_c *tc, struct dm_bio_prison_cell *cell) |
| 503 | dm_block_t data_block) | ||
| 504 | { | 513 | { |
| 505 | struct pool *pool = tc->pool; | 514 | struct pool *pool = tc->pool; |
| 506 | unsigned long flags; | 515 | unsigned long flags; |
| @@ -513,17 +522,13 @@ static void cell_defer(struct thin_c *tc, struct dm_bio_prison_cell *cell, | |||
| 513 | } | 522 | } |
| 514 | 523 | ||
| 515 | /* | 524 | /* |
| 516 | * Same as cell_defer above, except it omits one particular detainee, | 525 | * Same as cell_defer except it omits the original holder of the cell. |
| 517 | * a write bio that covers the block and has already been processed. | ||
| 518 | */ | 526 | */ |
| 519 | static void cell_defer_except(struct thin_c *tc, struct dm_bio_prison_cell *cell) | 527 | static void cell_defer_no_holder(struct thin_c *tc, struct dm_bio_prison_cell *cell) |
| 520 | { | 528 | { |
| 521 | struct bio_list bios; | ||
| 522 | struct pool *pool = tc->pool; | 529 | struct pool *pool = tc->pool; |
| 523 | unsigned long flags; | 530 | unsigned long flags; |
| 524 | 531 | ||
| 525 | bio_list_init(&bios); | ||
| 526 | |||
| 527 | spin_lock_irqsave(&pool->lock, flags); | 532 | spin_lock_irqsave(&pool->lock, flags); |
| 528 | dm_cell_release_no_holder(cell, &pool->deferred_bios); | 533 | dm_cell_release_no_holder(cell, &pool->deferred_bios); |
| 529 | spin_unlock_irqrestore(&pool->lock, flags); | 534 | spin_unlock_irqrestore(&pool->lock, flags); |
| @@ -561,7 +566,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m) | |||
| 561 | */ | 566 | */ |
| 562 | r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block); | 567 | r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block); |
| 563 | if (r) { | 568 | if (r) { |
| 564 | DMERR("dm_thin_insert_block() failed"); | 569 | DMERR_LIMIT("dm_thin_insert_block() failed"); |
| 565 | dm_cell_error(m->cell); | 570 | dm_cell_error(m->cell); |
| 566 | goto out; | 571 | goto out; |
| 567 | } | 572 | } |
| @@ -573,10 +578,10 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m) | |||
| 573 | * the bios in the cell. | 578 | * the bios in the cell. |
| 574 | */ | 579 | */ |
| 575 | if (bio) { | 580 | if (bio) { |
| 576 | cell_defer_except(tc, m->cell); | 581 | cell_defer_no_holder(tc, m->cell); |
| 577 | bio_endio(bio, 0); | 582 | bio_endio(bio, 0); |
| 578 | } else | 583 | } else |
| 579 | cell_defer(tc, m->cell, m->data_block); | 584 | cell_defer(tc, m->cell); |
| 580 | 585 | ||
| 581 | out: | 586 | out: |
| 582 | list_del(&m->list); | 587 | list_del(&m->list); |
| @@ -588,8 +593,8 @@ static void process_prepared_discard_fail(struct dm_thin_new_mapping *m) | |||
| 588 | struct thin_c *tc = m->tc; | 593 | struct thin_c *tc = m->tc; |
| 589 | 594 | ||
| 590 | bio_io_error(m->bio); | 595 | bio_io_error(m->bio); |
| 591 | cell_defer_except(tc, m->cell); | 596 | cell_defer_no_holder(tc, m->cell); |
| 592 | cell_defer_except(tc, m->cell2); | 597 | cell_defer_no_holder(tc, m->cell2); |
| 593 | mempool_free(m, tc->pool->mapping_pool); | 598 | mempool_free(m, tc->pool->mapping_pool); |
| 594 | } | 599 | } |
| 595 | 600 | ||
| @@ -597,13 +602,15 @@ static void process_prepared_discard_passdown(struct dm_thin_new_mapping *m) | |||
| 597 | { | 602 | { |
| 598 | struct thin_c *tc = m->tc; | 603 | struct thin_c *tc = m->tc; |
| 599 | 604 | ||
| 605 | inc_all_io_entry(tc->pool, m->bio); | ||
| 606 | cell_defer_no_holder(tc, m->cell); | ||
| 607 | cell_defer_no_holder(tc, m->cell2); | ||
| 608 | |||
| 600 | if (m->pass_discard) | 609 | if (m->pass_discard) |
| 601 | remap_and_issue(tc, m->bio, m->data_block); | 610 | remap_and_issue(tc, m->bio, m->data_block); |
| 602 | else | 611 | else |
| 603 | bio_endio(m->bio, 0); | 612 | bio_endio(m->bio, 0); |
| 604 | 613 | ||
| 605 | cell_defer_except(tc, m->cell); | ||
| 606 | cell_defer_except(tc, m->cell2); | ||
| 607 | mempool_free(m, tc->pool->mapping_pool); | 614 | mempool_free(m, tc->pool->mapping_pool); |
| 608 | } | 615 | } |
| 609 | 616 | ||
| @@ -614,7 +621,7 @@ static void process_prepared_discard(struct dm_thin_new_mapping *m) | |||
| 614 | 621 | ||
| 615 | r = dm_thin_remove_block(tc->td, m->virt_block); | 622 | r = dm_thin_remove_block(tc->td, m->virt_block); |
| 616 | if (r) | 623 | if (r) |
| 617 | DMERR("dm_thin_remove_block() failed"); | 624 | DMERR_LIMIT("dm_thin_remove_block() failed"); |
| 618 | 625 | ||
| 619 | process_prepared_discard_passdown(m); | 626 | process_prepared_discard_passdown(m); |
| 620 | } | 627 | } |
| @@ -706,11 +713,12 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block, | |||
| 706 | * bio immediately. Otherwise we use kcopyd to clone the data first. | 713 | * bio immediately. Otherwise we use kcopyd to clone the data first. |
| 707 | */ | 714 | */ |
| 708 | if (io_overwrites_block(pool, bio)) { | 715 | if (io_overwrites_block(pool, bio)) { |
| 709 | struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; | 716 | struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); |
| 710 | 717 | ||
| 711 | h->overwrite_mapping = m; | 718 | h->overwrite_mapping = m; |
| 712 | m->bio = bio; | 719 | m->bio = bio; |
| 713 | save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); | 720 | save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); |
| 721 | inc_all_io_entry(pool, bio); | ||
| 714 | remap_and_issue(tc, bio, data_dest); | 722 | remap_and_issue(tc, bio, data_dest); |
| 715 | } else { | 723 | } else { |
| 716 | struct dm_io_region from, to; | 724 | struct dm_io_region from, to; |
| @@ -727,7 +735,7 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block, | |||
| 727 | 0, copy_complete, m); | 735 | 0, copy_complete, m); |
| 728 | if (r < 0) { | 736 | if (r < 0) { |
| 729 | mempool_free(m, pool->mapping_pool); | 737 | mempool_free(m, pool->mapping_pool); |
| 730 | DMERR("dm_kcopyd_copy() failed"); | 738 | DMERR_LIMIT("dm_kcopyd_copy() failed"); |
| 731 | dm_cell_error(cell); | 739 | dm_cell_error(cell); |
| 732 | } | 740 | } |
| 733 | } | 741 | } |
| @@ -775,11 +783,12 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, | |||
| 775 | process_prepared_mapping(m); | 783 | process_prepared_mapping(m); |
| 776 | 784 | ||
| 777 | else if (io_overwrites_block(pool, bio)) { | 785 | else if (io_overwrites_block(pool, bio)) { |
| 778 | struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; | 786 | struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); |
| 779 | 787 | ||
| 780 | h->overwrite_mapping = m; | 788 | h->overwrite_mapping = m; |
| 781 | m->bio = bio; | 789 | m->bio = bio; |
| 782 | save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); | 790 | save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); |
| 791 | inc_all_io_entry(pool, bio); | ||
| 783 | remap_and_issue(tc, bio, data_block); | 792 | remap_and_issue(tc, bio, data_block); |
| 784 | } else { | 793 | } else { |
| 785 | int r; | 794 | int r; |
| @@ -792,7 +801,7 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, | |||
| 792 | r = dm_kcopyd_zero(pool->copier, 1, &to, 0, copy_complete, m); | 801 | r = dm_kcopyd_zero(pool->copier, 1, &to, 0, copy_complete, m); |
| 793 | if (r < 0) { | 802 | if (r < 0) { |
| 794 | mempool_free(m, pool->mapping_pool); | 803 | mempool_free(m, pool->mapping_pool); |
| 795 | DMERR("dm_kcopyd_zero() failed"); | 804 | DMERR_LIMIT("dm_kcopyd_zero() failed"); |
| 796 | dm_cell_error(cell); | 805 | dm_cell_error(cell); |
| 797 | } | 806 | } |
| 798 | } | 807 | } |
| @@ -804,7 +813,7 @@ static int commit(struct pool *pool) | |||
| 804 | 813 | ||
| 805 | r = dm_pool_commit_metadata(pool->pmd); | 814 | r = dm_pool_commit_metadata(pool->pmd); |
| 806 | if (r) | 815 | if (r) |
| 807 | DMERR("commit failed, error = %d", r); | 816 | DMERR_LIMIT("commit failed: error = %d", r); |
| 808 | 817 | ||
| 809 | return r; | 818 | return r; |
| 810 | } | 819 | } |
| @@ -889,7 +898,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) | |||
| 889 | */ | 898 | */ |
| 890 | static void retry_on_resume(struct bio *bio) | 899 | static void retry_on_resume(struct bio *bio) |
| 891 | { | 900 | { |
| 892 | struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; | 901 | struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); |
| 893 | struct thin_c *tc = h->tc; | 902 | struct thin_c *tc = h->tc; |
| 894 | struct pool *pool = tc->pool; | 903 | struct pool *pool = tc->pool; |
| 895 | unsigned long flags; | 904 | unsigned long flags; |
| @@ -936,7 +945,7 @@ static void process_discard(struct thin_c *tc, struct bio *bio) | |||
| 936 | */ | 945 | */ |
| 937 | build_data_key(tc->td, lookup_result.block, &key2); | 946 | build_data_key(tc->td, lookup_result.block, &key2); |
| 938 | if (dm_bio_detain(tc->pool->prison, &key2, bio, &cell2)) { | 947 | if (dm_bio_detain(tc->pool->prison, &key2, bio, &cell2)) { |
| 939 | dm_cell_release_singleton(cell, bio); | 948 | cell_defer_no_holder(tc, cell); |
| 940 | break; | 949 | break; |
| 941 | } | 950 | } |
| 942 | 951 | ||
| @@ -962,13 +971,15 @@ static void process_discard(struct thin_c *tc, struct bio *bio) | |||
| 962 | wake_worker(pool); | 971 | wake_worker(pool); |
| 963 | } | 972 | } |
| 964 | } else { | 973 | } else { |
| 974 | inc_all_io_entry(pool, bio); | ||
| 975 | cell_defer_no_holder(tc, cell); | ||
| 976 | cell_defer_no_holder(tc, cell2); | ||
| 977 | |||
| 965 | /* | 978 | /* |
| 966 | * The DM core makes sure that the discard doesn't span | 979 | * The DM core makes sure that the discard doesn't span |
| 967 | * a block boundary. So we submit the discard of a | 980 | * a block boundary. So we submit the discard of a |
| 968 | * partial block appropriately. | 981 | * partial block appropriately. |
| 969 | */ | 982 | */ |
| 970 | dm_cell_release_singleton(cell, bio); | ||
| 971 | dm_cell_release_singleton(cell2, bio); | ||
| 972 | if ((!lookup_result.shared) && pool->pf.discard_passdown) | 983 | if ((!lookup_result.shared) && pool->pf.discard_passdown) |
| 973 | remap_and_issue(tc, bio, lookup_result.block); | 984 | remap_and_issue(tc, bio, lookup_result.block); |
| 974 | else | 985 | else |
| @@ -980,13 +991,14 @@ static void process_discard(struct thin_c *tc, struct bio *bio) | |||
| 980 | /* | 991 | /* |
| 981 | * It isn't provisioned, just forget it. | 992 | * It isn't provisioned, just forget it. |
| 982 | */ | 993 | */ |
| 983 | dm_cell_release_singleton(cell, bio); | 994 | cell_defer_no_holder(tc, cell); |
| 984 | bio_endio(bio, 0); | 995 | bio_endio(bio, 0); |
| 985 | break; | 996 | break; |
| 986 | 997 | ||
| 987 | default: | 998 | default: |
| 988 | DMERR("discard: find block unexpectedly returned %d", r); | 999 | DMERR_LIMIT("%s: dm_thin_find_block() failed: error = %d", |
| 989 | dm_cell_release_singleton(cell, bio); | 1000 | __func__, r); |
| 1001 | cell_defer_no_holder(tc, cell); | ||
| 990 | bio_io_error(bio); | 1002 | bio_io_error(bio); |
| 991 | break; | 1003 | break; |
| 992 | } | 1004 | } |
| @@ -1012,7 +1024,8 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block, | |||
| 1012 | break; | 1024 | break; |
| 1013 | 1025 | ||
| 1014 | default: | 1026 | default: |
| 1015 | DMERR("%s: alloc_data_block() failed, error = %d", __func__, r); | 1027 | DMERR_LIMIT("%s: alloc_data_block() failed: error = %d", |
| 1028 | __func__, r); | ||
| 1016 | dm_cell_error(cell); | 1029 | dm_cell_error(cell); |
| 1017 | break; | 1030 | break; |
| 1018 | } | 1031 | } |
| @@ -1037,11 +1050,12 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio, | |||
| 1037 | if (bio_data_dir(bio) == WRITE && bio->bi_size) | 1050 | if (bio_data_dir(bio) == WRITE && bio->bi_size) |
| 1038 | break_sharing(tc, bio, block, &key, lookup_result, cell); | 1051 | break_sharing(tc, bio, block, &key, lookup_result, cell); |
| 1039 | else { | 1052 | else { |
| 1040 | struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; | 1053 | struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); |
| 1041 | 1054 | ||
| 1042 | h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds); | 1055 | h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds); |
| 1056 | inc_all_io_entry(pool, bio); | ||
| 1057 | cell_defer_no_holder(tc, cell); | ||
| 1043 | 1058 | ||
| 1044 | dm_cell_release_singleton(cell, bio); | ||
| 1045 | remap_and_issue(tc, bio, lookup_result->block); | 1059 | remap_and_issue(tc, bio, lookup_result->block); |
| 1046 | } | 1060 | } |
| 1047 | } | 1061 | } |
| @@ -1056,7 +1070,9 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block | |||
| 1056 | * Remap empty bios (flushes) immediately, without provisioning. | 1070 | * Remap empty bios (flushes) immediately, without provisioning. |
| 1057 | */ | 1071 | */ |
| 1058 | if (!bio->bi_size) { | 1072 | if (!bio->bi_size) { |
| 1059 | dm_cell_release_singleton(cell, bio); | 1073 | inc_all_io_entry(tc->pool, bio); |
| 1074 | cell_defer_no_holder(tc, cell); | ||
| 1075 | |||
| 1060 | remap_and_issue(tc, bio, 0); | 1076 | remap_and_issue(tc, bio, 0); |
| 1061 | return; | 1077 | return; |
| 1062 | } | 1078 | } |
| @@ -1066,7 +1082,7 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block | |||
| 1066 | */ | 1082 | */ |
| 1067 | if (bio_data_dir(bio) == READ) { | 1083 | if (bio_data_dir(bio) == READ) { |
| 1068 | zero_fill_bio(bio); | 1084 | zero_fill_bio(bio); |
| 1069 | dm_cell_release_singleton(cell, bio); | 1085 | cell_defer_no_holder(tc, cell); |
| 1070 | bio_endio(bio, 0); | 1086 | bio_endio(bio, 0); |
| 1071 | return; | 1087 | return; |
| 1072 | } | 1088 | } |
| @@ -1085,7 +1101,8 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block | |||
| 1085 | break; | 1101 | break; |
| 1086 | 1102 | ||
| 1087 | default: | 1103 | default: |
| 1088 | DMERR("%s: alloc_data_block() failed, error = %d", __func__, r); | 1104 | DMERR_LIMIT("%s: alloc_data_block() failed: error = %d", |
| 1105 | __func__, r); | ||
| 1089 | set_pool_mode(tc->pool, PM_READ_ONLY); | 1106 | set_pool_mode(tc->pool, PM_READ_ONLY); |
| 1090 | dm_cell_error(cell); | 1107 | dm_cell_error(cell); |
| 1091 | break; | 1108 | break; |
| @@ -1111,34 +1128,31 @@ static void process_bio(struct thin_c *tc, struct bio *bio) | |||
| 1111 | r = dm_thin_find_block(tc->td, block, 1, &lookup_result); | 1128 | r = dm_thin_find_block(tc->td, block, 1, &lookup_result); |
| 1112 | switch (r) { | 1129 | switch (r) { |
| 1113 | case 0: | 1130 | case 0: |
| 1114 | /* | 1131 | if (lookup_result.shared) { |
| 1115 | * We can release this cell now. This thread is the only | ||
| 1116 | * one that puts bios into a cell, and we know there were | ||
| 1117 | * no preceding bios. | ||
| 1118 | */ | ||
| 1119 | /* | ||
| 1120 | * TODO: this will probably have to change when discard goes | ||
| 1121 | * back in. | ||
| 1122 | */ | ||
| 1123 | dm_cell_release_singleton(cell, bio); | ||
| 1124 | |||
| 1125 | if (lookup_result.shared) | ||
| 1126 | process_shared_bio(tc, bio, block, &lookup_result); | 1132 | process_shared_bio(tc, bio, block, &lookup_result); |
| 1127 | else | 1133 | cell_defer_no_holder(tc, cell); |
| 1134 | } else { | ||
| 1135 | inc_all_io_entry(tc->pool, bio); | ||
| 1136 | cell_defer_no_holder(tc, cell); | ||
| 1137 | |||
| 1128 | remap_and_issue(tc, bio, lookup_result.block); | 1138 | remap_and_issue(tc, bio, lookup_result.block); |
| 1139 | } | ||
| 1129 | break; | 1140 | break; |
| 1130 | 1141 | ||
| 1131 | case -ENODATA: | 1142 | case -ENODATA: |
| 1132 | if (bio_data_dir(bio) == READ && tc->origin_dev) { | 1143 | if (bio_data_dir(bio) == READ && tc->origin_dev) { |
| 1133 | dm_cell_release_singleton(cell, bio); | 1144 | inc_all_io_entry(tc->pool, bio); |
| 1145 | cell_defer_no_holder(tc, cell); | ||
| 1146 | |||
| 1134 | remap_to_origin_and_issue(tc, bio); | 1147 | remap_to_origin_and_issue(tc, bio); |
| 1135 | } else | 1148 | } else |
| 1136 | provision_block(tc, bio, block, cell); | 1149 | provision_block(tc, bio, block, cell); |
| 1137 | break; | 1150 | break; |
| 1138 | 1151 | ||
| 1139 | default: | 1152 | default: |
| 1140 | DMERR("dm_thin_find_block() failed, error = %d", r); | 1153 | DMERR_LIMIT("%s: dm_thin_find_block() failed: error = %d", |
| 1141 | dm_cell_release_singleton(cell, bio); | 1154 | __func__, r); |
| 1155 | cell_defer_no_holder(tc, cell); | ||
| 1142 | bio_io_error(bio); | 1156 | bio_io_error(bio); |
| 1143 | break; | 1157 | break; |
| 1144 | } | 1158 | } |
| @@ -1156,8 +1170,10 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio) | |||
| 1156 | case 0: | 1170 | case 0: |
| 1157 | if (lookup_result.shared && (rw == WRITE) && bio->bi_size) | 1171 | if (lookup_result.shared && (rw == WRITE) && bio->bi_size) |
| 1158 | bio_io_error(bio); | 1172 | bio_io_error(bio); |
| 1159 | else | 1173 | else { |
| 1174 | inc_all_io_entry(tc->pool, bio); | ||
| 1160 | remap_and_issue(tc, bio, lookup_result.block); | 1175 | remap_and_issue(tc, bio, lookup_result.block); |
| 1176 | } | ||
| 1161 | break; | 1177 | break; |
| 1162 | 1178 | ||
| 1163 | case -ENODATA: | 1179 | case -ENODATA: |
| @@ -1167,6 +1183,7 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio) | |||
| 1167 | } | 1183 | } |
| 1168 | 1184 | ||
| 1169 | if (tc->origin_dev) { | 1185 | if (tc->origin_dev) { |
| 1186 | inc_all_io_entry(tc->pool, bio); | ||
| 1170 | remap_to_origin_and_issue(tc, bio); | 1187 | remap_to_origin_and_issue(tc, bio); |
| 1171 | break; | 1188 | break; |
| 1172 | } | 1189 | } |
| @@ -1176,7 +1193,8 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio) | |||
| 1176 | break; | 1193 | break; |
| 1177 | 1194 | ||
| 1178 | default: | 1195 | default: |
| 1179 | DMERR("dm_thin_find_block() failed, error = %d", r); | 1196 | DMERR_LIMIT("%s: dm_thin_find_block() failed: error = %d", |
| 1197 | __func__, r); | ||
| 1180 | bio_io_error(bio); | 1198 | bio_io_error(bio); |
| 1181 | break; | 1199 | break; |
| 1182 | } | 1200 | } |
| @@ -1207,7 +1225,7 @@ static void process_deferred_bios(struct pool *pool) | |||
| 1207 | spin_unlock_irqrestore(&pool->lock, flags); | 1225 | spin_unlock_irqrestore(&pool->lock, flags); |
| 1208 | 1226 | ||
| 1209 | while ((bio = bio_list_pop(&bios))) { | 1227 | while ((bio = bio_list_pop(&bios))) { |
| 1210 | struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; | 1228 | struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); |
| 1211 | struct thin_c *tc = h->tc; | 1229 | struct thin_c *tc = h->tc; |
| 1212 | 1230 | ||
| 1213 | /* | 1231 | /* |
| @@ -1340,32 +1358,30 @@ static void thin_defer_bio(struct thin_c *tc, struct bio *bio) | |||
| 1340 | wake_worker(pool); | 1358 | wake_worker(pool); |
| 1341 | } | 1359 | } |
| 1342 | 1360 | ||
| 1343 | static struct dm_thin_endio_hook *thin_hook_bio(struct thin_c *tc, struct bio *bio) | 1361 | static void thin_hook_bio(struct thin_c *tc, struct bio *bio) |
| 1344 | { | 1362 | { |
| 1345 | struct pool *pool = tc->pool; | 1363 | struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); |
| 1346 | struct dm_thin_endio_hook *h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO); | ||
| 1347 | 1364 | ||
| 1348 | h->tc = tc; | 1365 | h->tc = tc; |
| 1349 | h->shared_read_entry = NULL; | 1366 | h->shared_read_entry = NULL; |
| 1350 | h->all_io_entry = bio->bi_rw & REQ_DISCARD ? NULL : dm_deferred_entry_inc(pool->all_io_ds); | 1367 | h->all_io_entry = NULL; |
| 1351 | h->overwrite_mapping = NULL; | 1368 | h->overwrite_mapping = NULL; |
| 1352 | |||
| 1353 | return h; | ||
| 1354 | } | 1369 | } |
| 1355 | 1370 | ||
| 1356 | /* | 1371 | /* |
| 1357 | * Non-blocking function called from the thin target's map function. | 1372 | * Non-blocking function called from the thin target's map function. |
| 1358 | */ | 1373 | */ |
| 1359 | static int thin_bio_map(struct dm_target *ti, struct bio *bio, | 1374 | static int thin_bio_map(struct dm_target *ti, struct bio *bio) |
| 1360 | union map_info *map_context) | ||
| 1361 | { | 1375 | { |
| 1362 | int r; | 1376 | int r; |
| 1363 | struct thin_c *tc = ti->private; | 1377 | struct thin_c *tc = ti->private; |
| 1364 | dm_block_t block = get_bio_block(tc, bio); | 1378 | dm_block_t block = get_bio_block(tc, bio); |
| 1365 | struct dm_thin_device *td = tc->td; | 1379 | struct dm_thin_device *td = tc->td; |
| 1366 | struct dm_thin_lookup_result result; | 1380 | struct dm_thin_lookup_result result; |
| 1381 | struct dm_bio_prison_cell *cell1, *cell2; | ||
| 1382 | struct dm_cell_key key; | ||
| 1367 | 1383 | ||
| 1368 | map_context->ptr = thin_hook_bio(tc, bio); | 1384 | thin_hook_bio(tc, bio); |
| 1369 | 1385 | ||
| 1370 | if (get_pool_mode(tc->pool) == PM_FAIL) { | 1386 | if (get_pool_mode(tc->pool) == PM_FAIL) { |
| 1371 | bio_io_error(bio); | 1387 | bio_io_error(bio); |
| @@ -1400,12 +1416,25 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio, | |||
| 1400 | * shared flag will be set in their case. | 1416 | * shared flag will be set in their case. |
| 1401 | */ | 1417 | */ |
| 1402 | thin_defer_bio(tc, bio); | 1418 | thin_defer_bio(tc, bio); |
| 1403 | r = DM_MAPIO_SUBMITTED; | 1419 | return DM_MAPIO_SUBMITTED; |
| 1404 | } else { | ||
| 1405 | remap(tc, bio, result.block); | ||
| 1406 | r = DM_MAPIO_REMAPPED; | ||
| 1407 | } | 1420 | } |
| 1408 | break; | 1421 | |
| 1422 | build_virtual_key(tc->td, block, &key); | ||
| 1423 | if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1)) | ||
| 1424 | return DM_MAPIO_SUBMITTED; | ||
| 1425 | |||
| 1426 | build_data_key(tc->td, result.block, &key); | ||
| 1427 | if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2)) { | ||
| 1428 | cell_defer_no_holder(tc, cell1); | ||
| 1429 | return DM_MAPIO_SUBMITTED; | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | inc_all_io_entry(tc->pool, bio); | ||
| 1433 | cell_defer_no_holder(tc, cell2); | ||
| 1434 | cell_defer_no_holder(tc, cell1); | ||
| 1435 | |||
| 1436 | remap(tc, bio, result.block); | ||
| 1437 | return DM_MAPIO_REMAPPED; | ||
| 1409 | 1438 | ||
| 1410 | case -ENODATA: | 1439 | case -ENODATA: |
| 1411 | if (get_pool_mode(tc->pool) == PM_READ_ONLY) { | 1440 | if (get_pool_mode(tc->pool) == PM_READ_ONLY) { |
| @@ -1414,8 +1443,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio, | |||
| 1414 | * of doing so. Just error it. | 1443 | * of doing so. Just error it. |
| 1415 | */ | 1444 | */ |
| 1416 | bio_io_error(bio); | 1445 | bio_io_error(bio); |
| 1417 | r = DM_MAPIO_SUBMITTED; | 1446 | return DM_MAPIO_SUBMITTED; |
| 1418 | break; | ||
| 1419 | } | 1447 | } |
| 1420 | /* fall through */ | 1448 | /* fall through */ |
| 1421 | 1449 | ||
| @@ -1425,8 +1453,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio, | |||
| 1425 | * provide the hint to load the metadata into cache. | 1453 | * provide the hint to load the metadata into cache. |
| 1426 | */ | 1454 | */ |
| 1427 | thin_defer_bio(tc, bio); | 1455 | thin_defer_bio(tc, bio); |
| 1428 | r = DM_MAPIO_SUBMITTED; | 1456 | return DM_MAPIO_SUBMITTED; |
| 1429 | break; | ||
| 1430 | 1457 | ||
| 1431 | default: | 1458 | default: |
| 1432 | /* | 1459 | /* |
| @@ -1435,11 +1462,8 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio, | |||
| 1435 | * pool is switched to fail-io mode. | 1462 | * pool is switched to fail-io mode. |
| 1436 | */ | 1463 | */ |
| 1437 | bio_io_error(bio); | 1464 | bio_io_error(bio); |
| 1438 | r = DM_MAPIO_SUBMITTED; | 1465 | return DM_MAPIO_SUBMITTED; |
| 1439 | break; | ||
| 1440 | } | 1466 | } |
| 1441 | |||
| 1442 | return r; | ||
| 1443 | } | 1467 | } |
| 1444 | 1468 | ||
| 1445 | static int pool_is_congested(struct dm_target_callbacks *cb, int bdi_bits) | 1469 | static int pool_is_congested(struct dm_target_callbacks *cb, int bdi_bits) |
| @@ -1566,14 +1590,12 @@ static void __pool_destroy(struct pool *pool) | |||
| 1566 | if (pool->next_mapping) | 1590 | if (pool->next_mapping) |
| 1567 | mempool_free(pool->next_mapping, pool->mapping_pool); | 1591 | mempool_free(pool->next_mapping, pool->mapping_pool); |
| 1568 | mempool_destroy(pool->mapping_pool); | 1592 | mempool_destroy(pool->mapping_pool); |
| 1569 | mempool_destroy(pool->endio_hook_pool); | ||
| 1570 | dm_deferred_set_destroy(pool->shared_read_ds); | 1593 | dm_deferred_set_destroy(pool->shared_read_ds); |
| 1571 | dm_deferred_set_destroy(pool->all_io_ds); | 1594 | dm_deferred_set_destroy(pool->all_io_ds); |
| 1572 | kfree(pool); | 1595 | kfree(pool); |
| 1573 | } | 1596 | } |
| 1574 | 1597 | ||
| 1575 | static struct kmem_cache *_new_mapping_cache; | 1598 | static struct kmem_cache *_new_mapping_cache; |
| 1576 | static struct kmem_cache *_endio_hook_cache; | ||
| 1577 | 1599 | ||
| 1578 | static struct pool *pool_create(struct mapped_device *pool_md, | 1600 | static struct pool *pool_create(struct mapped_device *pool_md, |
| 1579 | struct block_device *metadata_dev, | 1601 | struct block_device *metadata_dev, |
| @@ -1667,13 +1689,6 @@ static struct pool *pool_create(struct mapped_device *pool_md, | |||
| 1667 | goto bad_mapping_pool; | 1689 | goto bad_mapping_pool; |
| 1668 | } | 1690 | } |
| 1669 | 1691 | ||
| 1670 | pool->endio_hook_pool = mempool_create_slab_pool(ENDIO_HOOK_POOL_SIZE, | ||
| 1671 | _endio_hook_cache); | ||
| 1672 | if (!pool->endio_hook_pool) { | ||
| 1673 | *error = "Error creating pool's endio_hook mempool"; | ||
| 1674 | err_p = ERR_PTR(-ENOMEM); | ||
| 1675 | goto bad_endio_hook_pool; | ||
| 1676 | } | ||
| 1677 | pool->ref_count = 1; | 1692 | pool->ref_count = 1; |
| 1678 | pool->last_commit_jiffies = jiffies; | 1693 | pool->last_commit_jiffies = jiffies; |
| 1679 | pool->pool_md = pool_md; | 1694 | pool->pool_md = pool_md; |
| @@ -1682,8 +1697,6 @@ static struct pool *pool_create(struct mapped_device *pool_md, | |||
| 1682 | 1697 | ||
| 1683 | return pool; | 1698 | return pool; |
| 1684 | 1699 | ||
| 1685 | bad_endio_hook_pool: | ||
| 1686 | mempool_destroy(pool->mapping_pool); | ||
| 1687 | bad_mapping_pool: | 1700 | bad_mapping_pool: |
| 1688 | dm_deferred_set_destroy(pool->all_io_ds); | 1701 | dm_deferred_set_destroy(pool->all_io_ds); |
| 1689 | bad_all_io_ds: | 1702 | bad_all_io_ds: |
| @@ -1966,8 +1979,7 @@ out_unlock: | |||
| 1966 | return r; | 1979 | return r; |
| 1967 | } | 1980 | } |
| 1968 | 1981 | ||
| 1969 | static int pool_map(struct dm_target *ti, struct bio *bio, | 1982 | static int pool_map(struct dm_target *ti, struct bio *bio) |
| 1970 | union map_info *map_context) | ||
| 1971 | { | 1983 | { |
| 1972 | int r; | 1984 | int r; |
| 1973 | struct pool_c *pt = ti->private; | 1985 | struct pool_c *pt = ti->private; |
| @@ -2358,7 +2370,9 @@ static int pool_status(struct dm_target *ti, status_type_t type, | |||
| 2358 | else | 2370 | else |
| 2359 | DMEMIT("rw "); | 2371 | DMEMIT("rw "); |
| 2360 | 2372 | ||
| 2361 | if (pool->pf.discard_enabled && pool->pf.discard_passdown) | 2373 | if (!pool->pf.discard_enabled) |
| 2374 | DMEMIT("ignore_discard"); | ||
| 2375 | else if (pool->pf.discard_passdown) | ||
| 2362 | DMEMIT("discard_passdown"); | 2376 | DMEMIT("discard_passdown"); |
| 2363 | else | 2377 | else |
| 2364 | DMEMIT("no_discard_passdown"); | 2378 | DMEMIT("no_discard_passdown"); |
| @@ -2454,7 +2468,7 @@ static struct target_type pool_target = { | |||
| 2454 | .name = "thin-pool", | 2468 | .name = "thin-pool", |
| 2455 | .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | | 2469 | .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | |
| 2456 | DM_TARGET_IMMUTABLE, | 2470 | DM_TARGET_IMMUTABLE, |
| 2457 | .version = {1, 5, 0}, | 2471 | .version = {1, 6, 0}, |
| 2458 | .module = THIS_MODULE, | 2472 | .module = THIS_MODULE, |
| 2459 | .ctr = pool_ctr, | 2473 | .ctr = pool_ctr, |
| 2460 | .dtr = pool_dtr, | 2474 | .dtr = pool_dtr, |
| @@ -2576,6 +2590,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
| 2576 | 2590 | ||
| 2577 | ti->num_flush_requests = 1; | 2591 | ti->num_flush_requests = 1; |
| 2578 | ti->flush_supported = true; | 2592 | ti->flush_supported = true; |
| 2593 | ti->per_bio_data_size = sizeof(struct dm_thin_endio_hook); | ||
| 2579 | 2594 | ||
| 2580 | /* In case the pool supports discards, pass them on. */ | 2595 | /* In case the pool supports discards, pass them on. */ |
| 2581 | if (tc->pool->pf.discard_enabled) { | 2596 | if (tc->pool->pf.discard_enabled) { |
| @@ -2609,20 +2624,17 @@ out_unlock: | |||
| 2609 | return r; | 2624 | return r; |
| 2610 | } | 2625 | } |
| 2611 | 2626 | ||
| 2612 | static int thin_map(struct dm_target *ti, struct bio *bio, | 2627 | static int thin_map(struct dm_target *ti, struct bio *bio) |
| 2613 | union map_info *map_context) | ||
| 2614 | { | 2628 | { |
| 2615 | bio->bi_sector = dm_target_offset(ti, bio->bi_sector); | 2629 | bio->bi_sector = dm_target_offset(ti, bio->bi_sector); |
| 2616 | 2630 | ||
| 2617 | return thin_bio_map(ti, bio, map_context); | 2631 | return thin_bio_map(ti, bio); |
| 2618 | } | 2632 | } |
| 2619 | 2633 | ||
| 2620 | static int thin_endio(struct dm_target *ti, | 2634 | static int thin_endio(struct dm_target *ti, struct bio *bio, int err) |
| 2621 | struct bio *bio, int err, | ||
| 2622 | union map_info *map_context) | ||
| 2623 | { | 2635 | { |
| 2624 | unsigned long flags; | 2636 | unsigned long flags; |
| 2625 | struct dm_thin_endio_hook *h = map_context->ptr; | 2637 | struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); |
| 2626 | struct list_head work; | 2638 | struct list_head work; |
| 2627 | struct dm_thin_new_mapping *m, *tmp; | 2639 | struct dm_thin_new_mapping *m, *tmp; |
| 2628 | struct pool *pool = h->tc->pool; | 2640 | struct pool *pool = h->tc->pool; |
| @@ -2643,14 +2655,15 @@ static int thin_endio(struct dm_target *ti, | |||
| 2643 | if (h->all_io_entry) { | 2655 | if (h->all_io_entry) { |
| 2644 | INIT_LIST_HEAD(&work); | 2656 | INIT_LIST_HEAD(&work); |
| 2645 | dm_deferred_entry_dec(h->all_io_entry, &work); | 2657 | dm_deferred_entry_dec(h->all_io_entry, &work); |
| 2646 | spin_lock_irqsave(&pool->lock, flags); | 2658 | if (!list_empty(&work)) { |
| 2647 | list_for_each_entry_safe(m, tmp, &work, list) | 2659 | spin_lock_irqsave(&pool->lock, flags); |
| 2648 | list_add(&m->list, &pool->prepared_discards); | 2660 | list_for_each_entry_safe(m, tmp, &work, list) |
| 2649 | spin_unlock_irqrestore(&pool->lock, flags); | 2661 | list_add(&m->list, &pool->prepared_discards); |
| 2662 | spin_unlock_irqrestore(&pool->lock, flags); | ||
| 2663 | wake_worker(pool); | ||
| 2664 | } | ||
| 2650 | } | 2665 | } |
| 2651 | 2666 | ||
| 2652 | mempool_free(h, pool->endio_hook_pool); | ||
| 2653 | |||
| 2654 | return 0; | 2667 | return 0; |
| 2655 | } | 2668 | } |
| 2656 | 2669 | ||
| @@ -2745,7 +2758,7 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) | |||
| 2745 | 2758 | ||
| 2746 | static struct target_type thin_target = { | 2759 | static struct target_type thin_target = { |
| 2747 | .name = "thin", | 2760 | .name = "thin", |
| 2748 | .version = {1, 5, 0}, | 2761 | .version = {1, 6, 0}, |
| 2749 | .module = THIS_MODULE, | 2762 | .module = THIS_MODULE, |
| 2750 | .ctr = thin_ctr, | 2763 | .ctr = thin_ctr, |
| 2751 | .dtr = thin_dtr, | 2764 | .dtr = thin_dtr, |
| @@ -2779,14 +2792,8 @@ static int __init dm_thin_init(void) | |||
| 2779 | if (!_new_mapping_cache) | 2792 | if (!_new_mapping_cache) |
| 2780 | goto bad_new_mapping_cache; | 2793 | goto bad_new_mapping_cache; |
| 2781 | 2794 | ||
| 2782 | _endio_hook_cache = KMEM_CACHE(dm_thin_endio_hook, 0); | ||
| 2783 | if (!_endio_hook_cache) | ||
| 2784 | goto bad_endio_hook_cache; | ||
| 2785 | |||
| 2786 | return 0; | 2795 | return 0; |
| 2787 | 2796 | ||
| 2788 | bad_endio_hook_cache: | ||
| 2789 | kmem_cache_destroy(_new_mapping_cache); | ||
| 2790 | bad_new_mapping_cache: | 2797 | bad_new_mapping_cache: |
| 2791 | dm_unregister_target(&pool_target); | 2798 | dm_unregister_target(&pool_target); |
| 2792 | bad_pool_target: | 2799 | bad_pool_target: |
| @@ -2801,7 +2808,6 @@ static void dm_thin_exit(void) | |||
| 2801 | dm_unregister_target(&pool_target); | 2808 | dm_unregister_target(&pool_target); |
| 2802 | 2809 | ||
| 2803 | kmem_cache_destroy(_new_mapping_cache); | 2810 | kmem_cache_destroy(_new_mapping_cache); |
| 2804 | kmem_cache_destroy(_endio_hook_cache); | ||
| 2805 | } | 2811 | } |
| 2806 | 2812 | ||
| 2807 | module_init(dm_thin_init); | 2813 | module_init(dm_thin_init); |
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index 9e7328bb4030..52cde982164a 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c | |||
| @@ -55,7 +55,6 @@ struct dm_verity { | |||
| 55 | unsigned shash_descsize;/* the size of temporary space for crypto */ | 55 | unsigned shash_descsize;/* the size of temporary space for crypto */ |
| 56 | int hash_failed; /* set to 1 if hash of any block failed */ | 56 | int hash_failed; /* set to 1 if hash of any block failed */ |
| 57 | 57 | ||
| 58 | mempool_t *io_mempool; /* mempool of struct dm_verity_io */ | ||
| 59 | mempool_t *vec_mempool; /* mempool of bio vector */ | 58 | mempool_t *vec_mempool; /* mempool of bio vector */ |
| 60 | 59 | ||
| 61 | struct workqueue_struct *verify_wq; | 60 | struct workqueue_struct *verify_wq; |
| @@ -66,7 +65,6 @@ struct dm_verity { | |||
| 66 | 65 | ||
| 67 | struct dm_verity_io { | 66 | struct dm_verity_io { |
| 68 | struct dm_verity *v; | 67 | struct dm_verity *v; |
| 69 | struct bio *bio; | ||
| 70 | 68 | ||
| 71 | /* original values of bio->bi_end_io and bio->bi_private */ | 69 | /* original values of bio->bi_end_io and bio->bi_private */ |
| 72 | bio_end_io_t *orig_bi_end_io; | 70 | bio_end_io_t *orig_bi_end_io; |
| @@ -389,8 +387,8 @@ test_block_hash: | |||
| 389 | */ | 387 | */ |
| 390 | static void verity_finish_io(struct dm_verity_io *io, int error) | 388 | static void verity_finish_io(struct dm_verity_io *io, int error) |
| 391 | { | 389 | { |
| 392 | struct bio *bio = io->bio; | ||
| 393 | struct dm_verity *v = io->v; | 390 | struct dm_verity *v = io->v; |
| 391 | struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_bio_data_size); | ||
| 394 | 392 | ||
| 395 | bio->bi_end_io = io->orig_bi_end_io; | 393 | bio->bi_end_io = io->orig_bi_end_io; |
| 396 | bio->bi_private = io->orig_bi_private; | 394 | bio->bi_private = io->orig_bi_private; |
| @@ -398,8 +396,6 @@ static void verity_finish_io(struct dm_verity_io *io, int error) | |||
| 398 | if (io->io_vec != io->io_vec_inline) | 396 | if (io->io_vec != io->io_vec_inline) |
| 399 | mempool_free(io->io_vec, v->vec_mempool); | 397 | mempool_free(io->io_vec, v->vec_mempool); |
| 400 | 398 | ||
| 401 | mempool_free(io, v->io_mempool); | ||
| 402 | |||
| 403 | bio_endio(bio, error); | 399 | bio_endio(bio, error); |
| 404 | } | 400 | } |
| 405 | 401 | ||
| @@ -462,8 +458,7 @@ no_prefetch_cluster: | |||
| 462 | * Bio map function. It allocates dm_verity_io structure and bio vector and | 458 | * Bio map function. It allocates dm_verity_io structure and bio vector and |
| 463 | * fills them. Then it issues prefetches and the I/O. | 459 | * fills them. Then it issues prefetches and the I/O. |
| 464 | */ | 460 | */ |
| 465 | static int verity_map(struct dm_target *ti, struct bio *bio, | 461 | static int verity_map(struct dm_target *ti, struct bio *bio) |
| 466 | union map_info *map_context) | ||
| 467 | { | 462 | { |
| 468 | struct dm_verity *v = ti->private; | 463 | struct dm_verity *v = ti->private; |
| 469 | struct dm_verity_io *io; | 464 | struct dm_verity_io *io; |
| @@ -486,9 +481,8 @@ static int verity_map(struct dm_target *ti, struct bio *bio, | |||
| 486 | if (bio_data_dir(bio) == WRITE) | 481 | if (bio_data_dir(bio) == WRITE) |
| 487 | return -EIO; | 482 | return -EIO; |
| 488 | 483 | ||
| 489 | io = mempool_alloc(v->io_mempool, GFP_NOIO); | 484 | io = dm_per_bio_data(bio, ti->per_bio_data_size); |
| 490 | io->v = v; | 485 | io->v = v; |
| 491 | io->bio = bio; | ||
| 492 | io->orig_bi_end_io = bio->bi_end_io; | 486 | io->orig_bi_end_io = bio->bi_end_io; |
| 493 | io->orig_bi_private = bio->bi_private; | 487 | io->orig_bi_private = bio->bi_private; |
| 494 | io->block = bio->bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT); | 488 | io->block = bio->bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT); |
| @@ -610,9 +604,6 @@ static void verity_dtr(struct dm_target *ti) | |||
| 610 | if (v->vec_mempool) | 604 | if (v->vec_mempool) |
| 611 | mempool_destroy(v->vec_mempool); | 605 | mempool_destroy(v->vec_mempool); |
| 612 | 606 | ||
| 613 | if (v->io_mempool) | ||
| 614 | mempool_destroy(v->io_mempool); | ||
| 615 | |||
| 616 | if (v->bufio) | 607 | if (v->bufio) |
| 617 | dm_bufio_client_destroy(v->bufio); | 608 | dm_bufio_client_destroy(v->bufio); |
| 618 | 609 | ||
| @@ -841,13 +832,7 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
| 841 | goto bad; | 832 | goto bad; |
| 842 | } | 833 | } |
| 843 | 834 | ||
| 844 | v->io_mempool = mempool_create_kmalloc_pool(DM_VERITY_MEMPOOL_SIZE, | 835 | ti->per_bio_data_size = roundup(sizeof(struct dm_verity_io) + v->shash_descsize + v->digest_size * 2, __alignof__(struct dm_verity_io)); |
| 845 | sizeof(struct dm_verity_io) + v->shash_descsize + v->digest_size * 2); | ||
| 846 | if (!v->io_mempool) { | ||
| 847 | ti->error = "Cannot allocate io mempool"; | ||
| 848 | r = -ENOMEM; | ||
| 849 | goto bad; | ||
| 850 | } | ||
| 851 | 836 | ||
| 852 | v->vec_mempool = mempool_create_kmalloc_pool(DM_VERITY_MEMPOOL_SIZE, | 837 | v->vec_mempool = mempool_create_kmalloc_pool(DM_VERITY_MEMPOOL_SIZE, |
| 853 | BIO_MAX_PAGES * sizeof(struct bio_vec)); | 838 | BIO_MAX_PAGES * sizeof(struct bio_vec)); |
| @@ -875,7 +860,7 @@ bad: | |||
| 875 | 860 | ||
| 876 | static struct target_type verity_target = { | 861 | static struct target_type verity_target = { |
| 877 | .name = "verity", | 862 | .name = "verity", |
| 878 | .version = {1, 0, 0}, | 863 | .version = {1, 1, 0}, |
| 879 | .module = THIS_MODULE, | 864 | .module = THIS_MODULE, |
| 880 | .ctr = verity_ctr, | 865 | .ctr = verity_ctr, |
| 881 | .dtr = verity_dtr, | 866 | .dtr = verity_dtr, |
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c index cc2b3cb81946..69a5c3b3b340 100644 --- a/drivers/md/dm-zero.c +++ b/drivers/md/dm-zero.c | |||
| @@ -33,8 +33,7 @@ static int zero_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 33 | /* | 33 | /* |
| 34 | * Return zeros only on reads | 34 | * Return zeros only on reads |
| 35 | */ | 35 | */ |
| 36 | static int zero_map(struct dm_target *ti, struct bio *bio, | 36 | static int zero_map(struct dm_target *ti, struct bio *bio) |
| 37 | union map_info *map_context) | ||
| 38 | { | 37 | { |
| 39 | switch(bio_rw(bio)) { | 38 | switch(bio_rw(bio)) { |
| 40 | case READ: | 39 | case READ: |
| @@ -56,7 +55,7 @@ static int zero_map(struct dm_target *ti, struct bio *bio, | |||
| 56 | 55 | ||
| 57 | static struct target_type zero_target = { | 56 | static struct target_type zero_target = { |
| 58 | .name = "zero", | 57 | .name = "zero", |
| 59 | .version = {1, 0, 0}, | 58 | .version = {1, 1, 0}, |
| 60 | .module = THIS_MODULE, | 59 | .module = THIS_MODULE, |
| 61 | .ctr = zero_ctr, | 60 | .ctr = zero_ctr, |
| 62 | .map = zero_map, | 61 | .map = zero_map, |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 77e6eff41cae..c72e4d5a9617 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
| @@ -63,18 +63,6 @@ struct dm_io { | |||
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | /* | 65 | /* |
| 66 | * For bio-based dm. | ||
| 67 | * One of these is allocated per target within a bio. Hopefully | ||
| 68 | * this will be simplified out one day. | ||
| 69 | */ | ||
| 70 | struct dm_target_io { | ||
| 71 | struct dm_io *io; | ||
| 72 | struct dm_target *ti; | ||
| 73 | union map_info info; | ||
| 74 | struct bio clone; | ||
| 75 | }; | ||
| 76 | |||
| 77 | /* | ||
| 78 | * For request-based dm. | 66 | * For request-based dm. |
| 79 | * One of these is allocated per request. | 67 | * One of these is allocated per request. |
| 80 | */ | 68 | */ |
| @@ -657,7 +645,7 @@ static void clone_endio(struct bio *bio, int error) | |||
| 657 | error = -EIO; | 645 | error = -EIO; |
| 658 | 646 | ||
| 659 | if (endio) { | 647 | if (endio) { |
| 660 | r = endio(tio->ti, bio, error, &tio->info); | 648 | r = endio(tio->ti, bio, error); |
| 661 | if (r < 0 || r == DM_ENDIO_REQUEUE) | 649 | if (r < 0 || r == DM_ENDIO_REQUEUE) |
| 662 | /* | 650 | /* |
| 663 | * error and requeue request are handled | 651 | * error and requeue request are handled |
| @@ -1016,7 +1004,7 @@ static void __map_bio(struct dm_target *ti, struct dm_target_io *tio) | |||
| 1016 | */ | 1004 | */ |
| 1017 | atomic_inc(&tio->io->io_count); | 1005 | atomic_inc(&tio->io->io_count); |
| 1018 | sector = clone->bi_sector; | 1006 | sector = clone->bi_sector; |
| 1019 | r = ti->type->map(ti, clone, &tio->info); | 1007 | r = ti->type->map(ti, clone); |
| 1020 | if (r == DM_MAPIO_REMAPPED) { | 1008 | if (r == DM_MAPIO_REMAPPED) { |
| 1021 | /* the bio has been remapped so dispatch it */ | 1009 | /* the bio has been remapped so dispatch it */ |
| 1022 | 1010 | ||
| @@ -1111,6 +1099,7 @@ static struct dm_target_io *alloc_tio(struct clone_info *ci, | |||
| 1111 | tio->io = ci->io; | 1099 | tio->io = ci->io; |
| 1112 | tio->ti = ti; | 1100 | tio->ti = ti; |
| 1113 | memset(&tio->info, 0, sizeof(tio->info)); | 1101 | memset(&tio->info, 0, sizeof(tio->info)); |
| 1102 | tio->target_request_nr = 0; | ||
| 1114 | 1103 | ||
| 1115 | return tio; | 1104 | return tio; |
| 1116 | } | 1105 | } |
| @@ -1121,7 +1110,7 @@ static void __issue_target_request(struct clone_info *ci, struct dm_target *ti, | |||
| 1121 | struct dm_target_io *tio = alloc_tio(ci, ti, ci->bio->bi_max_vecs); | 1110 | struct dm_target_io *tio = alloc_tio(ci, ti, ci->bio->bi_max_vecs); |
| 1122 | struct bio *clone = &tio->clone; | 1111 | struct bio *clone = &tio->clone; |
| 1123 | 1112 | ||
| 1124 | tio->info.target_request_nr = request_nr; | 1113 | tio->target_request_nr = request_nr; |
| 1125 | 1114 | ||
| 1126 | /* | 1115 | /* |
| 1127 | * Discard requests require the bio's inline iovecs be initialized. | 1116 | * Discard requests require the bio's inline iovecs be initialized. |
| @@ -1174,7 +1163,28 @@ static void __clone_and_map_simple(struct clone_info *ci, struct dm_target *ti) | |||
| 1174 | ci->sector_count = 0; | 1163 | ci->sector_count = 0; |
| 1175 | } | 1164 | } |
| 1176 | 1165 | ||
| 1177 | static int __clone_and_map_discard(struct clone_info *ci) | 1166 | typedef unsigned (*get_num_requests_fn)(struct dm_target *ti); |
| 1167 | |||
| 1168 | static unsigned get_num_discard_requests(struct dm_target *ti) | ||
| 1169 | { | ||
| 1170 | return ti->num_discard_requests; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | static unsigned get_num_write_same_requests(struct dm_target *ti) | ||
| 1174 | { | ||
| 1175 | return ti->num_write_same_requests; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | typedef bool (*is_split_required_fn)(struct dm_target *ti); | ||
| 1179 | |||
| 1180 | static bool is_split_required_for_discard(struct dm_target *ti) | ||
| 1181 | { | ||
| 1182 | return ti->split_discard_requests; | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | static int __clone_and_map_changing_extent_only(struct clone_info *ci, | ||
| 1186 | get_num_requests_fn get_num_requests, | ||
| 1187 | is_split_required_fn is_split_required) | ||
| 1178 | { | 1188 | { |
| 1179 | struct dm_target *ti; | 1189 | struct dm_target *ti; |
| 1180 | sector_t len; | 1190 | sector_t len; |
| @@ -1185,15 +1195,15 @@ static int __clone_and_map_discard(struct clone_info *ci) | |||
| 1185 | return -EIO; | 1195 | return -EIO; |
| 1186 | 1196 | ||
| 1187 | /* | 1197 | /* |
| 1188 | * Even though the device advertised discard support, | 1198 | * Even though the device advertised support for this type of |
| 1189 | * that does not mean every target supports it, and | 1199 | * request, that does not mean every target supports it, and |
| 1190 | * reconfiguration might also have changed that since the | 1200 | * reconfiguration might also have changed that since the |
| 1191 | * check was performed. | 1201 | * check was performed. |
| 1192 | */ | 1202 | */ |
| 1193 | if (!ti->num_discard_requests) | 1203 | if (!get_num_requests || !get_num_requests(ti)) |
| 1194 | return -EOPNOTSUPP; | 1204 | return -EOPNOTSUPP; |
| 1195 | 1205 | ||
| 1196 | if (!ti->split_discard_requests) | 1206 | if (is_split_required && !is_split_required(ti)) |
| 1197 | len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti)); | 1207 | len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti)); |
| 1198 | else | 1208 | else |
| 1199 | len = min(ci->sector_count, max_io_len(ci->sector, ti)); | 1209 | len = min(ci->sector_count, max_io_len(ci->sector, ti)); |
| @@ -1206,6 +1216,17 @@ static int __clone_and_map_discard(struct clone_info *ci) | |||
| 1206 | return 0; | 1216 | return 0; |
| 1207 | } | 1217 | } |
| 1208 | 1218 | ||
| 1219 | static int __clone_and_map_discard(struct clone_info *ci) | ||
| 1220 | { | ||
| 1221 | return __clone_and_map_changing_extent_only(ci, get_num_discard_requests, | ||
| 1222 | is_split_required_for_discard); | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | static int __clone_and_map_write_same(struct clone_info *ci) | ||
| 1226 | { | ||
| 1227 | return __clone_and_map_changing_extent_only(ci, get_num_write_same_requests, NULL); | ||
| 1228 | } | ||
| 1229 | |||
| 1209 | static int __clone_and_map(struct clone_info *ci) | 1230 | static int __clone_and_map(struct clone_info *ci) |
| 1210 | { | 1231 | { |
| 1211 | struct bio *bio = ci->bio; | 1232 | struct bio *bio = ci->bio; |
| @@ -1215,6 +1236,8 @@ static int __clone_and_map(struct clone_info *ci) | |||
| 1215 | 1236 | ||
| 1216 | if (unlikely(bio->bi_rw & REQ_DISCARD)) | 1237 | if (unlikely(bio->bi_rw & REQ_DISCARD)) |
| 1217 | return __clone_and_map_discard(ci); | 1238 | return __clone_and_map_discard(ci); |
| 1239 | else if (unlikely(bio->bi_rw & REQ_WRITE_SAME)) | ||
| 1240 | return __clone_and_map_write_same(ci); | ||
| 1218 | 1241 | ||
| 1219 | ti = dm_table_find_target(ci->map, ci->sector); | 1242 | ti = dm_table_find_target(ci->map, ci->sector); |
| 1220 | if (!dm_target_is_valid(ti)) | 1243 | if (!dm_target_is_valid(ti)) |
| @@ -1946,13 +1969,20 @@ static void free_dev(struct mapped_device *md) | |||
| 1946 | 1969 | ||
| 1947 | static void __bind_mempools(struct mapped_device *md, struct dm_table *t) | 1970 | static void __bind_mempools(struct mapped_device *md, struct dm_table *t) |
| 1948 | { | 1971 | { |
| 1949 | struct dm_md_mempools *p; | 1972 | struct dm_md_mempools *p = dm_table_get_md_mempools(t); |
| 1950 | 1973 | ||
| 1951 | if (md->io_pool && (md->tio_pool || dm_table_get_type(t) == DM_TYPE_BIO_BASED) && md->bs) | 1974 | if (md->io_pool && (md->tio_pool || dm_table_get_type(t) == DM_TYPE_BIO_BASED) && md->bs) { |
| 1952 | /* the md already has necessary mempools */ | 1975 | /* |
| 1976 | * The md already has necessary mempools. Reload just the | ||
| 1977 | * bioset because front_pad may have changed because | ||
| 1978 | * a different table was loaded. | ||
| 1979 | */ | ||
| 1980 | bioset_free(md->bs); | ||
| 1981 | md->bs = p->bs; | ||
| 1982 | p->bs = NULL; | ||
| 1953 | goto out; | 1983 | goto out; |
| 1984 | } | ||
| 1954 | 1985 | ||
| 1955 | p = dm_table_get_md_mempools(t); | ||
| 1956 | BUG_ON(!p || md->io_pool || md->tio_pool || md->bs); | 1986 | BUG_ON(!p || md->io_pool || md->tio_pool || md->bs); |
| 1957 | 1987 | ||
| 1958 | md->io_pool = p->io_pool; | 1988 | md->io_pool = p->io_pool; |
| @@ -2711,7 +2741,7 @@ int dm_noflush_suspending(struct dm_target *ti) | |||
| 2711 | } | 2741 | } |
| 2712 | EXPORT_SYMBOL_GPL(dm_noflush_suspending); | 2742 | EXPORT_SYMBOL_GPL(dm_noflush_suspending); |
| 2713 | 2743 | ||
| 2714 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity) | 2744 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_bio_data_size) |
| 2715 | { | 2745 | { |
| 2716 | struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL); | 2746 | struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL); |
| 2717 | unsigned int pool_size = (type == DM_TYPE_BIO_BASED) ? 16 : MIN_IOS; | 2747 | unsigned int pool_size = (type == DM_TYPE_BIO_BASED) ? 16 : MIN_IOS; |
| @@ -2719,6 +2749,8 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity) | |||
| 2719 | if (!pools) | 2749 | if (!pools) |
| 2720 | return NULL; | 2750 | return NULL; |
| 2721 | 2751 | ||
| 2752 | per_bio_data_size = roundup(per_bio_data_size, __alignof__(struct dm_target_io)); | ||
| 2753 | |||
| 2722 | pools->io_pool = (type == DM_TYPE_BIO_BASED) ? | 2754 | pools->io_pool = (type == DM_TYPE_BIO_BASED) ? |
| 2723 | mempool_create_slab_pool(MIN_IOS, _io_cache) : | 2755 | mempool_create_slab_pool(MIN_IOS, _io_cache) : |
| 2724 | mempool_create_slab_pool(MIN_IOS, _rq_bio_info_cache); | 2756 | mempool_create_slab_pool(MIN_IOS, _rq_bio_info_cache); |
| @@ -2734,7 +2766,7 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity) | |||
| 2734 | 2766 | ||
| 2735 | pools->bs = (type == DM_TYPE_BIO_BASED) ? | 2767 | pools->bs = (type == DM_TYPE_BIO_BASED) ? |
| 2736 | bioset_create(pool_size, | 2768 | bioset_create(pool_size, |
| 2737 | offsetof(struct dm_target_io, clone)) : | 2769 | per_bio_data_size + offsetof(struct dm_target_io, clone)) : |
| 2738 | bioset_create(pool_size, | 2770 | bioset_create(pool_size, |
| 2739 | offsetof(struct dm_rq_clone_bio_info, clone)); | 2771 | offsetof(struct dm_rq_clone_bio_info, clone)); |
| 2740 | if (!pools->bs) | 2772 | if (!pools->bs) |
diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 6a99fefaa743..45b97da1bd06 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h | |||
| @@ -159,7 +159,7 @@ void dm_kcopyd_exit(void); | |||
| 159 | /* | 159 | /* |
| 160 | * Mempool operations | 160 | * Mempool operations |
| 161 | */ | 161 | */ |
| 162 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity); | 162 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_bio_data_size); |
| 163 | void dm_free_md_mempools(struct dm_md_mempools *pools); | 163 | void dm_free_md_mempools(struct dm_md_mempools *pools); |
| 164 | 164 | ||
| 165 | #endif | 165 | #endif |
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c index a3ae09124a67..28c3ed072a79 100644 --- a/drivers/md/persistent-data/dm-block-manager.c +++ b/drivers/md/persistent-data/dm-block-manager.c | |||
| @@ -428,15 +428,17 @@ static int dm_bm_validate_buffer(struct dm_block_manager *bm, | |||
| 428 | if (!v) | 428 | if (!v) |
| 429 | return 0; | 429 | return 0; |
| 430 | r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(bm->bufio)); | 430 | r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(bm->bufio)); |
| 431 | if (unlikely(r)) | 431 | if (unlikely(r)) { |
| 432 | DMERR_LIMIT("%s validator check failed for block %llu", v->name, | ||
| 433 | (unsigned long long) dm_bufio_get_block_number(buf)); | ||
| 432 | return r; | 434 | return r; |
| 435 | } | ||
| 433 | aux->validator = v; | 436 | aux->validator = v; |
| 434 | } else { | 437 | } else { |
| 435 | if (unlikely(aux->validator != v)) { | 438 | if (unlikely(aux->validator != v)) { |
| 436 | DMERR("validator mismatch (old=%s vs new=%s) for block %llu", | 439 | DMERR_LIMIT("validator mismatch (old=%s vs new=%s) for block %llu", |
| 437 | aux->validator->name, v ? v->name : "NULL", | 440 | aux->validator->name, v ? v->name : "NULL", |
| 438 | (unsigned long long) | 441 | (unsigned long long) dm_bufio_get_block_number(buf)); |
| 439 | dm_bufio_get_block_number(buf)); | ||
| 440 | return -EINVAL; | 442 | return -EINVAL; |
| 441 | } | 443 | } |
| 442 | } | 444 | } |
diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h index 5709bfeab1e8..accbb05f17b6 100644 --- a/drivers/md/persistent-data/dm-btree-internal.h +++ b/drivers/md/persistent-data/dm-btree-internal.h | |||
| @@ -36,13 +36,13 @@ struct node_header { | |||
| 36 | __le32 padding; | 36 | __le32 padding; |
| 37 | } __packed; | 37 | } __packed; |
| 38 | 38 | ||
| 39 | struct node { | 39 | struct btree_node { |
| 40 | struct node_header header; | 40 | struct node_header header; |
| 41 | __le64 keys[0]; | 41 | __le64 keys[0]; |
| 42 | } __packed; | 42 | } __packed; |
| 43 | 43 | ||
| 44 | 44 | ||
| 45 | void inc_children(struct dm_transaction_manager *tm, struct node *n, | 45 | void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, |
| 46 | struct dm_btree_value_type *vt); | 46 | struct dm_btree_value_type *vt); |
| 47 | 47 | ||
| 48 | int new_block(struct dm_btree_info *info, struct dm_block **result); | 48 | int new_block(struct dm_btree_info *info, struct dm_block **result); |
| @@ -64,7 +64,7 @@ struct ro_spine { | |||
| 64 | void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info); | 64 | void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info); |
| 65 | int exit_ro_spine(struct ro_spine *s); | 65 | int exit_ro_spine(struct ro_spine *s); |
| 66 | int ro_step(struct ro_spine *s, dm_block_t new_child); | 66 | int ro_step(struct ro_spine *s, dm_block_t new_child); |
| 67 | struct node *ro_node(struct ro_spine *s); | 67 | struct btree_node *ro_node(struct ro_spine *s); |
| 68 | 68 | ||
| 69 | struct shadow_spine { | 69 | struct shadow_spine { |
| 70 | struct dm_btree_info *info; | 70 | struct dm_btree_info *info; |
| @@ -98,17 +98,17 @@ int shadow_root(struct shadow_spine *s); | |||
| 98 | /* | 98 | /* |
| 99 | * Some inlines. | 99 | * Some inlines. |
| 100 | */ | 100 | */ |
| 101 | static inline __le64 *key_ptr(struct node *n, uint32_t index) | 101 | static inline __le64 *key_ptr(struct btree_node *n, uint32_t index) |
| 102 | { | 102 | { |
| 103 | return n->keys + index; | 103 | return n->keys + index; |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | static inline void *value_base(struct node *n) | 106 | static inline void *value_base(struct btree_node *n) |
| 107 | { | 107 | { |
| 108 | return &n->keys[le32_to_cpu(n->header.max_entries)]; | 108 | return &n->keys[le32_to_cpu(n->header.max_entries)]; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | static inline void *value_ptr(struct node *n, uint32_t index) | 111 | static inline void *value_ptr(struct btree_node *n, uint32_t index) |
| 112 | { | 112 | { |
| 113 | uint32_t value_size = le32_to_cpu(n->header.value_size); | 113 | uint32_t value_size = le32_to_cpu(n->header.value_size); |
| 114 | return value_base(n) + (value_size * index); | 114 | return value_base(n) + (value_size * index); |
| @@ -117,7 +117,7 @@ static inline void *value_ptr(struct node *n, uint32_t index) | |||
| 117 | /* | 117 | /* |
| 118 | * Assumes the values are suitably-aligned and converts to core format. | 118 | * Assumes the values are suitably-aligned and converts to core format. |
| 119 | */ | 119 | */ |
| 120 | static inline uint64_t value64(struct node *n, uint32_t index) | 120 | static inline uint64_t value64(struct btree_node *n, uint32_t index) |
| 121 | { | 121 | { |
| 122 | __le64 *values_le = value_base(n); | 122 | __le64 *values_le = value_base(n); |
| 123 | 123 | ||
| @@ -127,7 +127,7 @@ static inline uint64_t value64(struct node *n, uint32_t index) | |||
| 127 | /* | 127 | /* |
| 128 | * Searching for a key within a single node. | 128 | * Searching for a key within a single node. |
| 129 | */ | 129 | */ |
| 130 | int lower_bound(struct node *n, uint64_t key); | 130 | int lower_bound(struct btree_node *n, uint64_t key); |
| 131 | 131 | ||
| 132 | extern struct dm_block_validator btree_node_validator; | 132 | extern struct dm_block_validator btree_node_validator; |
| 133 | 133 | ||
diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c index aa71e2359a07..c4f28133ef82 100644 --- a/drivers/md/persistent-data/dm-btree-remove.c +++ b/drivers/md/persistent-data/dm-btree-remove.c | |||
| @@ -53,7 +53,7 @@ | |||
| 53 | /* | 53 | /* |
| 54 | * Some little utilities for moving node data around. | 54 | * Some little utilities for moving node data around. |
| 55 | */ | 55 | */ |
| 56 | static void node_shift(struct node *n, int shift) | 56 | static void node_shift(struct btree_node *n, int shift) |
| 57 | { | 57 | { |
| 58 | uint32_t nr_entries = le32_to_cpu(n->header.nr_entries); | 58 | uint32_t nr_entries = le32_to_cpu(n->header.nr_entries); |
| 59 | uint32_t value_size = le32_to_cpu(n->header.value_size); | 59 | uint32_t value_size = le32_to_cpu(n->header.value_size); |
| @@ -79,7 +79,7 @@ static void node_shift(struct node *n, int shift) | |||
| 79 | } | 79 | } |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | static void node_copy(struct node *left, struct node *right, int shift) | 82 | static void node_copy(struct btree_node *left, struct btree_node *right, int shift) |
| 83 | { | 83 | { |
| 84 | uint32_t nr_left = le32_to_cpu(left->header.nr_entries); | 84 | uint32_t nr_left = le32_to_cpu(left->header.nr_entries); |
| 85 | uint32_t value_size = le32_to_cpu(left->header.value_size); | 85 | uint32_t value_size = le32_to_cpu(left->header.value_size); |
| @@ -108,7 +108,7 @@ static void node_copy(struct node *left, struct node *right, int shift) | |||
| 108 | /* | 108 | /* |
| 109 | * Delete a specific entry from a leaf node. | 109 | * Delete a specific entry from a leaf node. |
| 110 | */ | 110 | */ |
| 111 | static void delete_at(struct node *n, unsigned index) | 111 | static void delete_at(struct btree_node *n, unsigned index) |
| 112 | { | 112 | { |
| 113 | unsigned nr_entries = le32_to_cpu(n->header.nr_entries); | 113 | unsigned nr_entries = le32_to_cpu(n->header.nr_entries); |
| 114 | unsigned nr_to_copy = nr_entries - (index + 1); | 114 | unsigned nr_to_copy = nr_entries - (index + 1); |
| @@ -128,7 +128,7 @@ static void delete_at(struct node *n, unsigned index) | |||
| 128 | n->header.nr_entries = cpu_to_le32(nr_entries - 1); | 128 | n->header.nr_entries = cpu_to_le32(nr_entries - 1); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | static unsigned merge_threshold(struct node *n) | 131 | static unsigned merge_threshold(struct btree_node *n) |
| 132 | { | 132 | { |
| 133 | return le32_to_cpu(n->header.max_entries) / 3; | 133 | return le32_to_cpu(n->header.max_entries) / 3; |
| 134 | } | 134 | } |
| @@ -136,7 +136,7 @@ static unsigned merge_threshold(struct node *n) | |||
| 136 | struct child { | 136 | struct child { |
| 137 | unsigned index; | 137 | unsigned index; |
| 138 | struct dm_block *block; | 138 | struct dm_block *block; |
| 139 | struct node *n; | 139 | struct btree_node *n; |
| 140 | }; | 140 | }; |
| 141 | 141 | ||
| 142 | static struct dm_btree_value_type le64_type = { | 142 | static struct dm_btree_value_type le64_type = { |
| @@ -147,7 +147,7 @@ static struct dm_btree_value_type le64_type = { | |||
| 147 | .equal = NULL | 147 | .equal = NULL |
| 148 | }; | 148 | }; |
| 149 | 149 | ||
| 150 | static int init_child(struct dm_btree_info *info, struct node *parent, | 150 | static int init_child(struct dm_btree_info *info, struct btree_node *parent, |
| 151 | unsigned index, struct child *result) | 151 | unsigned index, struct child *result) |
| 152 | { | 152 | { |
| 153 | int r, inc; | 153 | int r, inc; |
| @@ -177,7 +177,7 @@ static int exit_child(struct dm_btree_info *info, struct child *c) | |||
| 177 | return dm_tm_unlock(info->tm, c->block); | 177 | return dm_tm_unlock(info->tm, c->block); |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | static void shift(struct node *left, struct node *right, int count) | 180 | static void shift(struct btree_node *left, struct btree_node *right, int count) |
| 181 | { | 181 | { |
| 182 | uint32_t nr_left = le32_to_cpu(left->header.nr_entries); | 182 | uint32_t nr_left = le32_to_cpu(left->header.nr_entries); |
| 183 | uint32_t nr_right = le32_to_cpu(right->header.nr_entries); | 183 | uint32_t nr_right = le32_to_cpu(right->header.nr_entries); |
| @@ -203,11 +203,11 @@ static void shift(struct node *left, struct node *right, int count) | |||
| 203 | right->header.nr_entries = cpu_to_le32(nr_right + count); | 203 | right->header.nr_entries = cpu_to_le32(nr_right + count); |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | static void __rebalance2(struct dm_btree_info *info, struct node *parent, | 206 | static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent, |
| 207 | struct child *l, struct child *r) | 207 | struct child *l, struct child *r) |
| 208 | { | 208 | { |
| 209 | struct node *left = l->n; | 209 | struct btree_node *left = l->n; |
| 210 | struct node *right = r->n; | 210 | struct btree_node *right = r->n; |
| 211 | uint32_t nr_left = le32_to_cpu(left->header.nr_entries); | 211 | uint32_t nr_left = le32_to_cpu(left->header.nr_entries); |
| 212 | uint32_t nr_right = le32_to_cpu(right->header.nr_entries); | 212 | uint32_t nr_right = le32_to_cpu(right->header.nr_entries); |
| 213 | unsigned threshold = 2 * merge_threshold(left) + 1; | 213 | unsigned threshold = 2 * merge_threshold(left) + 1; |
| @@ -239,7 +239,7 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, | |||
| 239 | unsigned left_index) | 239 | unsigned left_index) |
| 240 | { | 240 | { |
| 241 | int r; | 241 | int r; |
| 242 | struct node *parent; | 242 | struct btree_node *parent; |
| 243 | struct child left, right; | 243 | struct child left, right; |
| 244 | 244 | ||
| 245 | parent = dm_block_data(shadow_current(s)); | 245 | parent = dm_block_data(shadow_current(s)); |
| @@ -270,9 +270,9 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, | |||
| 270 | * in right, then rebalance2. This wastes some cpu, but I want something | 270 | * in right, then rebalance2. This wastes some cpu, but I want something |
| 271 | * simple atm. | 271 | * simple atm. |
| 272 | */ | 272 | */ |
| 273 | static void delete_center_node(struct dm_btree_info *info, struct node *parent, | 273 | static void delete_center_node(struct dm_btree_info *info, struct btree_node *parent, |
| 274 | struct child *l, struct child *c, struct child *r, | 274 | struct child *l, struct child *c, struct child *r, |
| 275 | struct node *left, struct node *center, struct node *right, | 275 | struct btree_node *left, struct btree_node *center, struct btree_node *right, |
| 276 | uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) | 276 | uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) |
| 277 | { | 277 | { |
| 278 | uint32_t max_entries = le32_to_cpu(left->header.max_entries); | 278 | uint32_t max_entries = le32_to_cpu(left->header.max_entries); |
| @@ -301,9 +301,9 @@ static void delete_center_node(struct dm_btree_info *info, struct node *parent, | |||
| 301 | /* | 301 | /* |
| 302 | * Redistributes entries among 3 sibling nodes. | 302 | * Redistributes entries among 3 sibling nodes. |
| 303 | */ | 303 | */ |
| 304 | static void redistribute3(struct dm_btree_info *info, struct node *parent, | 304 | static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, |
| 305 | struct child *l, struct child *c, struct child *r, | 305 | struct child *l, struct child *c, struct child *r, |
| 306 | struct node *left, struct node *center, struct node *right, | 306 | struct btree_node *left, struct btree_node *center, struct btree_node *right, |
| 307 | uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) | 307 | uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) |
| 308 | { | 308 | { |
| 309 | int s; | 309 | int s; |
| @@ -343,12 +343,12 @@ static void redistribute3(struct dm_btree_info *info, struct node *parent, | |||
| 343 | *key_ptr(parent, r->index) = right->keys[0]; | 343 | *key_ptr(parent, r->index) = right->keys[0]; |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | static void __rebalance3(struct dm_btree_info *info, struct node *parent, | 346 | static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent, |
| 347 | struct child *l, struct child *c, struct child *r) | 347 | struct child *l, struct child *c, struct child *r) |
| 348 | { | 348 | { |
| 349 | struct node *left = l->n; | 349 | struct btree_node *left = l->n; |
| 350 | struct node *center = c->n; | 350 | struct btree_node *center = c->n; |
| 351 | struct node *right = r->n; | 351 | struct btree_node *right = r->n; |
| 352 | 352 | ||
| 353 | uint32_t nr_left = le32_to_cpu(left->header.nr_entries); | 353 | uint32_t nr_left = le32_to_cpu(left->header.nr_entries); |
| 354 | uint32_t nr_center = le32_to_cpu(center->header.nr_entries); | 354 | uint32_t nr_center = le32_to_cpu(center->header.nr_entries); |
| @@ -371,7 +371,7 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info, | |||
| 371 | unsigned left_index) | 371 | unsigned left_index) |
| 372 | { | 372 | { |
| 373 | int r; | 373 | int r; |
| 374 | struct node *parent = dm_block_data(shadow_current(s)); | 374 | struct btree_node *parent = dm_block_data(shadow_current(s)); |
| 375 | struct child left, center, right; | 375 | struct child left, center, right; |
| 376 | 376 | ||
| 377 | /* | 377 | /* |
| @@ -421,7 +421,7 @@ static int get_nr_entries(struct dm_transaction_manager *tm, | |||
| 421 | { | 421 | { |
| 422 | int r; | 422 | int r; |
| 423 | struct dm_block *block; | 423 | struct dm_block *block; |
| 424 | struct node *n; | 424 | struct btree_node *n; |
| 425 | 425 | ||
| 426 | r = dm_tm_read_lock(tm, b, &btree_node_validator, &block); | 426 | r = dm_tm_read_lock(tm, b, &btree_node_validator, &block); |
| 427 | if (r) | 427 | if (r) |
| @@ -438,7 +438,7 @@ static int rebalance_children(struct shadow_spine *s, | |||
| 438 | { | 438 | { |
| 439 | int i, r, has_left_sibling, has_right_sibling; | 439 | int i, r, has_left_sibling, has_right_sibling; |
| 440 | uint32_t child_entries; | 440 | uint32_t child_entries; |
| 441 | struct node *n; | 441 | struct btree_node *n; |
| 442 | 442 | ||
| 443 | n = dm_block_data(shadow_current(s)); | 443 | n = dm_block_data(shadow_current(s)); |
| 444 | 444 | ||
| @@ -483,7 +483,7 @@ static int rebalance_children(struct shadow_spine *s, | |||
| 483 | return r; | 483 | return r; |
| 484 | } | 484 | } |
| 485 | 485 | ||
| 486 | static int do_leaf(struct node *n, uint64_t key, unsigned *index) | 486 | static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index) |
| 487 | { | 487 | { |
| 488 | int i = lower_bound(n, key); | 488 | int i = lower_bound(n, key); |
| 489 | 489 | ||
| @@ -506,7 +506,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info, | |||
| 506 | uint64_t key, unsigned *index) | 506 | uint64_t key, unsigned *index) |
| 507 | { | 507 | { |
| 508 | int i = *index, r; | 508 | int i = *index, r; |
| 509 | struct node *n; | 509 | struct btree_node *n; |
| 510 | 510 | ||
| 511 | for (;;) { | 511 | for (;;) { |
| 512 | r = shadow_step(s, root, vt); | 512 | r = shadow_step(s, root, vt); |
| @@ -556,7 +556,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root, | |||
| 556 | unsigned level, last_level = info->levels - 1; | 556 | unsigned level, last_level = info->levels - 1; |
| 557 | int index = 0, r = 0; | 557 | int index = 0, r = 0; |
| 558 | struct shadow_spine spine; | 558 | struct shadow_spine spine; |
| 559 | struct node *n; | 559 | struct btree_node *n; |
| 560 | 560 | ||
| 561 | init_shadow_spine(&spine, info); | 561 | init_shadow_spine(&spine, info); |
| 562 | for (level = 0; level < info->levels; level++) { | 562 | for (level = 0; level < info->levels; level++) { |
diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c index d9a7912ee8ee..f199a0c4ed04 100644 --- a/drivers/md/persistent-data/dm-btree-spine.c +++ b/drivers/md/persistent-data/dm-btree-spine.c | |||
| @@ -23,7 +23,7 @@ static void node_prepare_for_write(struct dm_block_validator *v, | |||
| 23 | struct dm_block *b, | 23 | struct dm_block *b, |
| 24 | size_t block_size) | 24 | size_t block_size) |
| 25 | { | 25 | { |
| 26 | struct node *n = dm_block_data(b); | 26 | struct btree_node *n = dm_block_data(b); |
| 27 | struct node_header *h = &n->header; | 27 | struct node_header *h = &n->header; |
| 28 | 28 | ||
| 29 | h->blocknr = cpu_to_le64(dm_block_location(b)); | 29 | h->blocknr = cpu_to_le64(dm_block_location(b)); |
| @@ -38,15 +38,15 @@ static int node_check(struct dm_block_validator *v, | |||
| 38 | struct dm_block *b, | 38 | struct dm_block *b, |
| 39 | size_t block_size) | 39 | size_t block_size) |
| 40 | { | 40 | { |
| 41 | struct node *n = dm_block_data(b); | 41 | struct btree_node *n = dm_block_data(b); |
| 42 | struct node_header *h = &n->header; | 42 | struct node_header *h = &n->header; |
| 43 | size_t value_size; | 43 | size_t value_size; |
| 44 | __le32 csum_disk; | 44 | __le32 csum_disk; |
| 45 | uint32_t flags; | 45 | uint32_t flags; |
| 46 | 46 | ||
| 47 | if (dm_block_location(b) != le64_to_cpu(h->blocknr)) { | 47 | if (dm_block_location(b) != le64_to_cpu(h->blocknr)) { |
| 48 | DMERR("node_check failed blocknr %llu wanted %llu", | 48 | DMERR_LIMIT("node_check failed: blocknr %llu != wanted %llu", |
| 49 | le64_to_cpu(h->blocknr), dm_block_location(b)); | 49 | le64_to_cpu(h->blocknr), dm_block_location(b)); |
| 50 | return -ENOTBLK; | 50 | return -ENOTBLK; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| @@ -54,8 +54,8 @@ static int node_check(struct dm_block_validator *v, | |||
| 54 | block_size - sizeof(__le32), | 54 | block_size - sizeof(__le32), |
| 55 | BTREE_CSUM_XOR)); | 55 | BTREE_CSUM_XOR)); |
| 56 | if (csum_disk != h->csum) { | 56 | if (csum_disk != h->csum) { |
| 57 | DMERR("node_check failed csum %u wanted %u", | 57 | DMERR_LIMIT("node_check failed: csum %u != wanted %u", |
| 58 | le32_to_cpu(csum_disk), le32_to_cpu(h->csum)); | 58 | le32_to_cpu(csum_disk), le32_to_cpu(h->csum)); |
| 59 | return -EILSEQ; | 59 | return -EILSEQ; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| @@ -63,12 +63,12 @@ static int node_check(struct dm_block_validator *v, | |||
| 63 | 63 | ||
| 64 | if (sizeof(struct node_header) + | 64 | if (sizeof(struct node_header) + |
| 65 | (sizeof(__le64) + value_size) * le32_to_cpu(h->max_entries) > block_size) { | 65 | (sizeof(__le64) + value_size) * le32_to_cpu(h->max_entries) > block_size) { |
| 66 | DMERR("node_check failed: max_entries too large"); | 66 | DMERR_LIMIT("node_check failed: max_entries too large"); |
| 67 | return -EILSEQ; | 67 | return -EILSEQ; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | if (le32_to_cpu(h->nr_entries) > le32_to_cpu(h->max_entries)) { | 70 | if (le32_to_cpu(h->nr_entries) > le32_to_cpu(h->max_entries)) { |
| 71 | DMERR("node_check failed, too many entries"); | 71 | DMERR_LIMIT("node_check failed: too many entries"); |
| 72 | return -EILSEQ; | 72 | return -EILSEQ; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| @@ -77,7 +77,7 @@ static int node_check(struct dm_block_validator *v, | |||
| 77 | */ | 77 | */ |
| 78 | flags = le32_to_cpu(h->flags); | 78 | flags = le32_to_cpu(h->flags); |
| 79 | if (!(flags & INTERNAL_NODE) && !(flags & LEAF_NODE)) { | 79 | if (!(flags & INTERNAL_NODE) && !(flags & LEAF_NODE)) { |
| 80 | DMERR("node_check failed, node is neither INTERNAL or LEAF"); | 80 | DMERR_LIMIT("node_check failed: node is neither INTERNAL or LEAF"); |
| 81 | return -EILSEQ; | 81 | return -EILSEQ; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| @@ -164,7 +164,7 @@ int ro_step(struct ro_spine *s, dm_block_t new_child) | |||
| 164 | return r; | 164 | return r; |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | struct node *ro_node(struct ro_spine *s) | 167 | struct btree_node *ro_node(struct ro_spine *s) |
| 168 | { | 168 | { |
| 169 | struct dm_block *block; | 169 | struct dm_block *block; |
| 170 | 170 | ||
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c index d12b2cc51f1a..4caf66918cdb 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c | |||
| @@ -38,7 +38,7 @@ static void array_insert(void *base, size_t elt_size, unsigned nr_elts, | |||
| 38 | /*----------------------------------------------------------------*/ | 38 | /*----------------------------------------------------------------*/ |
| 39 | 39 | ||
| 40 | /* makes the assumption that no two keys are the same. */ | 40 | /* makes the assumption that no two keys are the same. */ |
| 41 | static int bsearch(struct node *n, uint64_t key, int want_hi) | 41 | static int bsearch(struct btree_node *n, uint64_t key, int want_hi) |
| 42 | { | 42 | { |
| 43 | int lo = -1, hi = le32_to_cpu(n->header.nr_entries); | 43 | int lo = -1, hi = le32_to_cpu(n->header.nr_entries); |
| 44 | 44 | ||
| @@ -58,12 +58,12 @@ static int bsearch(struct node *n, uint64_t key, int want_hi) | |||
| 58 | return want_hi ? hi : lo; | 58 | return want_hi ? hi : lo; |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | int lower_bound(struct node *n, uint64_t key) | 61 | int lower_bound(struct btree_node *n, uint64_t key) |
| 62 | { | 62 | { |
| 63 | return bsearch(n, key, 0); | 63 | return bsearch(n, key, 0); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | void inc_children(struct dm_transaction_manager *tm, struct node *n, | 66 | void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, |
| 67 | struct dm_btree_value_type *vt) | 67 | struct dm_btree_value_type *vt) |
| 68 | { | 68 | { |
| 69 | unsigned i; | 69 | unsigned i; |
| @@ -77,7 +77,7 @@ void inc_children(struct dm_transaction_manager *tm, struct node *n, | |||
| 77 | vt->inc(vt->context, value_ptr(n, i)); | 77 | vt->inc(vt->context, value_ptr(n, i)); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | static int insert_at(size_t value_size, struct node *node, unsigned index, | 80 | static int insert_at(size_t value_size, struct btree_node *node, unsigned index, |
| 81 | uint64_t key, void *value) | 81 | uint64_t key, void *value) |
| 82 | __dm_written_to_disk(value) | 82 | __dm_written_to_disk(value) |
| 83 | { | 83 | { |
| @@ -122,7 +122,7 @@ int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root) | |||
| 122 | { | 122 | { |
| 123 | int r; | 123 | int r; |
| 124 | struct dm_block *b; | 124 | struct dm_block *b; |
| 125 | struct node *n; | 125 | struct btree_node *n; |
| 126 | size_t block_size; | 126 | size_t block_size; |
| 127 | uint32_t max_entries; | 127 | uint32_t max_entries; |
| 128 | 128 | ||
| @@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(dm_btree_empty); | |||
| 154 | #define MAX_SPINE_DEPTH 64 | 154 | #define MAX_SPINE_DEPTH 64 |
| 155 | struct frame { | 155 | struct frame { |
| 156 | struct dm_block *b; | 156 | struct dm_block *b; |
| 157 | struct node *n; | 157 | struct btree_node *n; |
| 158 | unsigned level; | 158 | unsigned level; |
| 159 | unsigned nr_children; | 159 | unsigned nr_children; |
| 160 | unsigned current_child; | 160 | unsigned current_child; |
| @@ -230,6 +230,11 @@ static void pop_frame(struct del_stack *s) | |||
| 230 | dm_tm_unlock(s->tm, f->b); | 230 | dm_tm_unlock(s->tm, f->b); |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | static bool is_internal_level(struct dm_btree_info *info, struct frame *f) | ||
| 234 | { | ||
| 235 | return f->level < (info->levels - 1); | ||
| 236 | } | ||
| 237 | |||
| 233 | int dm_btree_del(struct dm_btree_info *info, dm_block_t root) | 238 | int dm_btree_del(struct dm_btree_info *info, dm_block_t root) |
| 234 | { | 239 | { |
| 235 | int r; | 240 | int r; |
| @@ -241,7 +246,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root) | |||
| 241 | s->tm = info->tm; | 246 | s->tm = info->tm; |
| 242 | s->top = -1; | 247 | s->top = -1; |
| 243 | 248 | ||
| 244 | r = push_frame(s, root, 1); | 249 | r = push_frame(s, root, 0); |
| 245 | if (r) | 250 | if (r) |
| 246 | goto out; | 251 | goto out; |
| 247 | 252 | ||
| @@ -267,7 +272,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root) | |||
| 267 | if (r) | 272 | if (r) |
| 268 | goto out; | 273 | goto out; |
| 269 | 274 | ||
| 270 | } else if (f->level != (info->levels - 1)) { | 275 | } else if (is_internal_level(info, f)) { |
| 271 | b = value64(f->n, f->current_child); | 276 | b = value64(f->n, f->current_child); |
| 272 | f->current_child++; | 277 | f->current_child++; |
| 273 | r = push_frame(s, b, f->level + 1); | 278 | r = push_frame(s, b, f->level + 1); |
| @@ -295,7 +300,7 @@ EXPORT_SYMBOL_GPL(dm_btree_del); | |||
| 295 | /*----------------------------------------------------------------*/ | 300 | /*----------------------------------------------------------------*/ |
| 296 | 301 | ||
| 297 | static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key, | 302 | static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key, |
| 298 | int (*search_fn)(struct node *, uint64_t), | 303 | int (*search_fn)(struct btree_node *, uint64_t), |
| 299 | uint64_t *result_key, void *v, size_t value_size) | 304 | uint64_t *result_key, void *v, size_t value_size) |
| 300 | { | 305 | { |
| 301 | int i, r; | 306 | int i, r; |
| @@ -406,7 +411,7 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root, | |||
| 406 | size_t size; | 411 | size_t size; |
| 407 | unsigned nr_left, nr_right; | 412 | unsigned nr_left, nr_right; |
| 408 | struct dm_block *left, *right, *parent; | 413 | struct dm_block *left, *right, *parent; |
| 409 | struct node *ln, *rn, *pn; | 414 | struct btree_node *ln, *rn, *pn; |
| 410 | __le64 location; | 415 | __le64 location; |
| 411 | 416 | ||
| 412 | left = shadow_current(s); | 417 | left = shadow_current(s); |
| @@ -491,7 +496,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key) | |||
| 491 | size_t size; | 496 | size_t size; |
| 492 | unsigned nr_left, nr_right; | 497 | unsigned nr_left, nr_right; |
| 493 | struct dm_block *left, *right, *new_parent; | 498 | struct dm_block *left, *right, *new_parent; |
| 494 | struct node *pn, *ln, *rn; | 499 | struct btree_node *pn, *ln, *rn; |
| 495 | __le64 val; | 500 | __le64 val; |
| 496 | 501 | ||
| 497 | new_parent = shadow_current(s); | 502 | new_parent = shadow_current(s); |
| @@ -576,7 +581,7 @@ static int btree_insert_raw(struct shadow_spine *s, dm_block_t root, | |||
| 576 | uint64_t key, unsigned *index) | 581 | uint64_t key, unsigned *index) |
| 577 | { | 582 | { |
| 578 | int r, i = *index, top = 1; | 583 | int r, i = *index, top = 1; |
| 579 | struct node *node; | 584 | struct btree_node *node; |
| 580 | 585 | ||
| 581 | for (;;) { | 586 | for (;;) { |
| 582 | r = shadow_step(s, root, vt); | 587 | r = shadow_step(s, root, vt); |
| @@ -643,7 +648,7 @@ static int insert(struct dm_btree_info *info, dm_block_t root, | |||
| 643 | unsigned level, index = -1, last_level = info->levels - 1; | 648 | unsigned level, index = -1, last_level = info->levels - 1; |
| 644 | dm_block_t block = root; | 649 | dm_block_t block = root; |
| 645 | struct shadow_spine spine; | 650 | struct shadow_spine spine; |
| 646 | struct node *n; | 651 | struct btree_node *n; |
| 647 | struct dm_btree_value_type le64_type; | 652 | struct dm_btree_value_type le64_type; |
| 648 | 653 | ||
| 649 | le64_type.context = NULL; | 654 | le64_type.context = NULL; |
diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c index f3a9af8cdec3..3e7a88d99eb0 100644 --- a/drivers/md/persistent-data/dm-space-map-common.c +++ b/drivers/md/persistent-data/dm-space-map-common.c | |||
| @@ -39,8 +39,8 @@ static int index_check(struct dm_block_validator *v, | |||
| 39 | __le32 csum_disk; | 39 | __le32 csum_disk; |
| 40 | 40 | ||
| 41 | if (dm_block_location(b) != le64_to_cpu(mi_le->blocknr)) { | 41 | if (dm_block_location(b) != le64_to_cpu(mi_le->blocknr)) { |
| 42 | DMERR("index_check failed blocknr %llu wanted %llu", | 42 | DMERR_LIMIT("index_check failed: blocknr %llu != wanted %llu", |
| 43 | le64_to_cpu(mi_le->blocknr), dm_block_location(b)); | 43 | le64_to_cpu(mi_le->blocknr), dm_block_location(b)); |
| 44 | return -ENOTBLK; | 44 | return -ENOTBLK; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| @@ -48,8 +48,8 @@ static int index_check(struct dm_block_validator *v, | |||
| 48 | block_size - sizeof(__le32), | 48 | block_size - sizeof(__le32), |
| 49 | INDEX_CSUM_XOR)); | 49 | INDEX_CSUM_XOR)); |
| 50 | if (csum_disk != mi_le->csum) { | 50 | if (csum_disk != mi_le->csum) { |
| 51 | DMERR("index_check failed csum %u wanted %u", | 51 | DMERR_LIMIT("index_check failed: csum %u != wanted %u", |
| 52 | le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum)); | 52 | le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum)); |
| 53 | return -EILSEQ; | 53 | return -EILSEQ; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| @@ -89,8 +89,8 @@ static int bitmap_check(struct dm_block_validator *v, | |||
| 89 | __le32 csum_disk; | 89 | __le32 csum_disk; |
| 90 | 90 | ||
| 91 | if (dm_block_location(b) != le64_to_cpu(disk_header->blocknr)) { | 91 | if (dm_block_location(b) != le64_to_cpu(disk_header->blocknr)) { |
| 92 | DMERR("bitmap check failed blocknr %llu wanted %llu", | 92 | DMERR_LIMIT("bitmap check failed: blocknr %llu != wanted %llu", |
| 93 | le64_to_cpu(disk_header->blocknr), dm_block_location(b)); | 93 | le64_to_cpu(disk_header->blocknr), dm_block_location(b)); |
| 94 | return -ENOTBLK; | 94 | return -ENOTBLK; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| @@ -98,8 +98,8 @@ static int bitmap_check(struct dm_block_validator *v, | |||
| 98 | block_size - sizeof(__le32), | 98 | block_size - sizeof(__le32), |
| 99 | BITMAP_CSUM_XOR)); | 99 | BITMAP_CSUM_XOR)); |
| 100 | if (csum_disk != disk_header->csum) { | 100 | if (csum_disk != disk_header->csum) { |
| 101 | DMERR("bitmap check failed csum %u wanted %u", | 101 | DMERR_LIMIT("bitmap check failed: csum %u != wanted %u", |
| 102 | le32_to_cpu(csum_disk), le32_to_cpu(disk_header->csum)); | 102 | le32_to_cpu(csum_disk), le32_to_cpu(disk_header->csum)); |
| 103 | return -EILSEQ; | 103 | return -EILSEQ; |
| 104 | } | 104 | } |
| 105 | 105 | ||
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index e89ae5e7a519..906cf3df71af 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c | |||
| @@ -337,7 +337,7 @@ static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b) | |||
| 337 | { | 337 | { |
| 338 | int r = sm_metadata_new_block_(sm, b); | 338 | int r = sm_metadata_new_block_(sm, b); |
| 339 | if (r) | 339 | if (r) |
| 340 | DMERR("out of metadata space"); | 340 | DMERR("unable to allocate new metadata block"); |
| 341 | return r; | 341 | return r; |
| 342 | } | 342 | } |
| 343 | 343 | ||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 770a0d01e0b9..05164d7f054b 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
| 26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
| 27 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
| 28 | #include <plat/cpu.h> | ||
| 29 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
| 30 | #include <linux/platform_data/usb-omap.h> | 29 | #include <linux/platform_data/usb-omap.h> |
| 31 | #include <linux/pm_runtime.h> | 30 | #include <linux/pm_runtime.h> |
| @@ -384,7 +383,7 @@ static void omap_usbhs_init(struct device *dev) | |||
| 384 | reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; | 383 | reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; |
| 385 | 384 | ||
| 386 | /* Bypass the TLL module for PHY mode operation */ | 385 | /* Bypass the TLL module for PHY mode operation */ |
| 387 | if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { | 386 | if (pdata->single_ulpi_bypass) { |
| 388 | dev_dbg(dev, "OMAP3 ES version <= ES2.1\n"); | 387 | dev_dbg(dev, "OMAP3 ES version <= ES2.1\n"); |
| 389 | if (is_ehci_phy_mode(pdata->port_mode[0]) || | 388 | if (is_ehci_phy_mode(pdata->port_mode[0]) || |
| 390 | is_ehci_phy_mode(pdata->port_mode[1]) || | 389 | is_ehci_phy_mode(pdata->port_mode[1]) || |
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 8d082b46426b..d971817182f7 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c | |||
| @@ -53,6 +53,10 @@ | |||
| 53 | #include <linux/kthread.h> | 53 | #include <linux/kthread.h> |
| 54 | #include "xpc.h" | 54 | #include "xpc.h" |
| 55 | 55 | ||
| 56 | #ifdef CONFIG_X86_64 | ||
| 57 | #include <asm/traps.h> | ||
| 58 | #endif | ||
| 59 | |||
| 56 | /* define two XPC debug device structures to be used with dev_dbg() et al */ | 60 | /* define two XPC debug device structures to be used with dev_dbg() et al */ |
| 57 | 61 | ||
| 58 | struct device_driver xpc_dbg_name = { | 62 | struct device_driver xpc_dbg_name = { |
| @@ -1079,6 +1083,9 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) | |||
| 1079 | return NOTIFY_DONE; | 1083 | return NOTIFY_DONE; |
| 1080 | } | 1084 | } |
| 1081 | 1085 | ||
| 1086 | /* Used to only allow one cpu to complete disconnect */ | ||
| 1087 | static unsigned int xpc_die_disconnecting; | ||
| 1088 | |||
| 1082 | /* | 1089 | /* |
| 1083 | * Notify other partitions to deactivate from us by first disengaging from all | 1090 | * Notify other partitions to deactivate from us by first disengaging from all |
| 1084 | * references to our memory. | 1091 | * references to our memory. |
| @@ -1092,6 +1099,9 @@ xpc_die_deactivate(void) | |||
| 1092 | long keep_waiting; | 1099 | long keep_waiting; |
| 1093 | long wait_to_print; | 1100 | long wait_to_print; |
| 1094 | 1101 | ||
| 1102 | if (cmpxchg(&xpc_die_disconnecting, 0, 1)) | ||
| 1103 | return; | ||
| 1104 | |||
| 1095 | /* keep xpc_hb_checker thread from doing anything (just in case) */ | 1105 | /* keep xpc_hb_checker thread from doing anything (just in case) */ |
| 1096 | xpc_exiting = 1; | 1106 | xpc_exiting = 1; |
| 1097 | 1107 | ||
| @@ -1159,7 +1169,7 @@ xpc_die_deactivate(void) | |||
| 1159 | * about the lack of a heartbeat. | 1169 | * about the lack of a heartbeat. |
| 1160 | */ | 1170 | */ |
| 1161 | static int | 1171 | static int |
| 1162 | xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | 1172 | xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args) |
| 1163 | { | 1173 | { |
| 1164 | #ifdef CONFIG_IA64 /* !!! temporary kludge */ | 1174 | #ifdef CONFIG_IA64 /* !!! temporary kludge */ |
| 1165 | switch (event) { | 1175 | switch (event) { |
| @@ -1191,7 +1201,27 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) | |||
| 1191 | break; | 1201 | break; |
| 1192 | } | 1202 | } |
| 1193 | #else | 1203 | #else |
| 1194 | xpc_die_deactivate(); | 1204 | struct die_args *die_args = _die_args; |
| 1205 | |||
| 1206 | switch (event) { | ||
| 1207 | case DIE_TRAP: | ||
| 1208 | if (die_args->trapnr == X86_TRAP_DF) | ||
| 1209 | xpc_die_deactivate(); | ||
| 1210 | |||
| 1211 | if (((die_args->trapnr == X86_TRAP_MF) || | ||
| 1212 | (die_args->trapnr == X86_TRAP_XF)) && | ||
| 1213 | !user_mode_vm(die_args->regs)) | ||
| 1214 | xpc_die_deactivate(); | ||
| 1215 | |||
| 1216 | break; | ||
| 1217 | case DIE_INT3: | ||
| 1218 | case DIE_DEBUG: | ||
| 1219 | break; | ||
| 1220 | case DIE_OOPS: | ||
| 1221 | case DIE_GPF: | ||
| 1222 | default: | ||
| 1223 | xpc_die_deactivate(); | ||
| 1224 | } | ||
| 1195 | #endif | 1225 | #endif |
| 1196 | 1226 | ||
| 1197 | return NOTIFY_DONE; | 1227 | return NOTIFY_DONE; |
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c index fec406b4553d..c071d410488f 100644 --- a/drivers/mtd/ubi/attach.c +++ b/drivers/mtd/ubi/attach.c | |||
| @@ -322,7 +322,6 @@ static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai, | |||
| 322 | int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, | 322 | int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, |
| 323 | int pnum, const struct ubi_vid_hdr *vid_hdr) | 323 | int pnum, const struct ubi_vid_hdr *vid_hdr) |
| 324 | { | 324 | { |
| 325 | void *buf; | ||
| 326 | int len, err, second_is_newer, bitflips = 0, corrupted = 0; | 325 | int len, err, second_is_newer, bitflips = 0, corrupted = 0; |
| 327 | uint32_t data_crc, crc; | 326 | uint32_t data_crc, crc; |
| 328 | struct ubi_vid_hdr *vh = NULL; | 327 | struct ubi_vid_hdr *vh = NULL; |
| @@ -393,18 +392,14 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, | |||
| 393 | /* Read the data of the copy and check the CRC */ | 392 | /* Read the data of the copy and check the CRC */ |
| 394 | 393 | ||
| 395 | len = be32_to_cpu(vid_hdr->data_size); | 394 | len = be32_to_cpu(vid_hdr->data_size); |
| 396 | buf = vmalloc(len); | ||
| 397 | if (!buf) { | ||
| 398 | err = -ENOMEM; | ||
| 399 | goto out_free_vidh; | ||
| 400 | } | ||
| 401 | 395 | ||
| 402 | err = ubi_io_read_data(ubi, buf, pnum, 0, len); | 396 | mutex_lock(&ubi->buf_mutex); |
| 397 | err = ubi_io_read_data(ubi, ubi->peb_buf, pnum, 0, len); | ||
| 403 | if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) | 398 | if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err)) |
| 404 | goto out_free_buf; | 399 | goto out_unlock; |
| 405 | 400 | ||
| 406 | data_crc = be32_to_cpu(vid_hdr->data_crc); | 401 | data_crc = be32_to_cpu(vid_hdr->data_crc); |
| 407 | crc = crc32(UBI_CRC32_INIT, buf, len); | 402 | crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, len); |
| 408 | if (crc != data_crc) { | 403 | if (crc != data_crc) { |
| 409 | dbg_bld("PEB %d CRC error: calculated %#08x, must be %#08x", | 404 | dbg_bld("PEB %d CRC error: calculated %#08x, must be %#08x", |
| 410 | pnum, crc, data_crc); | 405 | pnum, crc, data_crc); |
| @@ -415,8 +410,8 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, | |||
| 415 | dbg_bld("PEB %d CRC is OK", pnum); | 410 | dbg_bld("PEB %d CRC is OK", pnum); |
| 416 | bitflips = !!err; | 411 | bitflips = !!err; |
| 417 | } | 412 | } |
| 413 | mutex_unlock(&ubi->buf_mutex); | ||
| 418 | 414 | ||
| 419 | vfree(buf); | ||
| 420 | ubi_free_vid_hdr(ubi, vh); | 415 | ubi_free_vid_hdr(ubi, vh); |
| 421 | 416 | ||
| 422 | if (second_is_newer) | 417 | if (second_is_newer) |
| @@ -426,8 +421,8 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, | |||
| 426 | 421 | ||
| 427 | return second_is_newer | (bitflips << 1) | (corrupted << 2); | 422 | return second_is_newer | (bitflips << 1) | (corrupted << 2); |
| 428 | 423 | ||
| 429 | out_free_buf: | 424 | out_unlock: |
| 430 | vfree(buf); | 425 | mutex_unlock(&ubi->buf_mutex); |
| 431 | out_free_vidh: | 426 | out_free_vidh: |
| 432 | ubi_free_vid_hdr(ubi, vh); | 427 | ubi_free_vid_hdr(ubi, vh); |
| 433 | return err; | 428 | return err; |
| @@ -1453,7 +1448,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) | |||
| 1453 | goto out_wl; | 1448 | goto out_wl; |
| 1454 | 1449 | ||
| 1455 | #ifdef CONFIG_MTD_UBI_FASTMAP | 1450 | #ifdef CONFIG_MTD_UBI_FASTMAP |
| 1456 | if (ubi->fm && ubi->dbg->chk_gen) { | 1451 | if (ubi->fm && ubi_dbg_chk_gen(ubi)) { |
| 1457 | struct ubi_attach_info *scan_ai; | 1452 | struct ubi_attach_info *scan_ai; |
| 1458 | 1453 | ||
| 1459 | scan_ai = alloc_ai("ubi_ckh_aeb_slab_cache"); | 1454 | scan_ai = alloc_ai("ubi_ckh_aeb_slab_cache"); |
| @@ -1503,7 +1498,7 @@ static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai) | |||
| 1503 | struct ubi_ainf_peb *aeb, *last_aeb; | 1498 | struct ubi_ainf_peb *aeb, *last_aeb; |
| 1504 | uint8_t *buf; | 1499 | uint8_t *buf; |
| 1505 | 1500 | ||
| 1506 | if (!ubi->dbg->chk_gen) | 1501 | if (!ubi_dbg_chk_gen(ubi)) |
| 1507 | return 0; | 1502 | return 0; |
| 1508 | 1503 | ||
| 1509 | /* | 1504 | /* |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 344b4cb49d4e..a56133585e92 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
| @@ -825,8 +825,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id) | |||
| 825 | * No available PEBs to re-size the volume, clear the flag on | 825 | * No available PEBs to re-size the volume, clear the flag on |
| 826 | * flash and exit. | 826 | * flash and exit. |
| 827 | */ | 827 | */ |
| 828 | memcpy(&vtbl_rec, &ubi->vtbl[vol_id], | 828 | vtbl_rec = ubi->vtbl[vol_id]; |
| 829 | sizeof(struct ubi_vtbl_record)); | ||
| 830 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); | 829 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); |
| 831 | if (err) | 830 | if (err) |
| 832 | ubi_err("cannot clean auto-resize flag for volume %d", | 831 | ubi_err("cannot clean auto-resize flag for volume %d", |
| @@ -986,14 +985,10 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, | |||
| 986 | if (!ubi->fm_buf) | 985 | if (!ubi->fm_buf) |
| 987 | goto out_free; | 986 | goto out_free; |
| 988 | #endif | 987 | #endif |
| 989 | err = ubi_debugging_init_dev(ubi); | ||
| 990 | if (err) | ||
| 991 | goto out_free; | ||
| 992 | |||
| 993 | err = ubi_attach(ubi, 0); | 988 | err = ubi_attach(ubi, 0); |
| 994 | if (err) { | 989 | if (err) { |
| 995 | ubi_err("failed to attach mtd%d, error %d", mtd->index, err); | 990 | ubi_err("failed to attach mtd%d, error %d", mtd->index, err); |
| 996 | goto out_debugging; | 991 | goto out_free; |
| 997 | } | 992 | } |
| 998 | 993 | ||
| 999 | if (ubi->autoresize_vol_id != -1) { | 994 | if (ubi->autoresize_vol_id != -1) { |
| @@ -1060,8 +1055,6 @@ out_detach: | |||
| 1060 | ubi_wl_close(ubi); | 1055 | ubi_wl_close(ubi); |
| 1061 | ubi_free_internal_volumes(ubi); | 1056 | ubi_free_internal_volumes(ubi); |
| 1062 | vfree(ubi->vtbl); | 1057 | vfree(ubi->vtbl); |
| 1063 | out_debugging: | ||
| 1064 | ubi_debugging_exit_dev(ubi); | ||
| 1065 | out_free: | 1058 | out_free: |
| 1066 | vfree(ubi->peb_buf); | 1059 | vfree(ubi->peb_buf); |
| 1067 | vfree(ubi->fm_buf); | 1060 | vfree(ubi->fm_buf); |
| @@ -1139,7 +1132,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) | |||
| 1139 | ubi_free_internal_volumes(ubi); | 1132 | ubi_free_internal_volumes(ubi); |
| 1140 | vfree(ubi->vtbl); | 1133 | vfree(ubi->vtbl); |
| 1141 | put_mtd_device(ubi->mtd); | 1134 | put_mtd_device(ubi->mtd); |
| 1142 | ubi_debugging_exit_dev(ubi); | ||
| 1143 | vfree(ubi->peb_buf); | 1135 | vfree(ubi->peb_buf); |
| 1144 | vfree(ubi->fm_buf); | 1136 | vfree(ubi->fm_buf); |
| 1145 | ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num); | 1137 | ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num); |
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index 26908a59506b..63cb1d7236ce 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c | |||
| @@ -217,32 +217,6 @@ void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req) | |||
| 217 | pr_err("\t1st 16 characters of name: %s\n", nm); | 217 | pr_err("\t1st 16 characters of name: %s\n", nm); |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | /** | ||
| 221 | * ubi_debugging_init_dev - initialize debugging for an UBI device. | ||
| 222 | * @ubi: UBI device description object | ||
| 223 | * | ||
| 224 | * This function initializes debugging-related data for UBI device @ubi. | ||
| 225 | * Returns zero in case of success and a negative error code in case of | ||
| 226 | * failure. | ||
| 227 | */ | ||
| 228 | int ubi_debugging_init_dev(struct ubi_device *ubi) | ||
| 229 | { | ||
| 230 | ubi->dbg = kzalloc(sizeof(struct ubi_debug_info), GFP_KERNEL); | ||
| 231 | if (!ubi->dbg) | ||
| 232 | return -ENOMEM; | ||
| 233 | |||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | |||
| 237 | /** | ||
| 238 | * ubi_debugging_exit_dev - free debugging data for an UBI device. | ||
| 239 | * @ubi: UBI device description object | ||
| 240 | */ | ||
| 241 | void ubi_debugging_exit_dev(struct ubi_device *ubi) | ||
| 242 | { | ||
| 243 | kfree(ubi->dbg); | ||
| 244 | } | ||
| 245 | |||
| 246 | /* | 220 | /* |
| 247 | * Root directory for UBI stuff in debugfs. Contains sub-directories which | 221 | * Root directory for UBI stuff in debugfs. Contains sub-directories which |
| 248 | * contain the stuff specific to particular UBI devices. | 222 | * contain the stuff specific to particular UBI devices. |
| @@ -295,7 +269,7 @@ static ssize_t dfs_file_read(struct file *file, char __user *user_buf, | |||
| 295 | ubi = ubi_get_device(ubi_num); | 269 | ubi = ubi_get_device(ubi_num); |
| 296 | if (!ubi) | 270 | if (!ubi) |
| 297 | return -ENODEV; | 271 | return -ENODEV; |
| 298 | d = ubi->dbg; | 272 | d = &ubi->dbg; |
| 299 | 273 | ||
| 300 | if (dent == d->dfs_chk_gen) | 274 | if (dent == d->dfs_chk_gen) |
| 301 | val = d->chk_gen; | 275 | val = d->chk_gen; |
| @@ -341,7 +315,7 @@ static ssize_t dfs_file_write(struct file *file, const char __user *user_buf, | |||
| 341 | ubi = ubi_get_device(ubi_num); | 315 | ubi = ubi_get_device(ubi_num); |
| 342 | if (!ubi) | 316 | if (!ubi) |
| 343 | return -ENODEV; | 317 | return -ENODEV; |
| 344 | d = ubi->dbg; | 318 | d = &ubi->dbg; |
| 345 | 319 | ||
| 346 | buf_size = min_t(size_t, count, (sizeof(buf) - 1)); | 320 | buf_size = min_t(size_t, count, (sizeof(buf) - 1)); |
| 347 | if (copy_from_user(buf, user_buf, buf_size)) { | 321 | if (copy_from_user(buf, user_buf, buf_size)) { |
| @@ -398,7 +372,7 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi) | |||
| 398 | unsigned long ubi_num = ubi->ubi_num; | 372 | unsigned long ubi_num = ubi->ubi_num; |
| 399 | const char *fname; | 373 | const char *fname; |
| 400 | struct dentry *dent; | 374 | struct dentry *dent; |
| 401 | struct ubi_debug_info *d = ubi->dbg; | 375 | struct ubi_debug_info *d = &ubi->dbg; |
| 402 | 376 | ||
| 403 | if (!IS_ENABLED(CONFIG_DEBUG_FS)) | 377 | if (!IS_ENABLED(CONFIG_DEBUG_FS)) |
| 404 | return 0; | 378 | return 0; |
| @@ -471,5 +445,5 @@ out: | |||
| 471 | void ubi_debugfs_exit_dev(struct ubi_device *ubi) | 445 | void ubi_debugfs_exit_dev(struct ubi_device *ubi) |
| 472 | { | 446 | { |
| 473 | if (IS_ENABLED(CONFIG_DEBUG_FS)) | 447 | if (IS_ENABLED(CONFIG_DEBUG_FS)) |
| 474 | debugfs_remove_recursive(ubi->dbg->dfs_dir); | 448 | debugfs_remove_recursive(ubi->dbg.dfs_dir); |
| 475 | } | 449 | } |
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 3dbc877d9663..33f8f3b2c9b2 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h | |||
| @@ -60,51 +60,11 @@ void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type); | |||
| 60 | void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req); | 60 | void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req); |
| 61 | int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, | 61 | int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, |
| 62 | int len); | 62 | int len); |
| 63 | int ubi_debugging_init_dev(struct ubi_device *ubi); | ||
| 64 | void ubi_debugging_exit_dev(struct ubi_device *ubi); | ||
| 65 | int ubi_debugfs_init(void); | 63 | int ubi_debugfs_init(void); |
| 66 | void ubi_debugfs_exit(void); | 64 | void ubi_debugfs_exit(void); |
| 67 | int ubi_debugfs_init_dev(struct ubi_device *ubi); | 65 | int ubi_debugfs_init_dev(struct ubi_device *ubi); |
| 68 | void ubi_debugfs_exit_dev(struct ubi_device *ubi); | 66 | void ubi_debugfs_exit_dev(struct ubi_device *ubi); |
| 69 | 67 | ||
| 70 | /* | ||
| 71 | * The UBI debugfs directory name pattern and maximum name length (3 for "ubi" | ||
| 72 | * + 2 for the number plus 1 for the trailing zero byte. | ||
| 73 | */ | ||
| 74 | #define UBI_DFS_DIR_NAME "ubi%d" | ||
| 75 | #define UBI_DFS_DIR_LEN (3 + 2 + 1) | ||
| 76 | |||
| 77 | /** | ||
| 78 | * struct ubi_debug_info - debugging information for an UBI device. | ||
| 79 | * | ||
| 80 | * @chk_gen: if UBI general extra checks are enabled | ||
| 81 | * @chk_io: if UBI I/O extra checks are enabled | ||
| 82 | * @disable_bgt: disable the background task for testing purposes | ||
| 83 | * @emulate_bitflips: emulate bit-flips for testing purposes | ||
| 84 | * @emulate_io_failures: emulate write/erase failures for testing purposes | ||
| 85 | * @dfs_dir_name: name of debugfs directory containing files of this UBI device | ||
| 86 | * @dfs_dir: direntry object of the UBI device debugfs directory | ||
| 87 | * @dfs_chk_gen: debugfs knob to enable UBI general extra checks | ||
| 88 | * @dfs_chk_io: debugfs knob to enable UBI I/O extra checks | ||
| 89 | * @dfs_disable_bgt: debugfs knob to disable the background task | ||
| 90 | * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips | ||
| 91 | * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures | ||
| 92 | */ | ||
| 93 | struct ubi_debug_info { | ||
| 94 | unsigned int chk_gen:1; | ||
| 95 | unsigned int chk_io:1; | ||
| 96 | unsigned int disable_bgt:1; | ||
| 97 | unsigned int emulate_bitflips:1; | ||
| 98 | unsigned int emulate_io_failures:1; | ||
| 99 | char dfs_dir_name[UBI_DFS_DIR_LEN + 1]; | ||
| 100 | struct dentry *dfs_dir; | ||
| 101 | struct dentry *dfs_chk_gen; | ||
| 102 | struct dentry *dfs_chk_io; | ||
| 103 | struct dentry *dfs_disable_bgt; | ||
| 104 | struct dentry *dfs_emulate_bitflips; | ||
| 105 | struct dentry *dfs_emulate_io_failures; | ||
| 106 | }; | ||
| 107 | |||
| 108 | /** | 68 | /** |
| 109 | * ubi_dbg_is_bgt_disabled - if the background thread is disabled. | 69 | * ubi_dbg_is_bgt_disabled - if the background thread is disabled. |
| 110 | * @ubi: UBI device description object | 70 | * @ubi: UBI device description object |
| @@ -114,7 +74,7 @@ struct ubi_debug_info { | |||
| 114 | */ | 74 | */ |
| 115 | static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi) | 75 | static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi) |
| 116 | { | 76 | { |
| 117 | return ubi->dbg->disable_bgt; | 77 | return ubi->dbg.disable_bgt; |
| 118 | } | 78 | } |
| 119 | 79 | ||
| 120 | /** | 80 | /** |
| @@ -125,7 +85,7 @@ static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi) | |||
| 125 | */ | 85 | */ |
| 126 | static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi) | 86 | static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi) |
| 127 | { | 87 | { |
| 128 | if (ubi->dbg->emulate_bitflips) | 88 | if (ubi->dbg.emulate_bitflips) |
| 129 | return !(random32() % 200); | 89 | return !(random32() % 200); |
| 130 | return 0; | 90 | return 0; |
| 131 | } | 91 | } |
| @@ -139,7 +99,7 @@ static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi) | |||
| 139 | */ | 99 | */ |
| 140 | static inline int ubi_dbg_is_write_failure(const struct ubi_device *ubi) | 100 | static inline int ubi_dbg_is_write_failure(const struct ubi_device *ubi) |
| 141 | { | 101 | { |
| 142 | if (ubi->dbg->emulate_io_failures) | 102 | if (ubi->dbg.emulate_io_failures) |
| 143 | return !(random32() % 500); | 103 | return !(random32() % 500); |
| 144 | return 0; | 104 | return 0; |
| 145 | } | 105 | } |
| @@ -153,9 +113,18 @@ static inline int ubi_dbg_is_write_failure(const struct ubi_device *ubi) | |||
| 153 | */ | 113 | */ |
| 154 | static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi) | 114 | static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi) |
| 155 | { | 115 | { |
| 156 | if (ubi->dbg->emulate_io_failures) | 116 | if (ubi->dbg.emulate_io_failures) |
| 157 | return !(random32() % 400); | 117 | return !(random32() % 400); |
| 158 | return 0; | 118 | return 0; |
| 159 | } | 119 | } |
| 160 | 120 | ||
| 121 | static inline int ubi_dbg_chk_io(const struct ubi_device *ubi) | ||
| 122 | { | ||
| 123 | return ubi->dbg.chk_io; | ||
| 124 | } | ||
| 125 | |||
| 126 | static inline int ubi_dbg_chk_gen(const struct ubi_device *ubi) | ||
| 127 | { | ||
| 128 | return ubi->dbg.chk_gen; | ||
| 129 | } | ||
| 161 | #endif /* !__UBI_DEBUG_H__ */ | 130 | #endif /* !__UBI_DEBUG_H__ */ |
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 1a5f53c090d4..0648c6996d43 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c | |||
| @@ -814,10 +814,8 @@ static int ubi_attach_fastmap(struct ubi_device *ubi, | |||
| 814 | if (max_sqnum > ai->max_sqnum) | 814 | if (max_sqnum > ai->max_sqnum) |
| 815 | ai->max_sqnum = max_sqnum; | 815 | ai->max_sqnum = max_sqnum; |
| 816 | 816 | ||
| 817 | list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) { | 817 | list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) |
| 818 | list_del(&tmp_aeb->u.list); | 818 | list_move_tail(&tmp_aeb->u.list, &ai->free); |
| 819 | list_add_tail(&tmp_aeb->u.list, &ai->free); | ||
| 820 | } | ||
| 821 | 819 | ||
| 822 | /* | 820 | /* |
| 823 | * If fastmap is leaking PEBs (must not happen), raise a | 821 | * If fastmap is leaking PEBs (must not happen), raise a |
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index 4bd4db8c84c9..b93807b4c459 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c | |||
| @@ -171,17 +171,17 @@ static void gluebi_put_device(struct mtd_info *mtd) | |||
| 171 | static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, | 171 | static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, |
| 172 | size_t *retlen, unsigned char *buf) | 172 | size_t *retlen, unsigned char *buf) |
| 173 | { | 173 | { |
| 174 | int err = 0, lnum, offs, total_read; | 174 | int err = 0, lnum, offs, bytes_left; |
| 175 | struct gluebi_device *gluebi; | 175 | struct gluebi_device *gluebi; |
| 176 | 176 | ||
| 177 | gluebi = container_of(mtd, struct gluebi_device, mtd); | 177 | gluebi = container_of(mtd, struct gluebi_device, mtd); |
| 178 | lnum = div_u64_rem(from, mtd->erasesize, &offs); | 178 | lnum = div_u64_rem(from, mtd->erasesize, &offs); |
| 179 | total_read = len; | 179 | bytes_left = len; |
| 180 | while (total_read) { | 180 | while (bytes_left) { |
| 181 | size_t to_read = mtd->erasesize - offs; | 181 | size_t to_read = mtd->erasesize - offs; |
| 182 | 182 | ||
| 183 | if (to_read > total_read) | 183 | if (to_read > bytes_left) |
| 184 | to_read = total_read; | 184 | to_read = bytes_left; |
| 185 | 185 | ||
| 186 | err = ubi_read(gluebi->desc, lnum, buf, offs, to_read); | 186 | err = ubi_read(gluebi->desc, lnum, buf, offs, to_read); |
| 187 | if (err) | 187 | if (err) |
| @@ -189,11 +189,11 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 189 | 189 | ||
| 190 | lnum += 1; | 190 | lnum += 1; |
| 191 | offs = 0; | 191 | offs = 0; |
| 192 | total_read -= to_read; | 192 | bytes_left -= to_read; |
| 193 | buf += to_read; | 193 | buf += to_read; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | *retlen = len - total_read; | 196 | *retlen = len - bytes_left; |
| 197 | return err; | 197 | return err; |
| 198 | } | 198 | } |
| 199 | 199 | ||
| @@ -211,7 +211,7 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 211 | static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, | 211 | static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, |
| 212 | size_t *retlen, const u_char *buf) | 212 | size_t *retlen, const u_char *buf) |
| 213 | { | 213 | { |
| 214 | int err = 0, lnum, offs, total_written; | 214 | int err = 0, lnum, offs, bytes_left; |
| 215 | struct gluebi_device *gluebi; | 215 | struct gluebi_device *gluebi; |
| 216 | 216 | ||
| 217 | gluebi = container_of(mtd, struct gluebi_device, mtd); | 217 | gluebi = container_of(mtd, struct gluebi_device, mtd); |
| @@ -220,12 +220,12 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 220 | if (len % mtd->writesize || offs % mtd->writesize) | 220 | if (len % mtd->writesize || offs % mtd->writesize) |
| 221 | return -EINVAL; | 221 | return -EINVAL; |
| 222 | 222 | ||
| 223 | total_written = len; | 223 | bytes_left = len; |
| 224 | while (total_written) { | 224 | while (bytes_left) { |
| 225 | size_t to_write = mtd->erasesize - offs; | 225 | size_t to_write = mtd->erasesize - offs; |
| 226 | 226 | ||
| 227 | if (to_write > total_written) | 227 | if (to_write > bytes_left) |
| 228 | to_write = total_written; | 228 | to_write = bytes_left; |
| 229 | 229 | ||
| 230 | err = ubi_leb_write(gluebi->desc, lnum, buf, offs, to_write); | 230 | err = ubi_leb_write(gluebi->desc, lnum, buf, offs, to_write); |
| 231 | if (err) | 231 | if (err) |
| @@ -233,11 +233,11 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 233 | 233 | ||
| 234 | lnum += 1; | 234 | lnum += 1; |
| 235 | offs = 0; | 235 | offs = 0; |
| 236 | total_written -= to_write; | 236 | bytes_left -= to_write; |
| 237 | buf += to_write; | 237 | buf += to_write; |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | *retlen = len - total_written; | 240 | *retlen = len - bytes_left; |
| 241 | return err; | 241 | return err; |
| 242 | } | 242 | } |
| 243 | 243 | ||
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 78a1dcbf2107..bf79def40126 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
| @@ -1132,7 +1132,7 @@ static int self_check_not_bad(const struct ubi_device *ubi, int pnum) | |||
| 1132 | { | 1132 | { |
| 1133 | int err; | 1133 | int err; |
| 1134 | 1134 | ||
| 1135 | if (!ubi->dbg->chk_io) | 1135 | if (!ubi_dbg_chk_io(ubi)) |
| 1136 | return 0; | 1136 | return 0; |
| 1137 | 1137 | ||
| 1138 | err = ubi_io_is_bad(ubi, pnum); | 1138 | err = ubi_io_is_bad(ubi, pnum); |
| @@ -1159,7 +1159,7 @@ static int self_check_ec_hdr(const struct ubi_device *ubi, int pnum, | |||
| 1159 | int err; | 1159 | int err; |
| 1160 | uint32_t magic; | 1160 | uint32_t magic; |
| 1161 | 1161 | ||
| 1162 | if (!ubi->dbg->chk_io) | 1162 | if (!ubi_dbg_chk_io(ubi)) |
| 1163 | return 0; | 1163 | return 0; |
| 1164 | 1164 | ||
| 1165 | magic = be32_to_cpu(ec_hdr->magic); | 1165 | magic = be32_to_cpu(ec_hdr->magic); |
| @@ -1197,7 +1197,7 @@ static int self_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) | |||
| 1197 | uint32_t crc, hdr_crc; | 1197 | uint32_t crc, hdr_crc; |
| 1198 | struct ubi_ec_hdr *ec_hdr; | 1198 | struct ubi_ec_hdr *ec_hdr; |
| 1199 | 1199 | ||
| 1200 | if (!ubi->dbg->chk_io) | 1200 | if (!ubi_dbg_chk_io(ubi)) |
| 1201 | return 0; | 1201 | return 0; |
| 1202 | 1202 | ||
| 1203 | ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS); | 1203 | ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS); |
| @@ -1241,7 +1241,7 @@ static int self_check_vid_hdr(const struct ubi_device *ubi, int pnum, | |||
| 1241 | int err; | 1241 | int err; |
| 1242 | uint32_t magic; | 1242 | uint32_t magic; |
| 1243 | 1243 | ||
| 1244 | if (!ubi->dbg->chk_io) | 1244 | if (!ubi_dbg_chk_io(ubi)) |
| 1245 | return 0; | 1245 | return 0; |
| 1246 | 1246 | ||
| 1247 | magic = be32_to_cpu(vid_hdr->magic); | 1247 | magic = be32_to_cpu(vid_hdr->magic); |
| @@ -1282,7 +1282,7 @@ static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) | |||
| 1282 | struct ubi_vid_hdr *vid_hdr; | 1282 | struct ubi_vid_hdr *vid_hdr; |
| 1283 | void *p; | 1283 | void *p; |
| 1284 | 1284 | ||
| 1285 | if (!ubi->dbg->chk_io) | 1285 | if (!ubi_dbg_chk_io(ubi)) |
| 1286 | return 0; | 1286 | return 0; |
| 1287 | 1287 | ||
| 1288 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); | 1288 | vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); |
| @@ -1334,7 +1334,7 @@ static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum, | |||
| 1334 | void *buf1; | 1334 | void *buf1; |
| 1335 | loff_t addr = (loff_t)pnum * ubi->peb_size + offset; | 1335 | loff_t addr = (loff_t)pnum * ubi->peb_size + offset; |
| 1336 | 1336 | ||
| 1337 | if (!ubi->dbg->chk_io) | 1337 | if (!ubi_dbg_chk_io(ubi)) |
| 1338 | return 0; | 1338 | return 0; |
| 1339 | 1339 | ||
| 1340 | buf1 = __vmalloc(len, GFP_NOFS, PAGE_KERNEL); | 1340 | buf1 = __vmalloc(len, GFP_NOFS, PAGE_KERNEL); |
| @@ -1398,7 +1398,7 @@ int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) | |||
| 1398 | void *buf; | 1398 | void *buf; |
| 1399 | loff_t addr = (loff_t)pnum * ubi->peb_size + offset; | 1399 | loff_t addr = (loff_t)pnum * ubi->peb_size + offset; |
| 1400 | 1400 | ||
| 1401 | if (!ubi->dbg->chk_io) | 1401 | if (!ubi_dbg_chk_io(ubi)) |
| 1402 | return 0; | 1402 | return 0; |
| 1403 | 1403 | ||
| 1404 | buf = __vmalloc(len, GFP_NOFS, PAGE_KERNEL); | 1404 | buf = __vmalloc(len, GFP_NOFS, PAGE_KERNEL); |
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 7d57469723cf..8ea6297a208f 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
| @@ -85,6 +85,13 @@ | |||
| 85 | #define UBI_UNKNOWN -1 | 85 | #define UBI_UNKNOWN -1 |
| 86 | 86 | ||
| 87 | /* | 87 | /* |
| 88 | * The UBI debugfs directory name pattern and maximum name length (3 for "ubi" | ||
| 89 | * + 2 for the number plus 1 for the trailing zero byte. | ||
| 90 | */ | ||
| 91 | #define UBI_DFS_DIR_NAME "ubi%d" | ||
| 92 | #define UBI_DFS_DIR_LEN (3 + 2 + 1) | ||
| 93 | |||
| 94 | /* | ||
| 88 | * Error codes returned by the I/O sub-system. | 95 | * Error codes returned by the I/O sub-system. |
| 89 | * | 96 | * |
| 90 | * UBI_IO_FF: the read region of flash contains only 0xFFs | 97 | * UBI_IO_FF: the read region of flash contains only 0xFFs |
| @@ -342,6 +349,37 @@ struct ubi_volume_desc { | |||
| 342 | struct ubi_wl_entry; | 349 | struct ubi_wl_entry; |
| 343 | 350 | ||
| 344 | /** | 351 | /** |
| 352 | * struct ubi_debug_info - debugging information for an UBI device. | ||
| 353 | * | ||
| 354 | * @chk_gen: if UBI general extra checks are enabled | ||
| 355 | * @chk_io: if UBI I/O extra checks are enabled | ||
| 356 | * @disable_bgt: disable the background task for testing purposes | ||
| 357 | * @emulate_bitflips: emulate bit-flips for testing purposes | ||
| 358 | * @emulate_io_failures: emulate write/erase failures for testing purposes | ||
| 359 | * @dfs_dir_name: name of debugfs directory containing files of this UBI device | ||
| 360 | * @dfs_dir: direntry object of the UBI device debugfs directory | ||
| 361 | * @dfs_chk_gen: debugfs knob to enable UBI general extra checks | ||
| 362 | * @dfs_chk_io: debugfs knob to enable UBI I/O extra checks | ||
| 363 | * @dfs_disable_bgt: debugfs knob to disable the background task | ||
| 364 | * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips | ||
| 365 | * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures | ||
| 366 | */ | ||
| 367 | struct ubi_debug_info { | ||
| 368 | unsigned int chk_gen:1; | ||
| 369 | unsigned int chk_io:1; | ||
| 370 | unsigned int disable_bgt:1; | ||
| 371 | unsigned int emulate_bitflips:1; | ||
| 372 | unsigned int emulate_io_failures:1; | ||
| 373 | char dfs_dir_name[UBI_DFS_DIR_LEN + 1]; | ||
| 374 | struct dentry *dfs_dir; | ||
| 375 | struct dentry *dfs_chk_gen; | ||
| 376 | struct dentry *dfs_chk_io; | ||
| 377 | struct dentry *dfs_disable_bgt; | ||
| 378 | struct dentry *dfs_emulate_bitflips; | ||
| 379 | struct dentry *dfs_emulate_io_failures; | ||
| 380 | }; | ||
| 381 | |||
| 382 | /** | ||
| 345 | * struct ubi_device - UBI device description structure | 383 | * struct ubi_device - UBI device description structure |
| 346 | * @dev: UBI device object to use the the Linux device model | 384 | * @dev: UBI device object to use the the Linux device model |
| 347 | * @cdev: character device object to create character device | 385 | * @cdev: character device object to create character device |
| @@ -545,7 +583,7 @@ struct ubi_device { | |||
| 545 | struct mutex buf_mutex; | 583 | struct mutex buf_mutex; |
| 546 | struct mutex ckvol_mutex; | 584 | struct mutex ckvol_mutex; |
| 547 | 585 | ||
| 548 | struct ubi_debug_info *dbg; | 586 | struct ubi_debug_info dbg; |
| 549 | }; | 587 | }; |
| 550 | 588 | ||
| 551 | /** | 589 | /** |
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 9f2ebd8750e7..ec2c2dc1c1ca 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c | |||
| @@ -64,8 +64,7 @@ static int set_update_marker(struct ubi_device *ubi, struct ubi_volume *vol) | |||
| 64 | return 0; | 64 | return 0; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id], | 67 | vtbl_rec = ubi->vtbl[vol->vol_id]; |
| 68 | sizeof(struct ubi_vtbl_record)); | ||
| 69 | vtbl_rec.upd_marker = 1; | 68 | vtbl_rec.upd_marker = 1; |
| 70 | 69 | ||
| 71 | mutex_lock(&ubi->device_mutex); | 70 | mutex_lock(&ubi->device_mutex); |
| @@ -93,8 +92,7 @@ static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 93 | 92 | ||
| 94 | dbg_gen("clear update marker for volume %d", vol->vol_id); | 93 | dbg_gen("clear update marker for volume %d", vol->vol_id); |
| 95 | 94 | ||
| 96 | memcpy(&vtbl_rec, &ubi->vtbl[vol->vol_id], | 95 | vtbl_rec = ubi->vtbl[vol->vol_id]; |
| 97 | sizeof(struct ubi_vtbl_record)); | ||
| 98 | ubi_assert(vol->upd_marker && vtbl_rec.upd_marker); | 96 | ubi_assert(vol->upd_marker && vtbl_rec.upd_marker); |
| 99 | vtbl_rec.upd_marker = 0; | 97 | vtbl_rec.upd_marker = 0; |
| 100 | 98 | ||
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 9169e58c262e..8330703c098f 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
| @@ -535,7 +535,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) | |||
| 535 | } | 535 | } |
| 536 | 536 | ||
| 537 | /* Change volume table record */ | 537 | /* Change volume table record */ |
| 538 | memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); | 538 | vtbl_rec = ubi->vtbl[vol_id]; |
| 539 | vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs); | 539 | vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs); |
| 540 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); | 540 | err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); |
| 541 | if (err) | 541 | if (err) |
| @@ -847,7 +847,7 @@ static int self_check_volumes(struct ubi_device *ubi) | |||
| 847 | { | 847 | { |
| 848 | int i, err = 0; | 848 | int i, err = 0; |
| 849 | 849 | ||
| 850 | if (!ubi->dbg->chk_gen) | 850 | if (!ubi_dbg_chk_gen(ubi)) |
| 851 | return 0; | 851 | return 0; |
| 852 | 852 | ||
| 853 | for (i = 0; i < ubi->vtbl_slots; i++) { | 853 | for (i = 0; i < ubi->vtbl_slots; i++) { |
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 926e3df14fb2..d77b1c1d7c72 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c | |||
| @@ -858,7 +858,7 @@ out_free: | |||
| 858 | */ | 858 | */ |
| 859 | static void self_vtbl_check(const struct ubi_device *ubi) | 859 | static void self_vtbl_check(const struct ubi_device *ubi) |
| 860 | { | 860 | { |
| 861 | if (!ubi->dbg->chk_gen) | 861 | if (!ubi_dbg_chk_gen(ubi)) |
| 862 | return; | 862 | return; |
| 863 | 863 | ||
| 864 | if (vtbl_check(ubi, ubi->vtbl)) { | 864 | if (vtbl_check(ubi, ubi->vtbl)) { |
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 2144f611196e..5df49d3cb5c7 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * @ubi: UBI device description object | ||
| 3 | * Copyright (c) International Business Machines Corp., 2006 | 2 | * Copyright (c) International Business Machines Corp., 2006 |
| 4 | * | 3 | * |
| 5 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
| @@ -2050,7 +2049,7 @@ static int self_check_ec(struct ubi_device *ubi, int pnum, int ec) | |||
| 2050 | long long read_ec; | 2049 | long long read_ec; |
| 2051 | struct ubi_ec_hdr *ec_hdr; | 2050 | struct ubi_ec_hdr *ec_hdr; |
| 2052 | 2051 | ||
| 2053 | if (!ubi->dbg->chk_gen) | 2052 | if (!ubi_dbg_chk_gen(ubi)) |
| 2054 | return 0; | 2053 | return 0; |
| 2055 | 2054 | ||
| 2056 | ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS); | 2055 | ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS); |
| @@ -2090,7 +2089,7 @@ out_free: | |||
| 2090 | static int self_check_in_wl_tree(const struct ubi_device *ubi, | 2089 | static int self_check_in_wl_tree(const struct ubi_device *ubi, |
| 2091 | struct ubi_wl_entry *e, struct rb_root *root) | 2090 | struct ubi_wl_entry *e, struct rb_root *root) |
| 2092 | { | 2091 | { |
| 2093 | if (!ubi->dbg->chk_gen) | 2092 | if (!ubi_dbg_chk_gen(ubi)) |
| 2094 | return 0; | 2093 | return 0; |
| 2095 | 2094 | ||
| 2096 | if (in_wl_tree(e, root)) | 2095 | if (in_wl_tree(e, root)) |
| @@ -2116,7 +2115,7 @@ static int self_check_in_pq(const struct ubi_device *ubi, | |||
| 2116 | struct ubi_wl_entry *p; | 2115 | struct ubi_wl_entry *p; |
| 2117 | int i; | 2116 | int i; |
| 2118 | 2117 | ||
| 2119 | if (!ubi->dbg->chk_gen) | 2118 | if (!ubi_dbg_chk_gen(ubi)) |
| 2120 | return 0; | 2119 | return 0; |
| 2121 | 2120 | ||
| 2122 | for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i) | 2121 | for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i) |
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/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 378988b5709a..6db997c78a5f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | |||
| @@ -35,6 +35,8 @@ | |||
| 35 | #ifndef __CXGB4_H__ | 35 | #ifndef __CXGB4_H__ |
| 36 | #define __CXGB4_H__ | 36 | #define __CXGB4_H__ |
| 37 | 37 | ||
| 38 | #include "t4_hw.h" | ||
| 39 | |||
| 38 | #include <linux/bitops.h> | 40 | #include <linux/bitops.h> |
| 39 | #include <linux/cache.h> | 41 | #include <linux/cache.h> |
| 40 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
| @@ -212,6 +214,8 @@ struct tp_err_stats { | |||
| 212 | struct tp_params { | 214 | struct tp_params { |
| 213 | unsigned int ntxchan; /* # of Tx channels */ | 215 | unsigned int ntxchan; /* # of Tx channels */ |
| 214 | unsigned int tre; /* log2 of core clocks per TP tick */ | 216 | unsigned int tre; /* log2 of core clocks per TP tick */ |
| 217 | unsigned short tx_modq_map; /* TX modulation scheduler queue to */ | ||
| 218 | /* channel map */ | ||
| 215 | 219 | ||
| 216 | uint32_t dack_re; /* DACK timer resolution */ | 220 | uint32_t dack_re; /* DACK timer resolution */ |
| 217 | unsigned short tx_modq[NCHAN]; /* channel to modulation queue map */ | 221 | unsigned short tx_modq[NCHAN]; /* channel to modulation queue map */ |
| @@ -526,6 +530,7 @@ struct adapter { | |||
| 526 | struct net_device *port[MAX_NPORTS]; | 530 | struct net_device *port[MAX_NPORTS]; |
| 527 | u8 chan_map[NCHAN]; /* channel -> port map */ | 531 | u8 chan_map[NCHAN]; /* channel -> port map */ |
| 528 | 532 | ||
| 533 | u32 filter_mode; | ||
| 529 | unsigned int l2t_start; | 534 | unsigned int l2t_start; |
| 530 | unsigned int l2t_end; | 535 | unsigned int l2t_end; |
| 531 | struct l2t_data *l2t; | 536 | struct l2t_data *l2t; |
| @@ -545,6 +550,129 @@ struct adapter { | |||
| 545 | spinlock_t stats_lock; | 550 | spinlock_t stats_lock; |
| 546 | }; | 551 | }; |
| 547 | 552 | ||
| 553 | /* Defined bit width of user definable filter tuples | ||
| 554 | */ | ||
| 555 | #define ETHTYPE_BITWIDTH 16 | ||
| 556 | #define FRAG_BITWIDTH 1 | ||
| 557 | #define MACIDX_BITWIDTH 9 | ||
| 558 | #define FCOE_BITWIDTH 1 | ||
| 559 | #define IPORT_BITWIDTH 3 | ||
| 560 | #define MATCHTYPE_BITWIDTH 3 | ||
| 561 | #define PROTO_BITWIDTH 8 | ||
| 562 | #define TOS_BITWIDTH 8 | ||
| 563 | #define PF_BITWIDTH 8 | ||
| 564 | #define VF_BITWIDTH 8 | ||
| 565 | #define IVLAN_BITWIDTH 16 | ||
| 566 | #define OVLAN_BITWIDTH 16 | ||
| 567 | |||
| 568 | /* Filter matching rules. These consist of a set of ingress packet field | ||
| 569 | * (value, mask) tuples. The associated ingress packet field matches the | ||
| 570 | * tuple when ((field & mask) == value). (Thus a wildcard "don't care" field | ||
| 571 | * rule can be constructed by specifying a tuple of (0, 0).) A filter rule | ||
| 572 | * matches an ingress packet when all of the individual individual field | ||
| 573 | * matching rules are true. | ||
| 574 | * | ||
| 575 | * Partial field masks are always valid, however, while it may be easy to | ||
| 576 | * understand their meanings for some fields (e.g. IP address to match a | ||
| 577 | * subnet), for others making sensible partial masks is less intuitive (e.g. | ||
| 578 | * MPS match type) ... | ||
| 579 | * | ||
| 580 | * Most of the following data structures are modeled on T4 capabilities. | ||
| 581 | * Drivers for earlier chips use the subsets which make sense for those chips. | ||
| 582 | * We really need to come up with a hardware-independent mechanism to | ||
| 583 | * represent hardware filter capabilities ... | ||
| 584 | */ | ||
| 585 | struct ch_filter_tuple { | ||
| 586 | /* Compressed header matching field rules. The TP_VLAN_PRI_MAP | ||
| 587 | * register selects which of these fields will participate in the | ||
| 588 | * filter match rules -- up to a maximum of 36 bits. Because | ||
| 589 | * TP_VLAN_PRI_MAP is a global register, all filters must use the same | ||
| 590 | * set of fields. | ||
| 591 | */ | ||
| 592 | uint32_t ethtype:ETHTYPE_BITWIDTH; /* Ethernet type */ | ||
| 593 | uint32_t frag:FRAG_BITWIDTH; /* IP fragmentation header */ | ||
| 594 | uint32_t ivlan_vld:1; /* inner VLAN valid */ | ||
| 595 | uint32_t ovlan_vld:1; /* outer VLAN valid */ | ||
| 596 | uint32_t pfvf_vld:1; /* PF/VF valid */ | ||
| 597 | uint32_t macidx:MACIDX_BITWIDTH; /* exact match MAC index */ | ||
| 598 | uint32_t fcoe:FCOE_BITWIDTH; /* FCoE packet */ | ||
| 599 | uint32_t iport:IPORT_BITWIDTH; /* ingress port */ | ||
| 600 | uint32_t matchtype:MATCHTYPE_BITWIDTH; /* MPS match type */ | ||
| 601 | uint32_t proto:PROTO_BITWIDTH; /* protocol type */ | ||
| 602 | uint32_t tos:TOS_BITWIDTH; /* TOS/Traffic Type */ | ||
| 603 | uint32_t pf:PF_BITWIDTH; /* PCI-E PF ID */ | ||
| 604 | uint32_t vf:VF_BITWIDTH; /* PCI-E VF ID */ | ||
| 605 | uint32_t ivlan:IVLAN_BITWIDTH; /* inner VLAN */ | ||
| 606 | uint32_t ovlan:OVLAN_BITWIDTH; /* outer VLAN */ | ||
| 607 | |||
| 608 | /* Uncompressed header matching field rules. These are always | ||
| 609 | * available for field rules. | ||
| 610 | */ | ||
| 611 | uint8_t lip[16]; /* local IP address (IPv4 in [3:0]) */ | ||
| 612 | uint8_t fip[16]; /* foreign IP address (IPv4 in [3:0]) */ | ||
| 613 | uint16_t lport; /* local port */ | ||
| 614 | uint16_t fport; /* foreign port */ | ||
| 615 | }; | ||
| 616 | |||
| 617 | /* A filter ioctl command. | ||
| 618 | */ | ||
| 619 | struct ch_filter_specification { | ||
| 620 | /* Administrative fields for filter. | ||
| 621 | */ | ||
| 622 | uint32_t hitcnts:1; /* count filter hits in TCB */ | ||
| 623 | uint32_t prio:1; /* filter has priority over active/server */ | ||
| 624 | |||
| 625 | /* Fundamental filter typing. This is the one element of filter | ||
| 626 | * matching that doesn't exist as a (value, mask) tuple. | ||
| 627 | */ | ||
| 628 | uint32_t type:1; /* 0 => IPv4, 1 => IPv6 */ | ||
| 629 | |||
| 630 | /* Packet dispatch information. Ingress packets which match the | ||
| 631 | * filter rules will be dropped, passed to the host or switched back | ||
| 632 | * out as egress packets. | ||
| 633 | */ | ||
| 634 | uint32_t action:2; /* drop, pass, switch */ | ||
| 635 | |||
| 636 | uint32_t rpttid:1; /* report TID in RSS hash field */ | ||
| 637 | |||
| 638 | uint32_t dirsteer:1; /* 0 => RSS, 1 => steer to iq */ | ||
| 639 | uint32_t iq:10; /* ingress queue */ | ||
| 640 | |||
| 641 | uint32_t maskhash:1; /* dirsteer=0: store RSS hash in TCB */ | ||
| 642 | uint32_t dirsteerhash:1;/* dirsteer=1: 0 => TCB contains RSS hash */ | ||
| 643 | /* 1 => TCB contains IQ ID */ | ||
| 644 | |||
| 645 | /* Switch proxy/rewrite fields. An ingress packet which matches a | ||
| 646 | * filter with "switch" set will be looped back out as an egress | ||
| 647 | * packet -- potentially with some Ethernet header rewriting. | ||
| 648 | */ | ||
| 649 | uint32_t eport:2; /* egress port to switch packet out */ | ||
| 650 | uint32_t newdmac:1; /* rewrite destination MAC address */ | ||
| 651 | uint32_t newsmac:1; /* rewrite source MAC address */ | ||
| 652 | uint32_t newvlan:2; /* rewrite VLAN Tag */ | ||
| 653 | uint8_t dmac[ETH_ALEN]; /* new destination MAC address */ | ||
| 654 | uint8_t smac[ETH_ALEN]; /* new source MAC address */ | ||
| 655 | uint16_t vlan; /* VLAN Tag to insert */ | ||
| 656 | |||
| 657 | /* Filter rule value/mask pairs. | ||
| 658 | */ | ||
| 659 | struct ch_filter_tuple val; | ||
| 660 | struct ch_filter_tuple mask; | ||
| 661 | }; | ||
| 662 | |||
| 663 | enum { | ||
| 664 | FILTER_PASS = 0, /* default */ | ||
| 665 | FILTER_DROP, | ||
| 666 | FILTER_SWITCH | ||
| 667 | }; | ||
| 668 | |||
| 669 | enum { | ||
| 670 | VLAN_NOCHANGE = 0, /* default */ | ||
| 671 | VLAN_REMOVE, | ||
| 672 | VLAN_INSERT, | ||
| 673 | VLAN_REWRITE | ||
| 674 | }; | ||
| 675 | |||
| 548 | static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) | 676 | static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) |
| 549 | { | 677 | { |
| 550 | return readl(adap->regs + reg_addr); | 678 | return readl(adap->regs + reg_addr); |
| @@ -701,6 +829,12 @@ static inline int t4_wr_mbox_ns(struct adapter *adap, int mbox, const void *cmd, | |||
| 701 | void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, | 829 | void t4_write_indirect(struct adapter *adap, unsigned int addr_reg, |
| 702 | unsigned int data_reg, const u32 *vals, | 830 | unsigned int data_reg, const u32 *vals, |
| 703 | unsigned int nregs, unsigned int start_idx); | 831 | unsigned int nregs, unsigned int start_idx); |
| 832 | void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, | ||
| 833 | unsigned int data_reg, u32 *vals, unsigned int nregs, | ||
| 834 | unsigned int start_idx); | ||
| 835 | |||
| 836 | struct fw_filter_wr; | ||
| 837 | |||
| 704 | void t4_intr_enable(struct adapter *adapter); | 838 | void t4_intr_enable(struct adapter *adapter); |
| 705 | void t4_intr_disable(struct adapter *adapter); | 839 | void t4_intr_disable(struct adapter *adapter); |
| 706 | int t4_slow_intr_handler(struct adapter *adapter); | 840 | int t4_slow_intr_handler(struct adapter *adapter); |
| @@ -737,6 +871,8 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4, | |||
| 737 | void t4_load_mtus(struct adapter *adap, const unsigned short *mtus, | 871 | void t4_load_mtus(struct adapter *adap, const unsigned short *mtus, |
| 738 | const unsigned short *alpha, const unsigned short *beta); | 872 | const unsigned short *alpha, const unsigned short *beta); |
| 739 | 873 | ||
| 874 | void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid); | ||
| 875 | |||
| 740 | void t4_wol_magic_enable(struct adapter *adap, unsigned int port, | 876 | void t4_wol_magic_enable(struct adapter *adap, unsigned int port, |
| 741 | const u8 *addr); | 877 | const u8 *addr); |
| 742 | int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, | 878 | int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index a27b4ae20f43..f0718e1a8369 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | |||
| @@ -175,6 +175,30 @@ enum { | |||
| 175 | MIN_FL_ENTRIES = 16 | 175 | MIN_FL_ENTRIES = 16 |
| 176 | }; | 176 | }; |
| 177 | 177 | ||
| 178 | /* Host shadow copy of ingress filter entry. This is in host native format | ||
| 179 | * and doesn't match the ordering or bit order, etc. of the hardware of the | ||
| 180 | * firmware command. The use of bit-field structure elements is purely to | ||
| 181 | * remind ourselves of the field size limitations and save memory in the case | ||
| 182 | * where the filter table is large. | ||
| 183 | */ | ||
| 184 | struct filter_entry { | ||
| 185 | /* Administrative fields for filter. | ||
| 186 | */ | ||
| 187 | u32 valid:1; /* filter allocated and valid */ | ||
| 188 | u32 locked:1; /* filter is administratively locked */ | ||
| 189 | |||
| 190 | u32 pending:1; /* filter action is pending firmware reply */ | ||
| 191 | u32 smtidx:8; /* Source MAC Table index for smac */ | ||
| 192 | struct l2t_entry *l2t; /* Layer Two Table entry for dmac */ | ||
| 193 | |||
| 194 | /* The filter itself. Most of this is a straight copy of information | ||
| 195 | * provided by the extended ioctl(). Some fields are translated to | ||
| 196 | * internal forms -- for instance the Ingress Queue ID passed in from | ||
| 197 | * the ioctl() is translated into the Absolute Ingress Queue ID. | ||
| 198 | */ | ||
| 199 | struct ch_filter_specification fs; | ||
| 200 | }; | ||
| 201 | |||
| 178 | #define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \ | 202 | #define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \ |
| 179 | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\ | 203 | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\ |
| 180 | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) | 204 | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) |
| @@ -325,6 +349,9 @@ enum { | |||
| 325 | 349 | ||
| 326 | static unsigned int tp_vlan_pri_map = TP_VLAN_PRI_MAP_DEFAULT; | 350 | static unsigned int tp_vlan_pri_map = TP_VLAN_PRI_MAP_DEFAULT; |
| 327 | 351 | ||
| 352 | module_param(tp_vlan_pri_map, uint, 0644); | ||
| 353 | MODULE_PARM_DESC(tp_vlan_pri_map, "global compressed filter configuration"); | ||
| 354 | |||
| 328 | static struct dentry *cxgb4_debugfs_root; | 355 | static struct dentry *cxgb4_debugfs_root; |
| 329 | 356 | ||
| 330 | static LIST_HEAD(adapter_list); | 357 | static LIST_HEAD(adapter_list); |
| @@ -506,8 +533,67 @@ static int link_start(struct net_device *dev) | |||
| 506 | return ret; | 533 | return ret; |
| 507 | } | 534 | } |
| 508 | 535 | ||
| 509 | /* | 536 | /* Clear a filter and release any of its resources that we own. This also |
| 510 | * Response queue handler for the FW event queue. | 537 | * clears the filter's "pending" status. |
| 538 | */ | ||
| 539 | static void clear_filter(struct adapter *adap, struct filter_entry *f) | ||
| 540 | { | ||
| 541 | /* If the new or old filter have loopback rewriteing rules then we'll | ||
| 542 | * need to free any existing Layer Two Table (L2T) entries of the old | ||
| 543 | * filter rule. The firmware will handle freeing up any Source MAC | ||
| 544 | * Table (SMT) entries used for rewriting Source MAC Addresses in | ||
| 545 | * loopback rules. | ||
| 546 | */ | ||
| 547 | if (f->l2t) | ||
| 548 | cxgb4_l2t_release(f->l2t); | ||
| 549 | |||
| 550 | /* The zeroing of the filter rule below clears the filter valid, | ||
| 551 | * pending, locked flags, l2t pointer, etc. so it's all we need for | ||
| 552 | * this operation. | ||
| 553 | */ | ||
| 554 | memset(f, 0, sizeof(*f)); | ||
| 555 | } | ||
| 556 | |||
| 557 | /* Handle a filter write/deletion reply. | ||
| 558 | */ | ||
| 559 | static void filter_rpl(struct adapter *adap, const struct cpl_set_tcb_rpl *rpl) | ||
| 560 | { | ||
| 561 | unsigned int idx = GET_TID(rpl); | ||
| 562 | unsigned int nidx = idx - adap->tids.ftid_base; | ||
| 563 | unsigned int ret; | ||
| 564 | struct filter_entry *f; | ||
| 565 | |||
| 566 | if (idx >= adap->tids.ftid_base && nidx < | ||
| 567 | (adap->tids.nftids + adap->tids.nsftids)) { | ||
| 568 | idx = nidx; | ||
| 569 | ret = GET_TCB_COOKIE(rpl->cookie); | ||
| 570 | f = &adap->tids.ftid_tab[idx]; | ||
| 571 | |||
| 572 | if (ret == FW_FILTER_WR_FLT_DELETED) { | ||
| 573 | /* Clear the filter when we get confirmation from the | ||
| 574 | * hardware that the filter has been deleted. | ||
| 575 | */ | ||
| 576 | clear_filter(adap, f); | ||
| 577 | } else if (ret == FW_FILTER_WR_SMT_TBL_FULL) { | ||
| 578 | dev_err(adap->pdev_dev, "filter %u setup failed due to full SMT\n", | ||
| 579 | idx); | ||
| 580 | clear_filter(adap, f); | ||
| 581 | } else if (ret == FW_FILTER_WR_FLT_ADDED) { | ||
| 582 | f->smtidx = (be64_to_cpu(rpl->oldval) >> 24) & 0xff; | ||
| 583 | f->pending = 0; /* asynchronous setup completed */ | ||
| 584 | f->valid = 1; | ||
| 585 | } else { | ||
| 586 | /* Something went wrong. Issue a warning about the | ||
| 587 | * problem and clear everything out. | ||
| 588 | */ | ||
| 589 | dev_err(adap->pdev_dev, "filter %u setup failed with error %u\n", | ||
| 590 | idx, ret); | ||
| 591 | clear_filter(adap, f); | ||
| 592 | } | ||
| 593 | } | ||
| 594 | } | ||
| 595 | |||
| 596 | /* Response queue handler for the FW event queue. | ||
| 511 | */ | 597 | */ |
| 512 | static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, | 598 | static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, |
| 513 | const struct pkt_gl *gl) | 599 | const struct pkt_gl *gl) |
| @@ -542,6 +628,10 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, | |||
| 542 | const struct cpl_l2t_write_rpl *p = (void *)rsp; | 628 | const struct cpl_l2t_write_rpl *p = (void *)rsp; |
| 543 | 629 | ||
| 544 | do_l2t_write_rpl(q->adap, p); | 630 | do_l2t_write_rpl(q->adap, p); |
| 631 | } else if (opcode == CPL_SET_TCB_RPL) { | ||
| 632 | const struct cpl_set_tcb_rpl *p = (void *)rsp; | ||
| 633 | |||
| 634 | filter_rpl(q->adap, p); | ||
| 545 | } else | 635 | } else |
| 546 | dev_err(q->adap->pdev_dev, | 636 | dev_err(q->adap->pdev_dev, |
| 547 | "unexpected CPL %#x on FW event queue\n", opcode); | 637 | "unexpected CPL %#x on FW event queue\n", opcode); |
| @@ -983,6 +1073,148 @@ static void t4_free_mem(void *addr) | |||
| 983 | kfree(addr); | 1073 | kfree(addr); |
| 984 | } | 1074 | } |
| 985 | 1075 | ||
| 1076 | /* Send a Work Request to write the filter at a specified index. We construct | ||
| 1077 | * a Firmware Filter Work Request to have the work done and put the indicated | ||
| 1078 | * filter into "pending" mode which will prevent any further actions against | ||
| 1079 | * it till we get a reply from the firmware on the completion status of the | ||
| 1080 | * request. | ||
| 1081 | */ | ||
| 1082 | static int set_filter_wr(struct adapter *adapter, int fidx) | ||
| 1083 | { | ||
| 1084 | struct filter_entry *f = &adapter->tids.ftid_tab[fidx]; | ||
| 1085 | struct sk_buff *skb; | ||
| 1086 | struct fw_filter_wr *fwr; | ||
| 1087 | unsigned int ftid; | ||
| 1088 | |||
| 1089 | /* If the new filter requires loopback Destination MAC and/or VLAN | ||
| 1090 | * rewriting then we need to allocate a Layer 2 Table (L2T) entry for | ||
| 1091 | * the filter. | ||
| 1092 | */ | ||
| 1093 | if (f->fs.newdmac || f->fs.newvlan) { | ||
| 1094 | /* allocate L2T entry for new filter */ | ||
| 1095 | f->l2t = t4_l2t_alloc_switching(adapter->l2t); | ||
| 1096 | if (f->l2t == NULL) | ||
| 1097 | return -EAGAIN; | ||
| 1098 | if (t4_l2t_set_switching(adapter, f->l2t, f->fs.vlan, | ||
| 1099 | f->fs.eport, f->fs.dmac)) { | ||
| 1100 | cxgb4_l2t_release(f->l2t); | ||
| 1101 | f->l2t = NULL; | ||
| 1102 | return -ENOMEM; | ||
| 1103 | } | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | ftid = adapter->tids.ftid_base + fidx; | ||
| 1107 | |||
| 1108 | skb = alloc_skb(sizeof(*fwr), GFP_KERNEL | __GFP_NOFAIL); | ||
| 1109 | fwr = (struct fw_filter_wr *)__skb_put(skb, sizeof(*fwr)); | ||
| 1110 | memset(fwr, 0, sizeof(*fwr)); | ||
| 1111 | |||
| 1112 | /* It would be nice to put most of the following in t4_hw.c but most | ||
| 1113 | * of the work is translating the cxgbtool ch_filter_specification | ||
| 1114 | * into the Work Request and the definition of that structure is | ||
| 1115 | * currently in cxgbtool.h which isn't appropriate to pull into the | ||
| 1116 | * common code. We may eventually try to come up with a more neutral | ||
| 1117 | * filter specification structure but for now it's easiest to simply | ||
| 1118 | * put this fairly direct code in line ... | ||
| 1119 | */ | ||
| 1120 | fwr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR)); | ||
| 1121 | fwr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*fwr)/16)); | ||
| 1122 | fwr->tid_to_iq = | ||
| 1123 | htonl(V_FW_FILTER_WR_TID(ftid) | | ||
| 1124 | V_FW_FILTER_WR_RQTYPE(f->fs.type) | | ||
| 1125 | V_FW_FILTER_WR_NOREPLY(0) | | ||
| 1126 | V_FW_FILTER_WR_IQ(f->fs.iq)); | ||
| 1127 | fwr->del_filter_to_l2tix = | ||
| 1128 | htonl(V_FW_FILTER_WR_RPTTID(f->fs.rpttid) | | ||
| 1129 | V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) | | ||
| 1130 | V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) | | ||
| 1131 | V_FW_FILTER_WR_MASKHASH(f->fs.maskhash) | | ||
| 1132 | V_FW_FILTER_WR_DIRSTEERHASH(f->fs.dirsteerhash) | | ||
| 1133 | V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) | | ||
| 1134 | V_FW_FILTER_WR_DMAC(f->fs.newdmac) | | ||
| 1135 | V_FW_FILTER_WR_SMAC(f->fs.newsmac) | | ||
| 1136 | V_FW_FILTER_WR_INSVLAN(f->fs.newvlan == VLAN_INSERT || | ||
| 1137 | f->fs.newvlan == VLAN_REWRITE) | | ||
| 1138 | V_FW_FILTER_WR_RMVLAN(f->fs.newvlan == VLAN_REMOVE || | ||
| 1139 | f->fs.newvlan == VLAN_REWRITE) | | ||
| 1140 | V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) | | ||
| 1141 | V_FW_FILTER_WR_TXCHAN(f->fs.eport) | | ||
| 1142 | V_FW_FILTER_WR_PRIO(f->fs.prio) | | ||
| 1143 | V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0)); | ||
| 1144 | fwr->ethtype = htons(f->fs.val.ethtype); | ||
| 1145 | fwr->ethtypem = htons(f->fs.mask.ethtype); | ||
| 1146 | fwr->frag_to_ovlan_vldm = | ||
| 1147 | (V_FW_FILTER_WR_FRAG(f->fs.val.frag) | | ||
| 1148 | V_FW_FILTER_WR_FRAGM(f->fs.mask.frag) | | ||
| 1149 | V_FW_FILTER_WR_IVLAN_VLD(f->fs.val.ivlan_vld) | | ||
| 1150 | V_FW_FILTER_WR_OVLAN_VLD(f->fs.val.ovlan_vld) | | ||
| 1151 | V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld) | | ||
| 1152 | V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld)); | ||
| 1153 | fwr->smac_sel = 0; | ||
| 1154 | fwr->rx_chan_rx_rpl_iq = | ||
| 1155 | htons(V_FW_FILTER_WR_RX_CHAN(0) | | ||
| 1156 | V_FW_FILTER_WR_RX_RPL_IQ(adapter->sge.fw_evtq.abs_id)); | ||
| 1157 | fwr->maci_to_matchtypem = | ||
| 1158 | htonl(V_FW_FILTER_WR_MACI(f->fs.val.macidx) | | ||
| 1159 | V_FW_FILTER_WR_MACIM(f->fs.mask.macidx) | | ||
| 1160 | V_FW_FILTER_WR_FCOE(f->fs.val.fcoe) | | ||
| 1161 | V_FW_FILTER_WR_FCOEM(f->fs.mask.fcoe) | | ||
| 1162 | V_FW_FILTER_WR_PORT(f->fs.val.iport) | | ||
| 1163 | V_FW_FILTER_WR_PORTM(f->fs.mask.iport) | | ||
| 1164 | V_FW_FILTER_WR_MATCHTYPE(f->fs.val.matchtype) | | ||
| 1165 | V_FW_FILTER_WR_MATCHTYPEM(f->fs.mask.matchtype)); | ||
| 1166 | fwr->ptcl = f->fs.val.proto; | ||
| 1167 | fwr->ptclm = f->fs.mask.proto; | ||
| 1168 | fwr->ttyp = f->fs.val.tos; | ||
| 1169 | fwr->ttypm = f->fs.mask.tos; | ||
| 1170 | fwr->ivlan = htons(f->fs.val.ivlan); | ||
| 1171 | fwr->ivlanm = htons(f->fs.mask.ivlan); | ||
| 1172 | fwr->ovlan = htons(f->fs.val.ovlan); | ||
| 1173 | fwr->ovlanm = htons(f->fs.mask.ovlan); | ||
| 1174 | memcpy(fwr->lip, f->fs.val.lip, sizeof(fwr->lip)); | ||
| 1175 | memcpy(fwr->lipm, f->fs.mask.lip, sizeof(fwr->lipm)); | ||
| 1176 | memcpy(fwr->fip, f->fs.val.fip, sizeof(fwr->fip)); | ||
| 1177 | memcpy(fwr->fipm, f->fs.mask.fip, sizeof(fwr->fipm)); | ||
| 1178 | fwr->lp = htons(f->fs.val.lport); | ||
| 1179 | fwr->lpm = htons(f->fs.mask.lport); | ||
| 1180 | fwr->fp = htons(f->fs.val.fport); | ||
| 1181 | fwr->fpm = htons(f->fs.mask.fport); | ||
| 1182 | if (f->fs.newsmac) | ||
| 1183 | memcpy(fwr->sma, f->fs.smac, sizeof(fwr->sma)); | ||
| 1184 | |||
| 1185 | /* Mark the filter as "pending" and ship off the Filter Work Request. | ||
| 1186 | * When we get the Work Request Reply we'll clear the pending status. | ||
| 1187 | */ | ||
| 1188 | f->pending = 1; | ||
| 1189 | set_wr_txq(skb, CPL_PRIORITY_CONTROL, f->fs.val.iport & 0x3); | ||
| 1190 | t4_ofld_send(adapter, skb); | ||
| 1191 | return 0; | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | /* Delete the filter at a specified index. | ||
| 1195 | */ | ||
| 1196 | static int del_filter_wr(struct adapter *adapter, int fidx) | ||
| 1197 | { | ||
| 1198 | struct filter_entry *f = &adapter->tids.ftid_tab[fidx]; | ||
| 1199 | struct sk_buff *skb; | ||
| 1200 | struct fw_filter_wr *fwr; | ||
| 1201 | unsigned int len, ftid; | ||
| 1202 | |||
| 1203 | len = sizeof(*fwr); | ||
| 1204 | ftid = adapter->tids.ftid_base + fidx; | ||
| 1205 | |||
| 1206 | skb = alloc_skb(len, GFP_KERNEL | __GFP_NOFAIL); | ||
| 1207 | fwr = (struct fw_filter_wr *)__skb_put(skb, len); | ||
| 1208 | t4_mk_filtdelwr(ftid, fwr, adapter->sge.fw_evtq.abs_id); | ||
| 1209 | |||
| 1210 | /* Mark the filter as "pending" and ship off the Filter Work Request. | ||
| 1211 | * When we get the Work Request Reply we'll clear the pending status. | ||
| 1212 | */ | ||
| 1213 | f->pending = 1; | ||
| 1214 | t4_mgmt_tx(adapter, skb); | ||
| 1215 | return 0; | ||
| 1216 | } | ||
| 1217 | |||
| 986 | static inline int is_offload(const struct adapter *adap) | 1218 | static inline int is_offload(const struct adapter *adap) |
| 987 | { | 1219 | { |
| 988 | return adap->params.offload; | 1220 | return adap->params.offload; |
| @@ -2195,7 +2427,7 @@ int cxgb4_alloc_atid(struct tid_info *t, void *data) | |||
| 2195 | if (t->afree) { | 2427 | if (t->afree) { |
| 2196 | union aopen_entry *p = t->afree; | 2428 | union aopen_entry *p = t->afree; |
| 2197 | 2429 | ||
| 2198 | atid = p - t->atid_tab; | 2430 | atid = (p - t->atid_tab) + t->atid_base; |
| 2199 | t->afree = p->next; | 2431 | t->afree = p->next; |
| 2200 | p->data = data; | 2432 | p->data = data; |
| 2201 | t->atids_in_use++; | 2433 | t->atids_in_use++; |
| @@ -2210,7 +2442,7 @@ EXPORT_SYMBOL(cxgb4_alloc_atid); | |||
| 2210 | */ | 2442 | */ |
| 2211 | void cxgb4_free_atid(struct tid_info *t, unsigned int atid) | 2443 | void cxgb4_free_atid(struct tid_info *t, unsigned int atid) |
| 2212 | { | 2444 | { |
| 2213 | union aopen_entry *p = &t->atid_tab[atid]; | 2445 | union aopen_entry *p = &t->atid_tab[atid - t->atid_base]; |
| 2214 | 2446 | ||
| 2215 | spin_lock_bh(&t->atid_lock); | 2447 | spin_lock_bh(&t->atid_lock); |
| 2216 | p->next = t->afree; | 2448 | p->next = t->afree; |
| @@ -2249,8 +2481,34 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data) | |||
| 2249 | } | 2481 | } |
| 2250 | EXPORT_SYMBOL(cxgb4_alloc_stid); | 2482 | EXPORT_SYMBOL(cxgb4_alloc_stid); |
| 2251 | 2483 | ||
| 2252 | /* | 2484 | /* Allocate a server filter TID and set it to the supplied value. |
| 2253 | * Release a server TID. | 2485 | */ |
| 2486 | int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data) | ||
| 2487 | { | ||
| 2488 | int stid; | ||
| 2489 | |||
| 2490 | spin_lock_bh(&t->stid_lock); | ||
| 2491 | if (family == PF_INET) { | ||
| 2492 | stid = find_next_zero_bit(t->stid_bmap, | ||
| 2493 | t->nstids + t->nsftids, t->nstids); | ||
| 2494 | if (stid < (t->nstids + t->nsftids)) | ||
| 2495 | __set_bit(stid, t->stid_bmap); | ||
| 2496 | else | ||
| 2497 | stid = -1; | ||
| 2498 | } else { | ||
| 2499 | stid = -1; | ||
| 2500 | } | ||
| 2501 | if (stid >= 0) { | ||
| 2502 | t->stid_tab[stid].data = data; | ||
| 2503 | stid += t->stid_base; | ||
| 2504 | t->stids_in_use++; | ||
| 2505 | } | ||
| 2506 | spin_unlock_bh(&t->stid_lock); | ||
| 2507 | return stid; | ||
| 2508 | } | ||
| 2509 | EXPORT_SYMBOL(cxgb4_alloc_sftid); | ||
| 2510 | |||
| 2511 | /* Release a server TID. | ||
| 2254 | */ | 2512 | */ |
| 2255 | void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family) | 2513 | void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family) |
| 2256 | { | 2514 | { |
| @@ -2362,18 +2620,26 @@ EXPORT_SYMBOL(cxgb4_remove_tid); | |||
| 2362 | static int tid_init(struct tid_info *t) | 2620 | static int tid_init(struct tid_info *t) |
| 2363 | { | 2621 | { |
| 2364 | size_t size; | 2622 | size_t size; |
| 2623 | unsigned int stid_bmap_size; | ||
| 2365 | unsigned int natids = t->natids; | 2624 | unsigned int natids = t->natids; |
| 2366 | 2625 | ||
| 2367 | size = t->ntids * sizeof(*t->tid_tab) + natids * sizeof(*t->atid_tab) + | 2626 | stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids); |
| 2627 | size = t->ntids * sizeof(*t->tid_tab) + | ||
| 2628 | natids * sizeof(*t->atid_tab) + | ||
| 2368 | t->nstids * sizeof(*t->stid_tab) + | 2629 | t->nstids * sizeof(*t->stid_tab) + |
| 2369 | BITS_TO_LONGS(t->nstids) * sizeof(long); | 2630 | t->nsftids * sizeof(*t->stid_tab) + |
| 2631 | stid_bmap_size * sizeof(long) + | ||
| 2632 | t->nftids * sizeof(*t->ftid_tab) + | ||
| 2633 | t->nsftids * sizeof(*t->ftid_tab); | ||
| 2634 | |||
| 2370 | t->tid_tab = t4_alloc_mem(size); | 2635 | t->tid_tab = t4_alloc_mem(size); |
| 2371 | if (!t->tid_tab) | 2636 | if (!t->tid_tab) |
| 2372 | return -ENOMEM; | 2637 | return -ENOMEM; |
| 2373 | 2638 | ||
| 2374 | t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids]; | 2639 | t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids]; |
| 2375 | t->stid_tab = (struct serv_entry *)&t->atid_tab[natids]; | 2640 | t->stid_tab = (struct serv_entry *)&t->atid_tab[natids]; |
| 2376 | t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids]; | 2641 | t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids + t->nsftids]; |
| 2642 | t->ftid_tab = (struct filter_entry *)&t->stid_bmap[stid_bmap_size]; | ||
| 2377 | spin_lock_init(&t->stid_lock); | 2643 | spin_lock_init(&t->stid_lock); |
| 2378 | spin_lock_init(&t->atid_lock); | 2644 | spin_lock_init(&t->atid_lock); |
| 2379 | 2645 | ||
| @@ -2388,7 +2654,7 @@ static int tid_init(struct tid_info *t) | |||
| 2388 | t->atid_tab[natids - 1].next = &t->atid_tab[natids]; | 2654 | t->atid_tab[natids - 1].next = &t->atid_tab[natids]; |
| 2389 | t->afree = t->atid_tab; | 2655 | t->afree = t->atid_tab; |
| 2390 | } | 2656 | } |
| 2391 | bitmap_zero(t->stid_bmap, t->nstids); | 2657 | bitmap_zero(t->stid_bmap, t->nstids + t->nsftids); |
| 2392 | return 0; | 2658 | return 0; |
| 2393 | } | 2659 | } |
| 2394 | 2660 | ||
| @@ -2404,7 +2670,8 @@ static int tid_init(struct tid_info *t) | |||
| 2404 | * Returns <0 on error and one of the %NET_XMIT_* values on success. | 2670 | * Returns <0 on error and one of the %NET_XMIT_* values on success. |
| 2405 | */ | 2671 | */ |
| 2406 | int cxgb4_create_server(const struct net_device *dev, unsigned int stid, | 2672 | int cxgb4_create_server(const struct net_device *dev, unsigned int stid, |
| 2407 | __be32 sip, __be16 sport, unsigned int queue) | 2673 | __be32 sip, __be16 sport, __be16 vlan, |
| 2674 | unsigned int queue) | ||
| 2408 | { | 2675 | { |
| 2409 | unsigned int chan; | 2676 | unsigned int chan; |
| 2410 | struct sk_buff *skb; | 2677 | struct sk_buff *skb; |
| @@ -2750,6 +3017,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld) | |||
| 2750 | { | 3017 | { |
| 2751 | void *handle; | 3018 | void *handle; |
| 2752 | struct cxgb4_lld_info lli; | 3019 | struct cxgb4_lld_info lli; |
| 3020 | unsigned short i; | ||
| 2753 | 3021 | ||
| 2754 | lli.pdev = adap->pdev; | 3022 | lli.pdev = adap->pdev; |
| 2755 | lli.l2t = adap->l2t; | 3023 | lli.l2t = adap->l2t; |
| @@ -2776,10 +3044,16 @@ static void uld_attach(struct adapter *adap, unsigned int uld) | |||
| 2776 | lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET( | 3044 | lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET( |
| 2777 | t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >> | 3045 | t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >> |
| 2778 | (adap->fn * 4)); | 3046 | (adap->fn * 4)); |
| 3047 | lli.filt_mode = adap->filter_mode; | ||
| 3048 | /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */ | ||
| 3049 | for (i = 0; i < NCHAN; i++) | ||
| 3050 | lli.tx_modq[i] = i; | ||
| 2779 | lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS); | 3051 | lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS); |
| 2780 | lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL); | 3052 | lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL); |
| 2781 | lli.fw_vers = adap->params.fw_vers; | 3053 | lli.fw_vers = adap->params.fw_vers; |
| 2782 | lli.dbfifo_int_thresh = dbfifo_int_thresh; | 3054 | lli.dbfifo_int_thresh = dbfifo_int_thresh; |
| 3055 | lli.sge_pktshift = adap->sge.pktshift; | ||
| 3056 | lli.enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN; | ||
| 2783 | 3057 | ||
| 2784 | handle = ulds[uld].add(&lli); | 3058 | handle = ulds[uld].add(&lli); |
| 2785 | if (IS_ERR(handle)) { | 3059 | if (IS_ERR(handle)) { |
| @@ -2999,6 +3273,126 @@ static int cxgb_close(struct net_device *dev) | |||
| 2999 | return t4_enable_vi(adapter, adapter->fn, pi->viid, false, false); | 3273 | return t4_enable_vi(adapter, adapter->fn, pi->viid, false, false); |
| 3000 | } | 3274 | } |
| 3001 | 3275 | ||
| 3276 | /* Return an error number if the indicated filter isn't writable ... | ||
| 3277 | */ | ||
| 3278 | static int writable_filter(struct filter_entry *f) | ||
| 3279 | { | ||
| 3280 | if (f->locked) | ||
| 3281 | return -EPERM; | ||
| 3282 | if (f->pending) | ||
| 3283 | return -EBUSY; | ||
| 3284 | |||
| 3285 | return 0; | ||
| 3286 | } | ||
| 3287 | |||
| 3288 | /* Delete the filter at the specified index (if valid). The checks for all | ||
| 3289 | * the common problems with doing this like the filter being locked, currently | ||
| 3290 | * pending in another operation, etc. | ||
| 3291 | */ | ||
| 3292 | static int delete_filter(struct adapter *adapter, unsigned int fidx) | ||
| 3293 | { | ||
| 3294 | struct filter_entry *f; | ||
| 3295 | int ret; | ||
| 3296 | |||
| 3297 | if (fidx >= adapter->tids.nftids + adapter->tids.nsftids) | ||
| 3298 | return -EINVAL; | ||
| 3299 | |||
| 3300 | f = &adapter->tids.ftid_tab[fidx]; | ||
| 3301 | ret = writable_filter(f); | ||
| 3302 | if (ret) | ||
| 3303 | return ret; | ||
| 3304 | if (f->valid) | ||
| 3305 | return del_filter_wr(adapter, fidx); | ||
| 3306 | |||
| 3307 | return 0; | ||
| 3308 | } | ||
| 3309 | |||
| 3310 | int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid, | ||
| 3311 | __be32 sip, __be16 sport, __be16 vlan, | ||
| 3312 | unsigned int queue, unsigned char port, unsigned char mask) | ||
| 3313 | { | ||
| 3314 | int ret; | ||
| 3315 | struct filter_entry *f; | ||
| 3316 | struct adapter *adap; | ||
| 3317 | int i; | ||
| 3318 | u8 *val; | ||
| 3319 | |||
| 3320 | adap = netdev2adap(dev); | ||
| 3321 | |||
| 3322 | /* Adjust stid to correct filter index */ | ||
| 3323 | stid -= adap->tids.nstids; | ||
| 3324 | stid += adap->tids.nftids; | ||
| 3325 | |||
| 3326 | /* Check to make sure the filter requested is writable ... | ||
| 3327 | */ | ||
| 3328 | f = &adap->tids.ftid_tab[stid]; | ||
| 3329 | ret = writable_filter(f); | ||
| 3330 | if (ret) | ||
| 3331 | return ret; | ||
| 3332 | |||
| 3333 | /* Clear out any old resources being used by the filter before | ||
| 3334 | * we start constructing the new filter. | ||
| 3335 | */ | ||
| 3336 | if (f->valid) | ||
| 3337 | clear_filter(adap, f); | ||
| 3338 | |||
| 3339 | /* Clear out filter specifications */ | ||
| 3340 | memset(&f->fs, 0, sizeof(struct ch_filter_specification)); | ||
| 3341 | f->fs.val.lport = cpu_to_be16(sport); | ||
| 3342 | f->fs.mask.lport = ~0; | ||
| 3343 | val = (u8 *)&sip; | ||
| 3344 | if ((val[0] | val[1] | val[2] | val[3]) != 0) { | ||
| 3345 | for (i = 0; i < 4; i++) { | ||
| 3346 | f->fs.val.lip[i] = val[i]; | ||
| 3347 | f->fs.mask.lip[i] = ~0; | ||
| 3348 | } | ||
| 3349 | if (adap->filter_mode & F_PORT) { | ||
| 3350 | f->fs.val.iport = port; | ||
| 3351 | f->fs.mask.iport = mask; | ||
| 3352 | } | ||
| 3353 | } | ||
| 3354 | |||
| 3355 | f->fs.dirsteer = 1; | ||
| 3356 | f->fs.iq = queue; | ||
| 3357 | /* Mark filter as locked */ | ||
| 3358 | f->locked = 1; | ||
| 3359 | f->fs.rpttid = 1; | ||
| 3360 | |||
| 3361 | ret = set_filter_wr(adap, stid); | ||
| 3362 | if (ret) { | ||
| 3363 | clear_filter(adap, f); | ||
| 3364 | return ret; | ||
| 3365 | } | ||
| 3366 | |||
| 3367 | return 0; | ||
| 3368 | } | ||
| 3369 | EXPORT_SYMBOL(cxgb4_create_server_filter); | ||
| 3370 | |||
| 3371 | int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid, | ||
| 3372 | unsigned int queue, bool ipv6) | ||
| 3373 | { | ||
| 3374 | int ret; | ||
| 3375 | struct filter_entry *f; | ||
| 3376 | struct adapter *adap; | ||
| 3377 | |||
| 3378 | adap = netdev2adap(dev); | ||
| 3379 | |||
| 3380 | /* Adjust stid to correct filter index */ | ||
| 3381 | stid -= adap->tids.nstids; | ||
| 3382 | stid += adap->tids.nftids; | ||
| 3383 | |||
| 3384 | f = &adap->tids.ftid_tab[stid]; | ||
| 3385 | /* Unlock the filter */ | ||
| 3386 | f->locked = 0; | ||
| 3387 | |||
| 3388 | ret = delete_filter(adap, stid); | ||
| 3389 | if (ret) | ||
| 3390 | return ret; | ||
| 3391 | |||
| 3392 | return 0; | ||
| 3393 | } | ||
| 3394 | EXPORT_SYMBOL(cxgb4_remove_server_filter); | ||
| 3395 | |||
| 3002 | static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev, | 3396 | static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev, |
| 3003 | struct rtnl_link_stats64 *ns) | 3397 | struct rtnl_link_stats64 *ns) |
| 3004 | { | 3398 | { |
| @@ -3245,6 +3639,34 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c) | |||
| 3245 | v = t4_read_reg(adap, TP_PIO_DATA); | 3639 | v = t4_read_reg(adap, TP_PIO_DATA); |
| 3246 | t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR); | 3640 | t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR); |
| 3247 | 3641 | ||
| 3642 | /* first 4 Tx modulation queues point to consecutive Tx channels */ | ||
| 3643 | adap->params.tp.tx_modq_map = 0xE4; | ||
| 3644 | t4_write_reg(adap, A_TP_TX_MOD_QUEUE_REQ_MAP, | ||
| 3645 | V_TX_MOD_QUEUE_REQ_MAP(adap->params.tp.tx_modq_map)); | ||
| 3646 | |||
| 3647 | /* associate each Tx modulation queue with consecutive Tx channels */ | ||
| 3648 | v = 0x84218421; | ||
| 3649 | t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, | ||
| 3650 | &v, 1, A_TP_TX_SCHED_HDR); | ||
| 3651 | t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, | ||
| 3652 | &v, 1, A_TP_TX_SCHED_FIFO); | ||
| 3653 | t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, | ||
| 3654 | &v, 1, A_TP_TX_SCHED_PCMD); | ||
| 3655 | |||
| 3656 | #define T4_TX_MODQ_10G_WEIGHT_DEFAULT 16 /* in KB units */ | ||
| 3657 | if (is_offload(adap)) { | ||
| 3658 | t4_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, | ||
| 3659 | V_TX_MODQ_WEIGHT0(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
| 3660 | V_TX_MODQ_WEIGHT1(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
| 3661 | V_TX_MODQ_WEIGHT2(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
| 3662 | V_TX_MODQ_WEIGHT3(T4_TX_MODQ_10G_WEIGHT_DEFAULT)); | ||
| 3663 | t4_write_reg(adap, A_TP_TX_MOD_CHANNEL_WEIGHT, | ||
| 3664 | V_TX_MODQ_WEIGHT0(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
| 3665 | V_TX_MODQ_WEIGHT1(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
| 3666 | V_TX_MODQ_WEIGHT2(T4_TX_MODQ_10G_WEIGHT_DEFAULT) | | ||
| 3667 | V_TX_MODQ_WEIGHT3(T4_TX_MODQ_10G_WEIGHT_DEFAULT)); | ||
| 3668 | } | ||
| 3669 | |||
| 3248 | /* get basic stuff going */ | 3670 | /* get basic stuff going */ |
| 3249 | return t4_early_init(adap, adap->fn); | 3671 | return t4_early_init(adap, adap->fn); |
| 3250 | } | 3672 | } |
| @@ -4035,6 +4457,10 @@ static int adap_init0(struct adapter *adap) | |||
| 4035 | for (j = 0; j < NCHAN; j++) | 4457 | for (j = 0; j < NCHAN; j++) |
| 4036 | adap->params.tp.tx_modq[j] = j; | 4458 | adap->params.tp.tx_modq[j] = j; |
| 4037 | 4459 | ||
| 4460 | t4_read_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA, | ||
| 4461 | &adap->filter_mode, 1, | ||
| 4462 | TP_VLAN_PRI_MAP); | ||
| 4463 | |||
| 4038 | adap->flags |= FW_OK; | 4464 | adap->flags |= FW_OK; |
| 4039 | return 0; | 4465 | return 0; |
| 4040 | 4466 | ||
| @@ -4661,6 +5087,17 @@ static void remove_one(struct pci_dev *pdev) | |||
| 4661 | if (adapter->debugfs_root) | 5087 | if (adapter->debugfs_root) |
| 4662 | debugfs_remove_recursive(adapter->debugfs_root); | 5088 | debugfs_remove_recursive(adapter->debugfs_root); |
| 4663 | 5089 | ||
| 5090 | /* If we allocated filters, free up state associated with any | ||
| 5091 | * valid filters ... | ||
| 5092 | */ | ||
| 5093 | if (adapter->tids.ftid_tab) { | ||
| 5094 | struct filter_entry *f = &adapter->tids.ftid_tab[0]; | ||
| 5095 | for (i = 0; i < (adapter->tids.nftids + | ||
| 5096 | adapter->tids.nsftids); i++, f++) | ||
| 5097 | if (f->valid) | ||
| 5098 | clear_filter(adapter, f); | ||
| 5099 | } | ||
| 5100 | |||
| 4664 | if (adapter->flags & FULL_INIT_DONE) | 5101 | if (adapter->flags & FULL_INIT_DONE) |
| 4665 | cxgb_down(adapter); | 5102 | cxgb_down(adapter); |
| 4666 | 5103 | ||
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 39bec73ff87c..e2bbc7f3e2de 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/cache.h> | 38 | #include <linux/cache.h> |
| 39 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
| 40 | #include <linux/skbuff.h> | 40 | #include <linux/skbuff.h> |
| 41 | #include <linux/inetdevice.h> | ||
| 41 | #include <linux/atomic.h> | 42 | #include <linux/atomic.h> |
| 42 | 43 | ||
| 43 | /* CPL message priority levels */ | 44 | /* CPL message priority levels */ |
| @@ -97,7 +98,9 @@ struct tid_info { | |||
| 97 | 98 | ||
| 98 | union aopen_entry *atid_tab; | 99 | union aopen_entry *atid_tab; |
| 99 | unsigned int natids; | 100 | unsigned int natids; |
| 101 | unsigned int atid_base; | ||
| 100 | 102 | ||
| 103 | struct filter_entry *ftid_tab; | ||
| 101 | unsigned int nftids; | 104 | unsigned int nftids; |
| 102 | unsigned int ftid_base; | 105 | unsigned int ftid_base; |
| 103 | unsigned int aftid_base; | 106 | unsigned int aftid_base; |
| @@ -129,7 +132,7 @@ static inline void *lookup_atid(const struct tid_info *t, unsigned int atid) | |||
| 129 | static inline void *lookup_stid(const struct tid_info *t, unsigned int stid) | 132 | static inline void *lookup_stid(const struct tid_info *t, unsigned int stid) |
| 130 | { | 133 | { |
| 131 | stid -= t->stid_base; | 134 | stid -= t->stid_base; |
| 132 | return stid < t->nstids ? t->stid_tab[stid].data : NULL; | 135 | return stid < (t->nstids + t->nsftids) ? t->stid_tab[stid].data : NULL; |
| 133 | } | 136 | } |
| 134 | 137 | ||
| 135 | static inline void cxgb4_insert_tid(struct tid_info *t, void *data, | 138 | static inline void cxgb4_insert_tid(struct tid_info *t, void *data, |
| @@ -141,6 +144,7 @@ static inline void cxgb4_insert_tid(struct tid_info *t, void *data, | |||
| 141 | 144 | ||
| 142 | int cxgb4_alloc_atid(struct tid_info *t, void *data); | 145 | int cxgb4_alloc_atid(struct tid_info *t, void *data); |
| 143 | int cxgb4_alloc_stid(struct tid_info *t, int family, void *data); | 146 | int cxgb4_alloc_stid(struct tid_info *t, int family, void *data); |
| 147 | int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data); | ||
| 144 | void cxgb4_free_atid(struct tid_info *t, unsigned int atid); | 148 | void cxgb4_free_atid(struct tid_info *t, unsigned int atid); |
| 145 | void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family); | 149 | void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family); |
| 146 | void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid); | 150 | void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid); |
| @@ -148,8 +152,14 @@ void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid); | |||
| 148 | struct in6_addr; | 152 | struct in6_addr; |
| 149 | 153 | ||
| 150 | int cxgb4_create_server(const struct net_device *dev, unsigned int stid, | 154 | int cxgb4_create_server(const struct net_device *dev, unsigned int stid, |
| 151 | __be32 sip, __be16 sport, unsigned int queue); | 155 | __be32 sip, __be16 sport, __be16 vlan, |
| 152 | 156 | unsigned int queue); | |
| 157 | int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid, | ||
| 158 | __be32 sip, __be16 sport, __be16 vlan, | ||
| 159 | unsigned int queue, | ||
| 160 | unsigned char port, unsigned char mask); | ||
| 161 | int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid, | ||
| 162 | unsigned int queue, bool ipv6); | ||
| 153 | static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue) | 163 | static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue) |
| 154 | { | 164 | { |
| 155 | skb_set_queue_mapping(skb, (queue << 1) | prio); | 165 | skb_set_queue_mapping(skb, (queue << 1) | prio); |
| @@ -221,9 +231,16 @@ struct cxgb4_lld_info { | |||
| 221 | unsigned int iscsi_iolen; /* iSCSI max I/O length */ | 231 | unsigned int iscsi_iolen; /* iSCSI max I/O length */ |
| 222 | unsigned short udb_density; /* # of user DB/page */ | 232 | unsigned short udb_density; /* # of user DB/page */ |
| 223 | unsigned short ucq_density; /* # of user CQs/page */ | 233 | unsigned short ucq_density; /* # of user CQs/page */ |
| 234 | unsigned short filt_mode; /* filter optional components */ | ||
| 235 | unsigned short tx_modq[NCHAN]; /* maps each tx channel to a */ | ||
| 236 | /* scheduler queue */ | ||
| 224 | void __iomem *gts_reg; /* address of GTS register */ | 237 | void __iomem *gts_reg; /* address of GTS register */ |
| 225 | void __iomem *db_reg; /* address of kernel doorbell */ | 238 | void __iomem *db_reg; /* address of kernel doorbell */ |
| 226 | int dbfifo_int_thresh; /* doorbell fifo int threshold */ | 239 | int dbfifo_int_thresh; /* doorbell fifo int threshold */ |
| 240 | unsigned int sge_pktshift; /* Padding between CPL and */ | ||
| 241 | /* packet data */ | ||
| 242 | bool enable_fw_ofld_conn; /* Enable connection through fw */ | ||
| 243 | /* WR */ | ||
| 227 | }; | 244 | }; |
| 228 | 245 | ||
| 229 | struct cxgb4_uld_info { | 246 | struct cxgb4_uld_info { |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c index 6ac77a62f361..29878098101e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c +++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c | |||
| @@ -484,6 +484,38 @@ void t4_l2t_update(struct adapter *adap, struct neighbour *neigh) | |||
| 484 | handle_failed_resolution(adap, arpq); | 484 | handle_failed_resolution(adap, arpq); |
| 485 | } | 485 | } |
| 486 | 486 | ||
| 487 | /* Allocate an L2T entry for use by a switching rule. Such need to be | ||
| 488 | * explicitly freed and while busy they are not on any hash chain, so normal | ||
| 489 | * address resolution updates do not see them. | ||
| 490 | */ | ||
| 491 | struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d) | ||
| 492 | { | ||
| 493 | struct l2t_entry *e; | ||
| 494 | |||
| 495 | write_lock_bh(&d->lock); | ||
| 496 | e = alloc_l2e(d); | ||
| 497 | if (e) { | ||
| 498 | spin_lock(&e->lock); /* avoid race with t4_l2t_free */ | ||
| 499 | e->state = L2T_STATE_SWITCHING; | ||
| 500 | atomic_set(&e->refcnt, 1); | ||
| 501 | spin_unlock(&e->lock); | ||
| 502 | } | ||
| 503 | write_unlock_bh(&d->lock); | ||
| 504 | return e; | ||
| 505 | } | ||
| 506 | |||
| 507 | /* Sets/updates the contents of a switching L2T entry that has been allocated | ||
| 508 | * with an earlier call to @t4_l2t_alloc_switching. | ||
| 509 | */ | ||
| 510 | int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan, | ||
| 511 | u8 port, u8 *eth_addr) | ||
| 512 | { | ||
| 513 | e->vlan = vlan; | ||
| 514 | e->lport = port; | ||
| 515 | memcpy(e->dmac, eth_addr, ETH_ALEN); | ||
| 516 | return write_l2e(adap, e, 0); | ||
| 517 | } | ||
| 518 | |||
| 487 | struct l2t_data *t4_init_l2t(void) | 519 | struct l2t_data *t4_init_l2t(void) |
| 488 | { | 520 | { |
| 489 | int i; | 521 | int i; |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.h b/drivers/net/ethernet/chelsio/cxgb4/l2t.h index 02b31d0c6410..108c0f1fce1c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/l2t.h +++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.h | |||
| @@ -100,6 +100,9 @@ struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh, | |||
| 100 | unsigned int priority); | 100 | unsigned int priority); |
| 101 | 101 | ||
| 102 | void t4_l2t_update(struct adapter *adap, struct neighbour *neigh); | 102 | void t4_l2t_update(struct adapter *adap, struct neighbour *neigh); |
| 103 | struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *d); | ||
| 104 | int t4_l2t_set_switching(struct adapter *adap, struct l2t_entry *e, u16 vlan, | ||
| 105 | u8 port, u8 *eth_addr); | ||
| 103 | struct l2t_data *t4_init_l2t(void); | 106 | struct l2t_data *t4_init_l2t(void); |
| 104 | void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl); | 107 | void do_l2t_write_rpl(struct adapter *p, const struct cpl_l2t_write_rpl *rpl); |
| 105 | 108 | ||
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 8d9c7547b070..22f3af5166bf 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | |||
| @@ -109,7 +109,7 @@ void t4_set_reg_field(struct adapter *adapter, unsigned int addr, u32 mask, | |||
| 109 | * Reads registers that are accessed indirectly through an address/data | 109 | * Reads registers that are accessed indirectly through an address/data |
| 110 | * register pair. | 110 | * register pair. |
| 111 | */ | 111 | */ |
| 112 | static void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, | 112 | void t4_read_indirect(struct adapter *adap, unsigned int addr_reg, |
| 113 | unsigned int data_reg, u32 *vals, | 113 | unsigned int data_reg, u32 *vals, |
| 114 | unsigned int nregs, unsigned int start_idx) | 114 | unsigned int nregs, unsigned int start_idx) |
| 115 | { | 115 | { |
| @@ -2268,6 +2268,26 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map, | |||
| 2268 | return 0; | 2268 | return 0; |
| 2269 | } | 2269 | } |
| 2270 | 2270 | ||
| 2271 | /* t4_mk_filtdelwr - create a delete filter WR | ||
| 2272 | * @ftid: the filter ID | ||
| 2273 | * @wr: the filter work request to populate | ||
| 2274 | * @qid: ingress queue to receive the delete notification | ||
| 2275 | * | ||
| 2276 | * Creates a filter work request to delete the supplied filter. If @qid is | ||
| 2277 | * negative the delete notification is suppressed. | ||
| 2278 | */ | ||
| 2279 | void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid) | ||
| 2280 | { | ||
| 2281 | memset(wr, 0, sizeof(*wr)); | ||
| 2282 | wr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR)); | ||
| 2283 | wr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*wr) / 16)); | ||
| 2284 | wr->tid_to_iq = htonl(V_FW_FILTER_WR_TID(ftid) | | ||
| 2285 | V_FW_FILTER_WR_NOREPLY(qid < 0)); | ||
| 2286 | wr->del_filter_to_l2tix = htonl(F_FW_FILTER_WR_DEL_FILTER); | ||
| 2287 | if (qid >= 0) | ||
| 2288 | wr->rx_chan_rx_rpl_iq = htons(V_FW_FILTER_WR_RX_RPL_IQ(qid)); | ||
| 2289 | } | ||
| 2290 | |||
| 2271 | #define INIT_CMD(var, cmd, rd_wr) do { \ | 2291 | #define INIT_CMD(var, cmd, rd_wr) do { \ |
| 2272 | (var).op_to_write = htonl(FW_CMD_OP(FW_##cmd##_CMD) | \ | 2292 | (var).op_to_write = htonl(FW_CMD_OP(FW_##cmd##_CMD) | \ |
| 2273 | FW_CMD_REQUEST | FW_CMD_##rd_wr); \ | 2293 | FW_CMD_REQUEST | FW_CMD_##rd_wr); \ |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h index b760808fd6d9..261d17703adc 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | |||
| @@ -193,8 +193,24 @@ struct work_request_hdr { | |||
| 193 | __be64 wr_lo; | 193 | __be64 wr_lo; |
| 194 | }; | 194 | }; |
| 195 | 195 | ||
| 196 | /* wr_hi fields */ | ||
| 197 | #define S_WR_OP 24 | ||
| 198 | #define V_WR_OP(x) ((__u64)(x) << S_WR_OP) | ||
| 199 | |||
| 196 | #define WR_HDR struct work_request_hdr wr | 200 | #define WR_HDR struct work_request_hdr wr |
| 197 | 201 | ||
| 202 | /* option 0 fields */ | ||
| 203 | #define S_MSS_IDX 60 | ||
| 204 | #define M_MSS_IDX 0xF | ||
| 205 | #define V_MSS_IDX(x) ((__u64)(x) << S_MSS_IDX) | ||
| 206 | #define G_MSS_IDX(x) (((x) >> S_MSS_IDX) & M_MSS_IDX) | ||
| 207 | |||
| 208 | /* option 2 fields */ | ||
| 209 | #define S_RSS_QUEUE 0 | ||
| 210 | #define M_RSS_QUEUE 0x3FF | ||
| 211 | #define V_RSS_QUEUE(x) ((x) << S_RSS_QUEUE) | ||
| 212 | #define G_RSS_QUEUE(x) (((x) >> S_RSS_QUEUE) & M_RSS_QUEUE) | ||
| 213 | |||
| 198 | struct cpl_pass_open_req { | 214 | struct cpl_pass_open_req { |
| 199 | WR_HDR; | 215 | WR_HDR; |
| 200 | union opcode_tid ot; | 216 | union opcode_tid ot; |
| @@ -204,12 +220,14 @@ struct cpl_pass_open_req { | |||
| 204 | __be32 peer_ip; | 220 | __be32 peer_ip; |
| 205 | __be64 opt0; | 221 | __be64 opt0; |
| 206 | #define TX_CHAN(x) ((x) << 2) | 222 | #define TX_CHAN(x) ((x) << 2) |
| 223 | #define NO_CONG(x) ((x) << 4) | ||
| 207 | #define DELACK(x) ((x) << 5) | 224 | #define DELACK(x) ((x) << 5) |
| 208 | #define ULP_MODE(x) ((x) << 8) | 225 | #define ULP_MODE(x) ((x) << 8) |
| 209 | #define RCV_BUFSIZ(x) ((x) << 12) | 226 | #define RCV_BUFSIZ(x) ((x) << 12) |
| 210 | #define DSCP(x) ((x) << 22) | 227 | #define DSCP(x) ((x) << 22) |
| 211 | #define SMAC_SEL(x) ((u64)(x) << 28) | 228 | #define SMAC_SEL(x) ((u64)(x) << 28) |
| 212 | #define L2T_IDX(x) ((u64)(x) << 36) | 229 | #define L2T_IDX(x) ((u64)(x) << 36) |
| 230 | #define TCAM_BYPASS(x) ((u64)(x) << 48) | ||
| 213 | #define NAGLE(x) ((u64)(x) << 49) | 231 | #define NAGLE(x) ((u64)(x) << 49) |
| 214 | #define WND_SCALE(x) ((u64)(x) << 50) | 232 | #define WND_SCALE(x) ((u64)(x) << 50) |
| 215 | #define KEEP_ALIVE(x) ((u64)(x) << 54) | 233 | #define KEEP_ALIVE(x) ((u64)(x) << 54) |
| @@ -247,8 +265,10 @@ struct cpl_pass_accept_rpl { | |||
| 247 | #define RSS_QUEUE_VALID (1 << 10) | 265 | #define RSS_QUEUE_VALID (1 << 10) |
| 248 | #define RX_COALESCE_VALID(x) ((x) << 11) | 266 | #define RX_COALESCE_VALID(x) ((x) << 11) |
| 249 | #define RX_COALESCE(x) ((x) << 12) | 267 | #define RX_COALESCE(x) ((x) << 12) |
| 268 | #define PACE(x) ((x) << 16) | ||
| 250 | #define TX_QUEUE(x) ((x) << 23) | 269 | #define TX_QUEUE(x) ((x) << 23) |
| 251 | #define RX_CHANNEL(x) ((x) << 26) | 270 | #define RX_CHANNEL(x) ((x) << 26) |
| 271 | #define CCTRL_ECN(x) ((x) << 27) | ||
| 252 | #define WND_SCALE_EN(x) ((x) << 28) | 272 | #define WND_SCALE_EN(x) ((x) << 28) |
| 253 | #define TSTAMPS_EN(x) ((x) << 29) | 273 | #define TSTAMPS_EN(x) ((x) << 29) |
| 254 | #define SACK_EN(x) ((x) << 30) | 274 | #define SACK_EN(x) ((x) << 30) |
| @@ -292,6 +312,9 @@ struct cpl_pass_establish { | |||
| 292 | union opcode_tid ot; | 312 | union opcode_tid ot; |
| 293 | __be32 rsvd; | 313 | __be32 rsvd; |
| 294 | __be32 tos_stid; | 314 | __be32 tos_stid; |
| 315 | #define PASS_OPEN_TID(x) ((x) << 0) | ||
| 316 | #define PASS_OPEN_TOS(x) ((x) << 24) | ||
| 317 | #define GET_PASS_OPEN_TID(x) (((x) >> 0) & 0xFFFFFF) | ||
| 295 | #define GET_POPEN_TID(x) ((x) & 0xffffff) | 318 | #define GET_POPEN_TID(x) ((x) & 0xffffff) |
| 296 | #define GET_POPEN_TOS(x) (((x) >> 24) & 0xff) | 319 | #define GET_POPEN_TOS(x) (((x) >> 24) & 0xff) |
| 297 | __be16 mac_idx; | 320 | __be16 mac_idx; |
| @@ -332,6 +355,7 @@ struct cpl_set_tcb_field { | |||
| 332 | __be16 word_cookie; | 355 | __be16 word_cookie; |
| 333 | #define TCB_WORD(x) ((x) << 0) | 356 | #define TCB_WORD(x) ((x) << 0) |
| 334 | #define TCB_COOKIE(x) ((x) << 5) | 357 | #define TCB_COOKIE(x) ((x) << 5) |
| 358 | #define GET_TCB_COOKIE(x) (((x) >> 5) & 7) | ||
| 335 | __be64 mask; | 359 | __be64 mask; |
| 336 | __be64 val; | 360 | __be64 val; |
| 337 | }; | 361 | }; |
| @@ -536,6 +560,37 @@ struct cpl_rx_pkt { | |||
| 536 | __be16 err_vec; | 560 | __be16 err_vec; |
| 537 | }; | 561 | }; |
| 538 | 562 | ||
| 563 | /* rx_pkt.l2info fields */ | ||
| 564 | #define S_RX_ETHHDR_LEN 0 | ||
| 565 | #define M_RX_ETHHDR_LEN 0x1F | ||
| 566 | #define V_RX_ETHHDR_LEN(x) ((x) << S_RX_ETHHDR_LEN) | ||
| 567 | #define G_RX_ETHHDR_LEN(x) (((x) >> S_RX_ETHHDR_LEN) & M_RX_ETHHDR_LEN) | ||
| 568 | |||
| 569 | #define S_RX_MACIDX 8 | ||
| 570 | #define M_RX_MACIDX 0x1FF | ||
| 571 | #define V_RX_MACIDX(x) ((x) << S_RX_MACIDX) | ||
| 572 | #define G_RX_MACIDX(x) (((x) >> S_RX_MACIDX) & M_RX_MACIDX) | ||
| 573 | |||
| 574 | #define S_RXF_SYN 21 | ||
| 575 | #define V_RXF_SYN(x) ((x) << S_RXF_SYN) | ||
| 576 | #define F_RXF_SYN V_RXF_SYN(1U) | ||
| 577 | |||
| 578 | #define S_RX_CHAN 28 | ||
| 579 | #define M_RX_CHAN 0xF | ||
| 580 | #define V_RX_CHAN(x) ((x) << S_RX_CHAN) | ||
| 581 | #define G_RX_CHAN(x) (((x) >> S_RX_CHAN) & M_RX_CHAN) | ||
| 582 | |||
| 583 | /* rx_pkt.hdr_len fields */ | ||
| 584 | #define S_RX_TCPHDR_LEN 0 | ||
| 585 | #define M_RX_TCPHDR_LEN 0x3F | ||
| 586 | #define V_RX_TCPHDR_LEN(x) ((x) << S_RX_TCPHDR_LEN) | ||
| 587 | #define G_RX_TCPHDR_LEN(x) (((x) >> S_RX_TCPHDR_LEN) & M_RX_TCPHDR_LEN) | ||
| 588 | |||
| 589 | #define S_RX_IPHDR_LEN 6 | ||
| 590 | #define M_RX_IPHDR_LEN 0x3FF | ||
| 591 | #define V_RX_IPHDR_LEN(x) ((x) << S_RX_IPHDR_LEN) | ||
| 592 | #define G_RX_IPHDR_LEN(x) (((x) >> S_RX_IPHDR_LEN) & M_RX_IPHDR_LEN) | ||
| 593 | |||
| 539 | struct cpl_trace_pkt { | 594 | struct cpl_trace_pkt { |
| 540 | u8 opcode; | 595 | u8 opcode; |
| 541 | u8 intf; | 596 | u8 intf; |
| @@ -634,6 +689,17 @@ struct cpl_fw6_msg { | |||
| 634 | /* cpl_fw6_msg.type values */ | 689 | /* cpl_fw6_msg.type values */ |
| 635 | enum { | 690 | enum { |
| 636 | FW6_TYPE_CMD_RPL = 0, | 691 | FW6_TYPE_CMD_RPL = 0, |
| 692 | FW6_TYPE_WR_RPL = 1, | ||
| 693 | FW6_TYPE_CQE = 2, | ||
| 694 | FW6_TYPE_OFLD_CONNECTION_WR_RPL = 3, | ||
| 695 | }; | ||
| 696 | |||
| 697 | struct cpl_fw6_msg_ofld_connection_wr_rpl { | ||
| 698 | __u64 cookie; | ||
| 699 | __be32 tid; /* or atid in case of active failure */ | ||
| 700 | __u8 t_state; | ||
| 701 | __u8 retval; | ||
| 702 | __u8 rsvd[2]; | ||
| 637 | }; | 703 | }; |
| 638 | 704 | ||
| 639 | enum { | 705 | enum { |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h index 75393f5cff41..83ec5f7844ac 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | |||
| @@ -1064,4 +1064,41 @@ | |||
| 1064 | #define ADDRESS(x) ((x) << ADDRESS_SHIFT) | 1064 | #define ADDRESS(x) ((x) << ADDRESS_SHIFT) |
| 1065 | 1065 | ||
| 1066 | #define XGMAC_PORT_INT_CAUSE 0x10dc | 1066 | #define XGMAC_PORT_INT_CAUSE 0x10dc |
| 1067 | |||
| 1068 | #define A_TP_TX_MOD_QUEUE_REQ_MAP 0x7e28 | ||
| 1069 | |||
| 1070 | #define A_TP_TX_MOD_CHANNEL_WEIGHT 0x7e34 | ||
| 1071 | |||
| 1072 | #define S_TX_MOD_QUEUE_REQ_MAP 0 | ||
| 1073 | #define M_TX_MOD_QUEUE_REQ_MAP 0xffffU | ||
| 1074 | #define V_TX_MOD_QUEUE_REQ_MAP(x) ((x) << S_TX_MOD_QUEUE_REQ_MAP) | ||
| 1075 | |||
| 1076 | #define A_TP_TX_MOD_QUEUE_WEIGHT0 0x7e30 | ||
| 1077 | |||
| 1078 | #define S_TX_MODQ_WEIGHT3 24 | ||
| 1079 | #define M_TX_MODQ_WEIGHT3 0xffU | ||
| 1080 | #define V_TX_MODQ_WEIGHT3(x) ((x) << S_TX_MODQ_WEIGHT3) | ||
| 1081 | |||
| 1082 | #define S_TX_MODQ_WEIGHT2 16 | ||
| 1083 | #define M_TX_MODQ_WEIGHT2 0xffU | ||
| 1084 | #define V_TX_MODQ_WEIGHT2(x) ((x) << S_TX_MODQ_WEIGHT2) | ||
| 1085 | |||
| 1086 | #define S_TX_MODQ_WEIGHT1 8 | ||
| 1087 | #define M_TX_MODQ_WEIGHT1 0xffU | ||
| 1088 | #define V_TX_MODQ_WEIGHT1(x) ((x) << S_TX_MODQ_WEIGHT1) | ||
| 1089 | |||
| 1090 | #define S_TX_MODQ_WEIGHT0 0 | ||
| 1091 | #define M_TX_MODQ_WEIGHT0 0xffU | ||
| 1092 | #define V_TX_MODQ_WEIGHT0(x) ((x) << S_TX_MODQ_WEIGHT0) | ||
| 1093 | |||
| 1094 | #define A_TP_TX_SCHED_HDR 0x23 | ||
| 1095 | |||
| 1096 | #define A_TP_TX_SCHED_FIFO 0x24 | ||
| 1097 | |||
| 1098 | #define A_TP_TX_SCHED_PCMD 0x25 | ||
| 1099 | |||
| 1100 | #define S_PORT 1 | ||
| 1101 | #define V_PORT(x) ((x) << S_PORT) | ||
| 1102 | #define F_PORT V_PORT(1U) | ||
| 1103 | |||
| 1067 | #endif /* __T4_REGS_H */ | 1104 | #endif /* __T4_REGS_H */ |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index 0abc864cdd3a..a0dcccd846c9 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | |||
| @@ -35,6 +35,45 @@ | |||
| 35 | #ifndef _T4FW_INTERFACE_H_ | 35 | #ifndef _T4FW_INTERFACE_H_ |
| 36 | #define _T4FW_INTERFACE_H_ | 36 | #define _T4FW_INTERFACE_H_ |
| 37 | 37 | ||
| 38 | enum fw_retval { | ||
| 39 | FW_SUCCESS = 0, /* completed sucessfully */ | ||
| 40 | FW_EPERM = 1, /* operation not permitted */ | ||
| 41 | FW_ENOENT = 2, /* no such file or directory */ | ||
| 42 | FW_EIO = 5, /* input/output error; hw bad */ | ||
| 43 | FW_ENOEXEC = 8, /* exec format error; inv microcode */ | ||
| 44 | FW_EAGAIN = 11, /* try again */ | ||
| 45 | FW_ENOMEM = 12, /* out of memory */ | ||
| 46 | FW_EFAULT = 14, /* bad address; fw bad */ | ||
| 47 | FW_EBUSY = 16, /* resource busy */ | ||
| 48 | FW_EEXIST = 17, /* file exists */ | ||
| 49 | FW_EINVAL = 22, /* invalid argument */ | ||
| 50 | FW_ENOSPC = 28, /* no space left on device */ | ||
| 51 | FW_ENOSYS = 38, /* functionality not implemented */ | ||
| 52 | FW_EPROTO = 71, /* protocol error */ | ||
| 53 | FW_EADDRINUSE = 98, /* address already in use */ | ||
| 54 | FW_EADDRNOTAVAIL = 99, /* cannot assigned requested address */ | ||
| 55 | FW_ENETDOWN = 100, /* network is down */ | ||
| 56 | FW_ENETUNREACH = 101, /* network is unreachable */ | ||
| 57 | FW_ENOBUFS = 105, /* no buffer space available */ | ||
| 58 | FW_ETIMEDOUT = 110, /* timeout */ | ||
| 59 | FW_EINPROGRESS = 115, /* fw internal */ | ||
| 60 | FW_SCSI_ABORT_REQUESTED = 128, /* */ | ||
| 61 | FW_SCSI_ABORT_TIMEDOUT = 129, /* */ | ||
| 62 | FW_SCSI_ABORTED = 130, /* */ | ||
| 63 | FW_SCSI_CLOSE_REQUESTED = 131, /* */ | ||
| 64 | FW_ERR_LINK_DOWN = 132, /* */ | ||
| 65 | FW_RDEV_NOT_READY = 133, /* */ | ||
| 66 | FW_ERR_RDEV_LOST = 134, /* */ | ||
| 67 | FW_ERR_RDEV_LOGO = 135, /* */ | ||
| 68 | FW_FCOE_NO_XCHG = 136, /* */ | ||
| 69 | FW_SCSI_RSP_ERR = 137, /* */ | ||
| 70 | FW_ERR_RDEV_IMPL_LOGO = 138, /* */ | ||
| 71 | FW_SCSI_UNDER_FLOW_ERR = 139, /* */ | ||
| 72 | FW_SCSI_OVER_FLOW_ERR = 140, /* */ | ||
| 73 | FW_SCSI_DDP_ERR = 141, /* DDP error*/ | ||
| 74 | FW_SCSI_TASK_ERR = 142, /* No SCSI tasks available */ | ||
| 75 | }; | ||
| 76 | |||
| 38 | #define FW_T4VF_SGE_BASE_ADDR 0x0000 | 77 | #define FW_T4VF_SGE_BASE_ADDR 0x0000 |
| 39 | #define FW_T4VF_MPS_BASE_ADDR 0x0100 | 78 | #define FW_T4VF_MPS_BASE_ADDR 0x0100 |
| 40 | #define FW_T4VF_PL_BASE_ADDR 0x0200 | 79 | #define FW_T4VF_PL_BASE_ADDR 0x0200 |
| @@ -46,6 +85,7 @@ enum fw_wr_opcodes { | |||
| 46 | FW_ULPTX_WR = 0x04, | 85 | FW_ULPTX_WR = 0x04, |
| 47 | FW_TP_WR = 0x05, | 86 | FW_TP_WR = 0x05, |
| 48 | FW_ETH_TX_PKT_WR = 0x08, | 87 | FW_ETH_TX_PKT_WR = 0x08, |
| 88 | FW_OFLD_CONNECTION_WR = 0x2f, | ||
| 49 | FW_FLOWC_WR = 0x0a, | 89 | FW_FLOWC_WR = 0x0a, |
| 50 | FW_OFLD_TX_DATA_WR = 0x0b, | 90 | FW_OFLD_TX_DATA_WR = 0x0b, |
| 51 | FW_CMD_WR = 0x10, | 91 | FW_CMD_WR = 0x10, |
| @@ -81,6 +121,282 @@ struct fw_wr_hdr { | |||
| 81 | #define FW_WR_LEN16(x) ((x) << 0) | 121 | #define FW_WR_LEN16(x) ((x) << 0) |
| 82 | 122 | ||
| 83 | #define HW_TPL_FR_MT_PR_IV_P_FC 0X32B | 123 | #define HW_TPL_FR_MT_PR_IV_P_FC 0X32B |
| 124 | #define HW_TPL_FR_MT_PR_OV_P_FC 0X327 | ||
| 125 | |||
| 126 | /* filter wr reply code in cookie in CPL_SET_TCB_RPL */ | ||
| 127 | enum fw_filter_wr_cookie { | ||
| 128 | FW_FILTER_WR_SUCCESS, | ||
| 129 | FW_FILTER_WR_FLT_ADDED, | ||
| 130 | FW_FILTER_WR_FLT_DELETED, | ||
| 131 | FW_FILTER_WR_SMT_TBL_FULL, | ||
| 132 | FW_FILTER_WR_EINVAL, | ||
| 133 | }; | ||
| 134 | |||
| 135 | struct fw_filter_wr { | ||
| 136 | __be32 op_pkd; | ||
| 137 | __be32 len16_pkd; | ||
| 138 | __be64 r3; | ||
| 139 | __be32 tid_to_iq; | ||
| 140 | __be32 del_filter_to_l2tix; | ||
| 141 | __be16 ethtype; | ||
| 142 | __be16 ethtypem; | ||
| 143 | __u8 frag_to_ovlan_vldm; | ||
| 144 | __u8 smac_sel; | ||
| 145 | __be16 rx_chan_rx_rpl_iq; | ||
| 146 | __be32 maci_to_matchtypem; | ||
| 147 | __u8 ptcl; | ||
| 148 | __u8 ptclm; | ||
| 149 | __u8 ttyp; | ||
| 150 | __u8 ttypm; | ||
| 151 | __be16 ivlan; | ||
| 152 | __be16 ivlanm; | ||
| 153 | __be16 ovlan; | ||
| 154 | __be16 ovlanm; | ||
| 155 | __u8 lip[16]; | ||
| 156 | __u8 lipm[16]; | ||
| 157 | __u8 fip[16]; | ||
| 158 | __u8 fipm[16]; | ||
| 159 | __be16 lp; | ||
| 160 | __be16 lpm; | ||
| 161 | __be16 fp; | ||
| 162 | __be16 fpm; | ||
| 163 | __be16 r7; | ||
| 164 | __u8 sma[6]; | ||
| 165 | }; | ||
| 166 | |||
| 167 | #define S_FW_FILTER_WR_TID 12 | ||
| 168 | #define M_FW_FILTER_WR_TID 0xfffff | ||
| 169 | #define V_FW_FILTER_WR_TID(x) ((x) << S_FW_FILTER_WR_TID) | ||
| 170 | #define G_FW_FILTER_WR_TID(x) \ | ||
| 171 | (((x) >> S_FW_FILTER_WR_TID) & M_FW_FILTER_WR_TID) | ||
| 172 | |||
| 173 | #define S_FW_FILTER_WR_RQTYPE 11 | ||
| 174 | #define M_FW_FILTER_WR_RQTYPE 0x1 | ||
| 175 | #define V_FW_FILTER_WR_RQTYPE(x) ((x) << S_FW_FILTER_WR_RQTYPE) | ||
| 176 | #define G_FW_FILTER_WR_RQTYPE(x) \ | ||
| 177 | (((x) >> S_FW_FILTER_WR_RQTYPE) & M_FW_FILTER_WR_RQTYPE) | ||
| 178 | #define F_FW_FILTER_WR_RQTYPE V_FW_FILTER_WR_RQTYPE(1U) | ||
| 179 | |||
| 180 | #define S_FW_FILTER_WR_NOREPLY 10 | ||
| 181 | #define M_FW_FILTER_WR_NOREPLY 0x1 | ||
| 182 | #define V_FW_FILTER_WR_NOREPLY(x) ((x) << S_FW_FILTER_WR_NOREPLY) | ||
| 183 | #define G_FW_FILTER_WR_NOREPLY(x) \ | ||
| 184 | (((x) >> S_FW_FILTER_WR_NOREPLY) & M_FW_FILTER_WR_NOREPLY) | ||
| 185 | #define F_FW_FILTER_WR_NOREPLY V_FW_FILTER_WR_NOREPLY(1U) | ||
| 186 | |||
| 187 | #define S_FW_FILTER_WR_IQ 0 | ||
| 188 | #define M_FW_FILTER_WR_IQ 0x3ff | ||
| 189 | #define V_FW_FILTER_WR_IQ(x) ((x) << S_FW_FILTER_WR_IQ) | ||
| 190 | #define G_FW_FILTER_WR_IQ(x) \ | ||
| 191 | (((x) >> S_FW_FILTER_WR_IQ) & M_FW_FILTER_WR_IQ) | ||
| 192 | |||
| 193 | #define S_FW_FILTER_WR_DEL_FILTER 31 | ||
| 194 | #define M_FW_FILTER_WR_DEL_FILTER 0x1 | ||
| 195 | #define V_FW_FILTER_WR_DEL_FILTER(x) ((x) << S_FW_FILTER_WR_DEL_FILTER) | ||
| 196 | #define G_FW_FILTER_WR_DEL_FILTER(x) \ | ||
| 197 | (((x) >> S_FW_FILTER_WR_DEL_FILTER) & M_FW_FILTER_WR_DEL_FILTER) | ||
| 198 | #define F_FW_FILTER_WR_DEL_FILTER V_FW_FILTER_WR_DEL_FILTER(1U) | ||
| 199 | |||
| 200 | #define S_FW_FILTER_WR_RPTTID 25 | ||
| 201 | #define M_FW_FILTER_WR_RPTTID 0x1 | ||
| 202 | #define V_FW_FILTER_WR_RPTTID(x) ((x) << S_FW_FILTER_WR_RPTTID) | ||
| 203 | #define G_FW_FILTER_WR_RPTTID(x) \ | ||
| 204 | (((x) >> S_FW_FILTER_WR_RPTTID) & M_FW_FILTER_WR_RPTTID) | ||
| 205 | #define F_FW_FILTER_WR_RPTTID V_FW_FILTER_WR_RPTTID(1U) | ||
| 206 | |||
| 207 | #define S_FW_FILTER_WR_DROP 24 | ||
| 208 | #define M_FW_FILTER_WR_DROP 0x1 | ||
| 209 | #define V_FW_FILTER_WR_DROP(x) ((x) << S_FW_FILTER_WR_DROP) | ||
| 210 | #define G_FW_FILTER_WR_DROP(x) \ | ||
| 211 | (((x) >> S_FW_FILTER_WR_DROP) & M_FW_FILTER_WR_DROP) | ||
| 212 | #define F_FW_FILTER_WR_DROP V_FW_FILTER_WR_DROP(1U) | ||
| 213 | |||
| 214 | #define S_FW_FILTER_WR_DIRSTEER 23 | ||
| 215 | #define M_FW_FILTER_WR_DIRSTEER 0x1 | ||
| 216 | #define V_FW_FILTER_WR_DIRSTEER(x) ((x) << S_FW_FILTER_WR_DIRSTEER) | ||
| 217 | #define G_FW_FILTER_WR_DIRSTEER(x) \ | ||
| 218 | (((x) >> S_FW_FILTER_WR_DIRSTEER) & M_FW_FILTER_WR_DIRSTEER) | ||
| 219 | #define F_FW_FILTER_WR_DIRSTEER V_FW_FILTER_WR_DIRSTEER(1U) | ||
| 220 | |||
| 221 | #define S_FW_FILTER_WR_MASKHASH 22 | ||
| 222 | #define M_FW_FILTER_WR_MASKHASH 0x1 | ||
| 223 | #define V_FW_FILTER_WR_MASKHASH(x) ((x) << S_FW_FILTER_WR_MASKHASH) | ||
| 224 | #define G_FW_FILTER_WR_MASKHASH(x) \ | ||
| 225 | (((x) >> S_FW_FILTER_WR_MASKHASH) & M_FW_FILTER_WR_MASKHASH) | ||
| 226 | #define F_FW_FILTER_WR_MASKHASH V_FW_FILTER_WR_MASKHASH(1U) | ||
| 227 | |||
| 228 | #define S_FW_FILTER_WR_DIRSTEERHASH 21 | ||
| 229 | #define M_FW_FILTER_WR_DIRSTEERHASH 0x1 | ||
| 230 | #define V_FW_FILTER_WR_DIRSTEERHASH(x) ((x) << S_FW_FILTER_WR_DIRSTEERHASH) | ||
| 231 | #define G_FW_FILTER_WR_DIRSTEERHASH(x) \ | ||
| 232 | (((x) >> S_FW_FILTER_WR_DIRSTEERHASH) & M_FW_FILTER_WR_DIRSTEERHASH) | ||
| 233 | #define F_FW_FILTER_WR_DIRSTEERHASH V_FW_FILTER_WR_DIRSTEERHASH(1U) | ||
| 234 | |||
| 235 | #define S_FW_FILTER_WR_LPBK 20 | ||
| 236 | #define M_FW_FILTER_WR_LPBK 0x1 | ||
| 237 | #define V_FW_FILTER_WR_LPBK(x) ((x) << S_FW_FILTER_WR_LPBK) | ||
| 238 | #define G_FW_FILTER_WR_LPBK(x) \ | ||
| 239 | (((x) >> S_FW_FILTER_WR_LPBK) & M_FW_FILTER_WR_LPBK) | ||
| 240 | #define F_FW_FILTER_WR_LPBK V_FW_FILTER_WR_LPBK(1U) | ||
| 241 | |||
| 242 | #define S_FW_FILTER_WR_DMAC 19 | ||
| 243 | #define M_FW_FILTER_WR_DMAC 0x1 | ||
| 244 | #define V_FW_FILTER_WR_DMAC(x) ((x) << S_FW_FILTER_WR_DMAC) | ||
| 245 | #define G_FW_FILTER_WR_DMAC(x) \ | ||
| 246 | (((x) >> S_FW_FILTER_WR_DMAC) & M_FW_FILTER_WR_DMAC) | ||
| 247 | #define F_FW_FILTER_WR_DMAC V_FW_FILTER_WR_DMAC(1U) | ||
| 248 | |||
| 249 | #define S_FW_FILTER_WR_SMAC 18 | ||
| 250 | #define M_FW_FILTER_WR_SMAC 0x1 | ||
| 251 | #define V_FW_FILTER_WR_SMAC(x) ((x) << S_FW_FILTER_WR_SMAC) | ||
| 252 | #define G_FW_FILTER_WR_SMAC(x) \ | ||
| 253 | (((x) >> S_FW_FILTER_WR_SMAC) & M_FW_FILTER_WR_SMAC) | ||
| 254 | #define F_FW_FILTER_WR_SMAC V_FW_FILTER_WR_SMAC(1U) | ||
| 255 | |||
| 256 | #define S_FW_FILTER_WR_INSVLAN 17 | ||
| 257 | #define M_FW_FILTER_WR_INSVLAN 0x1 | ||
| 258 | #define V_FW_FILTER_WR_INSVLAN(x) ((x) << S_FW_FILTER_WR_INSVLAN) | ||
| 259 | #define G_FW_FILTER_WR_INSVLAN(x) \ | ||
| 260 | (((x) >> S_FW_FILTER_WR_INSVLAN) & M_FW_FILTER_WR_INSVLAN) | ||
| 261 | #define F_FW_FILTER_WR_INSVLAN V_FW_FILTER_WR_INSVLAN(1U) | ||
| 262 | |||
| 263 | #define S_FW_FILTER_WR_RMVLAN 16 | ||
| 264 | #define M_FW_FILTER_WR_RMVLAN 0x1 | ||
| 265 | #define V_FW_FILTER_WR_RMVLAN(x) ((x) << S_FW_FILTER_WR_RMVLAN) | ||
| 266 | #define G_FW_FILTER_WR_RMVLAN(x) \ | ||
| 267 | (((x) >> S_FW_FILTER_WR_RMVLAN) & M_FW_FILTER_WR_RMVLAN) | ||
| 268 | #define F_FW_FILTER_WR_RMVLAN V_FW_FILTER_WR_RMVLAN(1U) | ||
| 269 | |||
| 270 | #define S_FW_FILTER_WR_HITCNTS 15 | ||
| 271 | #define M_FW_FILTER_WR_HITCNTS 0x1 | ||
| 272 | #define V_FW_FILTER_WR_HITCNTS(x) ((x) << S_FW_FILTER_WR_HITCNTS) | ||
| 273 | #define G_FW_FILTER_WR_HITCNTS(x) \ | ||
| 274 | (((x) >> S_FW_FILTER_WR_HITCNTS) & M_FW_FILTER_WR_HITCNTS) | ||
| 275 | #define F_FW_FILTER_WR_HITCNTS V_FW_FILTER_WR_HITCNTS(1U) | ||
| 276 | |||
| 277 | #define S_FW_FILTER_WR_TXCHAN 13 | ||
| 278 | #define M_FW_FILTER_WR_TXCHAN 0x3 | ||
| 279 | #define V_FW_FILTER_WR_TXCHAN(x) ((x) << S_FW_FILTER_WR_TXCHAN) | ||
| 280 | #define G_FW_FILTER_WR_TXCHAN(x) \ | ||
| 281 | (((x) >> S_FW_FILTER_WR_TXCHAN) & M_FW_FILTER_WR_TXCHAN) | ||
| 282 | |||
| 283 | #define S_FW_FILTER_WR_PRIO 12 | ||
| 284 | #define M_FW_FILTER_WR_PRIO 0x1 | ||
| 285 | #define V_FW_FILTER_WR_PRIO(x) ((x) << S_FW_FILTER_WR_PRIO) | ||
| 286 | #define G_FW_FILTER_WR_PRIO(x) \ | ||
| 287 | (((x) >> S_FW_FILTER_WR_PRIO) & M_FW_FILTER_WR_PRIO) | ||
| 288 | #define F_FW_FILTER_WR_PRIO V_FW_FILTER_WR_PRIO(1U) | ||
| 289 | |||
| 290 | #define S_FW_FILTER_WR_L2TIX 0 | ||
| 291 | #define M_FW_FILTER_WR_L2TIX 0xfff | ||
| 292 | #define V_FW_FILTER_WR_L2TIX(x) ((x) << S_FW_FILTER_WR_L2TIX) | ||
| 293 | #define G_FW_FILTER_WR_L2TIX(x) \ | ||
| 294 | (((x) >> S_FW_FILTER_WR_L2TIX) & M_FW_FILTER_WR_L2TIX) | ||
| 295 | |||
| 296 | #define S_FW_FILTER_WR_FRAG 7 | ||
| 297 | #define M_FW_FILTER_WR_FRAG 0x1 | ||
| 298 | #define V_FW_FILTER_WR_FRAG(x) ((x) << S_FW_FILTER_WR_FRAG) | ||
| 299 | #define G_FW_FILTER_WR_FRAG(x) \ | ||
| 300 | (((x) >> S_FW_FILTER_WR_FRAG) & M_FW_FILTER_WR_FRAG) | ||
| 301 | #define F_FW_FILTER_WR_FRAG V_FW_FILTER_WR_FRAG(1U) | ||
| 302 | |||
| 303 | #define S_FW_FILTER_WR_FRAGM 6 | ||
| 304 | #define M_FW_FILTER_WR_FRAGM 0x1 | ||
| 305 | #define V_FW_FILTER_WR_FRAGM(x) ((x) << S_FW_FILTER_WR_FRAGM) | ||
| 306 | #define G_FW_FILTER_WR_FRAGM(x) \ | ||
| 307 | (((x) >> S_FW_FILTER_WR_FRAGM) & M_FW_FILTER_WR_FRAGM) | ||
| 308 | #define F_FW_FILTER_WR_FRAGM V_FW_FILTER_WR_FRAGM(1U) | ||
| 309 | |||
| 310 | #define S_FW_FILTER_WR_IVLAN_VLD 5 | ||
| 311 | #define M_FW_FILTER_WR_IVLAN_VLD 0x1 | ||
| 312 | #define V_FW_FILTER_WR_IVLAN_VLD(x) ((x) << S_FW_FILTER_WR_IVLAN_VLD) | ||
| 313 | #define G_FW_FILTER_WR_IVLAN_VLD(x) \ | ||
| 314 | (((x) >> S_FW_FILTER_WR_IVLAN_VLD) & M_FW_FILTER_WR_IVLAN_VLD) | ||
| 315 | #define F_FW_FILTER_WR_IVLAN_VLD V_FW_FILTER_WR_IVLAN_VLD(1U) | ||
| 316 | |||
| 317 | #define S_FW_FILTER_WR_OVLAN_VLD 4 | ||
| 318 | #define M_FW_FILTER_WR_OVLAN_VLD 0x1 | ||
| 319 | #define V_FW_FILTER_WR_OVLAN_VLD(x) ((x) << S_FW_FILTER_WR_OVLAN_VLD) | ||
| 320 | #define G_FW_FILTER_WR_OVLAN_VLD(x) \ | ||
| 321 | (((x) >> S_FW_FILTER_WR_OVLAN_VLD) & M_FW_FILTER_WR_OVLAN_VLD) | ||
| 322 | #define F_FW_FILTER_WR_OVLAN_VLD V_FW_FILTER_WR_OVLAN_VLD(1U) | ||
| 323 | |||
| 324 | #define S_FW_FILTER_WR_IVLAN_VLDM 3 | ||
| 325 | #define M_FW_FILTER_WR_IVLAN_VLDM 0x1 | ||
| 326 | #define V_FW_FILTER_WR_IVLAN_VLDM(x) ((x) << S_FW_FILTER_WR_IVLAN_VLDM) | ||
| 327 | #define G_FW_FILTER_WR_IVLAN_VLDM(x) \ | ||
| 328 | (((x) >> S_FW_FILTER_WR_IVLAN_VLDM) & M_FW_FILTER_WR_IVLAN_VLDM) | ||
| 329 | #define F_FW_FILTER_WR_IVLAN_VLDM V_FW_FILTER_WR_IVLAN_VLDM(1U) | ||
| 330 | |||
| 331 | #define S_FW_FILTER_WR_OVLAN_VLDM 2 | ||
| 332 | #define M_FW_FILTER_WR_OVLAN_VLDM 0x1 | ||
| 333 | #define V_FW_FILTER_WR_OVLAN_VLDM(x) ((x) << S_FW_FILTER_WR_OVLAN_VLDM) | ||
| 334 | #define G_FW_FILTER_WR_OVLAN_VLDM(x) \ | ||
| 335 | (((x) >> S_FW_FILTER_WR_OVLAN_VLDM) & M_FW_FILTER_WR_OVLAN_VLDM) | ||
| 336 | #define F_FW_FILTER_WR_OVLAN_VLDM V_FW_FILTER_WR_OVLAN_VLDM(1U) | ||
| 337 | |||
| 338 | #define S_FW_FILTER_WR_RX_CHAN 15 | ||
| 339 | #define M_FW_FILTER_WR_RX_CHAN 0x1 | ||
| 340 | #define V_FW_FILTER_WR_RX_CHAN(x) ((x) << S_FW_FILTER_WR_RX_CHAN) | ||
| 341 | #define G_FW_FILTER_WR_RX_CHAN(x) \ | ||
| 342 | (((x) >> S_FW_FILTER_WR_RX_CHAN) & M_FW_FILTER_WR_RX_CHAN) | ||
| 343 | #define F_FW_FILTER_WR_RX_CHAN V_FW_FILTER_WR_RX_CHAN(1U) | ||
| 344 | |||
| 345 | #define S_FW_FILTER_WR_RX_RPL_IQ 0 | ||
| 346 | #define M_FW_FILTER_WR_RX_RPL_IQ 0x3ff | ||
| 347 | #define V_FW_FILTER_WR_RX_RPL_IQ(x) ((x) << S_FW_FILTER_WR_RX_RPL_IQ) | ||
| 348 | #define G_FW_FILTER_WR_RX_RPL_IQ(x) \ | ||
| 349 | (((x) >> S_FW_FILTER_WR_RX_RPL_IQ) & M_FW_FILTER_WR_RX_RPL_IQ) | ||
| 350 | |||
| 351 | #define S_FW_FILTER_WR_MACI 23 | ||
| 352 | #define M_FW_FILTER_WR_MACI 0x1ff | ||
| 353 | #define V_FW_FILTER_WR_MACI(x) ((x) << S_FW_FILTER_WR_MACI) | ||
| 354 | #define G_FW_FILTER_WR_MACI(x) \ | ||
| 355 | (((x) >> S_FW_FILTER_WR_MACI) & M_FW_FILTER_WR_MACI) | ||
| 356 | |||
| 357 | #define S_FW_FILTER_WR_MACIM 14 | ||
| 358 | #define M_FW_FILTER_WR_MACIM 0x1ff | ||
| 359 | #define V_FW_FILTER_WR_MACIM(x) ((x) << S_FW_FILTER_WR_MACIM) | ||
| 360 | #define G_FW_FILTER_WR_MACIM(x) \ | ||
| 361 | (((x) >> S_FW_FILTER_WR_MACIM) & M_FW_FILTER_WR_MACIM) | ||
| 362 | |||
| 363 | #define S_FW_FILTER_WR_FCOE 13 | ||
| 364 | #define M_FW_FILTER_WR_FCOE 0x1 | ||
| 365 | #define V_FW_FILTER_WR_FCOE(x) ((x) << S_FW_FILTER_WR_FCOE) | ||
| 366 | #define G_FW_FILTER_WR_FCOE(x) \ | ||
| 367 | (((x) >> S_FW_FILTER_WR_FCOE) & M_FW_FILTER_WR_FCOE) | ||
| 368 | #define F_FW_FILTER_WR_FCOE V_FW_FILTER_WR_FCOE(1U) | ||
| 369 | |||
| 370 | #define S_FW_FILTER_WR_FCOEM 12 | ||
| 371 | #define M_FW_FILTER_WR_FCOEM 0x1 | ||
| 372 | #define V_FW_FILTER_WR_FCOEM(x) ((x) << S_FW_FILTER_WR_FCOEM) | ||
| 373 | #define G_FW_FILTER_WR_FCOEM(x) \ | ||
| 374 | (((x) >> S_FW_FILTER_WR_FCOEM) & M_FW_FILTER_WR_FCOEM) | ||
| 375 | #define F_FW_FILTER_WR_FCOEM V_FW_FILTER_WR_FCOEM(1U) | ||
| 376 | |||
| 377 | #define S_FW_FILTER_WR_PORT 9 | ||
| 378 | #define M_FW_FILTER_WR_PORT 0x7 | ||
| 379 | #define V_FW_FILTER_WR_PORT(x) ((x) << S_FW_FILTER_WR_PORT) | ||
| 380 | #define G_FW_FILTER_WR_PORT(x) \ | ||
| 381 | (((x) >> S_FW_FILTER_WR_PORT) & M_FW_FILTER_WR_PORT) | ||
| 382 | |||
| 383 | #define S_FW_FILTER_WR_PORTM 6 | ||
| 384 | #define M_FW_FILTER_WR_PORTM 0x7 | ||
| 385 | #define V_FW_FILTER_WR_PORTM(x) ((x) << S_FW_FILTER_WR_PORTM) | ||
| 386 | #define G_FW_FILTER_WR_PORTM(x) \ | ||
| 387 | (((x) >> S_FW_FILTER_WR_PORTM) & M_FW_FILTER_WR_PORTM) | ||
| 388 | |||
| 389 | #define S_FW_FILTER_WR_MATCHTYPE 3 | ||
| 390 | #define M_FW_FILTER_WR_MATCHTYPE 0x7 | ||
| 391 | #define V_FW_FILTER_WR_MATCHTYPE(x) ((x) << S_FW_FILTER_WR_MATCHTYPE) | ||
| 392 | #define G_FW_FILTER_WR_MATCHTYPE(x) \ | ||
| 393 | (((x) >> S_FW_FILTER_WR_MATCHTYPE) & M_FW_FILTER_WR_MATCHTYPE) | ||
| 394 | |||
| 395 | #define S_FW_FILTER_WR_MATCHTYPEM 0 | ||
| 396 | #define M_FW_FILTER_WR_MATCHTYPEM 0x7 | ||
| 397 | #define V_FW_FILTER_WR_MATCHTYPEM(x) ((x) << S_FW_FILTER_WR_MATCHTYPEM) | ||
| 398 | #define G_FW_FILTER_WR_MATCHTYPEM(x) \ | ||
| 399 | (((x) >> S_FW_FILTER_WR_MATCHTYPEM) & M_FW_FILTER_WR_MATCHTYPEM) | ||
| 84 | 400 | ||
| 85 | struct fw_ulptx_wr { | 401 | struct fw_ulptx_wr { |
| 86 | __be32 op_to_compl; | 402 | __be32 op_to_compl; |
| @@ -100,6 +416,108 @@ struct fw_eth_tx_pkt_wr { | |||
| 100 | __be64 r3; | 416 | __be64 r3; |
| 101 | }; | 417 | }; |
| 102 | 418 | ||
| 419 | struct fw_ofld_connection_wr { | ||
| 420 | __be32 op_compl; | ||
| 421 | __be32 len16_pkd; | ||
| 422 | __u64 cookie; | ||
| 423 | __be64 r2; | ||
| 424 | __be64 r3; | ||
| 425 | struct fw_ofld_connection_le { | ||
| 426 | __be32 version_cpl; | ||
| 427 | __be32 filter; | ||
| 428 | __be32 r1; | ||
| 429 | __be16 lport; | ||
| 430 | __be16 pport; | ||
| 431 | union fw_ofld_connection_leip { | ||
| 432 | struct fw_ofld_connection_le_ipv4 { | ||
| 433 | __be32 pip; | ||
| 434 | __be32 lip; | ||
| 435 | __be64 r0; | ||
| 436 | __be64 r1; | ||
| 437 | __be64 r2; | ||
| 438 | } ipv4; | ||
| 439 | struct fw_ofld_connection_le_ipv6 { | ||
| 440 | __be64 pip_hi; | ||
| 441 | __be64 pip_lo; | ||
| 442 | __be64 lip_hi; | ||
| 443 | __be64 lip_lo; | ||
| 444 | } ipv6; | ||
| 445 | } u; | ||
| 446 | } le; | ||
| 447 | struct fw_ofld_connection_tcb { | ||
| 448 | __be32 t_state_to_astid; | ||
| 449 | __be16 cplrxdataack_cplpassacceptrpl; | ||
| 450 | __be16 rcv_adv; | ||
| 451 | __be32 rcv_nxt; | ||
| 452 | __be32 tx_max; | ||
| 453 | __be64 opt0; | ||
| 454 | __be32 opt2; | ||
| 455 | __be32 r1; | ||
| 456 | __be64 r2; | ||
| 457 | __be64 r3; | ||
| 458 | } tcb; | ||
| 459 | }; | ||
| 460 | |||
| 461 | #define S_FW_OFLD_CONNECTION_WR_VERSION 31 | ||
| 462 | #define M_FW_OFLD_CONNECTION_WR_VERSION 0x1 | ||
| 463 | #define V_FW_OFLD_CONNECTION_WR_VERSION(x) \ | ||
| 464 | ((x) << S_FW_OFLD_CONNECTION_WR_VERSION) | ||
| 465 | #define G_FW_OFLD_CONNECTION_WR_VERSION(x) \ | ||
| 466 | (((x) >> S_FW_OFLD_CONNECTION_WR_VERSION) & \ | ||
| 467 | M_FW_OFLD_CONNECTION_WR_VERSION) | ||
| 468 | #define F_FW_OFLD_CONNECTION_WR_VERSION \ | ||
| 469 | V_FW_OFLD_CONNECTION_WR_VERSION(1U) | ||
| 470 | |||
| 471 | #define S_FW_OFLD_CONNECTION_WR_CPL 30 | ||
| 472 | #define M_FW_OFLD_CONNECTION_WR_CPL 0x1 | ||
| 473 | #define V_FW_OFLD_CONNECTION_WR_CPL(x) ((x) << S_FW_OFLD_CONNECTION_WR_CPL) | ||
| 474 | #define G_FW_OFLD_CONNECTION_WR_CPL(x) \ | ||
| 475 | (((x) >> S_FW_OFLD_CONNECTION_WR_CPL) & M_FW_OFLD_CONNECTION_WR_CPL) | ||
| 476 | #define F_FW_OFLD_CONNECTION_WR_CPL V_FW_OFLD_CONNECTION_WR_CPL(1U) | ||
| 477 | |||
| 478 | #define S_FW_OFLD_CONNECTION_WR_T_STATE 28 | ||
| 479 | #define M_FW_OFLD_CONNECTION_WR_T_STATE 0xf | ||
| 480 | #define V_FW_OFLD_CONNECTION_WR_T_STATE(x) \ | ||
| 481 | ((x) << S_FW_OFLD_CONNECTION_WR_T_STATE) | ||
| 482 | #define G_FW_OFLD_CONNECTION_WR_T_STATE(x) \ | ||
| 483 | (((x) >> S_FW_OFLD_CONNECTION_WR_T_STATE) & \ | ||
| 484 | M_FW_OFLD_CONNECTION_WR_T_STATE) | ||
| 485 | |||
| 486 | #define S_FW_OFLD_CONNECTION_WR_RCV_SCALE 24 | ||
| 487 | #define M_FW_OFLD_CONNECTION_WR_RCV_SCALE 0xf | ||
| 488 | #define V_FW_OFLD_CONNECTION_WR_RCV_SCALE(x) \ | ||
| 489 | ((x) << S_FW_OFLD_CONNECTION_WR_RCV_SCALE) | ||
| 490 | #define G_FW_OFLD_CONNECTION_WR_RCV_SCALE(x) \ | ||
| 491 | (((x) >> S_FW_OFLD_CONNECTION_WR_RCV_SCALE) & \ | ||
| 492 | M_FW_OFLD_CONNECTION_WR_RCV_SCALE) | ||
| 493 | |||
| 494 | #define S_FW_OFLD_CONNECTION_WR_ASTID 0 | ||
| 495 | #define M_FW_OFLD_CONNECTION_WR_ASTID 0xffffff | ||
| 496 | #define V_FW_OFLD_CONNECTION_WR_ASTID(x) \ | ||
| 497 | ((x) << S_FW_OFLD_CONNECTION_WR_ASTID) | ||
| 498 | #define G_FW_OFLD_CONNECTION_WR_ASTID(x) \ | ||
| 499 | (((x) >> S_FW_OFLD_CONNECTION_WR_ASTID) & M_FW_OFLD_CONNECTION_WR_ASTID) | ||
| 500 | |||
| 501 | #define S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK 15 | ||
| 502 | #define M_FW_OFLD_CONNECTION_WR_CPLRXDATAACK 0x1 | ||
| 503 | #define V_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(x) \ | ||
| 504 | ((x) << S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) | ||
| 505 | #define G_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(x) \ | ||
| 506 | (((x) >> S_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) & \ | ||
| 507 | M_FW_OFLD_CONNECTION_WR_CPLRXDATAACK) | ||
| 508 | #define F_FW_OFLD_CONNECTION_WR_CPLRXDATAACK \ | ||
| 509 | V_FW_OFLD_CONNECTION_WR_CPLRXDATAACK(1U) | ||
| 510 | |||
| 511 | #define S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL 14 | ||
| 512 | #define M_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL 0x1 | ||
| 513 | #define V_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(x) \ | ||
| 514 | ((x) << S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) | ||
| 515 | #define G_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(x) \ | ||
| 516 | (((x) >> S_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) & \ | ||
| 517 | M_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL) | ||
| 518 | #define F_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL \ | ||
| 519 | V_FW_OFLD_CONNECTION_WR_CPLPASSACCEPTRPL(1U) | ||
| 520 | |||
| 103 | enum fw_flowc_mnem { | 521 | enum fw_flowc_mnem { |
| 104 | FW_FLOWC_MNEM_PFNVFN, /* PFN [15:8] VFN [7:0] */ | 522 | FW_FLOWC_MNEM_PFNVFN, /* PFN [15:8] VFN [7:0] */ |
| 105 | FW_FLOWC_MNEM_CH, | 523 | FW_FLOWC_MNEM_CH, |
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/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 9a9de51ecc91..8b3d0512a46b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c | |||
| @@ -1338,6 +1338,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, | |||
| 1338 | { | 1338 | { |
| 1339 | struct mlx4_cmd_mailbox *mailbox; | 1339 | struct mlx4_cmd_mailbox *mailbox; |
| 1340 | __be32 *outbox; | 1340 | __be32 *outbox; |
| 1341 | u32 dword_field; | ||
| 1341 | int err; | 1342 | int err; |
| 1342 | u8 byte_field; | 1343 | u8 byte_field; |
| 1343 | 1344 | ||
| @@ -1372,10 +1373,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, | |||
| 1372 | MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); | 1373 | MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); |
| 1373 | MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); | 1374 | MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); |
| 1374 | 1375 | ||
| 1376 | MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET); | ||
| 1377 | if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) { | ||
| 1378 | param->steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; | ||
| 1379 | } else { | ||
| 1380 | MLX4_GET(byte_field, outbox, INIT_HCA_UC_STEERING_OFFSET); | ||
| 1381 | if (byte_field & 0x8) | ||
| 1382 | param->steering_mode = MLX4_STEERING_MODE_B0; | ||
| 1383 | else | ||
| 1384 | param->steering_mode = MLX4_STEERING_MODE_A0; | ||
| 1385 | } | ||
| 1375 | /* steering attributes */ | 1386 | /* steering attributes */ |
| 1376 | if (dev->caps.steering_mode == | 1387 | if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { |
| 1377 | MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
| 1378 | |||
| 1379 | MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET); | 1388 | MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET); |
| 1380 | MLX4_GET(param->log_mc_entry_sz, outbox, | 1389 | MLX4_GET(param->log_mc_entry_sz, outbox, |
| 1381 | INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); | 1390 | INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h index 2c2e7ade2a34..dbf2f69cc59f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/drivers/net/ethernet/mellanox/mlx4/fw.h | |||
| @@ -172,6 +172,7 @@ struct mlx4_init_hca_param { | |||
| 172 | u8 log_uar_sz; | 172 | u8 log_uar_sz; |
| 173 | u8 uar_page_sz; /* log pg sz in 4k chunks */ | 173 | u8 uar_page_sz; /* log pg sz in 4k chunks */ |
| 174 | u8 fs_hash_enable_bits; | 174 | u8 fs_hash_enable_bits; |
| 175 | u8 steering_mode; /* for QUERY_HCA */ | ||
| 175 | u64 dev_cap_enabled; | 176 | u64 dev_cap_enabled; |
| 176 | }; | 177 | }; |
| 177 | 178 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index b2acbe7706a3..e1bafffbc3b1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
| @@ -85,15 +85,15 @@ static int probe_vf; | |||
| 85 | module_param(probe_vf, int, 0644); | 85 | module_param(probe_vf, int, 0644); |
| 86 | MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)"); | 86 | MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)"); |
| 87 | 87 | ||
| 88 | int mlx4_log_num_mgm_entry_size = 10; | 88 | int mlx4_log_num_mgm_entry_size = MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE; |
| 89 | module_param_named(log_num_mgm_entry_size, | 89 | module_param_named(log_num_mgm_entry_size, |
| 90 | mlx4_log_num_mgm_entry_size, int, 0444); | 90 | mlx4_log_num_mgm_entry_size, int, 0444); |
| 91 | MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num" | 91 | MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num" |
| 92 | " of qp per mcg, for example:" | 92 | " of qp per mcg, for example:" |
| 93 | " 10 gives 248.range: 9<=" | 93 | " 10 gives 248.range: 7 <=" |
| 94 | " log_num_mgm_entry_size <= 12." | 94 | " log_num_mgm_entry_size <= 12." |
| 95 | " Not in use with device managed" | 95 | " To activate device managed" |
| 96 | " flow steering"); | 96 | " flow steering when available, set to -1"); |
| 97 | 97 | ||
| 98 | static bool enable_64b_cqe_eqe; | 98 | static bool enable_64b_cqe_eqe; |
| 99 | module_param(enable_64b_cqe_eqe, bool, 0444); | 99 | module_param(enable_64b_cqe_eqe, bool, 0444); |
| @@ -281,28 +281,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
| 281 | dev->caps.max_gso_sz = dev_cap->max_gso_sz; | 281 | dev->caps.max_gso_sz = dev_cap->max_gso_sz; |
| 282 | dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz; | 282 | dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz; |
| 283 | 283 | ||
| 284 | if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN) { | ||
| 285 | dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; | ||
| 286 | dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; | ||
| 287 | dev->caps.fs_log_max_ucast_qp_range_size = | ||
| 288 | dev_cap->fs_log_max_ucast_qp_range_size; | ||
| 289 | } else { | ||
| 290 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && | ||
| 291 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) { | ||
| 292 | dev->caps.steering_mode = MLX4_STEERING_MODE_B0; | ||
| 293 | } else { | ||
| 294 | dev->caps.steering_mode = MLX4_STEERING_MODE_A0; | ||
| 295 | |||
| 296 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER || | ||
| 297 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) | ||
| 298 | mlx4_warn(dev, "Must have UC_STEER and MC_STEER flags " | ||
| 299 | "set to use B0 steering. Falling back to A0 steering mode.\n"); | ||
| 300 | } | ||
| 301 | dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); | ||
| 302 | } | ||
| 303 | mlx4_dbg(dev, "Steering mode is: %s\n", | ||
| 304 | mlx4_steering_mode_str(dev->caps.steering_mode)); | ||
| 305 | |||
| 306 | /* Sense port always allowed on supported devices for ConnectX-1 and -2 */ | 284 | /* Sense port always allowed on supported devices for ConnectX-1 and -2 */ |
| 307 | if (mlx4_priv(dev)->pci_dev_data & MLX4_PCI_DEV_FORCE_SENSE_PORT) | 285 | if (mlx4_priv(dev)->pci_dev_data & MLX4_PCI_DEV_FORCE_SENSE_PORT) |
| 308 | dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT; | 286 | dev->caps.flags |= MLX4_DEV_CAP_FLAG_SENSE_SUPPORT; |
| @@ -493,6 +471,23 @@ int mlx4_is_slave_active(struct mlx4_dev *dev, int slave) | |||
| 493 | } | 471 | } |
| 494 | EXPORT_SYMBOL(mlx4_is_slave_active); | 472 | EXPORT_SYMBOL(mlx4_is_slave_active); |
| 495 | 473 | ||
| 474 | static void slave_adjust_steering_mode(struct mlx4_dev *dev, | ||
| 475 | struct mlx4_dev_cap *dev_cap, | ||
| 476 | struct mlx4_init_hca_param *hca_param) | ||
| 477 | { | ||
| 478 | dev->caps.steering_mode = hca_param->steering_mode; | ||
| 479 | if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
| 480 | dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; | ||
| 481 | dev->caps.fs_log_max_ucast_qp_range_size = | ||
| 482 | dev_cap->fs_log_max_ucast_qp_range_size; | ||
| 483 | } else | ||
| 484 | dev->caps.num_qp_per_mgm = | ||
| 485 | 4 * ((1 << hca_param->log_mc_entry_sz)/16 - 2); | ||
| 486 | |||
| 487 | mlx4_dbg(dev, "Steering mode is: %s\n", | ||
| 488 | mlx4_steering_mode_str(dev->caps.steering_mode)); | ||
| 489 | } | ||
| 490 | |||
| 496 | static int mlx4_slave_cap(struct mlx4_dev *dev) | 491 | static int mlx4_slave_cap(struct mlx4_dev *dev) |
| 497 | { | 492 | { |
| 498 | int err; | 493 | int err; |
| @@ -635,6 +630,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) | |||
| 635 | dev->caps.cqe_size = 32; | 630 | dev->caps.cqe_size = 32; |
| 636 | } | 631 | } |
| 637 | 632 | ||
| 633 | slave_adjust_steering_mode(dev, &dev_cap, &hca_param); | ||
| 634 | |||
| 638 | return 0; | 635 | return 0; |
| 639 | 636 | ||
| 640 | err_mem: | 637 | err_mem: |
| @@ -1321,6 +1318,59 @@ static void mlx4_parav_master_pf_caps(struct mlx4_dev *dev) | |||
| 1321 | } | 1318 | } |
| 1322 | } | 1319 | } |
| 1323 | 1320 | ||
| 1321 | static int choose_log_fs_mgm_entry_size(int qp_per_entry) | ||
| 1322 | { | ||
| 1323 | int i = MLX4_MIN_MGM_LOG_ENTRY_SIZE; | ||
| 1324 | |||
| 1325 | for (i = MLX4_MIN_MGM_LOG_ENTRY_SIZE; i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE; | ||
| 1326 | i++) { | ||
| 1327 | if (qp_per_entry <= 4 * ((1 << i) / 16 - 2)) | ||
| 1328 | break; | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | return (i <= MLX4_MAX_MGM_LOG_ENTRY_SIZE) ? i : -1; | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | static void choose_steering_mode(struct mlx4_dev *dev, | ||
| 1335 | struct mlx4_dev_cap *dev_cap) | ||
| 1336 | { | ||
| 1337 | if (mlx4_log_num_mgm_entry_size == -1 && | ||
| 1338 | dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN && | ||
| 1339 | (!mlx4_is_mfunc(dev) || | ||
| 1340 | (dev_cap->fs_max_num_qp_per_entry >= (num_vfs + 1))) && | ||
| 1341 | choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry) >= | ||
| 1342 | MLX4_MIN_MGM_LOG_ENTRY_SIZE) { | ||
| 1343 | dev->oper_log_mgm_entry_size = | ||
| 1344 | choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry); | ||
| 1345 | dev->caps.steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED; | ||
| 1346 | dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry; | ||
| 1347 | dev->caps.fs_log_max_ucast_qp_range_size = | ||
| 1348 | dev_cap->fs_log_max_ucast_qp_range_size; | ||
| 1349 | } else { | ||
| 1350 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER && | ||
| 1351 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) | ||
| 1352 | dev->caps.steering_mode = MLX4_STEERING_MODE_B0; | ||
| 1353 | else { | ||
| 1354 | dev->caps.steering_mode = MLX4_STEERING_MODE_A0; | ||
| 1355 | |||
| 1356 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER || | ||
| 1357 | dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) | ||
| 1358 | mlx4_warn(dev, "Must have both UC_STEER and MC_STEER flags " | ||
| 1359 | "set to use B0 steering. Falling back to A0 steering mode.\n"); | ||
| 1360 | } | ||
| 1361 | dev->oper_log_mgm_entry_size = | ||
| 1362 | mlx4_log_num_mgm_entry_size > 0 ? | ||
| 1363 | mlx4_log_num_mgm_entry_size : | ||
| 1364 | MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE; | ||
| 1365 | dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); | ||
| 1366 | } | ||
| 1367 | mlx4_dbg(dev, "Steering mode is: %s, oper_log_mgm_entry_size = %d, " | ||
| 1368 | "modparam log_num_mgm_entry_size = %d\n", | ||
| 1369 | mlx4_steering_mode_str(dev->caps.steering_mode), | ||
| 1370 | dev->oper_log_mgm_entry_size, | ||
| 1371 | mlx4_log_num_mgm_entry_size); | ||
| 1372 | } | ||
| 1373 | |||
| 1324 | static int mlx4_init_hca(struct mlx4_dev *dev) | 1374 | static int mlx4_init_hca(struct mlx4_dev *dev) |
| 1325 | { | 1375 | { |
| 1326 | struct mlx4_priv *priv = mlx4_priv(dev); | 1376 | struct mlx4_priv *priv = mlx4_priv(dev); |
| @@ -1360,6 +1410,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev) | |||
| 1360 | goto err_stop_fw; | 1410 | goto err_stop_fw; |
| 1361 | } | 1411 | } |
| 1362 | 1412 | ||
| 1413 | choose_steering_mode(dev, &dev_cap); | ||
| 1414 | |||
| 1363 | if (mlx4_is_master(dev)) | 1415 | if (mlx4_is_master(dev)) |
| 1364 | mlx4_parav_master_pf_caps(dev); | 1416 | mlx4_parav_master_pf_caps(dev); |
| 1365 | 1417 | ||
| @@ -2452,6 +2504,17 @@ static int __init mlx4_verify_params(void) | |||
| 2452 | port_type_array[0] = true; | 2504 | port_type_array[0] = true; |
| 2453 | } | 2505 | } |
| 2454 | 2506 | ||
| 2507 | if (mlx4_log_num_mgm_entry_size != -1 && | ||
| 2508 | (mlx4_log_num_mgm_entry_size < MLX4_MIN_MGM_LOG_ENTRY_SIZE || | ||
| 2509 | mlx4_log_num_mgm_entry_size > MLX4_MAX_MGM_LOG_ENTRY_SIZE)) { | ||
| 2510 | pr_warning("mlx4_core: mlx4_log_num_mgm_entry_size (%d) not " | ||
| 2511 | "in legal range (-1 or %d..%d)\n", | ||
| 2512 | mlx4_log_num_mgm_entry_size, | ||
| 2513 | MLX4_MIN_MGM_LOG_ENTRY_SIZE, | ||
| 2514 | MLX4_MAX_MGM_LOG_ENTRY_SIZE); | ||
| 2515 | return -1; | ||
| 2516 | } | ||
| 2517 | |||
| 2455 | return 0; | 2518 | return 0; |
| 2456 | } | 2519 | } |
| 2457 | 2520 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index e151c21baf2b..1ee4db3c6400 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c | |||
| @@ -54,12 +54,7 @@ struct mlx4_mgm { | |||
| 54 | 54 | ||
| 55 | int mlx4_get_mgm_entry_size(struct mlx4_dev *dev) | 55 | int mlx4_get_mgm_entry_size(struct mlx4_dev *dev) |
| 56 | { | 56 | { |
| 57 | if (dev->caps.steering_mode == | 57 | return 1 << dev->oper_log_mgm_entry_size; |
| 58 | MLX4_STEERING_MODE_DEVICE_MANAGED) | ||
| 59 | return 1 << MLX4_FS_MGM_LOG_ENTRY_SIZE; | ||
| 60 | else | ||
| 61 | return min((1 << mlx4_log_num_mgm_entry_size), | ||
| 62 | MLX4_MAX_MGM_ENTRY_SIZE); | ||
| 63 | } | 58 | } |
| 64 | 59 | ||
| 65 | int mlx4_get_qp_per_mgm(struct mlx4_dev *dev) | 60 | int mlx4_get_qp_per_mgm(struct mlx4_dev *dev) |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 1cf42036d7bb..116c5c29d2d1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
| @@ -94,8 +94,10 @@ enum { | |||
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | enum { | 96 | enum { |
| 97 | MLX4_MAX_MGM_ENTRY_SIZE = 0x1000, | 97 | MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE = 10, |
| 98 | MLX4_MAX_QP_PER_MGM = 4 * (MLX4_MAX_MGM_ENTRY_SIZE / 16 - 2), | 98 | MLX4_MIN_MGM_LOG_ENTRY_SIZE = 7, |
| 99 | MLX4_MAX_MGM_LOG_ENTRY_SIZE = 12, | ||
| 100 | MLX4_MAX_QP_PER_MGM = 4 * ((1 << MLX4_MAX_MGM_LOG_ENTRY_SIZE) / 16 - 2), | ||
| 99 | MLX4_MTT_ENTRY_PER_SEG = 8, | 101 | MLX4_MTT_ENTRY_PER_SEG = 8, |
| 100 | }; | 102 | }; |
| 101 | 103 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index b05705f50f0f..561ed2a22a17 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
| @@ -3071,6 +3071,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
| 3071 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; | 3071 | struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; |
| 3072 | struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; | 3072 | struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; |
| 3073 | int err; | 3073 | int err; |
| 3074 | int qpn; | ||
| 3074 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; | 3075 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; |
| 3075 | struct _rule_hw *rule_header; | 3076 | struct _rule_hw *rule_header; |
| 3076 | int header_id; | 3077 | int header_id; |
| @@ -3080,13 +3081,21 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
| 3080 | return -EOPNOTSUPP; | 3081 | return -EOPNOTSUPP; |
| 3081 | 3082 | ||
| 3082 | ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; | 3083 | ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; |
| 3084 | qpn = be32_to_cpu(ctrl->qpn) & 0xffffff; | ||
| 3085 | err = get_res(dev, slave, qpn, RES_QP, NULL); | ||
| 3086 | if (err) { | ||
| 3087 | pr_err("Steering rule with qpn 0x%x rejected.\n", qpn); | ||
| 3088 | return err; | ||
| 3089 | } | ||
| 3083 | rule_header = (struct _rule_hw *)(ctrl + 1); | 3090 | rule_header = (struct _rule_hw *)(ctrl + 1); |
| 3084 | header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id)); | 3091 | header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id)); |
| 3085 | 3092 | ||
| 3086 | switch (header_id) { | 3093 | switch (header_id) { |
| 3087 | case MLX4_NET_TRANS_RULE_ID_ETH: | 3094 | case MLX4_NET_TRANS_RULE_ID_ETH: |
| 3088 | if (validate_eth_header_mac(slave, rule_header, rlist)) | 3095 | if (validate_eth_header_mac(slave, rule_header, rlist)) { |
| 3089 | return -EINVAL; | 3096 | err = -EINVAL; |
| 3097 | goto err_put; | ||
| 3098 | } | ||
| 3090 | break; | 3099 | break; |
| 3091 | case MLX4_NET_TRANS_RULE_ID_IB: | 3100 | case MLX4_NET_TRANS_RULE_ID_IB: |
| 3092 | break; | 3101 | break; |
| @@ -3094,14 +3103,17 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
| 3094 | case MLX4_NET_TRANS_RULE_ID_TCP: | 3103 | case MLX4_NET_TRANS_RULE_ID_TCP: |
| 3095 | case MLX4_NET_TRANS_RULE_ID_UDP: | 3104 | case MLX4_NET_TRANS_RULE_ID_UDP: |
| 3096 | pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n"); | 3105 | pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n"); |
| 3097 | if (add_eth_header(dev, slave, inbox, rlist, header_id)) | 3106 | if (add_eth_header(dev, slave, inbox, rlist, header_id)) { |
| 3098 | return -EINVAL; | 3107 | err = -EINVAL; |
| 3108 | goto err_put; | ||
| 3109 | } | ||
| 3099 | vhcr->in_modifier += | 3110 | vhcr->in_modifier += |
| 3100 | sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2; | 3111 | sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2; |
| 3101 | break; | 3112 | break; |
| 3102 | default: | 3113 | default: |
| 3103 | pr_err("Corrupted mailbox.\n"); | 3114 | pr_err("Corrupted mailbox.\n"); |
| 3104 | return -EINVAL; | 3115 | err = -EINVAL; |
| 3116 | goto err_put; | ||
| 3105 | } | 3117 | } |
| 3106 | 3118 | ||
| 3107 | err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, | 3119 | err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param, |
| @@ -3109,16 +3121,18 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
| 3109 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, | 3121 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, |
| 3110 | MLX4_CMD_NATIVE); | 3122 | MLX4_CMD_NATIVE); |
| 3111 | if (err) | 3123 | if (err) |
| 3112 | return err; | 3124 | goto err_put; |
| 3113 | 3125 | ||
| 3114 | err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0); | 3126 | err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0); |
| 3115 | if (err) { | 3127 | if (err) { |
| 3116 | mlx4_err(dev, "Fail to add flow steering resources.\n "); | 3128 | mlx4_err(dev, "Fail to add flow steering resources.\n "); |
| 3117 | /* detach rule*/ | 3129 | /* detach rule*/ |
| 3118 | mlx4_cmd(dev, vhcr->out_param, 0, 0, | 3130 | mlx4_cmd(dev, vhcr->out_param, 0, 0, |
| 3119 | MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, | 3131 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, |
| 3120 | MLX4_CMD_NATIVE); | 3132 | MLX4_CMD_NATIVE); |
| 3121 | } | 3133 | } |
| 3134 | err_put: | ||
| 3135 | put_res(dev, slave, qpn, RES_QP); | ||
| 3122 | return err; | 3136 | return err; |
| 3123 | } | 3137 | } |
| 3124 | 3138 | ||
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/virtio_net.c b/drivers/net/virtio_net.c index 68d64f0313ea..a6fcf15adc4f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -130,7 +130,6 @@ struct skb_vnet_hdr { | |||
| 130 | struct virtio_net_hdr hdr; | 130 | struct virtio_net_hdr hdr; |
| 131 | struct virtio_net_hdr_mrg_rxbuf mhdr; | 131 | struct virtio_net_hdr_mrg_rxbuf mhdr; |
| 132 | }; | 132 | }; |
| 133 | unsigned int num_sg; | ||
| 134 | }; | 133 | }; |
| 135 | 134 | ||
| 136 | struct padded_vnet_hdr { | 135 | struct padded_vnet_hdr { |
| @@ -530,10 +529,10 @@ static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp) | |||
| 530 | err = add_recvbuf_small(rq, gfp); | 529 | err = add_recvbuf_small(rq, gfp); |
| 531 | 530 | ||
| 532 | oom = err == -ENOMEM; | 531 | oom = err == -ENOMEM; |
| 533 | if (err < 0) | 532 | if (err) |
| 534 | break; | 533 | break; |
| 535 | ++rq->num; | 534 | ++rq->num; |
| 536 | } while (err > 0); | 535 | } while (rq->vq->num_free); |
| 537 | if (unlikely(rq->num > rq->max)) | 536 | if (unlikely(rq->num > rq->max)) |
| 538 | rq->max = rq->num; | 537 | rq->max = rq->num; |
| 539 | virtqueue_kick(rq->vq); | 538 | virtqueue_kick(rq->vq); |
| @@ -640,10 +639,10 @@ static int virtnet_open(struct net_device *dev) | |||
| 640 | return 0; | 639 | return 0; |
| 641 | } | 640 | } |
| 642 | 641 | ||
| 643 | static unsigned int free_old_xmit_skbs(struct send_queue *sq) | 642 | static void free_old_xmit_skbs(struct send_queue *sq) |
| 644 | { | 643 | { |
| 645 | struct sk_buff *skb; | 644 | struct sk_buff *skb; |
| 646 | unsigned int len, tot_sgs = 0; | 645 | unsigned int len; |
| 647 | struct virtnet_info *vi = sq->vq->vdev->priv; | 646 | struct virtnet_info *vi = sq->vq->vdev->priv; |
| 648 | struct virtnet_stats *stats = this_cpu_ptr(vi->stats); | 647 | struct virtnet_stats *stats = this_cpu_ptr(vi->stats); |
| 649 | 648 | ||
| @@ -655,10 +654,8 @@ static unsigned int free_old_xmit_skbs(struct send_queue *sq) | |||
| 655 | stats->tx_packets++; | 654 | stats->tx_packets++; |
| 656 | u64_stats_update_end(&stats->tx_syncp); | 655 | u64_stats_update_end(&stats->tx_syncp); |
| 657 | 656 | ||
| 658 | tot_sgs += skb_vnet_hdr(skb)->num_sg; | ||
| 659 | dev_kfree_skb_any(skb); | 657 | dev_kfree_skb_any(skb); |
| 660 | } | 658 | } |
| 661 | return tot_sgs; | ||
| 662 | } | 659 | } |
| 663 | 660 | ||
| 664 | static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) | 661 | static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) |
| @@ -666,6 +663,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) | |||
| 666 | struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); | 663 | struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); |
| 667 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; | 664 | const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; |
| 668 | struct virtnet_info *vi = sq->vq->vdev->priv; | 665 | struct virtnet_info *vi = sq->vq->vdev->priv; |
| 666 | unsigned num_sg; | ||
| 669 | 667 | ||
| 670 | pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); | 668 | pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); |
| 671 | 669 | ||
| @@ -704,8 +702,8 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) | |||
| 704 | else | 702 | else |
| 705 | sg_set_buf(sq->sg, &hdr->hdr, sizeof hdr->hdr); | 703 | sg_set_buf(sq->sg, &hdr->hdr, sizeof hdr->hdr); |
| 706 | 704 | ||
| 707 | hdr->num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1; | 705 | num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1; |
| 708 | return virtqueue_add_buf(sq->vq, sq->sg, hdr->num_sg, | 706 | return virtqueue_add_buf(sq->vq, sq->sg, num_sg, |
| 709 | 0, skb, GFP_ATOMIC); | 707 | 0, skb, GFP_ATOMIC); |
| 710 | } | 708 | } |
| 711 | 709 | ||
| @@ -714,28 +712,20 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 714 | struct virtnet_info *vi = netdev_priv(dev); | 712 | struct virtnet_info *vi = netdev_priv(dev); |
| 715 | int qnum = skb_get_queue_mapping(skb); | 713 | int qnum = skb_get_queue_mapping(skb); |
| 716 | struct send_queue *sq = &vi->sq[qnum]; | 714 | struct send_queue *sq = &vi->sq[qnum]; |
| 717 | int capacity; | 715 | int err; |
| 718 | 716 | ||
| 719 | /* Free up any pending old buffers before queueing new ones. */ | 717 | /* Free up any pending old buffers before queueing new ones. */ |
| 720 | free_old_xmit_skbs(sq); | 718 | free_old_xmit_skbs(sq); |
| 721 | 719 | ||
| 722 | /* Try to transmit */ | 720 | /* Try to transmit */ |
| 723 | capacity = xmit_skb(sq, skb); | 721 | err = xmit_skb(sq, skb); |
| 724 | 722 | ||
| 725 | /* This can happen with OOM and indirect buffers. */ | 723 | /* This should not happen! */ |
| 726 | if (unlikely(capacity < 0)) { | 724 | if (unlikely(err)) { |
| 727 | if (likely(capacity == -ENOMEM)) { | 725 | dev->stats.tx_fifo_errors++; |
| 728 | if (net_ratelimit()) | 726 | if (net_ratelimit()) |
| 729 | dev_warn(&dev->dev, | 727 | dev_warn(&dev->dev, |
| 730 | "TXQ (%d) failure: out of memory\n", | 728 | "Unexpected TXQ (%d) queue failure: %d\n", qnum, err); |
| 731 | qnum); | ||
| 732 | } else { | ||
| 733 | dev->stats.tx_fifo_errors++; | ||
| 734 | if (net_ratelimit()) | ||
| 735 | dev_warn(&dev->dev, | ||
| 736 | "Unexpected TXQ (%d) failure: %d\n", | ||
| 737 | qnum, capacity); | ||
| 738 | } | ||
| 739 | dev->stats.tx_dropped++; | 729 | dev->stats.tx_dropped++; |
| 740 | kfree_skb(skb); | 730 | kfree_skb(skb); |
| 741 | return NETDEV_TX_OK; | 731 | return NETDEV_TX_OK; |
| @@ -748,12 +738,12 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 748 | 738 | ||
| 749 | /* Apparently nice girls don't return TX_BUSY; stop the queue | 739 | /* Apparently nice girls don't return TX_BUSY; stop the queue |
| 750 | * before it gets out of hand. Naturally, this wastes entries. */ | 740 | * before it gets out of hand. Naturally, this wastes entries. */ |
| 751 | if (capacity < 2+MAX_SKB_FRAGS) { | 741 | if (sq->vq->num_free < 2+MAX_SKB_FRAGS) { |
| 752 | netif_stop_subqueue(dev, qnum); | 742 | netif_stop_subqueue(dev, qnum); |
| 753 | if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { | 743 | if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { |
| 754 | /* More just got used, free them then recheck. */ | 744 | /* More just got used, free them then recheck. */ |
| 755 | capacity += free_old_xmit_skbs(sq); | 745 | free_old_xmit_skbs(sq); |
| 756 | if (capacity >= 2+MAX_SKB_FRAGS) { | 746 | if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) { |
| 757 | netif_start_subqueue(dev, qnum); | 747 | netif_start_subqueue(dev, qnum); |
| 758 | virtqueue_disable_cb(sq->vq); | 748 | virtqueue_disable_cb(sq->vq); |
| 759 | } | 749 | } |
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/drivers/of/base.c b/drivers/of/base.c index db8d211a0d05..2390ddb22d60 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
| @@ -629,7 +629,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, | |||
| 629 | read_unlock(&devtree_lock); | 629 | read_unlock(&devtree_lock); |
| 630 | return np; | 630 | return np; |
| 631 | } | 631 | } |
| 632 | EXPORT_SYMBOL(of_find_matching_node); | 632 | EXPORT_SYMBOL(of_find_matching_node_and_match); |
| 633 | 633 | ||
| 634 | /** | 634 | /** |
| 635 | * of_modalias_node - Lookup appropriate modalias for a device node | 635 | * of_modalias_node - Lookup appropriate modalias for a device node |
diff --git a/drivers/pinctrl/pinctrl-exynos5440.c b/drivers/pinctrl/pinctrl-exynos5440.c index b8635f634e91..07db89528dc3 100644 --- a/drivers/pinctrl/pinctrl-exynos5440.c +++ b/drivers/pinctrl/pinctrl-exynos5440.c | |||
| @@ -117,7 +117,7 @@ struct exynos5440_pinctrl_priv_data { | |||
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| 119 | /* list of all possible config options supported */ | 119 | /* list of all possible config options supported */ |
| 120 | struct pin_config { | 120 | static struct pin_config { |
| 121 | char *prop_cfg; | 121 | char *prop_cfg; |
| 122 | unsigned int cfg_type; | 122 | unsigned int cfg_type; |
| 123 | } pcfgs[] = { | 123 | } pcfgs[] = { |
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index 8f31b656c4e9..864fed822f9d 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | #define FSUFFIX_LEN sizeof(FUNCTION_SUFFIX) | 37 | #define FSUFFIX_LEN sizeof(FUNCTION_SUFFIX) |
| 38 | 38 | ||
| 39 | /* list of all possible config options supported */ | 39 | /* list of all possible config options supported */ |
| 40 | struct pin_config { | 40 | static struct pin_config { |
| 41 | char *prop_cfg; | 41 | char *prop_cfg; |
| 42 | unsigned int cfg_type; | 42 | unsigned int cfg_type; |
| 43 | } pcfgs[] = { | 43 | } pcfgs[] = { |
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index 5addfd16e3cc..e2d4e67f7e88 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h | |||
| @@ -104,7 +104,7 @@ struct samsung_pinctrl_drv_data; | |||
| 104 | 104 | ||
| 105 | /** | 105 | /** |
| 106 | * struct samsung_pin_bank: represent a controller pin-bank. | 106 | * struct samsung_pin_bank: represent a controller pin-bank. |
| 107 | * @reg_offset: starting offset of the pin-bank registers. | 107 | * @pctl_offset: starting offset of the pin-bank registers. |
| 108 | * @pin_base: starting pin number of the bank. | 108 | * @pin_base: starting pin number of the bank. |
| 109 | * @nr_pins: number of pins included in this bank. | 109 | * @nr_pins: number of pins included in this bank. |
| 110 | * @func_width: width of the function selector bit field. | 110 | * @func_width: width of the function selector bit field. |
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 1859f71372e2..027096fe6a12 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c | |||
| @@ -764,7 +764,7 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst, | |||
| 764 | 764 | ||
| 765 | /* add message to the remote processor's virtqueue */ | 765 | /* add message to the remote processor's virtqueue */ |
| 766 | err = virtqueue_add_buf(vrp->svq, &sg, 1, 0, msg, GFP_KERNEL); | 766 | err = virtqueue_add_buf(vrp->svq, &sg, 1, 0, msg, GFP_KERNEL); |
| 767 | if (err < 0) { | 767 | if (err) { |
| 768 | /* | 768 | /* |
| 769 | * need to reclaim the buffer here, otherwise it's lost | 769 | * need to reclaim the buffer here, otherwise it's lost |
| 770 | * (memory won't leak, but rpmsg won't use it again for TX). | 770 | * (memory won't leak, but rpmsg won't use it again for TX). |
| @@ -776,8 +776,6 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst, | |||
| 776 | 776 | ||
| 777 | /* tell the remote processor it has a pending message to read */ | 777 | /* tell the remote processor it has a pending message to read */ |
| 778 | virtqueue_kick(vrp->svq); | 778 | virtqueue_kick(vrp->svq); |
| 779 | |||
| 780 | err = 0; | ||
| 781 | out: | 779 | out: |
| 782 | mutex_unlock(&vrp->tx_lock); | 780 | mutex_unlock(&vrp->tx_lock); |
| 783 | return err; | 781 | return err; |
| @@ -980,7 +978,7 @@ static int rpmsg_probe(struct virtio_device *vdev) | |||
| 980 | 978 | ||
| 981 | err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, cpu_addr, | 979 | err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, cpu_addr, |
| 982 | GFP_KERNEL); | 980 | GFP_KERNEL); |
| 983 | WARN_ON(err < 0); /* sanity check; this can't really happen */ | 981 | WARN_ON(err); /* sanity check; this can't really happen */ |
| 984 | } | 982 | } |
| 985 | 983 | ||
| 986 | /* suppress "tx-complete" interrupts */ | 984 | /* suppress "tx-complete" interrupts */ |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index f8a0aab218cb..5143629dedbd 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
| @@ -244,7 +244,6 @@ void rtc_device_unregister(struct rtc_device *rtc) | |||
| 244 | rtc_proc_del_device(rtc); | 244 | rtc_proc_del_device(rtc); |
| 245 | device_unregister(&rtc->dev); | 245 | device_unregister(&rtc->dev); |
| 246 | rtc->ops = NULL; | 246 | rtc->ops = NULL; |
| 247 | ida_simple_remove(&rtc_ida, rtc->id); | ||
| 248 | mutex_unlock(&rtc->ops_lock); | 247 | mutex_unlock(&rtc->ops_lock); |
| 249 | put_device(&rtc->dev); | 248 | put_device(&rtc->dev); |
| 250 | } | 249 | } |
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 18a4f0dd78a3..8da7a5cf83c6 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
| 37 | #include <linux/rtc.h> | 37 | #include <linux/rtc.h> |
| 38 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
| 39 | #include <linux/spinlock.h> | ||
| 39 | #include <linux/workqueue.h> | 40 | #include <linux/workqueue.h> |
| 40 | #include <linux/of.h> | 41 | #include <linux/of.h> |
| 41 | 42 | ||
diff --git a/drivers/scsi/csiostor/t4fw_api_stor.h b/drivers/scsi/csiostor/t4fw_api_stor.h index 1223e0d5fc07..097e52c0f8e1 100644 --- a/drivers/scsi/csiostor/t4fw_api_stor.h +++ b/drivers/scsi/csiostor/t4fw_api_stor.h | |||
| @@ -40,45 +40,6 @@ | |||
| 40 | * R E T U R N V A L U E S | 40 | * R E T U R N V A L U E S |
| 41 | ********************************/ | 41 | ********************************/ |
| 42 | 42 | ||
| 43 | enum fw_retval { | ||
| 44 | FW_SUCCESS = 0, /* completed sucessfully */ | ||
| 45 | FW_EPERM = 1, /* operation not permitted */ | ||
| 46 | FW_ENOENT = 2, /* no such file or directory */ | ||
| 47 | FW_EIO = 5, /* input/output error; hw bad */ | ||
| 48 | FW_ENOEXEC = 8, /* exec format error; inv microcode */ | ||
| 49 | FW_EAGAIN = 11, /* try again */ | ||
| 50 | FW_ENOMEM = 12, /* out of memory */ | ||
| 51 | FW_EFAULT = 14, /* bad address; fw bad */ | ||
| 52 | FW_EBUSY = 16, /* resource busy */ | ||
| 53 | FW_EEXIST = 17, /* file exists */ | ||
| 54 | FW_EINVAL = 22, /* invalid argument */ | ||
| 55 | FW_ENOSPC = 28, /* no space left on device */ | ||
| 56 | FW_ENOSYS = 38, /* functionality not implemented */ | ||
| 57 | FW_EPROTO = 71, /* protocol error */ | ||
| 58 | FW_EADDRINUSE = 98, /* address already in use */ | ||
| 59 | FW_EADDRNOTAVAIL = 99, /* cannot assigned requested address */ | ||
| 60 | FW_ENETDOWN = 100, /* network is down */ | ||
| 61 | FW_ENETUNREACH = 101, /* network is unreachable */ | ||
| 62 | FW_ENOBUFS = 105, /* no buffer space available */ | ||
| 63 | FW_ETIMEDOUT = 110, /* timeout */ | ||
| 64 | FW_EINPROGRESS = 115, /* fw internal */ | ||
| 65 | FW_SCSI_ABORT_REQUESTED = 128, /* */ | ||
| 66 | FW_SCSI_ABORT_TIMEDOUT = 129, /* */ | ||
| 67 | FW_SCSI_ABORTED = 130, /* */ | ||
| 68 | FW_SCSI_CLOSE_REQUESTED = 131, /* */ | ||
| 69 | FW_ERR_LINK_DOWN = 132, /* */ | ||
| 70 | FW_RDEV_NOT_READY = 133, /* */ | ||
| 71 | FW_ERR_RDEV_LOST = 134, /* */ | ||
| 72 | FW_ERR_RDEV_LOGO = 135, /* */ | ||
| 73 | FW_FCOE_NO_XCHG = 136, /* */ | ||
| 74 | FW_SCSI_RSP_ERR = 137, /* */ | ||
| 75 | FW_ERR_RDEV_IMPL_LOGO = 138, /* */ | ||
| 76 | FW_SCSI_UNDER_FLOW_ERR = 139, /* */ | ||
| 77 | FW_SCSI_OVER_FLOW_ERR = 140, /* */ | ||
| 78 | FW_SCSI_DDP_ERR = 141, /* DDP error*/ | ||
| 79 | FW_SCSI_TASK_ERR = 142, /* No SCSI tasks available */ | ||
| 80 | }; | ||
| 81 | |||
| 82 | enum fw_fcoe_link_sub_op { | 43 | enum fw_fcoe_link_sub_op { |
| 83 | FCOE_LINK_DOWN = 0x0, | 44 | FCOE_LINK_DOWN = 0x0, |
| 84 | FCOE_LINK_UP = 0x1, | 45 | FCOE_LINK_UP = 0x1, |
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index dd8dc27fa32c..74ab67a169ec 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c | |||
| @@ -215,7 +215,7 @@ static void virtscsi_ctrl_done(struct virtqueue *vq) | |||
| 215 | static int virtscsi_kick_event(struct virtio_scsi *vscsi, | 215 | static int virtscsi_kick_event(struct virtio_scsi *vscsi, |
| 216 | struct virtio_scsi_event_node *event_node) | 216 | struct virtio_scsi_event_node *event_node) |
| 217 | { | 217 | { |
| 218 | int ret; | 218 | int err; |
| 219 | struct scatterlist sg; | 219 | struct scatterlist sg; |
| 220 | unsigned long flags; | 220 | unsigned long flags; |
| 221 | 221 | ||
| @@ -223,13 +223,14 @@ static int virtscsi_kick_event(struct virtio_scsi *vscsi, | |||
| 223 | 223 | ||
| 224 | spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); | 224 | spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); |
| 225 | 225 | ||
| 226 | ret = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node, GFP_ATOMIC); | 226 | err = virtqueue_add_buf(vscsi->event_vq.vq, &sg, 0, 1, event_node, |
| 227 | if (ret >= 0) | 227 | GFP_ATOMIC); |
| 228 | if (!err) | ||
| 228 | virtqueue_kick(vscsi->event_vq.vq); | 229 | virtqueue_kick(vscsi->event_vq.vq); |
| 229 | 230 | ||
| 230 | spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags); | 231 | spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags); |
| 231 | 232 | ||
| 232 | return ret; | 233 | return err; |
| 233 | } | 234 | } |
| 234 | 235 | ||
| 235 | static int virtscsi_kick_event_all(struct virtio_scsi *vscsi) | 236 | static int virtscsi_kick_event_all(struct virtio_scsi *vscsi) |
| @@ -410,22 +411,23 @@ static int virtscsi_kick_cmd(struct virtio_scsi_target_state *tgt, | |||
| 410 | { | 411 | { |
| 411 | unsigned int out_num, in_num; | 412 | unsigned int out_num, in_num; |
| 412 | unsigned long flags; | 413 | unsigned long flags; |
| 413 | int ret; | 414 | int err; |
| 415 | bool needs_kick = false; | ||
| 414 | 416 | ||
| 415 | spin_lock_irqsave(&tgt->tgt_lock, flags); | 417 | spin_lock_irqsave(&tgt->tgt_lock, flags); |
| 416 | virtscsi_map_cmd(tgt, cmd, &out_num, &in_num, req_size, resp_size); | 418 | virtscsi_map_cmd(tgt, cmd, &out_num, &in_num, req_size, resp_size); |
| 417 | 419 | ||
| 418 | spin_lock(&vq->vq_lock); | 420 | spin_lock(&vq->vq_lock); |
| 419 | ret = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp); | 421 | err = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp); |
| 420 | spin_unlock(&tgt->tgt_lock); | 422 | spin_unlock(&tgt->tgt_lock); |
| 421 | if (ret >= 0) | 423 | if (!err) |
| 422 | ret = virtqueue_kick_prepare(vq->vq); | 424 | needs_kick = virtqueue_kick_prepare(vq->vq); |
| 423 | 425 | ||
| 424 | spin_unlock_irqrestore(&vq->vq_lock, flags); | 426 | spin_unlock_irqrestore(&vq->vq_lock, flags); |
| 425 | 427 | ||
| 426 | if (ret > 0) | 428 | if (needs_kick) |
| 427 | virtqueue_notify(vq->vq); | 429 | virtqueue_notify(vq->vq); |
| 428 | return ret; | 430 | return err; |
| 429 | } | 431 | } |
| 430 | 432 | ||
| 431 | static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) | 433 | static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) |
| @@ -467,7 +469,7 @@ static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) | |||
| 467 | 469 | ||
| 468 | if (virtscsi_kick_cmd(tgt, &vscsi->req_vq, cmd, | 470 | if (virtscsi_kick_cmd(tgt, &vscsi->req_vq, cmd, |
| 469 | sizeof cmd->req.cmd, sizeof cmd->resp.cmd, | 471 | sizeof cmd->req.cmd, sizeof cmd->resp.cmd, |
| 470 | GFP_ATOMIC) >= 0) | 472 | GFP_ATOMIC) == 0) |
| 471 | ret = 0; | 473 | ret = 0; |
| 472 | else | 474 | else |
| 473 | mempool_free(cmd, virtscsi_cmd_pool); | 475 | mempool_free(cmd, virtscsi_cmd_pool); |
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 75c0c4f5fdf2..ab34497bcfee 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
| 21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 22 | #include <linux/platform_data/atmel.h> | 22 | #include <linux/platform_data/atmel.h> |
| 23 | #include <linux/of.h> | ||
| 23 | 24 | ||
| 24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
| 25 | #include <asm/gpio.h> | 26 | #include <asm/gpio.h> |
| @@ -768,6 +769,10 @@ static int atmel_spi_setup(struct spi_device *spi) | |||
| 768 | 769 | ||
| 769 | /* chipselect must have been muxed as GPIO (e.g. in board setup) */ | 770 | /* chipselect must have been muxed as GPIO (e.g. in board setup) */ |
| 770 | npcs_pin = (unsigned int)spi->controller_data; | 771 | npcs_pin = (unsigned int)spi->controller_data; |
| 772 | |||
| 773 | if (gpio_is_valid(spi->cs_gpio)) | ||
| 774 | npcs_pin = spi->cs_gpio; | ||
| 775 | |||
| 771 | asd = spi->controller_state; | 776 | asd = spi->controller_state; |
| 772 | if (!asd) { | 777 | if (!asd) { |
| 773 | asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL); | 778 | asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL); |
| @@ -937,8 +942,9 @@ static int atmel_spi_probe(struct platform_device *pdev) | |||
| 937 | /* the spi->mode bits understood by this driver: */ | 942 | /* the spi->mode bits understood by this driver: */ |
| 938 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | 943 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
| 939 | 944 | ||
| 945 | master->dev.of_node = pdev->dev.of_node; | ||
| 940 | master->bus_num = pdev->id; | 946 | master->bus_num = pdev->id; |
| 941 | master->num_chipselect = 4; | 947 | master->num_chipselect = master->dev.of_node ? 0 : 4; |
| 942 | master->setup = atmel_spi_setup; | 948 | master->setup = atmel_spi_setup; |
| 943 | master->transfer = atmel_spi_transfer; | 949 | master->transfer = atmel_spi_transfer; |
| 944 | master->cleanup = atmel_spi_cleanup; | 950 | master->cleanup = atmel_spi_cleanup; |
| @@ -1064,11 +1070,20 @@ static int atmel_spi_resume(struct platform_device *pdev) | |||
| 1064 | #define atmel_spi_resume NULL | 1070 | #define atmel_spi_resume NULL |
| 1065 | #endif | 1071 | #endif |
| 1066 | 1072 | ||
| 1073 | #if defined(CONFIG_OF) | ||
| 1074 | static const struct of_device_id atmel_spi_dt_ids[] = { | ||
| 1075 | { .compatible = "atmel,at91rm9200-spi" }, | ||
| 1076 | { /* sentinel */ } | ||
| 1077 | }; | ||
| 1078 | |||
| 1079 | MODULE_DEVICE_TABLE(of, atmel_spi_dt_ids); | ||
| 1080 | #endif | ||
| 1067 | 1081 | ||
| 1068 | static struct platform_driver atmel_spi_driver = { | 1082 | static struct platform_driver atmel_spi_driver = { |
| 1069 | .driver = { | 1083 | .driver = { |
| 1070 | .name = "atmel_spi", | 1084 | .name = "atmel_spi", |
| 1071 | .owner = THIS_MODULE, | 1085 | .owner = THIS_MODULE, |
| 1086 | .of_match_table = of_match_ptr(atmel_spi_dt_ids), | ||
| 1072 | }, | 1087 | }, |
| 1073 | .suspend = atmel_spi_suspend, | 1088 | .suspend = atmel_spi_suspend, |
| 1074 | .resume = atmel_spi_resume, | 1089 | .resume = atmel_spi_resume, |
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 4dd7b7ce5c5a..ad93231a8038 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c | |||
| @@ -215,6 +215,10 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) | |||
| 215 | writel(0, regs + S3C64XX_SPI_PACKET_CNT); | 215 | writel(0, regs + S3C64XX_SPI_PACKET_CNT); |
| 216 | 216 | ||
| 217 | val = readl(regs + S3C64XX_SPI_CH_CFG); | 217 | val = readl(regs + S3C64XX_SPI_CH_CFG); |
| 218 | val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON); | ||
| 219 | writel(val, regs + S3C64XX_SPI_CH_CFG); | ||
| 220 | |||
| 221 | val = readl(regs + S3C64XX_SPI_CH_CFG); | ||
| 218 | val |= S3C64XX_SPI_CH_SW_RST; | 222 | val |= S3C64XX_SPI_CH_SW_RST; |
| 219 | val &= ~S3C64XX_SPI_CH_HS_EN; | 223 | val &= ~S3C64XX_SPI_CH_HS_EN; |
| 220 | writel(val, regs + S3C64XX_SPI_CH_CFG); | 224 | writel(val, regs + S3C64XX_SPI_CH_CFG); |
| @@ -248,10 +252,6 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) | |||
| 248 | val = readl(regs + S3C64XX_SPI_MODE_CFG); | 252 | val = readl(regs + S3C64XX_SPI_MODE_CFG); |
| 249 | val &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON); | 253 | val &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON); |
| 250 | writel(val, regs + S3C64XX_SPI_MODE_CFG); | 254 | writel(val, regs + S3C64XX_SPI_MODE_CFG); |
| 251 | |||
| 252 | val = readl(regs + S3C64XX_SPI_CH_CFG); | ||
| 253 | val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON); | ||
| 254 | writel(val, regs + S3C64XX_SPI_CH_CFG); | ||
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | static void s3c64xx_spi_dmacb(void *data) | 257 | static void s3c64xx_spi_dmacb(void *data) |
| @@ -771,8 +771,6 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, | |||
| 771 | if (list_is_last(&xfer->transfer_list, | 771 | if (list_is_last(&xfer->transfer_list, |
| 772 | &msg->transfers)) | 772 | &msg->transfers)) |
| 773 | cs_toggle = 1; | 773 | cs_toggle = 1; |
| 774 | else | ||
| 775 | disable_cs(sdd, spi); | ||
| 776 | } | 774 | } |
| 777 | 775 | ||
| 778 | msg->actual_length += xfer->len; | 776 | msg->actual_length += xfer->len; |
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index 32f7b55fce09..60cfae51c713 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c | |||
| @@ -290,7 +290,7 @@ static int hspi_probe(struct platform_device *pdev) | |||
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | clk = clk_get(NULL, "shyway_clk"); | 292 | clk = clk_get(NULL, "shyway_clk"); |
| 293 | if (!clk) { | 293 | if (IS_ERR(clk)) { |
| 294 | dev_err(&pdev->dev, "shyway_clk is required\n"); | 294 | dev_err(&pdev->dev, "shyway_clk is required\n"); |
| 295 | ret = -EINVAL; | 295 | ret = -EINVAL; |
| 296 | goto error0; | 296 | goto error0; |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index ab095acdb2a8..19ee901577da 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
| @@ -824,6 +824,7 @@ static void of_register_spi_devices(struct spi_master *master) | |||
| 824 | struct spi_device *spi; | 824 | struct spi_device *spi; |
| 825 | struct device_node *nc; | 825 | struct device_node *nc; |
| 826 | const __be32 *prop; | 826 | const __be32 *prop; |
| 827 | char modalias[SPI_NAME_SIZE + 4]; | ||
| 827 | int rc; | 828 | int rc; |
| 828 | int len; | 829 | int len; |
| 829 | 830 | ||
| @@ -887,7 +888,9 @@ static void of_register_spi_devices(struct spi_master *master) | |||
| 887 | spi->dev.of_node = nc; | 888 | spi->dev.of_node = nc; |
| 888 | 889 | ||
| 889 | /* Register the new device */ | 890 | /* Register the new device */ |
| 890 | request_module(spi->modalias); | 891 | snprintf(modalias, sizeof(modalias), "%s%s", SPI_MODULE_PREFIX, |
| 892 | spi->modalias); | ||
| 893 | request_module(modalias); | ||
| 891 | rc = spi_add_device(spi); | 894 | rc = spi_add_device(spi); |
| 892 | if (rc) { | 895 | if (rc) { |
| 893 | dev_err(&master->dev, "spi_device register error %s\n", | 896 | dev_err(&master->dev, "spi_device register error %s\n", |
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 23f797eb7a28..57d6b29c039c 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c | |||
| @@ -41,8 +41,7 @@ | |||
| 41 | #include <linux/of.h> | 41 | #include <linux/of.h> |
| 42 | #include <linux/gpio.h> | 42 | #include <linux/gpio.h> |
| 43 | #include <linux/pinctrl/consumer.h> | 43 | #include <linux/pinctrl/consumer.h> |
| 44 | 44 | #include <linux/platform_data/serial-omap.h> | |
| 45 | #include <plat/omap-serial.h> | ||
| 46 | 45 | ||
| 47 | #define OMAP_MAX_HSUART_PORTS 6 | 46 | #define OMAP_MAX_HSUART_PORTS 6 |
| 48 | 47 | ||
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 6c119944bbb6..b28e66c4376a 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
| @@ -43,6 +43,10 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) | |||
| 43 | u16 cmd; | 43 | u16 cmd; |
| 44 | u8 msix_pos; | 44 | u8 msix_pos; |
| 45 | 45 | ||
| 46 | ret = pci_enable_device(pdev); | ||
| 47 | if (ret) | ||
| 48 | return ret; | ||
| 49 | |||
| 46 | vdev->reset_works = (pci_reset_function(pdev) == 0); | 50 | vdev->reset_works = (pci_reset_function(pdev) == 0); |
| 47 | pci_save_state(pdev); | 51 | pci_save_state(pdev); |
| 48 | vdev->pci_saved_state = pci_store_saved_state(pdev); | 52 | vdev->pci_saved_state = pci_store_saved_state(pdev); |
| @@ -51,8 +55,11 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) | |||
| 51 | __func__, dev_name(&pdev->dev)); | 55 | __func__, dev_name(&pdev->dev)); |
| 52 | 56 | ||
| 53 | ret = vfio_config_init(vdev); | 57 | ret = vfio_config_init(vdev); |
| 54 | if (ret) | 58 | if (ret) { |
| 55 | goto out; | 59 | pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state); |
| 60 | pci_disable_device(pdev); | ||
| 61 | return ret; | ||
| 62 | } | ||
| 56 | 63 | ||
| 57 | if (likely(!nointxmask)) | 64 | if (likely(!nointxmask)) |
| 58 | vdev->pci_2_3 = pci_intx_mask_supported(pdev); | 65 | vdev->pci_2_3 = pci_intx_mask_supported(pdev); |
| @@ -77,24 +84,15 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) | |||
| 77 | } else | 84 | } else |
| 78 | vdev->msix_bar = 0xFF; | 85 | vdev->msix_bar = 0xFF; |
| 79 | 86 | ||
| 80 | ret = pci_enable_device(pdev); | 87 | return 0; |
| 81 | if (ret) | ||
| 82 | goto out; | ||
| 83 | |||
| 84 | return ret; | ||
| 85 | |||
| 86 | out: | ||
| 87 | kfree(vdev->pci_saved_state); | ||
| 88 | vdev->pci_saved_state = NULL; | ||
| 89 | vfio_config_free(vdev); | ||
| 90 | return ret; | ||
| 91 | } | 88 | } |
| 92 | 89 | ||
| 93 | static void vfio_pci_disable(struct vfio_pci_device *vdev) | 90 | static void vfio_pci_disable(struct vfio_pci_device *vdev) |
| 94 | { | 91 | { |
| 92 | struct pci_dev *pdev = vdev->pdev; | ||
| 95 | int bar; | 93 | int bar; |
| 96 | 94 | ||
| 97 | pci_disable_device(vdev->pdev); | 95 | pci_disable_device(pdev); |
| 98 | 96 | ||
| 99 | vfio_pci_set_irqs_ioctl(vdev, VFIO_IRQ_SET_DATA_NONE | | 97 | vfio_pci_set_irqs_ioctl(vdev, VFIO_IRQ_SET_DATA_NONE | |
| 100 | VFIO_IRQ_SET_ACTION_TRIGGER, | 98 | VFIO_IRQ_SET_ACTION_TRIGGER, |
| @@ -104,22 +102,40 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev) | |||
| 104 | 102 | ||
| 105 | vfio_config_free(vdev); | 103 | vfio_config_free(vdev); |
| 106 | 104 | ||
| 107 | pci_reset_function(vdev->pdev); | ||
| 108 | |||
| 109 | if (pci_load_and_free_saved_state(vdev->pdev, | ||
| 110 | &vdev->pci_saved_state) == 0) | ||
| 111 | pci_restore_state(vdev->pdev); | ||
| 112 | else | ||
| 113 | pr_info("%s: Couldn't reload %s saved state\n", | ||
| 114 | __func__, dev_name(&vdev->pdev->dev)); | ||
| 115 | |||
| 116 | for (bar = PCI_STD_RESOURCES; bar <= PCI_STD_RESOURCE_END; bar++) { | 105 | for (bar = PCI_STD_RESOURCES; bar <= PCI_STD_RESOURCE_END; bar++) { |
| 117 | if (!vdev->barmap[bar]) | 106 | if (!vdev->barmap[bar]) |
| 118 | continue; | 107 | continue; |
| 119 | pci_iounmap(vdev->pdev, vdev->barmap[bar]); | 108 | pci_iounmap(pdev, vdev->barmap[bar]); |
| 120 | pci_release_selected_regions(vdev->pdev, 1 << bar); | 109 | pci_release_selected_regions(pdev, 1 << bar); |
| 121 | vdev->barmap[bar] = NULL; | 110 | vdev->barmap[bar] = NULL; |
| 122 | } | 111 | } |
| 112 | |||
| 113 | /* | ||
| 114 | * If we have saved state, restore it. If we can reset the device, | ||
| 115 | * even better. Resetting with current state seems better than | ||
| 116 | * nothing, but saving and restoring current state without reset | ||
| 117 | * is just busy work. | ||
| 118 | */ | ||
| 119 | if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) { | ||
| 120 | pr_info("%s: Couldn't reload %s saved state\n", | ||
| 121 | __func__, dev_name(&pdev->dev)); | ||
| 122 | |||
| 123 | if (!vdev->reset_works) | ||
| 124 | return; | ||
| 125 | |||
| 126 | pci_save_state(pdev); | ||
| 127 | } | ||
| 128 | |||
| 129 | /* | ||
| 130 | * Disable INTx and MSI, presumably to avoid spurious interrupts | ||
| 131 | * during reset. Stolen from pci_reset_function() | ||
| 132 | */ | ||
| 133 | pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE); | ||
| 134 | |||
| 135 | if (vdev->reset_works) | ||
| 136 | __pci_reset_function(pdev); | ||
| 137 | |||
| 138 | pci_restore_state(pdev); | ||
| 123 | } | 139 | } |
| 124 | 140 | ||
| 125 | static void vfio_pci_release(void *device_data) | 141 | static void vfio_pci_release(void *device_data) |
| @@ -327,15 +343,10 @@ static long vfio_pci_ioctl(void *device_data, | |||
| 327 | hdr.count > vfio_pci_get_irq_count(vdev, hdr.index)) | 343 | hdr.count > vfio_pci_get_irq_count(vdev, hdr.index)) |
| 328 | return -EINVAL; | 344 | return -EINVAL; |
| 329 | 345 | ||
| 330 | data = kmalloc(hdr.count * size, GFP_KERNEL); | 346 | data = memdup_user((void __user *)(arg + minsz), |
| 331 | if (!data) | 347 | hdr.count * size); |
| 332 | return -ENOMEM; | 348 | if (IS_ERR(data)) |
| 333 | 349 | return PTR_ERR(data); | |
| 334 | if (copy_from_user(data, (void __user *)(arg + minsz), | ||
| 335 | hdr.count * size)) { | ||
| 336 | kfree(data); | ||
| 337 | return -EFAULT; | ||
| 338 | } | ||
| 339 | } | 350 | } |
| 340 | 351 | ||
| 341 | mutex_lock(&vdev->igate); | 352 | mutex_lock(&vdev->igate); |
| @@ -562,9 +573,9 @@ static int __init vfio_pci_init(void) | |||
| 562 | 573 | ||
| 563 | return 0; | 574 | return 0; |
| 564 | 575 | ||
| 565 | out_virqfd: | ||
| 566 | vfio_pci_virqfd_exit(); | ||
| 567 | out_driver: | 576 | out_driver: |
| 577 | vfio_pci_virqfd_exit(); | ||
| 578 | out_virqfd: | ||
| 568 | vfio_pci_uninit_perm_bits(); | 579 | vfio_pci_uninit_perm_bits(); |
| 569 | return ret; | 580 | return ret; |
| 570 | } | 581 | } |
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 56097c6d072d..12c264d3b058 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c | |||
| @@ -191,6 +191,17 @@ static void vfio_container_put(struct vfio_container *container) | |||
| 191 | kref_put(&container->kref, vfio_container_release); | 191 | kref_put(&container->kref, vfio_container_release); |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | static void vfio_group_unlock_and_free(struct vfio_group *group) | ||
| 195 | { | ||
| 196 | mutex_unlock(&vfio.group_lock); | ||
| 197 | /* | ||
| 198 | * Unregister outside of lock. A spurious callback is harmless now | ||
| 199 | * that the group is no longer in vfio.group_list. | ||
| 200 | */ | ||
| 201 | iommu_group_unregister_notifier(group->iommu_group, &group->nb); | ||
| 202 | kfree(group); | ||
| 203 | } | ||
| 204 | |||
| 194 | /** | 205 | /** |
| 195 | * Group objects - create, release, get, put, search | 206 | * Group objects - create, release, get, put, search |
| 196 | */ | 207 | */ |
| @@ -229,8 +240,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) | |||
| 229 | 240 | ||
| 230 | minor = vfio_alloc_group_minor(group); | 241 | minor = vfio_alloc_group_minor(group); |
| 231 | if (minor < 0) { | 242 | if (minor < 0) { |
| 232 | mutex_unlock(&vfio.group_lock); | 243 | vfio_group_unlock_and_free(group); |
| 233 | kfree(group); | ||
| 234 | return ERR_PTR(minor); | 244 | return ERR_PTR(minor); |
| 235 | } | 245 | } |
| 236 | 246 | ||
| @@ -239,8 +249,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) | |||
| 239 | if (tmp->iommu_group == iommu_group) { | 249 | if (tmp->iommu_group == iommu_group) { |
| 240 | vfio_group_get(tmp); | 250 | vfio_group_get(tmp); |
| 241 | vfio_free_group_minor(minor); | 251 | vfio_free_group_minor(minor); |
| 242 | mutex_unlock(&vfio.group_lock); | 252 | vfio_group_unlock_and_free(group); |
| 243 | kfree(group); | ||
| 244 | return tmp; | 253 | return tmp; |
| 245 | } | 254 | } |
| 246 | } | 255 | } |
| @@ -249,8 +258,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) | |||
| 249 | group, "%d", iommu_group_id(iommu_group)); | 258 | group, "%d", iommu_group_id(iommu_group)); |
| 250 | if (IS_ERR(dev)) { | 259 | if (IS_ERR(dev)) { |
| 251 | vfio_free_group_minor(minor); | 260 | vfio_free_group_minor(minor); |
| 252 | mutex_unlock(&vfio.group_lock); | 261 | vfio_group_unlock_and_free(group); |
| 253 | kfree(group); | ||
| 254 | return (struct vfio_group *)dev; /* ERR_PTR */ | 262 | return (struct vfio_group *)dev; /* ERR_PTR */ |
| 255 | } | 263 | } |
| 256 | 264 | ||
| @@ -274,16 +282,7 @@ static void vfio_group_release(struct kref *kref) | |||
| 274 | device_destroy(vfio.class, MKDEV(MAJOR(vfio.devt), group->minor)); | 282 | device_destroy(vfio.class, MKDEV(MAJOR(vfio.devt), group->minor)); |
| 275 | list_del(&group->vfio_next); | 283 | list_del(&group->vfio_next); |
| 276 | vfio_free_group_minor(group->minor); | 284 | vfio_free_group_minor(group->minor); |
| 277 | 285 | vfio_group_unlock_and_free(group); | |
| 278 | mutex_unlock(&vfio.group_lock); | ||
| 279 | |||
| 280 | /* | ||
| 281 | * Unregister outside of lock. A spurious callback is harmless now | ||
| 282 | * that the group is no longer in vfio.group_list. | ||
| 283 | */ | ||
| 284 | iommu_group_unregister_notifier(group->iommu_group, &group->nb); | ||
| 285 | |||
| 286 | kfree(group); | ||
| 287 | } | 286 | } |
| 288 | 287 | ||
| 289 | static void vfio_group_put(struct vfio_group *group) | 288 | static void vfio_group_put(struct vfio_group *group) |
| @@ -466,8 +465,9 @@ static int vfio_dev_viable(struct device *dev, void *data) | |||
| 466 | { | 465 | { |
| 467 | struct vfio_group *group = data; | 466 | struct vfio_group *group = data; |
| 468 | struct vfio_device *device; | 467 | struct vfio_device *device; |
| 468 | struct device_driver *drv = ACCESS_ONCE(dev->driver); | ||
| 469 | 469 | ||
| 470 | if (!dev->driver || vfio_whitelisted_driver(dev->driver)) | 470 | if (!drv || vfio_whitelisted_driver(drv)) |
| 471 | return 0; | 471 | return 0; |
| 472 | 472 | ||
| 473 | device = vfio_group_get_device(group, dev); | 473 | device = vfio_group_get_device(group, dev); |
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 809b0de59c09..ee59b74768d9 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c | |||
| @@ -10,33 +10,32 @@ static DEFINE_IDA(virtio_index_ida); | |||
| 10 | static ssize_t device_show(struct device *_d, | 10 | static ssize_t device_show(struct device *_d, |
| 11 | struct device_attribute *attr, char *buf) | 11 | struct device_attribute *attr, char *buf) |
| 12 | { | 12 | { |
| 13 | struct virtio_device *dev = container_of(_d,struct virtio_device,dev); | 13 | struct virtio_device *dev = dev_to_virtio(_d); |
| 14 | return sprintf(buf, "0x%04x\n", dev->id.device); | 14 | return sprintf(buf, "0x%04x\n", dev->id.device); |
| 15 | } | 15 | } |
| 16 | static ssize_t vendor_show(struct device *_d, | 16 | static ssize_t vendor_show(struct device *_d, |
| 17 | struct device_attribute *attr, char *buf) | 17 | struct device_attribute *attr, char *buf) |
| 18 | { | 18 | { |
| 19 | struct virtio_device *dev = container_of(_d,struct virtio_device,dev); | 19 | struct virtio_device *dev = dev_to_virtio(_d); |
| 20 | return sprintf(buf, "0x%04x\n", dev->id.vendor); | 20 | return sprintf(buf, "0x%04x\n", dev->id.vendor); |
| 21 | } | 21 | } |
| 22 | static ssize_t status_show(struct device *_d, | 22 | static ssize_t status_show(struct device *_d, |
| 23 | struct device_attribute *attr, char *buf) | 23 | struct device_attribute *attr, char *buf) |
| 24 | { | 24 | { |
| 25 | struct virtio_device *dev = container_of(_d,struct virtio_device,dev); | 25 | struct virtio_device *dev = dev_to_virtio(_d); |
| 26 | return sprintf(buf, "0x%08x\n", dev->config->get_status(dev)); | 26 | return sprintf(buf, "0x%08x\n", dev->config->get_status(dev)); |
| 27 | } | 27 | } |
| 28 | static ssize_t modalias_show(struct device *_d, | 28 | static ssize_t modalias_show(struct device *_d, |
| 29 | struct device_attribute *attr, char *buf) | 29 | struct device_attribute *attr, char *buf) |
| 30 | { | 30 | { |
| 31 | struct virtio_device *dev = container_of(_d,struct virtio_device,dev); | 31 | struct virtio_device *dev = dev_to_virtio(_d); |
| 32 | |||
| 33 | return sprintf(buf, "virtio:d%08Xv%08X\n", | 32 | return sprintf(buf, "virtio:d%08Xv%08X\n", |
| 34 | dev->id.device, dev->id.vendor); | 33 | dev->id.device, dev->id.vendor); |
| 35 | } | 34 | } |
| 36 | static ssize_t features_show(struct device *_d, | 35 | static ssize_t features_show(struct device *_d, |
| 37 | struct device_attribute *attr, char *buf) | 36 | struct device_attribute *attr, char *buf) |
| 38 | { | 37 | { |
| 39 | struct virtio_device *dev = container_of(_d, struct virtio_device, dev); | 38 | struct virtio_device *dev = dev_to_virtio(_d); |
| 40 | unsigned int i; | 39 | unsigned int i; |
| 41 | ssize_t len = 0; | 40 | ssize_t len = 0; |
| 42 | 41 | ||
| @@ -71,10 +70,10 @@ static inline int virtio_id_match(const struct virtio_device *dev, | |||
| 71 | static int virtio_dev_match(struct device *_dv, struct device_driver *_dr) | 70 | static int virtio_dev_match(struct device *_dv, struct device_driver *_dr) |
| 72 | { | 71 | { |
| 73 | unsigned int i; | 72 | unsigned int i; |
| 74 | struct virtio_device *dev = container_of(_dv,struct virtio_device,dev); | 73 | struct virtio_device *dev = dev_to_virtio(_dv); |
| 75 | const struct virtio_device_id *ids; | 74 | const struct virtio_device_id *ids; |
| 76 | 75 | ||
| 77 | ids = container_of(_dr, struct virtio_driver, driver)->id_table; | 76 | ids = drv_to_virtio(_dr)->id_table; |
| 78 | for (i = 0; ids[i].device; i++) | 77 | for (i = 0; ids[i].device; i++) |
| 79 | if (virtio_id_match(dev, &ids[i])) | 78 | if (virtio_id_match(dev, &ids[i])) |
| 80 | return 1; | 79 | return 1; |
| @@ -83,7 +82,7 @@ static int virtio_dev_match(struct device *_dv, struct device_driver *_dr) | |||
| 83 | 82 | ||
| 84 | static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env) | 83 | static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env) |
| 85 | { | 84 | { |
| 86 | struct virtio_device *dev = container_of(_dv,struct virtio_device,dev); | 85 | struct virtio_device *dev = dev_to_virtio(_dv); |
| 87 | 86 | ||
| 88 | return add_uevent_var(env, "MODALIAS=virtio:d%08Xv%08X", | 87 | return add_uevent_var(env, "MODALIAS=virtio:d%08Xv%08X", |
| 89 | dev->id.device, dev->id.vendor); | 88 | dev->id.device, dev->id.vendor); |
| @@ -98,8 +97,7 @@ void virtio_check_driver_offered_feature(const struct virtio_device *vdev, | |||
| 98 | unsigned int fbit) | 97 | unsigned int fbit) |
| 99 | { | 98 | { |
| 100 | unsigned int i; | 99 | unsigned int i; |
| 101 | struct virtio_driver *drv = container_of(vdev->dev.driver, | 100 | struct virtio_driver *drv = drv_to_virtio(vdev->dev.driver); |
| 102 | struct virtio_driver, driver); | ||
| 103 | 101 | ||
| 104 | for (i = 0; i < drv->feature_table_size; i++) | 102 | for (i = 0; i < drv->feature_table_size; i++) |
| 105 | if (drv->feature_table[i] == fbit) | 103 | if (drv->feature_table[i] == fbit) |
| @@ -111,9 +109,8 @@ EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature); | |||
| 111 | static int virtio_dev_probe(struct device *_d) | 109 | static int virtio_dev_probe(struct device *_d) |
| 112 | { | 110 | { |
| 113 | int err, i; | 111 | int err, i; |
| 114 | struct virtio_device *dev = container_of(_d,struct virtio_device,dev); | 112 | struct virtio_device *dev = dev_to_virtio(_d); |
| 115 | struct virtio_driver *drv = container_of(dev->dev.driver, | 113 | struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); |
| 116 | struct virtio_driver, driver); | ||
| 117 | u32 device_features; | 114 | u32 device_features; |
| 118 | 115 | ||
| 119 | /* We have a driver! */ | 116 | /* We have a driver! */ |
| @@ -152,9 +149,8 @@ static int virtio_dev_probe(struct device *_d) | |||
| 152 | 149 | ||
| 153 | static int virtio_dev_remove(struct device *_d) | 150 | static int virtio_dev_remove(struct device *_d) |
| 154 | { | 151 | { |
| 155 | struct virtio_device *dev = container_of(_d,struct virtio_device,dev); | 152 | struct virtio_device *dev = dev_to_virtio(_d); |
| 156 | struct virtio_driver *drv = container_of(dev->dev.driver, | 153 | struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); |
| 157 | struct virtio_driver, driver); | ||
| 158 | 154 | ||
| 159 | drv->remove(dev); | 155 | drv->remove(dev); |
| 160 | 156 | ||
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 2a70558b36ea..d19fe3e323b4 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
| @@ -139,10 +139,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num) | |||
| 139 | struct page *page = balloon_page_enqueue(vb_dev_info); | 139 | struct page *page = balloon_page_enqueue(vb_dev_info); |
| 140 | 140 | ||
| 141 | if (!page) { | 141 | if (!page) { |
| 142 | if (printk_ratelimit()) | 142 | dev_info_ratelimited(&vb->vdev->dev, |
| 143 | dev_printk(KERN_INFO, &vb->vdev->dev, | 143 | "Out of puff! Can't get %u pages\n", |
| 144 | "Out of puff! Can't get %u pages\n", | 144 | VIRTIO_BALLOON_PAGES_PER_PAGE); |
| 145 | VIRTIO_BALLOON_PAGES_PER_PAGE); | ||
| 146 | /* Sleep for at least 1/5 of a second before retry. */ | 145 | /* Sleep for at least 1/5 of a second before retry. */ |
| 147 | msleep(200); | 146 | msleep(200); |
| 148 | break; | 147 | break; |
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 6b1b7e184939..634f80bcdbd7 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c | |||
| @@ -225,7 +225,7 @@ static void vm_notify(struct virtqueue *vq) | |||
| 225 | 225 | ||
| 226 | /* We write the queue's selector into the notification register to | 226 | /* We write the queue's selector into the notification register to |
| 227 | * signal the other end */ | 227 | * signal the other end */ |
| 228 | writel(virtqueue_get_queue_index(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY); | 228 | writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY); |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | /* Notify all virtqueues on an interrupt. */ | 231 | /* Notify all virtqueues on an interrupt. */ |
| @@ -266,7 +266,7 @@ static void vm_del_vq(struct virtqueue *vq) | |||
| 266 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); | 266 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); |
| 267 | struct virtio_mmio_vq_info *info = vq->priv; | 267 | struct virtio_mmio_vq_info *info = vq->priv; |
| 268 | unsigned long flags, size; | 268 | unsigned long flags, size; |
| 269 | unsigned int index = virtqueue_get_queue_index(vq); | 269 | unsigned int index = vq->index; |
| 270 | 270 | ||
| 271 | spin_lock_irqsave(&vm_dev->lock, flags); | 271 | spin_lock_irqsave(&vm_dev->lock, flags); |
| 272 | list_del(&info->node); | 272 | list_del(&info->node); |
| @@ -521,25 +521,33 @@ static int vm_cmdline_set(const char *device, | |||
| 521 | int err; | 521 | int err; |
| 522 | struct resource resources[2] = {}; | 522 | struct resource resources[2] = {}; |
| 523 | char *str; | 523 | char *str; |
| 524 | long long int base; | 524 | long long int base, size; |
| 525 | unsigned int irq; | ||
| 525 | int processed, consumed = 0; | 526 | int processed, consumed = 0; |
| 526 | struct platform_device *pdev; | 527 | struct platform_device *pdev; |
| 527 | 528 | ||
| 528 | resources[0].flags = IORESOURCE_MEM; | 529 | /* Consume "size" part of the command line parameter */ |
| 529 | resources[1].flags = IORESOURCE_IRQ; | 530 | size = memparse(device, &str); |
| 530 | |||
| 531 | resources[0].end = memparse(device, &str) - 1; | ||
| 532 | 531 | ||
| 532 | /* Get "@<base>:<irq>[:<id>]" chunks */ | ||
| 533 | processed = sscanf(str, "@%lli:%u%n:%d%n", | 533 | processed = sscanf(str, "@%lli:%u%n:%d%n", |
| 534 | &base, &resources[1].start, &consumed, | 534 | &base, &irq, &consumed, |
| 535 | &vm_cmdline_id, &consumed); | 535 | &vm_cmdline_id, &consumed); |
| 536 | 536 | ||
| 537 | if (processed < 2 || processed > 3 || str[consumed]) | 537 | /* |
| 538 | * sscanf() must processes at least 2 chunks; also there | ||
| 539 | * must be no extra characters after the last chunk, so | ||
| 540 | * str[consumed] must be '\0' | ||
| 541 | */ | ||
| 542 | if (processed < 2 || str[consumed]) | ||
| 538 | return -EINVAL; | 543 | return -EINVAL; |
| 539 | 544 | ||
| 545 | resources[0].flags = IORESOURCE_MEM; | ||
| 540 | resources[0].start = base; | 546 | resources[0].start = base; |
| 541 | resources[0].end += base; | 547 | resources[0].end = base + size - 1; |
| 542 | resources[1].end = resources[1].start; | 548 | |
| 549 | resources[1].flags = IORESOURCE_IRQ; | ||
| 550 | resources[1].start = resources[1].end = irq; | ||
| 543 | 551 | ||
| 544 | if (!vm_cmdline_parent_registered) { | 552 | if (!vm_cmdline_parent_registered) { |
| 545 | err = device_register(&vm_cmdline_parent); | 553 | err = device_register(&vm_cmdline_parent); |
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index c33aea36598a..e3ecc94591ad 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
| @@ -203,8 +203,7 @@ static void vp_notify(struct virtqueue *vq) | |||
| 203 | 203 | ||
| 204 | /* we write the queue's selector into the notification register to | 204 | /* we write the queue's selector into the notification register to |
| 205 | * signal the other end */ | 205 | * signal the other end */ |
| 206 | iowrite16(virtqueue_get_queue_index(vq), | 206 | iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY); |
| 207 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY); | ||
| 208 | } | 207 | } |
| 209 | 208 | ||
| 210 | /* Handle a configuration change: Tell driver if it wants to know. */ | 209 | /* Handle a configuration change: Tell driver if it wants to know. */ |
| @@ -479,8 +478,7 @@ static void vp_del_vq(struct virtqueue *vq) | |||
| 479 | list_del(&info->node); | 478 | list_del(&info->node); |
| 480 | spin_unlock_irqrestore(&vp_dev->lock, flags); | 479 | spin_unlock_irqrestore(&vp_dev->lock, flags); |
| 481 | 480 | ||
| 482 | iowrite16(virtqueue_get_queue_index(vq), | 481 | iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); |
| 483 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); | ||
| 484 | 482 | ||
| 485 | if (vp_dev->msix_enabled) { | 483 | if (vp_dev->msix_enabled) { |
| 486 | iowrite16(VIRTIO_MSI_NO_VECTOR, | 484 | iowrite16(VIRTIO_MSI_NO_VECTOR, |
| @@ -830,16 +828,4 @@ static struct pci_driver virtio_pci_driver = { | |||
| 830 | #endif | 828 | #endif |
| 831 | }; | 829 | }; |
| 832 | 830 | ||
| 833 | static int __init virtio_pci_init(void) | 831 | module_pci_driver(virtio_pci_driver); |
| 834 | { | ||
| 835 | return pci_register_driver(&virtio_pci_driver); | ||
| 836 | } | ||
| 837 | |||
| 838 | module_init(virtio_pci_init); | ||
| 839 | |||
| 840 | static void __exit virtio_pci_exit(void) | ||
| 841 | { | ||
| 842 | pci_unregister_driver(&virtio_pci_driver); | ||
| 843 | } | ||
| 844 | |||
| 845 | module_exit(virtio_pci_exit); | ||
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index e639584b2dbd..ffd7e7da5d3b 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
| @@ -93,8 +93,6 @@ struct vring_virtqueue | |||
| 93 | /* Host publishes avail event idx */ | 93 | /* Host publishes avail event idx */ |
| 94 | bool event; | 94 | bool event; |
| 95 | 95 | ||
| 96 | /* Number of free buffers */ | ||
| 97 | unsigned int num_free; | ||
| 98 | /* Head of free buffer list. */ | 96 | /* Head of free buffer list. */ |
| 99 | unsigned int free_head; | 97 | unsigned int free_head; |
| 100 | /* Number we've added since last sync. */ | 98 | /* Number we've added since last sync. */ |
| @@ -106,9 +104,6 @@ struct vring_virtqueue | |||
| 106 | /* How to notify other side. FIXME: commonalize hcalls! */ | 104 | /* How to notify other side. FIXME: commonalize hcalls! */ |
| 107 | void (*notify)(struct virtqueue *vq); | 105 | void (*notify)(struct virtqueue *vq); |
| 108 | 106 | ||
| 109 | /* Index of the queue */ | ||
| 110 | int queue_index; | ||
| 111 | |||
| 112 | #ifdef DEBUG | 107 | #ifdef DEBUG |
| 113 | /* They're supposed to lock for us. */ | 108 | /* They're supposed to lock for us. */ |
| 114 | unsigned int in_use; | 109 | unsigned int in_use; |
| @@ -135,6 +130,13 @@ static int vring_add_indirect(struct vring_virtqueue *vq, | |||
| 135 | unsigned head; | 130 | unsigned head; |
| 136 | int i; | 131 | int i; |
| 137 | 132 | ||
| 133 | /* | ||
| 134 | * We require lowmem mappings for the descriptors because | ||
| 135 | * otherwise virt_to_phys will give us bogus addresses in the | ||
| 136 | * virtqueue. | ||
| 137 | */ | ||
| 138 | gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH); | ||
| 139 | |||
| 138 | desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp); | 140 | desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp); |
| 139 | if (!desc) | 141 | if (!desc) |
| 140 | return -ENOMEM; | 142 | return -ENOMEM; |
| @@ -160,7 +162,7 @@ static int vring_add_indirect(struct vring_virtqueue *vq, | |||
| 160 | desc[i-1].next = 0; | 162 | desc[i-1].next = 0; |
| 161 | 163 | ||
| 162 | /* We're about to use a buffer */ | 164 | /* We're about to use a buffer */ |
| 163 | vq->num_free--; | 165 | vq->vq.num_free--; |
| 164 | 166 | ||
| 165 | /* Use a single buffer which doesn't continue */ | 167 | /* Use a single buffer which doesn't continue */ |
| 166 | head = vq->free_head; | 168 | head = vq->free_head; |
| @@ -174,13 +176,6 @@ static int vring_add_indirect(struct vring_virtqueue *vq, | |||
| 174 | return head; | 176 | return head; |
| 175 | } | 177 | } |
| 176 | 178 | ||
| 177 | int virtqueue_get_queue_index(struct virtqueue *_vq) | ||
| 178 | { | ||
| 179 | struct vring_virtqueue *vq = to_vvq(_vq); | ||
| 180 | return vq->queue_index; | ||
| 181 | } | ||
| 182 | EXPORT_SYMBOL_GPL(virtqueue_get_queue_index); | ||
| 183 | |||
| 184 | /** | 179 | /** |
| 185 | * virtqueue_add_buf - expose buffer to other end | 180 | * virtqueue_add_buf - expose buffer to other end |
| 186 | * @vq: the struct virtqueue we're talking about. | 181 | * @vq: the struct virtqueue we're talking about. |
| @@ -193,10 +188,7 @@ EXPORT_SYMBOL_GPL(virtqueue_get_queue_index); | |||
| 193 | * Caller must ensure we don't call this with other virtqueue operations | 188 | * Caller must ensure we don't call this with other virtqueue operations |
| 194 | * at the same time (except where noted). | 189 | * at the same time (except where noted). |
| 195 | * | 190 | * |
| 196 | * Returns remaining capacity of queue or a negative error | 191 | * Returns zero or a negative error (ie. ENOSPC, ENOMEM). |
| 197 | * (ie. ENOSPC). Note that it only really makes sense to treat all | ||
| 198 | * positive return values as "available": indirect buffers mean that | ||
| 199 | * we can put an entire sg[] array inside a single queue entry. | ||
| 200 | */ | 192 | */ |
| 201 | int virtqueue_add_buf(struct virtqueue *_vq, | 193 | int virtqueue_add_buf(struct virtqueue *_vq, |
| 202 | struct scatterlist sg[], | 194 | struct scatterlist sg[], |
| @@ -228,7 +220,7 @@ int virtqueue_add_buf(struct virtqueue *_vq, | |||
| 228 | 220 | ||
| 229 | /* If the host supports indirect descriptor tables, and we have multiple | 221 | /* If the host supports indirect descriptor tables, and we have multiple |
| 230 | * buffers, then go indirect. FIXME: tune this threshold */ | 222 | * buffers, then go indirect. FIXME: tune this threshold */ |
| 231 | if (vq->indirect && (out + in) > 1 && vq->num_free) { | 223 | if (vq->indirect && (out + in) > 1 && vq->vq.num_free) { |
| 232 | head = vring_add_indirect(vq, sg, out, in, gfp); | 224 | head = vring_add_indirect(vq, sg, out, in, gfp); |
| 233 | if (likely(head >= 0)) | 225 | if (likely(head >= 0)) |
| 234 | goto add_head; | 226 | goto add_head; |
| @@ -237,9 +229,9 @@ int virtqueue_add_buf(struct virtqueue *_vq, | |||
| 237 | BUG_ON(out + in > vq->vring.num); | 229 | BUG_ON(out + in > vq->vring.num); |
| 238 | BUG_ON(out + in == 0); | 230 | BUG_ON(out + in == 0); |
| 239 | 231 | ||
| 240 | if (vq->num_free < out + in) { | 232 | if (vq->vq.num_free < out + in) { |
| 241 | pr_debug("Can't add buf len %i - avail = %i\n", | 233 | pr_debug("Can't add buf len %i - avail = %i\n", |
| 242 | out + in, vq->num_free); | 234 | out + in, vq->vq.num_free); |
| 243 | /* FIXME: for historical reasons, we force a notify here if | 235 | /* FIXME: for historical reasons, we force a notify here if |
| 244 | * there are outgoing parts to the buffer. Presumably the | 236 | * there are outgoing parts to the buffer. Presumably the |
| 245 | * host should service the ring ASAP. */ | 237 | * host should service the ring ASAP. */ |
| @@ -250,7 +242,7 @@ int virtqueue_add_buf(struct virtqueue *_vq, | |||
| 250 | } | 242 | } |
| 251 | 243 | ||
| 252 | /* We're about to use some buffers from the free list. */ | 244 | /* We're about to use some buffers from the free list. */ |
| 253 | vq->num_free -= out + in; | 245 | vq->vq.num_free -= out + in; |
| 254 | 246 | ||
| 255 | head = vq->free_head; | 247 | head = vq->free_head; |
| 256 | for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) { | 248 | for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) { |
| @@ -296,7 +288,7 @@ add_head: | |||
| 296 | pr_debug("Added buffer head %i to %p\n", head, vq); | 288 | pr_debug("Added buffer head %i to %p\n", head, vq); |
| 297 | END_USE(vq); | 289 | END_USE(vq); |
| 298 | 290 | ||
| 299 | return vq->num_free; | 291 | return 0; |
| 300 | } | 292 | } |
| 301 | EXPORT_SYMBOL_GPL(virtqueue_add_buf); | 293 | EXPORT_SYMBOL_GPL(virtqueue_add_buf); |
| 302 | 294 | ||
| @@ -393,13 +385,13 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head) | |||
| 393 | 385 | ||
| 394 | while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) { | 386 | while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) { |
| 395 | i = vq->vring.desc[i].next; | 387 | i = vq->vring.desc[i].next; |
| 396 | vq->num_free++; | 388 | vq->vq.num_free++; |
| 397 | } | 389 | } |
| 398 | 390 | ||
| 399 | vq->vring.desc[i].next = vq->free_head; | 391 | vq->vring.desc[i].next = vq->free_head; |
| 400 | vq->free_head = head; | 392 | vq->free_head = head; |
| 401 | /* Plus final descriptor */ | 393 | /* Plus final descriptor */ |
| 402 | vq->num_free++; | 394 | vq->vq.num_free++; |
| 403 | } | 395 | } |
| 404 | 396 | ||
| 405 | static inline bool more_used(const struct vring_virtqueue *vq) | 397 | static inline bool more_used(const struct vring_virtqueue *vq) |
| @@ -599,7 +591,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq) | |||
| 599 | return buf; | 591 | return buf; |
| 600 | } | 592 | } |
| 601 | /* That should have freed everything. */ | 593 | /* That should have freed everything. */ |
| 602 | BUG_ON(vq->num_free != vq->vring.num); | 594 | BUG_ON(vq->vq.num_free != vq->vring.num); |
| 603 | 595 | ||
| 604 | END_USE(vq); | 596 | END_USE(vq); |
| 605 | return NULL; | 597 | return NULL; |
| @@ -653,12 +645,13 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
| 653 | vq->vq.callback = callback; | 645 | vq->vq.callback = callback; |
| 654 | vq->vq.vdev = vdev; | 646 | vq->vq.vdev = vdev; |
| 655 | vq->vq.name = name; | 647 | vq->vq.name = name; |
| 648 | vq->vq.num_free = num; | ||
| 649 | vq->vq.index = index; | ||
| 656 | vq->notify = notify; | 650 | vq->notify = notify; |
| 657 | vq->weak_barriers = weak_barriers; | 651 | vq->weak_barriers = weak_barriers; |
| 658 | vq->broken = false; | 652 | vq->broken = false; |
| 659 | vq->last_used_idx = 0; | 653 | vq->last_used_idx = 0; |
| 660 | vq->num_added = 0; | 654 | vq->num_added = 0; |
| 661 | vq->queue_index = index; | ||
| 662 | list_add_tail(&vq->vq.list, &vdev->vqs); | 655 | list_add_tail(&vq->vq.list, &vdev->vqs); |
| 663 | #ifdef DEBUG | 656 | #ifdef DEBUG |
| 664 | vq->in_use = false; | 657 | vq->in_use = false; |
| @@ -673,7 +666,6 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
| 673 | vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; | 666 | vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; |
| 674 | 667 | ||
| 675 | /* Put everything in free lists. */ | 668 | /* Put everything in free lists. */ |
| 676 | vq->num_free = num; | ||
| 677 | vq->free_head = 0; | 669 | vq->free_head = 0; |
| 678 | for (i = 0; i < num-1; i++) { | 670 | for (i = 0; i < num-1; i++) { |
| 679 | vq->vring.desc[i].next = i+1; | 671 | vq->vring.desc[i].next = i+1; |
