From 5d7a288caf6d9b839a9a5bd28e56e15678669e67 Mon Sep 17 00:00:00 2001 From: Tycho Andersen Date: Thu, 4 May 2017 16:15:51 -0600 Subject: ata-sff: always map page before data transfer The XPFO [1] patchset may unmap pages from physmap if they happened to be destined for userspace. If such a page is unmapped, it needs to be remapped. Rather than test if a page is in the highmem/xpfo unmapped state, Christoph suggested [2] that we simply always map the page. v2: * drop comment about bounce buffer * don't save IRQs before kmap/unmap * formatting [1]: https://lkml.org/lkml/2016/11/4/245 [2]: https://lkml.org/lkml/2016/11/4/253 Suggested-and-reviewed-by: Christoph Hellwig Signed-off-by: Tycho Andersen CC: Juerg Haefliger Signed-off-by: Tejun Heo --- drivers/ata/libata-sff.c | 44 ++++++++------------------------------------ 1 file changed, 8 insertions(+), 36 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 274d6d7193d7..baa24a9a0e68 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -716,24 +716,10 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); - if (PageHighMem(page)) { - unsigned long flags; - - /* FIXME: use a bounce buffer */ - local_irq_save(flags); - buf = kmap_atomic(page); - - /* do the actual data transfer */ - ap->ops->sff_data_xfer(qc, buf + offset, qc->sect_size, - do_write); - - kunmap_atomic(buf); - local_irq_restore(flags); - } else { - buf = page_address(page); - ap->ops->sff_data_xfer(qc, buf + offset, qc->sect_size, - do_write); - } + /* do the actual data transfer */ + buf = kmap_atomic(page); + ap->ops->sff_data_xfer(qc, buf + offset, qc->sect_size, do_write); + kunmap_atomic(buf); if (!do_write && !PageSlab(page)) flush_dcache_page(page); @@ -861,24 +847,10 @@ next_sg: DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); - if (PageHighMem(page)) { - unsigned long flags; - - /* FIXME: use bounce buffer */ - local_irq_save(flags); - buf = kmap_atomic(page); - - /* do the actual data transfer */ - consumed = ap->ops->sff_data_xfer(qc, buf + offset, - count, rw); - - kunmap_atomic(buf); - local_irq_restore(flags); - } else { - buf = page_address(page); - consumed = ap->ops->sff_data_xfer(qc, buf + offset, - count, rw); - } + /* do the actual data transfer */ + buf = kmap_atomic(page); + consumed = ap->ops->sff_data_xfer(qc, buf + offset, count, rw); + kunmap_atomic(buf); bytes -= min(bytes, consumed); qc->curbytes += count; -- cgit v1.2.3 From 6baf20bce8318b3245a1f1fbcb290256b3c44a15 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 May 2017 09:16:18 -0300 Subject: libata: fix identation on a kernel-doc markup Sphinx got confused with the markup identation: ./drivers/ata/libata-scsi.c:3402: ERROR: Unexpected indentation. No functional changes. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 49ba9834c715..dcd38d9e9804 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3398,9 +3398,10 @@ static size_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax, * * Translate a SCSI WRITE SAME command to be either a DSM TRIM command or * an SCT Write Same command. - * Based on WRITE SAME has the UNMAP flag - * When set translate to DSM TRIM - * When clear translate to SCT Write Same + * Based on WRITE SAME has the UNMAP flag: + * + * - When set translate to DSM TRIM + * - When clear translate to SCT Write Same */ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) { -- cgit v1.2.3 From 9bb9a39ce51eae886575251e87d9292f679e3e32 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 16 May 2017 09:16:37 -0300 Subject: ata: update references for libata documentation The libata documentation is now using ReST. Update references to it to point to the new place. Signed-off-by: Mauro Carvalho Chehab Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Tejun Heo --- drivers/ata/acard-ahci.c | 2 +- drivers/ata/ahci.c | 2 +- drivers/ata/ahci.h | 2 +- drivers/ata/ata_piix.c | 2 +- drivers/ata/libahci.c | 2 +- drivers/ata/libata-core.c | 2 +- drivers/ata/libata-eh.c | 2 +- drivers/ata/libata-scsi.c | 2 +- drivers/ata/libata-sff.c | 2 +- drivers/ata/libata.h | 2 +- drivers/ata/pata_pdc2027x.c | 2 +- drivers/ata/pdc_adma.c | 2 +- drivers/ata/sata_nv.c | 2 +- drivers/ata/sata_promise.c | 2 +- drivers/ata/sata_promise.h | 2 +- drivers/ata/sata_qstor.c | 2 +- drivers/ata/sata_sil.c | 2 +- drivers/ata/sata_sis.c | 2 +- drivers/ata/sata_svw.c | 2 +- drivers/ata/sata_sx4.c | 2 +- drivers/ata/sata_uli.c | 2 +- drivers/ata/sata_via.c | 2 +- drivers/ata/sata_vsc.c | 2 +- include/linux/ata.h | 2 +- include/linux/libata.h | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c index ed6a30cd681a..940ddbc59aa7 100644 --- a/drivers/ata/acard-ahci.c +++ b/drivers/ata/acard-ahci.c @@ -25,7 +25,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * AHCI hardware documentation: * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 2fc52407306c..fd712e0e9d87 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -24,7 +24,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * AHCI hardware documentation: * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 5db6ab261643..30f67a1a4f54 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -24,7 +24,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * AHCI hardware documentation: * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index ffbe625e6fd2..8401c3b5be92 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -33,7 +33,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware documentation available at http://developer.intel.com/ * diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 3159f9e66d8f..6154f0e2b81a 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -24,7 +24,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * AHCI hardware documentation: * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2d83b8c75965..55aaa2e4c683 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -25,7 +25,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware documentation available from http://www.t13.org/ and * http://www.sata-io.org/ diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ef68232b5222..7e33e200aae5 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -25,7 +25,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware documentation available from http://www.t13.org/ and * http://www.sata-io.org/ diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index dcd38d9e9804..b0866f040d1f 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -25,7 +25,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware documentation available from * - http://www.t10.org/ diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index baa24a9a0e68..cc2f2e35f4c2 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -25,7 +25,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware documentation available from http://www.t13.org/ and * http://www.sata-io.org/ diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 120fce0befd3..5afe35baf61b 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -21,7 +21,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * */ diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index d9ef9e276225..82bfd51692f3 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -17,7 +17,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware information only available under NDA. * diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index 64d682c6ee57..f1e873a37465 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -21,7 +21,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * * Supports ATA disks in single-packet ADMA mode. diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 734f563b8d37..8c683ddd0f58 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -21,7 +21,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * No hardware documentation available outside of NVIDIA. * This driver programs the NVIDIA SATA controller in a similar diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 0fa211e2831c..d032bf657f70 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -25,7 +25,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware information only available under NDA. * diff --git a/drivers/ata/sata_promise.h b/drivers/ata/sata_promise.h index 00d6000e546f..61633ef5ed72 100644 --- a/drivers/ata/sata_promise.h +++ b/drivers/ata/sata_promise.h @@ -20,7 +20,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * */ diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index af987a4f33d1..1fe941688e95 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -23,7 +23,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * */ diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 29bcff086bce..ed76f070d21e 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -25,7 +25,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Documentation for SiI 3112: * http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2 diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index d1637ac40a73..30f4f35f36d4 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -24,7 +24,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware documentation available under NDA. * diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index ff614be55d0f..0fd6ac7e57ba 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -30,7 +30,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware documentation available under NDA. * diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index 48301cb3a316..405e606a234d 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -24,7 +24,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware documentation available under NDA. * diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index 08f98c3ed5c8..4f6e8d8156de 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -18,7 +18,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware documentation available under NDA. * diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index f3f538eec7b3..22e96fc77d09 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -25,7 +25,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware documentation available under NDA. * diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index 183eb52085df..9648127cca70 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -26,7 +26,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Vitesse hardware documentation presumably available under NDA. * Intel 31244 (same hardware interface) documentation presumably diff --git a/include/linux/ata.h b/include/linux/ata.h index ad7d9ee89ff0..73fe18edfdaf 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -20,7 +20,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * * Hardware documentation available from http://www.t13.org/ * diff --git a/include/linux/libata.h b/include/linux/libata.h index c9a69fc8821e..9e6633235ad7 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -19,7 +19,7 @@ * * * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* + * as Documentation/driver-api/libata.rst * */ -- cgit v1.2.3 From 7ed4a21ad3131588e01178c915e6a854f391104e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 30 May 2017 11:46:39 +0200 Subject: ata: bf54x: cut drvdata assignment ata_host_alloc_pinfo() assigns the host pointer to the struct device * drvdata, do not assign it a second time. Signed-off-by: Linus Walleij Signed-off-by: Tejun Heo --- drivers/ata/pata_bf54x.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index 9c5780a7e1b9..0e55a8da2748 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -1597,8 +1597,6 @@ static int bfin_atapi_probe(struct platform_device *pdev) return -ENODEV; } - platform_set_drvdata(pdev, host); - return 0; } -- cgit v1.2.3 From 62a98c2764e24b6ac637e3d3afe9dd6c5f088449 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 30 May 2017 11:46:40 +0200 Subject: ata: ep93xx: cut drvdata assignment ata_host_alloc_pinfo() assigns the host pointer to the struct device * drvdata, do not assign drv_data like this. Since ata_host_alloc_pinfo() is called after this site, the correct value is set eventually, but this assignment is just plain pointless. Signed-off-by: Linus Walleij Signed-off-by: Tejun Heo --- drivers/ata/pata_ep93xx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c index bf1b910c5d69..0a550190955a 100644 --- a/drivers/ata/pata_ep93xx.c +++ b/drivers/ata/pata_ep93xx.c @@ -944,7 +944,6 @@ static int ep93xx_pata_probe(struct platform_device *pdev) goto err_rel_gpio; } - platform_set_drvdata(pdev, drv_data); drv_data->pdev = pdev; drv_data->ide_base = ide_base; drv_data->udma_in_phys = mem_res->start + IDEUDMADATAIN; -- cgit v1.2.3 From a2136b31d37e8edcea93a00e73b6383403b5b76e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 30 May 2017 11:46:41 +0200 Subject: ata: dwc_460ex: cut drvdata assignment ata_host_alloc_pinfo() assigns the host pointer to the struct device * drvdata, do not assign it a second time. Signed-off-by: Linus Walleij Signed-off-by: Tejun Heo --- drivers/ata/sata_dwc_460ex.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index e0939bd5ea73..ce128d5a6ded 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1285,7 +1285,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) if (err) dev_err(&ofdev->dev, "failed to activate host"); - dev_set_drvdata(&ofdev->dev, host); return 0; error_out: -- cgit v1.2.3 From 0fe98fa056d75d824d1939dd1e8b71927a5f288a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 30 May 2017 11:46:42 +0200 Subject: ata: rb532_cf: cut drvdata assignment ata_host_alloc_pinfo() assigns the host pointer to the struct device * drvdata, do not assign it a second time. Signed-off-by: Linus Walleij Signed-off-by: Tejun Heo --- drivers/ata/pata_rb532_cf.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index c8b6a780a290..653b9a0bf727 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -148,8 +148,6 @@ static int rb532_pata_driver_probe(struct platform_device *pdev) if (!ah) return -ENOMEM; - platform_set_drvdata(pdev, ah); - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; -- cgit v1.2.3 From 7c61a26891dcb938489c6f9ad793491bb9ae3989 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 30 May 2017 11:46:43 +0200 Subject: ata: samsung_cf: cut drvdata assignment ata_host_alloc_pinfo() assigns the host pointer to the struct device * drvdata, do not assign it a second time. Signed-off-by: Linus Walleij Signed-off-by: Tejun Heo --- drivers/ata/pata_samsung_cf.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c index 431c7de30ce6..50801c40b029 100644 --- a/drivers/ata/pata_samsung_cf.c +++ b/drivers/ata/pata_samsung_cf.c @@ -582,8 +582,6 @@ static int __init pata_s3c_probe(struct platform_device *pdev) /* Set endianness and enable the interface */ pata_s3c_hwinit(info, pdata); - platform_set_drvdata(pdev, host); - ret = ata_host_activate(host, info->irq, info->irq ? pata_s3c_irq : NULL, 0, &pata_s3c_sht); -- cgit v1.2.3 From 74ee91d8181b9d55fff79bf1fd555b0c8238f67e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 30 May 2017 11:46:44 +0200 Subject: ata: sata_fsl: cut drvdata assignment ata_host_alloc_pinfo() assigns the host pointer to the struct device * drvdata, do not assign it a second time. Signed-off-by: Linus Walleij Signed-off-by: Tejun Heo --- drivers/ata/sata_fsl.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 01734d54c69c..95bf3abda6f6 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -1523,8 +1523,6 @@ static int sata_fsl_probe(struct platform_device *ofdev) ata_host_activate(host, irq, sata_fsl_interrupt, SATA_FSL_IRQ_FLAG, &sata_fsl_sht); - platform_set_drvdata(ofdev, host); - host_priv->intr_coalescing.show = fsl_sata_intr_coalescing_show; host_priv->intr_coalescing.store = fsl_sata_intr_coalescing_store; sysfs_attr_init(&host_priv->intr_coalescing.attr); -- cgit v1.2.3 From 0cee73f751ceb507d052f1a45d5f5f38bc33b25a Mon Sep 17 00:00:00 2001 From: Yuantian Tang Date: Fri, 2 Jun 2017 15:23:03 +0800 Subject: ahci: qoriq: add ls1088a platforms support Ls1088a is new introduced arm-based soc with sata support with following features: * Complies with the serial ATA 3.0 specification and the AHCI 1.3.1 specification * Contains a high-speed descriptor-based DMA controller * Supports the following: * Speeds of 1.5 Gb/s (first-generation SATA), 3 Gb/s (second-generation SATA), and 6 Gb/s (third-generation SATA) * FIS-based switching * Native command queuing (NCQ) commands * Port multiplier operation * Asynchronous notification * SATA Vendor BIST mode Signed-off-by: Tang Yuantian Signed-off-by: Tejun Heo --- drivers/ata/ahci_qoriq.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c index 4c96f3ac4976..b6b0bf76dfc7 100644 --- a/drivers/ata/ahci_qoriq.c +++ b/drivers/ata/ahci_qoriq.c @@ -47,12 +47,14 @@ #define SATA_ECC_DISABLE 0x00020000 #define ECC_DIS_ARMV8_CH2 0x80000000 +#define ECC_DIS_LS1088A 0x40000000 enum ahci_qoriq_type { AHCI_LS1021A, AHCI_LS1043A, AHCI_LS2080A, AHCI_LS1046A, + AHCI_LS1088A, AHCI_LS2088A, }; @@ -68,6 +70,7 @@ static const struct of_device_id ahci_qoriq_of_match[] = { { .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A}, { .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A}, { .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A}, + { .compatible = "fsl,ls1088a-ahci", .data = (void *)AHCI_LS1088A}, { .compatible = "fsl,ls2088a-ahci", .data = (void *)AHCI_LS2088A}, {}, }; @@ -203,6 +206,17 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv) writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); break; + case AHCI_LS1088A: + if (!qpriv->ecc_addr) + return -EINVAL; + writel(readl(qpriv->ecc_addr) | ECC_DIS_LS1088A, + qpriv->ecc_addr); + writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); + writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); + if (qpriv->is_dmacoherent) + writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); + break; + case AHCI_LS2088A: writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); -- cgit v1.2.3 From f01f62c257cc343246a5a9b2df8135f01fc044ab Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 4 Jun 2017 14:42:20 +0200 Subject: libata: move ata_read_log_page to libata-core.c It is core functionality, and only one of the users is in the EH code. Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/ata/libata-eh.c | 64 ----------------------------------------------- drivers/ata/libata.h | 4 +-- 3 files changed, 66 insertions(+), 66 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 55aaa2e4c683..f84419f0d209 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2047,6 +2047,70 @@ retry: return rc; } +/** + * ata_read_log_page - read a specific log page + * @dev: target device + * @log: log to read + * @page: page to read + * @buf: buffer to store read page + * @sectors: number of sectors to read + * + * Read log page using READ_LOG_EXT command. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, AC_ERR_* mask otherwise. + */ +unsigned int ata_read_log_page(struct ata_device *dev, u8 log, + u8 page, void *buf, unsigned int sectors) +{ + unsigned long ap_flags = dev->link->ap->flags; + struct ata_taskfile tf; + unsigned int err_mask; + bool dma = false; + + DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page); + + /* + * Return error without actually issuing the command on controllers + * which e.g. lockup on a read log page. + */ + if (ap_flags & ATA_FLAG_NO_LOG_PAGE) + return AC_ERR_DEV; + +retry: + ata_tf_init(dev, &tf); + if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id) && + !(dev->horkage & ATA_HORKAGE_NO_NCQ_LOG)) { + tf.command = ATA_CMD_READ_LOG_DMA_EXT; + tf.protocol = ATA_PROT_DMA; + dma = true; + } else { + tf.command = ATA_CMD_READ_LOG_EXT; + tf.protocol = ATA_PROT_PIO; + dma = false; + } + tf.lbal = log; + tf.lbam = page; + tf.nsect = sectors; + tf.hob_nsect = sectors >> 8; + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE; + + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, + buf, sectors * ATA_SECT_SIZE, 0); + + if (err_mask && dma) { + dev->horkage |= ATA_HORKAGE_NO_NCQ_LOG; + ata_dev_warn(dev, "READ LOG DMA EXT failed, trying unqueued\n"); + goto retry; + } + + DPRINTK("EXIT, err_mask=%x\n", err_mask); + return err_mask; +} + static int ata_do_link_spd_horkage(struct ata_device *dev) { struct ata_link *plink = ata_dev_phys_link(dev); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 7e33e200aae5..b70bcf6d2914 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1487,70 +1487,6 @@ static const char *ata_err_string(unsigned int err_mask) return "unknown error"; } -/** - * ata_read_log_page - read a specific log page - * @dev: target device - * @log: log to read - * @page: page to read - * @buf: buffer to store read page - * @sectors: number of sectors to read - * - * Read log page using READ_LOG_EXT command. - * - * LOCKING: - * Kernel thread context (may sleep). - * - * RETURNS: - * 0 on success, AC_ERR_* mask otherwise. - */ -unsigned int ata_read_log_page(struct ata_device *dev, u8 log, - u8 page, void *buf, unsigned int sectors) -{ - unsigned long ap_flags = dev->link->ap->flags; - struct ata_taskfile tf; - unsigned int err_mask; - bool dma = false; - - DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page); - - /* - * Return error without actually issuing the command on controllers - * which e.g. lockup on a read log page. - */ - if (ap_flags & ATA_FLAG_NO_LOG_PAGE) - return AC_ERR_DEV; - -retry: - ata_tf_init(dev, &tf); - if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id) && - !(dev->horkage & ATA_HORKAGE_NO_NCQ_LOG)) { - tf.command = ATA_CMD_READ_LOG_DMA_EXT; - tf.protocol = ATA_PROT_DMA; - dma = true; - } else { - tf.command = ATA_CMD_READ_LOG_EXT; - tf.protocol = ATA_PROT_PIO; - dma = false; - } - tf.lbal = log; - tf.lbam = page; - tf.nsect = sectors; - tf.hob_nsect = sectors >> 8; - tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE; - - err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, - buf, sectors * ATA_SECT_SIZE, 0); - - if (err_mask && dma) { - dev->horkage |= ATA_HORKAGE_NO_NCQ_LOG; - ata_dev_warn(dev, "READ LOG DMA EXT failed, trying unqueued\n"); - goto retry; - } - - DPRINTK("EXIT, err_mask=%x\n", err_mask); - return err_mask; -} - /** * ata_eh_read_log_10h - Read log page 10h for NCQ error details * @dev: Device to read log page 10h from diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 5afe35baf61b..839d487394b7 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -98,6 +98,8 @@ extern struct ata_port *ata_port_alloc(struct ata_host *host); extern const char *sata_spd_string(unsigned int spd); extern int ata_port_probe(struct ata_port *ap); extern void __ata_port_probe(struct ata_port *ap); +extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log, + u8 page, void *buf, unsigned int sectors); #define to_ata_port(d) container_of(d, struct ata_port, tdev) @@ -160,8 +162,6 @@ extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev, unsigned int action); extern void ata_eh_done(struct ata_link *link, struct ata_device *dev, unsigned int action); -extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log, - u8 page, void *buf, unsigned int sectors); extern void ata_eh_autopsy(struct ata_port *ap); const char *ata_get_cmd_descript(u8 command); extern void ata_eh_report(struct ata_port *ap); -- cgit v1.2.3 From efe205a320f24c4fe4af18c0cff2ffb07091951c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 4 Jun 2017 14:42:21 +0200 Subject: libata: factor out a ata_log_supported helper Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 59 +++++++++++++---------------------------------- 1 file changed, 16 insertions(+), 43 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index f84419f0d209..e79085809791 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2111,6 +2111,15 @@ retry: return err_mask; } +static bool ata_log_supported(struct ata_device *dev, u8 log) +{ + struct ata_port *ap = dev->link->ap; + + if (ata_read_log_page(dev, ATA_LOG_DIRECTORY, 0, ap->sector_buf, 1)) + return false; + return get_unaligned_le16(&ap->sector_buf[log * 2]) ? true : false; +} + static int ata_do_link_spd_horkage(struct ata_device *dev) { struct ata_link *plink = ata_dev_phys_link(dev); @@ -2158,21 +2167,9 @@ static void ata_dev_config_ncq_send_recv(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; unsigned int err_mask; - int log_index = ATA_LOG_NCQ_SEND_RECV * 2; - u16 log_pages; - err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY, - 0, ap->sector_buf, 1); - if (err_mask) { - ata_dev_dbg(dev, - "failed to get Log Directory Emask 0x%x\n", - err_mask); - return; - } - log_pages = get_unaligned_le16(&ap->sector_buf[log_index]); - if (!log_pages) { - ata_dev_warn(dev, - "NCQ Send/Recv Log not supported\n"); + if (!ata_log_supported(dev, ATA_LOG_NCQ_SEND_RECV)) { + ata_dev_warn(dev, "NCQ Send/Recv Log not supported\n"); return; } err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_SEND_RECV, @@ -2199,19 +2196,8 @@ static void ata_dev_config_ncq_non_data(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; unsigned int err_mask; - int log_index = ATA_LOG_NCQ_NON_DATA * 2; - u16 log_pages; - err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY, - 0, ap->sector_buf, 1); - if (err_mask) { - ata_dev_dbg(dev, - "failed to get Log Directory Emask 0x%x\n", - err_mask); - return; - } - log_pages = get_unaligned_le16(&ap->sector_buf[log_index]); - if (!log_pages) { + if (!ata_log_supported(dev, ATA_LOG_NCQ_NON_DATA)) { ata_dev_warn(dev, "NCQ Send/Recv Log not supported\n"); return; @@ -2339,7 +2325,7 @@ static void ata_dev_config_zac(struct ata_device *dev) struct ata_port *ap = dev->link->ap; unsigned int err_mask; u8 *identify_buf = ap->sector_buf; - int log_index = ATA_LOG_SATA_ID_DEV_DATA * 2, i, found = 0; + int i, found = 0; u16 log_pages; dev->zac_zones_optimal_open = U32_MAX; @@ -2360,24 +2346,11 @@ static void ata_dev_config_zac(struct ata_device *dev) if (!(dev->flags & ATA_DFLAG_ZAC)) return; - /* - * Read Log Directory to figure out if IDENTIFY DEVICE log - * is supported. - */ - err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY, - 0, ap->sector_buf, 1); - if (err_mask) { - ata_dev_info(dev, - "failed to get Log Directory Emask 0x%x\n", - err_mask); - return; - } - log_pages = get_unaligned_le16(&ap->sector_buf[log_index]); - if (log_pages == 0) { - ata_dev_warn(dev, - "ATA Identify Device Log not supported\n"); + if (!ata_log_supported(dev, ATA_LOG_SATA_ID_DEV_DATA)) { + ata_dev_warn(dev, "ATA Identify Device Log not supported\n"); return; } + /* * Read IDENTIFY DEVICE data log, page 0, to figure out * if page 9 is supported. -- cgit v1.2.3 From 1d51d5f3907abf86ef0521971bcddf5853564263 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 4 Jun 2017 14:42:22 +0200 Subject: libata: clarify log page naming / grouping Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 10 +++++----- include/linux/ata.h | 10 +++++++--- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e79085809791..bf6b40335598 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2226,7 +2226,7 @@ static void ata_dev_config_ncq_prio(struct ata_device *dev) } err_mask = ata_read_log_page(dev, - ATA_LOG_SATA_ID_DEV_DATA, + ATA_LOG_IDENTIFY_DEVICE, ATA_LOG_SATA_SETTINGS, ap->sector_buf, 1); @@ -2346,7 +2346,7 @@ static void ata_dev_config_zac(struct ata_device *dev) if (!(dev->flags & ATA_DFLAG_ZAC)) return; - if (!ata_log_supported(dev, ATA_LOG_SATA_ID_DEV_DATA)) { + if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE)) { ata_dev_warn(dev, "ATA Identify Device Log not supported\n"); return; } @@ -2355,7 +2355,7 @@ static void ata_dev_config_zac(struct ata_device *dev) * Read IDENTIFY DEVICE data log, page 0, to figure out * if page 9 is supported. */ - err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA, 0, + err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, 0, identify_buf, 1); if (err_mask) { ata_dev_info(dev, @@ -2379,7 +2379,7 @@ static void ata_dev_config_zac(struct ata_device *dev) /* * Read IDENTIFY DEVICE data log, page 9 (Zoned-device information) */ - err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA, + err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, ATA_LOG_ZONED_INFORMATION, identify_buf, 1); if (!err_mask) { @@ -2608,7 +2608,7 @@ int ata_dev_configure(struct ata_device *dev) dev->flags |= ATA_DFLAG_DEVSLP; err_mask = ata_read_log_page(dev, - ATA_LOG_SATA_ID_DEV_DATA, + ATA_LOG_IDENTIFY_DEVICE, ATA_LOG_SATA_SETTINGS, sata_setting, 1); diff --git a/include/linux/ata.h b/include/linux/ata.h index 73fe18edfdaf..c14bdcf31fdb 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -336,11 +336,15 @@ enum { /* READ_LOG_EXT pages */ ATA_LOG_DIRECTORY = 0x0, ATA_LOG_SATA_NCQ = 0x10, - ATA_LOG_NCQ_NON_DATA = 0x12, - ATA_LOG_NCQ_SEND_RECV = 0x13, - ATA_LOG_SATA_ID_DEV_DATA = 0x30, + ATA_LOG_NCQ_NON_DATA = 0x12, + ATA_LOG_NCQ_SEND_RECV = 0x13, + ATA_LOG_IDENTIFY_DEVICE = 0x30, + + /* Identify device log pages: */ ATA_LOG_SATA_SETTINGS = 0x08, ATA_LOG_ZONED_INFORMATION = 0x09, + + /* Identify device SATA settings log:*/ ATA_LOG_DEVSLP_OFFSET = 0x30, ATA_LOG_DEVSLP_SIZE = 0x08, ATA_LOG_DEVSLP_MDAT = 0x00, -- cgit v1.2.3 From a0fd2454a36ffab2ce39b3a91c1385a5f98e63f0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 4 Jun 2017 14:42:23 +0200 Subject: libata: factor out a ata_identify_page_supported helper tj: Updated line continuation style for consistency as pointed out by Sergei. Signed-off-by: Christoph Hellwig Cc: Sergei Shtylyov Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 59 +++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 27 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index bf6b40335598..61c97818568c 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2120,6 +2120,37 @@ static bool ata_log_supported(struct ata_device *dev, u8 log) return get_unaligned_le16(&ap->sector_buf[log * 2]) ? true : false; } +static bool ata_identify_page_supported(struct ata_device *dev, u8 page) +{ + struct ata_port *ap = dev->link->ap; + unsigned int err, i; + + if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE)) { + ata_dev_warn(dev, "ATA Identify Device Log not supported\n"); + return false; + } + + /* + * Read IDENTIFY DEVICE data log, page 0, to figure out if the page is + * supported. + */ + err = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, 0, ap->sector_buf, + 1); + if (err) { + ata_dev_info(dev, + "failed to get Device Identify Log Emask 0x%x\n", + err); + return false; + } + + for (i = 0; i < ap->sector_buf[8]; i++) { + if (ap->sector_buf[9 + i] == page) + return true; + } + + return false; +} + static int ata_do_link_spd_horkage(struct ata_device *dev) { struct ata_link *plink = ata_dev_phys_link(dev); @@ -2325,8 +2356,6 @@ static void ata_dev_config_zac(struct ata_device *dev) struct ata_port *ap = dev->link->ap; unsigned int err_mask; u8 *identify_buf = ap->sector_buf; - int i, found = 0; - u16 log_pages; dev->zac_zones_optimal_open = U32_MAX; dev->zac_zones_optimal_nonseq = U32_MAX; @@ -2346,31 +2375,7 @@ static void ata_dev_config_zac(struct ata_device *dev) if (!(dev->flags & ATA_DFLAG_ZAC)) return; - if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE)) { - ata_dev_warn(dev, "ATA Identify Device Log not supported\n"); - return; - } - - /* - * Read IDENTIFY DEVICE data log, page 0, to figure out - * if page 9 is supported. - */ - err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, 0, - identify_buf, 1); - if (err_mask) { - ata_dev_info(dev, - "failed to get Device Identify Log Emask 0x%x\n", - err_mask); - return; - } - log_pages = identify_buf[8]; - for (i = 0; i < log_pages; i++) { - if (identify_buf[9 + i] == ATA_LOG_ZONED_INFORMATION) { - found++; - break; - } - } - if (!found) { + if (!ata_identify_page_supported(dev, ATA_LOG_ZONED_INFORMATION)) { ata_dev_warn(dev, "ATA Zoned Information Log not supported\n"); return; -- cgit v1.2.3 From 818831c8b22f75353f59a63a484e20736c0567c9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 4 Jun 2017 14:42:24 +0200 Subject: libata: implement SECURITY PROTOCOL IN/OUT This allows us to use the generic OPAL code with ATA devices. Signed-off-by: Christoph Hellwig Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 32 ++++++++++++++++++++ drivers/ata/libata-scsi.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/ata.h | 1 + include/linux/libata.h | 1 + 4 files changed, 110 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 61c97818568c..a846c29f3248 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2405,6 +2405,37 @@ static void ata_dev_config_zac(struct ata_device *dev) } } +static void ata_dev_config_trusted(struct ata_device *dev) +{ + struct ata_port *ap = dev->link->ap; + u64 trusted_cap; + unsigned int err; + + if (!ata_identify_page_supported(dev, ATA_LOG_SECURITY)) { + ata_dev_warn(dev, + "Security Log not supported\n"); + return; + } + + err = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE, ATA_LOG_SECURITY, + ap->sector_buf, 1); + if (err) { + ata_dev_dbg(dev, + "failed to read Security Log, Emask 0x%x\n", err); + return; + } + + trusted_cap = get_unaligned_le64(&ap->sector_buf[40]); + if (!(trusted_cap & (1ULL << 63))) { + ata_dev_dbg(dev, + "Trusted Computing capability qword not valid!\n"); + return; + } + + if (trusted_cap & (1 << 0)) + dev->flags |= ATA_DFLAG_TRUSTED; +} + /** * ata_dev_configure - Configure the specified ATA/ATAPI device * @dev: Target device to configure @@ -2629,6 +2660,7 @@ int ata_dev_configure(struct ata_device *dev) } ata_dev_config_sense_reporting(dev); ata_dev_config_zac(dev); + ata_dev_config_trusted(dev); dev->cdb_len = 16; } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b0866f040d1f..8dc84fd77369 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3564,6 +3564,11 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) dev->class == ATA_DEV_ZAC) supported = 3; break; + case SECURITY_PROTOCOL_IN: + case SECURITY_PROTOCOL_OUT: + if (dev->flags & ATA_DFLAG_TRUSTED) + supported = 3; + break; default: break; } @@ -4068,6 +4073,71 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) return 1; } +static u8 ata_scsi_trusted_op(u32 len, bool send, bool dma) +{ + if (len == 0) + return ATA_CMD_TRUSTED_NONDATA; + else if (send) + return dma ? ATA_CMD_TRUSTED_SND_DMA : ATA_CMD_TRUSTED_SND; + else + return dma ? ATA_CMD_TRUSTED_RCV_DMA : ATA_CMD_TRUSTED_RCV; +} + +static unsigned int ata_scsi_security_inout_xlat(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + const u8 *cdb = scmd->cmnd; + struct ata_taskfile *tf = &qc->tf; + u8 secp = cdb[1]; + bool send = (cdb[0] == SECURITY_PROTOCOL_OUT); + u16 spsp = get_unaligned_be16(&cdb[2]); + u32 len = get_unaligned_be32(&cdb[6]); + bool dma = !(qc->dev->flags & ATA_DFLAG_PIO); + + /* + * We don't support the ATA "security" protocol. + */ + if (secp == 0xef) { + ata_scsi_set_invalid_field(qc->dev, scmd, 1, 0); + return 1; + } + + if (cdb[4] & 7) { /* INC_512 */ + if (len > 0xffff) { + ata_scsi_set_invalid_field(qc->dev, scmd, 6, 0); + return 1; + } + } else { + if (len > 0x01fffe00) { + ata_scsi_set_invalid_field(qc->dev, scmd, 6, 0); + return 1; + } + + /* convert to the sector-based ATA addressing */ + len = (len + 511) / 512; + } + + tf->protocol = dma ? ATA_PROT_DMA : ATA_PROT_PIO; + tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR | ATA_TFLAG_LBA; + if (send) + tf->flags |= ATA_TFLAG_WRITE; + tf->command = ata_scsi_trusted_op(len, send, dma); + tf->feature = secp; + tf->lbam = spsp & 0xff; + tf->lbah = spsp >> 8; + + if (len) { + tf->nsect = len & 0xff; + tf->lbal = len >> 8; + } else { + if (!send) + tf->lbah = (1 << 7); + } + + ata_qc_set_pc_nbytes(qc); + return 0; +} + /** * ata_get_xlat_func - check if SCSI to ATA translation is possible * @dev: ATA device @@ -4119,6 +4189,12 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) case ZBC_OUT: return ata_scsi_zbc_out_xlat; + case SECURITY_PROTOCOL_IN: + case SECURITY_PROTOCOL_OUT: + if (!(dev->flags & ATA_DFLAG_TRUSTED)) + break; + return ata_scsi_security_inout_xlat; + case START_STOP: return ata_scsi_start_stop_xlat; } diff --git a/include/linux/ata.h b/include/linux/ata.h index c14bdcf31fdb..e65ae4b2ed48 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -341,6 +341,7 @@ enum { ATA_LOG_IDENTIFY_DEVICE = 0x30, /* Identify device log pages: */ + ATA_LOG_SECURITY = 0x06, ATA_LOG_SATA_SETTINGS = 0x08, ATA_LOG_ZONED_INFORMATION = 0x09, diff --git a/include/linux/libata.h b/include/linux/libata.h index 9e6633235ad7..55de3da58b1c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -156,6 +156,7 @@ enum { ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */ ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */ ATA_DFLAG_AN = (1 << 7), /* AN configured */ + ATA_DFLAG_TRUSTED = (1 << 8), /* device supports trusted send/recv */ ATA_DFLAG_DMADIR = (1 << 10), /* device requires DMADIR */ ATA_DFLAG_CFG_MASK = (1 << 12) - 1, -- cgit v1.2.3 From be4e456ed3a5918f4e75f532837bb19128a690c9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 4 Jun 2017 10:50:08 +0200 Subject: ata: Add driver for Faraday Technology FTIDE010 This adds a driver for the Faraday Technology FTIDE010 PATA IP block. When used with the Storlink/Storm/Cortina Systems Gemini SoC, the PATA interface is accompanied by a PATA<->SATA bridge, so while the device appear as a PATA controller, it attaches physically to SATA disks, and also has a designated memory area with registers to set up the bridge. The Gemini SATA bridge is separated into its own driver file to make things modular and make it possible to reuse the PATA driver as stand-alone on other systems than the Gemini. dmesg excerpt from the D-Link DIR-685 storage router: gemini-sata-bridge 46000000.sata: SATA ID 00000e00, PHY ID: 01000100 gemini-sata-bridge 46000000.sata: set up the Gemini IDE/SATA nexus ftide010 63000000.ata: set up Gemini PATA0 ftide010 63000000.ata: device ID 00000500, irq 26, io base 0x63000000 ftide010 63000000.ata: SATA0 (master) start gemini-sata-bridge 46000000.sata: SATA0 PHY ready scsi host0: pata-ftide010 ata1: PATA max UDMA/133 irq 26 ata1.00: ATA-8: INTEL SSDSA2CW120G3, 4PC10302, max UDMA/133 ata1.00: 234441648 sectors, multi 1: LBA48 NCQ (depth 0/32) ata1.00: configured for UDMA/133 scsi 0:0:0:0: Direct-Access ATA INTEL SSDSA2CW12 0302 PQ: 0 ANSI: 5 ata1.00: Enabling discard_zeroes_data sd 0:0:0:0: [sda] 234441648 512-byte logical blocks: (120 GB/112 GiB) sd 0:0:0:0: [sda] Write Protect is off sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA ata1.00: Enabling discard_zeroes_data ata1.00: Enabling discard_zeroes_data sd 0:0:0:0: [sda] Attached SCSI disk After this I can flawlessly mount and read/write copy etc files from /dev/sda[n]. Cc: John Feng-Hsin Chiang Cc: Greentime Hu Acked-by: Hans Ulli Kroll Signed-off-by: Linus Walleij Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Tejun Heo --- MAINTAINERS | 9 + drivers/ata/Kconfig | 21 ++ drivers/ata/Makefile | 2 + drivers/ata/pata_ftide010.c | 567 ++++++++++++++++++++++++++++++++++++++++++++ drivers/ata/sata_gemini.c | 438 ++++++++++++++++++++++++++++++++++ drivers/ata/sata_gemini.h | 21 ++ 6 files changed, 1058 insertions(+) create mode 100644 drivers/ata/pata_ftide010.c create mode 100644 drivers/ata/sata_gemini.c create mode 100644 drivers/ata/sata_gemini.h (limited to 'drivers/ata') diff --git a/MAINTAINERS b/MAINTAINERS index f7d568b8f133..96753be12026 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7531,6 +7531,15 @@ S: Maintained F: drivers/ata/pata_*.c F: drivers/ata/ata_generic.c +LIBATA PATA FARADAY FTIDE010 AND GEMINI SATA BRIDGE DRIVERS +M: Linus Walleij +L: linux-ide@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata.git +S: Maintained +F: drivers/ata/pata_ftide010.c +F: drivers/ata/sata_gemini.c +F: drivers/ata/sata_gemini.h + LIBATA SATA AHCI PLATFORM devices support M: Hans de Goede M: Tejun Heo diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index de3eaf051697..948fc86980a1 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -213,6 +213,16 @@ config SATA_FSL If unsure, say N. +config SATA_GEMINI + tristate "Gemini SATA bridge support" + depends on PATA_FTIDE010 + default ARCH_GEMINI + help + This enabled support for the FTIDE010 to SATA bridge + found in Cortina Systems Gemini platform. + + If unsure, say N. + config SATA_AHCI_SEATTLE tristate "AMD Seattle 6.0Gbps AHCI SATA host controller support" depends on ARCH_SEATTLE @@ -599,6 +609,17 @@ config PATA_EP93XX If unsure, say N. +config PATA_FTIDE010 + tristate "Faraday Technology FTIDE010 PATA support" + depends on OF + depends on ARM + default ARCH_GEMINI + help + This option enables support for the Faraday FTIDE010 + PATA controller found in the Cortina Gemini SoCs. + + If unsure, say N. + config PATA_HPT366 tristate "HPT 366/368 PATA support" depends on PCI diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index cd931a5eba92..a26ef5a93919 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o obj-$(CONFIG_SATA_AHCI_SEATTLE) += ahci_seattle.o libahci.o libahci_platform.o obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o obj-$(CONFIG_SATA_FSL) += sata_fsl.o +obj-$(CONFIG_SATA_GEMINI) += sata_gemini.o obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o obj-$(CONFIG_SATA_SIL24) += sata_sil24.o obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o @@ -60,6 +61,7 @@ obj-$(CONFIG_PATA_CS5536) += pata_cs5536.o obj-$(CONFIG_PATA_CYPRESS) += pata_cypress.o obj-$(CONFIG_PATA_EFAR) += pata_efar.o obj-$(CONFIG_PATA_EP93XX) += pata_ep93xx.o +obj-$(CONFIG_PATA_FTIDE010) += pata_ftide010.o obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o diff --git a/drivers/ata/pata_ftide010.c b/drivers/ata/pata_ftide010.c new file mode 100644 index 000000000000..7b7e417ba8ba --- /dev/null +++ b/drivers/ata/pata_ftide010.c @@ -0,0 +1,567 @@ +/* + * Faraday Technology FTIDE010 driver + * Copyright (C) 2017 Linus Walleij + * + * Includes portions of the SL2312/SL3516/Gemini PATA driver + * Copyright (C) 2003 StorLine, Inc + * Copyright (C) 2009 Janos Laube + * Copyright (C) 2010 Frederic Pecourt + * Copyright (C) 2011 Tobias Waldvogel + */ + +#include +#include +#include +#include +#include +#include +#include +#include "sata_gemini.h" + +#define DRV_NAME "pata_ftide010" + +/** + * struct ftide010 - state container for the Faraday FTIDE010 + * @dev: pointer back to the device representing this controller + * @base: remapped I/O space address + * @pclk: peripheral clock for the IDE block + * @host: pointer to the ATA host for this device + * @master_cbl: master cable type + * @slave_cbl: slave cable type + * @sg: Gemini SATA bridge pointer, if running on the Gemini + * @master_to_sata0: Gemini SATA bridge: the ATA master is connected + * to the SATA0 bridge + * @slave_to_sata0: Gemini SATA bridge: the ATA slave is connected + * to the SATA0 bridge + * @master_to_sata1: Gemini SATA bridge: the ATA master is connected + * to the SATA1 bridge + * @slave_to_sata1: Gemini SATA bridge: the ATA slave is connected + * to the SATA1 bridge + */ +struct ftide010 { + struct device *dev; + void __iomem *base; + struct clk *pclk; + struct ata_host *host; + unsigned int master_cbl; + unsigned int slave_cbl; + /* Gemini-specific properties */ + struct sata_gemini *sg; + bool master_to_sata0; + bool slave_to_sata0; + bool master_to_sata1; + bool slave_to_sata1; +}; + +#define FTIDE010_DMA_REG 0x00 +#define FTIDE010_DMA_STATUS 0x02 +#define FTIDE010_IDE_BMDTPR 0x04 +#define FTIDE010_IDE_DEVICE_ID 0x08 +#define FTIDE010_PIO_TIMING 0x10 +#define FTIDE010_MWDMA_TIMING 0x11 +#define FTIDE010_UDMA_TIMING0 0x12 /* Master */ +#define FTIDE010_UDMA_TIMING1 0x13 /* Slave */ +#define FTIDE010_CLK_MOD 0x14 +/* These registers are mapped directly to the IDE registers */ +#define FTIDE010_CMD_DATA 0x20 +#define FTIDE010_ERROR_FEATURES 0x21 +#define FTIDE010_NSECT 0x22 +#define FTIDE010_LBAL 0x23 +#define FTIDE010_LBAM 0x24 +#define FTIDE010_LBAH 0x25 +#define FTIDE010_DEVICE 0x26 +#define FTIDE010_STATUS_COMMAND 0x27 +#define FTIDE010_ALTSTAT_CTRL 0x36 + +/* Set this bit for UDMA mode 5 and 6 */ +#define FTIDE010_UDMA_TIMING_MODE_56 BIT(7) + +/* 0 = 50 MHz, 1 = 66 MHz */ +#define FTIDE010_CLK_MOD_DEV0_CLK_SEL BIT(0) +#define FTIDE010_CLK_MOD_DEV1_CLK_SEL BIT(1) +/* Enable UDMA on a device */ +#define FTIDE010_CLK_MOD_DEV0_UDMA_EN BIT(4) +#define FTIDE010_CLK_MOD_DEV1_UDMA_EN BIT(5) + +static struct scsi_host_template pata_ftide010_sht = { + ATA_BMDMA_SHT(DRV_NAME), +}; + +/* + * Bus timings + * + * The unit of the below required timings is two clock periods of the ATA + * reference clock which is 30 nanoseconds per unit at 66MHz and 20 + * nanoseconds per unit at 50 MHz. The PIO timings assume 33MHz speed for + * PIO. + * + * pio_active_time: array of 5 elements for T2 timing for Mode 0, + * 1, 2, 3 and 4. Range 0..15. + * pio_recovery_time: array of 5 elements for T2l timing for Mode 0, + * 1, 2, 3 and 4. Range 0..15. + * mdma_50_active_time: array of 4 elements for Td timing for multi + * word DMA, Mode 0, 1, and 2 at 50 MHz. Range 0..15. + * mdma_50_recovery_time: array of 4 elements for Tk timing for + * multi word DMA, Mode 0, 1 and 2 at 50 MHz. Range 0..15. + * mdma_66_active_time: array of 4 elements for Td timing for multi + * word DMA, Mode 0, 1 and 2 at 66 MHz. Range 0..15. + * mdma_66_recovery_time: array of 4 elements for Tk timing for + * multi word DMA, Mode 0, 1 and 2 at 66 MHz. Range 0..15. + * udma_50_setup_time: array of 4 elements for Tvds timing for ultra + * DMA, Mode 0, 1, 2, 3, 4 and 5 at 50 MHz. Range 0..7. + * udma_50_hold_time: array of 4 elements for Tdvh timing for + * multi word DMA, Mode 0, 1, 2, 3, 4 and 5 at 50 MHz, Range 0..7. + * udma_66_setup_time: array of 4 elements for Tvds timing for multi + * word DMA, Mode 0, 1, 2, 3, 4, 5 and 6 at 66 MHz. Range 0..7. + * udma_66_hold_time: array of 4 elements for Tdvh timing for + * multi word DMA, Mode 0, 1, 2, 3, 4, 5 and 6 at 66 MHz. Range 0..7. + */ +static const u8 pio_active_time[5] = {10, 10, 10, 3, 3}; +static const u8 pio_recovery_time[5] = {10, 3, 1, 3, 1}; +static const u8 mwdma_50_active_time[3] = {6, 2, 2}; +static const u8 mwdma_50_recovery_time[3] = {6, 2, 1}; +static const u8 mwdma_66_active_time[3] = {8, 3, 3}; +static const u8 mwdma_66_recovery_time[3] = {8, 2, 1}; +static const u8 udma_50_setup_time[6] = {3, 3, 2, 2, 1, 1}; +static const u8 udma_50_hold_time[6] = {3, 1, 1, 1, 1, 1}; +static const u8 udma_66_setup_time[7] = {4, 4, 3, 2, }; +static const u8 udma_66_hold_time[7] = {}; + +/* + * We set 66 MHz for all MWDMA modes + */ +static const bool set_mdma_66_mhz[] = { true, true, true, true }; + +/* + * We set 66 MHz for UDMA modes 3, 4 and 6 and no others + */ +static const bool set_udma_66_mhz[] = { false, false, false, true, true, false, true }; + +static void ftide010_set_dmamode(struct ata_port *ap, struct ata_device *adev) +{ + struct ftide010 *ftide = ap->host->private_data; + u8 speed = adev->dma_mode; + u8 devno = adev->devno & 1; + u8 udma_en_mask; + u8 f66m_en_mask; + u8 clkreg; + u8 timreg; + u8 i; + + /* Target device 0 (master) or 1 (slave) */ + if (!devno) { + udma_en_mask = FTIDE010_CLK_MOD_DEV0_UDMA_EN; + f66m_en_mask = FTIDE010_CLK_MOD_DEV0_CLK_SEL; + } else { + udma_en_mask = FTIDE010_CLK_MOD_DEV1_UDMA_EN; + f66m_en_mask = FTIDE010_CLK_MOD_DEV1_CLK_SEL; + } + + clkreg = readb(ftide->base + FTIDE010_CLK_MOD); + clkreg &= ~udma_en_mask; + clkreg &= ~f66m_en_mask; + + if (speed & XFER_UDMA_0) { + i = speed & ~XFER_UDMA_0; + dev_dbg(ftide->dev, "set UDMA mode %02x, index %d\n", + speed, i); + + clkreg |= udma_en_mask; + if (set_udma_66_mhz[i]) { + clkreg |= f66m_en_mask; + timreg = udma_66_setup_time[i] << 4 | + udma_66_hold_time[i]; + } else { + timreg = udma_50_setup_time[i] << 4 | + udma_50_hold_time[i]; + } + + /* A special bit needs to be set for modes 5 and 6 */ + if (i >= 5) + timreg |= FTIDE010_UDMA_TIMING_MODE_56; + + dev_dbg(ftide->dev, "UDMA write clkreg = %02x, timreg = %02x\n", + clkreg, timreg); + + writeb(clkreg, ftide->base + FTIDE010_CLK_MOD); + writeb(timreg, ftide->base + FTIDE010_UDMA_TIMING0 + devno); + } else { + i = speed & ~XFER_MW_DMA_0; + dev_dbg(ftide->dev, "set MWDMA mode %02x, index %d\n", + speed, i); + + if (set_mdma_66_mhz[i]) { + clkreg |= f66m_en_mask; + timreg = mwdma_66_active_time[i] << 4 | + mwdma_66_recovery_time[i]; + } else { + timreg = mwdma_50_active_time[i] << 4 | + mwdma_50_recovery_time[i]; + } + dev_dbg(ftide->dev, + "MWDMA write clkreg = %02x, timreg = %02x\n", + clkreg, timreg); + /* This will affect all devices */ + writeb(clkreg, ftide->base + FTIDE010_CLK_MOD); + writeb(timreg, ftide->base + FTIDE010_MWDMA_TIMING); + } + + /* + * Store the current device (master or slave) in ap->private_data + * so that .qc_issue() can detect if this changes and reprogram + * the DMA settings. + */ + ap->private_data = adev; + + return; +} + +static void ftide010_set_piomode(struct ata_port *ap, struct ata_device *adev) +{ + struct ftide010 *ftide = ap->host->private_data; + u8 pio = adev->pio_mode - XFER_PIO_0; + + dev_dbg(ftide->dev, "set PIO mode %02x, index %d\n", + adev->pio_mode, pio); + writeb(pio_active_time[pio] << 4 | pio_recovery_time[pio], + ftide->base + FTIDE010_PIO_TIMING); +} + +/* + * We implement our own qc_issue() callback since we may need to set up + * the timings differently for master and slave transfers: the CLK_MOD_REG + * and MWDMA_TIMING_REG is shared between master and slave, so reprogramming + * this may be necessary. + */ +static unsigned int ftide010_qc_issue(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct ata_device *adev = qc->dev; + + /* + * If the device changed, i.e. slave->master, master->slave, + * then set up the DMA mode again so we are sure the timings + * are correct. + */ + if (adev != ap->private_data && ata_dma_enabled(adev)) + ftide010_set_dmamode(ap, adev); + + return ata_bmdma_qc_issue(qc); +} + +static struct ata_port_operations pata_ftide010_port_ops = { + .inherits = &ata_bmdma_port_ops, + .set_dmamode = ftide010_set_dmamode, + .set_piomode = ftide010_set_piomode, + .qc_issue = ftide010_qc_issue, +}; + +static struct ata_port_info ftide010_port_info[] = { + { + .flags = ATA_FLAG_SLAVE_POSS, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .pio_mask = ATA_PIO4, + .port_ops = &pata_ftide010_port_ops, + }, +}; + +#if IS_ENABLED(CONFIG_SATA_GEMINI) + +static int pata_ftide010_gemini_port_start(struct ata_port *ap) +{ + struct ftide010 *ftide = ap->host->private_data; + struct device *dev = ftide->dev; + struct sata_gemini *sg = ftide->sg; + int bridges = 0; + int ret; + + ret = ata_bmdma_port_start(ap); + if (ret) + return ret; + + if (ftide->master_to_sata0) { + dev_info(dev, "SATA0 (master) start\n"); + ret = gemini_sata_start_bridge(sg, 0); + if (!ret) + bridges++; + } + if (ftide->master_to_sata1) { + dev_info(dev, "SATA1 (master) start\n"); + ret = gemini_sata_start_bridge(sg, 1); + if (!ret) + bridges++; + } + /* Avoid double-starting */ + if (ftide->slave_to_sata0 && !ftide->master_to_sata0) { + dev_info(dev, "SATA0 (slave) start\n"); + ret = gemini_sata_start_bridge(sg, 0); + if (!ret) + bridges++; + } + /* Avoid double-starting */ + if (ftide->slave_to_sata1 && !ftide->master_to_sata1) { + dev_info(dev, "SATA1 (slave) start\n"); + ret = gemini_sata_start_bridge(sg, 1); + if (!ret) + bridges++; + } + + dev_info(dev, "brought %d bridges online\n", bridges); + return (bridges > 0) ? 0 : -EINVAL; // -ENODEV; +} + +static void pata_ftide010_gemini_port_stop(struct ata_port *ap) +{ + struct ftide010 *ftide = ap->host->private_data; + struct device *dev = ftide->dev; + struct sata_gemini *sg = ftide->sg; + + if (ftide->master_to_sata0) { + dev_info(dev, "SATA0 (master) stop\n"); + gemini_sata_stop_bridge(sg, 0); + } + if (ftide->master_to_sata1) { + dev_info(dev, "SATA1 (master) stop\n"); + gemini_sata_stop_bridge(sg, 1); + } + /* Avoid double-stopping */ + if (ftide->slave_to_sata0 && !ftide->master_to_sata0) { + dev_info(dev, "SATA0 (slave) stop\n"); + gemini_sata_stop_bridge(sg, 0); + } + /* Avoid double-stopping */ + if (ftide->slave_to_sata1 && !ftide->master_to_sata1) { + dev_info(dev, "SATA1 (slave) stop\n"); + gemini_sata_stop_bridge(sg, 1); + } +} + +static int pata_ftide010_gemini_cable_detect(struct ata_port *ap) +{ + struct ftide010 *ftide = ap->host->private_data; + + /* + * Return the master cable, I have no clue how to return a different + * cable for the slave than for the master. + */ + return ftide->master_cbl; +} + +static int pata_ftide010_gemini_init(struct ftide010 *ftide, + bool is_ata1) +{ + struct device *dev = ftide->dev; + struct sata_gemini *sg; + enum gemini_muxmode muxmode; + + /* Look up SATA bridge */ + sg = gemini_sata_bridge_get(); + if (IS_ERR(sg)) + return PTR_ERR(sg); + ftide->sg = sg; + + muxmode = gemini_sata_get_muxmode(sg); + + /* Special ops */ + pata_ftide010_port_ops.port_start = + pata_ftide010_gemini_port_start; + pata_ftide010_port_ops.port_stop = + pata_ftide010_gemini_port_stop; + pata_ftide010_port_ops.cable_detect = + pata_ftide010_gemini_cable_detect; + + /* Flag port as SATA-capable */ + if (gemini_sata_bridge_enabled(sg, is_ata1)) + ftide010_port_info[0].flags |= ATA_FLAG_SATA; + + /* + * We assume that a simple 40-wire cable is used in the PATA mode. + * if you're adding a system using the PATA interface, make sure + * the right cable is set up here, it might be necessary to use + * special hardware detection or encode the cable type in the device + * tree with special properties. + */ + if (!is_ata1) { + switch (muxmode) { + case GEMINI_MUXMODE_0: + ftide->master_cbl = ATA_CBL_SATA; + ftide->slave_cbl = ATA_CBL_PATA40; + ftide->master_to_sata0 = true; + break; + case GEMINI_MUXMODE_1: + ftide->master_cbl = ATA_CBL_SATA; + ftide->slave_cbl = ATA_CBL_NONE; + ftide->master_to_sata0 = true; + break; + case GEMINI_MUXMODE_2: + ftide->master_cbl = ATA_CBL_PATA40; + ftide->slave_cbl = ATA_CBL_PATA40; + break; + case GEMINI_MUXMODE_3: + ftide->master_cbl = ATA_CBL_SATA; + ftide->slave_cbl = ATA_CBL_SATA; + ftide->master_to_sata0 = true; + ftide->slave_to_sata1 = true; + break; + } + } else { + switch (muxmode) { + case GEMINI_MUXMODE_0: + ftide->master_cbl = ATA_CBL_SATA; + ftide->slave_cbl = ATA_CBL_NONE; + ftide->master_to_sata1 = true; + break; + case GEMINI_MUXMODE_1: + ftide->master_cbl = ATA_CBL_SATA; + ftide->slave_cbl = ATA_CBL_PATA40; + ftide->master_to_sata1 = true; + break; + case GEMINI_MUXMODE_2: + ftide->master_cbl = ATA_CBL_SATA; + ftide->slave_cbl = ATA_CBL_SATA; + ftide->slave_to_sata0 = true; + ftide->master_to_sata1 = true; + break; + case GEMINI_MUXMODE_3: + ftide->master_cbl = ATA_CBL_PATA40; + ftide->slave_cbl = ATA_CBL_PATA40; + break; + } + } + dev_info(dev, "set up Gemini PATA%d\n", is_ata1); + + return 0; +} +#else +static int pata_ftide010_gemini_init(struct ftide010 *ftide, + bool is_ata1) +{ + return -ENOTSUPP; +} +#endif + + +static int pata_ftide010_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + const struct ata_port_info pi = ftide010_port_info[0]; + const struct ata_port_info *ppi[] = { &pi, NULL }; + struct ftide010 *ftide; + struct resource *res; + int irq; + int ret; + int i; + + ftide = devm_kzalloc(dev, sizeof(*ftide), GFP_KERNEL); + if (!ftide) + return -ENOMEM; + ftide->dev = dev; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + ftide->base = devm_ioremap_resource(dev, res); + if (IS_ERR(ftide->base)) + return PTR_ERR(ftide->base); + + ftide->pclk = devm_clk_get(dev, "PCLK"); + if (!IS_ERR(ftide->pclk)) { + ret = clk_prepare_enable(ftide->pclk); + if (ret) { + dev_err(dev, "failed to enable PCLK\n"); + return ret; + } + } + + /* Some special Cortina Gemini init, if needed */ + if (of_device_is_compatible(np, "cortina,gemini-pata")) { + /* + * We need to know which instance is probing (the + * Gemini has two instances of FTIDE010) and we do + * this simply by looking at the physical base + * address, which is 0x63400000 for ATA1, else we + * are ATA0. This will also set up the cable types. + */ + ret = pata_ftide010_gemini_init(ftide, + (res->start == 0x63400000)); + if (ret) + goto err_dis_clk; + } else { + /* Else assume we are connected using PATA40 */ + ftide->master_cbl = ATA_CBL_PATA40; + ftide->slave_cbl = ATA_CBL_PATA40; + } + + ftide->host = ata_host_alloc_pinfo(dev, ppi, 1); + if (!ftide->host) { + ret = -ENOMEM; + goto err_dis_clk; + } + ftide->host->private_data = ftide; + + for (i = 0; i < ftide->host->n_ports; i++) { + struct ata_port *ap = ftide->host->ports[i]; + struct ata_ioports *ioaddr = &ap->ioaddr; + + ioaddr->bmdma_addr = ftide->base + FTIDE010_DMA_REG; + ioaddr->cmd_addr = ftide->base + FTIDE010_CMD_DATA; + ioaddr->ctl_addr = ftide->base + FTIDE010_ALTSTAT_CTRL; + ioaddr->altstatus_addr = ftide->base + FTIDE010_ALTSTAT_CTRL; + ata_sff_std_ports(ioaddr); + } + + dev_info(dev, "device ID %08x, irq %d, io base 0x%08x\n", + readl(ftide->base + FTIDE010_IDE_DEVICE_ID), irq, res->start); + + ret = ata_host_activate(ftide->host, irq, ata_bmdma_interrupt, + 0, &pata_ftide010_sht); + if (ret) + goto err_dis_clk; + + return 0; + +err_dis_clk: + if (!IS_ERR(ftide->pclk)) + clk_disable_unprepare(ftide->pclk); + return ret; +} + +static int pata_ftide010_remove(struct platform_device *pdev) +{ + struct ata_host *host = platform_get_drvdata(pdev); + struct ftide010 *ftide = host->private_data; + + ata_host_detach(ftide->host); + if (!IS_ERR(ftide->pclk)) + clk_disable_unprepare(ftide->pclk); + + return 0; +} + +static const struct of_device_id pata_ftide010_of_match[] = { + { + .compatible = "faraday,ftide010", + }, + {}, +}; + +static struct platform_driver pata_ftide010_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(pata_ftide010_of_match), + }, + .probe = pata_ftide010_probe, + .remove = pata_ftide010_remove, +}; +module_platform_driver(pata_ftide010_driver); + +MODULE_AUTHOR("Linus Walleij "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/ata/sata_gemini.c b/drivers/ata/sata_gemini.c new file mode 100644 index 000000000000..8c704523bae7 --- /dev/null +++ b/drivers/ata/sata_gemini.c @@ -0,0 +1,438 @@ +/* + * Cortina Systems Gemini SATA bridge add-on to Faraday FTIDE010 + * Copyright (C) 2017 Linus Walleij + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sata_gemini.h" + +#define DRV_NAME "gemini_sata_bridge" + +/** + * struct sata_gemini - a state container for a Gemini SATA bridge + * @dev: the containing device + * @base: remapped I/O memory base + * @muxmode: the current muxing mode + * @ide_pins: if the device is using the plain IDE interface pins + * @sata_bridge: if the device enables the SATA bridge + * @sata0_reset: SATA0 reset handler + * @sata1_reset: SATA1 reset handler + * @sata0_pclk: SATA0 PCLK handler + * @sata1_pclk: SATA1 PCLK handler + */ +struct sata_gemini { + struct device *dev; + void __iomem *base; + enum gemini_muxmode muxmode; + bool ide_pins; + bool sata_bridge; + struct reset_control *sata0_reset; + struct reset_control *sata1_reset; + struct clk *sata0_pclk; + struct clk *sata1_pclk; +}; + +/* Global IDE PAD Skew Control Register */ +#define GEMINI_GLOBAL_IDE_SKEW_CTRL 0x18 +#define GEMINI_IDE1_HOST_STROBE_DELAY_SHIFT 28 +#define GEMINI_IDE1_DEVICE_STROBE_DELAY_SHIFT 24 +#define GEMINI_IDE1_OUTPUT_IO_SKEW_SHIFT 20 +#define GEMINI_IDE1_INPUT_IO_SKEW_SHIFT 16 +#define GEMINI_IDE0_HOST_STROBE_DELAY_SHIFT 12 +#define GEMINI_IDE0_DEVICE_STROBE_DELAY_SHIFT 8 +#define GEMINI_IDE0_OUTPUT_IO_SKEW_SHIFT 4 +#define GEMINI_IDE0_INPUT_IO_SKEW_SHIFT 0 + +/* Miscellaneous Control Register */ +#define GEMINI_GLOBAL_MISC_CTRL 0x30 +/* + * Values of IDE IOMUX bits in the misc control register + * + * Bits 26:24 are "IDE IO Select", which decides what SATA + * adapters are connected to which of the two IDE/ATA + * controllers in the Gemini. We can connect the two IDE blocks + * to one SATA adapter each, both acting as master, or one IDE + * blocks to two SATA adapters so the IDE block can act in a + * master/slave configuration. + * + * We also bring out different blocks on the actual IDE + * pins (not SATA pins) if (and only if) these are muxed in. + * + * 111-100 - Reserved + * Mode 0: 000 - ata0 master <-> sata0 + * ata1 master <-> sata1 + * ata0 slave interface brought out on IDE pads + * Mode 1: 001 - ata0 master <-> sata0 + * ata1 master <-> sata1 + * ata1 slave interface brought out on IDE pads + * Mode 2: 010 - ata1 master <-> sata1 + * ata1 slave <-> sata0 + * ata0 master and slave interfaces brought out + * on IDE pads + * Mode 3: 011 - ata0 master <-> sata0 + * ata1 slave <-> sata1 + * ata1 master and slave interfaces brought out + * on IDE pads + */ +#define GEMINI_IDE_IOMUX_MASK (7 << 24) +#define GEMINI_IDE_IOMUX_MODE0 (0 << 24) +#define GEMINI_IDE_IOMUX_MODE1 (1 << 24) +#define GEMINI_IDE_IOMUX_MODE2 (2 << 24) +#define GEMINI_IDE_IOMUX_MODE3 (3 << 24) +#define GEMINI_IDE_IOMUX_SHIFT (24) +#define GEMINI_IDE_PADS_ENABLE BIT(4) +#define GEMINI_PFLASH_PADS_DISABLE BIT(1) + +/* + * Registers directly controlling the PATA<->SATA adapters + */ +#define GEMINI_SATA_ID 0x00 +#define GEMINI_SATA_PHY_ID 0x04 +#define GEMINI_SATA0_STATUS 0x08 +#define GEMINI_SATA1_STATUS 0x0c +#define GEMINI_SATA0_CTRL 0x18 +#define GEMINI_SATA1_CTRL 0x1c + +#define GEMINI_SATA_STATUS_BIST_DONE BIT(5) +#define GEMINI_SATA_STATUS_BIST_OK BIT(4) +#define GEMINI_SATA_STATUS_PHY_READY BIT(0) + +#define GEMINI_SATA_CTRL_PHY_BIST_EN BIT(14) +#define GEMINI_SATA_CTRL_PHY_FORCE_IDLE BIT(13) +#define GEMINI_SATA_CTRL_PHY_FORCE_READY BIT(12) +#define GEMINI_SATA_CTRL_PHY_AFE_LOOP_EN BIT(10) +#define GEMINI_SATA_CTRL_PHY_DIG_LOOP_EN BIT(9) +#define GEMINI_SATA_CTRL_HOTPLUG_DETECT_EN BIT(4) +#define GEMINI_SATA_CTRL_ATAPI_EN BIT(3) +#define GEMINI_SATA_CTRL_BUS_WITH_20 BIT(2) +#define GEMINI_SATA_CTRL_SLAVE_EN BIT(1) +#define GEMINI_SATA_CTRL_EN BIT(0) + +/* + * There is only ever one instance of this bridge on a system, + * so create a singleton so that the FTIDE010 instances can grab + * a reference to it. + */ +static struct sata_gemini *sg_singleton; + +struct sata_gemini *gemini_sata_bridge_get(void) +{ + if (sg_singleton) + return sg_singleton; + return ERR_PTR(-EPROBE_DEFER); +} +EXPORT_SYMBOL(gemini_sata_bridge_get); + +bool gemini_sata_bridge_enabled(struct sata_gemini *sg, bool is_ata1) +{ + if (!sg->sata_bridge) + return false; + /* + * In muxmode 2 and 3 one of the ATA controllers is + * actually not connected to any SATA bridge. + */ + if ((sg->muxmode == GEMINI_MUXMODE_2) && + !is_ata1) + return false; + if ((sg->muxmode == GEMINI_MUXMODE_3) && + is_ata1) + return false; + + return true; +} +EXPORT_SYMBOL(gemini_sata_bridge_enabled); + +enum gemini_muxmode gemini_sata_get_muxmode(struct sata_gemini *sg) +{ + return sg->muxmode; +} +EXPORT_SYMBOL(gemini_sata_get_muxmode); + +static int gemini_sata_setup_bridge(struct sata_gemini *sg, + unsigned int bridge) +{ + unsigned long timeout = jiffies + (HZ * 1); + bool bridge_online; + u32 val; + + if (bridge == 0) { + val = GEMINI_SATA_CTRL_HOTPLUG_DETECT_EN | GEMINI_SATA_CTRL_EN; + /* SATA0 slave mode is only used in muxmode 2 */ + if (sg->muxmode == GEMINI_MUXMODE_2) + val |= GEMINI_SATA_CTRL_SLAVE_EN; + writel(val, sg->base + GEMINI_SATA0_CTRL); + } else { + val = GEMINI_SATA_CTRL_HOTPLUG_DETECT_EN | GEMINI_SATA_CTRL_EN; + /* SATA1 slave mode is only used in muxmode 3 */ + if (sg->muxmode == GEMINI_MUXMODE_3) + val |= GEMINI_SATA_CTRL_SLAVE_EN; + writel(val, sg->base + GEMINI_SATA1_CTRL); + } + + /* Vendor code waits 10 ms here */ + msleep(10); + + /* Wait for PHY to become ready */ + do { + msleep(100); + + if (bridge == 0) + val = readl(sg->base + GEMINI_SATA0_STATUS); + else + val = readl(sg->base + GEMINI_SATA1_STATUS); + if (val & GEMINI_SATA_STATUS_PHY_READY) + break; + } while (time_before(jiffies, timeout)); + + bridge_online = !!(val & GEMINI_SATA_STATUS_PHY_READY); + + dev_info(sg->dev, "SATA%d PHY %s\n", bridge, + bridge_online ? "ready" : "not ready"); + + return bridge_online ? 0: -ENODEV; +} + +int gemini_sata_start_bridge(struct sata_gemini *sg, unsigned int bridge) +{ + struct clk *pclk; + int ret; + + if (bridge == 0) + pclk = sg->sata0_pclk; + else + pclk = sg->sata1_pclk; + clk_enable(pclk); + msleep(10); + + /* Do not keep clocking a bridge that is not online */ + ret = gemini_sata_setup_bridge(sg, bridge); + if (ret) + clk_disable(pclk); + + return ret; +} +EXPORT_SYMBOL(gemini_sata_start_bridge); + +void gemini_sata_stop_bridge(struct sata_gemini *sg, unsigned int bridge) +{ + if (bridge == 0) + clk_disable(sg->sata0_pclk); + else if (bridge == 1) + clk_disable(sg->sata1_pclk); +} +EXPORT_SYMBOL(gemini_sata_stop_bridge); + +int gemini_sata_reset_bridge(struct sata_gemini *sg, + unsigned int bridge) +{ + if (bridge == 0) + reset_control_reset(sg->sata0_reset); + else + reset_control_reset(sg->sata1_reset); + msleep(10); + return gemini_sata_setup_bridge(sg, bridge); +} +EXPORT_SYMBOL(gemini_sata_reset_bridge); + +static int gemini_sata_bridge_init(struct sata_gemini *sg) +{ + struct device *dev = sg->dev; + u32 sata_id, sata_phy_id; + int ret; + + sg->sata0_pclk = devm_clk_get(dev, "SATA0_PCLK"); + if (IS_ERR(sg->sata0_pclk)) { + dev_err(dev, "no SATA0 PCLK"); + return -ENODEV; + } + sg->sata1_pclk = devm_clk_get(dev, "SATA1_PCLK"); + if (IS_ERR(sg->sata1_pclk)) { + dev_err(dev, "no SATA1 PCLK"); + return -ENODEV; + } + + ret = clk_prepare_enable(sg->sata0_pclk); + if (ret) { + pr_err("failed to enable SATA0 PCLK\n"); + return ret; + } + ret = clk_prepare_enable(sg->sata1_pclk); + if (ret) { + pr_err("failed to enable SATA1 PCLK\n"); + clk_disable_unprepare(sg->sata0_pclk); + return ret; + } + + sg->sata0_reset = devm_reset_control_get(dev, "sata0"); + if (IS_ERR(sg->sata0_reset)) { + dev_err(dev, "no SATA0 reset controller\n"); + clk_disable_unprepare(sg->sata1_pclk); + clk_disable_unprepare(sg->sata0_pclk); + return PTR_ERR(sg->sata0_reset); + } + sg->sata1_reset = devm_reset_control_get(dev, "sata1"); + if (IS_ERR(sg->sata1_reset)) { + dev_err(dev, "no SATA1 reset controller\n"); + clk_disable_unprepare(sg->sata1_pclk); + clk_disable_unprepare(sg->sata0_pclk); + return PTR_ERR(sg->sata1_reset); + } + + sata_id = readl(sg->base + GEMINI_SATA_ID); + sata_phy_id = readl(sg->base + GEMINI_SATA_PHY_ID); + sg->sata_bridge = true; + clk_disable(sg->sata0_pclk); + clk_disable(sg->sata1_pclk); + + dev_info(dev, "SATA ID %08x, PHY ID: %08x\n", sata_id, sata_phy_id); + + return 0; +} + +static int gemini_sata_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct sata_gemini *sg; + static struct regmap *map; + struct resource *res; + enum gemini_muxmode muxmode; + u32 gmode; + u32 gmask; + u32 val; + int ret; + + sg = devm_kzalloc(dev, sizeof(*sg), GFP_KERNEL); + if (!sg) + return -ENOMEM; + sg->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + sg->base = devm_ioremap_resource(dev, res); + if (IS_ERR(sg->base)) + return PTR_ERR(sg->base); + + map = syscon_regmap_lookup_by_phandle(np, "syscon"); + if (IS_ERR(map)) { + dev_err(dev, "no global syscon\n"); + return PTR_ERR(map); + } + + /* Set up the SATA bridge if need be */ + if (of_property_read_bool(np, "cortina,gemini-enable-sata-bridge")) { + ret = gemini_sata_bridge_init(sg); + if (ret) + return ret; + } + + if (of_property_read_bool(np, "cortina,gemini-enable-ide-pins")) + sg->ide_pins = true; + + if (!sg->sata_bridge && !sg->ide_pins) { + dev_err(dev, "neither SATA bridge or IDE output enabled\n"); + ret = -EINVAL; + goto out_unprep_clk; + } + + ret = of_property_read_u32(np, "cortina,gemini-ata-muxmode", &muxmode); + if (ret) { + dev_err(dev, "could not parse ATA muxmode\n"); + goto out_unprep_clk; + } + if (muxmode > GEMINI_MUXMODE_3) { + dev_err(dev, "illegal muxmode %d\n", muxmode); + ret = -EINVAL; + goto out_unprep_clk; + } + sg->muxmode = muxmode; + gmask = GEMINI_IDE_IOMUX_MASK; + gmode = (muxmode << GEMINI_IDE_IOMUX_SHIFT); + + /* + * If we mux out the IDE, parallel flash must be disabled. + * SATA0 and SATA1 have dedicated pins and may coexist with + * parallel flash. + */ + if (sg->ide_pins) + gmode |= GEMINI_IDE_PADS_ENABLE | GEMINI_PFLASH_PADS_DISABLE; + else + gmask |= GEMINI_IDE_PADS_ENABLE; + + ret = regmap_update_bits(map, GEMINI_GLOBAL_MISC_CTRL, gmask, gmode); + if (ret) { + dev_err(dev, "unable to set up IDE muxing\n"); + ret = -ENODEV; + goto out_unprep_clk; + } + + /* FIXME: add more elaborate IDE skew control handling */ + if (sg->ide_pins) { + ret = regmap_read(map, GEMINI_GLOBAL_IDE_SKEW_CTRL, &val); + if (ret) { + dev_err(dev, "cannot read IDE skew control register\n"); + return ret; + } + dev_info(dev, "IDE skew control: %08x\n", val); + } + + dev_info(dev, "set up the Gemini IDE/SATA nexus\n"); + platform_set_drvdata(pdev, sg); + sg_singleton = sg; + + return 0; + +out_unprep_clk: + if (sg->sata_bridge) { + clk_unprepare(sg->sata1_pclk); + clk_unprepare(sg->sata0_pclk); + } + return ret; +} + +static int gemini_sata_remove(struct platform_device *pdev) +{ + struct sata_gemini *sg = platform_get_drvdata(pdev); + + if (sg->sata_bridge) { + clk_unprepare(sg->sata1_pclk); + clk_unprepare(sg->sata0_pclk); + } + sg_singleton = NULL; + + return 0; +} + +static const struct of_device_id gemini_sata_of_match[] = { + { + .compatible = "cortina,gemini-sata-bridge", + }, + {}, +}; + +static struct platform_driver gemini_sata_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(gemini_sata_of_match), + }, + .probe = gemini_sata_probe, + .remove = gemini_sata_remove, +}; +module_platform_driver(gemini_sata_driver); + +MODULE_AUTHOR("Linus Walleij "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/ata/sata_gemini.h b/drivers/ata/sata_gemini.h new file mode 100644 index 000000000000..ca1837a394c8 --- /dev/null +++ b/drivers/ata/sata_gemini.h @@ -0,0 +1,21 @@ +/* Header for the Gemini SATA bridge */ +#ifndef SATA_GEMINI_H +#define SATA_GEMINI_H + +struct sata_gemini; + +enum gemini_muxmode { + GEMINI_MUXMODE_0 = 0, + GEMINI_MUXMODE_1, + GEMINI_MUXMODE_2, + GEMINI_MUXMODE_3, +}; + +struct sata_gemini *gemini_sata_bridge_get(void); +bool gemini_sata_bridge_enabled(struct sata_gemini *sg, bool is_ata1); +enum gemini_muxmode gemini_sata_get_muxmode(struct sata_gemini *sg); +int gemini_sata_start_bridge(struct sata_gemini *sg, unsigned int bridge); +void gemini_sata_stop_bridge(struct sata_gemini *sg, unsigned int bridge); +int gemini_sata_reset_bridge(struct sata_gemini *sg, unsigned int bridge); + +#endif -- cgit v1.2.3 From f356b08205f6668248960093faf9326c7852a38d Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 9 Jun 2017 17:15:08 +0530 Subject: ata: declare ata_port_info structures as const ata_port_info structures are either copied to other objects or their references are stored in objects of type const. So, ata_port_info structures having similar usage pattern can be made const. Signed-off-by: Bhumika Goyal Signed-off-by: Tejun Heo --- drivers/ata/pata_rdc.c | 2 +- drivers/ata/pata_sch.c | 2 +- drivers/ata/sata_inic162x.c | 2 +- drivers/ata/sata_via.c | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c index 9ce5952216bc..959bb54fd803 100644 --- a/drivers/ata/pata_rdc.c +++ b/drivers/ata/pata_rdc.c @@ -292,7 +292,7 @@ static struct ata_port_operations rdc_pata_ops = { .prereset = rdc_pata_prereset, }; -static struct ata_port_info rdc_port_info = { +static const struct ata_port_info rdc_port_info = { .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c index b920c3407f8b..1b80a66caa54 100644 --- a/drivers/ata/pata_sch.c +++ b/drivers/ata/pata_sch.c @@ -81,7 +81,7 @@ static struct ata_port_operations sch_pata_ops = { .set_dmamode = sch_set_dmamode, }; -static struct ata_port_info sch_port_info = { +static const struct ata_port_info sch_port_info = { .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index e81a8217f1ff..9b6d7930d1c7 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -737,7 +737,7 @@ static struct ata_port_operations inic_port_ops = { .port_start = inic_port_start, }; -static struct ata_port_info inic_port_info = { +static const struct ata_port_info inic_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 22e96fc77d09..a3f6d330d106 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -166,7 +166,7 @@ static const struct ata_port_info vt6420_port_info = { .port_ops = &vt6420_sata_ops, }; -static struct ata_port_info vt6421_sport_info = { +static const struct ata_port_info vt6421_sport_info = { .flags = ATA_FLAG_SATA, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, @@ -174,7 +174,7 @@ static struct ata_port_info vt6421_sport_info = { .port_ops = &vt6421_sata_ops, }; -static struct ata_port_info vt6421_pport_info = { +static const struct ata_port_info vt6421_pport_info = { .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, /* No MWDMA */ @@ -182,7 +182,7 @@ static struct ata_port_info vt6421_pport_info = { .port_ops = &vt6421_pata_ops, }; -static struct ata_port_info vt8251_port_info = { +static const struct ata_port_info vt8251_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, -- cgit v1.2.3 From 08fc4756c35fb076027374ff026a82de3de3c5f4 Mon Sep 17 00:00:00 2001 From: Minwoo Im Date: Sun, 11 Jun 2017 23:53:00 +0900 Subject: libahci: wrong comments in ahci_do_softreset() AHCI 1.3.1 Spec says that software shall build two H2D register FISes in the command list to send a software reset. The comments in ahci_do_softreset() is currently D2H instead of H2D. Signed-off-by: Minwoo Im Signed-off-by: Tejun Heo --- drivers/ata/libahci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 6154f0e2b81a..b3a685ad9b87 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1400,7 +1400,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, ata_tf_init(link->device, &tf); - /* issue the first D2H Register FIS */ + /* issue the first H2D Register FIS */ msecs = 0; now = jiffies; if (time_after(deadline, now)) @@ -1417,7 +1417,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, /* spec says at least 5us, but be generous and sleep for 1ms */ ata_msleep(ap, 1); - /* issue the second D2H Register FIS */ + /* issue the second H2D Register FIS */ tf.ctl &= ~ATA_SRST; ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0); -- cgit v1.2.3 From 6ef56325d8a382be648c5743d038a20d4995008d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 12 Jun 2017 12:17:39 -0700 Subject: libata: Convert bare printks to pr_cont Linus Torvalds changed the behavior of printks without KERN_. Convert the continuation prints to use pr_cont. At the same time, convert the existing printks with KERN_ to pr_ Miscellanea: o Coalesce a multiline format Signed-off-by: Joe Perches Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 8dc84fd77369..0f788ad6f2f6 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -903,32 +903,32 @@ static void ata_dump_status(unsigned id, struct ata_taskfile *tf) { u8 stat = tf->command, err = tf->feature; - printk(KERN_WARNING "ata%u: status=0x%02x { ", id, stat); + pr_warn("ata%u: status=0x%02x { ", id, stat); if (stat & ATA_BUSY) { - printk("Busy }\n"); /* Data is not valid in this case */ + pr_cont("Busy }\n"); /* Data is not valid in this case */ } else { - if (stat & ATA_DRDY) printk("DriveReady "); - if (stat & ATA_DF) printk("DeviceFault "); - if (stat & ATA_DSC) printk("SeekComplete "); - if (stat & ATA_DRQ) printk("DataRequest "); - if (stat & ATA_CORR) printk("CorrectedError "); - if (stat & ATA_SENSE) printk("Sense "); - if (stat & ATA_ERR) printk("Error "); - printk("}\n"); + if (stat & ATA_DRDY) pr_cont("DriveReady "); + if (stat & ATA_DF) pr_cont("DeviceFault "); + if (stat & ATA_DSC) pr_cont("SeekComplete "); + if (stat & ATA_DRQ) pr_cont("DataRequest "); + if (stat & ATA_CORR) pr_cont("CorrectedError "); + if (stat & ATA_SENSE) pr_cont("Sense "); + if (stat & ATA_ERR) pr_cont("Error "); + pr_cont("}\n"); if (err) { - printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err); - if (err & ATA_ABORTED) printk("DriveStatusError "); + pr_warn("ata%u: error=0x%02x { ", id, err); + if (err & ATA_ABORTED) pr_cont("DriveStatusError "); if (err & ATA_ICRC) { if (err & ATA_ABORTED) - printk("BadCRC "); - else printk("Sector "); + pr_cont("BadCRC "); + else pr_cont("Sector "); } - if (err & ATA_UNC) printk("UncorrectableError "); - if (err & ATA_IDNF) printk("SectorIdNotFound "); - if (err & ATA_TRK0NF) printk("TrackZeroNotFound "); - if (err & ATA_AMNF) printk("AddrMarkNotFound "); - printk("}\n"); + if (err & ATA_UNC) pr_cont("UncorrectableError "); + if (err & ATA_IDNF) pr_cont("SectorIdNotFound "); + if (err & ATA_TRK0NF) pr_cont("TrackZeroNotFound "); + if (err & ATA_AMNF) pr_cont("AddrMarkNotFound "); + pr_cont("}\n"); } } } @@ -1059,8 +1059,7 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, translate_done: if (verbose) - printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x " - "to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", + pr_err("ata%u: translated ATA stat/err 0x%02x/%02x to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err, *sk, *asc, *ascq); return; } -- cgit v1.2.3 From 79af3ae6e293855321dcd1a43c73be316fdff1a9 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Fri, 16 Jun 2017 17:24:41 +0530 Subject: ata: pata_octeon_cf: make of_device_ids const. of_device_ids are not supposed to change at runtime. All functions working with of_device_ids provided by work with const of_device_ids. So mark the non-const structs as const. File size before: text data bss dec hex filename 465 696 4 1165 48d drivers/ata/pata_octeon_cf.o File size after constify octeon_cf_match. text data bss dec hex filename 865 280 4 1149 47d drivers/ata/pata_octeon_cf.o Signed-off-by: Arvind Yadav Signed-off-by: Tejun Heo --- drivers/ata/pata_octeon_cf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index f524a9099d01..1ba03d6df951 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -1038,7 +1038,7 @@ static void octeon_cf_shutdown(struct device *dev) } } -static struct of_device_id octeon_cf_match[] = { +static const struct of_device_id octeon_cf_match[] = { { .compatible = "cavium,ebt3000-compact-flash", }, -- cgit v1.2.3 From a5893870f8145b782e42d5ff187ae1dee6f2b650 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Fri, 16 Jun 2017 17:32:21 +0530 Subject: ata: sata_rcar: make of_device_ids const. of_device_ids are not supposed to change at runtime. All functions working with of_device_ids provided by work with const of_device_ids. So mark the non-const structs as const. File size before: text data bss dec hex filename 3946 2296 0 6242 1862 drivers/ata/sata_rcar.o File size after constify sata_rcar_match. text data bss dec hex filename 5554 696 0 6250 186a drivers/ata/sata_rcar.o Signed-off-by: Arvind Yadav Signed-off-by: Tejun Heo --- drivers/ata/sata_rcar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c index 5d38245a7a73..35945e31ba7d 100644 --- a/drivers/ata/sata_rcar.c +++ b/drivers/ata/sata_rcar.c @@ -828,7 +828,7 @@ static void sata_rcar_init_controller(struct ata_host *host) iowrite32(ATAPI_INT_ENABLE_SATAINT, base + ATAPI_INT_ENABLE_REG); } -static struct of_device_id sata_rcar_match[] = { +static const struct of_device_id sata_rcar_match[] = { { /* Deprecated by "renesas,sata-r8a7779" */ .compatible = "renesas,rcar-sata", -- cgit v1.2.3 From 01efd6006d19848084b9fcba7f3963ed38c1cd6c Mon Sep 17 00:00:00 2001 From: Minwoo Im Date: Tue, 20 Jun 2017 19:21:30 +0900 Subject: libata: make the function name in comment match the actual function The function name used to be ata_scsiop_mode_select() but renamed to ata_scsi_mode_select_xlat(). Update the comment accordingly. tj: Minor commit desc update. Signed-off-by: Minwoo Im Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 0f788ad6f2f6..4c300749aca5 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3914,7 +3914,7 @@ static int ata_mselect_control(struct ata_queued_cmd *qc, } /** - * ata_scsiop_mode_select - Simulate MODE SELECT 6, 10 commands + * ata_scsi_mode_select_xlat - Simulate MODE SELECT 6, 10 commands * @qc: Storage for translated ATA taskfile * * Converts a MODE SELECT command to an ATA SET FEATURES taskfile. -- cgit v1.2.3 From d0318fb3c388a4082a4ea2b94fc242cd5c064cea Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 22 Jun 2017 00:00:55 +0200 Subject: ata: ftide010: fix resource printing The new driver uses an incorrect format string for resource_size_t: drivers/ata/pata_ftide010.c: In function 'pata_ftide010_probe': drivers/ata/pata_ftide010.c:520:17: warning: format '%x' expects argument of type 'unsigned int', but argument 5 has type 'resource_size_t {aka long long unsigned int}' [-Wformat=] The nicest way to print the address is to pretty-print the resource using %pR. Fixes: be4e456ed3a5 ("ata: Add driver for Faraday Technology FTIDE010") Signed-off-by: Arnd Bergmann Signed-off-by: Tejun Heo --- drivers/ata/pata_ftide010.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_ftide010.c b/drivers/ata/pata_ftide010.c index 7b7e417ba8ba..5d4b72e21161 100644 --- a/drivers/ata/pata_ftide010.c +++ b/drivers/ata/pata_ftide010.c @@ -517,8 +517,8 @@ static int pata_ftide010_probe(struct platform_device *pdev) ata_sff_std_ports(ioaddr); } - dev_info(dev, "device ID %08x, irq %d, io base 0x%08x\n", - readl(ftide->base + FTIDE010_IDE_DEVICE_ID), irq, res->start); + dev_info(dev, "device ID %08x, irq %d, reg %pR\n", + readl(ftide->base + FTIDE010_IDE_DEVICE_ID), irq, res); ret = ata_host_activate(ftide->host, irq, ata_bmdma_interrupt, 0, &pata_ftide010_sht); -- cgit v1.2.3 From ef0da1bf767d9e557c6375c7066717eead54cb15 Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Wed, 21 Jun 2017 16:20:12 -0700 Subject: libata: Add the AHCI_HFLAG_YES_ALPM flag Some hardware is capable of supporting Aggresive Link Power Management even though it is not indicated by the Host Capability register. This commit adds the AHCI_HFLAG_YES_ALPM flag to the AHCI library to allow indication of this quirk when the Host Capability register is Read Only and therefore cannot be changed. Signed-off-by: Doug Berger Signed-off-by: Tejun Heo --- drivers/ata/ahci.h | 1 + drivers/ata/libahci.c | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 30f67a1a4f54..ee176e4af97a 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -248,6 +248,7 @@ enum { AHCI_HFLAG_MULTI_MSI = 0, #endif AHCI_HFLAG_WAKE_BEFORE_STOP = (1 << 22), /* wake before DMA stop */ + AHCI_HFLAG_YES_ALPM = (1 << 23), /* force ALPM cap on */ /* ap->flags bits */ diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index b3a685ad9b87..4462f8a8cf2c 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -504,6 +504,11 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv) cap &= ~HOST_CAP_FBS; } + if (!(cap & HOST_CAP_ALPM) && (hpriv->flags & AHCI_HFLAG_YES_ALPM)) { + dev_info(dev, "controller can do ALPM, turning on CAP_ALPM\n"); + cap |= HOST_CAP_ALPM; + } + if (hpriv->force_port_map && port_map != hpriv->force_port_map) { dev_info(dev, "forcing port_map 0x%x -> 0x%x\n", port_map, hpriv->force_port_map); -- cgit v1.2.3 From 7fab72f85d862572ed3281860dc550b7e737ac52 Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Wed, 21 Jun 2017 16:20:13 -0700 Subject: libata: Add the AHCI_HFLAG_NO_WRITE_TO_RO flag While most hardware will simply ignore a write to a read-only register, some hardware will signal an abort if this occurs. This commit introduces the flag AHCI_HFLAG_NO_WRITE_TO_RO to prevent the AHCI library from attempting to write to the HOST_CAP, HOST_CAP2, and HOST_PORTS_IMPL registers which may be read-only. Signed-off-by: Doug Berger Signed-off-by: Tejun Heo --- drivers/ata/ahci.h | 2 ++ drivers/ata/libahci.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index ee176e4af97a..8b61123d2c3c 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -249,6 +249,8 @@ enum { #endif AHCI_HFLAG_WAKE_BEFORE_STOP = (1 << 22), /* wake before DMA stop */ AHCI_HFLAG_YES_ALPM = (1 << 23), /* force ALPM cap on */ + AHCI_HFLAG_NO_WRITE_TO_RO = (1 << 24), /* don't write to read + only registers */ /* ap->flags bits */ diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 4462f8a8cf2c..3e286d86ab42 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -945,7 +945,8 @@ int ahci_reset_controller(struct ata_host *host) /* Some registers might be cleared on reset. Restore * initial values. */ - ahci_restore_initial_config(host); + if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO)) + ahci_restore_initial_config(host); } else dev_info(host->dev, "skipping global host reset\n"); -- cgit v1.2.3 From da8fa9cca5b760cb8e5ab16ce7e1941cfc3e04cc Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Wed, 21 Jun 2017 16:20:14 -0700 Subject: ata: ahci_brcm: Avoid writing to read-only registers This commit makes use of the AHCI_HFLAG_YES_ALPM flag to prevent the driver from writing to the read-only Host Capability register. It also sets the AHCI_HFLAG_NO_WRITE_TO_RO flag to prevent the AHCI library from writing to read-only registers. Signed-off-by: Doug Berger Signed-off-by: Tejun Heo --- drivers/ata/ahci_brcm.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c index 6f8a7341fa08..5936d1679bf3 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -39,7 +39,6 @@ #define PIODATA_ENDIAN_SHIFT 6 #define ENDIAN_SWAP_NONE 0 #define ENDIAN_SWAP_FULL 2 - #define OVERRIDE_HWINIT BIT(16) #define SATA_TOP_CTRL_TP_CTRL 0x8 #define SATA_TOP_CTRL_PHY_CTRL 0xc #define SATA_TOP_CTRL_PHY_CTRL_1 0x0 @@ -126,17 +125,13 @@ static inline void brcm_sata_writereg(u32 val, void __iomem *addr) static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv) { struct brcm_ahci_priv *priv = hpriv->plat_data; - u32 bus_ctrl, port_ctrl, host_caps; + u32 port_ctrl, host_caps; int i; /* Enable support for ALPM */ - bus_ctrl = brcm_sata_readreg(priv->top_ctrl + - SATA_TOP_CTRL_BUS_CTRL); - brcm_sata_writereg(bus_ctrl | OVERRIDE_HWINIT, - priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL); host_caps = readl(hpriv->mmio + HOST_CAP); - writel(host_caps | HOST_CAP_ALPM, hpriv->mmio); - brcm_sata_writereg(bus_ctrl, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL); + if (!(host_caps & HOST_CAP_ALPM)) + hpriv->flags |= AHCI_HFLAG_YES_ALPM; /* * Adjust timeout to allow PLL sufficient time to lock while waking @@ -360,6 +355,7 @@ static int brcm_ahci_probe(struct platform_device *pdev) if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ) hpriv->flags |= AHCI_HFLAG_NO_NCQ; + hpriv->flags |= AHCI_HFLAG_NO_WRITE_TO_RO; ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info, &ahci_platform_sht); -- cgit v1.2.3 From 98633258935bd793793c5d53da889cf0b050b9e4 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 25 Jun 2017 22:25:36 +0200 Subject: sata_via: Enable optional hotplug on VT6420 VT6420 seems to have the same hotplug capability as VT6421. However, enabling hotplug needs to expose SCR registers which can cause problems. It works for me but might break elsewhere. So add a module parameter vt6420_hotplug to enable this feature. Signed-off-by: Ondrej Zary Signed-off-by: Tejun Heo --- drivers/ata/sata_via.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index a3f6d330d106..93b8d783936a 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -80,6 +80,10 @@ struct svia_priv { bool wd_workaround; }; +static int vt6420_hotplug; +module_param_named(vt6420_hotplug, vt6420_hotplug, int, 0644); +MODULE_PARM_DESC(vt6420_hotplug, "Enable hot-plug support for VT6420 (0=Don't support, 1=support)"); + static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); #ifdef CONFIG_PM_SLEEP static int svia_pci_device_resume(struct pci_dev *pdev); @@ -473,6 +477,11 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) struct ata_host *host; int rc; + if (vt6420_hotplug) { + ppi[0]->port_ops->scr_read = svia_scr_read; + ppi[0]->port_ops->scr_write = svia_scr_write; + } + rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); if (rc) return rc; @@ -556,7 +565,7 @@ static void svia_wd_fix(struct pci_dev *pdev) pci_write_config_byte(pdev, 0x52, tmp8 | BIT(2)); } -static irqreturn_t vt6421_interrupt(int irq, void *dev_instance) +static irqreturn_t vt642x_interrupt(int irq, void *dev_instance) { struct ata_host *host = dev_instance; irqreturn_t rc = ata_bmdma_interrupt(irq, dev_instance); @@ -644,7 +653,7 @@ static void svia_configure(struct pci_dev *pdev, int board_id, pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8); } - if (board_id == vt6421) { + if ((board_id == vt6420 && vt6420_hotplug) || board_id == vt6421) { /* enable IRQ on hotplug */ pci_read_config_byte(pdev, SVIA_MISC_3, &tmp8); if ((tmp8 & SATA_HOTPLUG) != SATA_HOTPLUG) { @@ -744,8 +753,8 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) svia_configure(pdev, board_id, hpriv); pci_set_master(pdev); - if (board_id == vt6421) - return ata_host_activate(host, pdev->irq, vt6421_interrupt, + if ((board_id == vt6420 && vt6420_hotplug) || board_id == vt6421) + return ata_host_activate(host, pdev->irq, vt642x_interrupt, IRQF_SHARED, &svia_sht); else return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, -- cgit v1.2.3 From 0ce968f3825153d570f6d765f2c0c79bcb1f0949 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Tue, 27 Jun 2017 11:53:14 +0800 Subject: ahci: Add Device ID for ASMedia 1061R and 1062R Adding ASMedia 1061R and 1062R platform device IDs for SATA. Signed-off-by: Shawn Lin Signed-off-by: Tejun Heo --- drivers/ata/ahci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/ata') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index fd712e0e9d87..c3e68fbdde3b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -548,6 +548,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ + { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */ + { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */ /* * Samsung SSDs found on some macbooks. NCQ times out if MSI is -- cgit v1.2.3 From b1ffbf854e0887e2b828b9a3343264453662dec6 Mon Sep 17 00:00:00 2001 From: Minwoo Im Date: Sat, 24 Jun 2017 03:41:10 +0900 Subject: libata: Support for an ATA PASS-THROUGH(32) command. SAT-4(SCSI/ATA Translation) supports for an ata pass-thru(32). This patch will allow to translate an ata pass-thru(32) SCSI cmd to an ATA cmd. Signed-off-by: Minwoo Im Reviewed-by: Bart Van Assche Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 2 +- drivers/ata/libata-scsi.c | 72 +++++++++++++++++++++++++++++++++++++++++++---- include/scsi/scsi_proto.h | 1 + 3 files changed, 69 insertions(+), 6 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index a846c29f3248..d1b2c6b5f680 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2661,7 +2661,7 @@ int ata_dev_configure(struct ata_device *dev) ata_dev_config_sense_reporting(dev); ata_dev_config_zac(dev); ata_dev_config_trusted(dev); - dev->cdb_len = 16; + dev->cdb_len = 32; } /* ATAPI-specific feature tests */ diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 4c300749aca5..815c6e240aea 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3126,7 +3126,7 @@ ata_scsi_map_proto(u8 byte1) * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile * @qc: command structure to be initialized * - * Handles either 12 or 16-byte versions of the CDB. + * Handles either 12, 16, or 32-byte versions of the CDB. * * RETURNS: * Zero on success, non-zero on failure. @@ -3138,13 +3138,19 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) struct ata_device *dev = qc->dev; const u8 *cdb = scmd->cmnd; u16 fp; + u16 cdb_offset = 0; - if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) { + /* 7Fh variable length cmd means a ata pass-thru(32) */ + if (cdb[0] == VARIABLE_LENGTH_CMD) + cdb_offset = 9; + + tf->protocol = ata_scsi_map_proto(cdb[1 + cdb_offset]); + if (tf->protocol == ATA_PROT_UNKNOWN) { fp = 1; goto invalid_fld; } - if (ata_is_ncq(tf->protocol) && (cdb[2] & 0x3) == 0) + if (ata_is_ncq(tf->protocol) && (cdb[2 + cdb_offset] & 0x3) == 0) tf->protocol = ATA_PROT_NCQ_NODATA; /* enable LBA */ @@ -3180,7 +3186,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) tf->lbah = cdb[12]; tf->device = cdb[13]; tf->command = cdb[14]; - } else { + } else if (cdb[0] == ATA_12) { /* * 12-byte CDB - incapable of extended commands. */ @@ -3193,6 +3199,30 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) tf->lbah = cdb[7]; tf->device = cdb[8]; tf->command = cdb[9]; + } else { + /* + * 32-byte CDB - may contain extended command fields. + * + * If that is the case, copy the upper byte register values. + */ + if (cdb[10] & 0x01) { + tf->hob_feature = cdb[20]; + tf->hob_nsect = cdb[22]; + tf->hob_lbal = cdb[16]; + tf->hob_lbam = cdb[15]; + tf->hob_lbah = cdb[14]; + tf->flags |= ATA_TFLAG_LBA48; + } else + tf->flags &= ~ATA_TFLAG_LBA48; + + tf->feature = cdb[21]; + tf->nsect = cdb[23]; + tf->lbal = cdb[19]; + tf->lbam = cdb[18]; + tf->lbah = cdb[17]; + tf->device = cdb[24]; + tf->command = cdb[25]; + tf->auxiliary = get_unaligned_be32(&cdb[28]); } /* For NCQ commands copy the tag value */ @@ -4137,6 +4167,35 @@ static unsigned int ata_scsi_security_inout_xlat(struct ata_queued_cmd *qc) return 0; } +/** + * ata_scsi_var_len_cdb_xlat - SATL variable length CDB to Handler + * @qc: Command to be translated + * + * Translate a SCSI variable length CDB to specified commands. + * It checks a service action value in CDB to call corresponding handler. + * + * RETURNS: + * Zero on success, non-zero on failure + * + */ +static unsigned int ata_scsi_var_len_cdb_xlat(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + const u8 *cdb = scmd->cmnd; + const u16 sa = get_unaligned_be16(&cdb[8]); + + /* + * if service action represents a ata pass-thru(32) command, + * then pass it to ata_scsi_pass_thru handler. + */ + if (sa == ATA_32) + return ata_scsi_pass_thru(qc); + +unspprt_sa: + /* unsupported service action */ + return 1; +} + /** * ata_get_xlat_func - check if SCSI to ATA translation is possible * @dev: ATA device @@ -4177,6 +4236,9 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) case ATA_16: return ata_scsi_pass_thru; + case VARIABLE_LENGTH_CMD: + return ata_scsi_var_len_cdb_xlat; + case MODE_SELECT: case MODE_SELECT_10: return ata_scsi_mode_select_xlat; @@ -4461,7 +4523,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) shost->max_id = 16; shost->max_lun = 1; shost->max_channel = 1; - shost->max_cmd_len = 16; + shost->max_cmd_len = 32; /* Schedule policy is determined by ->qc_defer() * callback and it needs to see every deferred qc. diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h index ce78ec8e367d..06076b88d375 100644 --- a/include/scsi/scsi_proto.h +++ b/include/scsi/scsi_proto.h @@ -162,6 +162,7 @@ #define VERIFY_32 0x0a #define WRITE_32 0x0b #define WRITE_SAME_32 0x0d +#define ATA_32 0x1ff0 /* Values for T10/04-262r7 */ #define ATA_16 0x85 /* 16-byte pass-thru */ -- cgit v1.2.3 From c8ccf812c36bfc939063b83614beaa2562828e07 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 28 Jun 2017 14:18:13 -0400 Subject: libata: fix build warning from unused goto label b1ffbf854e08 ("libata: Support for an ATA PASS-THROUGH(32) command.") introduced an unused goto label. Remove it. Reported-by: Stephen Rothwell Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 815c6e240aea..9d1b66b4ce7b 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -4191,7 +4191,6 @@ static unsigned int ata_scsi_var_len_cdb_xlat(struct ata_queued_cmd *qc) if (sa == ATA_32) return ata_scsi_pass_thru(qc); -unspprt_sa: /* unsupported service action */ return 1; } -- cgit v1.2.3 From d80210f25ff0050245556bb8ce84d280d8fa4ca7 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 19 Jun 2017 14:26:46 +0200 Subject: sd: add support for TCG OPAL self encrypting disks Just wire up the generic TCG OPAL infrastructure to the SCSI disk driver and the Security In/Out commands. Note that I don't know of any actual SCSI disks that do support TCG OPAL, but this is required to support ATA disks through libata. Signed-off-by: Christoph Hellwig Acked-by: Martin K. Petersen Signed-off-by: Tejun Heo --- drivers/ata/libata-scsi.c | 3 +++ drivers/scsi/sd.c | 53 +++++++++++++++++++++++++++++++++++++++++++++- drivers/scsi/sd.h | 2 ++ include/scsi/scsi_device.h | 1 + 4 files changed, 58 insertions(+), 1 deletion(-) (limited to 'drivers/ata') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 9d1b66b4ce7b..d462c5a3a7ef 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1321,6 +1321,9 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, blk_queue_flush_queueable(q, false); + if (dev->flags & ATA_DFLAG_TRUSTED) + sdev->security_supported = 1; + dev->sdev = sdev; return 0; } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index f9d1432d7cc5..5d32fd7d3a3e 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -643,6 +644,26 @@ static void scsi_disk_put(struct scsi_disk *sdkp) mutex_unlock(&sd_ref_mutex); } +#ifdef CONFIG_BLK_SED_OPAL +static int sd_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, + size_t len, bool send) +{ + struct scsi_device *sdev = data; + u8 cdb[12] = { 0, }; + int ret; + + cdb[0] = send ? SECURITY_PROTOCOL_OUT : SECURITY_PROTOCOL_IN; + cdb[1] = secp; + put_unaligned_be16(spsp, &cdb[2]); + put_unaligned_be32(len, &cdb[6]); + + ret = scsi_execute_req(sdev, cdb, + send ? DMA_TO_DEVICE : DMA_FROM_DEVICE, + buffer, len, NULL, SD_TIMEOUT, SD_MAX_RETRIES, NULL); + return ret <= 0 ? ret : -EIO; +} +#endif /* CONFIG_BLK_SED_OPAL */ + static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd, unsigned int dix, unsigned int dif) { @@ -1439,6 +1460,9 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, if (error) goto out; + if (is_sed_ioctl(cmd)) + return sed_ioctl(sdkp->opal_dev, cmd, p); + /* * Send SCSI addressing ioctls directly to mid level, send other * ioctls to block level and then onto mid level if they can't be @@ -2994,6 +3018,20 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) sdkp->ws10 = 1; } +static void sd_read_security(struct scsi_disk *sdkp, unsigned char *buffer) +{ + struct scsi_device *sdev = sdkp->device; + + if (!sdev->security_supported) + return; + + if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, + SECURITY_PROTOCOL_IN) == 1 && + scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, + SECURITY_PROTOCOL_OUT) == 1) + sdkp->security = 1; +} + /** * sd_revalidate_disk - called the first time a new disk is seen, * performs disk spin up, read_capacity, etc. @@ -3047,6 +3085,7 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_cache_type(sdkp, buffer); sd_read_app_tag_own(sdkp, buffer); sd_read_write_same(sdkp, buffer); + sd_read_security(sdkp, buffer); } sdkp->first_scan = 0; @@ -3207,6 +3246,12 @@ static void sd_probe_async(void *data, async_cookie_t cookie) sd_revalidate_disk(gd); + if (sdkp->security) { + sdkp->opal_dev = init_opal_dev(sdp, &sd_sec_submit); + if (sdkp->opal_dev) + sd_printk(KERN_NOTICE, sdkp, "supports TCG Opal\n"); + } + sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", sdp->removable ? "removable " : ""); scsi_autopm_put_device(sdp); @@ -3356,6 +3401,8 @@ static int sd_remove(struct device *dev) sd_zbc_remove(sdkp); + free_opal_dev(sdkp->opal_dev); + blk_register_region(devt, SD_MINORS, NULL, sd_default_probe, NULL, NULL); @@ -3497,6 +3544,7 @@ static int sd_suspend_runtime(struct device *dev) static int sd_resume(struct device *dev) { struct scsi_disk *sdkp = dev_get_drvdata(dev); + int ret; if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ return 0; @@ -3505,7 +3553,10 @@ static int sd_resume(struct device *dev) return 0; sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); - return sd_start_stop_device(sdkp, 1); + ret = sd_start_stop_device(sdkp, 1); + if (!ret) + opal_unlock_from_suspend(sdkp->opal_dev); + return ret; } /** diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 61d02efd366c..99c4dde9b6bf 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -71,6 +71,7 @@ struct scsi_disk { struct scsi_device *device; struct device dev; struct gendisk *disk; + struct opal_dev *opal_dev; #ifdef CONFIG_BLK_DEV_ZONED unsigned int nr_zones; unsigned int zone_blocks; @@ -114,6 +115,7 @@ struct scsi_disk { unsigned rc_basis: 2; unsigned zoned: 2; unsigned urswrz : 1; + unsigned security : 1; unsigned ignore_medium_access_errors : 1; }; #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev) diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 05641aebd181..310c86a892e9 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -176,6 +176,7 @@ struct scsi_device { unsigned no_read_disc_info:1; /* Avoid READ_DISC_INFO cmds */ unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */ unsigned try_rc_10_first:1; /* Try READ_CAPACACITY_10 first */ + unsigned security_supported:1; /* Supports Security Protocols */ unsigned is_visible:1; /* is the device visible in sysfs */ unsigned wce_default_on:1; /* Cache is ON by default */ unsigned no_dif:1; /* T10 PI (DIF) should be disabled */ -- cgit v1.2.3