From 12ce6b0d21c2038ddae9da418aab198e284ad922 Mon Sep 17 00:00:00 2001 From: Max Staudt Date: Fri, 23 Aug 2019 12:49:11 +0200 Subject: ata/pata_buddha: Probe via modalias instead of initcall Up until now, the pata_buddha driver would only check for cards on initcall time. Now, the kernel will call its probe function as soon as a compatible card is detected. v7: Removed suppress_bind_attrs that slipped in v6: Only do the drvdata workaround for X-Surf (remove breaks otherwise) Style v5: Remove module_exit(): There's no good way to handle the X-Surf hack. Also include a workaround to save X-Surf's drvdata in case zorro8390 is active. v4: Clean up pata_buddha_probe() by using ent->driver_data. Support X-Surf via late_initcall() v3: Clean up devm_*, implement device removal. v2: Rename 'zdev' to 'z' to make the patch easy to analyse with git diff --ignore-space-change Signed-off-by: Max Staudt Signed-off-by: Jens Axboe --- drivers/ata/pata_buddha.c | 228 +++++++++++++++++++++++++++------------------- 1 file changed, 135 insertions(+), 93 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_buddha.c b/drivers/ata/pata_buddha.c index 11a8044ff633..27d4c417fc60 100644 --- a/drivers/ata/pata_buddha.c +++ b/drivers/ata/pata_buddha.c @@ -18,7 +18,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -29,7 +31,7 @@ #include #define DRV_NAME "pata_buddha" -#define DRV_VERSION "0.1.0" +#define DRV_VERSION "0.1.1" #define BUDDHA_BASE1 0x800 #define BUDDHA_BASE2 0xa00 @@ -47,11 +49,11 @@ enum { BOARD_XSURF }; -static unsigned int buddha_bases[3] __initdata = { +static unsigned int buddha_bases[3] = { BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3 }; -static unsigned int xsurf_bases[2] __initdata = { +static unsigned int xsurf_bases[2] = { XSURF_BASE1, XSURF_BASE2 }; @@ -145,111 +147,151 @@ static struct ata_port_operations pata_xsurf_ops = { .set_mode = pata_buddha_set_mode, }; -static int __init pata_buddha_init_one(void) +static int pata_buddha_probe(struct zorro_dev *z, + const struct zorro_device_id *ent) { - struct zorro_dev *z = NULL; + static const char * const board_name[] = { + "Buddha", "Catweasel", "X-Surf" + }; + struct ata_host *host; + void __iomem *buddha_board; + unsigned long board; + unsigned int type = ent->driver_data; + unsigned int nr_ports = (type == BOARD_CATWEASEL) ? 3 : 2; + void *old_drvdata; + int i; + + dev_info(&z->dev, "%s IDE controller\n", board_name[type]); + + board = z->resource.start; + + if (type != BOARD_XSURF) { + if (!devm_request_mem_region(&z->dev, + board + BUDDHA_BASE1, + 0x800, DRV_NAME)) + return -ENXIO; + } else { + if (!devm_request_mem_region(&z->dev, + board + XSURF_BASE1, + 0x1000, DRV_NAME)) + return -ENXIO; + if (!devm_request_mem_region(&z->dev, + board + XSURF_BASE2, + 0x1000, DRV_NAME)) { + } + } + + /* Workaround for X-Surf: Save drvdata in case zorro8390 has set it */ + if (type == BOARD_XSURF) + old_drvdata = dev_get_drvdata(&z->dev); + + /* allocate host */ + host = ata_host_alloc(&z->dev, nr_ports); + if (type == BOARD_XSURF) + dev_set_drvdata(&z->dev, old_drvdata); + if (!host) + return -ENXIO; + + buddha_board = ZTWO_VADDR(board); + + /* enable the board IRQ on Buddha/Catweasel */ + if (type != BOARD_XSURF) + z_writeb(0, buddha_board + BUDDHA_IRQ_MR); - while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { - static const char *board_name[] - = { "Buddha", "Catweasel", "X-Surf" }; - struct ata_host *host; - void __iomem *buddha_board; - unsigned long board; - unsigned int type, nr_ports = 2; - int i; - - if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) { - type = BOARD_BUDDHA; - } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL) { - type = BOARD_CATWEASEL; - nr_ports++; - } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF) { - type = BOARD_XSURF; - } else - continue; - - dev_info(&z->dev, "%s IDE controller\n", board_name[type]); - - board = z->resource.start; + for (i = 0; i < nr_ports; i++) { + struct ata_port *ap = host->ports[i]; + void __iomem *base, *irqport; + unsigned long ctl = 0; if (type != BOARD_XSURF) { - if (!devm_request_mem_region(&z->dev, - board + BUDDHA_BASE1, - 0x800, DRV_NAME)) - continue; + ap->ops = &pata_buddha_ops; + base = buddha_board + buddha_bases[i]; + ctl = BUDDHA_CONTROL; + irqport = buddha_board + BUDDHA_IRQ + i * 0x40; } else { - if (!devm_request_mem_region(&z->dev, - board + XSURF_BASE1, - 0x1000, DRV_NAME)) - continue; - if (!devm_request_mem_region(&z->dev, - board + XSURF_BASE2, - 0x1000, DRV_NAME)) - continue; + ap->ops = &pata_xsurf_ops; + base = buddha_board + xsurf_bases[i]; + /* X-Surf has no CS1* (Control/AltStat) */ + irqport = buddha_board + XSURF_IRQ; } - /* allocate host */ - host = ata_host_alloc(&z->dev, nr_ports); - if (!host) - continue; - - buddha_board = ZTWO_VADDR(board); - - /* enable the board IRQ on Buddha/Catweasel */ - if (type != BOARD_XSURF) - z_writeb(0, buddha_board + BUDDHA_IRQ_MR); - - for (i = 0; i < nr_ports; i++) { - struct ata_port *ap = host->ports[i]; - void __iomem *base, *irqport; - unsigned long ctl = 0; - - if (type != BOARD_XSURF) { - ap->ops = &pata_buddha_ops; - base = buddha_board + buddha_bases[i]; - ctl = BUDDHA_CONTROL; - irqport = buddha_board + BUDDHA_IRQ + i * 0x40; - } else { - ap->ops = &pata_xsurf_ops; - base = buddha_board + xsurf_bases[i]; - /* X-Surf has no CS1* (Control/AltStat) */ - irqport = buddha_board + XSURF_IRQ; - } - - ap->pio_mask = ATA_PIO4; - ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY; - - ap->ioaddr.data_addr = base; - ap->ioaddr.error_addr = base + 2 + 1 * 4; - ap->ioaddr.feature_addr = base + 2 + 1 * 4; - ap->ioaddr.nsect_addr = base + 2 + 2 * 4; - ap->ioaddr.lbal_addr = base + 2 + 3 * 4; - ap->ioaddr.lbam_addr = base + 2 + 4 * 4; - ap->ioaddr.lbah_addr = base + 2 + 5 * 4; - ap->ioaddr.device_addr = base + 2 + 6 * 4; - ap->ioaddr.status_addr = base + 2 + 7 * 4; - ap->ioaddr.command_addr = base + 2 + 7 * 4; - - if (ctl) { - ap->ioaddr.altstatus_addr = base + ctl; - ap->ioaddr.ctl_addr = base + ctl; - } - - ap->private_data = (void *)irqport; - - ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", board, - ctl ? board + buddha_bases[i] + ctl : 0); + ap->pio_mask = ATA_PIO4; + ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY; + + ap->ioaddr.data_addr = base; + ap->ioaddr.error_addr = base + 2 + 1 * 4; + ap->ioaddr.feature_addr = base + 2 + 1 * 4; + ap->ioaddr.nsect_addr = base + 2 + 2 * 4; + ap->ioaddr.lbal_addr = base + 2 + 3 * 4; + ap->ioaddr.lbam_addr = base + 2 + 4 * 4; + ap->ioaddr.lbah_addr = base + 2 + 5 * 4; + ap->ioaddr.device_addr = base + 2 + 6 * 4; + ap->ioaddr.status_addr = base + 2 + 7 * 4; + ap->ioaddr.command_addr = base + 2 + 7 * 4; + + if (ctl) { + ap->ioaddr.altstatus_addr = base + ctl; + ap->ioaddr.ctl_addr = base + ctl; } - ata_host_activate(host, IRQ_AMIGA_PORTS, ata_sff_interrupt, - IRQF_SHARED, &pata_buddha_sht); + ap->private_data = (void *)irqport; + ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", board, + ctl ? board + buddha_bases[i] + ctl : 0); } + ata_host_activate(host, IRQ_AMIGA_PORTS, ata_sff_interrupt, + IRQF_SHARED, &pata_buddha_sht); + return 0; } -module_init(pata_buddha_init_one); +static void pata_buddha_remove(struct zorro_dev *z) +{ + struct ata_host *host = dev_get_drvdata(&z->dev); + + ata_host_detach(host); +} + +static const struct zorro_device_id pata_buddha_zorro_tbl[] = { + { ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA, BOARD_BUDDHA}, + { ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL, BOARD_CATWEASEL}, + { 0 } +}; +MODULE_DEVICE_TABLE(zorro, pata_buddha_zorro_tbl); + +static struct zorro_driver pata_buddha_driver = { + .name = "pata_buddha", + .id_table = pata_buddha_zorro_tbl, + .probe = pata_buddha_probe, + .remove = pata_buddha_remove, +}; + +/* + * We cannot have a modalias for X-Surf boards, as it competes with the + * zorro8390 network driver. As a stopgap measure until we have proper + * MFD support for this board, we manually attach to it late after Zorro + * has enumerated its boards. + */ +static int __init pata_buddha_late_init(void) +{ + struct zorro_dev *z = NULL; + + /* Auto-bind to regular boards */ + zorro_register_driver(&pata_buddha_driver); + + /* Manually bind to all X-Surf boards */ + while ((z = zorro_find_device(ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, z))) { + static struct zorro_device_id xsurf_ent = { + ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, BOARD_XSURF + }; + + pata_buddha_probe(z, &xsurf_ent); + } + + return 0; +} +late_initcall(pata_buddha_late_init); MODULE_AUTHOR("Bartlomiej Zolnierkiewicz"); MODULE_DESCRIPTION("low-level driver for Buddha/Catweasel/X-Surf PATA"); -- cgit v1.2.3 From 759ad0979808a586816cf4f01bf5784080343d31 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 26 Aug 2019 12:57:18 +0200 Subject: acard_ahci: use dma_set_mask_and_coherent Use the dma_set_mask_and_coherent helper to set the DMA mask. Rely on the relatively recent change that setting a larger than required mask will never fail to avoid the need for the boilerplate 32-bit fallback code. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/ata/acard-ahci.c | 38 +++++--------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c index 85357f27a66b..753985c01517 100644 --- a/drivers/ata/acard-ahci.c +++ b/drivers/ata/acard-ahci.c @@ -160,37 +160,6 @@ static int acard_ahci_pci_device_resume(struct pci_dev *pdev) } #endif -static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) -{ - int rc; - - if (using_dac && - !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (rc) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "64-bit DMA enable failed\n"); - return rc; - } - } - } else { - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, "32-bit DMA enable failed\n"); - return rc; - } - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "32-bit consistent DMA enable failed\n"); - return rc; - } - } - return 0; -} - static void acard_ahci_pci_print_info(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); @@ -471,9 +440,12 @@ static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id } /* initialize adapter */ - rc = acard_ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); - if (rc) + rc = dma_set_mask_and_coherent(&pdev->dev, + DMA_BIT_MASK((hpriv->cap & HOST_CAP_64) ? 64 : 32)); + if (rc) { + dev_err(&pdev->dev, "DMA enable failed\n"); return rc; + } rc = ahci_reset_controller(host); if (rc) -- cgit v1.2.3 From b1716871c00dd48a8efa8ee93007490c939fc8c3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 26 Aug 2019 12:57:19 +0200 Subject: ahci: use dma_set_mask_and_coherent Use the dma_set_mask_and_coherent helper to set the DMA mask. Rely on the relatively recent change that setting a larger than required mask will never fail to avoid the need for the boilerplate 32-bit fallback code. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/ata/ahci.c | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index f7652baa6337..ad840f20f8e2 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -901,40 +901,23 @@ static int ahci_pci_device_resume(struct device *dev) static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) { + const int dma_bits = using_dac ? 64 : 32; int rc; /* * If the device fixup already set the dma_mask to some non-standard * value, don't extend it here. This happens on STA2X11, for example. + * + * XXX: manipulating the DMA mask from platform code is completely + * bogus, platform code should use dev->bus_dma_mask instead.. */ if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) return 0; - if (using_dac && - !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (rc) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "64-bit DMA enable failed\n"); - return rc; - } - } - } else { - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, "32-bit DMA enable failed\n"); - return rc; - } - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "32-bit consistent DMA enable failed\n"); - return rc; - } - } - return 0; + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits)); + if (rc) + dev_err(&pdev->dev, "DMA enable failed\n"); + return rc; } static void ahci_pci_print_info(struct ata_host *host) -- cgit v1.2.3 From 94c58148a6bcb1f2c342fb806409d35019b4bb12 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 26 Aug 2019 12:57:20 +0200 Subject: pdc_adma: use dma_set_mask_and_coherent Use the dma_set_mask_and_coherent helper to set the DMA mask. Rely on the relatively recent change that setting a larger than required mask will never fail to avoid the need for the boilerplate 32-bit fallback code. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/ata/pdc_adma.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index c5bbb07aa7d9..cb490531b62e 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -572,23 +572,6 @@ static void adma_host_init(struct ata_host *host, unsigned int chip_id) adma_reset_engine(host->ports[port_no]); } -static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) -{ - int rc; - - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, "32-bit DMA enable failed\n"); - return rc; - } - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); - return rc; - } - return 0; -} - static int adma_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -619,9 +602,11 @@ static int adma_ata_init_one(struct pci_dev *pdev, host->iomap = pcim_iomap_table(pdev); mmio_base = host->iomap[ADMA_MMIO_BAR]; - rc = adma_set_dma_masks(pdev, mmio_base); - if (rc) + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (rc) { + dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; + } for (port_no = 0; port_no < ADMA_PORTS; ++port_no) { struct ata_port *ap = host->ports[port_no]; -- cgit v1.2.3 From 496d4575e7ac57f4ee3457c10be214e6b3ce0bd0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 26 Aug 2019 12:57:21 +0200 Subject: sata_mv: use dma_set_mask_and_coherent Use the dma_set_mask_and_coherent helper to set the DMA mask. Rely on the relatively recent change that setting a larger than required mask will never fail to avoid the need for the boilerplate 32-bit fallback code. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/ata/sata_mv.c | 38 ++++---------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index da585d2bded6..ad385a113391 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -4314,38 +4314,6 @@ static struct pci_driver mv_pci_driver = { }; -/* move to PCI layer or libata core? */ -static int pci_go_64(struct pci_dev *pdev) -{ - int rc; - - if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (rc) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "64-bit DMA enable failed\n"); - return rc; - } - } - } else { - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, "32-bit DMA enable failed\n"); - return rc; - } - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "32-bit consistent DMA enable failed\n"); - return rc; - } - } - - return rc; -} - /** * mv_print_info - Dump key info to kernel log for perusal. * @host: ATA host to print info about @@ -4430,9 +4398,11 @@ static int mv_pci_init_one(struct pci_dev *pdev, host->iomap = pcim_iomap_table(pdev); hpriv->base = host->iomap[MV_PRIMARY_BAR]; - rc = pci_go_64(pdev); - if (rc) + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (rc) { + dev_err(&pdev->dev, "DMA enable failed\n"); return rc; + } rc = mv_create_dma_pools(hpriv, &pdev->dev); if (rc) -- cgit v1.2.3 From 51872b6606eb52a5c8b82e79c644d352fdb41d04 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 26 Aug 2019 12:57:22 +0200 Subject: sata_nv: use dma_set_mask_and_coherent Use the dma_set_mask_and_coherent helper to set the DMA mask. Rely on the relatively recent change that setting a larger than required mask will never fail to avoid the need for the boilerplate 32-bit fallback code. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/ata/sata_nv.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index b44b4b64354c..56946012d113 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -1122,14 +1122,10 @@ static int nv_adma_port_start(struct ata_port *ap) /* * Now that the legacy PRD and padding buffer are allocated we can - * try to raise the DMA mask to allocate the CPB/APRD table. + * raise the DMA mask to allocate the CPB/APRD table. */ - rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); - if (rc) { - rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) - return rc; - } + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + pp->adma_dma_mask = *dev->dma_mask; mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, -- cgit v1.2.3 From 440bd77f09b8a11a5c729ef61f346421e4d10b87 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 26 Aug 2019 12:57:23 +0200 Subject: sata_qstor: use dma_set_mask_and_coherent Use the dma_set_mask_and_coherent helper to set the DMA mask. Rely on the relatively recent change that setting a larger than required mask will never fail to avoid the need for the boilerplate 32-bit fallback code. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/ata/sata_qstor.c | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 865e5c58bd94..c53c5a47204d 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -537,33 +537,13 @@ static void qs_host_init(struct ata_host *host, unsigned int chip_id) static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) { u32 bus_info = readl(mmio_base + QS_HID_HPHY); - int rc, have_64bit_bus = (bus_info & QS_HPHY_64BIT); - - if (have_64bit_bus && - !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (rc) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "64-bit DMA enable failed\n"); - return rc; - } - } - } else { - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, "32-bit DMA enable failed\n"); - return rc; - } - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "32-bit consistent DMA enable failed\n"); - return rc; - } - } - return 0; + int dma_bits = (bus_info & QS_HPHY_64BIT) ? 64 : 32; + int rc; + + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits)); + if (rc) + dev_err(&pdev->dev, "%d-bit DMA enable failed\n", dma_bits); + return rc; } static int qs_ata_init_one(struct pci_dev *pdev, -- cgit v1.2.3 From dcc02c19cc06bd7bc1b6db0aa0087a2b6eb05b94 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 26 Aug 2019 12:57:24 +0200 Subject: sata_sil24: use dma_set_mask_and_coherent Use the dma_set_mask_and_coherent helper to set the DMA mask. Rely on the relatively recent change that setting a larger than required mask will never fail to avoid the need for the boilerplate 32-bit fallback code. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/ata/sata_sil24.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 98aad8206921..7bef82de53ca 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -1301,28 +1301,10 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) host->iomap = iomap; /* configure and activate the device */ - if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (rc) { - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "64-bit DMA enable failed\n"); - return rc; - } - } - } else { - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, "32-bit DMA enable failed\n"); - return rc; - } - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, - "32-bit consistent DMA enable failed\n"); - return rc; - } + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (rc) { + dev_err(&pdev->dev, "DMA enable failed\n"); + return rc; } /* Set max read request size to 4096. This slightly increases -- cgit v1.2.3 From b5e55556182d2e43da035df1bffbd492c72a7994 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 26 Aug 2019 12:57:25 +0200 Subject: libata: switch remaining drivers to use dma_set_mask_and_coherent Use dma_set_mask_and_coherent instead of separate dma_set_mask and dma_set_coherent_mask calls. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- drivers/ata/libata-sff.c | 8 +------- drivers/ata/pata_atp867x.c | 7 +------ drivers/ata/pata_cs5520.c | 6 +----- drivers/ata/pata_hpt3x3.c | 5 +---- drivers/ata/pata_ninja32.c | 5 +---- drivers/ata/pata_pdc2027x.c | 6 +----- drivers/ata/pata_sil680.c | 5 +---- drivers/ata/sata_inic162x.c | 8 +------- drivers/ata/sata_promise.c | 5 +---- drivers/ata/sata_sil.c | 5 +---- drivers/ata/sata_svw.c | 5 +---- drivers/ata/sata_sx4.c | 5 +---- drivers/ata/sata_via.c | 9 +-------- drivers/ata/sata_vsc.c | 5 +---- 14 files changed, 14 insertions(+), 70 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 10aa27882142..d911514de05c 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -3147,15 +3147,9 @@ void ata_pci_bmdma_init(struct ata_host *host) * ->sff_irq_clear method. Try to initialize bmdma_addr * regardless of dma masks. */ - rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); + rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); if (rc) ata_bmdma_nodma(host, "failed to set dma mask"); - if (!rc) { - rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); - if (rc) - ata_bmdma_nodma(host, - "failed to set consistent dma mask"); - } /* request and iomap DMA region */ rc = pcim_iomap_regions(pdev, 1 << 4, dev_driver_string(gdev)); diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index 2b9ed4ddef8d..cfd0cf2cbca6 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c @@ -463,12 +463,7 @@ static int atp867x_ata_pci_sff_init_host(struct ata_host *host) atp867x_fixup(host); - rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); - if (rc) - return rc; - - rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); - return rc; + return dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); } static int atp867x_init_one(struct pci_dev *pdev, diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 099a5c68a4c9..9052148b306d 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -155,14 +155,10 @@ static int cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return -ENODEV; } - if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { + if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { printk(KERN_ERR DRV_NAME ": unable to configure DMA mask.\n"); return -ENODEV; } - if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) { - printk(KERN_ERR DRV_NAME ": unable to configure consistent DMA mask.\n"); - return -ENODEV; - } /* Map IO ports and initialize host accordingly */ iomap[0] = devm_ioport_map(&pdev->dev, cmd_port[0], 8); diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index b2fc023783b1..83974d5eb387 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -221,10 +221,7 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) return rc; host->iomap = pcim_iomap_table(pdev); - rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); - if (rc) - return rc; - rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); + rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c index 607db1f05f9a..f9255d6fd194 100644 --- a/drivers/ata/pata_ninja32.c +++ b/drivers/ata/pata_ninja32.c @@ -123,10 +123,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id) return rc; host->iomap = pcim_iomap_table(dev); - rc = dma_set_mask(&dev->dev, ATA_DMA_MASK); - if (rc) - return rc; - rc = dma_set_coherent_mask(&dev->dev, ATA_DMA_MASK); + rc = dma_set_mask_and_coherent(&dev->dev, ATA_DMA_MASK); if (rc) return rc; pci_set_master(dev); diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index b656e1536855..de834fbb6dfe 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -722,11 +722,7 @@ static int pdc2027x_init_one(struct pci_dev *pdev, return rc; host->iomap = pcim_iomap_table(pdev); - rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); - if (rc) - return rc; - - rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); + rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index c14071be4f55..7ab9aea3b630 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -374,10 +374,7 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) host->iomap = pcim_iomap_table(pdev); /* Setup DMA masks */ - rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); - if (rc) - return rc; - rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); + rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; pci_set_master(pdev); diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 790968497dfe..7f99e23bff88 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -862,18 +862,12 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Set dma_mask. This devices doesn't support 64bit addressing. */ - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, "32-bit DMA enable failed\n"); return rc; } - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) { - dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n"); - return rc; - } - rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl); if (rc) { dev_err(&pdev->dev, "failed to initialize controller\n"); diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index f4dfec3b6e42..5fd464765ddc 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -1230,10 +1230,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev, /* initialize adapter */ pdc_host_init(host); - rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); - if (rc) - return rc; - rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); + rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 25b6a52be5ab..e6fbae2f645a 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -757,10 +757,7 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return rc; host->iomap = pcim_iomap_table(pdev); - rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); - if (rc) - return rc; - rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); + rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index b903d55c6c20..f8552559db7f 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -471,10 +471,7 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en ata_port_pbar_desc(ap, 5, offset, "port"); } - rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); - if (rc) - return rc; - rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); + rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index ae8e374d0a77..2277ba0c9c7f 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -1470,10 +1470,7 @@ static int pdc_sata_init_one(struct pci_dev *pdev, } /* configure and activate */ - rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); - if (rc) - return rc; - rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); + rc = dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); if (rc) return rc; diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index fcb9245b184f..c7891cc84ea0 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -505,14 +505,7 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) for (i = 0; i < host->n_ports; i++) vt6421_init_addrs(host->ports[i]); - rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK); - if (rc) - return rc; - rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK); - if (rc) - return rc; - - return 0; + return dma_set_mask_and_coherent(&pdev->dev, ATA_DMA_MASK); } static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index fd401e9164ef..8fa952cb9f7f 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -371,10 +371,7 @@ static int vsc_sata_init_one(struct pci_dev *pdev, /* * Use 32 bit DMA mask, because 64 bit address support is poor. */ - rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc) - return rc; - rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); if (rc) return rc; -- cgit v1.2.3 From 60fc35f327e0a9e60b955c0f3c3ed623608d1baa Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 30 Aug 2019 22:42:55 +0300 Subject: ahci: Do not export local variable ahci_em_messages The commit ed08d40cdec4 ("ahci: Changing two module params with static and __read_mostly") moved ahci_em_messages to be static while missing the fact of exporting it. WARNING: "ahci_em_messages" [vmlinux] is a static EXPORT_SYMBOL_GPL Drop export for the local variable ahci_em_messages. Fixes: ed08d40cdec4 ("ahci: Changing two module params with static and __read_mostly") Cc: Chuansheng Liu Signed-off-by: Andy Shevchenko Signed-off-by: Jens Axboe --- drivers/ata/libahci.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index e4c45d3cca79..bff369d9a1a7 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -175,7 +175,6 @@ struct ata_port_operations ahci_pmp_retry_srst_ops = { EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops); static bool ahci_em_messages __read_mostly = true; -EXPORT_SYMBOL_GPL(ahci_em_messages); module_param(ahci_em_messages, bool, 0444); /* add other LED protocol types when they become supported */ MODULE_PARM_DESC(ahci_em_messages, -- cgit v1.2.3 From c312ef176399e04fc5f7f2809d9a589751fbf6d9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 29 Aug 2019 16:30:34 -0700 Subject: libata/ahci: Drop PCS quirk for Denverton and beyond The Linux ahci driver has historically implemented a configuration fixup for platforms / platform-firmware that fails to enable the ports prior to OS hand-off at boot. The fixup was originally implemented way back before ahci moved from drivers/scsi/ to drivers/ata/, and was updated in 2007 via commit 49f290903935 "ahci: update PCS programming". The quirk sets a port-enable bitmap in the PCS register at offset 0x92. This quirk could be applied generically up until the arrival of the Denverton (DNV) platform. The DNV AHCI controller architecture supports more than 6 ports and along with that the PCS register location and format were updated to allow for more possible ports in the bitmap. DNV AHCI expands the register to 32-bits and moves it to offset 0x94. As it stands there are no known problem reports with existing Linux trying to set bits at offset 0x92 which indicates that the quirk is not applicable. Likely it is not applicable on a wider range of platforms, but it is difficult to discern which platforms if any still depend on the quirk. Rather than try to fix the PCS quirk to consider the DNV register layout instead require explicit opt-in. The assumption is that the OS driver need not touch this register, and platforms can be added with a new boad_ahci_pcs7 board-id when / if problematic platforms are found in the future. The logic in ahci_intel_pcs_quirk() looks for all Intel AHCI instances with "legacy" board-ids and otherwise skips the quirk if the board was matched by class-code. Reported-by: Stephen Douthit Cc: Christoph Hellwig Reviewed-by: Stephen Douthit Signed-off-by: Dan Williams Signed-off-by: Jens Axboe --- drivers/ata/ahci.c | 116 +++++++++++++++++++++++++++++++---------------------- drivers/ata/ahci.h | 2 + 2 files changed, 71 insertions(+), 47 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ad840f20f8e2..dd92faf197d5 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -65,6 +65,12 @@ enum board_ids { board_ahci_sb700, /* for SB700 and SB800 */ board_ahci_vt8251, + /* + * board IDs for Intel chipsets that support more than 6 ports + * *and* end up needing the PCS quirk. + */ + board_ahci_pcs7, + /* aliases */ board_ahci_mcp_linux = board_ahci_mcp65, board_ahci_mcp67 = board_ahci_mcp65, @@ -220,6 +226,12 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_vt8251_ops, }, + [board_ahci_pcs7] = { + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, }; static const struct pci_device_id ahci_pci_tbl[] = { @@ -264,26 +276,26 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci_mobile }, /* PCH M RAID */ { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ - { PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */ - { PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b0), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b1), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b2), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b3), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b4), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b5), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b6), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b7), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19bE), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19bF), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c0), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c1), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c2), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c3), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c4), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c5), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c6), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c7), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19cE), board_ahci_pcs7 }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19cF), board_ahci_pcs7 }, /* DNV AHCI */ { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ { PCI_VDEVICE(INTEL, 0x1c03), board_ahci_mobile }, /* CPT M AHCI */ { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ @@ -623,30 +635,6 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev, ahci_save_initial_config(&pdev->dev, hpriv); } -static int ahci_pci_reset_controller(struct ata_host *host) -{ - struct pci_dev *pdev = to_pci_dev(host->dev); - int rc; - - rc = ahci_reset_controller(host); - if (rc) - return rc; - - if (pdev->vendor == PCI_VENDOR_ID_INTEL) { - struct ahci_host_priv *hpriv = host->private_data; - u16 tmp16; - - /* configure PCS */ - pci_read_config_word(pdev, 0x92, &tmp16); - if ((tmp16 & hpriv->port_map) != hpriv->port_map) { - tmp16 |= hpriv->port_map; - pci_write_config_word(pdev, 0x92, tmp16); - } - } - - return 0; -} - static void ahci_pci_init_controller(struct ata_host *host) { struct ahci_host_priv *hpriv = host->private_data; @@ -849,7 +837,7 @@ static int ahci_pci_device_runtime_resume(struct device *dev) struct ata_host *host = pci_get_drvdata(pdev); int rc; - rc = ahci_pci_reset_controller(host); + rc = ahci_reset_controller(host); if (rc) return rc; ahci_pci_init_controller(host); @@ -884,7 +872,7 @@ static int ahci_pci_device_resume(struct device *dev) ahci_mcp89_apple_enable(pdev); if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { - rc = ahci_pci_reset_controller(host); + rc = ahci_reset_controller(host); if (rc) return rc; @@ -1602,6 +1590,34 @@ update_policy: ap->target_lpm_policy = policy; } +static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv) +{ + const struct pci_device_id *id = pci_match_id(ahci_pci_tbl, pdev); + u16 tmp16; + + /* + * Only apply the 6-port PCS quirk for known legacy platforms. + */ + if (!id || id->vendor != PCI_VENDOR_ID_INTEL) + return; + if (((enum board_ids) id->driver_data) < board_ahci_pcs7) + return; + + /* + * port_map is determined from PORTS_IMPL PCI register which is + * implemented as write or write-once register. If the register + * isn't programmed, ahci automatically generates it from number + * of ports, which is good enough for PCS programming. It is + * otherwise expected that platform firmware enables the ports + * before the OS boots. + */ + pci_read_config_word(pdev, PCS_6, &tmp16); + if ((tmp16 & hpriv->port_map) != hpriv->port_map) { + tmp16 |= hpriv->port_map; + pci_write_config_word(pdev, PCS_6, tmp16); + } +} + static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { unsigned int board_id = ent->driver_data; @@ -1714,6 +1730,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* save initial config */ ahci_pci_save_initial_config(pdev, hpriv); + /* + * If platform firmware failed to enable ports, try to enable + * them here. + */ + ahci_intel_pcs_quirk(pdev, hpriv); + /* prepare host */ if (hpriv->cap & HOST_CAP_NCQ) { pi.flags |= ATA_FLAG_NCQ; @@ -1823,7 +1845,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return rc; - rc = ahci_pci_reset_controller(host); + rc = ahci_reset_controller(host); if (rc) return rc; diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 0570629d719d..3dbf398c92ea 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -247,6 +247,8 @@ enum { ATA_FLAG_ACPI_SATA | ATA_FLAG_AN, ICH_MAP = 0x90, /* ICH MAP register */ + PCS_6 = 0x92, /* 6 port PCS */ + PCS_7 = 0x94, /* 7+ port PCS (Denverton) */ /* em constants */ EM_MAX_SLOTS = 8, -- cgit v1.2.3