diff options
Diffstat (limited to 'drivers/ata')
110 files changed, 16611 insertions, 5285 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 11ec911016c..2664da32d9d 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -2,14 +2,22 @@  # SATA/PATA driver configuration  # +config HAVE_PATA_PLATFORM +	bool +	help +	  This is an internal configuration node for any machine that +	  uses pata-platform driver to enable the relevant driver in the +	  configuration structure without having to submit endless patches +	  to update the PATA_PLATFORM entry. +  menuconfig ATA -	tristate "Serial ATA and Parallel ATA drivers" +	tristate "Serial ATA and Parallel ATA drivers (libata)"  	depends on HAS_IOMEM  	depends on BLOCK -	depends on !(M32R || M68K) || BROKEN +	depends on !(M32R || M68K || S390) || BROKEN  	select SCSI  	---help--- -	  If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or +	  If you want to use an ATA hard disk, ATA tape drive, ATA CD-ROM or  	  any other ATA device under Linux, say Y and make sure that you know  	  the name of your ATA host adapter (the card inside your computer  	  that "speaks" the ATA protocol, also called ATA controller), @@ -50,6 +58,20 @@ config ATA_ACPI  	  You can disable this at kernel boot time by using the  	  option libata.noacpi=1 +config SATA_ZPODD +	bool "SATA Zero Power Optical Disc Drive (ZPODD) support" +	depends on ATA_ACPI && PM_RUNTIME +	default n +	help +	  This option adds support for SATA Zero Power Optical Disc +	  Drive (ZPODD). It requires both the ODD and the platform +	  support, and if enabled, will automatically power on/off the +	  ODD when certain condition is satisfied. This does not impact +	  end user's experience of the ODD, only power is saved when +	  the ODD is not in use (i.e. no disc inside). + +	  If unsure, say N. +  config SATA_PMP  	bool "SATA Port Multiplier support"  	default y @@ -75,6 +97,56 @@ config SATA_AHCI_PLATFORM  	  If unsure, say N. +config AHCI_DA850 +	tristate "DaVinci DA850 AHCI SATA support" +	depends on ARCH_DAVINCI_DA850 +	help +	  This option enables support for the DaVinci DA850 SoC's +	  onboard AHCI SATA. + +	  If unsure, say N. + +config AHCI_ST +	tristate "ST AHCI SATA support" +	depends on ARCH_STI +	help +	  This option enables support for ST AHCI SATA controller. + +	  If unsure, say N. + +config AHCI_IMX +	tristate "Freescale i.MX AHCI SATA support" +	depends on MFD_SYSCON && (ARCH_MXC || COMPILE_TEST) +	help +	  This option enables support for the Freescale i.MX SoC's +	  onboard AHCI SATA. + +	  If unsure, say N. + +config AHCI_MVEBU +	tristate "Marvell EBU AHCI SATA support" +	depends on ARCH_MVEBU +	help +	  This option enables support for the Marvebu EBU SoC's +	  onboard AHCI SATA. + +	  If unsure, say N. + +config AHCI_SUNXI +	tristate "Allwinner sunxi AHCI SATA support" +	depends on ARCH_SUNXI +	help +	  This option enables support for the Allwinner sunxi SoC's +	  onboard AHCI SATA. + +	  If unsure, say N. + +config AHCI_XGENE +	tristate "APM X-Gene 6.0Gbps AHCI SATA host controller support" +	depends on PHY_XGENE +	help +	 This option enables support for APM X-Gene SoC SATA host controller. +  config SATA_FSL  	tristate "Freescale 3.0Gbps SATA support"  	depends on FSL_SOC @@ -85,11 +157,19 @@ config SATA_FSL  	  If unsure, say N.  config SATA_INIC162X -	tristate "Initio 162x SATA support" +	tristate "Initio 162x SATA support (Very Experimental)"  	depends on PCI  	help  	  This option enables support for Initio 162x Serial ATA. +config SATA_ACARD_AHCI +	tristate "ACard AHCI variant (ATP 8620)" +	depends on PCI +	help +	  This option enables support for Acard. + +	  If unsure, say N. +  config SATA_SIL24  	tristate "Silicon Image 3124/3132 SATA support"  	depends on PCI @@ -99,7 +179,7 @@ config SATA_SIL24  	  If unsure, say N.  config ATA_SFF -	bool "ATA SFF support" +	bool "ATA SFF support (for legacy IDE and PATA)"  	default y  	help  	  This option adds support for ATA controllers with SFF @@ -128,19 +208,9 @@ config PDC_ADMA  	  If unsure, say N. -config PATA_MPC52xx -	tristate "Freescale MPC52xx SoC internal IDE" -	depends on PPC_MPC52xx && PPC_BESTCOMM -	select PPC_BESTCOMM_ATA -	help -	  This option enables support for integrated IDE controller -	  of the Freescale MPC52xx SoC. - -	  If unsure, say N. -  config PATA_OCTEON_CF  	tristate "OCTEON Boot Bus Compact Flash support" -	depends on CPU_CAVIUM_OCTEON +	depends on CAVIUM_OCTEON_SOC  	help  	  This option enables a polled compact flash driver for use with  	  compact flash cards attached to the OCTEON boot bus. @@ -157,7 +227,7 @@ config SATA_QSTOR  config SATA_SX4  	tristate "Promise SATA SX4 support (Experimental)" -	depends on PCI && EXPERIMENTAL +	depends on PCI  	help  	  This option enables support for Promise Serial ATA SX4. @@ -196,8 +266,41 @@ config SATA_DWC  	  If unsure, say N. +config SATA_DWC_DEBUG +	bool "Debugging driver version" +	depends on SATA_DWC +	help +	  This option enables debugging output in the driver. + +config SATA_DWC_VDEBUG +	bool "Verbose debug output" +	depends on SATA_DWC_DEBUG +	help +	  This option enables the taskfile dumping and NCQ debugging. + +config SATA_DWC_PMP +	tristate "DesignWare Cores SATA with PMP support" +	depends on 460EX +	help +	  This option enables support for the on-chip SATA controller of the +	  AppliedMicro processor 460EX with PMP support. + +	  If unsure, say N. + +config SATA_HIGHBANK +	tristate "Calxeda Highbank SATA support" +	depends on ARCH_HIGHBANK || COMPILE_TEST +	help +	  This option enables support for the Calxeda Highbank SoC's +	  onboard SATA. + +	  If unsure, say N. +  config SATA_MV  	tristate "Marvell SATA support" +	depends on PCI || ARCH_DOVE || ARCH_KIRKWOOD || ARCH_MV78XX0 || \ +		   ARCH_MVEBU || ARCH_ORION5X || COMPILE_TEST +	select GENERIC_PHY  	help  	  This option enables support for the Marvell Serial ATA family.  	  Currently supports 88SX[56]0[48][01] PCI(-X) chips, @@ -221,6 +324,14 @@ config SATA_PROMISE  	  If unsure, say N. +config SATA_RCAR +	tristate "Renesas R-Car SATA support" +	depends on ARCH_SHMOBILE || COMPILE_TEST +	help +	  This option enables support for Renesas R-Car Serial ATA. + +	  If unsure, say N. +  config SATA_SIL  	tristate "Silicon Image SATA support"  	depends on PCI @@ -293,6 +404,14 @@ config PATA_AMD  	  If unsure, say N. +config PATA_ARASAN_CF +	tristate "ARASAN CompactFlash PATA Controller Support" +	depends on ARCH_SPEAR13XX || COMPILE_TEST +	depends on DMADEVICES +	select DMA_ENGINE +	help +	  Say Y here to support the ARASAN CompactFlash PATA controller +  config PATA_ARTOP  	tristate "ARTOP 6210/6260 PATA support"  	depends on PCI @@ -339,7 +458,7 @@ config PATA_CMD64X  config PATA_CS5520  	tristate "CS5510/5520 PATA support" -	depends on PCI +	depends on PCI && (X86_32 || COMPILE_TEST)  	help  	  This option enables support for the Cyrix 5510/5520  	  companion chip used with the MediaGX/Geode processor family. @@ -348,7 +467,7 @@ config PATA_CS5520  config PATA_CS5530  	tristate "CS5530 PATA support" -	depends on PCI +	depends on PCI && (X86_32 || COMPILE_TEST)  	help  	  This option enables support for the Cyrix/NatSemi/AMD CS5530  	  companion chip used with the MediaGX/Geode processor family. @@ -357,7 +476,7 @@ config PATA_CS5530  config PATA_CS5535  	tristate "CS5535 PATA support (Experimental)" -	depends on PCI && X86 && !X86_64 && EXPERIMENTAL +	depends on PCI && X86_32  	help  	  This option enables support for the NatSemi/AMD CS5535  	  companion chip used with the Geode processor family. @@ -366,7 +485,7 @@ config PATA_CS5535  config PATA_CS5536  	tristate "CS5536 PATA support" -	depends on PCI && X86 && !X86_64 +	depends on PCI && (X86_32 || MIPS || COMPILE_TEST)  	help  	  This option enables support for the AMD CS5536  	  companion chip used with the Geode LX processor family. @@ -375,7 +494,7 @@ config PATA_CS5536  config PATA_CYPRESS  	tristate "Cypress CY82C693 PATA support (Very Experimental)" -	depends on PCI && EXPERIMENTAL +	depends on PCI  	help  	  This option enables support for the Cypress/Contaq CY82C693  	  chipset found in some Alpha systems @@ -391,6 +510,15 @@ config PATA_EFAR  	  If unsure, say N. +config PATA_EP93XX +	tristate "Cirrus Logic EP93xx PATA support" +	depends on ARCH_EP93XX +	help +	  This option enables support for the PATA controller in +	  the Cirrus Logic EP9312 and EP9315 ARM CPU. + +	  If unsure, say N. +  config PATA_HPT366  	tristate "HPT 366/368 PATA support"  	depends on PCI @@ -410,11 +538,11 @@ config PATA_HPT37X  	  If unsure, say N.  config PATA_HPT3X2N -	tristate "HPT 372N/302N PATA support" +	tristate "HPT 371N/372N/302N PATA support"  	depends on PCI  	help  	  This option enables support for the N variant HPT PATA -	  controllers via the new ATA layer +	  controllers via the new ATA layer.  	  If unsure, say N. @@ -443,9 +571,18 @@ config PATA_ICSIDE  	  interface card.  This is not required for ICS partition support.  	  If you are unsure, say N to this. +config PATA_IMX +	tristate "PATA support for Freescale iMX" +	depends on ARCH_MXC +	help +	  This option enables support for the PATA host available on Freescale +          iMX SoCs. + +	  If unsure, say N. +  config PATA_IT8213  	tristate "IT8213 PATA support (Experimental)" -	depends on PCI && EXPERIMENTAL +	depends on PCI  	help  	  This option enables support for the ITE 821 PATA            controllers via the new ATA layer. @@ -491,6 +628,16 @@ config PATA_MARVELL  	  If unsure, say N. +config PATA_MPC52xx +	tristate "Freescale MPC52xx SoC internal IDE" +	depends on PPC_MPC52xx && PPC_BESTCOMM +	select PPC_BESTCOMM_ATA +	help +	  This option enables support for integrated IDE controller +	  of the Freescale MPC52xx SoC. + +	  If unsure, say N. +  config PATA_NETCELL  	tristate "NETCELL Revolution RAID support"  	depends on PCI @@ -528,7 +675,7 @@ config PATA_OLDPIIX  config PATA_OPTIDMA  	tristate "OPTI FireStar PATA support (Very Experimental)" -	depends on PCI && EXPERIMENTAL +	depends on PCI  	help  	  This option enables DMA/PIO support for the later OPTi  	  controllers found on some old motherboards and in some @@ -555,7 +702,7 @@ config PATA_PDC_OLD  config PATA_RADISYS  	tristate "RADISYS 82600 PATA support (Experimental)" -	depends on PCI && EXPERIMENTAL +	depends on PCI  	help  	  This option enables support for the RADISYS 82600  	  PATA controllers via the new ATA layer @@ -574,7 +721,7 @@ config PATA_RDC  config PATA_SC1200  	tristate "SC1200 PATA support" -	depends on PCI +	depends on PCI && (X86_32 || COMPILE_TEST)  	help  	  This option enables support for the NatSemi/AMD SC1200 SoC  	  companion chip used with the Geode processor family. @@ -626,7 +773,7 @@ config PATA_SIS  config PATA_TOSHIBA  	tristate "Toshiba Piccolo support (Experimental)" -	depends on PCI && EXPERIMENTAL +	depends on PCI  	help  	  Support for the Toshiba Piccolo controllers. Currently only the  	  primary channel is supported by this driver. @@ -677,7 +824,7 @@ comment "PIO-only SFF controllers"  config PATA_AT32  	tristate "Atmel AVR32 PATA support (Experimental)" -	depends on AVR32 && PLATFORM_AT32AP && EXPERIMENTAL +	depends on AVR32 && PLATFORM_AT32AP  	help  	  This option enables support for the IDE devices on the  	  Atmel AT32AP platform. @@ -686,7 +833,7 @@ config PATA_AT32  config PATA_AT91  	tristate "PATA support for AT91SAM9260" -	depends on ARM && ARCH_AT91 +	depends on ARM && SOC_AT91SAM9  	help  	  This option enables support for IDE devices on the Atmel AT91SAM9260 SoC. @@ -694,7 +841,7 @@ config PATA_AT91  config PATA_CMD640_PCI  	tristate "CMD640 PCI PATA support (Experimental)" -	depends on PCI && EXPERIMENTAL +	depends on PCI  	help  	  This option enables support for the CMD640 PCI IDE  	  interface chip. Only the primary channel is currently @@ -740,7 +887,7 @@ config PATA_NS87410  config PATA_OPTI  	tristate "OPTI621/6215 PATA support (Very Experimental)" -	depends on PCI && EXPERIMENTAL +	depends on PCI  	help  	  This option enables full PIO support for the early Opti ATA  	  controllers found on some old motherboards. @@ -765,17 +912,9 @@ config PATA_PCMCIA  	  If unsure, say N. -config HAVE_PATA_PLATFORM -	bool -	help -	  This is an internal configuration node for any machine that -	  uses pata-platform driver to enable the relevant driver in the -	  configuration structure without having to submit endless patches -	  to update the PATA_PLATFORM entry. -  config PATA_PLATFORM  	tristate "Generic platform device PATA support" -	depends on EMBEDDED || PPC || HAVE_PATA_PLATFORM +	depends on EXPERT || PPC || HAVE_PATA_PLATFORM  	help  	  This option enables support for generic directly connected ATA  	  devices commonly found on embedded systems. @@ -784,7 +923,7 @@ config PATA_PLATFORM  config PATA_OF_PLATFORM  	tristate "OpenFirmware platform device PATA support" -	depends on PATA_PLATFORM && PPC_OF +	depends on PATA_PLATFORM && OF  	help  	  This option enables support for generic directly connected ATA  	  devices commonly found on embedded systems with OpenFirmware @@ -795,6 +934,7 @@ config PATA_OF_PLATFORM  config PATA_QDI  	tristate "QDI VLB PATA support"  	depends on ISA +	select PATA_LEGACY  	help  	  Support for QDI 6500 and 6580 PATA controllers on VESA local bus. @@ -827,7 +967,7 @@ config PATA_SAMSUNG_CF  config PATA_WINBOND_VLB  	tristate "Winbond W83759A VLB PATA support (Experimental)" -	depends on ISA && EXPERIMENTAL +	depends on ISA  	select PATA_LEGACY  	help  	  Support for the Winbond W83759A controller on Vesa Local Bus @@ -855,7 +995,7 @@ config ATA_GENERIC  config PATA_LEGACY  	tristate "Legacy ISA PATA support (Experimental)" -	depends on (ISA || PCI) && EXPERIMENTAL +	depends on (ISA || PCI)  	help  	  This option enables support for ISA/VLB/PCI bus legacy PATA  	  ports and allows them to be accessed via the new ATA layer. diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index c501af5b12b..7e7a77de757 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -3,15 +3,24 @@ obj-$(CONFIG_ATA)		+= libata.o  # non-SFF interface  obj-$(CONFIG_SATA_AHCI)		+= ahci.o libahci.o -obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o +obj-$(CONFIG_SATA_ACARD_AHCI)	+= acard-ahci.o libahci.o +obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o  obj-$(CONFIG_SATA_FSL)		+= sata_fsl.o  obj-$(CONFIG_SATA_INIC162X)	+= sata_inic162x.o  obj-$(CONFIG_SATA_SIL24)	+= sata_sil24.o  obj-$(CONFIG_SATA_DWC)		+= sata_dwc_460ex.o +obj-$(CONFIG_SATA_DWC_PMP)	+= sata_dwc_pmp.o +obj-$(CONFIG_SATA_HIGHBANK)	+= sata_highbank.o libahci.o +obj-$(CONFIG_AHCI_DA850)	+= ahci_da850.o libahci.o libahci_platform.o +obj-$(CONFIG_AHCI_IMX)		+= ahci_imx.o libahci.o libahci_platform.o +obj-$(CONFIG_AHCI_MVEBU)	+= ahci_mvebu.o libahci.o libahci_platform.o +obj-$(CONFIG_AHCI_SUNXI)	+= ahci_sunxi.o libahci.o libahci_platform.o +obj-$(CONFIG_AHCI_ST)		+= ahci_st.o libahci.o libahci_platform.o +obj-$(CONFIG_AHCI_XGENE)	+= ahci_xgene.o libahci.o libahci_platform.o  # SFF w/ custom DMA  obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o -obj-$(CONFIG_PATA_MPC52xx)	+= pata_mpc52xx.o +obj-$(CONFIG_PATA_ARASAN_CF)	+= pata_arasan_cf.o  obj-$(CONFIG_PATA_OCTEON_CF)	+= pata_octeon_cf.o  obj-$(CONFIG_SATA_QSTOR)	+= sata_qstor.o  obj-$(CONFIG_SATA_SX4)		+= sata_sx4.o @@ -21,6 +30,7 @@ obj-$(CONFIG_ATA_PIIX)		+= ata_piix.o  obj-$(CONFIG_SATA_MV)		+= sata_mv.o  obj-$(CONFIG_SATA_NV)		+= sata_nv.o  obj-$(CONFIG_SATA_PROMISE)	+= sata_promise.o +obj-$(CONFIG_SATA_RCAR)		+= sata_rcar.o  obj-$(CONFIG_SATA_SIL)		+= sata_sil.o  obj-$(CONFIG_SATA_SIS)		+= sata_sis.o  obj-$(CONFIG_SATA_SVW)		+= sata_svw.o @@ -42,16 +52,19 @@ obj-$(CONFIG_PATA_CS5535)	+= pata_cs5535.o  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_HPT366)	+= pata_hpt366.o  obj-$(CONFIG_PATA_HPT37X)	+= pata_hpt37x.o  obj-$(CONFIG_PATA_HPT3X2N)	+= pata_hpt3x2n.o  obj-$(CONFIG_PATA_HPT3X3)	+= pata_hpt3x3.o  obj-$(CONFIG_PATA_ICSIDE)	+= pata_icside.o +obj-$(CONFIG_PATA_IMX)		+= pata_imx.o  obj-$(CONFIG_PATA_IT8213)	+= pata_it8213.o  obj-$(CONFIG_PATA_IT821X)	+= pata_it821x.o  obj-$(CONFIG_PATA_JMICRON)	+= pata_jmicron.o  obj-$(CONFIG_PATA_MACIO)	+= pata_macio.o  obj-$(CONFIG_PATA_MARVELL)	+= pata_marvell.o +obj-$(CONFIG_PATA_MPC52xx)	+= pata_mpc52xx.o  obj-$(CONFIG_PATA_NETCELL)	+= pata_netcell.o  obj-$(CONFIG_PATA_NINJA32)	+= pata_ninja32.o  obj-$(CONFIG_PATA_NS87415)	+= pata_ns87415.o @@ -85,7 +98,6 @@ obj-$(CONFIG_PATA_PCMCIA)	+= pata_pcmcia.o  obj-$(CONFIG_PATA_PALMLD)	+= pata_palmld.o  obj-$(CONFIG_PATA_PLATFORM)	+= pata_platform.o  obj-$(CONFIG_PATA_OF_PLATFORM)	+= pata_of_platform.o -obj-$(CONFIG_PATA_QDI)		+= pata_qdi.o  obj-$(CONFIG_PATA_RB532)	+= pata_rb532_cf.o  obj-$(CONFIG_PATA_RZ1000)	+= pata_rz1000.o  obj-$(CONFIG_PATA_SAMSUNG_CF)	+= pata_samsung_cf.o @@ -103,3 +115,4 @@ libata-y	:= libata-core.o libata-scsi.o libata-eh.o libata-transport.o  libata-$(CONFIG_ATA_SFF)	+= libata-sff.o  libata-$(CONFIG_SATA_PMP)	+= libata-pmp.o  libata-$(CONFIG_ATA_ACPI)	+= libata-acpi.o +libata-$(CONFIG_SATA_ZPODD)	+= libata-zpodd.o diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c new file mode 100644 index 00000000000..0cd7c7a39e5 --- /dev/null +++ b/drivers/ata/acard-ahci.c @@ -0,0 +1,511 @@ + +/* + *  acard-ahci.c - ACard AHCI SATA support + * + *  Maintained by:  Tejun Heo <tj@kernel.org> + *		    Please ALWAYS copy linux-ide@vger.kernel.org + *		    on emails. + * + *  Copyright 2010 Red Hat, Inc. + * + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2, or (at your option) + *  any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; see the file COPYING.  If not, write to + *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * libata documentation is available via 'make {ps|pdf}docs', + * as Documentation/DocBook/libata.* + * + * AHCI hardware documentation: + * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf + * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/blkdev.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/dma-mapping.h> +#include <linux/device.h> +#include <linux/dmi.h> +#include <linux/gfp.h> +#include <scsi/scsi_host.h> +#include <scsi/scsi_cmnd.h> +#include <linux/libata.h> +#include "ahci.h" + +#define DRV_NAME	"acard-ahci" +#define DRV_VERSION	"1.0" + +/* +  Received FIS structure limited to 80h. +*/ + +#define ACARD_AHCI_RX_FIS_SZ 128 + +enum { +	AHCI_PCI_BAR		= 5, +}; + +enum board_ids { +	board_acard_ahci, +}; + +struct acard_sg { +	__le32			addr; +	__le32			addr_hi; +	__le32			reserved; +	__le32			size;	 /* bit 31 (EOT) max==0x10000 (64k) */ +}; + +static void acard_ahci_qc_prep(struct ata_queued_cmd *qc); +static bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc); +static int acard_ahci_port_start(struct ata_port *ap); +static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); + +#ifdef CONFIG_PM_SLEEP +static int acard_ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); +static int acard_ahci_pci_device_resume(struct pci_dev *pdev); +#endif + +static struct scsi_host_template acard_ahci_sht = { +	AHCI_SHT("acard-ahci"), +}; + +static struct ata_port_operations acard_ops = { +	.inherits		= &ahci_ops, +	.qc_prep		= acard_ahci_qc_prep, +	.qc_fill_rtf		= acard_ahci_qc_fill_rtf, +	.port_start             = acard_ahci_port_start, +}; + +#define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags) + +static const struct ata_port_info acard_ahci_port_info[] = { +	[board_acard_ahci] = +	{ +		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ), +		.flags		= AHCI_FLAG_COMMON, +		.pio_mask	= ATA_PIO4, +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &acard_ops, +	}, +}; + +static const struct pci_device_id acard_ahci_pci_tbl[] = { +	/* ACard */ +	{ PCI_VDEVICE(ARTOP, 0x000d), board_acard_ahci }, /* ATP8620 */ + +	{ }    /* terminate list */ +}; + +static struct pci_driver acard_ahci_pci_driver = { +	.name			= DRV_NAME, +	.id_table		= acard_ahci_pci_tbl, +	.probe			= acard_ahci_init_one, +	.remove			= ata_pci_remove_one, +#ifdef CONFIG_PM_SLEEP +	.suspend		= acard_ahci_pci_device_suspend, +	.resume			= acard_ahci_pci_device_resume, +#endif +}; + +#ifdef CONFIG_PM_SLEEP +static int acard_ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ +	struct ata_host *host = pci_get_drvdata(pdev); +	struct ahci_host_priv *hpriv = host->private_data; +	void __iomem *mmio = hpriv->mmio; +	u32 ctl; + +	if (mesg.event & PM_EVENT_SUSPEND && +	    hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { +		dev_err(&pdev->dev, +			"BIOS update required for suspend/resume\n"); +		return -EIO; +	} + +	if (mesg.event & PM_EVENT_SLEEP) { +		/* AHCI spec rev1.1 section 8.3.3: +		 * Software must disable interrupts prior to requesting a +		 * transition of the HBA to D3 state. +		 */ +		ctl = readl(mmio + HOST_CTL); +		ctl &= ~HOST_IRQ_EN; +		writel(ctl, mmio + HOST_CTL); +		readl(mmio + HOST_CTL); /* flush */ +	} + +	return ata_pci_device_suspend(pdev, mesg); +} + +static int acard_ahci_pci_device_resume(struct pci_dev *pdev) +{ +	struct ata_host *host = pci_get_drvdata(pdev); +	int rc; + +	rc = ata_pci_device_do_resume(pdev); +	if (rc) +		return rc; + +	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { +		rc = ahci_reset_controller(host); +		if (rc) +			return rc; + +		ahci_init_controller(host); +	} + +	ata_host_resume(host); + +	return 0; +} +#endif + +static int acard_ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) +{ +	int rc; + +	if (using_dac && +	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { +		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); +		if (rc) { +			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); +			if (rc) { +				dev_err(&pdev->dev, +					   "64-bit DMA enable failed\n"); +				return rc; +			} +		} +	} else { +		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); +		if (rc) { +			dev_err(&pdev->dev, "32-bit DMA enable failed\n"); +			return rc; +		} +		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); +		if (rc) { +			dev_err(&pdev->dev, +				"32-bit consistent DMA enable failed\n"); +			return rc; +		} +	} +	return 0; +} + +static void acard_ahci_pci_print_info(struct ata_host *host) +{ +	struct pci_dev *pdev = to_pci_dev(host->dev); +	u16 cc; +	const char *scc_s; + +	pci_read_config_word(pdev, 0x0a, &cc); +	if (cc == PCI_CLASS_STORAGE_IDE) +		scc_s = "IDE"; +	else if (cc == PCI_CLASS_STORAGE_SATA) +		scc_s = "SATA"; +	else if (cc == PCI_CLASS_STORAGE_RAID) +		scc_s = "RAID"; +	else +		scc_s = "unknown"; + +	ahci_print_info(host, scc_s); +} + +static unsigned int acard_ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl) +{ +	struct scatterlist *sg; +	struct acard_sg *acard_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ; +	unsigned int si, last_si = 0; + +	VPRINTK("ENTER\n"); + +	/* +	 * Next, the S/G list. +	 */ +	for_each_sg(qc->sg, sg, qc->n_elem, si) { +		dma_addr_t addr = sg_dma_address(sg); +		u32 sg_len = sg_dma_len(sg); + +		/* +		 * ACard note: +		 * We must set an end-of-table (EOT) bit, +		 * and the segment cannot exceed 64k (0x10000) +		 */ +		acard_sg[si].addr = cpu_to_le32(addr & 0xffffffff); +		acard_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16); +		acard_sg[si].size = cpu_to_le32(sg_len); +		last_si = si; +	} + +	acard_sg[last_si].size |= cpu_to_le32(1 << 31);	/* set EOT */ + +	return si; +} + +static void acard_ahci_qc_prep(struct ata_queued_cmd *qc) +{ +	struct ata_port *ap = qc->ap; +	struct ahci_port_priv *pp = ap->private_data; +	int is_atapi = ata_is_atapi(qc->tf.protocol); +	void *cmd_tbl; +	u32 opts; +	const u32 cmd_fis_len = 5; /* five dwords */ +	unsigned int n_elem; + +	/* +	 * Fill in command table information.  First, the header, +	 * a SATA Register - Host to Device command FIS. +	 */ +	cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ; + +	ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl); +	if (is_atapi) { +		memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); +		memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len); +	} + +	n_elem = 0; +	if (qc->flags & ATA_QCFLAG_DMAMAP) +		n_elem = acard_ahci_fill_sg(qc, cmd_tbl); + +	/* +	 * Fill in command slot information. +	 * +	 * ACard note: prd table length not filled in +	 */ +	opts = cmd_fis_len | (qc->dev->link->pmp << 12); +	if (qc->tf.flags & ATA_TFLAG_WRITE) +		opts |= AHCI_CMD_WRITE; +	if (is_atapi) +		opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH; + +	ahci_fill_cmd_slot(pp, qc->tag, opts); +} + +static bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc) +{ +	struct ahci_port_priv *pp = qc->ap->private_data; +	u8 *rx_fis = pp->rx_fis; + +	if (pp->fbs_enabled) +		rx_fis += qc->dev->link->pmp * ACARD_AHCI_RX_FIS_SZ; + +	/* +	 * After a successful execution of an ATA PIO data-in command, +	 * the device doesn't send D2H Reg FIS to update the TF and +	 * the host should take TF and E_Status from the preceding PIO +	 * Setup FIS. +	 */ +	if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE && +	    !(qc->flags & ATA_QCFLAG_FAILED)) { +		ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf); +		qc->result_tf.command = (rx_fis + RX_FIS_PIO_SETUP)[15]; +	} else +		ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf); + +	return true; +} + +static int acard_ahci_port_start(struct ata_port *ap) +{ +	struct ahci_host_priv *hpriv = ap->host->private_data; +	struct device *dev = ap->host->dev; +	struct ahci_port_priv *pp; +	void *mem; +	dma_addr_t mem_dma; +	size_t dma_sz, rx_fis_sz; + +	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); +	if (!pp) +		return -ENOMEM; + +	/* check FBS capability */ +	if ((hpriv->cap & HOST_CAP_FBS) && sata_pmp_supported(ap)) { +		void __iomem *port_mmio = ahci_port_base(ap); +		u32 cmd = readl(port_mmio + PORT_CMD); +		if (cmd & PORT_CMD_FBSCP) +			pp->fbs_supported = true; +		else if (hpriv->flags & AHCI_HFLAG_YES_FBS) { +			dev_info(dev, "port %d can do FBS, forcing FBSCP\n", +				 ap->port_no); +			pp->fbs_supported = true; +		} else +			dev_warn(dev, "port %d is not capable of FBS\n", +				 ap->port_no); +	} + +	if (pp->fbs_supported) { +		dma_sz = AHCI_PORT_PRIV_FBS_DMA_SZ; +		rx_fis_sz = ACARD_AHCI_RX_FIS_SZ * 16; +	} else { +		dma_sz = AHCI_PORT_PRIV_DMA_SZ; +		rx_fis_sz = ACARD_AHCI_RX_FIS_SZ; +	} + +	mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL); +	if (!mem) +		return -ENOMEM; +	memset(mem, 0, dma_sz); + +	/* +	 * First item in chunk of DMA memory: 32-slot command table, +	 * 32 bytes each in size +	 */ +	pp->cmd_slot = mem; +	pp->cmd_slot_dma = mem_dma; + +	mem += AHCI_CMD_SLOT_SZ; +	mem_dma += AHCI_CMD_SLOT_SZ; + +	/* +	 * Second item: Received-FIS area +	 */ +	pp->rx_fis = mem; +	pp->rx_fis_dma = mem_dma; + +	mem += rx_fis_sz; +	mem_dma += rx_fis_sz; + +	/* +	 * Third item: data area for storing a single command +	 * and its scatter-gather table +	 */ +	pp->cmd_tbl = mem; +	pp->cmd_tbl_dma = mem_dma; + +	/* +	 * Save off initial list of interrupts to be enabled. +	 * This could be changed later +	 */ +	pp->intr_mask = DEF_PORT_IRQ; + +	ap->private_data = pp; + +	/* engage engines, captain */ +	return ahci_port_resume(ap); +} + +static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ +	unsigned int board_id = ent->driver_data; +	struct ata_port_info pi = acard_ahci_port_info[board_id]; +	const struct ata_port_info *ppi[] = { &pi, NULL }; +	struct device *dev = &pdev->dev; +	struct ahci_host_priv *hpriv; +	struct ata_host *host; +	int n_ports, i, rc; + +	VPRINTK("ENTER\n"); + +	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); + +	ata_print_version_once(&pdev->dev, DRV_VERSION); + +	/* acquire resources */ +	rc = pcim_enable_device(pdev); +	if (rc) +		return rc; + +	/* AHCI controllers often implement SFF compatible interface. +	 * Grab all PCI BARs just in case. +	 */ +	rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME); +	if (rc == -EBUSY) +		pcim_pin_device(pdev); +	if (rc) +		return rc; + +	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); +	if (!hpriv) +		return -ENOMEM; +	hpriv->flags |= (unsigned long)pi.private_data; + +	if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) +		pci_enable_msi(pdev); + +	hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; + +	/* save initial config */ +	ahci_save_initial_config(&pdev->dev, hpriv, 0, 0); + +	/* prepare host */ +	if (hpriv->cap & HOST_CAP_NCQ) +		pi.flags |= ATA_FLAG_NCQ; + +	if (hpriv->cap & HOST_CAP_PMP) +		pi.flags |= ATA_FLAG_PMP; + +	ahci_set_em_messages(hpriv, &pi); + +	/* CAP.NP sometimes indicate the index of the last enabled +	 * port, at other times, that of the last possible port, so +	 * determining the maximum port number requires looking at +	 * both CAP.NP and port_map. +	 */ +	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); + +	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); +	if (!host) +		return -ENOMEM; +	host->private_data = hpriv; + +	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) +		host->flags |= ATA_HOST_PARALLEL_SCAN; +	else +		printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n"); + +	for (i = 0; i < host->n_ports; i++) { +		struct ata_port *ap = host->ports[i]; + +		ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar"); +		ata_port_pbar_desc(ap, AHCI_PCI_BAR, +				   0x100 + ap->port_no * 0x80, "port"); + +		/* set initial link pm policy */ +		/* +		ap->pm_policy = NOT_AVAILABLE; +		*/ +		/* disabled/not-implemented port */ +		if (!(hpriv->port_map & (1 << i))) +			ap->ops = &ata_dummy_port_ops; +	} + +	/* initialize adapter */ +	rc = acard_ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); +	if (rc) +		return rc; + +	rc = ahci_reset_controller(host); +	if (rc) +		return rc; + +	ahci_init_controller(host); +	acard_ahci_pci_print_info(host); + +	pci_set_master(pdev); +	return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, +				 &acard_ahci_sht); +} + +module_pci_driver(acard_ahci_pci_driver); + +MODULE_AUTHOR("Jeff Garzik"); +MODULE_DESCRIPTION("ACard AHCI SATA low-level driver"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, acard_ahci_pci_tbl); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 328826381a2..4cd52a4541a 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1,7 +1,7 @@  /*   *  ahci.c - AHCI SATA support   * - *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> + *  Maintained by:  Tejun Heo <tj@kernel.org>   *    		    Please ALWAYS copy linux-ide@vger.kernel.org   *		    on emails.   * @@ -35,7 +35,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -52,13 +51,16 @@  #define DRV_VERSION	"3.0"  enum { -	AHCI_PCI_BAR		= 5, +	AHCI_PCI_BAR_STA2X11	= 0, +	AHCI_PCI_BAR_ENMOTUS	= 2, +	AHCI_PCI_BAR_STANDARD	= 5,  };  enum board_ids {  	/* board IDs by feature in alphabetical order */  	board_ahci,  	board_ahci_ign_iferr, +	board_ahci_noncq,  	board_ahci_nosntf,  	board_ahci_yes_fbs, @@ -79,10 +81,10 @@ enum board_ids {  };  static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, -			  unsigned long deadline);  static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,  				 unsigned long deadline); +static void ahci_mcp89_apple_enable(struct pci_dev *pdev); +static bool is_mcp89_apple(struct pci_dev *pdev);  static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,  				unsigned long deadline);  #ifdef CONFIG_PM @@ -104,41 +106,36 @@ static struct ata_port_operations ahci_p5wdh_ops = {  	.hardreset		= ahci_p5wdh_hardreset,  }; -static struct ata_port_operations ahci_sb600_ops = { -	.inherits		= &ahci_ops, -	.softreset		= ahci_sb600_softreset, -	.pmp_softreset		= ahci_sb600_softreset, -}; - -#define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags) -  static const struct ata_port_info ahci_port_info[] = {  	/* by features */ -	[board_ahci] = -	{ +	[board_ahci] = {  		.flags		= AHCI_FLAG_COMMON,  		.pio_mask	= ATA_PIO4,  		.udma_mask	= ATA_UDMA6,  		.port_ops	= &ahci_ops,  	}, -	[board_ahci_ign_iferr] = -	{ +	[board_ahci_ign_iferr] = {  		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),  		.flags		= AHCI_FLAG_COMMON,  		.pio_mask	= ATA_PIO4,  		.udma_mask	= ATA_UDMA6,  		.port_ops	= &ahci_ops,  	}, -	[board_ahci_nosntf] = -	{ +	[board_ahci_noncq] = { +		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ), +		.flags		= AHCI_FLAG_COMMON, +		.pio_mask	= ATA_PIO4, +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &ahci_ops, +	}, +	[board_ahci_nosntf] = {  		AHCI_HFLAGS	(AHCI_HFLAG_NO_SNTF),  		.flags		= AHCI_FLAG_COMMON,  		.pio_mask	= ATA_PIO4,  		.udma_mask	= ATA_UDMA6,  		.port_ops	= &ahci_ops,  	}, -	[board_ahci_yes_fbs] = -	{ +	[board_ahci_yes_fbs] = {  		AHCI_HFLAGS	(AHCI_HFLAG_YES_FBS),  		.flags		= AHCI_FLAG_COMMON,  		.pio_mask	= ATA_PIO4, @@ -146,61 +143,53 @@ static const struct ata_port_info ahci_port_info[] = {  		.port_ops	= &ahci_ops,  	},  	/* by chipsets */ -	[board_ahci_mcp65] = -	{ +	[board_ahci_mcp65] = {  		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |  				 AHCI_HFLAG_YES_NCQ), -		.flags		= AHCI_FLAG_COMMON, +		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,  		.pio_mask	= ATA_PIO4,  		.udma_mask	= ATA_UDMA6,  		.port_ops	= &ahci_ops,  	}, -	[board_ahci_mcp77] = -	{ +	[board_ahci_mcp77] = {  		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP),  		.flags		= AHCI_FLAG_COMMON,  		.pio_mask	= ATA_PIO4,  		.udma_mask	= ATA_UDMA6,  		.port_ops	= &ahci_ops,  	}, -	[board_ahci_mcp89] = -	{ +	[board_ahci_mcp89] = {  		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA),  		.flags		= AHCI_FLAG_COMMON,  		.pio_mask	= ATA_PIO4,  		.udma_mask	= ATA_UDMA6,  		.port_ops	= &ahci_ops,  	}, -	[board_ahci_mv] = -	{ +	[board_ahci_mv] = {  		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |  				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, +		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,  		.pio_mask	= ATA_PIO4,  		.udma_mask	= ATA_UDMA6,  		.port_ops	= &ahci_ops,  	}, -	[board_ahci_sb600] = -	{ +	[board_ahci_sb600] = {  		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |  				 AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 |  				 AHCI_HFLAG_32BIT_ONLY),  		.flags		= AHCI_FLAG_COMMON,  		.pio_mask	= ATA_PIO4,  		.udma_mask	= ATA_UDMA6, -		.port_ops	= &ahci_sb600_ops, +		.port_ops	= &ahci_pmp_retry_srst_ops,  	}, -	[board_ahci_sb700] =	/* for SB700 and SB800 */ -	{ +	[board_ahci_sb700] = {	/* for SB700 and SB800 */  		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL),  		.flags		= AHCI_FLAG_COMMON,  		.pio_mask	= ATA_PIO4,  		.udma_mask	= ATA_UDMA6, -		.port_ops	= &ahci_sb600_ops, +		.port_ops	= &ahci_pmp_retry_srst_ops,  	}, -	[board_ahci_vt8251] = -	{ +	[board_ahci_vt8251] = {  		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),  		.flags		= AHCI_FLAG_COMMON,  		.pio_mask	= ATA_PIO4, @@ -260,10 +249,69 @@ static const struct pci_device_id ahci_pci_tbl[] = {  	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */  	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */  	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ +	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ +	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ +	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */ +	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */ +	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */ +	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */ +	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */ +	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */ +	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */ +	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */ +	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */ +	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */ +	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */ +	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */ +	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */ +	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ +	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */ +	{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */ +	{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */ +	{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */ +	{ PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */ +	{ PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */ +	{ PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */ +	{ PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */ +	{ PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ +	{ PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ +	{ PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */ +	{ PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */ +	{ PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */ +	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ +	{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ +	{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ +	{ PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ +	{ PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ +	{ PCI_VDEVICE(INTEL, 0x8d0e), board_ahci }, /* Wellsburg RAID */ +	{ PCI_VDEVICE(INTEL, 0x8d62), board_ahci }, /* Wellsburg AHCI */ +	{ PCI_VDEVICE(INTEL, 0x8d64), board_ahci }, /* Wellsburg RAID */ +	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */ +	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */ +	{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */ +	{ PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */ +	{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */ +	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */ +	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */  	/* JMicron 360/1/3/5/6, match class to avoid IDE function */  	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,  	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr }, +	/* JMicron 362B and 362C have an AHCI function with IDE class code */ +	{ PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr }, +	{ PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },  	/* ATI */  	{ PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ @@ -276,6 +324,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {  	/* AMD */  	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ +	{ PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */  	/* AMD is using RAID class only for ahci controllers */  	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,  	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, @@ -375,14 +424,54 @@ static const struct pci_device_id ahci_pci_tbl[] = {  	{ PCI_VDEVICE(SI, 0x1185), board_ahci },		/* SiS 968 */  	{ PCI_VDEVICE(SI, 0x0186), board_ahci },		/* SiS 968 */ +	/* ST Microelectronics */ +	{ PCI_VDEVICE(STMICRO, 0xCC06), board_ahci },		/* ST ConneXt */ +  	/* Marvell */  	{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv },	/* 6145 */  	{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv },	/* 6121 */ -	{ PCI_DEVICE(0x1b4b, 0x9123), +	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), +	  .class = PCI_CLASS_STORAGE_SATA_AHCI, +	  .class_mask = 0xffffff,  	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */ +	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), +	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */ +	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178, +			 PCI_VENDOR_ID_MARVELL_EXT, 0x9170), +	  .driver_data = board_ahci_yes_fbs },			/* 88se9170 */ +	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), +	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */ +	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), +	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 */ +	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), +	  .driver_data = board_ahci_yes_fbs },			/* 88se9172 on some Gigabyte */ +	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0), +	  .driver_data = board_ahci_yes_fbs }, +	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), +	  .driver_data = board_ahci_yes_fbs }, +	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), +	  .driver_data = board_ahci_yes_fbs }, +	{ PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), +	  .driver_data = board_ahci_yes_fbs },  	/* Promise */  	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */ +	{ PCI_VDEVICE(PROMISE, 0x3781), board_ahci },   /* FastTrak TX8660 ahci-mode */ + +	/* Asmedia */ +	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },	/* ASM1060 */ +	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },	/* ASM1060 */ +	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */ +	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */ + +	/* +	 * Samsung SSDs found on some macbooks.  NCQ times out. +	 * https://bugzilla.kernel.org/show_bug.cgi?id=60731 +	 */ +	{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq }, + +	/* Enmotus */ +	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },  	/* Generic, PCI class code for AHCI */  	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -489,59 +578,11 @@ static void ahci_pci_init_controller(struct ata_host *host)  	ahci_init_controller(host);  } -static int ahci_sb600_check_ready(struct ata_link *link) -{ -	void __iomem *port_mmio = ahci_port_base(link->ap); -	u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; -	u32 irq_status = readl(port_mmio + PORT_IRQ_STAT); - -	/* -	 * There is no need to check TFDATA if BAD PMP is found due to HW bug, -	 * which can save timeout delay. -	 */ -	if (irq_status & PORT_IRQ_BAD_PMP) -		return -EIO; - -	return ata_check_ready(status); -} - -static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class, -				unsigned long deadline) -{ -	struct ata_port *ap = link->ap; -	void __iomem *port_mmio = ahci_port_base(ap); -	int pmp = sata_srst_pmp(link); -	int rc; -	u32 irq_sts; - -	DPRINTK("ENTER\n"); - -	rc = ahci_do_softreset(link, class, pmp, deadline, -			       ahci_sb600_check_ready); - -	/* -	 * Soft reset fails on some ATI chips with IPMS set when PMP -	 * is enabled but SATA HDD/ODD is connected to SATA port, -	 * do soft reset again to port 0. -	 */ -	if (rc == -EIO) { -		irq_sts = readl(port_mmio + PORT_IRQ_STAT); -		if (irq_sts & PORT_IRQ_BAD_PMP) { -			ata_link_printk(link, KERN_WARNING, -					"applying SB600 PMP SRST workaround " -					"and retrying\n"); -			rc = ahci_do_softreset(link, class, 0, deadline, -					       ahci_check_ready); -		} -	} - -	return rc; -} -  static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,  				 unsigned long deadline)  {  	struct ata_port *ap = link->ap; +	struct ahci_host_priv *hpriv = ap->host->private_data;  	bool online;  	int rc; @@ -552,7 +593,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,  	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),  				 deadline, &online, NULL); -	ahci_start_engine(ap); +	hpriv->start_engine(ap);  	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); @@ -567,6 +608,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,  {  	struct ata_port *ap = link->ap;  	struct ahci_port_priv *pp = ap->private_data; +	struct ahci_host_priv *hpriv = ap->host->private_data;  	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;  	struct ata_taskfile tf;  	bool online; @@ -576,13 +618,13 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,  	/* clear D2H reception area to properly wait for D2H FIS */  	ata_tf_init(link->device, &tf); -	tf.command = 0x80; +	tf.command = ATA_BUSY;  	ata_tf_to_fis(&tf, 0, 0, d2h_fis);  	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),  				 deadline, &online, NULL); -	ahci_start_engine(ap); +	hpriv->start_engine(ap);  	/* The pseudo configuration device on SIMG4726 attached to  	 * ASUS P5W-DH Deluxe doesn't send signature FIS after @@ -609,15 +651,15 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,  #ifdef CONFIG_PM  static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	struct ahci_host_priv *hpriv = host->private_data;  	void __iomem *mmio = hpriv->mmio;  	u32 ctl;  	if (mesg.event & PM_EVENT_SUSPEND &&  	    hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { -		dev_printk(KERN_ERR, &pdev->dev, -			   "BIOS update required for suspend/resume\n"); +		dev_err(&pdev->dev, +			"BIOS update required for suspend/resume\n");  		return -EIO;  	} @@ -637,13 +679,17 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)  static int ahci_pci_device_resume(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev);  	if (rc)  		return rc; +	/* Apple BIOS helpfully mangles the registers on resume */ +	if (is_mcp89_apple(pdev)) +		ahci_mcp89_apple_enable(pdev); +  	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {  		rc = ahci_pci_reset_controller(host);  		if (rc) @@ -662,28 +708,34 @@ static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)  {  	int rc; +	/* +	 * If the device fixup already set the dma_mask to some non-standard +	 * value, don't extend it here. This happens on STA2X11, for example. +	 */ +	if (pdev->dma_mask && pdev->dma_mask < DMA_BIT_MASK(32)) +		return 0; +  	if (using_dac &&  	    !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {  		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));  		if (rc) {  			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));  			if (rc) { -				dev_printk(KERN_ERR, &pdev->dev, -					   "64-bit DMA enable failed\n"); +				dev_err(&pdev->dev, +					"64-bit DMA enable failed\n");  				return rc;  			}  		}  	} else {  		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));  		if (rc) { -			dev_printk(KERN_ERR, &pdev->dev, -				   "32-bit DMA enable failed\n"); +			dev_err(&pdev->dev, "32-bit DMA enable failed\n");  			return rc;  		}  		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));  		if (rc) { -			dev_printk(KERN_ERR, &pdev->dev, -				   "32-bit consistent DMA enable failed\n"); +			dev_err(&pdev->dev, +				"32-bit consistent DMA enable failed\n");  			return rc;  		}  	} @@ -746,14 +798,56 @@ static void ahci_p5wdh_workaround(struct ata_host *host)  	    dmi_check_system(sysids)) {  		struct ata_port *ap = host->ports[1]; -		dev_printk(KERN_INFO, &pdev->dev, "enabling ASUS P5W DH " -			   "Deluxe on-board SIMG4726 workaround\n"); +		dev_info(&pdev->dev, +			 "enabling ASUS P5W DH Deluxe on-board SIMG4726 workaround\n");  		ap->ops = &ahci_p5wdh_ops;  		ap->link.flags |= ATA_LFLAG_NO_SRST | ATA_LFLAG_ASSUME_ATA;  	}  } +/* + * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when + * booting in BIOS compatibility mode.  We restore the registers but not ID. + */ +static void ahci_mcp89_apple_enable(struct pci_dev *pdev) +{ +	u32 val; + +	printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n"); + +	pci_read_config_dword(pdev, 0xf8, &val); +	val |= 1 << 0x1b; +	/* the following changes the device ID, but appears not to affect function */ +	/* val = (val & ~0xf0000000) | 0x80000000; */ +	pci_write_config_dword(pdev, 0xf8, val); + +	pci_read_config_dword(pdev, 0x54c, &val); +	val |= 1 << 0xc; +	pci_write_config_dword(pdev, 0x54c, val); + +	pci_read_config_dword(pdev, 0x4a4, &val); +	val &= 0xff; +	val |= 0x01060100; +	pci_write_config_dword(pdev, 0x4a4, val); + +	pci_read_config_dword(pdev, 0x54c, &val); +	val &= ~(1 << 0xc); +	pci_write_config_dword(pdev, 0x54c, val); + +	pci_read_config_dword(pdev, 0xf8, &val); +	val &= ~(1 << 0x1b); +	pci_write_config_dword(pdev, 0xf8, val); +} + +static bool is_mcp89_apple(struct pci_dev *pdev) +{ +	return pdev->vendor == PCI_VENDOR_ID_NVIDIA && +		pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && +		pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && +		pdev->subsystem_device == 0xcb89; +} +  /* only some SB600 ahci controllers can do 64bit DMA */  static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)  { @@ -798,6 +892,34 @@ static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)  				DMI_MATCH(DMI_BOARD_NAME, "MS-7376"),  			},  		}, +		/* +		 * All BIOS versions for the MSI K9AGM2 (MS-7327) support +		 * 64bit DMA. +		 * +		 * This board also had the typo mentioned above in the +		 * Manufacturer DMI field (fixed in BIOS version 1.5), so +		 * match on DMI_BOARD_VENDOR of "MICRO-STAR INTER" again. +		 */ +		{ +			.ident = "MSI K9AGM2", +			.matches = { +				DMI_MATCH(DMI_BOARD_VENDOR, +					  "MICRO-STAR INTER"), +				DMI_MATCH(DMI_BOARD_NAME, "MS-7327"), +			}, +		}, +		/* +		 * All BIOS versions for the Asus M3A support 64bit DMA. +		 * (all release versions from 0301 to 1206 were tested) +		 */ +		{ +			.ident = "ASUS M3A", +			.matches = { +				DMI_MATCH(DMI_BOARD_VENDOR, +					  "ASUSTeK Computer INC."), +				DMI_MATCH(DMI_BOARD_NAME, "M3A"), +			}, +		},  		{ }  	};  	const struct dmi_system_id *match; @@ -818,14 +940,14 @@ static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)  	if (strcmp(buf, match->driver_data) >= 0)  		goto enable_64bit;  	else { -		dev_printk(KERN_WARNING, &pdev->dev, "%s: BIOS too old, " -			   "forcing 32bit DMA, update BIOS\n", match->ident); +		dev_warn(&pdev->dev, +			 "%s: BIOS too old, forcing 32bit DMA, update BIOS\n", +			 match->ident);  		return false;  	}  enable_64bit: -	dev_printk(KERN_WARNING, &pdev->dev, "%s: enabling 64bit DMA\n", -		   match->ident); +	dev_warn(&pdev->dev, "%s: enabling 64bit DMA\n", match->ident);  	return true;  } @@ -919,7 +1041,7 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)  		/*  		 * Acer eMachines G725 has the same problem.  BIOS  		 * V1.03 is known to be broken.  V3.04 is known to -		 * work.  Inbetween, there are V1.06, V2.06 and V3.03 +		 * work.  Between, there are V1.06, V2.06 and V3.03  		 * that we don't have much idea about.  For now,  		 * blacklist anything older than V3.04.  		 * @@ -998,6 +1120,17 @@ static bool ahci_broken_online(struct pci_dev *pdev)  	return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);  } +static bool ahci_broken_devslp(struct pci_dev *pdev) +{ +	/* device with broken DEVSLP but still showing SDS capability */ +	static const struct pci_device_id ids[] = { +		{ PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ +		{} +	}; + +	return pci_match_id(ids, pdev); +} +  #ifdef CONFIG_ATA_ACPI  static void ahci_gtf_filter_workaround(struct ata_host *host)  { @@ -1028,9 +1161,8 @@ static void ahci_gtf_filter_workaround(struct ata_host *host)  		return;  	filter = (unsigned long)dmi->driver_data; -	dev_printk(KERN_INFO, host->dev, -		   "applying extra ACPI _GTF filter 0x%x for %s\n", -		   filter, dmi->ident); +	dev_info(host->dev, "applying extra ACPI _GTF filter 0x%x for %s\n", +		 filter, dmi->ident);  	for (i = 0; i < host->n_ports; i++) {  		struct ata_port *ap = host->ports[i]; @@ -1047,23 +1179,132 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)  {}  #endif +static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports, +				struct ahci_host_priv *hpriv) +{ +	int rc, nvec; + +	if (hpriv->flags & AHCI_HFLAG_NO_MSI) +		goto intx; + +	nvec = pci_msi_vec_count(pdev); +	if (nvec < 0) +		goto intx; + +	/* +	 * If number of MSIs is less than number of ports then Sharing Last +	 * Message mode could be enforced. In this case assume that advantage +	 * of multipe MSIs is negated and use single MSI mode instead. +	 */ +	if (nvec < n_ports) +		goto single_msi; + +	rc = pci_enable_msi_exact(pdev, nvec); +	if (rc == -ENOSPC) +		goto single_msi; +	else if (rc < 0) +		goto intx; + +	/* fallback to single MSI mode if the controller enforced MRSM mode */ +	if (readl(hpriv->mmio + HOST_CTL) & HOST_MRSM) { +		pci_disable_msi(pdev); +		printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n"); +		goto single_msi; +	} + +	return nvec; + +single_msi: +	if (pci_enable_msi(pdev)) +		goto intx; +	return 1; + +intx: +	pci_intx(pdev, 1); +	return 0; +} + +/** + *	ahci_host_activate - start AHCI host, request IRQs and register it + *	@host: target ATA host + *	@irq: base IRQ number to request + *	@n_msis: number of MSIs allocated for this host + *	@irq_handler: irq_handler used when requesting IRQs + *	@irq_flags: irq_flags used when requesting IRQs + * + *	Similar to ata_host_activate, but requests IRQs according to AHCI-1.1 + *	when multiple MSIs were allocated. That is one MSI per port, starting + *	from @irq. + * + *	LOCKING: + *	Inherited from calling layer (may sleep). + * + *	RETURNS: + *	0 on success, -errno otherwise. + */ +int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis) +{ +	int i, rc; + +	/* Sharing Last Message among several ports is not supported */ +	if (n_msis < host->n_ports) +		return -EINVAL; + +	rc = ata_host_start(host); +	if (rc) +		return rc; + +	for (i = 0; i < host->n_ports; i++) { +		struct ahci_port_priv *pp = host->ports[i]->private_data; + +		/* Do not receive interrupts sent by dummy ports */ +		if (!pp) { +			disable_irq(irq + i); +			continue; +		} + +		rc = devm_request_threaded_irq(host->dev, irq + i, +					       ahci_hw_interrupt, +					       ahci_thread_fn, IRQF_SHARED, +					       pp->irq_desc, host->ports[i]); +		if (rc) +			goto out_free_irqs; +	} + +	for (i = 0; i < host->n_ports; i++) +		ata_port_desc(host->ports[i], "irq %d", irq + i); + +	rc = ata_host_register(host, &ahci_sht); +	if (rc) +		goto out_free_all_irqs; + +	return 0; + +out_free_all_irqs: +	i = host->n_ports; +out_free_irqs: +	for (i--; i >= 0; i--) +		devm_free_irq(host->dev, irq + i, host->ports[i]); + +	return rc; +} +  static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	unsigned int board_id = ent->driver_data;  	struct ata_port_info pi = ahci_port_info[board_id];  	const struct ata_port_info *ppi[] = { &pi, NULL };  	struct device *dev = &pdev->dev;  	struct ahci_host_priv *hpriv;  	struct ata_host *host; -	int n_ports, i, rc; +	int n_ports, n_msis, i, rc; +	int ahci_pci_bar = AHCI_PCI_BAR_STANDARD;  	VPRINTK("ENTER\n");  	WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS); -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* The AHCI driver can only drive the SATA ports, the PATA driver  	   can drive them all so if both drivers are selected make sure @@ -1071,38 +1312,29 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)  		return -ENODEV; -	/* -	 * For some reason, MCP89 on MacBook 7,1 doesn't work with -	 * ahci, use ata_generic instead. -	 */ -	if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && -	    pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA && -	    pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE && -	    pdev->subsystem_device == 0xcb89) -		return -ENODEV; +	/* Apple BIOS on MCP89 prevents us using AHCI */ +	if (is_mcp89_apple(pdev)) +		ahci_mcp89_apple_enable(pdev);  	/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.  	 * At the moment, we can only use the AHCI mode. Let the users know  	 * that for SAS drives they're out of luck.  	 */  	if (pdev->vendor == PCI_VENDOR_ID_PROMISE) -		dev_printk(KERN_INFO, &pdev->dev, "PDC42819 " -			   "can only drive SATA devices with this driver\n"); +		dev_info(&pdev->dev, +			 "PDC42819 can only drive SATA devices with this driver\n"); + +	/* Both Connext and Enmotus devices use non-standard BARs */ +	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) +		ahci_pci_bar = AHCI_PCI_BAR_STA2X11; +	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) +		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;  	/* acquire resources */  	rc = pcim_enable_device(pdev);  	if (rc)  		return rc; -	/* AHCI controllers often implement SFF compatible interface. -	 * Grab all PCI BARs just in case. -	 */ -	rc = pcim_iomap_regions_request_all(pdev, 1 << AHCI_PCI_BAR, DRV_NAME); -	if (rc == -EBUSY) -		pcim_pin_device(pdev); -	if (rc) -		return rc; -  	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&  	    (pdev->device == 0x2652 || pdev->device == 0x2653)) {  		u8 map; @@ -1113,12 +1345,21 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  		 */  		pci_read_config_byte(pdev, ICH_MAP, &map);  		if (map & 0x3) { -			dev_printk(KERN_INFO, &pdev->dev, "controller is in " -				   "combined mode, can't enable AHCI mode\n"); +			dev_info(&pdev->dev, +				 "controller is in combined mode, can't enable AHCI mode\n");  			return -ENODEV;  		}  	} +	/* AHCI controllers often implement SFF compatible interface. +	 * Grab all PCI BARs just in case. +	 */ +	rc = pcim_iomap_regions_request_all(pdev, 1 << ahci_pci_bar, DRV_NAME); +	if (rc == -EBUSY) +		pcim_pin_device(pdev); +	if (rc) +		return rc; +  	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);  	if (!hpriv)  		return -ENOMEM; @@ -1137,10 +1378,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (ahci_sb600_enable_64bit(pdev))  		hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; -	if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) -		pci_intx(pdev, 1); +	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; -	hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; +	/* must set flag prior to save config in order to take effect */ +	if (ahci_broken_devslp(pdev)) +		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;  	/* save initial config */  	ahci_pci_save_initial_config(pdev, hpriv); @@ -1156,6 +1398,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  		 */  		if (!(hpriv->flags & AHCI_HFLAG_NO_FPDMA_AA))  			pi.flags |= ATA_FLAG_FPDMA_AA; + +		/* +		 * All AHCI controllers should be forward-compatible +		 * with the new auxiliary field. This code should be +		 * conditionalized if any buggy AHCI controllers are +		 * encountered. +		 */ +		pi.flags |= ATA_FLAG_FPDMA_AUX;  	}  	if (hpriv->cap & HOST_CAP_PMP) @@ -1171,8 +1421,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (ahci_broken_suspend(pdev)) {  		hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; -		dev_printk(KERN_WARNING, &pdev->dev, -			   "BIOS update required for suspend/resume\n"); +		dev_warn(&pdev->dev, +			 "BIOS update required for suspend/resume\n");  	}  	if (ahci_broken_online(pdev)) { @@ -1188,6 +1438,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	 */  	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); +	n_msis = ahci_init_interrupts(pdev, n_ports, hpriv); +	if (n_msis > 1) +		hpriv->flags |= AHCI_HFLAG_MULTI_MSI; +  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);  	if (!host)  		return -ENOMEM; @@ -1196,7 +1450,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)  		host->flags |= ATA_HOST_PARALLEL_SCAN;  	else -		printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n"); +		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");  	if (pi.flags & ATA_FLAG_EM)  		ahci_reset_em(host); @@ -1204,8 +1458,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	for (i = 0; i < host->n_ports; i++) {  		struct ata_port *ap = host->ports[i]; -		ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar"); -		ata_port_pbar_desc(ap, AHCI_PCI_BAR, +		ata_port_pbar_desc(ap, ahci_pci_bar, -1, "abar"); +		ata_port_pbar_desc(ap, ahci_pci_bar,  				   0x100 + ap->port_no * 0x80, "port");  		/* set enclosure management message type */ @@ -1237,26 +1491,18 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	ahci_pci_print_info(host);  	pci_set_master(pdev); -	return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, -				 &ahci_sht); -} -static int __init ahci_init(void) -{ -	return pci_register_driver(&ahci_pci_driver); -} +	if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) +		return ahci_host_activate(host, pdev->irq, n_msis); -static void __exit ahci_exit(void) -{ -	pci_unregister_driver(&ahci_pci_driver); +	return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, +				 &ahci_sht);  } +module_pci_driver(ahci_pci_driver);  MODULE_AUTHOR("Jeff Garzik");  MODULE_DESCRIPTION("AHCI SATA low-level driver");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, ahci_pci_tbl);  MODULE_VERSION(DRV_VERSION); - -module_init(ahci_init); -module_exit(ahci_exit); diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 329cbbb9128..5513296e5e2 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -1,7 +1,7 @@  /*   *  ahci.h - Common AHCI SATA definitions and declarations   * - *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> + *  Maintained by:  Tejun Heo <tj@kernel.org>   *    		    Please ALWAYS copy linux-ide@vger.kernel.org   *		    on emails.   * @@ -35,7 +35,10 @@  #ifndef _AHCI_H  #define _AHCI_H +#include <linux/clk.h>  #include <linux/libata.h> +#include <linux/phy/phy.h> +#include <linux/regulator/consumer.h>  /* Enclosure Management Control */  #define EM_CTRL_MSG_TYPE              0x000f0000 @@ -50,6 +53,7 @@  enum {  	AHCI_MAX_PORTS		= 32, +	AHCI_MAX_CLKS		= 3,  	AHCI_MAX_SG		= 168, /* hardware max is 64K */  	AHCI_DMA_BOUNDARY	= 0xffffffff,  	AHCI_MAX_CMDS		= 32, @@ -90,6 +94,7 @@ enum {  	/* HOST_CTL bits */  	HOST_RESET		= (1 << 0),  /* reset controller; self-clear */  	HOST_IRQ_EN		= (1 << 1),  /* global IRQ enable */ +	HOST_MRSM		= (1 << 2),  /* MSI Revert to Single Message */  	HOST_AHCI_EN		= (1 << 31), /* AHCI enabled */  	/* HOST_CAP bits */ @@ -115,6 +120,9 @@ enum {  	HOST_CAP2_BOH		= (1 << 0),  /* BIOS/OS handoff supported */  	HOST_CAP2_NVMHCI	= (1 << 1),  /* NVMHCI supported */  	HOST_CAP2_APST		= (1 << 2),  /* Automatic partial to slumber */ +	HOST_CAP2_SDS		= (1 << 3),  /* Support device sleep */ +	HOST_CAP2_SADM		= (1 << 4),  /* Support aggressive DevSlp */ +	HOST_CAP2_DESO		= (1 << 5),  /* DevSlp from slumber only */  	/* registers for each SATA port */  	PORT_LST_ADDR		= 0x00, /* command list DMA addr */ @@ -133,6 +141,7 @@ enum {  	PORT_SCR_ACT		= 0x34, /* SATA phy register: SActive */  	PORT_SCR_NTF		= 0x3c, /* SATA phy register: SNotification */  	PORT_FBS		= 0x40, /* FIS-based Switching */ +	PORT_DEVSLP		= 0x44, /* device sleep */  	/* PORT_IRQ_{STAT,MASK} bits */  	PORT_IRQ_COLD_PRES	= (1 << 31), /* cold presence detect */ @@ -186,6 +195,7 @@ enum {  	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */  	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */ +	/* PORT_FBS bits */  	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */  	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */  	PORT_FBS_DEV_OFFSET	= 8,  /* FBS device to issue offset */ @@ -194,7 +204,19 @@ enum {  	PORT_FBS_DEC		= (1 << 1), /* FBS device error clear */  	PORT_FBS_EN		= (1 << 0), /* Enable FBS */ +	/* PORT_DEVSLP bits */ +	PORT_DEVSLP_DM_OFFSET	= 25,             /* DITO multiplier offset */ +	PORT_DEVSLP_DM_MASK	= (0xf << 25),    /* DITO multiplier mask */ +	PORT_DEVSLP_DITO_OFFSET	= 15,             /* DITO offset */ +	PORT_DEVSLP_MDAT_OFFSET	= 10,             /* Minimum assertion time */ +	PORT_DEVSLP_DETO_OFFSET	= 2,              /* DevSlp exit timeout */ +	PORT_DEVSLP_DSP		= (1 << 1),       /* DevSlp present */ +	PORT_DEVSLP_ADSE	= (1 << 0),       /* Aggressive DevSlp enable */ +  	/* hpriv->flags bits */ + +#define AHCI_HFLAGS(flags)		.private_data	= (void *)(flags) +  	AHCI_HFLAG_NO_NCQ		= (1 << 0),  	AHCI_HFLAG_IGN_IRQ_IF_ERR	= (1 << 1), /* ignore IRQ_IF_ERR */  	AHCI_HFLAG_IGN_SERR_INTERNAL	= (1 << 2), /* ignore SERR_INTERNAL */ @@ -210,13 +232,17 @@ enum {  	AHCI_HFLAG_NO_SNTF		= (1 << 12), /* no sntf */  	AHCI_HFLAG_NO_FPDMA_AA		= (1 << 13), /* no FPDMA AA */  	AHCI_HFLAG_YES_FBS		= (1 << 14), /* force FBS cap on */ +	AHCI_HFLAG_DELAY_ENGINE		= (1 << 15), /* do not start engine on +						        port start (wait until +						        error-handling stage) */ +	AHCI_HFLAG_MULTI_MSI		= (1 << 16), /* multiple PCI MSIs */ +	AHCI_HFLAG_NO_DEVSLP		= (1 << 17), /* no device sleep */ +	AHCI_HFLAG_NO_FBS		= (1 << 18), /* no FBS */  	/* ap->flags bits */ -	AHCI_FLAG_COMMON		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -					  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | -					  ATA_FLAG_ACPI_SATA | ATA_FLAG_AN | -					  ATA_FLAG_LPM, +	AHCI_FLAG_COMMON		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | +					  ATA_FLAG_ACPI_SATA | ATA_FLAG_AN,  	ICH_MAP				= 0x90, /* ICH MAP register */ @@ -227,10 +253,14 @@ enum {  	/* em_ctl bits */  	EM_CTL_RST		= (1 << 9), /* Reset */  	EM_CTL_TM		= (1 << 8), /* Transmit Message */ -	EM_CTL_MR		= (1 << 0), /* Message Recieved */ +	EM_CTL_MR		= (1 << 0), /* Message Received */  	EM_CTL_ALHD		= (1 << 26), /* Activity LED */  	EM_CTL_XMT		= (1 << 25), /* Transmit Only */  	EM_CTL_SMB		= (1 << 24), /* Single Message Buffer */ +	EM_CTL_SGPIO		= (1 << 19), /* SGPIO messages supported */ +	EM_CTL_SES		= (1 << 18), /* SES-2 messages supported */ +	EM_CTL_SAFTE		= (1 << 17), /* SAF-TE messages supported */ +	EM_CTL_LED		= (1 << 16), /* LED messages supported */  	/* em message type */  	EM_MSG_TYPE_LED		= (1 << 0), /* LED */ @@ -274,16 +304,19 @@ struct ahci_port_priv {  	unsigned int		ncq_saw_d2h:1;  	unsigned int		ncq_saw_dmas:1;  	unsigned int		ncq_saw_sdb:1; +	u32			intr_status;	/* interrupts to handle */ +	spinlock_t		lock;		/* protects parent ata_port */  	u32 			intr_mask;	/* interrupts to enable */  	bool			fbs_supported;	/* set iff FBS is supported */  	bool			fbs_enabled;	/* set iff FBS is enabled */  	int			fbs_last_dev;	/* save FBS.DEV of last FIS */  	/* enclosure management info per PM slot */  	struct ahci_em_priv	em_priv[EM_MAX_SLOTS]; +	char			*irq_desc;	/* desc in /proc/interrupts */  };  struct ahci_host_priv { -	void __iomem *		mmio;		/* bus-independant mem map */ +	void __iomem *		mmio;		/* bus-independent mem map */  	unsigned int		flags;		/* AHCI_HFLAG_* */  	u32			cap;		/* cap to use */  	u32			cap2;		/* cap2 to use */ @@ -294,6 +327,17 @@ struct ahci_host_priv {  	u32 			em_loc; /* enclosure management location */  	u32			em_buf_sz;	/* EM buffer size in byte */  	u32			em_msg_type;	/* EM message type */ +	bool			got_runtime_pm; /* Did we do pm_runtime_get? */ +	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */ +	struct regulator	*target_pwr;	/* Optional */ +	struct phy		*phy;		/* If platform uses phy */ +	void			*plat_data;	/* Other platform data */ +	/* +	 * Optional ahci_start_engine override, if not set this gets set to the +	 * default ahci_start_engine during ahci_save_initial_config, this can +	 * be overridden anytime before the host is activated. +	 */ +	void			(*start_engine)(struct ata_port *ap);  };  extern int ahci_ignore_sss; @@ -310,7 +354,12 @@ extern struct device_attribute *ahci_sdev_attrs[];  	.sdev_attrs		= ahci_sdev_attrs  extern struct ata_port_operations ahci_ops; +extern struct ata_port_operations ahci_platform_ops; +extern struct ata_port_operations ahci_pmp_retry_srst_ops; +unsigned int ahci_dev_classify(struct ata_port *ap); +void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, +			u32 opts);  void ahci_save_initial_config(struct device *dev,  			      struct ahci_host_priv *hpriv,  			      unsigned int force_port_map, @@ -322,15 +371,22 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,  		      int pmp, unsigned long deadline,  		      int (*check_ready)(struct ata_link *link)); +unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);  int ahci_stop_engine(struct ata_port *ap); +void ahci_start_fis_rx(struct ata_port *ap);  void ahci_start_engine(struct ata_port *ap);  int ahci_check_ready(struct ata_link *link);  int ahci_kick_engine(struct ata_port *ap); +int ahci_port_resume(struct ata_port *ap);  void ahci_set_em_messages(struct ahci_host_priv *hpriv,  			  struct ata_port_info *pi);  int ahci_reset_em(struct ata_host *host);  irqreturn_t ahci_interrupt(int irq, void *dev_instance); +irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance); +irqreturn_t ahci_thread_fn(int irq, void *dev_instance);  void ahci_print_info(struct ata_host *host, const char *scc_s); +int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis); +void ahci_error_handler(struct ata_port *ap);  static inline void __iomem *__ahci_port_base(struct ata_host *host,  					     unsigned int port_no) diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c new file mode 100644 index 00000000000..2b77d53bccf --- /dev/null +++ b/drivers/ata/ahci_da850.c @@ -0,0 +1,115 @@ +/* + * DaVinci DA850 AHCI SATA platform driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pm.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/libata.h> +#include <linux/ahci_platform.h> +#include "ahci.h" + +/* SATA PHY Control Register offset from AHCI base */ +#define SATA_P0PHYCR_REG	0x178 + +#define SATA_PHY_MPY(x)		((x) << 0) +#define SATA_PHY_LOS(x)		((x) << 6) +#define SATA_PHY_RXCDR(x)	((x) << 10) +#define SATA_PHY_RXEQ(x)	((x) << 13) +#define SATA_PHY_TXSWING(x)	((x) << 19) +#define SATA_PHY_ENPLL(x)	((x) << 31) + +/* + * The multiplier needed for 1.5GHz PLL output. + * + * NOTE: This is currently hardcoded to be suitable for 100MHz crystal + * frequency (which is used by DA850 EVM board) and may need to be changed + * if you would like to use this driver on some other board. + */ +#define DA850_SATA_CLK_MULTIPLIER	7 + +static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg, +			    void __iomem *ahci_base) +{ +	unsigned int val; + +	/* Enable SATA clock receiver */ +	val = readl(pwrdn_reg); +	val &= ~BIT(0); +	writel(val, pwrdn_reg); + +	val = SATA_PHY_MPY(DA850_SATA_CLK_MULTIPLIER + 1) | SATA_PHY_LOS(1) | +	      SATA_PHY_RXCDR(4) | SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) | +	      SATA_PHY_ENPLL(1); + +	writel(val, ahci_base + SATA_P0PHYCR_REG); +} + +static const struct ata_port_info ahci_da850_port_info = { +	.flags		= AHCI_FLAG_COMMON, +	.pio_mask	= ATA_PIO4, +	.udma_mask	= ATA_UDMA6, +	.port_ops	= &ahci_platform_ops, +}; + +static int ahci_da850_probe(struct platform_device *pdev) +{ +	struct device *dev = &pdev->dev; +	struct ahci_host_priv *hpriv; +	struct resource *res; +	void __iomem *pwrdn_reg; +	int rc; + +	hpriv = ahci_platform_get_resources(pdev); +	if (IS_ERR(hpriv)) +		return PTR_ERR(hpriv); + +	rc = ahci_platform_enable_resources(hpriv); +	if (rc) +		return rc; + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1); +	if (!res) +		goto disable_resources; + +	pwrdn_reg = devm_ioremap(dev, res->start, resource_size(res)); +	if (!pwrdn_reg) +		goto disable_resources; + +	da850_sata_init(dev, pwrdn_reg, hpriv->mmio); + +	rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info, +				     0, 0, 0); +	if (rc) +		goto disable_resources; + +	return 0; +disable_resources: +	ahci_platform_disable_resources(hpriv); +	return rc; +} + +static SIMPLE_DEV_PM_OPS(ahci_da850_pm_ops, ahci_platform_suspend, +			 ahci_platform_resume); + +static struct platform_driver ahci_da850_driver = { +	.probe = ahci_da850_probe, +	.remove = ata_platform_remove_one, +	.driver = { +		.name = "ahci_da850", +		.owner = THIS_MODULE, +		.pm = &ahci_da850_pm_ops, +	}, +}; +module_platform_driver(ahci_da850_driver); + +MODULE_DESCRIPTION("DaVinci DA850 AHCI SATA platform driver"); +MODULE_AUTHOR("Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c new file mode 100644 index 00000000000..cac4360f272 --- /dev/null +++ b/drivers/ata/ahci_imx.c @@ -0,0 +1,527 @@ +/* + * copyright (c) 2013 Freescale Semiconductor, Inc. + * Freescale IMX AHCI SATA platform driver + * + * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/ahci_platform.h> +#include <linux/of_device.h> +#include <linux/mfd/syscon.h> +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> +#include <linux/libata.h> +#include "ahci.h" + +enum { +	/* Timer 1-ms Register */ +	IMX_TIMER1MS				= 0x00e0, +	/* Port0 PHY Control Register */ +	IMX_P0PHYCR				= 0x0178, +	IMX_P0PHYCR_TEST_PDDQ			= 1 << 20, +	IMX_P0PHYCR_CR_READ			= 1 << 19, +	IMX_P0PHYCR_CR_WRITE			= 1 << 18, +	IMX_P0PHYCR_CR_CAP_DATA			= 1 << 17, +	IMX_P0PHYCR_CR_CAP_ADDR			= 1 << 16, +	/* Port0 PHY Status Register */ +	IMX_P0PHYSR				= 0x017c, +	IMX_P0PHYSR_CR_ACK			= 1 << 18, +	IMX_P0PHYSR_CR_DATA_OUT			= 0xffff << 0, +	/* Lane0 Output Status Register */ +	IMX_LANE0_OUT_STAT			= 0x2003, +	IMX_LANE0_OUT_STAT_RX_PLL_STATE		= 1 << 1, +	/* Clock Reset Register */ +	IMX_CLOCK_RESET				= 0x7f3f, +	IMX_CLOCK_RESET_RESET			= 1 << 0, +}; + +enum ahci_imx_type { +	AHCI_IMX53, +	AHCI_IMX6Q, +}; + +struct imx_ahci_priv { +	struct platform_device *ahci_pdev; +	enum ahci_imx_type type; +	struct clk *sata_clk; +	struct clk *sata_ref_clk; +	struct clk *ahb_clk; +	struct regmap *gpr; +	bool no_device; +	bool first_time; +}; + +static int ahci_imx_hotplug; +module_param_named(hotplug, ahci_imx_hotplug, int, 0644); +MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)"); + +static void ahci_imx_host_stop(struct ata_host *host); + +static int imx_phy_crbit_assert(void __iomem *mmio, u32 bit, bool assert) +{ +	int timeout = 10; +	u32 crval; +	u32 srval; + +	/* Assert or deassert the bit */ +	crval = readl(mmio + IMX_P0PHYCR); +	if (assert) +		crval |= bit; +	else +		crval &= ~bit; +	writel(crval, mmio + IMX_P0PHYCR); + +	/* Wait for the cr_ack signal */ +	do { +		srval = readl(mmio + IMX_P0PHYSR); +		if ((assert ? srval : ~srval) & IMX_P0PHYSR_CR_ACK) +			break; +		usleep_range(100, 200); +	} while (--timeout); + +	return timeout ? 0 : -ETIMEDOUT; +} + +static int imx_phy_reg_addressing(u16 addr, void __iomem *mmio) +{ +	u32 crval = addr; +	int ret; + +	/* Supply the address on cr_data_in */ +	writel(crval, mmio + IMX_P0PHYCR); + +	/* Assert the cr_cap_addr signal */ +	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, true); +	if (ret) +		return ret; + +	/* Deassert cr_cap_addr */ +	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, false); +	if (ret) +		return ret; + +	return 0; +} + +static int imx_phy_reg_write(u16 val, void __iomem *mmio) +{ +	u32 crval = val; +	int ret; + +	/* Supply the data on cr_data_in */ +	writel(crval, mmio + IMX_P0PHYCR); + +	/* Assert the cr_cap_data signal */ +	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, true); +	if (ret) +		return ret; + +	/* Deassert cr_cap_data */ +	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, false); +	if (ret) +		return ret; + +	if (val & IMX_CLOCK_RESET_RESET) { +		/* +		 * In case we're resetting the phy, it's unable to acknowledge, +		 * so we return immediately here. +		 */ +		crval |= IMX_P0PHYCR_CR_WRITE; +		writel(crval, mmio + IMX_P0PHYCR); +		goto out; +	} + +	/* Assert the cr_write signal */ +	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, true); +	if (ret) +		return ret; + +	/* Deassert cr_write */ +	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, false); +	if (ret) +		return ret; + +out: +	return 0; +} + +static int imx_phy_reg_read(u16 *val, void __iomem *mmio) +{ +	int ret; + +	/* Assert the cr_read signal */ +	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, true); +	if (ret) +		return ret; + +	/* Capture the data from cr_data_out[] */ +	*val = readl(mmio + IMX_P0PHYSR) & IMX_P0PHYSR_CR_DATA_OUT; + +	/* Deassert cr_read */ +	ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, false); +	if (ret) +		return ret; + +	return 0; +} + +static int imx_sata_phy_reset(struct ahci_host_priv *hpriv) +{ +	void __iomem *mmio = hpriv->mmio; +	int timeout = 10; +	u16 val; +	int ret; + +	/* Reset SATA PHY by setting RESET bit of PHY register CLOCK_RESET */ +	ret = imx_phy_reg_addressing(IMX_CLOCK_RESET, mmio); +	if (ret) +		return ret; +	ret = imx_phy_reg_write(IMX_CLOCK_RESET_RESET, mmio); +	if (ret) +		return ret; + +	/* Wait for PHY RX_PLL to be stable */ +	do { +		usleep_range(100, 200); +		ret = imx_phy_reg_addressing(IMX_LANE0_OUT_STAT, mmio); +		if (ret) +			return ret; +		ret = imx_phy_reg_read(&val, mmio); +		if (ret) +			return ret; +		if (val & IMX_LANE0_OUT_STAT_RX_PLL_STATE) +			break; +	} while (--timeout); + +	return timeout ? 0 : -ETIMEDOUT; +} + +static int imx_sata_enable(struct ahci_host_priv *hpriv) +{ +	struct imx_ahci_priv *imxpriv = hpriv->plat_data; +	struct device *dev = &imxpriv->ahci_pdev->dev; +	int ret; + +	if (imxpriv->no_device) +		return 0; + +	if (hpriv->target_pwr) { +		ret = regulator_enable(hpriv->target_pwr); +		if (ret) +			return ret; +	} + +	ret = clk_prepare_enable(imxpriv->sata_ref_clk); +	if (ret < 0) +		goto disable_regulator; + +	if (imxpriv->type == AHCI_IMX6Q) { +		/* +		 * set PHY Paremeters, two steps to configure the GPR13, +		 * one write for rest of parameters, mask of first write +		 * is 0x07ffffff, and the other one write for setting +		 * the mpll_clk_en. +		 */ +		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, +				   IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK | +				   IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK | +				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK | +				   IMX6Q_GPR13_SATA_SPD_MODE_MASK | +				   IMX6Q_GPR13_SATA_MPLL_SS_EN | +				   IMX6Q_GPR13_SATA_TX_ATTEN_MASK | +				   IMX6Q_GPR13_SATA_TX_BOOST_MASK | +				   IMX6Q_GPR13_SATA_TX_LVL_MASK | +				   IMX6Q_GPR13_SATA_MPLL_CLK_EN | +				   IMX6Q_GPR13_SATA_TX_EDGE_RATE, +				   IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB | +				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M | +				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | +				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G | +				   IMX6Q_GPR13_SATA_MPLL_SS_EN | +				   IMX6Q_GPR13_SATA_TX_ATTEN_9_16 | +				   IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB | +				   IMX6Q_GPR13_SATA_TX_LVL_1_025_V); +		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, +				   IMX6Q_GPR13_SATA_MPLL_CLK_EN, +				   IMX6Q_GPR13_SATA_MPLL_CLK_EN); + +		usleep_range(100, 200); + +		ret = imx_sata_phy_reset(hpriv); +		if (ret) { +			dev_err(dev, "failed to reset phy: %d\n", ret); +			goto disable_regulator; +		} +	} + +	usleep_range(1000, 2000); + +	return 0; + +disable_regulator: +	if (hpriv->target_pwr) +		regulator_disable(hpriv->target_pwr); + +	return ret; +} + +static void imx_sata_disable(struct ahci_host_priv *hpriv) +{ +	struct imx_ahci_priv *imxpriv = hpriv->plat_data; + +	if (imxpriv->no_device) +		return; + +	if (imxpriv->type == AHCI_IMX6Q) { +		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, +				   IMX6Q_GPR13_SATA_MPLL_CLK_EN, +				   !IMX6Q_GPR13_SATA_MPLL_CLK_EN); +	} + +	clk_disable_unprepare(imxpriv->sata_ref_clk); + +	if (hpriv->target_pwr) +		regulator_disable(hpriv->target_pwr); +} + +static void ahci_imx_error_handler(struct ata_port *ap) +{ +	u32 reg_val; +	struct ata_device *dev; +	struct ata_host *host = dev_get_drvdata(ap->dev); +	struct ahci_host_priv *hpriv = host->private_data; +	void __iomem *mmio = hpriv->mmio; +	struct imx_ahci_priv *imxpriv = hpriv->plat_data; + +	ahci_error_handler(ap); + +	if (!(imxpriv->first_time) || ahci_imx_hotplug) +		return; + +	imxpriv->first_time = false; + +	ata_for_each_dev(dev, &ap->link, ENABLED) +		return; +	/* +	 * Disable link to save power.  An imx ahci port can't be recovered +	 * without full reset once the pddq mode is enabled making it +	 * impossible to use as part of libata LPM. +	 */ +	reg_val = readl(mmio + IMX_P0PHYCR); +	writel(reg_val | IMX_P0PHYCR_TEST_PDDQ, mmio + IMX_P0PHYCR); +	imx_sata_disable(hpriv); +	imxpriv->no_device = true; + +	dev_info(ap->dev, "no device found, disabling link.\n"); +	dev_info(ap->dev, "pass " MODULE_PARAM_PREFIX ".hotplug=1 to enable hotplug\n"); +} + +static int ahci_imx_softreset(struct ata_link *link, unsigned int *class, +		       unsigned long deadline) +{ +	struct ata_port *ap = link->ap; +	struct ata_host *host = dev_get_drvdata(ap->dev); +	struct ahci_host_priv *hpriv = host->private_data; +	struct imx_ahci_priv *imxpriv = hpriv->plat_data; +	int ret = -EIO; + +	if (imxpriv->type == AHCI_IMX53) +		ret = ahci_pmp_retry_srst_ops.softreset(link, class, deadline); +	else if (imxpriv->type == AHCI_IMX6Q) +		ret = ahci_ops.softreset(link, class, deadline); + +	return ret; +} + +static struct ata_port_operations ahci_imx_ops = { +	.inherits	= &ahci_ops, +	.host_stop	= ahci_imx_host_stop, +	.error_handler	= ahci_imx_error_handler, +	.softreset	= ahci_imx_softreset, +}; + +static const struct ata_port_info ahci_imx_port_info = { +	.flags		= AHCI_FLAG_COMMON, +	.pio_mask	= ATA_PIO4, +	.udma_mask	= ATA_UDMA6, +	.port_ops	= &ahci_imx_ops, +}; + +static const struct of_device_id imx_ahci_of_match[] = { +	{ .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 }, +	{ .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q }, +	{}, +}; +MODULE_DEVICE_TABLE(of, imx_ahci_of_match); + +static int imx_ahci_probe(struct platform_device *pdev) +{ +	struct device *dev = &pdev->dev; +	const struct of_device_id *of_id; +	struct ahci_host_priv *hpriv; +	struct imx_ahci_priv *imxpriv; +	unsigned int reg_val; +	int ret; + +	of_id = of_match_device(imx_ahci_of_match, dev); +	if (!of_id) +		return -EINVAL; + +	imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL); +	if (!imxpriv) +		return -ENOMEM; + +	imxpriv->ahci_pdev = pdev; +	imxpriv->no_device = false; +	imxpriv->first_time = true; +	imxpriv->type = (enum ahci_imx_type)of_id->data; + +	imxpriv->sata_clk = devm_clk_get(dev, "sata"); +	if (IS_ERR(imxpriv->sata_clk)) { +		dev_err(dev, "can't get sata clock.\n"); +		return PTR_ERR(imxpriv->sata_clk); +	} + +	imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref"); +	if (IS_ERR(imxpriv->sata_ref_clk)) { +		dev_err(dev, "can't get sata_ref clock.\n"); +		return PTR_ERR(imxpriv->sata_ref_clk); +	} + +	imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); +	if (IS_ERR(imxpriv->ahb_clk)) { +		dev_err(dev, "can't get ahb clock.\n"); +		return PTR_ERR(imxpriv->ahb_clk); +	} + +	if (imxpriv->type == AHCI_IMX6Q) { +		imxpriv->gpr = syscon_regmap_lookup_by_compatible( +							"fsl,imx6q-iomuxc-gpr"); +		if (IS_ERR(imxpriv->gpr)) { +			dev_err(dev, +				"failed to find fsl,imx6q-iomux-gpr regmap\n"); +			return PTR_ERR(imxpriv->gpr); +		} +	} + +	hpriv = ahci_platform_get_resources(pdev); +	if (IS_ERR(hpriv)) +		return PTR_ERR(hpriv); + +	hpriv->plat_data = imxpriv; + +	ret = clk_prepare_enable(imxpriv->sata_clk); +	if (ret) +		return ret; + +	ret = imx_sata_enable(hpriv); +	if (ret) +		goto disable_clk; + +	/* +	 * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, +	 * and IP vendor specific register IMX_TIMER1MS. +	 * Configure CAP_SSS (support stagered spin up). +	 * Implement the port0. +	 * Get the ahb clock rate, and configure the TIMER1MS register. +	 */ +	reg_val = readl(hpriv->mmio + HOST_CAP); +	if (!(reg_val & HOST_CAP_SSS)) { +		reg_val |= HOST_CAP_SSS; +		writel(reg_val, hpriv->mmio + HOST_CAP); +	} +	reg_val = readl(hpriv->mmio + HOST_PORTS_IMPL); +	if (!(reg_val & 0x1)) { +		reg_val |= 0x1; +		writel(reg_val, hpriv->mmio + HOST_PORTS_IMPL); +	} + +	reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; +	writel(reg_val, hpriv->mmio + IMX_TIMER1MS); + +	ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, +				      0, 0, 0); +	if (ret) +		goto disable_sata; + +	return 0; + +disable_sata: +	imx_sata_disable(hpriv); +disable_clk: +	clk_disable_unprepare(imxpriv->sata_clk); +	return ret; +} + +static void ahci_imx_host_stop(struct ata_host *host) +{ +	struct ahci_host_priv *hpriv = host->private_data; +	struct imx_ahci_priv *imxpriv = hpriv->plat_data; + +	imx_sata_disable(hpriv); +	clk_disable_unprepare(imxpriv->sata_clk); +} + +#ifdef CONFIG_PM_SLEEP +static int imx_ahci_suspend(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	struct ahci_host_priv *hpriv = host->private_data; +	int ret; + +	ret = ahci_platform_suspend_host(dev); +	if (ret) +		return ret; + +	imx_sata_disable(hpriv); + +	return 0; +} + +static int imx_ahci_resume(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	struct ahci_host_priv *hpriv = host->private_data; +	int ret; + +	ret = imx_sata_enable(hpriv); +	if (ret) +		return ret; + +	return ahci_platform_resume_host(dev); +} +#endif + +static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume); + +static struct platform_driver imx_ahci_driver = { +	.probe = imx_ahci_probe, +	.remove = ata_platform_remove_one, +	.driver = { +		.name = "ahci-imx", +		.owner = THIS_MODULE, +		.of_match_table = imx_ahci_of_match, +		.pm = &ahci_imx_pm_ops, +	}, +}; +module_platform_driver(imx_ahci_driver); + +MODULE_DESCRIPTION("Freescale i.MX AHCI SATA platform driver"); +MODULE_AUTHOR("Richard Zhu <Hong-Xing.Zhu@freescale.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ahci:imx"); diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c new file mode 100644 index 00000000000..fd3dfd733b8 --- /dev/null +++ b/drivers/ata/ahci_mvebu.c @@ -0,0 +1,128 @@ +/* + * AHCI glue platform driver for Marvell EBU SOCs + * + * Copyright (C) 2014 Marvell + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * Marcin Wojtas <mw@semihalf.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2.  This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/ahci_platform.h> +#include <linux/kernel.h> +#include <linux/mbus.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include "ahci.h" + +#define AHCI_VENDOR_SPECIFIC_0_ADDR  0xa0 +#define AHCI_VENDOR_SPECIFIC_0_DATA  0xa4 + +#define AHCI_WINDOW_CTRL(win)	(0x60 + ((win) << 4)) +#define AHCI_WINDOW_BASE(win)	(0x64 + ((win) << 4)) +#define AHCI_WINDOW_SIZE(win)	(0x68 + ((win) << 4)) + +static void ahci_mvebu_mbus_config(struct ahci_host_priv *hpriv, +				   const struct mbus_dram_target_info *dram) +{ +	int i; + +	for (i = 0; i < 4; i++) { +		writel(0, hpriv->mmio + AHCI_WINDOW_CTRL(i)); +		writel(0, hpriv->mmio + AHCI_WINDOW_BASE(i)); +		writel(0, hpriv->mmio + AHCI_WINDOW_SIZE(i)); +	} + +	for (i = 0; i < dram->num_cs; i++) { +		const struct mbus_dram_window *cs = dram->cs + i; + +		writel((cs->mbus_attr << 8) | +		       (dram->mbus_dram_target_id << 4) | 1, +		       hpriv->mmio + AHCI_WINDOW_CTRL(i)); +		writel(cs->base, hpriv->mmio + AHCI_WINDOW_BASE(i)); +		writel(((cs->size - 1) & 0xffff0000), +		       hpriv->mmio + AHCI_WINDOW_SIZE(i)); +	} +} + +static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv) +{ +	/* +	 * Enable the regret bit to allow the SATA unit to regret a +	 * request that didn't receive an acknowlegde and avoid a +	 * deadlock +	 */ +	writel(0x4, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_ADDR); +	writel(0x80, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA); +} + +static const struct ata_port_info ahci_mvebu_port_info = { +	.flags	   = AHCI_FLAG_COMMON, +	.pio_mask  = ATA_PIO4, +	.udma_mask = ATA_UDMA6, +	.port_ops  = &ahci_platform_ops, +}; + +static int ahci_mvebu_probe(struct platform_device *pdev) +{ +	struct ahci_host_priv *hpriv; +	const struct mbus_dram_target_info *dram; +	int rc; + +	hpriv = ahci_platform_get_resources(pdev); +	if (IS_ERR(hpriv)) +		return PTR_ERR(hpriv); + +	rc = ahci_platform_enable_resources(hpriv); +	if (rc) +		return rc; + +	dram = mv_mbus_dram_info(); +	if (!dram) +		return -ENODEV; + +	ahci_mvebu_mbus_config(hpriv, dram); +	ahci_mvebu_regret_option(hpriv); + +	rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info, +				     0, 0, 0); +	if (rc) +		goto disable_resources; + +	return 0; + +disable_resources: +	ahci_platform_disable_resources(hpriv); +	return rc; +} + +static const struct of_device_id ahci_mvebu_of_match[] = { +	{ .compatible = "marvell,armada-380-ahci", }, +	{ }, +}; +MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match); + +/* + * We currently don't provide power management related operations, + * since there is no suspend/resume support at the platform level for + * Armada 38x for the moment. + */ +static struct platform_driver ahci_mvebu_driver = { +	.probe = ahci_mvebu_probe, +	.remove = ata_platform_remove_one, +	.driver = { +		.name = "ahci-mvebu", +		.owner = THIS_MODULE, +		.of_match_table = ahci_mvebu_of_match, +	}, +}; +module_platform_driver(ahci_mvebu_driver); + +MODULE_DESCRIPTION("Marvell EBU AHCI SATA driver"); +MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>, Marcin Wojtas <mw@semihalf.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ahci_mvebu"); diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 6fef1fa75c5..b10d81ddb52 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -13,67 +13,37 @@   */  #include <linux/kernel.h> -#include <linux/gfp.h>  #include <linux/module.h> -#include <linux/init.h> -#include <linux/interrupt.h> +#include <linux/pm.h>  #include <linux/device.h> +#include <linux/of_device.h>  #include <linux/platform_device.h>  #include <linux/libata.h>  #include <linux/ahci_platform.h>  #include "ahci.h" -static struct scsi_host_template ahci_platform_sht = { -	AHCI_SHT("ahci_platform"), +static const struct ata_port_info ahci_port_info = { +	.flags		= AHCI_FLAG_COMMON, +	.pio_mask	= ATA_PIO4, +	.udma_mask	= ATA_UDMA6, +	.port_ops	= &ahci_platform_ops,  }; -static int __init ahci_probe(struct platform_device *pdev) +static int ahci_probe(struct platform_device *pdev)  {  	struct device *dev = &pdev->dev; -	struct ahci_platform_data *pdata = dev->platform_data; -	struct ata_port_info pi = { -		.flags		= AHCI_FLAG_COMMON, -		.pio_mask	= ATA_PIO4, -		.udma_mask	= ATA_UDMA6, -		.port_ops	= &ahci_ops, -	}; -	const struct ata_port_info *ppi[] = { &pi, NULL }; +	struct ahci_platform_data *pdata = dev_get_platdata(dev);  	struct ahci_host_priv *hpriv; -	struct ata_host *host; -	struct resource *mem; -	int irq; -	int n_ports; -	int i; +	unsigned long hflags = 0;  	int rc; -	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!mem) { -		dev_err(dev, "no mmio space\n"); -		return -EINVAL; -	} - -	irq = platform_get_irq(pdev, 0); -	if (irq <= 0) { -		dev_err(dev, "no irq\n"); -		return -EINVAL; -	} - -	if (pdata && pdata->ata_port_info) -		pi = *pdata->ata_port_info; - -	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); -	if (!hpriv) { -		dev_err(dev, "can't alloc ahci_host_priv\n"); -		return -ENOMEM; -	} +	hpriv = ahci_platform_get_resources(pdev); +	if (IS_ERR(hpriv)) +		return PTR_ERR(hpriv); -	hpriv->flags |= (unsigned long)pi.private_data; - -	hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem)); -	if (!hpriv->mmio) { -		dev_err(dev, "can't map %pR\n", mem); -		return -ENOMEM; -	} +	rc = ahci_platform_enable_resources(hpriv); +	if (rc) +		return rc;  	/*  	 * Some platforms might need to prepare for mmio region access, @@ -84,112 +54,50 @@ static int __init ahci_probe(struct platform_device *pdev)  	if (pdata && pdata->init) {  		rc = pdata->init(dev, hpriv->mmio);  		if (rc) -			return rc; -	} - -	ahci_save_initial_config(dev, hpriv, -		pdata ? pdata->force_port_map : 0, -		pdata ? pdata->mask_port_map  : 0); - -	/* prepare host */ -	if (hpriv->cap & HOST_CAP_NCQ) -		pi.flags |= ATA_FLAG_NCQ; - -	if (hpriv->cap & HOST_CAP_PMP) -		pi.flags |= ATA_FLAG_PMP; - -	ahci_set_em_messages(hpriv, &pi); - -	/* CAP.NP sometimes indicate the index of the last enabled -	 * port, at other times, that of the last possible port, so -	 * determining the maximum port number requires looking at -	 * both CAP.NP and port_map. -	 */ -	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); - -	host = ata_host_alloc_pinfo(dev, ppi, n_ports); -	if (!host) { -		rc = -ENOMEM; -		goto err0; -	} - -	host->private_data = hpriv; - -	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) -		host->flags |= ATA_HOST_PARALLEL_SCAN; -	else -		printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n"); - -	if (pi.flags & ATA_FLAG_EM) -		ahci_reset_em(host); - -	for (i = 0; i < host->n_ports; i++) { -		struct ata_port *ap = host->ports[i]; - -		ata_port_desc(ap, "mmio %pR", mem); -		ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); - -		/* set enclosure management message type */ -		if (ap->flags & ATA_FLAG_EM) -			ap->em_message_type = hpriv->em_msg_type; - -		/* disabled/not-implemented port */ -		if (!(hpriv->port_map & (1 << i))) -			ap->ops = &ata_dummy_port_ops; +			goto disable_resources;  	} -	rc = ahci_reset_controller(host); -	if (rc) -		goto err0; - -	ahci_init_controller(host); -	ahci_print_info(host, "platform"); +	if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci")) +		hflags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ; -	rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, -			       &ahci_platform_sht); +	rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info, +				     hflags, 0, 0);  	if (rc) -		goto err0; +		goto pdata_exit;  	return 0; -err0: +pdata_exit:  	if (pdata && pdata->exit)  		pdata->exit(dev); +disable_resources: +	ahci_platform_disable_resources(hpriv);  	return rc;  } -static int __devexit ahci_remove(struct platform_device *pdev) -{ -	struct device *dev = &pdev->dev; -	struct ahci_platform_data *pdata = dev->platform_data; -	struct ata_host *host = dev_get_drvdata(dev); - -	ata_host_detach(host); +static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, +			 ahci_platform_resume); -	if (pdata && pdata->exit) -		pdata->exit(dev); - -	return 0; -} +static const struct of_device_id ahci_of_match[] = { +	{ .compatible = "snps,spear-ahci", }, +	{ .compatible = "snps,exynos5440-ahci", }, +	{ .compatible = "ibm,476gtr-ahci", }, +	{ .compatible = "snps,dwc-ahci", }, +	{ .compatible = "hisilicon,hisi-ahci", }, +	{}, +}; +MODULE_DEVICE_TABLE(of, ahci_of_match);  static struct platform_driver ahci_driver = { -	.remove = __devexit_p(ahci_remove), +	.probe = ahci_probe, +	.remove = ata_platform_remove_one,  	.driver = {  		.name = "ahci",  		.owner = THIS_MODULE, +		.of_match_table = ahci_of_match, +		.pm = &ahci_pm_ops,  	},  }; - -static int __init ahci_init(void) -{ -	return platform_driver_probe(&ahci_driver, ahci_probe); -} -module_init(ahci_init); - -static void __exit ahci_exit(void) -{ -	platform_driver_unregister(&ahci_driver); -} -module_exit(ahci_exit); +module_platform_driver(ahci_driver);  MODULE_DESCRIPTION("AHCI SATA platform driver");  MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c new file mode 100644 index 00000000000..2595598df9c --- /dev/null +++ b/drivers/ata/ahci_st.c @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2012 STMicroelectronics Limited + * + * Authors: Francesco Virlinzi <francesco.virlinzi@st.com> + *	    Alexandre Torgue <alexandre.torgue@st.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/export.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/of.h> +#include <linux/ahci_platform.h> +#include <linux/libata.h> +#include <linux/reset.h> +#include <linux/io.h> +#include <linux/dma-mapping.h> + +#include "ahci.h" + +#define ST_AHCI_OOBR			0xbc +#define ST_AHCI_OOBR_WE			BIT(31) +#define ST_AHCI_OOBR_CWMIN_SHIFT	24 +#define ST_AHCI_OOBR_CWMAX_SHIFT	16 +#define ST_AHCI_OOBR_CIMIN_SHIFT	8 +#define ST_AHCI_OOBR_CIMAX_SHIFT	0 + +struct st_ahci_drv_data { +	struct platform_device *ahci; +	struct reset_control *pwr; +	struct reset_control *sw_rst; +	struct reset_control *pwr_rst; +	struct ahci_host_priv *hpriv; +}; + +static void st_ahci_configure_oob(void __iomem *mmio) +{ +	unsigned long old_val, new_val; + +	new_val = (0x02 << ST_AHCI_OOBR_CWMIN_SHIFT) | +		  (0x04 << ST_AHCI_OOBR_CWMAX_SHIFT) | +		  (0x08 << ST_AHCI_OOBR_CIMIN_SHIFT) | +		  (0x0C << ST_AHCI_OOBR_CIMAX_SHIFT); + +	old_val = readl(mmio + ST_AHCI_OOBR); +	writel(old_val | ST_AHCI_OOBR_WE, mmio + ST_AHCI_OOBR); +	writel(new_val | ST_AHCI_OOBR_WE, mmio + ST_AHCI_OOBR); +	writel(new_val, mmio + ST_AHCI_OOBR); +} + +static int st_ahci_deassert_resets(struct device *dev) +{ +	struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev); +	int err; + +	if (drv_data->pwr) { +		err = reset_control_deassert(drv_data->pwr); +		if (err) { +			dev_err(dev, "unable to bring out of pwrdwn\n"); +			return err; +		} +	} + +	st_ahci_configure_oob(drv_data->hpriv->mmio); + +	if (drv_data->sw_rst) { +		err = reset_control_deassert(drv_data->sw_rst); +		if (err) { +			dev_err(dev, "unable to bring out of sw-rst\n"); +			return err; +		} +	} + +	if (drv_data->pwr_rst) { +		err = reset_control_deassert(drv_data->pwr_rst); +		if (err) { +			dev_err(dev, "unable to bring out of pwr-rst\n"); +			return err; +		} +	} + +	return 0; +} + +static void st_ahci_host_stop(struct ata_host *host) +{ +	struct ahci_host_priv *hpriv = host->private_data; +	struct device *dev = host->dev; +	struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev); +	int err; + +	if (drv_data->pwr) { +		err = reset_control_assert(drv_data->pwr); +		if (err) +			dev_err(dev, "unable to pwrdwn\n"); +	} + +	ahci_platform_disable_resources(hpriv); +} + +static int st_ahci_probe_resets(struct platform_device *pdev) +{ +	struct st_ahci_drv_data *drv_data = platform_get_drvdata(pdev); + +	drv_data->pwr = devm_reset_control_get(&pdev->dev, "pwr-dwn"); +	if (IS_ERR(drv_data->pwr)) { +		dev_info(&pdev->dev, "power reset control not defined\n"); +		drv_data->pwr = NULL; +	} + +	drv_data->sw_rst = devm_reset_control_get(&pdev->dev, "sw-rst"); +	if (IS_ERR(drv_data->sw_rst)) { +		dev_info(&pdev->dev, "soft reset control not defined\n"); +		drv_data->sw_rst = NULL; +	} + +	drv_data->pwr_rst = devm_reset_control_get(&pdev->dev, "pwr-rst"); +	if (IS_ERR(drv_data->pwr_rst)) { +		dev_dbg(&pdev->dev, "power soft reset control not defined\n"); +		drv_data->pwr_rst = NULL; +	} + +	return st_ahci_deassert_resets(&pdev->dev); +} + +static struct ata_port_operations st_ahci_port_ops = { +	.inherits	= &ahci_platform_ops, +	.host_stop	= st_ahci_host_stop, +}; + +static const struct ata_port_info st_ahci_port_info = { +	.flags          = AHCI_FLAG_COMMON, +	.pio_mask       = ATA_PIO4, +	.udma_mask      = ATA_UDMA6, +	.port_ops       = &st_ahci_port_ops, +}; + +static int st_ahci_probe(struct platform_device *pdev) +{ +	struct st_ahci_drv_data *drv_data; +	struct ahci_host_priv *hpriv; +	int err; + +	drv_data = devm_kzalloc(&pdev->dev, sizeof(*drv_data), GFP_KERNEL); +	if (!drv_data) +		return -ENOMEM; + +	platform_set_drvdata(pdev, drv_data); + +	hpriv = ahci_platform_get_resources(pdev); +	if (IS_ERR(hpriv)) +		return PTR_ERR(hpriv); + +	drv_data->hpriv = hpriv; + +	err = st_ahci_probe_resets(pdev); +	if (err) +		return err; + +	err = ahci_platform_enable_resources(hpriv); +	if (err) +		return err; + +	err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, 0, 0, 0); +	if (err) { +		ahci_platform_disable_resources(hpriv); +		return err; +	} + +	return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int st_ahci_suspend(struct device *dev) +{ +	struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev); +	struct ahci_host_priv *hpriv = drv_data->hpriv; +	int err; + +	err = ahci_platform_suspend_host(dev); +	if (err) +		return err; + +	if (drv_data->pwr) { +		err = reset_control_assert(drv_data->pwr); +		if (err) { +			dev_err(dev, "unable to pwrdwn"); +			return err; +		} +	} + +	ahci_platform_disable_resources(hpriv); + +	return 0; +} + +static int st_ahci_resume(struct device *dev) +{ +	struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev); +	struct ahci_host_priv *hpriv = drv_data->hpriv; +	int err; + +	err = ahci_platform_enable_resources(hpriv); +	if (err) +		return err; + +	err = st_ahci_deassert_resets(dev); +	if (err) { +		ahci_platform_disable_resources(hpriv); +		return err; +	} + +	return ahci_platform_resume_host(dev); +} +#endif + +static SIMPLE_DEV_PM_OPS(st_ahci_pm_ops, st_ahci_suspend, st_ahci_resume); + +static struct of_device_id st_ahci_match[] = { +	{ .compatible = "st,ahci", }, +	{}, +}; +MODULE_DEVICE_TABLE(of, st_ahci_match); + +static struct platform_driver st_ahci_driver = { +	.driver = { +		.name = "st_ahci", +		.owner = THIS_MODULE, +		.pm = &st_ahci_pm_ops, +		.of_match_table = of_match_ptr(st_ahci_match), +	}, +	.probe = st_ahci_probe, +	.remove = ata_platform_remove_one, +}; +module_platform_driver(st_ahci_driver); + +MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>"); +MODULE_AUTHOR("Francesco Virlinzi <francesco.virlinzi@st.com>"); +MODULE_DESCRIPTION("STMicroelectronics SATA AHCI Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c new file mode 100644 index 00000000000..02002f125bd --- /dev/null +++ b/drivers/ata/ahci_sunxi.c @@ -0,0 +1,252 @@ +/* + * Allwinner sunxi AHCI SATA platform driver + * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl> + * Copyright 2014 Hans de Goede <hdegoede@redhat.com> + * + * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov + * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>, + * Daniel Wang <danielwang@allwinnertech.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/ahci_platform.h> +#include <linux/clk.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> +#include "ahci.h" + +#define AHCI_BISTAFR	0x00a0 +#define AHCI_BISTCR	0x00a4 +#define AHCI_BISTFCTR	0x00a8 +#define AHCI_BISTSR	0x00ac +#define AHCI_BISTDECR	0x00b0 +#define AHCI_DIAGNR0	0x00b4 +#define AHCI_DIAGNR1	0x00b8 +#define AHCI_OOBR	0x00bc +#define AHCI_PHYCS0R	0x00c0 +#define AHCI_PHYCS1R	0x00c4 +#define AHCI_PHYCS2R	0x00c8 +#define AHCI_TIMER1MS	0x00e0 +#define AHCI_GPARAM1R	0x00e8 +#define AHCI_GPARAM2R	0x00ec +#define AHCI_PPARAMR	0x00f0 +#define AHCI_TESTR	0x00f4 +#define AHCI_VERSIONR	0x00f8 +#define AHCI_IDR	0x00fc +#define AHCI_RWCR	0x00fc +#define AHCI_P0DMACR	0x0170 +#define AHCI_P0PHYCR	0x0178 +#define AHCI_P0PHYSR	0x017c + +static void sunxi_clrbits(void __iomem *reg, u32 clr_val) +{ +	u32 reg_val; + +	reg_val = readl(reg); +	reg_val &= ~(clr_val); +	writel(reg_val, reg); +} + +static void sunxi_setbits(void __iomem *reg, u32 set_val) +{ +	u32 reg_val; + +	reg_val = readl(reg); +	reg_val |= set_val; +	writel(reg_val, reg); +} + +static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val) +{ +	u32 reg_val; + +	reg_val = readl(reg); +	reg_val &= ~(clr_val); +	reg_val |= set_val; +	writel(reg_val, reg); +} + +static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift) +{ +	return (readl(reg) >> shift) & mask; +} + +static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base) +{ +	u32 reg_val; +	int timeout; + +	/* This magic is from the original code */ +	writel(0, reg_base + AHCI_RWCR); +	msleep(5); + +	sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19)); +	sunxi_clrsetbits(reg_base + AHCI_PHYCS0R, +			 (0x7 << 24), +			 (0x5 << 24) | BIT(23) | BIT(18)); +	sunxi_clrsetbits(reg_base + AHCI_PHYCS1R, +			 (0x3 << 16) | (0x1f << 8) | (0x3 << 6), +			 (0x2 << 16) | (0x6 << 8) | (0x2 << 6)); +	sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15)); +	sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19)); +	sunxi_clrsetbits(reg_base + AHCI_PHYCS0R, +			 (0x7 << 20), (0x3 << 20)); +	sunxi_clrsetbits(reg_base + AHCI_PHYCS2R, +			 (0x1f << 5), (0x19 << 5)); +	msleep(5); + +	sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19)); + +	timeout = 250; /* Power up takes aprox 50 us */ +	do { +		reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28); +		if (reg_val == 0x02) +			break; + +		if (--timeout == 0) { +			dev_err(dev, "PHY power up failed.\n"); +			return -EIO; +		} +		udelay(1); +	} while (1); + +	sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24)); + +	timeout = 100; /* Calibration takes aprox 10 us */ +	do { +		reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24); +		if (reg_val == 0x00) +			break; + +		if (--timeout == 0) { +			dev_err(dev, "PHY calibration failed.\n"); +			return -EIO; +		} +		udelay(1); +	} while (1); + +	msleep(15); + +	writel(0x7, reg_base + AHCI_RWCR); + +	return 0; +} + +static void ahci_sunxi_start_engine(struct ata_port *ap) +{ +	void __iomem *port_mmio = ahci_port_base(ap); +	struct ahci_host_priv *hpriv = ap->host->private_data; + +	/* Setup DMA before DMA start */ +	sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ff00, 0x00004400); + +	/* Start DMA */ +	sunxi_setbits(port_mmio + PORT_CMD, PORT_CMD_START); +} + +static const struct ata_port_info ahci_sunxi_port_info = { +	.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NCQ, +	.pio_mask	= ATA_PIO4, +	.udma_mask	= ATA_UDMA6, +	.port_ops	= &ahci_platform_ops, +}; + +static int ahci_sunxi_probe(struct platform_device *pdev) +{ +	struct device *dev = &pdev->dev; +	struct ahci_host_priv *hpriv; +	unsigned long hflags; +	int rc; + +	hpriv = ahci_platform_get_resources(pdev); +	if (IS_ERR(hpriv)) +		return PTR_ERR(hpriv); + +	hpriv->start_engine = ahci_sunxi_start_engine; + +	rc = ahci_platform_enable_resources(hpriv); +	if (rc) +		return rc; + +	rc = ahci_sunxi_phy_init(dev, hpriv->mmio); +	if (rc) +		goto disable_resources; + +	hflags = AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | +		 AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ; + +	rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info, +				     hflags, 0, 0); +	if (rc) +		goto disable_resources; + +	return 0; + +disable_resources: +	ahci_platform_disable_resources(hpriv); +	return rc; +} + +#ifdef CONFIG_PM_SLEEP +static int ahci_sunxi_resume(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	struct ahci_host_priv *hpriv = host->private_data; +	int rc; + +	rc = ahci_platform_enable_resources(hpriv); +	if (rc) +		return rc; + +	rc = ahci_sunxi_phy_init(dev, hpriv->mmio); +	if (rc) +		goto disable_resources; + +	rc = ahci_platform_resume_host(dev); +	if (rc) +		goto disable_resources; + +	return 0; + +disable_resources: +	ahci_platform_disable_resources(hpriv); +	return rc; +} +#endif + +static SIMPLE_DEV_PM_OPS(ahci_sunxi_pm_ops, ahci_platform_suspend, +			 ahci_sunxi_resume); + +static const struct of_device_id ahci_sunxi_of_match[] = { +	{ .compatible = "allwinner,sun4i-a10-ahci", }, +	{ }, +}; +MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match); + +static struct platform_driver ahci_sunxi_driver = { +	.probe = ahci_sunxi_probe, +	.remove = ata_platform_remove_one, +	.driver = { +		.name = "ahci-sunxi", +		.owner = THIS_MODULE, +		.of_match_table = ahci_sunxi_of_match, +		.pm = &ahci_sunxi_pm_ops, +	}, +}; +module_platform_driver(ahci_sunxi_driver); + +MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA driver"); +MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c new file mode 100644 index 00000000000..ee3a3659bd9 --- /dev/null +++ b/drivers/ata/ahci_xgene.c @@ -0,0 +1,523 @@ +/* + * AppliedMicro X-Gene SoC SATA Host Controller Driver + * + * Copyright (c) 2014, Applied Micro Circuits Corporation + * Author: Loc Ho <lho@apm.com> + *         Tuan Phan <tphan@apm.com> + *         Suman Tripathi <stripathi@apm.com> + * + * This program is free software; you can redistribute  it and/or modify it + * under  the terms of  the GNU General  Public License as published by the + * Free Software Foundation;  either version 2 of the  License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + * + * NOTE: PM support is not currently available. + * + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/ahci_platform.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/phy/phy.h> +#include "ahci.h" + +/* Max # of disk per a controller */ +#define MAX_AHCI_CHN_PERCTR		2 + +/* MUX CSR */ +#define SATA_ENET_CONFIG_REG		0x00000000 +#define  CFG_SATA_ENET_SELECT_MASK	0x00000001 + +/* SATA core host controller CSR */ +#define SLVRDERRATTRIBUTES		0x00000000 +#define SLVWRERRATTRIBUTES		0x00000004 +#define MSTRDERRATTRIBUTES		0x00000008 +#define MSTWRERRATTRIBUTES		0x0000000c +#define BUSCTLREG			0x00000014 +#define IOFMSTRWAUX			0x00000018 +#define INTSTATUSMASK			0x0000002c +#define ERRINTSTATUS			0x00000030 +#define ERRINTSTATUSMASK		0x00000034 + +/* SATA host AHCI CSR */ +#define PORTCFG				0x000000a4 +#define  PORTADDR_SET(dst, src) \ +		(((dst) & ~0x0000003f) | (((u32)(src)) & 0x0000003f)) +#define PORTPHY1CFG		0x000000a8 +#define PORTPHY1CFG_FRCPHYRDY_SET(dst, src) \ +		(((dst) & ~0x00100000) | (((u32)(src) << 0x14) & 0x00100000)) +#define PORTPHY2CFG			0x000000ac +#define PORTPHY3CFG			0x000000b0 +#define PORTPHY4CFG			0x000000b4 +#define PORTPHY5CFG			0x000000b8 +#define SCTL0				0x0000012C +#define PORTPHY5CFG_RTCHG_SET(dst, src) \ +		(((dst) & ~0xfff00000) | (((u32)(src) << 0x14) & 0xfff00000)) +#define PORTAXICFG_EN_CONTEXT_SET(dst, src) \ +		(((dst) & ~0x01000000) | (((u32)(src) << 0x18) & 0x01000000)) +#define PORTAXICFG			0x000000bc +#define PORTAXICFG_OUTTRANS_SET(dst, src) \ +		(((dst) & ~0x00f00000) | (((u32)(src) << 0x14) & 0x00f00000)) + +/* SATA host controller AXI CSR */ +#define INT_SLV_TMOMASK			0x00000010 + +/* SATA diagnostic CSR */ +#define CFG_MEM_RAM_SHUTDOWN		0x00000070 +#define BLOCK_MEM_RDY			0x00000074 + +struct xgene_ahci_context { +	struct ahci_host_priv *hpriv; +	struct device *dev; +	u8 last_cmd[MAX_AHCI_CHN_PERCTR]; /* tracking the last command issued*/ +	void __iomem *csr_core;		/* Core CSR address of IP */ +	void __iomem *csr_diag;		/* Diag CSR address of IP */ +	void __iomem *csr_axi;		/* AXI CSR address of IP */ +	void __iomem *csr_mux;		/* MUX CSR address of IP */ +}; + +static int xgene_ahci_init_memram(struct xgene_ahci_context *ctx) +{ +	dev_dbg(ctx->dev, "Release memory from shutdown\n"); +	writel(0x0, ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN); +	readl(ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN); /* Force a barrier */ +	msleep(1);	/* reset may take up to 1ms */ +	if (readl(ctx->csr_diag + BLOCK_MEM_RDY) != 0xFFFFFFFF) { +		dev_err(ctx->dev, "failed to release memory from shutdown\n"); +		return -ENODEV; +	} +	return 0; +} + +/** + * xgene_ahci_restart_engine - Restart the dma engine. + * @ap : ATA port of interest + * + * Restarts the dma engine inside the controller. + */ +static int xgene_ahci_restart_engine(struct ata_port *ap) +{ +	struct ahci_host_priv *hpriv = ap->host->private_data; + +	ahci_stop_engine(ap); +	ahci_start_fis_rx(ap); +	hpriv->start_engine(ap); + +	return 0; +} + +/** + * xgene_ahci_qc_issue - Issue commands to the device + * @qc: Command to issue + * + * Due to Hardware errata for IDENTIFY DEVICE command, the controller cannot + * clear the BSY bit after receiving the PIO setup FIS. This results in the dma + * state machine goes into the CMFatalErrorUpdate state and locks up. By + * restarting the dma engine, it removes the controller out of lock up state. + */ +static unsigned int xgene_ahci_qc_issue(struct ata_queued_cmd *qc) +{ +	struct ata_port *ap = qc->ap; +	struct ahci_host_priv *hpriv = ap->host->private_data; +	struct xgene_ahci_context *ctx = hpriv->plat_data; +	int rc = 0; + +	if (unlikely(ctx->last_cmd[ap->port_no] == ATA_CMD_ID_ATA)) +		xgene_ahci_restart_engine(ap); + +	rc = ahci_qc_issue(qc); + +	/* Save the last command issued */ +	ctx->last_cmd[ap->port_no] = qc->tf.command; + +	return rc; +} + +/** + * xgene_ahci_read_id - Read ID data from the specified device + * @dev: device + * @tf: proposed taskfile + * @id: data buffer + * + * This custom read ID function is required due to the fact that the HW + * does not support DEVSLP. + */ +static unsigned int xgene_ahci_read_id(struct ata_device *dev, +				       struct ata_taskfile *tf, u16 *id) +{ +	u32 err_mask; + +	err_mask = ata_do_dev_read_id(dev, tf, id); +	if (err_mask) +		return err_mask; + +	/* +	 * Mask reserved area. Word78 spec of Link Power Management +	 * bit15-8: reserved +	 * bit7: NCQ autosence +	 * bit6: Software settings preservation supported +	 * bit5: reserved +	 * bit4: In-order sata delivery supported +	 * bit3: DIPM requests supported +	 * bit2: DMA Setup FIS Auto-Activate optimization supported +	 * bit1: DMA Setup FIX non-Zero buffer offsets supported +	 * bit0: Reserved +	 * +	 * Clear reserved bit 8 (DEVSLP bit) as we don't support DEVSLP +	 */ +	id[ATA_ID_FEATURE_SUPP] &= ~(1 << 8); + +	return 0; +} + +static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel) +{ +	void __iomem *mmio = ctx->hpriv->mmio; +	u32 val; + +	dev_dbg(ctx->dev, "port configure mmio 0x%p channel %d\n", +		mmio, channel); +	val = readl(mmio + PORTCFG); +	val = PORTADDR_SET(val, channel == 0 ? 2 : 3); +	writel(val, mmio + PORTCFG); +	readl(mmio + PORTCFG);  /* Force a barrier */ +	/* Disable fix rate */ +	writel(0x0001fffe, mmio + PORTPHY1CFG); +	readl(mmio + PORTPHY1CFG); /* Force a barrier */ +	writel(0x5018461c, mmio + PORTPHY2CFG); +	readl(mmio + PORTPHY2CFG); /* Force a barrier */ +	writel(0x1c081907, mmio + PORTPHY3CFG); +	readl(mmio + PORTPHY3CFG); /* Force a barrier */ +	writel(0x1c080815, mmio + PORTPHY4CFG); +	readl(mmio + PORTPHY4CFG); /* Force a barrier */ +	/* Set window negotiation */ +	val = readl(mmio + PORTPHY5CFG); +	val = PORTPHY5CFG_RTCHG_SET(val, 0x300); +	writel(val, mmio + PORTPHY5CFG); +	readl(mmio + PORTPHY5CFG); /* Force a barrier */ +	val = readl(mmio + PORTAXICFG); +	val = PORTAXICFG_EN_CONTEXT_SET(val, 0x1); /* Enable context mgmt */ +	val = PORTAXICFG_OUTTRANS_SET(val, 0xe); /* Set outstanding */ +	writel(val, mmio + PORTAXICFG); +	readl(mmio + PORTAXICFG); /* Force a barrier */ +} + +/** + * xgene_ahci_do_hardreset - Issue the actual COMRESET + * @link: link to reset + * @deadline: deadline jiffies for the operation + * @online: Return value to indicate if device online + * + * Due to the limitation of the hardware PHY, a difference set of setting is + * required for each supported disk speed - Gen3 (6.0Gbps), Gen2 (3.0Gbps), + * and Gen1 (1.5Gbps). Otherwise during long IO stress test, the PHY will + * report disparity error and etc. In addition, during COMRESET, there can + * be error reported in the register PORT_SCR_ERR. For SERR_DISPARITY and + * SERR_10B_8B_ERR, the PHY receiver line must be reseted. The following + * algorithm is followed to proper configure the hardware PHY during COMRESET: + * + * Alg Part 1: + * 1. Start the PHY at Gen3 speed (default setting) + * 2. Issue the COMRESET + * 3. If no link, go to Alg Part 3 + * 4. If link up, determine if the negotiated speed matches the PHY + *    configured speed + * 5. If they matched, go to Alg Part 2 + * 6. If they do not matched and first time, configure the PHY for the linked + *    up disk speed and repeat step 2 + * 7. Go to Alg Part 2 + * + * Alg Part 2: + * 1. On link up, if there are any SERR_DISPARITY and SERR_10B_8B_ERR error + *    reported in the register PORT_SCR_ERR, then reset the PHY receiver line + * 2. Go to Alg Part 3 + * + * Alg Part 3: + * 1. Clear any pending from register PORT_SCR_ERR. + * + * NOTE: For the initial version, we will NOT support Gen1/Gen2. In addition + *       and until the underlying PHY supports an method to reset the receiver + *       line, on detection of SERR_DISPARITY or SERR_10B_8B_ERR errors, + *       an warning message will be printed. + */ +static int xgene_ahci_do_hardreset(struct ata_link *link, +				   unsigned long deadline, bool *online) +{ +	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); +	struct ata_port *ap = link->ap; +	struct ahci_host_priv *hpriv = ap->host->private_data; +	struct xgene_ahci_context *ctx = hpriv->plat_data; +	struct ahci_port_priv *pp = ap->private_data; +	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; +	void __iomem *port_mmio = ahci_port_base(ap); +	struct ata_taskfile tf; +	int rc; +	u32 val; + +	/* clear D2H reception area to properly wait for D2H FIS */ +	ata_tf_init(link->device, &tf); +	tf.command = ATA_BUSY; +	ata_tf_to_fis(&tf, 0, 0, d2h_fis); +	rc = sata_link_hardreset(link, timing, deadline, online, +				 ahci_check_ready); + +	val = readl(port_mmio + PORT_SCR_ERR); +	if (val & (SERR_DISPARITY | SERR_10B_8B_ERR)) +		dev_warn(ctx->dev, "link has error\n"); + +	/* clear all errors if any pending */ +	val = readl(port_mmio + PORT_SCR_ERR); +	writel(val, port_mmio + PORT_SCR_ERR); + +	return rc; +} + +static int xgene_ahci_hardreset(struct ata_link *link, unsigned int *class, +				unsigned long deadline) +{ +	struct ata_port *ap = link->ap; +        struct ahci_host_priv *hpriv = ap->host->private_data; +	void __iomem *port_mmio = ahci_port_base(ap); +	bool online; +	int rc; +	u32 portcmd_saved; +	u32 portclb_saved; +	u32 portclbhi_saved; +	u32 portrxfis_saved; +	u32 portrxfishi_saved; + +	/* As hardreset resets these CSR, save it to restore later */ +	portcmd_saved = readl(port_mmio + PORT_CMD); +	portclb_saved = readl(port_mmio + PORT_LST_ADDR); +	portclbhi_saved = readl(port_mmio + PORT_LST_ADDR_HI); +	portrxfis_saved = readl(port_mmio + PORT_FIS_ADDR); +	portrxfishi_saved = readl(port_mmio + PORT_FIS_ADDR_HI); + +	ahci_stop_engine(ap); + +	rc = xgene_ahci_do_hardreset(link, deadline, &online); + +	/* As controller hardreset clears them, restore them */ +	writel(portcmd_saved, port_mmio + PORT_CMD); +	writel(portclb_saved, port_mmio + PORT_LST_ADDR); +	writel(portclbhi_saved, port_mmio + PORT_LST_ADDR_HI); +	writel(portrxfis_saved, port_mmio + PORT_FIS_ADDR); +	writel(portrxfishi_saved, port_mmio + PORT_FIS_ADDR_HI); + +	hpriv->start_engine(ap); + +	if (online) +		*class = ahci_dev_classify(ap); + +	return rc; +} + +static void xgene_ahci_host_stop(struct ata_host *host) +{ +	struct ahci_host_priv *hpriv = host->private_data; + +	ahci_platform_disable_resources(hpriv); +} + +static struct ata_port_operations xgene_ahci_ops = { +	.inherits = &ahci_ops, +	.host_stop = xgene_ahci_host_stop, +	.hardreset = xgene_ahci_hardreset, +	.read_id = xgene_ahci_read_id, +	.qc_issue = xgene_ahci_qc_issue, +}; + +static const struct ata_port_info xgene_ahci_port_info = { +	.flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ, +	.pio_mask = ATA_PIO4, +	.udma_mask = ATA_UDMA6, +	.port_ops = &xgene_ahci_ops, +}; + +static int xgene_ahci_hw_init(struct ahci_host_priv *hpriv) +{ +	struct xgene_ahci_context *ctx = hpriv->plat_data; +	int i; +	int rc; +	u32 val; + +	/* Remove IP RAM out of shutdown */ +	rc = xgene_ahci_init_memram(ctx); +	if (rc) +		return rc; + +	for (i = 0; i < MAX_AHCI_CHN_PERCTR; i++) +		xgene_ahci_set_phy_cfg(ctx, i); + +	/* AXI disable Mask */ +	writel(0xffffffff, hpriv->mmio + HOST_IRQ_STAT); +	readl(hpriv->mmio + HOST_IRQ_STAT); /* Force a barrier */ +	writel(0, ctx->csr_core + INTSTATUSMASK); +	val = readl(ctx->csr_core + INTSTATUSMASK); /* Force a barrier */ +	dev_dbg(ctx->dev, "top level interrupt mask 0x%X value 0x%08X\n", +		INTSTATUSMASK, val); + +	writel(0x0, ctx->csr_core + ERRINTSTATUSMASK); +	readl(ctx->csr_core + ERRINTSTATUSMASK); /* Force a barrier */ +	writel(0x0, ctx->csr_axi + INT_SLV_TMOMASK); +	readl(ctx->csr_axi + INT_SLV_TMOMASK); + +	/* Enable AXI Interrupt */ +	writel(0xffffffff, ctx->csr_core + SLVRDERRATTRIBUTES); +	writel(0xffffffff, ctx->csr_core + SLVWRERRATTRIBUTES); +	writel(0xffffffff, ctx->csr_core + MSTRDERRATTRIBUTES); +	writel(0xffffffff, ctx->csr_core + MSTWRERRATTRIBUTES); + +	/* Enable coherency */ +	val = readl(ctx->csr_core + BUSCTLREG); +	val &= ~0x00000002;     /* Enable write coherency */ +	val &= ~0x00000001;     /* Enable read coherency */ +	writel(val, ctx->csr_core + BUSCTLREG); + +	val = readl(ctx->csr_core + IOFMSTRWAUX); +	val |= (1 << 3);        /* Enable read coherency */ +	val |= (1 << 9);        /* Enable write coherency */ +	writel(val, ctx->csr_core + IOFMSTRWAUX); +	val = readl(ctx->csr_core + IOFMSTRWAUX); +	dev_dbg(ctx->dev, "coherency 0x%X value 0x%08X\n", +		IOFMSTRWAUX, val); + +	return rc; +} + +static int xgene_ahci_mux_select(struct xgene_ahci_context *ctx) +{ +	u32 val; + +	/* Check for optional MUX resource */ +	if (IS_ERR(ctx->csr_mux)) +		return 0; + +	val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG); +	val &= ~CFG_SATA_ENET_SELECT_MASK; +	writel(val, ctx->csr_mux + SATA_ENET_CONFIG_REG); +	val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG); +	return val & CFG_SATA_ENET_SELECT_MASK ? -1 : 0; +} + +static int xgene_ahci_probe(struct platform_device *pdev) +{ +	struct device *dev = &pdev->dev; +	struct ahci_host_priv *hpriv; +	struct xgene_ahci_context *ctx; +	struct resource *res; +	unsigned long hflags; +	int rc; + +	hpriv = ahci_platform_get_resources(pdev); +	if (IS_ERR(hpriv)) +		return PTR_ERR(hpriv); + +	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); +	if (!ctx) +		return -ENOMEM; + +	hpriv->plat_data = ctx; +	ctx->hpriv = hpriv; +	ctx->dev = dev; + +	/* Retrieve the IP core resource */ +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1); +	ctx->csr_core = devm_ioremap_resource(dev, res); +	if (IS_ERR(ctx->csr_core)) +		return PTR_ERR(ctx->csr_core); + +	/* Retrieve the IP diagnostic resource */ +	res = platform_get_resource(pdev, IORESOURCE_MEM, 2); +	ctx->csr_diag = devm_ioremap_resource(dev, res); +	if (IS_ERR(ctx->csr_diag)) +		return PTR_ERR(ctx->csr_diag); + +	/* Retrieve the IP AXI resource */ +	res = platform_get_resource(pdev, IORESOURCE_MEM, 3); +	ctx->csr_axi = devm_ioremap_resource(dev, res); +	if (IS_ERR(ctx->csr_axi)) +		return PTR_ERR(ctx->csr_axi); + +	/* Retrieve the optional IP mux resource */ +	res = platform_get_resource(pdev, IORESOURCE_MEM, 4); +	ctx->csr_mux = devm_ioremap_resource(dev, res); + +	dev_dbg(dev, "VAddr 0x%p Mmio VAddr 0x%p\n", ctx->csr_core, +		hpriv->mmio); + +	/* Select ATA */ +	if ((rc = xgene_ahci_mux_select(ctx))) { +		dev_err(dev, "SATA mux selection failed error %d\n", rc); +		return -ENODEV; +	} + +	/* Due to errata, HW requires full toggle transition */ +	rc = ahci_platform_enable_clks(hpriv); +	if (rc) +		goto disable_resources; +	ahci_platform_disable_clks(hpriv); + +	rc = ahci_platform_enable_resources(hpriv); +	if (rc) +		goto disable_resources; + +	/* Configure the host controller */ +	xgene_ahci_hw_init(hpriv); + +	/* +	 * Setup DMA mask. This is preliminary until the DMA range is sorted +	 * out. +	 */ +	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); +	if (rc) { +		dev_err(dev, "Unable to set dma mask\n"); +		goto disable_resources; +	} + +	hflags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ; + +	rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info, +				     hflags, 0, 0); +	if (rc) +		goto disable_resources; + +	dev_dbg(dev, "X-Gene SATA host controller initialized\n"); +	return 0; + +disable_resources: +	ahci_platform_disable_resources(hpriv); +	return rc; +} + +static const struct of_device_id xgene_ahci_of_match[] = { +	{.compatible = "apm,xgene-ahci"}, +	{}, +}; +MODULE_DEVICE_TABLE(of, xgene_ahci_of_match); + +static struct platform_driver xgene_ahci_driver = { +	.probe = xgene_ahci_probe, +	.remove = ata_platform_remove_one, +	.driver = { +		.name = "xgene-ahci", +		.owner = THIS_MODULE, +		.of_match_table = xgene_ahci_of_match, +	}, +}; + +module_platform_driver(xgene_ahci_driver); + +MODULE_DESCRIPTION("APM X-Gene AHCI SATA driver"); +MODULE_AUTHOR("Loc Ho <lho@apm.com>"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.4"); diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 6981f7680a0..9ff545ce8da 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -19,7 +19,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -81,14 +80,13 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)  				xfer_mask |= ata_xfer_mode2mask(XFER_MW_DMA_0);  			} -			ata_dev_printk(dev, KERN_INFO, "configured for %s\n", -				       name); +			ata_dev_info(dev, "configured for %s\n", name);  			dev->xfer_mode = ata_xfer_mask2mode(xfer_mask);  			dev->xfer_shift = ata_xfer_mode2shift(dev->xfer_mode);  			dev->flags &= ~ATA_DFLAG_PIO;  		} else { -			ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); +			ata_dev_info(dev, "configured for PIO\n");  			dev->xfer_mode = XFER_PIO_0;  			dev->xfer_shift = ATA_SHIFT_PIO;  			dev->flags |= ATA_DFLAG_PIO; @@ -178,7 +176,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id  	if ((id->driver_data & ATA_GEN_CLASS_MATCH) && all_generic_ide == 0)  		return -ENODEV; -	if (id->driver_data & ATA_GEN_INTEL_IDER) +	if ((id->driver_data & ATA_GEN_INTEL_IDER) && !all_generic_ide)  		if (!is_intel_ider(dev))  			return -ENODEV; @@ -222,13 +220,6 @@ static struct pci_device_id ata_generic[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_OPTI,   PCI_DEVICE_ID_OPTI_82C558), },  	{ PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE),  	  .driver_data = ATA_GEN_FORCE_DMA }, -	/* -	 * For some reason, MCP89 on MacBook 7,1 doesn't work with -	 * ahci, use ata_generic instead. -	 */ -	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA, -	  PCI_VENDOR_ID_APPLE, 0xcb89, -	  .driver_data = ATA_GEN_FORCE_DMA },  #if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE)  	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },  	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),  }, @@ -237,7 +228,7 @@ static struct pci_device_id ata_generic[] = {  #endif  	/* Intel, IDE class device */  	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, -	  PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL,  +	  PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL,  	  .driver_data = ATA_GEN_INTEL_IDER },  	/* Must come last. If you add entries adjust this table appropriately */  	{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL), @@ -250,23 +241,13 @@ static struct pci_driver ata_generic_pci_driver = {  	.id_table	= ata_generic,  	.probe 		= ata_generic_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init ata_generic_init(void) -{ -	return pci_register_driver(&ata_generic_pci_driver); -} - - -static void __exit ata_generic_exit(void) -{ -	pci_unregister_driver(&ata_generic_pci_driver); -} - +module_pci_driver(ata_generic_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for generic ATA"); @@ -274,7 +255,4 @@ MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, ata_generic);  MODULE_VERSION(DRV_VERSION); -module_init(ata_generic_init); -module_exit(ata_generic_exit); -  module_param(all_generic_ide, int, 0); diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 6cb14ca8ee8..893e30e9a9e 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1,7 +1,7 @@  /*   *    ata_piix.c - Intel PATA/SATA controllers   * - *    Maintained by:  Jeff Garzik <jgarzik@pobox.com> + *    Maintained by:  Tejun Heo <tj@kernel.org>   *    		    Please ALWAYS copy linux-ide@vger.kernel.org   *		    on emails.   * @@ -38,16 +38,16 @@   *  Hardware documentation available at http://developer.intel.com/   *   * Documentation - *	Publically available from Intel web site. Errata documentation - * is also publically available. As an aide to anyone hacking on this + *	Publicly available from Intel web site. Errata documentation + * is also publicly available. As an aide to anyone hacking on this   * driver the list of errata that are relevant is below, going back to   * PIIX4. Older device documentation is now a bit tricky to find.   *   * The chipsets all follow very much the same design. The original Triton - * series chipsets do _not_ support independant device timings, but this + * series chipsets do _not_ support independent device timings, but this   * is fixed in Triton II. With the odd mobile exception the chips then   * change little except in gaining more modes until SATA arrives. This - * driver supports only the chips with independant timing (that is those + * driver supports only the chips with independent timing (that is those   * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix   * for the early chip drivers.   * @@ -100,7 +100,7 @@  enum {  	PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */ -	ICH5_PMR		= 0x90, /* port mapping register */ +	ICH5_PMR		= 0x90, /* address map register */  	ICH5_PCS		= 0x92,	/* port control and status */  	PIIX_SIDPR_BAR		= 5,  	PIIX_SIDPR_LEN		= 16, @@ -113,6 +113,8 @@ enum {  	PIIX_PATA_FLAGS		= ATA_FLAG_SLAVE_POSS,  	PIIX_SATA_FLAGS		= ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR, +	PIIX_FLAG_PIO16		= (1 << 30), /*support 16bit PIO only*/ +  	PIIX_80C_PRI		= (1 << 5) | (1 << 4),  	PIIX_80C_SEC		= (1 << 7) | (1 << 6), @@ -122,7 +124,7 @@ enum {  	P2			= 2,  /* port 2 */  	P3			= 3,  /* port 3 */  	IDE			= -1, /* IDE */ -	NA			= -2, /* not avaliable */ +	NA			= -2, /* not available */  	RV			= -3, /* reserved */  	PIIX_AHCI_DEVICE	= 6, @@ -147,6 +149,9 @@ enum piix_controller_ids {  	ich8m_apple_sata,	/* locks up on second port enable */  	tolapai_sata,  	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */ +	ich8_sata_snb, +	ich8_2port_sata_snb, +	ich8_2port_sata_byt,  };  struct piix_map_db { @@ -161,27 +166,6 @@ struct piix_host_priv {  	void __iomem *sidpr;  }; -static int piix_init_one(struct pci_dev *pdev, -			 const struct pci_device_id *ent); -static void piix_remove_one(struct pci_dev *pdev); -static int piix_pata_prereset(struct ata_link *link, unsigned long deadline); -static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev); -static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev); -static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev); -static int ich_pata_cable_detect(struct ata_port *ap); -static u8 piix_vmw_bmdma_status(struct ata_port *ap); -static int piix_sidpr_scr_read(struct ata_link *link, -			       unsigned int reg, u32 *val); -static int piix_sidpr_scr_write(struct ata_link *link, -				unsigned int reg, u32 val); -static int piix_sidpr_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, -			      unsigned hints); -static bool piix_irq_check(struct ata_port *ap); -#ifdef CONFIG_PM -static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); -static int piix_pci_device_resume(struct pci_dev *pdev); -#endif -  static unsigned int in_module_init = 1;  static const struct pci_device_id piix_pci_tbl[] = { @@ -230,7 +214,7 @@ static const struct pci_device_id piix_pci_tbl[] = {  	{ 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },  	/* SATA ports */ -	 +  	/* 82801EB (ICH5) */  	{ 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },  	/* 82801EB (ICH5) */ @@ -249,7 +233,7 @@ static const struct pci_device_id piix_pci_tbl[] = {  	  PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich6m_sata },  	/* 82801GB/GR/GH (ICH7, identical to ICH6) */  	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, -	/* 2801GBM/GHM (ICH7M, identical to ICH6M) */ +	/* 82801GBM/GHM (ICH7M, identical to ICH6M)  */  	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata },  	/* Enterprise Southbridge 2 (631xESB/632xESB) */  	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, @@ -298,75 +282,66 @@ static const struct pci_device_id piix_pci_tbl[] = {  	/* SATA Controller IDE (PCH) */  	{ 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },  	/* SATA Controller IDE (CPT) */ -	{ 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, +	{ 0x8086, 0x1c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },  	/* SATA Controller IDE (CPT) */ -	{ 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, +	{ 0x8086, 0x1c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },  	/* SATA Controller IDE (CPT) */  	{ 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },  	/* SATA Controller IDE (CPT) */  	{ 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },  	/* SATA Controller IDE (PBG) */ -	{ 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, +	{ 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },  	/* SATA Controller IDE (PBG) */  	{ 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, -	{ }	/* terminate list */ -}; - -static struct pci_driver piix_pci_driver = { -	.name			= DRV_NAME, -	.id_table		= piix_pci_tbl, -	.probe			= piix_init_one, -	.remove			= piix_remove_one, -#ifdef CONFIG_PM -	.suspend		= piix_pci_device_suspend, -	.resume			= piix_pci_device_resume, -#endif -}; - -static struct scsi_host_template piix_sht = { -	ATA_BMDMA_SHT(DRV_NAME), -}; - -static struct ata_port_operations piix_sata_ops = { -	.inherits		= &ata_bmdma32_port_ops, -	.sff_irq_check		= piix_irq_check, -}; - -static struct ata_port_operations piix_pata_ops = { -	.inherits		= &piix_sata_ops, -	.cable_detect		= ata_cable_40wire, -	.set_piomode		= piix_set_piomode, -	.set_dmamode		= piix_set_dmamode, -	.prereset		= piix_pata_prereset, -}; - -static struct ata_port_operations piix_vmw_ops = { -	.inherits		= &piix_pata_ops, -	.bmdma_status		= piix_vmw_bmdma_status, -}; - -static struct ata_port_operations ich_pata_ops = { -	.inherits		= &piix_pata_ops, -	.cable_detect		= ich_pata_cable_detect, -	.set_dmamode		= ich_set_dmamode, -}; - -static struct device_attribute *piix_sidpr_shost_attrs[] = { -	&dev_attr_link_power_management_policy, -	NULL -}; +	/* SATA Controller IDE (Panther Point) */ +	{ 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, +	/* SATA Controller IDE (Panther Point) */ +	{ 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, +	/* SATA Controller IDE (Panther Point) */ +	{ 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, +	/* SATA Controller IDE (Panther Point) */ +	{ 0x8086, 0x1e09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, +	/* SATA Controller IDE (Lynx Point) */ +	{ 0x8086, 0x8c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, +	/* SATA Controller IDE (Lynx Point) */ +	{ 0x8086, 0x8c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, +	/* SATA Controller IDE (Lynx Point) */ +	{ 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, +	/* SATA Controller IDE (Lynx Point) */ +	{ 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, +	/* SATA Controller IDE (Lynx Point-LP) */ +	{ 0x8086, 0x9c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, +	/* SATA Controller IDE (Lynx Point-LP) */ +	{ 0x8086, 0x9c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, +	/* SATA Controller IDE (Lynx Point-LP) */ +	{ 0x8086, 0x9c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, +	/* SATA Controller IDE (Lynx Point-LP) */ +	{ 0x8086, 0x9c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, +	/* SATA Controller IDE (DH89xxCC) */ +	{ 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, +	/* SATA Controller IDE (Avoton) */ +	{ 0x8086, 0x1f20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, +	/* SATA Controller IDE (Avoton) */ +	{ 0x8086, 0x1f21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, +	/* SATA Controller IDE (Avoton) */ +	{ 0x8086, 0x1f30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, +	/* SATA Controller IDE (Avoton) */ +	{ 0x8086, 0x1f31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, +	/* SATA Controller IDE (Wellsburg) */ +	{ 0x8086, 0x8d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, +	/* SATA Controller IDE (Wellsburg) */ +	{ 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, +	/* SATA Controller IDE (Wellsburg) */ +	{ 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, +	/* SATA Controller IDE (Wellsburg) */ +	{ 0x8086, 0x8d68, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, +	/* SATA Controller IDE (BayTrail) */ +	{ 0x8086, 0x0F20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt }, +	{ 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt }, +	/* SATA Controller IDE (Coleto Creek) */ +	{ 0x8086, 0x23a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, -static struct scsi_host_template piix_sidpr_sht = { -	ATA_BMDMA_SHT(DRV_NAME), -	.shost_attrs		= piix_sidpr_shost_attrs, -}; - -static struct ata_port_operations piix_sidpr_sata_ops = { -	.inherits		= &piix_sata_ops, -	.hardreset		= sata_std_hardreset, -	.scr_read		= piix_sidpr_scr_read, -	.scr_write		= piix_sidpr_scr_write, -	.set_lpm		= piix_sidpr_set_lpm, +	{ }	/* terminate list */  };  static const struct piix_map_db ich5_map_db = { @@ -470,134 +445,9 @@ static const struct piix_map_db *piix_map_db_table[] = {  	[ich8_2port_sata]	= &ich8_2port_map_db,  	[ich8m_apple_sata]	= &ich8m_apple_map_db,  	[tolapai_sata]		= &tolapai_map_db, -}; - -static struct ata_port_info piix_port_info[] = { -	[piix_pata_mwdma] = 	/* PIIX3 MWDMA only */ -	{ -		.flags		= PIIX_PATA_FLAGS, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ -		.port_ops	= &piix_pata_ops, -	}, - -	[piix_pata_33] =	/* PIIX4 at 33MHz */ -	{ -		.flags		= PIIX_PATA_FLAGS, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ -		.udma_mask	= ATA_UDMA2, -		.port_ops	= &piix_pata_ops, -	}, - -	[ich_pata_33] = 	/* ICH0 - ICH at 33Mhz*/ -	{ -		.flags		= PIIX_PATA_FLAGS, -		.pio_mask 	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok  */ -		.udma_mask	= ATA_UDMA2, -		.port_ops	= &ich_pata_ops, -	}, - -	[ich_pata_66] = 	/* ICH controllers up to 66MHz */ -	{ -		.flags		= PIIX_PATA_FLAGS, -		.pio_mask 	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */ -		.udma_mask	= ATA_UDMA4, -		.port_ops	= &ich_pata_ops, -	}, - -	[ich_pata_100] = -	{ -		.flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA12_ONLY, -		.udma_mask	= ATA_UDMA5, -		.port_ops	= &ich_pata_ops, -	}, - -	[ich_pata_100_nomwdma1] = -	{ -		.flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA2_ONLY, -		.udma_mask	= ATA_UDMA5, -		.port_ops	= &ich_pata_ops, -	}, - -	[ich5_sata] = -	{ -		.flags		= PIIX_SATA_FLAGS, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA2, -		.udma_mask	= ATA_UDMA6, -		.port_ops	= &piix_sata_ops, -	}, - -	[ich6_sata] = -	{ -		.flags		= PIIX_SATA_FLAGS, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA2, -		.udma_mask	= ATA_UDMA6, -		.port_ops	= &piix_sata_ops, -	}, - -	[ich6m_sata] = -	{ -		.flags		= PIIX_SATA_FLAGS, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA2, -		.udma_mask	= ATA_UDMA6, -		.port_ops	= &piix_sata_ops, -	}, - -	[ich8_sata] = -	{ -		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA2, -		.udma_mask	= ATA_UDMA6, -		.port_ops	= &piix_sata_ops, -	}, - -	[ich8_2port_sata] = -	{ -		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA2, -		.udma_mask	= ATA_UDMA6, -		.port_ops	= &piix_sata_ops, -	}, - -	[tolapai_sata] = -	{ -		.flags		= PIIX_SATA_FLAGS, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA2, -		.udma_mask	= ATA_UDMA6, -		.port_ops	= &piix_sata_ops, -	}, - -	[ich8m_apple_sata] = -	{ -		.flags		= PIIX_SATA_FLAGS, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA2, -		.udma_mask	= ATA_UDMA6, -		.port_ops	= &piix_sata_ops, -	}, - -	[piix_pata_vmw] = -	{ -		.flags		= PIIX_PATA_FLAGS, -		.pio_mask	= ATA_PIO4, -		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ -		.udma_mask	= ATA_UDMA2, -		.port_ops	= &piix_vmw_ops, -	}, - +	[ich8_sata_snb]		= &ich8_map_db, +	[ich8_2port_sata_snb]	= &ich8_2port_map_db, +	[ich8_2port_sata_byt]	= &ich8_2port_map_db,  };  static struct pci_bits piix_enable_bits[] = { @@ -641,6 +491,14 @@ static const struct ich_laptop ich_laptop[] = {  	{ 0, }  }; +static int piix_port_start(struct ata_port *ap) +{ +	if (!(ap->flags & PIIX_FLAG_PIO16)) +		ap->pflags |= ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE; + +	return ata_bmdma_port_start(ap); +} +  /**   *	ich_pata_cable_detect - Probe host controller cable detect info   *	@ap: Port for which cable detect info is desired @@ -659,7 +517,7 @@ static int ich_pata_cable_detect(struct ata_port *ap)  	const struct ich_laptop *lap = &ich_laptop[0];  	u8 mask; -	/* Check for specials - Acer Aspire 5602WLMi */ +	/* Check for specials */  	while (lap->device) {  		if (lap->device == pdev->device &&  		    lap->subvendor == pdev->subsystem_vendor && @@ -696,22 +554,11 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)  static DEFINE_SPINLOCK(piix_lock); -/** - *	piix_set_piomode - Initialize host controller PATA PIO timings - *	@ap: Port whose timings we are configuring - *	@adev: um - * - *	Set PIO mode for device, in host controller PCI config space. - * - *	LOCKING: - *	None (inherited from caller). - */ - -static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) +static void piix_set_timings(struct ata_port *ap, struct ata_device *adev, +			     u8 pio)  {  	struct pci_dev *dev	= to_pci_dev(ap->host->dev);  	unsigned long flags; -	unsigned int pio	= adev->pio_mode - XFER_PIO_0;  	unsigned int is_slave	= (adev->devno != 0);  	unsigned int master_port= ap->port_no ? 0x42 : 0x40;  	unsigned int slave_port	= 0x44; @@ -736,10 +583,16 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)  		control |= 1;	/* TIME1 enable */  	if (ata_pio_need_iordy(adev))  		control |= 2;	/* IE enable */ -  	/* Intel specifies that the PPE functionality is for disk only */  	if (adev->class == ATA_DEV_ATA)  		control |= 4;	/* PPE enable */ +	/* +	 * If the drive MWDMA is faster than it can do PIO then +	 * we must force PIO into PIO0 +	 */ +	if (adev->pio_mode < XFER_PIO_0 + pio) +		/* Enable DMA timing only */ +		control |= 8;	/* PIO cycles in PIO0 */  	spin_lock_irqsave(&piix_lock, flags); @@ -751,8 +604,6 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)  	if (is_slave) {  		/* clear TIME1|IE1|PPE1|DTE1 */  		master_data &= 0xff0f; -		/* Enable SITRE (separate slave timing register) */ -		master_data |= 0x4000;  		/* enable PPE1, IE1 and TIME1 as needed */  		master_data |= (control << 4);  		pci_read_config_byte(dev, slave_port, &slave_data); @@ -770,6 +621,9 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)  			(timings[pio][0] << 12) |  			(timings[pio][1] << 8);  	} + +	/* Enable SITRE (separate slave timing register) */ +	master_data |= 0x4000;  	pci_write_config_word(dev, master_port, master_data);  	if (is_slave)  		pci_write_config_byte(dev, slave_port, slave_data); @@ -787,6 +641,22 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)  }  /** + *	piix_set_piomode - Initialize host controller PATA PIO timings + *	@ap: Port whose timings we are configuring + *	@adev: Drive in question + * + *	Set PIO mode for device, in host controller PCI config space. + * + *	LOCKING: + *	None (inherited from caller). + */ + +static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) +{ +	piix_set_timings(ap, adev, adev->pio_mode - XFER_PIO_0); +} + +/**   *	do_pata_set_dmamode - Initialize host controller PATA PIO timings   *	@ap: Port whose timings we are configuring   *	@adev: Drive in question @@ -802,31 +672,20 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in  {  	struct pci_dev *dev	= to_pci_dev(ap->host->dev);  	unsigned long flags; -	u8 master_port		= ap->port_no ? 0x42 : 0x40; -	u16 master_data;  	u8 speed		= adev->dma_mode;  	int devid		= adev->devno + 2 * ap->port_no;  	u8 udma_enable		= 0; -	static const	 /* ISP  RTC */ -	u8 timings[][2]	= { { 0, 0 }, -			    { 0, 0 }, -			    { 1, 0 }, -			    { 2, 1 }, -			    { 2, 3 }, }; - -	spin_lock_irqsave(&piix_lock, flags); - -	pci_read_config_word(dev, master_port, &master_data); -	if (ap->udma_mask) -		pci_read_config_byte(dev, 0x48, &udma_enable); -  	if (speed >= XFER_UDMA_0) { -		unsigned int udma = adev->dma_mode - XFER_UDMA_0; +		unsigned int udma = speed - XFER_UDMA_0;  		u16 udma_timing;  		u16 ideconf;  		int u_clock, u_speed; +		spin_lock_irqsave(&piix_lock, flags); + +		pci_read_config_byte(dev, 0x48, &udma_enable); +  		/*  		 * UDMA is handled by a combination of clock switching and  		 * selection of dividers @@ -859,56 +718,21 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in  			   performance (WR_PingPong_En) */  			pci_write_config_word(dev, 0x54, ideconf);  		} + +		pci_write_config_byte(dev, 0x48, udma_enable); + +		spin_unlock_irqrestore(&piix_lock, flags);  	} else { -		/* -		 * MWDMA is driven by the PIO timings. We must also enable -		 * IORDY unconditionally along with TIME1. PPE has already -		 * been set when the PIO timing was set. -		 */ -		unsigned int mwdma	= adev->dma_mode - XFER_MW_DMA_0; -		unsigned int control; -		u8 slave_data; +		/* MWDMA is driven by the PIO timings. */ +		unsigned int mwdma = speed - XFER_MW_DMA_0;  		const unsigned int needed_pio[3] = {  			XFER_PIO_0, XFER_PIO_3, XFER_PIO_4  		};  		int pio = needed_pio[mwdma] - XFER_PIO_0; -		control = 3;	/* IORDY|TIME1 */ - -		/* If the drive MWDMA is faster than it can do PIO then -		   we must force PIO into PIO0 */ - -		if (adev->pio_mode < needed_pio[mwdma]) -			/* Enable DMA timing only */ -			control |= 8;	/* PIO cycles in PIO0 */ - -		if (adev->devno) {	/* Slave */ -			master_data &= 0xFF4F;  /* Mask out IORDY|TIME1|DMAONLY */ -			master_data |= control << 4; -			pci_read_config_byte(dev, 0x44, &slave_data); -			slave_data &= (ap->port_no ? 0x0f : 0xf0); -			/* Load the matching timing */ -			slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); -			pci_write_config_byte(dev, 0x44, slave_data); -		} else { 	/* Master */ -			master_data &= 0xCCF4;	/* Mask out IORDY|TIME1|DMAONLY -						   and master timing bits */ -			master_data |= control; -			master_data |= -				(timings[pio][0] << 12) | -				(timings[pio][1] << 8); -		} - -		if (ap->udma_mask) -			udma_enable &= ~(1 << devid); - -		pci_write_config_word(dev, master_port, master_data); +		/* XFER_PIO_0 is never used currently */ +		piix_set_timings(ap, adev, pio);  	} -	/* Don't scribble on 0x48 if the controller does not support UDMA */ -	if (ap->udma_mask) -		pci_write_config_byte(dev, 0x48, udma_enable); - -	spin_unlock_irqrestore(&piix_lock, flags);  }  /** @@ -1006,7 +830,7 @@ static bool piix_irq_check(struct ata_port *ap)  	return ap->ops->bmdma_status(ap) & ATA_DMA_INTR;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int piix_broken_suspend(void)  {  	static const struct dmi_system_id sysids[] = { @@ -1116,6 +940,13 @@ static int piix_broken_suspend(void)  			},  		},  		{ +			.ident = "Satellite Pro A120", +			.matches = { +				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), +				DMI_MATCH(DMI_PRODUCT_NAME, "Satellite Pro A120"), +			}, +		}, +		{  			.ident = "Portege M500",  			.matches = {  				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -1164,7 +995,7 @@ static int piix_broken_suspend(void)  static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	unsigned long flags;  	int rc = 0; @@ -1199,7 +1030,7 @@ static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)  static int piix_pci_device_resume(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	unsigned long flags;  	int rc; @@ -1217,8 +1048,9 @@ static int piix_pci_device_resume(struct pci_dev *pdev)  		 */  		rc = pci_reenable_device(pdev);  		if (rc) -			dev_printk(KERN_ERR, &pdev->dev, "failed to enable " -				   "device after resume (%d)\n", rc); +			dev_err(&pdev->dev, +				"failed to enable device after resume (%d)\n", +				rc);  	} else  		rc = ata_pci_device_do_resume(pdev); @@ -1234,6 +1066,213 @@ static u8 piix_vmw_bmdma_status(struct ata_port *ap)  	return ata_bmdma_status(ap) & ~ATA_DMA_ERR;  } +static struct scsi_host_template piix_sht = { +	ATA_BMDMA_SHT(DRV_NAME), +}; + +static struct ata_port_operations piix_sata_ops = { +	.inherits		= &ata_bmdma32_port_ops, +	.sff_irq_check		= piix_irq_check, +	.port_start		= piix_port_start, +}; + +static struct ata_port_operations piix_pata_ops = { +	.inherits		= &piix_sata_ops, +	.cable_detect		= ata_cable_40wire, +	.set_piomode		= piix_set_piomode, +	.set_dmamode		= piix_set_dmamode, +	.prereset		= piix_pata_prereset, +}; + +static struct ata_port_operations piix_vmw_ops = { +	.inherits		= &piix_pata_ops, +	.bmdma_status		= piix_vmw_bmdma_status, +}; + +static struct ata_port_operations ich_pata_ops = { +	.inherits		= &piix_pata_ops, +	.cable_detect		= ich_pata_cable_detect, +	.set_dmamode		= ich_set_dmamode, +}; + +static struct device_attribute *piix_sidpr_shost_attrs[] = { +	&dev_attr_link_power_management_policy, +	NULL +}; + +static struct scsi_host_template piix_sidpr_sht = { +	ATA_BMDMA_SHT(DRV_NAME), +	.shost_attrs		= piix_sidpr_shost_attrs, +}; + +static struct ata_port_operations piix_sidpr_sata_ops = { +	.inherits		= &piix_sata_ops, +	.hardreset		= sata_std_hardreset, +	.scr_read		= piix_sidpr_scr_read, +	.scr_write		= piix_sidpr_scr_write, +	.set_lpm		= piix_sidpr_set_lpm, +}; + +static struct ata_port_info piix_port_info[] = { +	[piix_pata_mwdma] =	/* PIIX3 MWDMA only */ +	{ +		.flags		= PIIX_PATA_FLAGS, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ +		.port_ops	= &piix_pata_ops, +	}, + +	[piix_pata_33] =	/* PIIX4 at 33MHz */ +	{ +		.flags		= PIIX_PATA_FLAGS, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ +		.udma_mask	= ATA_UDMA2, +		.port_ops	= &piix_pata_ops, +	}, + +	[ich_pata_33] =		/* ICH0 - ICH at 33Mhz*/ +	{ +		.flags		= PIIX_PATA_FLAGS, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok  */ +		.udma_mask	= ATA_UDMA2, +		.port_ops	= &ich_pata_ops, +	}, + +	[ich_pata_66] =		/* ICH controllers up to 66MHz */ +	{ +		.flags		= PIIX_PATA_FLAGS, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */ +		.udma_mask	= ATA_UDMA4, +		.port_ops	= &ich_pata_ops, +	}, + +	[ich_pata_100] = +	{ +		.flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA12_ONLY, +		.udma_mask	= ATA_UDMA5, +		.port_ops	= &ich_pata_ops, +	}, + +	[ich_pata_100_nomwdma1] = +	{ +		.flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA2_ONLY, +		.udma_mask	= ATA_UDMA5, +		.port_ops	= &ich_pata_ops, +	}, + +	[ich5_sata] = +	{ +		.flags		= PIIX_SATA_FLAGS, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA2, +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &piix_sata_ops, +	}, + +	[ich6_sata] = +	{ +		.flags		= PIIX_SATA_FLAGS, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA2, +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &piix_sata_ops, +	}, + +	[ich6m_sata] = +	{ +		.flags		= PIIX_SATA_FLAGS, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA2, +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &piix_sata_ops, +	}, + +	[ich8_sata] = +	{ +		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA2, +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &piix_sata_ops, +	}, + +	[ich8_2port_sata] = +	{ +		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA2, +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &piix_sata_ops, +	}, + +	[tolapai_sata] = +	{ +		.flags		= PIIX_SATA_FLAGS, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA2, +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &piix_sata_ops, +	}, + +	[ich8m_apple_sata] = +	{ +		.flags		= PIIX_SATA_FLAGS, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA2, +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &piix_sata_ops, +	}, + +	[piix_pata_vmw] = +	{ +		.flags		= PIIX_PATA_FLAGS, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ +		.udma_mask	= ATA_UDMA2, +		.port_ops	= &piix_vmw_ops, +	}, + +	/* +	 * some Sandybridge chipsets have broken 32 mode up to now, +	 * see https://bugzilla.kernel.org/show_bug.cgi?id=40592 +	 */ +	[ich8_sata_snb] = +	{ +		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA2, +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &piix_sata_ops, +	}, + +	[ich8_2port_sata_snb] = +	{ +		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR +					| PIIX_FLAG_PIO16, +		.pio_mask	= ATA_PIO4, +		.mwdma_mask	= ATA_MWDMA2, +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &piix_sata_ops, +	}, + +	[ich8_2port_sata_byt] = +	{ +		.flags          = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16, +		.pio_mask       = ATA_PIO4, +		.mwdma_mask     = ATA_MWDMA2, +		.udma_mask      = ATA_UDMA6, +		.port_ops       = &piix_sata_ops, +	}, + +}; +  #define AHCI_PCI_BAR 5  #define AHCI_GLOBAL_CTL 0x04  #define AHCI_ENABLE (1 << 31) @@ -1277,7 +1316,7 @@ static int piix_disable_ahci(struct pci_dev *pdev)   *	they are found return an error code so we can turn off DMA   */ -static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) +static int piix_check_450nx_errata(struct pci_dev *ata_dev)  {  	struct pci_dev *pdev = NULL;  	u16 cfg; @@ -1295,14 +1334,16 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)  			no_piix_dma = 2;  	}  	if (no_piix_dma) -		dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n"); -	if (no_piix_dma == 2) -		dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n"); +		dev_warn(&ata_dev->dev, +			 "450NX errata present, disabling IDE DMA%s\n", +			 no_piix_dma == 2 ? " - a BIOS update may resolve this" +			 : ""); +  	return no_piix_dma;  } -static void __devinit piix_init_pcs(struct ata_host *host, -				    const struct piix_map_db *map_db) +static void piix_init_pcs(struct ata_host *host, +			  const struct piix_map_db *map_db)  {  	struct pci_dev *pdev = to_pci_dev(host->dev);  	u16 pcs, new_pcs; @@ -1318,49 +1359,49 @@ static void __devinit piix_init_pcs(struct ata_host *host,  	}  } -static const int *__devinit piix_init_sata_map(struct pci_dev *pdev, -					       struct ata_port_info *pinfo, -					       const struct piix_map_db *map_db) +static const int *piix_init_sata_map(struct pci_dev *pdev, +				     struct ata_port_info *pinfo, +				     const struct piix_map_db *map_db)  {  	const int *map;  	int i, invalid_map = 0;  	u8 map_value; +	char buf[32]; +	char *p = buf, *end = buf + sizeof(buf);  	pci_read_config_byte(pdev, ICH5_PMR, &map_value);  	map = map_db->map[map_value & map_db->mask]; -	dev_printk(KERN_INFO, &pdev->dev, "MAP [");  	for (i = 0; i < 4; i++) {  		switch (map[i]) {  		case RV:  			invalid_map = 1; -			printk(" XX"); +			p += scnprintf(p, end - p, " XX");  			break;  		case NA: -			printk(" --"); +			p += scnprintf(p, end - p, " --");  			break;  		case IDE:  			WARN_ON((i & 1) || map[i + 1] != IDE);  			pinfo[i / 2] = piix_port_info[ich_pata_100];  			i++; -			printk(" IDE IDE"); +			p += scnprintf(p, end - p, " IDE IDE");  			break;  		default: -			printk(" P%d", map[i]); +			p += scnprintf(p, end - p, " P%d", map[i]);  			if (i & 1)  				pinfo[i / 2].flags |= ATA_FLAG_SLAVE_POSS;  			break;  		}  	} -	printk(" ]\n"); +	dev_info(&pdev->dev, "MAP [%s ]\n", buf);  	if (invalid_map) -		dev_printk(KERN_ERR, &pdev->dev, -			   "invalid MAP value %u\n", map_value); +		dev_err(&pdev->dev, "invalid MAP value %u\n", map_value);  	return map;  } @@ -1390,15 +1431,15 @@ static bool piix_no_sidpr(struct ata_host *host)  	if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 &&  	    pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG &&  	    pdev->subsystem_device == 0xb049) { -		dev_printk(KERN_WARNING, host->dev, -			   "Samsung DB-P70 detected, disabling SIDPR\n"); +		dev_warn(host->dev, +			 "Samsung DB-P70 detected, disabling SIDPR\n");  		return true;  	}  	return false;  } -static int __devinit piix_init_sidpr(struct ata_host *host) +static int piix_init_sidpr(struct ata_host *host)  {  	struct pci_dev *pdev = to_pci_dev(host->dev);  	struct piix_host_priv *hpriv = host->private_data; @@ -1443,8 +1484,8 @@ static int __devinit piix_init_sidpr(struct ata_host *host)  		piix_sidpr_scr_read(link0, SCR_CONTROL, &scontrol);  		if ((scontrol & 0xf00) != 0x300) { -			dev_printk(KERN_INFO, host->dev, "SCR access via " -				   "SIDPR is available but doesn't work\n"); +			dev_info(host->dev, +				 "SCR access via SIDPR is available but doesn't work\n");  			return 0;  		}  	} @@ -1493,8 +1534,7 @@ static void piix_iocfg_bit18_quirk(struct ata_host *host)  	 * affected systems.  	 */  	if (hpriv->saved_iocfg & (1 << 18)) { -		dev_printk(KERN_INFO, &pdev->dev, -			   "applying IOCFG bit18 quirk\n"); +		dev_info(&pdev->dev, "applying IOCFG bit18 quirk\n");  		pci_write_config_dword(pdev, PIIX_IOCFG,  				       hpriv->saved_iocfg & ~(1 << 18));  	} @@ -1535,6 +1575,62 @@ static bool piix_broken_system_poweroff(struct pci_dev *pdev)  	return false;  } +static int prefer_ms_hyperv = 1; +module_param(prefer_ms_hyperv, int, 0); +MODULE_PARM_DESC(prefer_ms_hyperv, +	"Prefer Hyper-V paravirtualization drivers instead of ATA, " +	"0 - Use ATA drivers, " +	"1 (Default) - Use the paravirtualization drivers."); + +static void piix_ignore_devices_quirk(struct ata_host *host) +{ +#if IS_ENABLED(CONFIG_HYPERV_STORAGE) +	static const struct dmi_system_id ignore_hyperv[] = { +		{ +			/* On Hyper-V hypervisors the disks are exposed on +			 * both the emulated SATA controller and on the +			 * paravirtualised drivers.  The CD/DVD devices +			 * are only exposed on the emulated controller. +			 * Request we ignore ATA devices on this host. +			 */ +			.ident = "Hyper-V Virtual Machine", +			.matches = { +				DMI_MATCH(DMI_SYS_VENDOR, +						"Microsoft Corporation"), +				DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), +			}, +		}, +		{ }	/* terminate list */ +	}; +	static const struct dmi_system_id allow_virtual_pc[] = { +		{ +			/* In MS Virtual PC guests the DMI ident is nearly +			 * identical to a Hyper-V guest. One difference is the +			 * product version which is used here to identify +			 * a Virtual PC guest. This entry allows ata_piix to +			 * drive the emulated hardware. +			 */ +			.ident = "MS Virtual PC 2007", +			.matches = { +				DMI_MATCH(DMI_SYS_VENDOR, +						"Microsoft Corporation"), +				DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), +				DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"), +			}, +		}, +		{ }	/* terminate list */ +	}; +	const struct dmi_system_id *ignore = dmi_first_match(ignore_hyperv); +	const struct dmi_system_id *allow = dmi_first_match(allow_virtual_pc); + +	if (ignore && !allow && prefer_ms_hyperv) { +		host->flags |= ATA_HOST_IGNORE_ATA; +		dev_info(host->dev, "%s detected, ATA device ignore set\n", +			ignore->ident); +	} +#endif +} +  /**   *	piix_init_one - Register PIIX ATA PCI device with kernel services   *	@pdev: PCI device to register @@ -1550,10 +1646,8 @@ static bool piix_broken_system_poweroff(struct pci_dev *pdev)   *	Zero on success, or -ERRNO value.   */ -static int __devinit piix_init_one(struct pci_dev *pdev, -				   const struct pci_device_id *ent) +static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	struct device *dev = &pdev->dev;  	struct ata_port_info port_info[2];  	const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] }; @@ -1563,9 +1657,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,  	struct piix_host_priv *hpriv;  	int rc; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* no hotplugging support for later devices (FIXME) */  	if (!in_module_init && ent->driver_data >= ich5_sata) @@ -1653,13 +1745,16 @@ static int __devinit piix_init_one(struct pci_dev *pdev,  	}  	host->flags |= ATA_HOST_PARALLEL_SCAN; +	/* Allow hosts to specify device types to ignore when scanning. */ +	piix_ignore_devices_quirk(host); +  	pci_set_master(pdev);  	return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);  }  static void piix_remove_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	struct piix_host_priv *hpriv = host->private_data;  	pci_write_config_dword(pdev, PIIX_IOCFG, hpriv->saved_iocfg); @@ -1667,6 +1762,17 @@ static void piix_remove_one(struct pci_dev *pdev)  	ata_pci_remove_one(pdev);  } +static struct pci_driver piix_pci_driver = { +	.name			= DRV_NAME, +	.id_table		= piix_pci_tbl, +	.probe			= piix_init_one, +	.remove			= piix_remove_one, +#ifdef CONFIG_PM_SLEEP +	.suspend		= piix_pci_device_suspend, +	.resume			= piix_pci_device_resume, +#endif +}; +  static int __init piix_init(void)  {  	int rc; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index ebc08d65b3d..d72ce047030 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1,7 +1,7 @@  /*   *  libahci.c - Common AHCI SATA low-level routines   * - *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> + *  Maintained by:  Tejun Heo <tj@kernel.org>   *    		    Please ALWAYS copy linux-ide@vger.kernel.org   *		    on emails.   * @@ -35,7 +35,6 @@  #include <linux/kernel.h>  #include <linux/gfp.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -45,6 +44,7 @@  #include <scsi/scsi_cmnd.h>  #include <linux/libata.h>  #include "ahci.h" +#include "libata.h"  static int ahci_skip_host_reset;  int ahci_ignore_sss; @@ -68,7 +68,6 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,  static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);  static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); -static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);  static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);  static int ahci_port_start(struct ata_port *ap);  static void ahci_port_stop(struct ata_port *ap); @@ -76,21 +75,20 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc);  static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc);  static void ahci_freeze(struct ata_port *ap);  static void ahci_thaw(struct ata_port *ap); +static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep);  static void ahci_enable_fbs(struct ata_port *ap);  static void ahci_disable_fbs(struct ata_port *ap);  static void ahci_pmp_attach(struct ata_port *ap);  static void ahci_pmp_detach(struct ata_port *ap);  static int ahci_softreset(struct ata_link *link, unsigned int *class,  			  unsigned long deadline); +static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class, +			  unsigned long deadline);  static int ahci_hardreset(struct ata_link *link, unsigned int *class,  			  unsigned long deadline);  static void ahci_postreset(struct ata_link *link, unsigned int *class); -static void ahci_error_handler(struct ata_port *ap);  static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); -static int ahci_port_resume(struct ata_port *ap);  static void ahci_dev_config(struct ata_device *dev); -static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, -			       u32 opts);  #ifdef CONFIG_PM  static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);  #endif @@ -112,6 +110,8 @@ static ssize_t ahci_read_em_buffer(struct device *dev,  static ssize_t ahci_store_em_buffer(struct device *dev,  				    struct device_attribute *attr,  				    const char *buf, size_t size); +static ssize_t ahci_show_em_supported(struct device *dev, +				      struct device_attribute *attr, char *buf);  static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);  static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL); @@ -119,6 +119,7 @@ static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);  static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);  static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,  		   ahci_read_em_buffer, ahci_store_em_buffer); +static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL);  struct device_attribute *ahci_shost_attrs[] = {  	&dev_attr_link_power_management_policy, @@ -129,6 +130,7 @@ struct device_attribute *ahci_shost_attrs[] = {  	&dev_attr_ahci_host_version,  	&dev_attr_ahci_port_cmd,  	&dev_attr_em_buffer, +	&dev_attr_em_message_supported,  	NULL  };  EXPORT_SYMBOL_GPL(ahci_shost_attrs); @@ -168,6 +170,7 @@ struct ata_port_operations ahci_ops = {  	.em_store		= ahci_led_store,  	.sw_activity_show	= ahci_activity_show,  	.sw_activity_store	= ahci_activity_store, +	.transmit_led_message	= ahci_transmit_led_message,  #ifdef CONFIG_PM  	.port_suspend		= ahci_port_suspend,  	.port_resume		= ahci_port_resume, @@ -177,13 +180,24 @@ struct ata_port_operations ahci_ops = {  };  EXPORT_SYMBOL_GPL(ahci_ops); -int ahci_em_messages = 1; +struct ata_port_operations ahci_pmp_retry_srst_ops = { +	.inherits		= &ahci_ops, +	.softreset		= ahci_pmp_retry_softreset, +}; +EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops); + +static bool ahci_em_messages __read_mostly = true;  EXPORT_SYMBOL_GPL(ahci_em_messages); -module_param(ahci_em_messages, int, 0444); +module_param(ahci_em_messages, bool, 0444);  /* add other LED protocol types when they become supported */  MODULE_PARM_DESC(ahci_em_messages,  	"AHCI Enclosure Management Message control (0 = off, 1 = on)"); +/* device sleep idle timeout in ms */ +static int devslp_idle_timeout __read_mostly = 1000; +module_param(devslp_idle_timeout, int, 0644); +MODULE_PARM_DESC(devslp_idle_timeout, "device sleep idle timeout"); +  static void ahci_enable_ahci(void __iomem *mmio)  {  	int i; @@ -285,10 +299,10 @@ static ssize_t ahci_read_em_buffer(struct device *dev,  	/* the count should not be larger than PAGE_SIZE */  	if (count > PAGE_SIZE) {  		if (printk_ratelimit()) -			ata_port_printk(ap, KERN_WARNING, -					"EM read buffer size too large: " -					"buffer size %u, page size %lu\n", -					hpriv->em_buf_sz, PAGE_SIZE); +			ata_port_warn(ap, +				      "EM read buffer size too large: " +				      "buffer size %u, page size %lu\n", +				      hpriv->em_buf_sz, PAGE_SIZE);  		count = PAGE_SIZE;  	} @@ -346,6 +360,24 @@ static ssize_t ahci_store_em_buffer(struct device *dev,  	return size;  } +static ssize_t ahci_show_em_supported(struct device *dev, +				      struct device_attribute *attr, char *buf) +{ +	struct Scsi_Host *shost = class_to_shost(dev); +	struct ata_port *ap = ata_shost_to_port(shost); +	struct ahci_host_priv *hpriv = ap->host->private_data; +	void __iomem *mmio = hpriv->mmio; +	u32 em_ctl; + +	em_ctl = readl(mmio + HOST_EM_CTL); + +	return sprintf(buf, "%s%s%s%s\n", +		       em_ctl & EM_CTL_LED ? "led " : "", +		       em_ctl & EM_CTL_SAFTE ? "saf-te " : "", +		       em_ctl & EM_CTL_SES ? "ses-2 " : "", +		       em_ctl & EM_CTL_SGPIO ? "sgpio " : ""); +} +  /**   *	ahci_save_initial_config - Save and fixup initial config values   *	@dev: target AHCI device @@ -360,6 +392,9 @@ static ssize_t ahci_store_em_buffer(struct device *dev,   *   *	If inconsistent, config values are fixed up by this function.   * + *	If it is not set already this function sets hpriv->start_engine to + *	ahci_start_engine. + *   *	LOCKING:   *	None.   */ @@ -391,51 +426,58 @@ void ahci_save_initial_config(struct device *dev,  	/* some chips have errata preventing 64bit use */  	if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) { -		dev_printk(KERN_INFO, dev, -			   "controller can't do 64bit DMA, forcing 32bit\n"); +		dev_info(dev, "controller can't do 64bit DMA, forcing 32bit\n");  		cap &= ~HOST_CAP_64;  	}  	if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) { -		dev_printk(KERN_INFO, dev, -			   "controller can't do NCQ, turning off CAP_NCQ\n"); +		dev_info(dev, "controller can't do NCQ, turning off CAP_NCQ\n");  		cap &= ~HOST_CAP_NCQ;  	}  	if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) { -		dev_printk(KERN_INFO, dev, -			   "controller can do NCQ, turning on CAP_NCQ\n"); +		dev_info(dev, "controller can do NCQ, turning on CAP_NCQ\n");  		cap |= HOST_CAP_NCQ;  	}  	if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) { -		dev_printk(KERN_INFO, dev, -			   "controller can't do PMP, turning off CAP_PMP\n"); +		dev_info(dev, "controller can't do PMP, turning off CAP_PMP\n");  		cap &= ~HOST_CAP_PMP;  	}  	if ((cap & HOST_CAP_SNTF) && (hpriv->flags & AHCI_HFLAG_NO_SNTF)) { -		dev_printk(KERN_INFO, dev, -			   "controller can't do SNTF, turning off CAP_SNTF\n"); +		dev_info(dev, +			 "controller can't do SNTF, turning off CAP_SNTF\n");  		cap &= ~HOST_CAP_SNTF;  	} +	if ((cap2 & HOST_CAP2_SDS) && (hpriv->flags & AHCI_HFLAG_NO_DEVSLP)) { +		dev_info(dev, +			 "controller can't do DEVSLP, turning off\n"); +		cap2 &= ~HOST_CAP2_SDS; +		cap2 &= ~HOST_CAP2_SADM; +	} +  	if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) { -		dev_printk(KERN_INFO, dev, -			   "controller can do FBS, turning on CAP_FBS\n"); +		dev_info(dev, "controller can do FBS, turning on CAP_FBS\n");  		cap |= HOST_CAP_FBS;  	} +	if ((cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_NO_FBS)) { +		dev_info(dev, "controller can't do FBS, turning off CAP_FBS\n"); +		cap &= ~HOST_CAP_FBS; +	} +  	if (force_port_map && port_map != force_port_map) { -		dev_printk(KERN_INFO, dev, "forcing port_map 0x%x -> 0x%x\n", -			   port_map, force_port_map); +		dev_info(dev, "forcing port_map 0x%x -> 0x%x\n", +			 port_map, force_port_map);  		port_map = force_port_map;  	}  	if (mask_port_map) { -		dev_printk(KERN_ERR, dev, "masking port_map 0x%x -> 0x%x\n", -			   port_map, -			   port_map & mask_port_map); +		dev_warn(dev, "masking port_map 0x%x -> 0x%x\n", +			port_map, +			port_map & mask_port_map);  		port_map &= mask_port_map;  	} @@ -451,10 +493,9 @@ void ahci_save_initial_config(struct device *dev,  		 * port_map and let it be generated from n_ports.  		 */  		if (map_ports > ahci_nr_ports(cap)) { -			dev_printk(KERN_WARNING, dev, -				   "implemented port map (0x%x) contains more " -				   "ports than nr_ports (%u), using nr_ports\n", -				   port_map, ahci_nr_ports(cap)); +			dev_warn(dev, +				 "implemented port map (0x%x) contains more ports than nr_ports (%u), using nr_ports\n", +				 port_map, ahci_nr_ports(cap));  			port_map = 0;  		}  	} @@ -462,8 +503,7 @@ void ahci_save_initial_config(struct device *dev,  	/* fabricate port_map from cap.nr_ports */  	if (!port_map) {  		port_map = (1 << ahci_nr_ports(cap)) - 1; -		dev_printk(KERN_WARNING, dev, -			   "forcing PORTS_IMPL to 0x%x\n", port_map); +		dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);  		/* write the fixed up value to the PI register */  		hpriv->saved_port_map = port_map; @@ -473,6 +513,9 @@ void ahci_save_initial_config(struct device *dev,  	hpriv->cap = cap;  	hpriv->cap2 = cap2;  	hpriv->port_map = port_map; + +	if (!hpriv->start_engine) +		hpriv->start_engine = ahci_start_engine;  }  EXPORT_SYMBOL_GPL(ahci_save_initial_config); @@ -576,7 +619,7 @@ int ahci_stop_engine(struct ata_port *ap)  }  EXPORT_SYMBOL_GPL(ahci_stop_engine); -static void ahci_start_fis_rx(struct ata_port *ap) +void ahci_start_fis_rx(struct ata_port *ap)  {  	void __iomem *port_mmio = ahci_port_base(ap);  	struct ahci_host_priv *hpriv = ap->host->private_data; @@ -602,6 +645,7 @@ static void ahci_start_fis_rx(struct ata_port *ap)  	/* flush */  	readl(port_mmio + PORT_CMD);  } +EXPORT_SYMBOL_GPL(ahci_start_fis_rx);  static int ahci_stop_fis_rx(struct ata_port *ap)  { @@ -682,6 +726,16 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,  		}  	} +	/* set aggressive device sleep */ +	if ((hpriv->cap2 & HOST_CAP2_SDS) && +	    (hpriv->cap2 & HOST_CAP2_SADM) && +	    (link->device->flags & ATA_DFLAG_DEVSLP)) { +		if (policy == ATA_LPM_MIN_POWER) +			ahci_set_aggressive_devslp(ap, true); +		else +			ahci_set_aggressive_devslp(ap, false); +	} +  	if (policy == ATA_LPM_MAX_POWER) {  		sata_link_scr_lpm(link, policy, false); @@ -717,6 +771,7 @@ static void ahci_power_down(struct ata_port *ap)  static void ahci_start_port(struct ata_port *ap)  { +	struct ahci_host_priv *hpriv = ap->host->private_data;  	struct ahci_port_priv *pp = ap->private_data;  	struct ata_link *link;  	struct ahci_em_priv *emp; @@ -727,7 +782,8 @@ static void ahci_start_port(struct ata_port *ap)  	ahci_start_fis_rx(ap);  	/* enable DMA */ -	ahci_start_engine(ap); +	if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE)) +		hpriv->start_engine(ap);  	/* turn on LEDs */  	if (ap->flags & ATA_FLAG_EM) { @@ -736,11 +792,19 @@ static void ahci_start_port(struct ata_port *ap)  			/* EM Transmit bit maybe busy during init */  			for (i = 0; i < EM_MAX_RETRY; i++) { -				rc = ahci_transmit_led_message(ap, +				rc = ap->ops->transmit_led_message(ap,  							       emp->led_state,  							       4); +				/* +				 * If busy, give a breather but do not +				 * release EH ownership by using msleep() +				 * instead of ata_msleep().  EM Transmit +				 * bit is busy for the whole host and +				 * releasing ownership will cause other +				 * ports to fail the same way. +				 */  				if (rc == -EBUSY) -					ata_msleep(ap, 1); +					msleep(1);  				else  					break;  			} @@ -803,8 +867,8 @@ int ahci_reset_controller(struct ata_host *host)  					HOST_RESET, 10, 1000);  		if (tmp & HOST_RESET) { -			dev_printk(KERN_ERR, host->dev, -				   "controller reset failed (0x%x)\n", tmp); +			dev_err(host->dev, "controller reset failed (0x%x)\n", +				tmp);  			return -EIO;  		} @@ -816,8 +880,7 @@ int ahci_reset_controller(struct ata_host *host)  		 */  		ahci_restore_initial_config(host);  	} else -		dev_printk(KERN_INFO, host->dev, -			   "skipping global host reset\n"); +		dev_info(host->dev, "skipping global host reset\n");  	return 0;  } @@ -878,7 +941,7 @@ static void ahci_sw_activity_blink(unsigned long arg)  			led_message |= (1 << 16);  	}  	spin_unlock_irqrestore(ap->lock, flags); -	ahci_transmit_led_message(ap, led_message, 4); +	ap->ops->transmit_led_message(ap, led_message, 4);  }  static void ahci_init_sw_activity(struct ata_link *link) @@ -986,12 +1049,13 @@ static ssize_t ahci_led_show(struct ata_port *ap, char *buf)  static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,  				size_t size)  { -	int state; +	unsigned int state;  	int pmp;  	struct ahci_port_priv *pp = ap->private_data;  	struct ahci_em_priv *emp; -	state = simple_strtoul(buf, NULL, 0); +	if (kstrtouint(buf, 0, &state) < 0) +		return -EINVAL;  	/* get the slot number from the message */  	pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; @@ -1007,7 +1071,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,  	if (emp->blink_policy)  		state &= ~EM_MSG_LED_VALUE_ACTIVITY; -	return ahci_transmit_led_message(ap, state, size); +	return ap->ops->transmit_led_message(ap, state, size);  }  static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val) @@ -1026,7 +1090,7 @@ static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)  		/* set the LED to OFF */  		port_led_state &= EM_MSG_LED_VALUE_OFF;  		port_led_state |= (ap->port_no | (link->pmp << 8)); -		ahci_transmit_led_message(ap, port_led_state, 4); +		ap->ops->transmit_led_message(ap, port_led_state, 4);  	} else {  		link->flags |= ATA_LFLAG_SW_ACTIVITY;  		if (val == BLINK_OFF) { @@ -1034,7 +1098,7 @@ static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)  			port_led_state &= EM_MSG_LED_VALUE_OFF;  			port_led_state |= (ap->port_no | (link->pmp << 8));  			port_led_state |= EM_MSG_LED_VALUE_ON; /* check this */ -			ahci_transmit_led_message(ap, port_led_state, 4); +			ap->ops->transmit_led_message(ap, port_led_state, 4);  		}  	}  	emp->blink_policy = val; @@ -1113,12 +1177,12 @@ static void ahci_dev_config(struct ata_device *dev)  	if (hpriv->flags & AHCI_HFLAG_SECT255) {  		dev->max_sectors = 255; -		ata_dev_printk(dev, KERN_INFO, -			       "SB600 AHCI: limiting to 255 sectors per cmd\n"); +		ata_dev_info(dev, +			     "SB600 AHCI: limiting to 255 sectors per cmd\n");  	}  } -static unsigned int ahci_dev_classify(struct ata_port *ap) +unsigned int ahci_dev_classify(struct ata_port *ap)  {  	void __iomem *port_mmio = ahci_port_base(ap);  	struct ata_taskfile tf; @@ -1132,9 +1196,10 @@ static unsigned int ahci_dev_classify(struct ata_port *ap)  	return ata_dev_classify(&tf);  } +EXPORT_SYMBOL_GPL(ahci_dev_classify); -static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, -			       u32 opts) +void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, +			u32 opts)  {  	dma_addr_t cmd_tbl_dma; @@ -1145,6 +1210,7 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,  	pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);  	pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);  } +EXPORT_SYMBOL_GPL(ahci_fill_cmd_slot);  int ahci_kick_engine(struct ata_port *ap)  { @@ -1186,7 +1252,7 @@ int ahci_kick_engine(struct ata_port *ap)  	/* restart engine */   out_restart: -	ahci_start_engine(ap); +	hpriv->start_engine(ap);  	return rc;  }  EXPORT_SYMBOL_GPL(ahci_kick_engine); @@ -1227,9 +1293,11 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,  {  	struct ata_port *ap = link->ap;  	struct ahci_host_priv *hpriv = ap->host->private_data; +	struct ahci_port_priv *pp = ap->private_data;  	const char *reason = NULL;  	unsigned long now, msecs;  	struct ata_taskfile tf; +	bool fbs_disabled = false;  	int rc;  	DPRINTK("ENTER\n"); @@ -1237,8 +1305,17 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,  	/* prepare for SRST (AHCI-1.1 10.4.1) */  	rc = ahci_kick_engine(ap);  	if (rc && rc != -EOPNOTSUPP) -		ata_link_printk(link, KERN_WARNING, -				"failed to reset engine (errno=%d)\n", rc); +		ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc); + +	/* +	 * According to AHCI-1.2 9.3.9: if FBS is enable, software shall +	 * clear PxFBS.EN to '0' prior to issuing software reset to devices +	 * that is attached to port multiplier. +	 */ +	if (!ata_is_host_link(link) && pp->fbs_enabled) { +		ahci_disable_fbs(ap); +		fbs_disabled = true; +	}  	ata_tf_init(link->device, &tf); @@ -1271,8 +1348,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,  		 * be trusted.  Treat device readiness timeout as link  		 * offline.  		 */ -		ata_link_printk(link, KERN_INFO, -				"device not ready, treating as offline\n"); +		ata_link_info(link, "device not ready, treating as offline\n");  		*class = ATA_DEV_NONE;  	} else if (rc) {  		/* link occupied, -ENODEV too is an error */ @@ -1281,11 +1357,15 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,  	} else  		*class = ahci_dev_classify(ap); +	/* re-enable FBS if disabled before */ +	if (fbs_disabled) +		ahci_enable_fbs(ap); +  	DPRINTK("EXIT, class=%u\n", *class);  	return 0;   fail: -	ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason); +	ata_link_err(link, "softreset failed (%s)\n", reason);  	return rc;  } @@ -1309,12 +1389,62 @@ static int ahci_softreset(struct ata_link *link, unsigned int *class,  }  EXPORT_SYMBOL_GPL(ahci_do_softreset); +static int ahci_bad_pmp_check_ready(struct ata_link *link) +{ +	void __iomem *port_mmio = ahci_port_base(link->ap); +	u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; +	u32 irq_status = readl(port_mmio + PORT_IRQ_STAT); + +	/* +	 * There is no need to check TFDATA if BAD PMP is found due to HW bug, +	 * which can save timeout delay. +	 */ +	if (irq_status & PORT_IRQ_BAD_PMP) +		return -EIO; + +	return ata_check_ready(status); +} + +static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class, +				    unsigned long deadline) +{ +	struct ata_port *ap = link->ap; +	void __iomem *port_mmio = ahci_port_base(ap); +	int pmp = sata_srst_pmp(link); +	int rc; +	u32 irq_sts; + +	DPRINTK("ENTER\n"); + +	rc = ahci_do_softreset(link, class, pmp, deadline, +			       ahci_bad_pmp_check_ready); + +	/* +	 * Soft reset fails with IPMS set when PMP is enabled but +	 * SATA HDD/ODD is connected to SATA port, do soft reset +	 * again to port 0. +	 */ +	if (rc == -EIO) { +		irq_sts = readl(port_mmio + PORT_IRQ_STAT); +		if (irq_sts & PORT_IRQ_BAD_PMP) { +			ata_link_warn(link, +					"applying PMP SRST workaround " +					"and retrying\n"); +			rc = ahci_do_softreset(link, class, 0, deadline, +					       ahci_check_ready); +		} +	} + +	return rc; +} +  static int ahci_hardreset(struct ata_link *link, unsigned int *class,  			  unsigned long deadline)  {  	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);  	struct ata_port *ap = link->ap;  	struct ahci_port_priv *pp = ap->private_data; +	struct ahci_host_priv *hpriv = ap->host->private_data;  	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;  	struct ata_taskfile tf;  	bool online; @@ -1326,13 +1456,13 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,  	/* clear D2H reception area to properly wait for D2H FIS */  	ata_tf_init(link->device, &tf); -	tf.command = 0x80; +	tf.command = ATA_BUSY;  	ata_tf_to_fis(&tf, 0, 0, d2h_fis);  	rc = sata_link_hardreset(link, timing, deadline, &online,  				 ahci_check_ready); -	ahci_start_engine(ap); +	hpriv->start_engine(ap);  	if (online)  		*class = ahci_dev_classify(ap); @@ -1454,8 +1584,7 @@ static void ahci_fbs_dec_intr(struct ata_port *ap)  	}  	if (fbs & PORT_FBS_DEC) -		dev_printk(KERN_ERR, ap->host->dev, -			   "failed to clear device error\n"); +		dev_err(ap->host->dev, "failed to clear device error\n");  }  static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) @@ -1475,8 +1604,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)  		u32 fbs = readl(port_mmio + PORT_FBS);  		int pmp = fbs >> PORT_FBS_DWE_OFFSET; -		if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links) && -		    ata_link_online(&ap->pmp_link[pmp])) { +		if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links)) {  			link = &ap->pmp_link[pmp];  			fbs_need_dec = true;  		} @@ -1520,7 +1648,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)  	}  	if (irq_stat & PORT_IRQ_UNK_FIS) { -		u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK); +		u32 *unk = pp->rx_fis + RX_FIS_UNK;  		active_ehi->err_mask |= AC_ERR_HSM;  		active_ehi->action |= ATA_EH_RESET; @@ -1570,19 +1698,16 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)  		ata_port_abort(ap);  } -static void ahci_port_intr(struct ata_port *ap) +static void ahci_handle_port_interrupt(struct ata_port *ap, +				       void __iomem *port_mmio, u32 status)  { -	void __iomem *port_mmio = ahci_port_base(ap);  	struct ata_eh_info *ehi = &ap->link.eh_info;  	struct ahci_port_priv *pp = ap->private_data;  	struct ahci_host_priv *hpriv = ap->host->private_data;  	int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING); -	u32 status, qc_active = 0; +	u32 qc_active = 0;  	int rc; -	status = readl(port_mmio + PORT_IRQ_STAT); -	writel(status, port_mmio + PORT_IRQ_STAT); -  	/* ignore BAD_PMP while resetting */  	if (unlikely(resetting))  		status &= ~PORT_IRQ_BAD_PMP; @@ -1658,6 +1783,107 @@ static void ahci_port_intr(struct ata_port *ap)  	}  } +static void ahci_port_intr(struct ata_port *ap) +{ +	void __iomem *port_mmio = ahci_port_base(ap); +	u32 status; + +	status = readl(port_mmio + PORT_IRQ_STAT); +	writel(status, port_mmio + PORT_IRQ_STAT); + +	ahci_handle_port_interrupt(ap, port_mmio, status); +} + +irqreturn_t ahci_thread_fn(int irq, void *dev_instance) +{ +	struct ata_port *ap = dev_instance; +	struct ahci_port_priv *pp = ap->private_data; +	void __iomem *port_mmio = ahci_port_base(ap); +	unsigned long flags; +	u32 status; + +	spin_lock_irqsave(&ap->host->lock, flags); +	status = pp->intr_status; +	if (status) +		pp->intr_status = 0; +	spin_unlock_irqrestore(&ap->host->lock, flags); + +	spin_lock_bh(ap->lock); +	ahci_handle_port_interrupt(ap, port_mmio, status); +	spin_unlock_bh(ap->lock); + +	return IRQ_HANDLED; +} +EXPORT_SYMBOL_GPL(ahci_thread_fn); + +static void ahci_hw_port_interrupt(struct ata_port *ap) +{ +	void __iomem *port_mmio = ahci_port_base(ap); +	struct ahci_port_priv *pp = ap->private_data; +	u32 status; + +	status = readl(port_mmio + PORT_IRQ_STAT); +	writel(status, port_mmio + PORT_IRQ_STAT); + +	pp->intr_status |= status; +} + +irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance) +{ +	struct ata_port *ap_this = dev_instance; +	struct ahci_port_priv *pp = ap_this->private_data; +	struct ata_host *host = ap_this->host; +	struct ahci_host_priv *hpriv = host->private_data; +	void __iomem *mmio = hpriv->mmio; +	unsigned int i; +	u32 irq_stat, irq_masked; + +	VPRINTK("ENTER\n"); + +	spin_lock(&host->lock); + +	irq_stat = readl(mmio + HOST_IRQ_STAT); + +	if (!irq_stat) { +		u32 status = pp->intr_status; + +		spin_unlock(&host->lock); + +		VPRINTK("EXIT\n"); + +		return status ? IRQ_WAKE_THREAD : IRQ_NONE; +	} + +	irq_masked = irq_stat & hpriv->port_map; + +	for (i = 0; i < host->n_ports; i++) { +		struct ata_port *ap; + +		if (!(irq_masked & (1 << i))) +			continue; + +		ap = host->ports[i]; +		if (ap) { +			ahci_hw_port_interrupt(ap); +			VPRINTK("port %u\n", i); +		} else { +			VPRINTK("port %u (no irq)\n", i); +			if (ata_ratelimit()) +				dev_warn(host->dev, +					 "interrupt on disabled port %u\n", i); +		} +	} + +	writel(irq_stat, mmio + HOST_IRQ_STAT); + +	spin_unlock(&host->lock); + +	VPRINTK("EXIT\n"); + +	return IRQ_WAKE_THREAD; +} +EXPORT_SYMBOL_GPL(ahci_hw_interrupt); +  irqreturn_t ahci_interrupt(int irq, void *dev_instance)  {  	struct ata_host *host = dev_instance; @@ -1693,8 +1919,8 @@ irqreturn_t ahci_interrupt(int irq, void *dev_instance)  		} else {  			VPRINTK("port %u (no irq)\n", i);  			if (ata_ratelimit()) -				dev_printk(KERN_WARNING, host->dev, -					"interrupt on disabled port %u\n", i); +				dev_warn(host->dev, +					 "interrupt on disabled port %u\n", i);  		}  		handled = 1; @@ -1719,7 +1945,7 @@ irqreturn_t ahci_interrupt(int irq, void *dev_instance)  }  EXPORT_SYMBOL_GPL(ahci_interrupt); -static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) +unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)  {  	struct ata_port *ap = qc->ap;  	void __iomem *port_mmio = ahci_port_base(ap); @@ -1748,6 +1974,7 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)  	return 0;  } +EXPORT_SYMBOL_GPL(ahci_qc_issue);  static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)  { @@ -1798,12 +2025,14 @@ static void ahci_thaw(struct ata_port *ap)  	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);  } -static void ahci_error_handler(struct ata_port *ap) +void ahci_error_handler(struct ata_port *ap)  { +	struct ahci_host_priv *hpriv = ap->host->private_data; +  	if (!(ap->pflags & ATA_PFLAG_FROZEN)) {  		/* restart engine */  		ahci_stop_engine(ap); -		ahci_start_engine(ap); +		hpriv->start_engine(ap);  	}  	sata_pmp_error_handler(ap); @@ -1811,6 +2040,7 @@ static void ahci_error_handler(struct ata_port *ap)  	if (!ata_dev_enabled(ap->link.device))  		ahci_stop_engine(ap);  } +EXPORT_SYMBOL_GPL(ahci_error_handler);  static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)  { @@ -1821,8 +2051,85 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)  		ahci_kick_engine(ap);  } +static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) +{ +	struct ahci_host_priv *hpriv = ap->host->private_data; +	void __iomem *port_mmio = ahci_port_base(ap); +	struct ata_device *dev = ap->link.device; +	u32 devslp, dm, dito, mdat, deto; +	int rc; +	unsigned int err_mask; + +	devslp = readl(port_mmio + PORT_DEVSLP); +	if (!(devslp & PORT_DEVSLP_DSP)) { +		dev_err(ap->host->dev, "port does not support device sleep\n"); +		return; +	} + +	/* disable device sleep */ +	if (!sleep) { +		if (devslp & PORT_DEVSLP_ADSE) { +			writel(devslp & ~PORT_DEVSLP_ADSE, +			       port_mmio + PORT_DEVSLP); +			err_mask = ata_dev_set_feature(dev, +						       SETFEATURES_SATA_DISABLE, +						       SATA_DEVSLP); +			if (err_mask && err_mask != AC_ERR_DEV) +				ata_dev_warn(dev, "failed to disable DEVSLP\n"); +		} +		return; +	} + +	/* device sleep was already enabled */ +	if (devslp & PORT_DEVSLP_ADSE) +		return; + +	/* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */ +	rc = ahci_stop_engine(ap); +	if (rc) +		return; + +	dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET; +	dito = devslp_idle_timeout / (dm + 1); +	if (dito > 0x3ff) +		dito = 0x3ff; + +	/* Use the nominal value 10 ms if the read MDAT is zero, +	 * the nominal value of DETO is 20 ms. +	 */ +	if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] & +	    ATA_LOG_DEVSLP_VALID_MASK) { +		mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] & +		       ATA_LOG_DEVSLP_MDAT_MASK; +		if (!mdat) +			mdat = 10; +		deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO]; +		if (!deto) +			deto = 20; +	} else { +		mdat = 10; +		deto = 20; +	} + +	devslp |= ((dito << PORT_DEVSLP_DITO_OFFSET) | +		   (mdat << PORT_DEVSLP_MDAT_OFFSET) | +		   (deto << PORT_DEVSLP_DETO_OFFSET) | +		   PORT_DEVSLP_ADSE); +	writel(devslp, port_mmio + PORT_DEVSLP); + +	hpriv->start_engine(ap); + +	/* enable device sleep feature for the drive */ +	err_mask = ata_dev_set_feature(dev, +				       SETFEATURES_SATA_ENABLE, +				       SATA_DEVSLP); +	if (err_mask && err_mask != AC_ERR_DEV) +		ata_dev_warn(dev, "failed to enable DEVSLP\n"); +} +  static void ahci_enable_fbs(struct ata_port *ap)  { +	struct ahci_host_priv *hpriv = ap->host->private_data;  	struct ahci_port_priv *pp = ap->private_data;  	void __iomem *port_mmio = ahci_port_base(ap);  	u32 fbs; @@ -1845,17 +2152,18 @@ static void ahci_enable_fbs(struct ata_port *ap)  	writel(fbs | PORT_FBS_EN, port_mmio + PORT_FBS);  	fbs = readl(port_mmio + PORT_FBS);  	if (fbs & PORT_FBS_EN) { -		dev_printk(KERN_INFO, ap->host->dev, "FBS is enabled.\n"); +		dev_info(ap->host->dev, "FBS is enabled\n");  		pp->fbs_enabled = true;  		pp->fbs_last_dev = -1; /* initialization */  	} else -		dev_printk(KERN_ERR, ap->host->dev, "Failed to enable FBS\n"); +		dev_err(ap->host->dev, "Failed to enable FBS\n"); -	ahci_start_engine(ap); +	hpriv->start_engine(ap);  }  static void ahci_disable_fbs(struct ata_port *ap)  { +	struct ahci_host_priv *hpriv = ap->host->private_data;  	struct ahci_port_priv *pp = ap->private_data;  	void __iomem *port_mmio = ahci_port_base(ap);  	u32 fbs; @@ -1877,13 +2185,13 @@ static void ahci_disable_fbs(struct ata_port *ap)  	writel(fbs & ~PORT_FBS_EN, port_mmio + PORT_FBS);  	fbs = readl(port_mmio + PORT_FBS);  	if (fbs & PORT_FBS_EN) -		dev_printk(KERN_ERR, ap->host->dev, "Failed to disable FBS\n"); +		dev_err(ap->host->dev, "Failed to disable FBS\n");  	else { -		dev_printk(KERN_INFO, ap->host->dev, "FBS is disabled.\n"); +		dev_info(ap->host->dev, "FBS is disabled\n");  		pp->fbs_enabled = false;  	} -	ahci_start_engine(ap); +	hpriv->start_engine(ap);  }  static void ahci_pmp_attach(struct ata_port *ap) @@ -1899,7 +2207,17 @@ static void ahci_pmp_attach(struct ata_port *ap)  	ahci_enable_fbs(ap);  	pp->intr_mask |= PORT_IRQ_BAD_PMP; -	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); + +	/* +	 * We must not change the port interrupt mask register if the +	 * port is marked frozen, the value in pp->intr_mask will be +	 * restored later when the port is thawed. +	 * +	 * Note that during initialization, the port is marked as +	 * frozen since the irq handler is not yet registered. +	 */ +	if (!(ap->pflags & ATA_PFLAG_FROZEN)) +		writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);  }  static void ahci_pmp_detach(struct ata_port *ap) @@ -1915,10 +2233,13 @@ static void ahci_pmp_detach(struct ata_port *ap)  	writel(cmd, port_mmio + PORT_CMD);  	pp->intr_mask &= ~PORT_IRQ_BAD_PMP; -	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); + +	/* see comment above in ahci_pmp_attach() */ +	if (!(ap->pflags & ATA_PFLAG_FROZEN)) +		writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);  } -static int ahci_port_resume(struct ata_port *ap) +int ahci_port_resume(struct ata_port *ap)  {  	ahci_power_up(ap);  	ahci_start_port(ap); @@ -1930,6 +2251,7 @@ static int ahci_port_resume(struct ata_port *ap)  	return 0;  } +EXPORT_SYMBOL_GPL(ahci_port_resume);  #ifdef CONFIG_PM  static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) @@ -1941,8 +2263,8 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)  	if (rc == 0)  		ahci_power_down(ap);  	else { -		ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc); -		ahci_start_port(ap); +		ata_port_err(ap, "%s (%d)\n", emsg, rc); +		ata_port_freeze(ap);  	}  	return rc; @@ -1962,6 +2284,16 @@ static int ahci_port_start(struct ata_port *ap)  	if (!pp)  		return -ENOMEM; +	if (ap->host->n_ports > 1) { +		pp->irq_desc = devm_kzalloc(dev, 8, GFP_KERNEL); +		if (!pp->irq_desc) { +			devm_kfree(dev, pp); +			return -ENOMEM; +		} +		snprintf(pp->irq_desc, 8, +			 "%s%d", dev_driver_string(dev), ap->port_no); +	} +  	/* check FBS capability */  	if ((hpriv->cap & HOST_CAP_FBS) && sata_pmp_supported(ap)) {  		void __iomem *port_mmio = ahci_port_base(ap); @@ -1969,14 +2301,12 @@ static int ahci_port_start(struct ata_port *ap)  		if (cmd & PORT_CMD_FBSCP)  			pp->fbs_supported = true;  		else if (hpriv->flags & AHCI_HFLAG_YES_FBS) { -			dev_printk(KERN_INFO, dev, -				   "port %d can do FBS, forcing FBSCP\n", -				   ap->port_no); +			dev_info(dev, "port %d can do FBS, forcing FBSCP\n", +				 ap->port_no);  			pp->fbs_supported = true;  		} else -			dev_printk(KERN_WARNING, dev, -				   "port %d is not capable of FBS\n", -				   ap->port_no); +			dev_warn(dev, "port %d is not capable of FBS\n", +				 ap->port_no);  	}  	if (pp->fbs_supported) { @@ -2024,6 +2354,14 @@ static int ahci_port_start(struct ata_port *ap)  	 */  	pp->intr_mask = DEF_PORT_IRQ; +	/* +	 * Switch to per-port locking in case each port has its own MSI vector. +	 */ +	if ((hpriv->flags & AHCI_HFLAG_MULTI_MSI)) { +		spin_lock_init(&pp->lock); +		ap->lock = &pp->lock; +	} +  	ap->private_data = pp;  	/* engage engines, captain */ @@ -2038,7 +2376,7 @@ static void ahci_port_stop(struct ata_port *ap)  	/* de-initialize port */  	rc = ahci_deinit_port(ap, &emsg);  	if (rc) -		ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc); +		ata_port_warn(ap, "%s (%d)\n", emsg, rc);  }  void ahci_print_info(struct ata_host *host, const char *scc_s) @@ -2083,7 +2421,8 @@ void ahci_print_info(struct ata_host *host, const char *scc_s)  		"flags: "  		"%s%s%s%s%s%s%s"  		"%s%s%s%s%s%s%s" -		"%s%s%s%s%s%s\n" +		"%s%s%s%s%s%s%s" +		"%s%s\n"  		,  		cap & HOST_CAP_64 ? "64bit " : "", @@ -2103,6 +2442,9 @@ void ahci_print_info(struct ata_host *host, const char *scc_s)  		cap & HOST_CAP_CCC ? "ccc " : "",  		cap & HOST_CAP_EMS ? "ems " : "",  		cap & HOST_CAP_SXS ? "sxs " : "", +		cap2 & HOST_CAP2_DESO ? "deso " : "", +		cap2 & HOST_CAP2_SADM ? "sadm " : "", +		cap2 & HOST_CAP2_SDS ? "sds " : "",  		cap2 & HOST_CAP2_APST ? "apst " : "",  		cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "",  		cap2 & HOST_CAP2_BOH ? "boh " : "" diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c new file mode 100644 index 00000000000..b0077589f06 --- /dev/null +++ b/drivers/ata/libahci_platform.c @@ -0,0 +1,549 @@ +/* + * AHCI SATA platform library + * + * Copyright 2004-2005  Red Hat, Inc. + *   Jeff Garzik <jgarzik@pobox.com> + * Copyright 2010  MontaVista Software, LLC. + *   Anton Vorontsov <avorontsov@ru.mvista.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + */ + +#include <linux/clk.h> +#include <linux/kernel.h> +#include <linux/gfp.h> +#include <linux/module.h> +#include <linux/pm.h> +#include <linux/interrupt.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/libata.h> +#include <linux/ahci_platform.h> +#include <linux/phy/phy.h> +#include <linux/pm_runtime.h> +#include "ahci.h" + +static void ahci_host_stop(struct ata_host *host); + +struct ata_port_operations ahci_platform_ops = { +	.inherits	= &ahci_ops, +	.host_stop	= ahci_host_stop, +}; +EXPORT_SYMBOL_GPL(ahci_platform_ops); + +static struct scsi_host_template ahci_platform_sht = { +	AHCI_SHT("ahci_platform"), +}; + +/** + * ahci_platform_enable_clks - Enable platform clocks + * @hpriv: host private area to store config values + * + * This function enables all the clks found in hpriv->clks, starting at + * index 0. If any clk fails to enable it disables all the clks already + * enabled in reverse order, and then returns an error. + * + * RETURNS: + * 0 on success otherwise a negative error code + */ +int ahci_platform_enable_clks(struct ahci_host_priv *hpriv) +{ +	int c, rc; + +	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) { +		rc = clk_prepare_enable(hpriv->clks[c]); +		if (rc) +			goto disable_unprepare_clk; +	} +	return 0; + +disable_unprepare_clk: +	while (--c >= 0) +		clk_disable_unprepare(hpriv->clks[c]); +	return rc; +} +EXPORT_SYMBOL_GPL(ahci_platform_enable_clks); + +/** + * ahci_platform_disable_clks - Disable platform clocks + * @hpriv: host private area to store config values + * + * This function disables all the clks found in hpriv->clks, in reverse + * order of ahci_platform_enable_clks (starting at the end of the array). + */ +void ahci_platform_disable_clks(struct ahci_host_priv *hpriv) +{ +	int c; + +	for (c = AHCI_MAX_CLKS - 1; c >= 0; c--) +		if (hpriv->clks[c]) +			clk_disable_unprepare(hpriv->clks[c]); +} +EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); + +/** + * ahci_platform_enable_resources - Enable platform resources + * @hpriv: host private area to store config values + * + * This function enables all ahci_platform managed resources in the + * following order: + * 1) Regulator + * 2) Clocks (through ahci_platform_enable_clks) + * 3) Phy + * + * If resource enabling fails at any point the previous enabled resources + * are disabled in reverse order. + * + * RETURNS: + * 0 on success otherwise a negative error code + */ +int ahci_platform_enable_resources(struct ahci_host_priv *hpriv) +{ +	int rc; + +	if (hpriv->target_pwr) { +		rc = regulator_enable(hpriv->target_pwr); +		if (rc) +			return rc; +	} + +	rc = ahci_platform_enable_clks(hpriv); +	if (rc) +		goto disable_regulator; + +	if (hpriv->phy) { +		rc = phy_init(hpriv->phy); +		if (rc) +			goto disable_clks; + +		rc = phy_power_on(hpriv->phy); +		if (rc) { +			phy_exit(hpriv->phy); +			goto disable_clks; +		} +	} + +	return 0; + +disable_clks: +	ahci_platform_disable_clks(hpriv); + +disable_regulator: +	if (hpriv->target_pwr) +		regulator_disable(hpriv->target_pwr); +	return rc; +} +EXPORT_SYMBOL_GPL(ahci_platform_enable_resources); + +/** + * ahci_platform_disable_resources - Disable platform resources + * @hpriv: host private area to store config values + * + * This function disables all ahci_platform managed resources in the + * following order: + * 1) Phy + * 2) Clocks (through ahci_platform_disable_clks) + * 3) Regulator + */ +void ahci_platform_disable_resources(struct ahci_host_priv *hpriv) +{ +	if (hpriv->phy) { +		phy_power_off(hpriv->phy); +		phy_exit(hpriv->phy); +	} + +	ahci_platform_disable_clks(hpriv); + +	if (hpriv->target_pwr) +		regulator_disable(hpriv->target_pwr); +} +EXPORT_SYMBOL_GPL(ahci_platform_disable_resources); + +static void ahci_platform_put_resources(struct device *dev, void *res) +{ +	struct ahci_host_priv *hpriv = res; +	int c; + +	if (hpriv->got_runtime_pm) { +		pm_runtime_put_sync(dev); +		pm_runtime_disable(dev); +	} + +	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) +		clk_put(hpriv->clks[c]); +} + +/** + * ahci_platform_get_resources - Get platform resources + * @pdev: platform device to get resources for + * + * This function allocates an ahci_host_priv struct, and gets the following + * resources, storing a reference to them inside the returned struct: + * + * 1) mmio registers (IORESOURCE_MEM 0, mandatory) + * 2) regulator for controlling the targets power (optional) + * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, + *    or for non devicetree enabled platforms a single clock + *	4) phy (optional) + * + * RETURNS: + * The allocated ahci_host_priv on success, otherwise an ERR_PTR value + */ +struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev) +{ +	struct device *dev = &pdev->dev; +	struct ahci_host_priv *hpriv; +	struct clk *clk; +	int i, rc = -ENOMEM; + +	if (!devres_open_group(dev, NULL, GFP_KERNEL)) +		return ERR_PTR(-ENOMEM); + +	hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv), +			     GFP_KERNEL); +	if (!hpriv) +		goto err_out; + +	devres_add(dev, hpriv); + +	hpriv->mmio = devm_ioremap_resource(dev, +			      platform_get_resource(pdev, IORESOURCE_MEM, 0)); +	if (IS_ERR(hpriv->mmio)) { +		dev_err(dev, "no mmio space\n"); +		rc = PTR_ERR(hpriv->mmio); +		goto err_out; +	} + +	hpriv->target_pwr = devm_regulator_get_optional(dev, "target"); +	if (IS_ERR(hpriv->target_pwr)) { +		rc = PTR_ERR(hpriv->target_pwr); +		if (rc == -EPROBE_DEFER) +			goto err_out; +		hpriv->target_pwr = NULL; +	} + +	for (i = 0; i < AHCI_MAX_CLKS; i++) { +		/* +		 * For now we must use clk_get(dev, NULL) for the first clock, +		 * because some platforms (da850, spear13xx) are not yet +		 * converted to use devicetree for clocks.  For new platforms +		 * this is equivalent to of_clk_get(dev->of_node, 0). +		 */ +		if (i == 0) +			clk = clk_get(dev, NULL); +		else +			clk = of_clk_get(dev->of_node, i); + +		if (IS_ERR(clk)) { +			rc = PTR_ERR(clk); +			if (rc == -EPROBE_DEFER) +				goto err_out; +			break; +		} +		hpriv->clks[i] = clk; +	} + +	hpriv->phy = devm_phy_get(dev, "sata-phy"); +	if (IS_ERR(hpriv->phy)) { +		rc = PTR_ERR(hpriv->phy); +		switch (rc) { +		case -ENOSYS: +			/* No PHY support. Check if PHY is required. */ +			if (of_find_property(dev->of_node, "phys", NULL)) { +				dev_err(dev, "couldn't get sata-phy: ENOSYS\n"); +				goto err_out; +			} +		case -ENODEV: +			/* continue normally */ +			hpriv->phy = NULL; +			break; + +		case -EPROBE_DEFER: +			goto err_out; + +		default: +			dev_err(dev, "couldn't get sata-phy\n"); +			goto err_out; +		} +	} + +	pm_runtime_enable(dev); +	pm_runtime_get_sync(dev); +	hpriv->got_runtime_pm = true; + +	devres_remove_group(dev, NULL); +	return hpriv; + +err_out: +	devres_release_group(dev, NULL); +	return ERR_PTR(rc); +} +EXPORT_SYMBOL_GPL(ahci_platform_get_resources); + +/** + * ahci_platform_init_host - Bring up an ahci-platform host + * @pdev: platform device pointer for the host + * @hpriv: ahci-host private data for the host + * @pi_template: template for the ata_port_info to use + * @host_flags: ahci host flags used in ahci_host_priv + * @force_port_map: param passed to ahci_save_initial_config + * @mask_port_map: param passed to ahci_save_initial_config + * + * This function does all the usual steps needed to bring up an + * ahci-platform host, note any necessary resources (ie clks, phy, etc.) + * must be initialized / enabled before calling this. + * + * RETURNS: + * 0 on success otherwise a negative error code + */ +int ahci_platform_init_host(struct platform_device *pdev, +			    struct ahci_host_priv *hpriv, +			    const struct ata_port_info *pi_template, +			    unsigned long host_flags, +			    unsigned int force_port_map, +			    unsigned int mask_port_map) +{ +	struct device *dev = &pdev->dev; +	struct ata_port_info pi = *pi_template; +	const struct ata_port_info *ppi[] = { &pi, NULL }; +	struct ata_host *host; +	int i, irq, n_ports, rc; + +	irq = platform_get_irq(pdev, 0); +	if (irq <= 0) { +		dev_err(dev, "no irq\n"); +		return -EINVAL; +	} + +	/* prepare host */ +	pi.private_data = (void *)host_flags; +	hpriv->flags |= host_flags; + +	ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map); + +	if (hpriv->cap & HOST_CAP_NCQ) +		pi.flags |= ATA_FLAG_NCQ; + +	if (hpriv->cap & HOST_CAP_PMP) +		pi.flags |= ATA_FLAG_PMP; + +	ahci_set_em_messages(hpriv, &pi); + +	/* CAP.NP sometimes indicate the index of the last enabled +	 * port, at other times, that of the last possible port, so +	 * determining the maximum port number requires looking at +	 * both CAP.NP and port_map. +	 */ +	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); + +	host = ata_host_alloc_pinfo(dev, ppi, n_ports); +	if (!host) +		return -ENOMEM; + +	host->private_data = hpriv; + +	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) +		host->flags |= ATA_HOST_PARALLEL_SCAN; +	else +		dev_info(dev, "SSS flag set, parallel bus scan disabled\n"); + +	if (pi.flags & ATA_FLAG_EM) +		ahci_reset_em(host); + +	for (i = 0; i < host->n_ports; i++) { +		struct ata_port *ap = host->ports[i]; + +		ata_port_desc(ap, "mmio %pR", +			      platform_get_resource(pdev, IORESOURCE_MEM, 0)); +		ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); + +		/* set enclosure management message type */ +		if (ap->flags & ATA_FLAG_EM) +			ap->em_message_type = hpriv->em_msg_type; + +		/* disabled/not-implemented port */ +		if (!(hpriv->port_map & (1 << i))) +			ap->ops = &ata_dummy_port_ops; +	} + +	rc = ahci_reset_controller(host); +	if (rc) +		return rc; + +	ahci_init_controller(host); +	ahci_print_info(host, "platform"); + +	return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, +				 &ahci_platform_sht); +} +EXPORT_SYMBOL_GPL(ahci_platform_init_host); + +static void ahci_host_stop(struct ata_host *host) +{ +	struct device *dev = host->dev; +	struct ahci_platform_data *pdata = dev_get_platdata(dev); +	struct ahci_host_priv *hpriv = host->private_data; + +	if (pdata && pdata->exit) +		pdata->exit(dev); + +	ahci_platform_disable_resources(hpriv); +} + +#ifdef CONFIG_PM_SLEEP +/** + * ahci_platform_suspend_host - Suspend an ahci-platform host + * @dev: device pointer for the host + * + * This function does all the usual steps needed to suspend an + * ahci-platform host, note any necessary resources (ie clks, phy, etc.) + * must be disabled after calling this. + * + * RETURNS: + * 0 on success otherwise a negative error code + */ +int ahci_platform_suspend_host(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	struct ahci_host_priv *hpriv = host->private_data; +	void __iomem *mmio = hpriv->mmio; +	u32 ctl; + +	if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { +		dev_err(dev, "firmware update required for suspend/resume\n"); +		return -EIO; +	} + +	/* +	 * AHCI spec rev1.1 section 8.3.3: +	 * Software must disable interrupts prior to requesting a +	 * transition of the HBA to D3 state. +	 */ +	ctl = readl(mmio + HOST_CTL); +	ctl &= ~HOST_IRQ_EN; +	writel(ctl, mmio + HOST_CTL); +	readl(mmio + HOST_CTL); /* flush */ + +	return ata_host_suspend(host, PMSG_SUSPEND); +} +EXPORT_SYMBOL_GPL(ahci_platform_suspend_host); + +/** + * ahci_platform_resume_host - Resume an ahci-platform host + * @dev: device pointer for the host + * + * This function does all the usual steps needed to resume an ahci-platform + * host, note any necessary resources (ie clks, phy, etc.)  must be + * initialized / enabled before calling this. + * + * RETURNS: + * 0 on success otherwise a negative error code + */ +int ahci_platform_resume_host(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	int rc; + +	if (dev->power.power_state.event == PM_EVENT_SUSPEND) { +		rc = ahci_reset_controller(host); +		if (rc) +			return rc; + +		ahci_init_controller(host); +	} + +	ata_host_resume(host); + +	return 0; +} +EXPORT_SYMBOL_GPL(ahci_platform_resume_host); + +/** + * ahci_platform_suspend - Suspend an ahci-platform device + * @dev: the platform device to suspend + * + * This function suspends the host associated with the device, followed by + * disabling all the resources of the device. + * + * RETURNS: + * 0 on success otherwise a negative error code + */ +int ahci_platform_suspend(struct device *dev) +{ +	struct ahci_platform_data *pdata = dev_get_platdata(dev); +	struct ata_host *host = dev_get_drvdata(dev); +	struct ahci_host_priv *hpriv = host->private_data; +	int rc; + +	rc = ahci_platform_suspend_host(dev); +	if (rc) +		return rc; + +	if (pdata && pdata->suspend) { +		rc = pdata->suspend(dev); +		if (rc) +			goto resume_host; +	} + +	ahci_platform_disable_resources(hpriv); + +	return 0; + +resume_host: +	ahci_platform_resume_host(dev); +	return rc; +} +EXPORT_SYMBOL_GPL(ahci_platform_suspend); + +/** + * ahci_platform_resume - Resume an ahci-platform device + * @dev: the platform device to resume + * + * This function enables all the resources of the device followed by + * resuming the host associated with the device. + * + * RETURNS: + * 0 on success otherwise a negative error code + */ +int ahci_platform_resume(struct device *dev) +{ +	struct ahci_platform_data *pdata = dev_get_platdata(dev); +	struct ata_host *host = dev_get_drvdata(dev); +	struct ahci_host_priv *hpriv = host->private_data; +	int rc; + +	rc = ahci_platform_enable_resources(hpriv); +	if (rc) +		return rc; + +	if (pdata && pdata->resume) { +		rc = pdata->resume(dev); +		if (rc) +			goto disable_resources; +	} + +	rc = ahci_platform_resume_host(dev); +	if (rc) +		goto disable_resources; + +	/* We resumed so update PM runtime state */ +	pm_runtime_disable(dev); +	pm_runtime_set_active(dev); +	pm_runtime_enable(dev); + +	return 0; + +disable_resources: +	ahci_platform_disable_resources(hpriv); + +	return rc; +} +EXPORT_SYMBOL_GPL(ahci_platform_resume); +#endif + +MODULE_DESCRIPTION("AHCI SATA platform library"); +MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 8b5ea399a4f..97a14fe47de 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -16,11 +16,10 @@  #include <linux/libata.h>  #include <linux/pci.h>  #include <linux/slab.h> +#include <linux/pm_runtime.h>  #include <scsi/scsi_device.h>  #include "libata.h" -#include <acpi/acpi_bus.h> -  unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT;  module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644);  MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM, 0x8=FPDMA non-zero offset, 0x10=FPDMA DMA Setup FIS auto-activate)"); @@ -33,76 +32,34 @@ struct ata_acpi_gtf {  	u8	tf[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */  } __packed; -/* - *	Helper - belongs in the PCI layer somewhere eventually - */ -static int is_pci_dev(struct device *dev) -{ -	return (dev->bus == &pci_bus_type); -} -  static void ata_acpi_clear_gtf(struct ata_device *dev)  {  	kfree(dev->gtf_cache);  	dev->gtf_cache = NULL;  } +struct ata_acpi_hotplug_context { +	struct acpi_hotplug_context hp; +	union { +		struct ata_port *ap; +		struct ata_device *dev; +	} data; +}; + +#define ata_hotplug_data(context) (container_of((context), struct ata_acpi_hotplug_context, hp)->data) +  /** - * ata_acpi_associate_sata_port - associate SATA port with ACPI objects - * @ap: target SATA port + * ata_dev_acpi_handle - provide the acpi_handle for an ata_device + * @dev: the acpi_handle returned will correspond to this device   * - * Look up ACPI objects associated with @ap and initialize acpi_handle - * fields of @ap, the port and devices accordingly. - * - * LOCKING: - * EH context. - * - * RETURNS: - * 0 on success, -errno on failure. + * Returns the acpi_handle for the ACPI namespace object corresponding to + * the ata_device passed into the function, or NULL if no such object exists + * or ACPI is disabled for this device due to consecutive errors.   */ -void ata_acpi_associate_sata_port(struct ata_port *ap) -{ -	WARN_ON(!(ap->flags & ATA_FLAG_ACPI_SATA)); - -	if (!sata_pmp_attached(ap)) { -		u64 adr = SATA_ADR(ap->port_no, NO_PORT_MULT); - -		ap->link.device->acpi_handle = -			acpi_get_child(ap->host->acpi_handle, adr); -	} else { -		struct ata_link *link; - -		ap->link.device->acpi_handle = NULL; - -		ata_for_each_link(link, ap, EDGE) { -			u64 adr = SATA_ADR(ap->port_no, link->pmp); - -			link->device->acpi_handle = -				acpi_get_child(ap->host->acpi_handle, adr); -		} -	} -} - -static void ata_acpi_associate_ide_port(struct ata_port *ap) +acpi_handle ata_dev_acpi_handle(struct ata_device *dev)  { -	int max_devices, i; - -	ap->acpi_handle = acpi_get_child(ap->host->acpi_handle, ap->port_no); -	if (!ap->acpi_handle) -		return; - -	max_devices = 1; -	if (ap->flags & ATA_FLAG_SLAVE_POSS) -		max_devices++; - -	for (i = 0; i < max_devices; i++) { -		struct ata_device *dev = &ap->link.device[i]; - -		dev->acpi_handle = acpi_get_child(ap->acpi_handle, i); -	} - -	if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) -		ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; +	return dev->flags & ATA_DFLAG_ACPI_DISABLED ? +			NULL : ACPI_HANDLE(&dev->tdev);  }  /* @ap and @dev are the same as ata_acpi_handle_hotplug() */ @@ -174,18 +131,17 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,  		ata_port_wait_eh(ap);  } -static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data) +static int ata_acpi_dev_notify_dock(struct acpi_device *adev, u32 event)  { -	struct ata_device *dev = data; - +	struct ata_device *dev = ata_hotplug_data(adev->hp).dev;  	ata_acpi_handle_hotplug(dev->link->ap, dev, event); +	return 0;  } -static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data) +static int ata_acpi_ap_notify_dock(struct acpi_device *adev, u32 event)  { -	struct ata_port *ap = data; - -	ata_acpi_handle_hotplug(ap, NULL, event); +	ata_acpi_handle_hotplug(ata_hotplug_data(adev->hp).ap, NULL, event); +	return 0;  }  static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev, @@ -207,75 +163,85 @@ static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,  	}  } -static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data) +static void ata_acpi_ap_uevent(struct acpi_device *adev, u32 event)  { -	ata_acpi_uevent(data, NULL, event); +	ata_acpi_uevent(ata_hotplug_data(adev->hp).ap, NULL, event);  } -static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data) +static void ata_acpi_dev_uevent(struct acpi_device *adev, u32 event)  { -	struct ata_device *dev = data; +	struct ata_device *dev = ata_hotplug_data(adev->hp).dev;  	ata_acpi_uevent(dev->link->ap, dev, event);  } -static struct acpi_dock_ops ata_acpi_dev_dock_ops = { -	.handler = ata_acpi_dev_notify_dock, -	.uevent = ata_acpi_dev_uevent, -}; +/* bind acpi handle to pata port */ +void ata_acpi_bind_port(struct ata_port *ap) +{ +	struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); +	struct acpi_device *adev; +	struct ata_acpi_hotplug_context *context; -static struct acpi_dock_ops ata_acpi_ap_dock_ops = { -	.handler = ata_acpi_ap_notify_dock, -	.uevent = ata_acpi_ap_uevent, -}; +	if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_companion) +		return; -/** - * ata_acpi_associate - associate ATA host with ACPI objects - * @host: target ATA host - * - * Look up ACPI objects associated with @host and initialize - * acpi_handle fields of @host, its ports and devices accordingly. - * - * LOCKING: - * EH context. - * - * RETURNS: - * 0 on success, -errno on failure. - */ -void ata_acpi_associate(struct ata_host *host) -{ -	int i, j; +	acpi_preset_companion(&ap->tdev, host_companion, ap->port_no); -	if (!is_pci_dev(host->dev) || libata_noacpi) +	if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) +		ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; + +	adev = ACPI_COMPANION(&ap->tdev); +	if (!adev || adev->hp)  		return; -	host->acpi_handle = DEVICE_ACPI_HANDLE(host->dev); -	if (!host->acpi_handle) +	context = kzalloc(sizeof(*context), GFP_KERNEL); +	if (!context)  		return; -	for (i = 0; i < host->n_ports; i++) { -		struct ata_port *ap = host->ports[i]; +	context->data.ap = ap; +	acpi_initialize_hp_context(adev, &context->hp, ata_acpi_ap_notify_dock, +				   ata_acpi_ap_uevent); +} + +void ata_acpi_bind_dev(struct ata_device *dev) +{ +	struct ata_port *ap = dev->link->ap; +	struct acpi_device *port_companion = ACPI_COMPANION(&ap->tdev); +	struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); +	struct acpi_device *parent, *adev; +	struct ata_acpi_hotplug_context *context; +	u64 adr; -		if (host->ports[0]->flags & ATA_FLAG_ACPI_SATA) -			ata_acpi_associate_sata_port(ap); +	/* +	 * For both sata/pata devices, host companion device is required. +	 * For pata device, port companion device is also required. +	 */ +	if (libata_noacpi || !host_companion || +			(!(ap->flags & ATA_FLAG_ACPI_SATA) && !port_companion)) +		return; + +	if (ap->flags & ATA_FLAG_ACPI_SATA) { +		if (!sata_pmp_attached(ap)) +			adr = SATA_ADR(ap->port_no, NO_PORT_MULT);  		else -			ata_acpi_associate_ide_port(ap); +			adr = SATA_ADR(ap->port_no, dev->link->pmp); +		parent = host_companion; +	} else { +		adr = dev->devno; +		parent = port_companion; +	} -		if (ap->acpi_handle) { -			/* we might be on a docking station */ -			register_hotplug_dock_device(ap->acpi_handle, -					     &ata_acpi_ap_dock_ops, ap); -		} +	acpi_preset_companion(&dev->tdev, parent, adr); +	adev = ACPI_COMPANION(&dev->tdev); +	if (!adev || adev->hp) +		return; -		for (j = 0; j < ata_link_max_devices(&ap->link); j++) { -			struct ata_device *dev = &ap->link.device[j]; +	context = kzalloc(sizeof(*context), GFP_KERNEL); +	if (!context) +		return; -			if (dev->acpi_handle) { -				/* we might be on a docking station */ -				register_hotplug_dock_device(dev->acpi_handle, -					     &ata_acpi_dev_dock_ops, dev); -			} -		} -	} +	context->data.dev = dev; +	acpi_initialize_hp_context(adev, &context->hp, ata_acpi_dev_notify_dock, +				   ata_acpi_dev_uevent);  }  /** @@ -299,7 +265,7 @@ void ata_acpi_dissociate(struct ata_host *host)  		struct ata_port *ap = host->ports[i];  		const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap); -		if (ap->acpi_handle && gtm) +		if (ACPI_HANDLE(&ap->tdev) && gtm)  			ata_acpi_stm(ap, gtm);  	}  } @@ -323,8 +289,12 @@ int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)  	union acpi_object *out_obj;  	acpi_status status;  	int rc = 0; +	acpi_handle handle = ACPI_HANDLE(&ap->tdev); -	status = acpi_evaluate_object(ap->acpi_handle, "_GTM", NULL, &output); +	if (!handle) +		return -EINVAL; + +	status = acpi_evaluate_object(handle, "_GTM", NULL, &output);  	rc = -ENOENT;  	if (status == AE_NOT_FOUND) @@ -332,25 +302,22 @@ int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)  	rc = -EINVAL;  	if (ACPI_FAILURE(status)) { -		ata_port_printk(ap, KERN_ERR, -				"ACPI get timing mode failed (AE 0x%x)\n", -				status); +		ata_port_err(ap, "ACPI get timing mode failed (AE 0x%x)\n", +			     status);  		goto out_free;  	}  	out_obj = output.pointer;  	if (out_obj->type != ACPI_TYPE_BUFFER) { -		ata_port_printk(ap, KERN_WARNING, -				"_GTM returned unexpected object type 0x%x\n", -				out_obj->type); +		ata_port_warn(ap, "_GTM returned unexpected object type 0x%x\n", +			      out_obj->type);  		goto out_free;  	}  	if (out_obj->buffer.length != sizeof(struct ata_acpi_gtm)) { -		ata_port_printk(ap, KERN_ERR, -				"_GTM returned invalid length %d\n", -				out_obj->buffer.length); +		ata_port_err(ap, "_GTM returned invalid length %d\n", +			     out_obj->buffer.length);  		goto out_free;  	} @@ -397,13 +364,14 @@ int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm)  	input.count = 3;  	input.pointer = in_params; -	status = acpi_evaluate_object(ap->acpi_handle, "_STM", &input, NULL); +	status = acpi_evaluate_object(ACPI_HANDLE(&ap->tdev), "_STM", +				      &input, NULL);  	if (status == AE_NOT_FOUND)  		return -ENOENT;  	if (ACPI_FAILURE(status)) { -		ata_port_printk(ap, KERN_ERR, -			"ACPI set timing mode failed (status=0x%x)\n", status); +		ata_port_err(ap, "ACPI set timing mode failed (status=0x%x)\n", +			     status);  		return -EINVAL;  	}  	return 0; @@ -450,18 +418,18 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)  	output.pointer = NULL;	/* ACPI-CA sets this; save/free it later */  	if (ata_msg_probe(ap)) -		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n", -			       __func__, ap->port_no); +		ata_dev_dbg(dev, "%s: ENTER: port#: %d\n", +			    __func__, ap->port_no);  	/* _GTF has no input parameters */ -	status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output); +	status = acpi_evaluate_object(ata_dev_acpi_handle(dev), "_GTF", NULL, +				      &output);  	out_obj = dev->gtf_cache = output.pointer;  	if (ACPI_FAILURE(status)) {  		if (status != AE_NOT_FOUND) { -			ata_dev_printk(dev, KERN_WARNING, -				       "_GTF evaluation failed (AE 0x%x)\n", -				       status); +			ata_dev_warn(dev, "_GTF evaluation failed (AE 0x%x)\n", +				     status);  			rc = -EINVAL;  		}  		goto out_free; @@ -469,27 +437,24 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)  	if (!output.length || !output.pointer) {  		if (ata_msg_probe(ap)) -			ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: " -				"length or ptr is NULL (0x%llx, 0x%p)\n", -				__func__, -				(unsigned long long)output.length, -				output.pointer); +			ata_dev_dbg(dev, "%s: Run _GTF: length or ptr is NULL (0x%llx, 0x%p)\n", +				    __func__, +				    (unsigned long long)output.length, +				    output.pointer);  		rc = -EINVAL;  		goto out_free;  	}  	if (out_obj->type != ACPI_TYPE_BUFFER) { -		ata_dev_printk(dev, KERN_WARNING, -			       "_GTF unexpected object type 0x%x\n", -			       out_obj->type); +		ata_dev_warn(dev, "_GTF unexpected object type 0x%x\n", +			     out_obj->type);  		rc = -EINVAL;  		goto out_free;  	}  	if (out_obj->buffer.length % REGS_PER_GTF) { -		ata_dev_printk(dev, KERN_WARNING, -			       "unexpected _GTF length (%d)\n", -			       out_obj->buffer.length); +		ata_dev_warn(dev, "unexpected _GTF length (%d)\n", +			     out_obj->buffer.length);  		rc = -EINVAL;  		goto out_free;  	} @@ -499,9 +464,8 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)  	if (gtf) {  		*gtf = (void *)out_obj->buffer.pointer;  		if (ata_msg_probe(ap)) -			ata_dev_printk(dev, KERN_DEBUG, -				       "%s: returning gtf=%p, gtf_count=%d\n", -				       __func__, *gtf, rc); +			ata_dev_dbg(dev, "%s: returning gtf=%p, gtf_count=%d\n", +				    __func__, *gtf, rc);  	}  	return rc; @@ -660,8 +624,7 @@ static int ata_acpi_filter_tf(struct ata_device *dev,   * @dev: target ATA device   * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)   * - * Outputs ATA taskfile to standard ATA host controller using MMIO - * or PIO as indicated by the ATA_FLAG_MMIO flag. + * Outputs ATA taskfile to standard ATA host controller.   * Writes the control, feature, nsect, lbal, lbam, and lbah registers.   * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,   * hob_lbal, hob_lbam, and hob_lbah. @@ -812,8 +775,8 @@ static int ata_acpi_push_id(struct ata_device *dev)  	union acpi_object in_params[1];  	if (ata_msg_probe(ap)) -		ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n", -			       __func__, dev->devno, ap->port_no); +		ata_dev_dbg(dev, "%s: ix = %d, port#: %d\n", +			    __func__, dev->devno, ap->port_no);  	/* Give the drive Identify data to the drive via the _SDD method */  	/* _SDD: set up input parameters */ @@ -826,15 +789,15 @@ static int ata_acpi_push_id(struct ata_device *dev)  	/* It's OK for _SDD to be missing too. */  	swap_buf_le16(dev->id, ATA_ID_WORDS); -	status = acpi_evaluate_object(dev->acpi_handle, "_SDD", &input, NULL); +	status = acpi_evaluate_object(ata_dev_acpi_handle(dev), "_SDD", &input, +				      NULL);  	swap_buf_le16(dev->id, ATA_ID_WORDS);  	if (status == AE_NOT_FOUND)  		return -ENOENT;  	if (ACPI_FAILURE(status)) { -		ata_dev_printk(dev, KERN_WARNING, -			       "ACPI _SDD failed (AE 0x%x)\n", status); +		ata_dev_warn(dev, "ACPI _SDD failed (AE 0x%x)\n", status);  		return -EIO;  	} @@ -877,7 +840,7 @@ void ata_acpi_on_resume(struct ata_port *ap)  	const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);  	struct ata_device *dev; -	if (ap->acpi_handle && gtm) { +	if (ACPI_HANDLE(&ap->tdev) && gtm) {  		/* _GTM valid */  		/* restore timing parameters */ @@ -890,6 +853,7 @@ void ata_acpi_on_resume(struct ata_port *ap)  		ata_for_each_dev(dev, &ap->link, ALL) {  			ata_acpi_clear_gtf(dev);  			if (ata_dev_enabled(dev) && +			    ata_dev_acpi_handle(dev) &&  			    ata_dev_get_GTF(dev, NULL) >= 0)  				dev->flags |= ATA_DFLAG_ACPI_PENDING;  		} @@ -906,34 +870,94 @@ void ata_acpi_on_resume(struct ata_port *ap)  	}  } -/** - * ata_acpi_set_state - set the port power state - * @ap: target ATA port - * @state: state, on/off - * - * This function executes the _PS0/_PS3 ACPI method to set the power state. - * ACPI spec requires _PS0 when IDE power on and _PS3 when power off - */ -void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) +static int ata_acpi_choose_suspend_state(struct ata_device *dev, bool runtime) +{ +	int d_max_in = ACPI_STATE_D3_COLD; +	if (!runtime) +		goto out; + +	/* +	 * For ATAPI, runtime D3 cold is only allowed +	 * for ZPODD in zero power ready state +	 */ +	if (dev->class == ATA_DEV_ATAPI && +	    !(zpodd_dev_enabled(dev) && zpodd_zpready(dev))) +		d_max_in = ACPI_STATE_D3_HOT; + +out: +	return acpi_pm_device_sleep_state(&dev->tdev, NULL, d_max_in); +} + +static void sata_acpi_set_state(struct ata_port *ap, pm_message_t state) +{ +	bool runtime = PMSG_IS_AUTO(state); +	struct ata_device *dev; +	acpi_handle handle; +	int acpi_state; + +	ata_for_each_dev(dev, &ap->link, ENABLED) { +		handle = ata_dev_acpi_handle(dev); +		if (!handle) +			continue; + +		if (!(state.event & PM_EVENT_RESUME)) { +			acpi_state = ata_acpi_choose_suspend_state(dev, runtime); +			if (acpi_state == ACPI_STATE_D0) +				continue; +			if (runtime && zpodd_dev_enabled(dev) && +			    acpi_state == ACPI_STATE_D3_COLD) +				zpodd_enable_run_wake(dev); +			acpi_bus_set_power(handle, acpi_state); +		} else { +			if (runtime && zpodd_dev_enabled(dev)) +				zpodd_disable_run_wake(dev); +			acpi_bus_set_power(handle, ACPI_STATE_D0); +		} +	} +} + +/* ACPI spec requires _PS0 when IDE power on and _PS3 when power off */ +static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state)  {  	struct ata_device *dev; +	acpi_handle port_handle; -	if (!ap->acpi_handle || (ap->flags & ATA_FLAG_ACPI_SATA)) +	port_handle = ACPI_HANDLE(&ap->tdev); +	if (!port_handle)  		return;  	/* channel first and then drives for power on and vica versa  	   for power off */ -	if (state.event == PM_EVENT_ON) -		acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0); +	if (state.event & PM_EVENT_RESUME) +		acpi_bus_set_power(port_handle, ACPI_STATE_D0);  	ata_for_each_dev(dev, &ap->link, ENABLED) { -		if (dev->acpi_handle) -			acpi_bus_set_power(dev->acpi_handle, -				state.event == PM_EVENT_ON ? -					ACPI_STATE_D0 : ACPI_STATE_D3); +		acpi_handle dev_handle = ata_dev_acpi_handle(dev); +		if (!dev_handle) +			continue; + +		acpi_bus_set_power(dev_handle, state.event & PM_EVENT_RESUME ? +					ACPI_STATE_D0 : ACPI_STATE_D3_COLD);  	} -	if (state.event != PM_EVENT_ON) -		acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D3); + +	if (!(state.event & PM_EVENT_RESUME)) +		acpi_bus_set_power(port_handle, ACPI_STATE_D3_COLD); +} + +/** + * ata_acpi_set_state - set the port power state + * @ap: target ATA port + * @state: state, on/off + * + * This function sets a proper ACPI D state for the device on + * system and runtime PM operations. + */ +void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) +{ +	if (ap->flags & ATA_FLAG_ACPI_SATA) +		sata_acpi_set_state(ap, state); +	else +		pata_acpi_set_state(ap, state);  }  /** @@ -958,7 +982,7 @@ int ata_acpi_on_devcfg(struct ata_device *dev)  	int nr_executed = 0;  	int rc; -	if (!dev->acpi_handle) +	if (!ata_dev_acpi_handle(dev))  		return 0;  	/* do we need to do _GTF? */ @@ -984,8 +1008,8 @@ int ata_acpi_on_devcfg(struct ata_device *dev)  	if (nr_executed) {  		rc = ata_dev_reread_id(dev, 0);  		if (rc < 0) { -			ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY " -				       "after ACPI commands\n"); +			ata_dev_err(dev, +				    "failed to IDENTIFY after ACPI commands\n");  			return rc;  		}  	} @@ -1003,9 +1027,8 @@ int ata_acpi_on_devcfg(struct ata_device *dev)  		return rc;  	} -	ata_dev_printk(dev, KERN_WARNING, -		       "ACPI: failed the second time, disabled\n"); -	dev->acpi_handle = NULL; +	dev->flags |= ATA_DFLAG_ACPI_DISABLED; +	ata_dev_warn(dev, "ACPI: failed the second time, disabled\n");  	/* We can safely continue if no _GTF command has been executed  	 * and port is not frozen. diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 7f77c67d267..677c0c1b03b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1,7 +1,7 @@  /*   *  libata-core.c - helper library for ATA   * - *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> + *  Maintained by:  Tejun Heo <tj@kernel.org>   *    		    Please ALWAYS copy linux-ide@vger.kernel.org   *		    on emails.   * @@ -66,6 +66,8 @@  #include <asm/byteorder.h>  #include <linux/cdrom.h>  #include <linux/ratelimit.h> +#include <linux/pm_runtime.h> +#include <linux/platform_device.h>  #include "libata.h"  #include "libata-transport.h" @@ -79,6 +81,8 @@ const struct ata_port_operations ata_base_port_ops = {  	.prereset		= ata_std_prereset,  	.postreset		= ata_std_postreset,  	.error_handler		= ata_std_error_handler, +	.sched_eh		= ata_std_sched_eh, +	.end_eh			= ata_std_end_eh,  };  const struct ata_port_operations sata_port_ops = { @@ -94,7 +98,7 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev);  static void ata_dev_xfermask(struct ata_device *dev);  static unsigned long ata_dev_blacklisted(const struct ata_device *dev); -unsigned int ata_print_id = 1; +atomic_t ata_print_id = ATOMIC_INIT(0);  struct ata_force_param {  	const char	*name; @@ -335,8 +339,7 @@ void ata_force_cbl(struct ata_port *ap)  			continue;  		ap->cbl = fe->param.cbl; -		ata_port_printk(ap, KERN_NOTICE, -				"FORCE: cable set to %s\n", fe->param.name); +		ata_port_notice(ap, "FORCE: cable set to %s\n", fe->param.name);  		return;  	}  } @@ -378,8 +381,7 @@ static void ata_force_link_limits(struct ata_link *link)  		/* only honor the first spd limit */  		if (!did_spd && fe->param.spd_limit) {  			link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1; -			ata_link_printk(link, KERN_NOTICE, -					"FORCE: PHY spd limit set to %s\n", +			ata_link_notice(link, "FORCE: PHY spd limit set to %s\n",  					fe->param.name);  			did_spd = true;  		} @@ -387,7 +389,7 @@ static void ata_force_link_limits(struct ata_link *link)  		/* let lflags stack */  		if (fe->param.lflags) {  			link->flags |= fe->param.lflags; -			ata_link_printk(link, KERN_NOTICE, +			ata_link_notice(link,  					"FORCE: link flag 0x%x forced -> 0x%x\n",  					fe->param.lflags, link->flags);  		} @@ -442,8 +444,8 @@ static void ata_force_xfermask(struct ata_device *dev)  			dev->pio_mask = pio_mask;  		} -		ata_dev_printk(dev, KERN_NOTICE, -			"FORCE: xfer_mask set to %s\n", fe->param.name); +		ata_dev_notice(dev, "FORCE: xfer_mask set to %s\n", +			       fe->param.name);  		return;  	}  } @@ -486,8 +488,8 @@ static void ata_force_horkage(struct ata_device *dev)  		dev->horkage |= fe->param.horkage_on;  		dev->horkage &= ~fe->param.horkage_off; -		ata_dev_printk(dev, KERN_NOTICE, -			"FORCE: horkage modified (%s)\n", fe->param.name); +		ata_dev_notice(dev, "FORCE: horkage modified (%s)\n", +			       fe->param.name);  	}  } @@ -567,10 +569,10 @@ void ata_tf_to_fis(const struct ata_taskfile *tf, u8 pmp, int is_cmd, u8 *fis)  	fis[14] = 0;  	fis[15] = tf->ctl; -	fis[16] = 0; -	fis[17] = 0; -	fis[18] = 0; -	fis[19] = 0; +	fis[16] = tf->auxiliary & 0xff; +	fis[17] = (tf->auxiliary >> 8) & 0xff; +	fis[18] = (tf->auxiliary >> 16) & 0xff; +	fis[19] = (tf->auxiliary >> 24) & 0xff;  }  /** @@ -711,8 +713,8 @@ u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)  		sect = tf->lbal;  		if (!sect) { -			ata_dev_printk(dev, KERN_WARNING, "device reported " -				       "invalid CHS sector 0\n"); +			ata_dev_warn(dev, +				     "device reported invalid CHS sector 0\n");  			sect = 1; /* oh well */  		} @@ -773,7 +775,7 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,  		tf->lbam = (block >> 8) & 0xff;  		tf->lbal = block & 0xff; -		tf->device = 1 << 6; +		tf->device = ATA_LBA;  		if (tf->flags & ATA_TFLAG_FUA)  			tf->device |= 1 << 7;  	} else if (dev->flags & ATA_DFLAG_LBA) { @@ -1230,8 +1232,9 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)  	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);  	if (err_mask) { -		ata_dev_printk(dev, KERN_WARNING, "failed to read native " -			       "max address (err_mask=0x%x)\n", err_mask); +		ata_dev_warn(dev, +			     "failed to read native max address (err_mask=0x%x)\n", +			     err_mask);  		if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED))  			return -EACCES;  		return -EIO; @@ -1292,8 +1295,9 @@ static int ata_set_max_sectors(struct ata_device *dev, u64 new_sectors)  	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);  	if (err_mask) { -		ata_dev_printk(dev, KERN_WARNING, "failed to set " -			       "max address (err_mask=0x%x)\n", err_mask); +		ata_dev_warn(dev, +			     "failed to set max address (err_mask=0x%x)\n", +			     err_mask);  		if (err_mask == AC_ERR_DEV &&  		    (tf.feature & (ATA_ABORTED | ATA_IDNF)))  			return -EACCES; @@ -1336,8 +1340,8 @@ static int ata_hpa_resize(struct ata_device *dev)  		 * be unlocked, skip HPA resizing.  		 */  		if (rc == -EACCES || !unlock_hpa) { -			ata_dev_printk(dev, KERN_WARNING, "HPA support seems " -				       "broken, skipping HPA handling\n"); +			ata_dev_warn(dev, +				     "HPA support seems broken, skipping HPA handling\n");  			dev->horkage |= ATA_HORKAGE_BROKEN_HPA;  			/* we can continue if device aborted the command */ @@ -1355,14 +1359,13 @@ static int ata_hpa_resize(struct ata_device *dev)  			return 0;  		if (native_sectors > sectors) -			ata_dev_printk(dev, KERN_INFO, +			ata_dev_info(dev,  				"HPA detected: current %llu, native %llu\n",  				(unsigned long long)sectors,  				(unsigned long long)native_sectors);  		else if (native_sectors < sectors) -			ata_dev_printk(dev, KERN_WARNING, -				"native sectors (%llu) is smaller than " -				"sectors (%llu)\n", +			ata_dev_warn(dev, +				"native sectors (%llu) is smaller than sectors (%llu)\n",  				(unsigned long long)native_sectors,  				(unsigned long long)sectors);  		return 0; @@ -1372,10 +1375,10 @@ static int ata_hpa_resize(struct ata_device *dev)  	rc = ata_set_max_sectors(dev, native_sectors);  	if (rc == -EACCES) {  		/* if device aborted the command, skip HPA resizing */ -		ata_dev_printk(dev, KERN_WARNING, "device aborted resize " -			       "(%llu -> %llu), skipping HPA handling\n", -			       (unsigned long long)sectors, -			       (unsigned long long)native_sectors); +		ata_dev_warn(dev, +			     "device aborted resize (%llu -> %llu), skipping HPA handling\n", +			     (unsigned long long)sectors, +			     (unsigned long long)native_sectors);  		dev->horkage |= ATA_HORKAGE_BROKEN_HPA;  		return 0;  	} else if (rc) @@ -1384,14 +1387,14 @@ static int ata_hpa_resize(struct ata_device *dev)  	/* re-read IDENTIFY data */  	rc = ata_dev_reread_id(dev, 0);  	if (rc) { -		ata_dev_printk(dev, KERN_ERR, "failed to re-read IDENTIFY " -			       "data after HPA resizing\n"); +		ata_dev_err(dev, +			    "failed to re-read IDENTIFY data after HPA resizing\n");  		return rc;  	}  	if (print_info) {  		u64 new_sectors = ata_id_n_sectors(dev->id); -		ata_dev_printk(dev, KERN_INFO, +		ata_dev_info(dev,  			"HPA unlocked: %llu -> %llu, native %llu\n",  			(unsigned long long)sectors,  			(unsigned long long)new_sectors, @@ -1521,7 +1524,7 @@ static void ata_qc_complete_internal(struct ata_queued_cmd *qc)   *	@dev: Device to which the command is sent   *	@tf: Taskfile registers for the command and the result   *	@cdb: CDB for packet command - *	@dma_dir: Data tranfer direction of the command + *	@dma_dir: Data transfer direction of the command   *	@sgl: sg list for the data buffer of the command   *	@n_elem: Number of sg entries   *	@timeout: Timeout in msecs (0 for default) @@ -1599,6 +1602,12 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,  	qc->tf = *tf;  	if (cdb)  		memcpy(qc->cdb, cdb, ATAPI_CDB_LEN); + +	/* some SATA bridges need us to indicate data xfer direction */ +	if (tf->protocol == ATAPI_PROT_DMA && (dev->flags & ATA_DFLAG_DMADIR) && +	    dma_dir == DMA_FROM_DEVICE) +		qc->tf.feature |= ATAPI_DMADIR; +  	qc->flags |= ATA_QCFLAG_RESULT_TF;  	qc->dma_dir = dma_dir;  	if (dma_dir != DMA_NONE) { @@ -1655,8 +1664,8 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,  				ata_qc_complete(qc);  			if (ata_msg_warn(ap)) -				ata_dev_printk(dev, KERN_WARNING, -					"qc timeout (cmd 0x%x)\n", command); +				ata_dev_warn(dev, "qc timeout (cmd 0x%x)\n", +					     command);  		}  		spin_unlock_irqrestore(ap->lock, flags); @@ -1703,7 +1712,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,   *	@dev: Device to which the command is sent   *	@tf: Taskfile registers for the command and the result   *	@cdb: CDB for packet command - *	@dma_dir: Data tranfer direction of the command + *	@dma_dir: Data transfer direction of the command   *	@buf: Data buffer of the command   *	@buflen: Length of data buffer   *	@timeout: Timeout in msecs (0 for default) @@ -1870,7 +1879,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,  	int rc;  	if (ata_msg_ctl(ap)) -		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__); +		ata_dev_dbg(dev, "%s: ENTER\n", __func__);  retry:  	ata_tf_init(dev, &tf); @@ -1909,14 +1918,13 @@ retry:  	if (err_mask) {  		if (err_mask & AC_ERR_NODEV_HINT) { -			ata_dev_printk(dev, KERN_DEBUG, -				       "NODEV after polling detection\n"); +			ata_dev_dbg(dev, "NODEV after polling detection\n");  			return -ENOENT;  		}  		if (is_semb) { -			ata_dev_printk(dev, KERN_INFO, "IDENTIFY failed on " -				       "device w/ SEMB sig, disabled\n"); +			ata_dev_info(dev, +		     "IDENTIFY failed on device w/ SEMB sig, disabled\n");  			/* SEMB is not supported yet */  			*p_class = ATA_DEV_SEMB_UNSUP;  			return 0; @@ -1942,8 +1950,8 @@ retry:  			 * both flavors of IDENTIFYs which happens  			 * sometimes with phantom devices.  			 */ -			ata_dev_printk(dev, KERN_DEBUG, -				       "both IDENTIFYs aborted, assuming NODEV\n"); +			ata_dev_dbg(dev, +				    "both IDENTIFYs aborted, assuming NODEV\n");  			return -ENOENT;  		} @@ -1953,9 +1961,9 @@ retry:  	}  	if (dev->horkage & ATA_HORKAGE_DUMP_ID) { -		ata_dev_printk(dev, KERN_DEBUG, "dumping IDENTIFY data, " -			       "class=%d may_fallback=%d tried_spinup=%d\n", -			       class, may_fallback, tried_spinup); +		ata_dev_dbg(dev, "dumping IDENTIFY data, " +			    "class=%d may_fallback=%d tried_spinup=%d\n", +			    class, may_fallback, tried_spinup);  		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,  			       16, 2, id, ATA_ID_WORDS * sizeof(*id), true);  	} @@ -1974,6 +1982,12 @@ retry:  	if (class == ATA_DEV_ATA) {  		if (!ata_id_is_ata(id) && !ata_id_is_cfa(id))  			goto err_out; +		if (ap->host->flags & ATA_HOST_IGNORE_ATA && +							ata_id_is_ata(id)) { +			ata_dev_dbg(dev, +				"host indicates ignore ATA devices, ignored\n"); +			return -ENOENT; +		}  	} else {  		if (ata_id_is_ata(id))  			goto err_out; @@ -2034,8 +2048,8 @@ retry:   err_out:  	if (ata_msg_warn(ap)) -		ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY " -			       "(%s, err_mask=0x%x)\n", reason, err_mask); +		ata_dev_warn(dev, "failed to IDENTIFY (%s, err_mask=0x%x)\n", +			     reason, err_mask);  	return rc;  } @@ -2065,9 +2079,8 @@ static int ata_do_link_spd_horkage(struct ata_device *dev)  	 * guaranteed by setting sata_spd_limit to target_limit above.  	 */  	if (plink->sata_spd > target) { -		ata_dev_printk(dev, KERN_INFO, -			       "applying link speed limit horkage to %s\n", -			       sata_spd_string(target)); +		ata_dev_info(dev, "applying link speed limit horkage to %s\n", +			     sata_spd_string(target));  		return -EAGAIN;  	}  	return 0; @@ -2110,8 +2123,9 @@ static int ata_dev_config_ncq(struct ata_device *dev,  		err_mask = ata_dev_set_feature(dev, SETFEATURES_SATA_ENABLE,  			SATA_FPDMA_AA);  		if (err_mask) { -			ata_dev_printk(dev, KERN_ERR, "failed to enable AA" -				"(error_mask=0x%x)\n", err_mask); +			ata_dev_err(dev, +				    "failed to enable AA (error_mask=0x%x)\n", +				    err_mask);  			if (err_mask != AC_ERR_DEV) {  				dev->horkage |= ATA_HORKAGE_BROKEN_FPDMA_AA;  				return -EIO; @@ -2125,6 +2139,29 @@ static int ata_dev_config_ncq(struct ata_device *dev,  	else  		snprintf(desc, desc_sz, "NCQ (depth %d/%d)%s", hdepth,  			ddepth, aa_desc); + +	if ((ap->flags & ATA_FLAG_FPDMA_AUX) && +	    ata_id_has_ncq_send_and_recv(dev->id)) { +		err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_SEND_RECV, +					     0, ap->sector_buf, 1); +		if (err_mask) { +			ata_dev_dbg(dev, +				    "failed to get NCQ Send/Recv Log Emask 0x%x\n", +				    err_mask); +		} else { +			u8 *cmds = dev->ncq_send_recv_cmds; + +			dev->flags |= ATA_DFLAG_NCQ_SEND_RECV; +			memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE); + +			if (dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) { +				ata_dev_dbg(dev, "disabling queued TRIM support\n"); +				cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &= +					~ATA_LOG_NCQ_SEND_RECV_DSM_TRIM; +			} +		} +	} +  	return 0;  } @@ -2148,37 +2185,35 @@ int ata_dev_configure(struct ata_device *dev)  	int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;  	const u16 *id = dev->id;  	unsigned long xfer_mask; +	unsigned int err_mask;  	char revbuf[7];		/* XYZ-99\0 */  	char fwrevbuf[ATA_ID_FW_REV_LEN+1];  	char modelbuf[ATA_ID_PROD_LEN+1];  	int rc;  	if (!ata_dev_enabled(dev) && ata_msg_info(ap)) { -		ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT -- nodev\n", -			       __func__); +		ata_dev_info(dev, "%s: ENTER/EXIT -- nodev\n", __func__);  		return 0;  	}  	if (ata_msg_probe(ap)) -		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__); +		ata_dev_dbg(dev, "%s: ENTER\n", __func__);  	/* set horkage */  	dev->horkage |= ata_dev_blacklisted(dev);  	ata_force_horkage(dev);  	if (dev->horkage & ATA_HORKAGE_DISABLE) { -		ata_dev_printk(dev, KERN_INFO, -			       "unsupported device, disabling\n"); +		ata_dev_info(dev, "unsupported device, disabling\n");  		ata_dev_disable(dev);  		return 0;  	}  	if ((!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) &&  	    dev->class == ATA_DEV_ATAPI) { -		ata_dev_printk(dev, KERN_WARNING, -			"WARNING: ATAPI is %s, device ignored.\n", -			atapi_enabled ? "not supported with this driver" -				      : "disabled"); +		ata_dev_warn(dev, "WARNING: ATAPI is %s, device ignored\n", +			     atapi_enabled ? "not supported with this driver" +			     : "disabled");  		ata_dev_disable(dev);  		return 0;  	} @@ -2187,6 +2222,16 @@ int ata_dev_configure(struct ata_device *dev)  	if (rc)  		return rc; +	/* some WD SATA-1 drives have issues with LPM, turn on NOLPM for them */ +	if ((dev->horkage & ATA_HORKAGE_WD_BROKEN_LPM) && +	    (id[ATA_ID_SATA_CAPABILITY] & 0xe) == 0x2) +		dev->horkage |= ATA_HORKAGE_NOLPM; + +	if (dev->horkage & ATA_HORKAGE_NOLPM) { +		ata_dev_warn(dev, "LPM support broken, forcing max_power\n"); +		dev->link->ap->target_lpm_policy = ATA_LPM_MAX_POWER; +	} +  	/* let ACPI work its magic */  	rc = ata_acpi_on_devcfg(dev);  	if (rc) @@ -2199,12 +2244,12 @@ int ata_dev_configure(struct ata_device *dev)  	/* print device capabilities */  	if (ata_msg_probe(ap)) -		ata_dev_printk(dev, KERN_DEBUG, -			       "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x " -			       "85:%04x 86:%04x 87:%04x 88:%04x\n", -			       __func__, -			       id[49], id[82], id[83], id[84], -			       id[85], id[86], id[87], id[88]); +		ata_dev_dbg(dev, +			    "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x " +			    "85:%04x 86:%04x 87:%04x 88:%04x\n", +			    __func__, +			    id[49], id[82], id[83], id[84], +			    id[85], id[86], id[87], id[88]);  	/* initialize to-be-configured parameters */  	dev->flags &= ~ATA_DFLAG_CFG_MASK; @@ -2238,17 +2283,15 @@ int ata_dev_configure(struct ata_device *dev)  		if (ata_id_is_cfa(id)) {  			/* CPRM may make this media unusable */  			if (id[ATA_ID_CFA_KEY_MGMT] & 1) -				ata_dev_printk(dev, KERN_WARNING, -					       "supports DRM functions and may " -					       "not be fully accessable.\n"); +				ata_dev_warn(dev, +	"supports DRM functions and may not be fully accessible\n");  			snprintf(revbuf, 7, "CFA");  		} else {  			snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));  			/* Warn the user if the device has TPM extensions */  			if (ata_id_has_tpm(id)) -				ata_dev_printk(dev, KERN_WARNING, -					       "supports DRM functions and may " -					       "not be fully accessable.\n"); +				ata_dev_warn(dev, +	"supports DRM functions and may not be fully accessible\n");  		}  		dev->n_sectors = ata_id_n_sectors(id); @@ -2285,12 +2328,11 @@ int ata_dev_configure(struct ata_device *dev)  			/* print device info to dmesg */  			if (ata_msg_drv(ap) && print_info) { -				ata_dev_printk(dev, KERN_INFO, -					"%s: %s, %s, max %s\n", -					revbuf, modelbuf, fwrevbuf, -					ata_mode_string(xfer_mask)); -				ata_dev_printk(dev, KERN_INFO, -					"%Lu sectors, multi %u: %s %s\n", +				ata_dev_info(dev, "%s: %s, %s, max %s\n", +					     revbuf, modelbuf, fwrevbuf, +					     ata_mode_string(xfer_mask)); +				ata_dev_info(dev, +					     "%llu sectors, multi %u: %s %s\n",  					(unsigned long long)dev->n_sectors,  					dev->multi_count, lba_desc, ncq_desc);  			} @@ -2311,18 +2353,41 @@ int ata_dev_configure(struct ata_device *dev)  			/* print device info to dmesg */  			if (ata_msg_drv(ap) && print_info) { -				ata_dev_printk(dev, KERN_INFO, -					"%s: %s, %s, max %s\n", -					revbuf,	modelbuf, fwrevbuf, -					ata_mode_string(xfer_mask)); -				ata_dev_printk(dev, KERN_INFO, -					"%Lu sectors, multi %u, CHS %u/%u/%u\n", -					(unsigned long long)dev->n_sectors, -					dev->multi_count, dev->cylinders, -					dev->heads, dev->sectors); +				ata_dev_info(dev, "%s: %s, %s, max %s\n", +					     revbuf,	modelbuf, fwrevbuf, +					     ata_mode_string(xfer_mask)); +				ata_dev_info(dev, +					     "%llu sectors, multi %u, CHS %u/%u/%u\n", +					     (unsigned long long)dev->n_sectors, +					     dev->multi_count, dev->cylinders, +					     dev->heads, dev->sectors);  			}  		} +		/* Check and mark DevSlp capability. Get DevSlp timing variables +		 * from SATA Settings page of Identify Device Data Log. +		 */ +		if (ata_id_has_devslp(dev->id)) { +			u8 *sata_setting = ap->sector_buf; +			int i, j; + +			dev->flags |= ATA_DFLAG_DEVSLP; +			err_mask = ata_read_log_page(dev, +						     ATA_LOG_SATA_ID_DEV_DATA, +						     ATA_LOG_SATA_SETTINGS, +						     sata_setting, +						     1); +			if (err_mask) +				ata_dev_dbg(dev, +					    "failed to get Identify Device Data, Emask 0x%x\n", +					    err_mask); +			else +				for (i = 0; i < ATA_LOG_DEVSLP_SIZE; i++) { +					j = ATA_LOG_DEVSLP_OFFSET + i; +					dev->devslp_timing[i] = sata_setting[j]; +				} +		} +  		dev->cdb_len = 16;  	} @@ -2336,8 +2401,7 @@ int ata_dev_configure(struct ata_device *dev)  		rc = atapi_cdb_len(id);  		if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {  			if (ata_msg_warn(ap)) -				ata_dev_printk(dev, KERN_WARNING, -					       "unsupported CDB len\n"); +				ata_dev_warn(dev, "unsupported CDB len\n");  			rc = -EINVAL;  			goto err_out_nosup;  		} @@ -2352,15 +2416,13 @@ int ata_dev_configure(struct ata_device *dev)  		    (ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&  		    (!sata_pmp_attached(ap) ||  		     sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) { -			unsigned int err_mask; -  			/* issue SET feature command to turn this on */  			err_mask = ata_dev_set_feature(dev,  					SETFEATURES_SATA_ENABLE, SATA_AN);  			if (err_mask) -				ata_dev_printk(dev, KERN_ERR, -					"failed to enable ATAPI AN " -					"(err_mask=0x%x)\n", err_mask); +				ata_dev_err(dev, +					    "failed to enable ATAPI AN (err_mask=0x%x)\n", +					    err_mask);  			else {  				dev->flags |= ATA_DFLAG_AN;  				atapi_an_string = ", ATAPI AN"; @@ -2372,19 +2434,24 @@ int ata_dev_configure(struct ata_device *dev)  			cdb_intr_string = ", CDB intr";  		} -		if (atapi_dmadir || atapi_id_dmadir(dev->id)) { +		if (atapi_dmadir || (dev->horkage & ATA_HORKAGE_ATAPI_DMADIR) || atapi_id_dmadir(dev->id)) {  			dev->flags |= ATA_DFLAG_DMADIR;  			dma_dir_string = ", DMADIR";  		} +		if (ata_id_has_da(dev->id)) { +			dev->flags |= ATA_DFLAG_DA; +			zpodd_init(dev); +		} +  		/* print device info to dmesg */  		if (ata_msg_drv(ap) && print_info) -			ata_dev_printk(dev, KERN_INFO, -				       "ATAPI: %s, %s, max %s%s%s%s\n", -				       modelbuf, fwrevbuf, -				       ata_mode_string(xfer_mask), -				       cdb_intr_string, atapi_an_string, -				       dma_dir_string); +			ata_dev_info(dev, +				     "ATAPI: %s, %s, max %s%s%s%s\n", +				     modelbuf, fwrevbuf, +				     ata_mode_string(xfer_mask), +				     cdb_intr_string, atapi_an_string, +				     dma_dir_string);  	}  	/* determine max_sectors */ @@ -2396,8 +2463,7 @@ int ata_dev_configure(struct ata_device *dev)  	   200 sectors */  	if (ata_dev_knobble(dev)) {  		if (ata_msg_drv(ap) && print_info) -			ata_dev_printk(dev, KERN_INFO, -				       "applying bridge limits\n"); +			ata_dev_info(dev, "applying bridge limits\n");  		dev->udma_mask &= ATA_UDMA5;  		dev->max_sectors = ATA_MAX_SECTORS;  	} @@ -2412,6 +2478,9 @@ int ata_dev_configure(struct ata_device *dev)  		dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,  					 dev->max_sectors); +	if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48) +		dev->max_sectors = ATA_MAX_SECTORS_LBA48; +  	if (ap->ops->dev_config)  		ap->ops->dev_config(dev); @@ -2423,26 +2492,23 @@ int ata_dev_configure(struct ata_device *dev)  		   bugs */  		if (print_info) { -			ata_dev_printk(dev, KERN_WARNING, +			ata_dev_warn(dev,  "Drive reports diagnostics failure. This may indicate a drive\n"); -			ata_dev_printk(dev, KERN_WARNING, +			ata_dev_warn(dev,  "fault or invalid emulation. Contact drive vendor for information.\n");  		}  	}  	if ((dev->horkage & ATA_HORKAGE_FIRMWARE_WARN) && print_info) { -		ata_dev_printk(dev, KERN_WARNING, "WARNING: device requires " -			       "firmware update to be fully functional.\n"); -		ata_dev_printk(dev, KERN_WARNING, "         contact the vendor " -			       "or visit http://ata.wiki.kernel.org.\n"); +		ata_dev_warn(dev, "WARNING: device requires firmware update to be fully functional\n"); +		ata_dev_warn(dev, "         contact the vendor or visit http://ata.wiki.kernel.org\n");  	}  	return 0;  err_out_nosup:  	if (ata_msg_probe(ap)) -		ata_dev_printk(dev, KERN_DEBUG, -			       "%s: EXIT, err\n", __func__); +		ata_dev_dbg(dev, "%s: EXIT, err\n", __func__);  	return rc;  } @@ -2543,6 +2609,7 @@ int ata_bus_probe(struct ata_port *ap)  		 * bus as we may be talking too fast.  		 */  		dev->pio_mode = XFER_PIO_0; +		dev->dma_mode = 0xff;  		/* If the controller has a pio mode setup function  		 * then use it to set the chipset to rights. Don't @@ -2663,13 +2730,11 @@ static void sata_print_link_status(struct ata_link *link)  	if (ata_phys_link_online(link)) {  		tmp = (sstatus >> 4) & 0xf; -		ata_link_printk(link, KERN_INFO, -				"SATA link up %s (SStatus %X SControl %X)\n", -				sata_spd_string(tmp), sstatus, scontrol); +		ata_link_info(link, "SATA link up %s (SStatus %X SControl %X)\n", +			      sata_spd_string(tmp), sstatus, scontrol);  	} else { -		ata_link_printk(link, KERN_INFO, -				"SATA link down (SStatus %X SControl %X)\n", -				sstatus, scontrol); +		ata_link_info(link, "SATA link down (SStatus %X SControl %X)\n", +			      sstatus, scontrol);  	}  } @@ -2758,8 +2823,8 @@ int sata_down_spd_limit(struct ata_link *link, u32 spd_limit)  	link->sata_spd_limit = mask; -	ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n", -			sata_spd_string(fls(mask))); +	ata_link_warn(link, "limiting SATA link speed to %s\n", +		      sata_spd_string(fls(mask)));  	return 0;  } @@ -2927,6 +2992,10 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)  	if (xfer_mode == t->mode)  		return t; + +	WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n", +			__func__, xfer_mode); +  	return NULL;  } @@ -2954,7 +3023,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,  	if (id[ATA_ID_FIELD_VALID] & 2) {	/* EIDE drive */  		memset(&p, 0, sizeof(p)); -		if (speed >= XFER_PIO_0 && speed <= XFER_SW_DMA_0) { +		if (speed >= XFER_PIO_0 && speed < XFER_SW_DMA_0) {  			if (speed <= XFER_PIO_2)  				p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];  			else if ((speed <= XFER_PIO_4) || @@ -3136,8 +3205,7 @@ int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel)  			snprintf(buf, sizeof(buf), "%s",  				 ata_mode_string(xfer_mask)); -		ata_dev_printk(dev, KERN_WARNING, -			       "limiting speed to %s\n", buf); +		ata_dev_warn(dev, "limiting speed to %s\n", buf);  	}  	ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, @@ -3164,9 +3232,9 @@ static int ata_dev_set_mode(struct ata_device *dev)  		dev_err_whine = " (SET_XFERMODE skipped)";  	else {  		if (nosetxfer) -			ata_dev_printk(dev, KERN_WARNING, -				       "NOSETXFER but PATA detected - can't " -				       "skip SETXFER, might malfunction\n"); +			ata_dev_warn(dev, +				     "NOSETXFER but PATA detected - can't " +				     "skip SETXFER, might malfunction\n");  		err_mask = ata_dev_set_xfermode(dev);  	} @@ -3216,15 +3284,14 @@ static int ata_dev_set_mode(struct ata_device *dev)  	DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n",  		dev->xfer_shift, (int)dev->xfer_mode); -	ata_dev_printk(dev, KERN_INFO, "configured for %s%s\n", -		       ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)), -		       dev_err_whine); +	ata_dev_info(dev, "configured for %s%s\n", +		     ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)), +		     dev_err_whine);  	return 0;   fail: -	ata_dev_printk(dev, KERN_ERR, "failed to set xfermode " -		       "(err_mask=0x%x)\n", err_mask); +	ata_dev_err(dev, "failed to set xfermode (err_mask=0x%x)\n", err_mask);  	return -EIO;  } @@ -3266,10 +3333,10 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)  		ata_force_xfermask(dev);  		pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0); -		dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);  		if (libata_dma_mask & mode_mask) -			dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); +			dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, +						     dev->udma_mask);  		else  			dma_mask = 0; @@ -3286,7 +3353,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)  	/* step 2: always set host PIO timings */  	ata_for_each_dev(dev, link, ENABLED) {  		if (dev->pio_mode == 0xff) { -			ata_dev_printk(dev, KERN_WARNING, "no PIO support\n"); +			ata_dev_warn(dev, "no PIO support\n");  			rc = -EINVAL;  			goto out;  		} @@ -3404,7 +3471,7 @@ int ata_wait_ready(struct ata_link *link, unsigned long deadline,  		if (!warned && time_after(now, start + 5 * HZ) &&  		    (deadline - now > 3 * HZ)) { -			ata_link_printk(link, KERN_WARNING, +			ata_link_warn(link,  				"link is slow to respond, please be patient "  				"(ready=%d)\n", tmp);  			warned = 1; @@ -3552,16 +3619,14 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,  	} while ((scontrol & 0xf0f) != 0x300 && --tries);  	if ((scontrol & 0xf0f) != 0x300) { -		ata_link_printk(link, KERN_ERR, -				"failed to resume link (SControl %X)\n", -				scontrol); +		ata_link_warn(link, "failed to resume link (SControl %X)\n", +			     scontrol);  		return 0;  	}  	if (tries < ATA_LINK_RESUME_TRIES) -		ata_link_printk(link, KERN_WARNING, -				"link resume succeeded after %d retries\n", -				ATA_LINK_RESUME_TRIES - tries); +		ata_link_warn(link, "link resume succeeded after %d retries\n", +			      ATA_LINK_RESUME_TRIES - tries);  	if ((rc = sata_link_debounce(link, params, deadline)))  		return rc; @@ -3606,7 +3671,7 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,  	switch (policy) {  	case ATA_LPM_MAX_POWER:  		/* disable all LPM transitions */ -		scontrol |= (0x3 << 8); +		scontrol |= (0x7 << 8);  		/* initiate transition to active state */  		if (spm_wakeup) {  			scontrol |= (0x4 << 12); @@ -3616,11 +3681,17 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,  	case ATA_LPM_MED_POWER:  		/* allow LPM to PARTIAL */  		scontrol &= ~(0x1 << 8); -		scontrol |= (0x2 << 8); +		scontrol |= (0x6 << 8);  		break;  	case ATA_LPM_MIN_POWER: -		/* no restrictions on LPM transitions */ -		scontrol &= ~(0x3 << 8); +		if (ata_link_nr_enabled(link) > 0) +			/* no restrictions on LPM transitions */ +			scontrol &= ~(0x7 << 8); +		else { +			/* empty port, power off */ +			scontrol &= ~0xf; +			scontrol |= (0x1 << 2); +		}  		break;  	default:  		WARN_ON(1); @@ -3672,8 +3743,9 @@ int ata_std_prereset(struct ata_link *link, unsigned long deadline)  		rc = sata_link_resume(link, timing, deadline);  		/* whine about phy resume failure but proceed */  		if (rc && rc != -EOPNOTSUPP) -			ata_link_printk(link, KERN_WARNING, "failed to resume " -					"link for reset (errno=%d)\n", rc); +			ata_link_warn(link, +				      "failed to resume link for reset (errno=%d)\n", +				      rc);  	}  	/* no point in trying softreset on offline link */ @@ -3789,8 +3861,7 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,  		/* online is set iff link is online && reset succeeded */  		if (online)  			*online = false; -		ata_link_printk(link, KERN_ERR, -				"COMRESET failed (errno=%d)\n", rc); +		ata_link_err(link, "COMRESET failed (errno=%d)\n", rc);  	}  	DPRINTK("EXIT, rc=%d\n", rc);  	return rc; @@ -3874,8 +3945,8 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,  	unsigned char serial[2][ATA_ID_SERNO_LEN + 1];  	if (dev->class != new_class) { -		ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n", -			       dev->class, new_class); +		ata_dev_info(dev, "class mismatch %d != %d\n", +			     dev->class, new_class);  		return 0;  	} @@ -3885,14 +3956,14 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,  	ata_id_c_string(new_id, serial[1], ATA_ID_SERNO, sizeof(serial[1]));  	if (strcmp(model[0], model[1])) { -		ata_dev_printk(dev, KERN_INFO, "model number mismatch " -			       "'%s' != '%s'\n", model[0], model[1]); +		ata_dev_info(dev, "model number mismatch '%s' != '%s'\n", +			     model[0], model[1]);  		return 0;  	}  	if (strcmp(serial[0], serial[1])) { -		ata_dev_printk(dev, KERN_INFO, "serial number mismatch " -			       "'%s' != '%s'\n", serial[0], serial[1]); +		ata_dev_info(dev, "serial number mismatch '%s' != '%s'\n", +			     serial[0], serial[1]);  		return 0;  	} @@ -3962,8 +4033,8 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,  	    new_class != ATA_DEV_ATA &&  	    new_class != ATA_DEV_ATAPI &&  	    new_class != ATA_DEV_SEMB) { -		ata_dev_printk(dev, KERN_INFO, "class mismatch %u != %u\n", -			       dev->class, new_class); +		ata_dev_info(dev, "class mismatch %u != %u\n", +			     dev->class, new_class);  		rc = -ENODEV;  		goto fail;  	} @@ -3984,9 +4055,9 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,  		return 0;  	/* n_sectors has changed */ -	ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch %llu != %llu\n", -		       (unsigned long long)n_sectors, -		       (unsigned long long)dev->n_sectors); +	ata_dev_warn(dev, "n_sectors mismatch %llu != %llu\n", +		     (unsigned long long)n_sectors, +		     (unsigned long long)dev->n_sectors);  	/*  	 * Something could have caused HPA to be unlocked @@ -3995,9 +4066,9 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,  	 */  	if (dev->n_native_sectors == n_native_sectors &&  	    dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) { -		ata_dev_printk(dev, KERN_WARNING, -			       "new n_sectors matches native, probably " -			       "late HPA unlock, n_sectors updated\n"); +		ata_dev_warn(dev, +			     "new n_sectors matches native, probably " +			     "late HPA unlock, n_sectors updated\n");  		/* use the larger n_sectors */  		return 0;  	} @@ -4011,9 +4082,9 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,  	if (dev->n_native_sectors == n_native_sectors &&  	    dev->n_sectors < n_sectors && n_sectors == n_native_sectors &&  	    !(dev->horkage & ATA_HORKAGE_BROKEN_HPA)) { -		ata_dev_printk(dev, KERN_WARNING, -			       "old n_sectors matches native, probably " -			       "late HPA lock, will try to unlock HPA\n"); +		ata_dev_warn(dev, +			     "old n_sectors matches native, probably " +			     "late HPA lock, will try to unlock HPA\n");  		/* try unlocking HPA */  		dev->flags |= ATA_DFLAG_UNLOCK_HPA;  		rc = -EIO; @@ -4024,7 +4095,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,  	dev->n_native_sectors = n_native_sectors;  	dev->n_sectors = n_sectors;   fail: -	ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc); +	ata_dev_err(dev, "revalidation failed (errno=%d)\n", rc);  	return rc;  } @@ -4064,12 +4135,15 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {  	{ "_NEC DV5800A", 	NULL,		ATA_HORKAGE_NODMA },  	{ "SAMSUNG CD-ROM SN-124", "N001",	ATA_HORKAGE_NODMA },  	{ "Seagate STT20000A", NULL,		ATA_HORKAGE_NODMA }, +	{ " 2GB ATA Flash Disk", "ADMA428M",	ATA_HORKAGE_NODMA },  	/* Odd clown on sil3726/4726 PMPs */  	{ "Config  Disk",	NULL,		ATA_HORKAGE_DISABLE },  	/* Weird ATAPI devices */  	{ "TORiSAN DVD-ROM DRD-N216", NULL,	ATA_HORKAGE_MAX_SEC_128 },  	{ "QUANTUM DAT    DAT72-000", NULL,	ATA_HORKAGE_ATAPI_MOD16_DMA }, +	{ "Slimtype DVD A  DS8A8SH", NULL,	ATA_HORKAGE_MAX_SEC_LBA48 }, +	{ "Slimtype DVD A  DS8A9SH", NULL,	ATA_HORKAGE_MAX_SEC_LBA48 },  	/* Devices we expect to fail diagnostics */ @@ -4099,6 +4173,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {  	{ "ST3320[68]13AS",	"SD1[5-9]",	ATA_HORKAGE_NONCQ |  						ATA_HORKAGE_FIRMWARE_WARN }, +	/* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */ +	{ "ST1000LM024 HN-M101MBB", "2AR10001",	ATA_HORKAGE_BROKEN_FPDMA_AA }, +	{ "ST1000LM024 HN-M101MBB", "2BA30001",	ATA_HORKAGE_BROKEN_FPDMA_AA }, +  	/* Blacklist entries taken from Silicon Image 3124/3132  	   Windows driver .inf file - also several Linux problem reports */  	{ "HTS541060G9SA00",    "MB3OC60D",     ATA_HORKAGE_NONCQ, }, @@ -4129,15 +4207,44 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {  	/* Devices that do not need bridging limits applied */  	{ "MTRON MSP-SATA*",		NULL,	ATA_HORKAGE_BRIDGE_OK, }, +	{ "BUFFALO HD-QSU2/R5",		NULL,	ATA_HORKAGE_BRIDGE_OK, },  	/* Devices which aren't very happy with higher link speeds */  	{ "WD My Book",			NULL,	ATA_HORKAGE_1_5_GBPS, }, +	{ "Seagate FreeAgent GoFlex",	NULL,	ATA_HORKAGE_1_5_GBPS, },  	/*  	 * Devices which choke on SETXFER.  Applies only if both the  	 * device and controller are SATA.  	 */ -	{ "PIONEER DVD-RW  DVRTD08",	"1.00",	ATA_HORKAGE_NOSETXFER }, +	{ "PIONEER DVD-RW  DVRTD08",	NULL,	ATA_HORKAGE_NOSETXFER }, +	{ "PIONEER DVD-RW  DVRTD08A",	NULL,	ATA_HORKAGE_NOSETXFER }, +	{ "PIONEER DVD-RW  DVR-215",	NULL,	ATA_HORKAGE_NOSETXFER }, +	{ "PIONEER DVD-RW  DVR-212D",	NULL,	ATA_HORKAGE_NOSETXFER }, +	{ "PIONEER DVD-RW  DVR-216D",	NULL,	ATA_HORKAGE_NOSETXFER }, + +	/* devices that don't properly handle queued TRIM commands */ +	{ "Micron_M500*",		NULL,	ATA_HORKAGE_NO_NCQ_TRIM, }, +	{ "Crucial_CT???M500SSD*",	NULL,	ATA_HORKAGE_NO_NCQ_TRIM, }, +	{ "Micron_M550*",		NULL,	ATA_HORKAGE_NO_NCQ_TRIM, }, +	{ "Crucial_CT???M550SSD*",	NULL,	ATA_HORKAGE_NO_NCQ_TRIM, }, + +	/* +	 * Some WD SATA-I drives spin up and down erratically when the link +	 * is put into the slumber mode.  We don't have full list of the +	 * affected devices.  Disable LPM if the device matches one of the +	 * known prefixes and is SATA-1.  As a side effect LPM partial is +	 * lost too. +	 * +	 * https://bugzilla.kernel.org/show_bug.cgi?id=57211 +	 */ +	{ "WDC WD800JD-*",		NULL,	ATA_HORKAGE_WD_BROKEN_LPM }, +	{ "WDC WD1200JD-*",		NULL,	ATA_HORKAGE_WD_BROKEN_LPM }, +	{ "WDC WD1600JD-*",		NULL,	ATA_HORKAGE_WD_BROKEN_LPM }, +	{ "WDC WD2000JD-*",		NULL,	ATA_HORKAGE_WD_BROKEN_LPM }, +	{ "WDC WD2500JD-*",		NULL,	ATA_HORKAGE_WD_BROKEN_LPM }, +	{ "WDC WD3000JD-*",		NULL,	ATA_HORKAGE_WD_BROKEN_LPM }, +	{ "WDC WD3200JD-*",		NULL,	ATA_HORKAGE_WD_BROKEN_LPM },  	/* End Marker */  	{ } @@ -4209,7 +4316,7 @@ static int glob_match (const char *text, const char *pattern)  		return 0;  /* End of both strings: match */  	return 1;  /* No match */  } -  +  static unsigned long ata_dev_blacklisted(const struct ata_device *dev)  {  	unsigned char model_num[ATA_ID_PROD_LEN + 1]; @@ -4350,15 +4457,15 @@ static void ata_dev_xfermask(struct ata_device *dev)  	if (ata_dma_blacklisted(dev)) {  		xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); -		ata_dev_printk(dev, KERN_WARNING, -			       "device is on DMA blacklist, disabling DMA\n"); +		ata_dev_warn(dev, +			     "device is on DMA blacklist, disabling DMA\n");  	}  	if ((host->flags & ATA_HOST_SIMPLEX) &&  	    host->simplex_claimed && host->simplex_claimed != ap) {  		xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); -		ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by " -			       "other device, disabling DMA\n"); +		ata_dev_warn(dev, +			     "simplex DMA is claimed by other device, disabling DMA\n");  	}  	if (ap->flags & ATA_FLAG_NO_IORDY) @@ -4378,8 +4485,8 @@ static void ata_dev_xfermask(struct ata_device *dev)  	if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))  		/* UDMA/44 or higher would be available */  		if (cable_is_40wire(ap)) { -			ata_dev_printk(dev, KERN_WARNING, -				 "limited to UDMA/33 due to 40-wire cable\n"); +			ata_dev_warn(dev, +				     "limited to UDMA/33 due to 40-wire cable\n");  			xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);  		} @@ -4467,6 +4574,7 @@ unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, u8 feature)  	DPRINTK("EXIT, err_mask=%x\n", err_mask);  	return err_mask;  } +EXPORT_SYMBOL_GPL(ata_dev_set_feature);  /**   *	ata_dev_init_params - Issue INIT DEV PARAMS command @@ -4679,6 +4787,10 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)   *	ata_qc_new - Request an available ATA command, for queueing   *	@ap: target port   * + *	Some ATA host controllers may implement a queue depth which is less + *	than ATA_MAX_QUEUE. So we shouldn't allocate a tag which is beyond + *	the hardware limitation. + *   *	LOCKING:   *	None.   */ @@ -4686,21 +4798,27 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)  static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)  {  	struct ata_queued_cmd *qc = NULL; -	unsigned int i; +	unsigned int max_queue = ap->host->n_tags; +	unsigned int i, tag;  	/* no command while frozen */  	if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))  		return NULL; -	/* the last tag is reserved for internal command. */ -	for (i = 0; i < ATA_MAX_QUEUE - 1; i++) -		if (!test_and_set_bit(i, &ap->qc_allocated)) { -			qc = __ata_qc_from_tag(ap, i); +	for (i = 0, tag = ap->last_tag + 1; i < max_queue; i++, tag++) { +		tag = tag < max_queue ? tag : 0; + +		/* the last tag is reserved for internal command. */ +		if (tag == ATA_TAG_INTERNAL) +			continue; + +		if (!test_and_set_bit(tag, &ap->qc_allocated)) { +			qc = __ata_qc_from_tag(ap, tag); +			qc->tag = tag; +			ap->last_tag = tag;  			break;  		} - -	if (qc) -		qc->tag = i; +	}  	return qc;  } @@ -4807,9 +4925,6 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc)  {  	struct ata_device *dev = qc->dev; -	if (ata_tag_internal(qc->tag)) -		return; -  	if (ata_is_nodata(qc->tf.protocol))  		return; @@ -4858,14 +4973,23 @@ void ata_qc_complete(struct ata_queued_cmd *qc)  		if (unlikely(qc->err_mask))  			qc->flags |= ATA_QCFLAG_FAILED; -		if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { -			/* always fill result TF for failed qc */ +		/* +		 * Finish internal commands without any further processing +		 * and always with the result TF filled. +		 */ +		if (unlikely(ata_tag_internal(qc->tag))) {  			fill_result_tf(qc); +			__ata_qc_complete(qc); +			return; +		} -			if (!ata_tag_internal(qc->tag)) -				ata_qc_schedule_eh(qc); -			else -				__ata_qc_complete(qc); +		/* +		 * Non-internal qc has failed.  Fill the result TF and +		 * summon EH. +		 */ +		if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { +			fill_result_tf(qc); +			ata_qc_schedule_eh(qc);  			return;  		} @@ -4940,8 +5064,8 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active)  	done_mask = ap->qc_active ^ qc_active;  	if (unlikely(done_mask & qc_active)) { -		ata_port_printk(ap, KERN_ERR, "illegal qc_active transition " -				"(%08x->%08x)\n", ap->qc_active, qc_active); +		ata_port_err(ap, "illegal qc_active transition (%08x->%08x)\n", +			     ap->qc_active, qc_active);  		return -EINVAL;  	} @@ -5240,112 +5364,210 @@ bool ata_link_offline(struct ata_link *link)  }  #ifdef CONFIG_PM -static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg, -			       unsigned int action, unsigned int ehi_flags, -			       int wait) +static void ata_port_request_pm(struct ata_port *ap, pm_message_t mesg, +				unsigned int action, unsigned int ehi_flags, +				bool async)  { +	struct ata_link *link;  	unsigned long flags; -	int i, rc; -	for (i = 0; i < host->n_ports; i++) { -		struct ata_port *ap = host->ports[i]; -		struct ata_link *link; +	/* Previous resume operation might still be in +	 * progress.  Wait for PM_PENDING to clear. +	 */ +	if (ap->pflags & ATA_PFLAG_PM_PENDING) { +		ata_port_wait_eh(ap); +		WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); +	} -		/* Previous resume operation might still be in -		 * progress.  Wait for PM_PENDING to clear. -		 */ -		if (ap->pflags & ATA_PFLAG_PM_PENDING) { -			ata_port_wait_eh(ap); -			WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); -		} +	/* request PM ops to EH */ +	spin_lock_irqsave(ap->lock, flags); -		/* request PM ops to EH */ -		spin_lock_irqsave(ap->lock, flags); +	ap->pm_mesg = mesg; +	ap->pflags |= ATA_PFLAG_PM_PENDING; +	ata_for_each_link(link, ap, HOST_FIRST) { +		link->eh_info.action |= action; +		link->eh_info.flags |= ehi_flags; +	} -		ap->pm_mesg = mesg; -		if (wait) { -			rc = 0; -			ap->pm_result = &rc; -		} +	ata_port_schedule_eh(ap); -		ap->pflags |= ATA_PFLAG_PM_PENDING; -		ata_for_each_link(link, ap, HOST_FIRST) { -			link->eh_info.action |= action; -			link->eh_info.flags |= ehi_flags; -		} +	spin_unlock_irqrestore(ap->lock, flags); -		ata_port_schedule_eh(ap); +	if (!async) { +		ata_port_wait_eh(ap); +		WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); +	} +} -		spin_unlock_irqrestore(ap->lock, flags); +/* + * On some hardware, device fails to respond after spun down for suspend.  As + * the device won't be used before being resumed, we don't need to touch the + * device.  Ask EH to skip the usual stuff and proceed directly to suspend. + * + * http://thread.gmane.org/gmane.linux.ide/46764 + */ +static const unsigned int ata_port_suspend_ehi = ATA_EHI_QUIET +						 | ATA_EHI_NO_AUTOPSY +						 | ATA_EHI_NO_RECOVERY; -		/* wait and check result */ -		if (wait) { -			ata_port_wait_eh(ap); -			WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING); -			if (rc) -				return rc; -		} +static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg) +{ +	ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, false); +} + +static void ata_port_suspend_async(struct ata_port *ap, pm_message_t mesg) +{ +	ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, true); +} + +static int ata_port_pm_suspend(struct device *dev) +{ +	struct ata_port *ap = to_ata_port(dev); + +	if (pm_runtime_suspended(dev)) +		return 0; + +	ata_port_suspend(ap, PMSG_SUSPEND); +	return 0; +} + +static int ata_port_pm_freeze(struct device *dev) +{ +	struct ata_port *ap = to_ata_port(dev); + +	if (pm_runtime_suspended(dev)) +		return 0; + +	ata_port_suspend(ap, PMSG_FREEZE); +	return 0; +} + +static int ata_port_pm_poweroff(struct device *dev) +{ +	ata_port_suspend(to_ata_port(dev), PMSG_HIBERNATE); +	return 0; +} + +static const unsigned int ata_port_resume_ehi = ATA_EHI_NO_AUTOPSY +						| ATA_EHI_QUIET; + +static void ata_port_resume(struct ata_port *ap, pm_message_t mesg) +{ +	ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, false); +} + +static void ata_port_resume_async(struct ata_port *ap, pm_message_t mesg) +{ +	ata_port_request_pm(ap, mesg, ATA_EH_RESET, ata_port_resume_ehi, true); +} + +static int ata_port_pm_resume(struct device *dev) +{ +	ata_port_resume_async(to_ata_port(dev), PMSG_RESUME); +	pm_runtime_disable(dev); +	pm_runtime_set_active(dev); +	pm_runtime_enable(dev); +	return 0; +} + +/* + * For ODDs, the upper layer will poll for media change every few seconds, + * which will make it enter and leave suspend state every few seconds. And + * as each suspend will cause a hard/soft reset, the gain of runtime suspend + * is very little and the ODD may malfunction after constantly being reset. + * So the idle callback here will not proceed to suspend if a non-ZPODD capable + * ODD is attached to the port. + */ +static int ata_port_runtime_idle(struct device *dev) +{ +	struct ata_port *ap = to_ata_port(dev); +	struct ata_link *link; +	struct ata_device *adev; + +	ata_for_each_link(link, ap, HOST_FIRST) { +		ata_for_each_dev(adev, link, ENABLED) +			if (adev->class == ATA_DEV_ATAPI && +			    !zpodd_dev_enabled(adev)) +				return -EBUSY;  	}  	return 0;  } +static int ata_port_runtime_suspend(struct device *dev) +{ +	ata_port_suspend(to_ata_port(dev), PMSG_AUTO_SUSPEND); +	return 0; +} + +static int ata_port_runtime_resume(struct device *dev) +{ +	ata_port_resume(to_ata_port(dev), PMSG_AUTO_RESUME); +	return 0; +} + +static const struct dev_pm_ops ata_port_pm_ops = { +	.suspend = ata_port_pm_suspend, +	.resume = ata_port_pm_resume, +	.freeze = ata_port_pm_freeze, +	.thaw = ata_port_pm_resume, +	.poweroff = ata_port_pm_poweroff, +	.restore = ata_port_pm_resume, + +	.runtime_suspend = ata_port_runtime_suspend, +	.runtime_resume = ata_port_runtime_resume, +	.runtime_idle = ata_port_runtime_idle, +}; + +/* sas ports don't participate in pm runtime management of ata_ports, + * and need to resume ata devices at the domain level, not the per-port + * level. sas suspend/resume is async to allow parallel port recovery + * since sas has multiple ata_port instances per Scsi_Host. + */ +void ata_sas_port_suspend(struct ata_port *ap) +{ +	ata_port_suspend_async(ap, PMSG_SUSPEND); +} +EXPORT_SYMBOL_GPL(ata_sas_port_suspend); + +void ata_sas_port_resume(struct ata_port *ap) +{ +	ata_port_resume_async(ap, PMSG_RESUME); +} +EXPORT_SYMBOL_GPL(ata_sas_port_resume); +  /**   *	ata_host_suspend - suspend host   *	@host: host to suspend   *	@mesg: PM message   * - *	Suspend @host.  Actual operation is performed by EH.  This - *	function requests EH to perform PM operations and waits for EH - *	to finish. - * - *	LOCKING: - *	Kernel thread context (may sleep). - * - *	RETURNS: - *	0 on success, -errno on failure. + *	Suspend @host.  Actual operation is performed by port suspend.   */  int ata_host_suspend(struct ata_host *host, pm_message_t mesg)  { -	unsigned int ehi_flags = ATA_EHI_QUIET; -	int rc; - -	/* -	 * On some hardware, device fails to respond after spun down -	 * for suspend.  As the device won't be used before being -	 * resumed, we don't need to touch the device.  Ask EH to skip -	 * the usual stuff and proceed directly to suspend. -	 * -	 * http://thread.gmane.org/gmane.linux.ide/46764 -	 */ -	if (mesg.event == PM_EVENT_SUSPEND) -		ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY; - -	rc = ata_host_request_pm(host, mesg, 0, ehi_flags, 1); -	if (rc == 0) -		host->dev->power.power_state = mesg; -	return rc; +	host->dev->power.power_state = mesg; +	return 0;  }  /**   *	ata_host_resume - resume host   *	@host: host to resume   * - *	Resume @host.  Actual operation is performed by EH.  This - *	function requests EH to perform PM operations and returns. - *	Note that all resume operations are performed parallely. - * - *	LOCKING: - *	Kernel thread context (may sleep). + *	Resume @host.  Actual operation is performed by port resume.   */  void ata_host_resume(struct ata_host *host)  { -	ata_host_request_pm(host, PMSG_ON, ATA_EH_RESET, -			    ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);  	host->dev->power.power_state = PMSG_ON;  }  #endif +struct device_type ata_port_type = { +	.name = "ata_port", +#ifdef CONFIG_PM +	.pm = &ata_port_pm_ops, +#endif +}; +  /**   *	ata_dev_init - Initialize an ata_device structure   *	@dev: Device structure to initialize @@ -5472,10 +5694,11 @@ struct ata_port *ata_port_alloc(struct ata_host *host)  	ap = kzalloc(sizeof(*ap), GFP_KERNEL);  	if (!ap)  		return NULL; -	 -	ap->pflags |= ATA_PFLAG_INITIALIZING; + +	ap->pflags |= ATA_PFLAG_INITIALIZING | ATA_PFLAG_FROZEN;  	ap->lock = &host->lock;  	ap->print_id = -1; +	ap->local_port_no = -1;  	ap->host = host;  	ap->dev = host->dev; @@ -5833,9 +6056,9 @@ int ata_host_start(struct ata_host *host)  			rc = ap->ops->port_start(ap);  			if (rc) {  				if (rc != -ENODEV) -					dev_printk(KERN_ERR, host->dev, -						"failed to start port %d " -						"(errno=%d)\n", i, rc); +					dev_err(host->dev, +						"failed to start port %d (errno=%d)\n", +						i, rc);  				goto err_out;  			}  		} @@ -5859,31 +6082,59 @@ int ata_host_start(struct ata_host *host)  }  /** - *	ata_sas_host_init - Initialize a host struct + *	ata_sas_host_init - Initialize a host struct for sas (ipr, libsas)   *	@host:	host to initialize   *	@dev:	device host is attached to - *	@flags:	host flags   *	@ops:	port_ops   * - *	LOCKING: - *	PCI/etc. bus probe sem. - *   */ -/* KILLME - the only user left is ipr */  void ata_host_init(struct ata_host *host, struct device *dev, -		   unsigned long flags, struct ata_port_operations *ops) +		   struct ata_port_operations *ops)  {  	spin_lock_init(&host->lock);  	mutex_init(&host->eh_mutex); +	host->n_tags = ATA_MAX_QUEUE - 1;  	host->dev = dev; -	host->flags = flags;  	host->ops = ops;  } +void __ata_port_probe(struct ata_port *ap) +{ +	struct ata_eh_info *ehi = &ap->link.eh_info; +	unsigned long flags; + +	/* kick EH for boot probing */ +	spin_lock_irqsave(ap->lock, flags); + +	ehi->probe_mask |= ATA_ALL_DEVICES; +	ehi->action |= ATA_EH_RESET; +	ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; + +	ap->pflags &= ~ATA_PFLAG_INITIALIZING; +	ap->pflags |= ATA_PFLAG_LOADING; +	ata_port_schedule_eh(ap); + +	spin_unlock_irqrestore(ap->lock, flags); +} + +int ata_port_probe(struct ata_port *ap) +{ +	int rc = 0; + +	if (ap->ops->error_handler) { +		__ata_port_probe(ap); +		ata_port_wait_eh(ap); +	} else { +		DPRINTK("ata%u: bus probe begin\n", ap->print_id); +		rc = ata_bus_probe(ap); +		DPRINTK("ata%u: bus probe end\n", ap->print_id); +	} +	return rc; +} +  static void async_port_probe(void *data, async_cookie_t cookie)  { -	int rc;  	struct ata_port *ap = data;  	/* @@ -5896,47 +6147,14 @@ static void async_port_probe(void *data, async_cookie_t cookie)  	if (!(ap->host->flags & ATA_HOST_PARALLEL_SCAN) && ap->port_no != 0)  		async_synchronize_cookie(cookie); -	/* probe */ -	if (ap->ops->error_handler) { -		struct ata_eh_info *ehi = &ap->link.eh_info; -		unsigned long flags; - -		/* kick EH for boot probing */ -		spin_lock_irqsave(ap->lock, flags); - -		ehi->probe_mask |= ATA_ALL_DEVICES; -		ehi->action |= ATA_EH_RESET; -		ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; - -		ap->pflags &= ~ATA_PFLAG_INITIALIZING; -		ap->pflags |= ATA_PFLAG_LOADING; -		ata_port_schedule_eh(ap); - -		spin_unlock_irqrestore(ap->lock, flags); - -		/* wait for EH to finish */ -		ata_port_wait_eh(ap); -	} else { -		DPRINTK("ata%u: bus probe begin\n", ap->print_id); -		rc = ata_bus_probe(ap); -		DPRINTK("ata%u: bus probe end\n", ap->print_id); - -		if (rc) { -			/* FIXME: do something useful here? -			 * Current libata behavior will -			 * tear down everything when -			 * the module is removed -			 * or the h/w is unplugged. -			 */ -		} -	} +	(void)ata_port_probe(ap);  	/* in order to keep device order, we need to synchronize at this point */  	async_synchronize_cookie(cookie);  	ata_scsi_scan_host(ap, 1); -  } +  /**   *	ata_host_register - register initialized ATA host   *	@host: ATA host to register @@ -5957,10 +6175,11 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)  {  	int i, rc; +	host->n_tags = clamp(sht->can_queue, 1, ATA_MAX_QUEUE - 1); +  	/* host must have been started */  	if (!(host->flags & ATA_HOST_STARTED)) { -		dev_printk(KERN_ERR, host->dev, -			   "BUG: trying to register unstarted host\n"); +		dev_err(host->dev, "BUG: trying to register unstarted host\n");  		WARN_ON(1);  		return -EINVAL;  	} @@ -5973,10 +6192,11 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)  		kfree(host->ports[i]);  	/* give ports names and add SCSI hosts */ -	for (i = 0; i < host->n_ports; i++) -		host->ports[i]->print_id = ata_print_id++; +	for (i = 0; i < host->n_ports; i++) { +		host->ports[i]->print_id = atomic_inc_return(&ata_print_id); +		host->ports[i]->local_port_no = i + 1; +	} -	  	/* Create associated sysfs transport objects  */  	for (i = 0; i < host->n_ports; i++) {  		rc = ata_tport_add(host->dev,host->ports[i]); @@ -5989,9 +6209,6 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)  	if (rc)  		goto err_tadd; -	/* associate with ACPI nodes */ -	ata_acpi_associate(host); -  	/* set cable, sata_spd_limit and report */  	for (i = 0; i < host->n_ports; i++) {  		struct ata_port *ap = host->ports[i]; @@ -6011,14 +6228,13 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)  					      ap->udma_mask);  		if (!ata_port_is_dummy(ap)) { -			ata_port_printk(ap, KERN_INFO, -					"%cATA max %s %s\n", -					(ap->flags & ATA_FLAG_SATA) ? 'S' : 'P', -					ata_mode_string(xfer_mask), -					ap->link.eh_info.desc); +			ata_port_info(ap, "%cATA max %s %s\n", +				      (ap->flags & ATA_FLAG_SATA) ? 'S' : 'P', +				      ata_mode_string(xfer_mask), +				      ap->link.eh_info.desc);  			ata_ehi_clear_desc(&ap->link.eh_info);  		} else -			ata_port_printk(ap, KERN_INFO, "DUMMY\n"); +			ata_port_info(ap, "DUMMY\n");  	}  	/* perform each probe asynchronously */ @@ -6106,6 +6322,8 @@ int ata_host_activate(struct ata_host *host, int irq,  static void ata_port_detach(struct ata_port *ap)  {  	unsigned long flags; +	struct ata_link *link; +	struct ata_device *dev;  	if (!ap->ops->error_handler)  		goto skip_eh; @@ -6122,18 +6340,24 @@ static void ata_port_detach(struct ata_port *ap)  	/* it better be dead now */  	WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED)); -	cancel_rearming_delayed_work(&ap->hotplug_task); +	cancel_delayed_work_sync(&ap->hotplug_task);   skip_eh: +	/* clean up zpodd on port removal */ +	ata_for_each_link(link, ap, HOST_FIRST) { +		ata_for_each_dev(dev, link, ALL) { +			if (zpodd_dev_enabled(dev)) +				zpodd_exit(dev); +		} +	}  	if (ap->pmp_link) {  		int i;  		for (i = 0; i < SATA_PMP_MAX_PORTS; i++)  			ata_tlink_delete(&ap->pmp_link[i]);  	} -	ata_tport_delete(ap); -  	/* remove the associated SCSI host */  	scsi_remove_host(ap->scsi_host); +	ata_tport_delete(ap);  }  /** @@ -6171,8 +6395,7 @@ void ata_host_detach(struct ata_host *host)   */  void ata_pci_remove_one(struct pci_dev *pdev)  { -	struct device *dev = &pdev->dev; -	struct ata_host *host = dev_get_drvdata(dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	ata_host_detach(host);  } @@ -6230,8 +6453,8 @@ int ata_pci_device_do_resume(struct pci_dev *pdev)  	rc = pcim_enable_device(pdev);  	if (rc) { -		dev_printk(KERN_ERR, &pdev->dev, -			   "failed to enable device after resume (%d)\n", rc); +		dev_err(&pdev->dev, +			"failed to enable device after resume (%d)\n", rc);  		return rc;  	} @@ -6241,7 +6464,7 @@ int ata_pci_device_do_resume(struct pci_dev *pdev)  int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc = 0;  	rc = ata_host_suspend(host, mesg); @@ -6255,7 +6478,7 @@ int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)  int ata_pci_device_resume(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -6267,6 +6490,26 @@ int ata_pci_device_resume(struct pci_dev *pdev)  #endif /* CONFIG_PCI */ +/** + *	ata_platform_remove_one - Platform layer callback for device removal + *	@pdev: Platform device that was removed + * + *	Platform layer indicates to libata via this hook that hot-unplug or + *	module unload event has occurred.  Detach all ports.  Resource + *	release is handled via devres. + * + *	LOCKING: + *	Inherited from platform layer (may sleep). + */ +int ata_platform_remove_one(struct platform_device *pdev) +{ +	struct ata_host *host = platform_get_drvdata(pdev); + +	ata_host_detach(host); + +	return 0; +} +  static int __init ata_parse_force_one(char **cur,  				      struct ata_force_ent *force_ent,  				      const char **reason) @@ -6325,6 +6568,9 @@ static int __init ata_parse_force_one(char **cur,  		{ "nohrst",	.lflags		= ATA_LFLAG_NO_HRST },  		{ "nosrst",	.lflags		= ATA_LFLAG_NO_SRST },  		{ "norst",	.lflags		= ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST }, +		{ "rstonce",	.lflags		= ATA_LFLAG_RST_ONCE }, +		{ "atapi_dmadir", .horkage_on	= ATA_HORKAGE_ATAPI_DMADIR }, +		{ "disable",	.horkage_on	= ATA_HORKAGE_DISABLE },  	};  	char *start = *cur, *p = *cur;  	char *id, *val, *endp; @@ -6464,7 +6710,7 @@ static int __init ata_init(void)  		ata_sff_exit();  		rc = -ENOMEM;  		goto err_out; -	}		 +	}  	printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");  	return 0; @@ -6581,6 +6827,8 @@ struct ata_port_operations ata_dummy_port_ops = {  	.qc_prep		= ata_noop_qc_prep,  	.qc_issue		= ata_dummy_qc_issue,  	.error_handler		= ata_dummy_error_handler, +	.sched_eh		= ata_std_sched_eh, +	.end_eh			= ata_std_end_eh,  };  const struct ata_port_info ata_dummy_port_info = { @@ -6588,6 +6836,82 @@ const struct ata_port_info ata_dummy_port_info = {  };  /* + * Utility print functions + */ +int ata_port_printk(const struct ata_port *ap, const char *level, +		    const char *fmt, ...) +{ +	struct va_format vaf; +	va_list args; +	int r; + +	va_start(args, fmt); + +	vaf.fmt = fmt; +	vaf.va = &args; + +	r = printk("%sata%u: %pV", level, ap->print_id, &vaf); + +	va_end(args); + +	return r; +} +EXPORT_SYMBOL(ata_port_printk); + +int ata_link_printk(const struct ata_link *link, const char *level, +		    const char *fmt, ...) +{ +	struct va_format vaf; +	va_list args; +	int r; + +	va_start(args, fmt); + +	vaf.fmt = fmt; +	vaf.va = &args; + +	if (sata_pmp_attached(link->ap) || link->ap->slave_link) +		r = printk("%sata%u.%02u: %pV", +			   level, link->ap->print_id, link->pmp, &vaf); +	else +		r = printk("%sata%u: %pV", +			   level, link->ap->print_id, &vaf); + +	va_end(args); + +	return r; +} +EXPORT_SYMBOL(ata_link_printk); + +int ata_dev_printk(const struct ata_device *dev, const char *level, +		    const char *fmt, ...) +{ +	struct va_format vaf; +	va_list args; +	int r; + +	va_start(args, fmt); + +	vaf.fmt = fmt; +	vaf.va = &args; + +	r = printk("%sata%u.%02u: %pV", +		   level, dev->link->ap->print_id, dev->link->pmp + dev->devno, +		   &vaf); + +	va_end(args); + +	return r; +} +EXPORT_SYMBOL(ata_dev_printk); + +void ata_print_version(const struct device *dev, const char *version) +{ +	dev_printk(KERN_DEBUG, dev, "version %s\n", version); +} +EXPORT_SYMBOL(ata_print_version); + +/*   * libata is essentially a library of internal helper functions for   * low-level ATA host controller drivers.  As such, the API/ABI is   * likely to change as new drivers are added and updated. @@ -6647,6 +6971,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);  EXPORT_SYMBOL_GPL(ata_scsi_slave_config);  EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);  EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth); +EXPORT_SYMBOL_GPL(__ata_change_queue_depth);  EXPORT_SYMBOL_GPL(sata_scr_valid);  EXPORT_SYMBOL_GPL(sata_scr_read);  EXPORT_SYMBOL_GPL(sata_scr_write); @@ -6679,6 +7004,8 @@ EXPORT_SYMBOL_GPL(ata_pci_device_resume);  #endif /* CONFIG_PM */  #endif /* CONFIG_PCI */ +EXPORT_SYMBOL_GPL(ata_platform_remove_one); +  EXPORT_SYMBOL_GPL(__ata_ehi_push_desc);  EXPORT_SYMBOL_GPL(ata_ehi_push_desc);  EXPORT_SYMBOL_GPL(ata_ehi_clear_desc); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 5e590504f3a..dad83df555c 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1,7 +1,7 @@  /*   *  libata-eh.c - libata error handling   * - *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> + *  Maintained by:  Tejun Heo <tj@kernel.org>   *    		    Please ALWAYS copy linux-ide@vger.kernel.org   *		    on emails.   * @@ -34,6 +34,7 @@  #include <linux/kernel.h>  #include <linux/blkdev.h> +#include <linux/export.h>  #include <linux/pci.h>  #include <scsi/scsi.h>  #include <scsi/scsi_host.h> @@ -94,12 +95,13 @@ enum {   * represents timeout for that try.  The first try can be soft or   * hardreset.  All others are hardreset if available.  In most cases   * the first reset w/ 10sec timeout should succeed.  Following entries - * are mostly for error handling, hotplug and retarded devices. + * are mostly for error handling, hotplug and those outlier devices that + * take an exceptionally long time to recover from reset.   */  static const unsigned long ata_eh_reset_timeouts[] = {  	10000,	/* most drives spin up by 10sec */  	10000,	/* > 99% working drives spin up before 20sec */ -	35000,	/* give > 30 secs of idleness for retarded devices */ +	35000,	/* give > 30 secs of idleness for outlier devices */  	 5000,	/* and sweet one last chance */  	ULONG_MAX, /* > 1 min has elapsed, give up */  }; @@ -418,7 +420,7 @@ int ata_ering_map(struct ata_ering *ering,  	return rc;  } -int ata_ering_clear_cb(struct ata_ering_entry *ent, void *void_arg) +static int ata_ering_clear_cb(struct ata_ering_entry *ent, void *void_arg)  {  	ent->eflags |= ATA_EFLAG_OLD_ER;  	return 0; @@ -587,11 +589,43 @@ static void ata_eh_unload(struct ata_port *ap)  void ata_scsi_error(struct Scsi_Host *host)  {  	struct ata_port *ap = ata_shost_to_port(host); -	int i;  	unsigned long flags; +	LIST_HEAD(eh_work_q);  	DPRINTK("ENTER\n"); +	spin_lock_irqsave(host->host_lock, flags); +	list_splice_init(&host->eh_cmd_q, &eh_work_q); +	spin_unlock_irqrestore(host->host_lock, flags); + +	ata_scsi_cmd_error_handler(host, ap, &eh_work_q); + +	/* If we timed raced normal completion and there is nothing to +	   recover nr_timedout == 0 why exactly are we doing error recovery ? */ +	ata_scsi_port_error_handler(host, ap); + +	/* finish or retry handled scmd's and clean up */ +	WARN_ON(host->host_failed || !list_empty(&eh_work_q)); + +	DPRINTK("EXIT\n"); +} + +/** + * ata_scsi_cmd_error_handler - error callback for a list of commands + * @host:	scsi host containing the port + * @ap:		ATA port within the host + * @eh_work_q:	list of commands to process + * + * process the given list of commands and return those finished to the + * ap->eh_done_q.  This function is the first part of the libata error + * handler which processes a given list of failed commands. + */ +void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, +				struct list_head *eh_work_q) +{ +	int i; +	unsigned long flags; +  	/* make sure sff pio task is not running */  	ata_sff_flush_pio_task(ap); @@ -627,7 +661,7 @@ void ata_scsi_error(struct Scsi_Host *host)  		if (ap->ops->lost_interrupt)  			ap->ops->lost_interrupt(ap); -		list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) { +		list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) {  			struct ata_queued_cmd *qc;  			for (i = 0; i < ATA_MAX_QUEUE; i++) { @@ -671,8 +705,20 @@ void ata_scsi_error(struct Scsi_Host *host)  	} else  		spin_unlock_wait(ap->lock); -	/* If we timed raced normal completion and there is nothing to -	   recover nr_timedout == 0 why exactly are we doing error recovery ? */ +} +EXPORT_SYMBOL(ata_scsi_cmd_error_handler); + +/** + * ata_scsi_port_error_handler - recover the port after the commands + * @host:	SCSI host containing the port + * @ap:		the ATA port + * + * Handle the recovery of the port @ap after all the commands + * have been recovered. + */ +void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap) +{ +	unsigned long flags;  	/* invoke error handler */  	if (ap->ops->error_handler) { @@ -727,7 +773,7 @@ void ata_scsi_error(struct Scsi_Host *host)  		/* process port suspend request */  		ata_eh_handle_port_suspend(ap); -		/* Exception might have happend after ->error_handler +		/* Exception might have happened after ->error_handler  		 * recovered the port but before this point.  Repeat  		 * EH in such case.  		 */ @@ -738,8 +784,9 @@ void ata_scsi_error(struct Scsi_Host *host)  				spin_unlock_irqrestore(ap->lock, flags);  				goto repeat;  			} -			ata_port_printk(ap, KERN_ERR, "EH pending after %d " -					"tries, giving up\n", ATA_EH_MAX_TRIES); +			ata_port_err(ap, +				     "EH pending after %d tries, giving up\n", +				     ATA_EH_MAX_TRIES);  			ap->pflags &= ~ATA_PFLAG_EH_PENDING;  		} @@ -747,12 +794,12 @@ void ata_scsi_error(struct Scsi_Host *host)  		ata_for_each_link(link, ap, HOST_FIRST)  			memset(&link->eh_info, 0, sizeof(link->eh_info)); -		/* Clear host_eh_scheduled while holding ap->lock such -		 * that if exception occurs after this point but -		 * before EH completion, SCSI midlayer will +		/* end eh (clear host_eh_scheduled) while holding +		 * ap->lock such that if exception occurs after this +		 * point but before EH completion, SCSI midlayer will  		 * re-initiate EH.  		 */ -		host->host_eh_scheduled = 0; +		ap->ops->end_eh(ap);  		spin_unlock_irqrestore(ap->lock, flags);  		ata_eh_release(ap); @@ -761,9 +808,6 @@ void ata_scsi_error(struct Scsi_Host *host)  		ap->ops->eng_timeout(ap);  	} -	/* finish or retry handled scmd's and clean up */ -	WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); -  	scsi_eh_flush_done_q(&ap->eh_done_q);  	/* clean up */ @@ -775,7 +819,7 @@ void ata_scsi_error(struct Scsi_Host *host)  		schedule_delayed_work(&ap->hotplug_task, 0);  	if (ap->pflags & ATA_PFLAG_RECOVERED) -		ata_port_printk(ap, KERN_INFO, "EH complete\n"); +		ata_port_info(ap, "EH complete\n");  	ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED); @@ -784,9 +828,8 @@ void ata_scsi_error(struct Scsi_Host *host)  	wake_up_all(&ap->eh_wait_q);  	spin_unlock_irqrestore(ap->lock, flags); - -	DPRINTK("EXIT\n");  } +EXPORT_SYMBOL_GPL(ata_scsi_port_error_handler);  /**   *	ata_port_wait_eh - Wait for the currently pending EH to complete @@ -821,6 +864,7 @@ void ata_port_wait_eh(struct ata_port *ap)  		goto retry;  	}  } +EXPORT_SYMBOL_GPL(ata_port_wait_eh);  static int ata_eh_nr_in_flight(struct ata_port *ap)  { @@ -943,16 +987,13 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc)  }  /** - *	ata_port_schedule_eh - schedule error handling without a qc - *	@ap: ATA port to schedule EH for + * ata_std_sched_eh - non-libsas ata_ports issue eh with this common routine + * @ap: ATA port to schedule EH for   * - *	Schedule error handling for @ap.  EH will kick in as soon as - *	all commands are drained. - * - *	LOCKING: + *	LOCKING: inherited from ata_port_schedule_eh   *	spin_lock_irqsave(host lock)   */ -void ata_port_schedule_eh(struct ata_port *ap) +void ata_std_sched_eh(struct ata_port *ap)  {  	WARN_ON(!ap->ops->error_handler); @@ -964,6 +1005,44 @@ void ata_port_schedule_eh(struct ata_port *ap)  	DPRINTK("port EH scheduled\n");  } +EXPORT_SYMBOL_GPL(ata_std_sched_eh); + +/** + * ata_std_end_eh - non-libsas ata_ports complete eh with this common routine + * @ap: ATA port to end EH for + * + * In the libata object model there is a 1:1 mapping of ata_port to + * shost, so host fields can be directly manipulated under ap->lock, in + * the libsas case we need to hold a lock at the ha->level to coordinate + * these events. + * + *	LOCKING: + *	spin_lock_irqsave(host lock) + */ +void ata_std_end_eh(struct ata_port *ap) +{ +	struct Scsi_Host *host = ap->scsi_host; + +	host->host_eh_scheduled = 0; +} +EXPORT_SYMBOL(ata_std_end_eh); + + +/** + *	ata_port_schedule_eh - schedule error handling without a qc + *	@ap: ATA port to schedule EH for + * + *	Schedule error handling for @ap.  EH will kick in as soon as + *	all commands are drained. + * + *	LOCKING: + *	spin_lock_irqsave(host lock) + */ +void ata_port_schedule_eh(struct ata_port *ap) +{ +	/* see: ata_std_sched_eh, unless you know better */ +	ap->ops->sched_eh(ap); +}  static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link)  { @@ -1244,14 +1323,14 @@ void ata_eh_qc_complete(struct ata_queued_cmd *qc)   *	should be retried.  To be used from EH.   *   *	SCSI midlayer limits the number of retries to scmd->allowed. - *	scmd->retries is decremented for commands which get retried + *	scmd->allowed is incremented for commands which get retried   *	due to unrelated failures (qc->err_mask is zero).   */  void ata_eh_qc_retry(struct ata_queued_cmd *qc)  {  	struct scsi_cmnd *scmd = qc->scsicmd; -	if (!qc->err_mask && scmd->retries) -		scmd->retries--; +	if (!qc->err_mask) +		scmd->allowed++;  	__ata_eh_qc_complete(qc);  } @@ -1270,7 +1349,7 @@ void ata_dev_disable(struct ata_device *dev)  		return;  	if (ata_msg_drv(dev->link->ap)) -		ata_dev_printk(dev, KERN_WARNING, "disabled\n"); +		ata_dev_warn(dev, "disabled\n");  	ata_acpi_on_disable(dev);  	ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);  	dev->class++; @@ -1409,6 +1488,7 @@ static const char *ata_err_string(unsigned int err_mask)  /**   *	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 @@ -1421,17 +1501,18 @@ static const char *ata_err_string(unsigned int err_mask)   *	RETURNS:   *	0 on success, AC_ERR_* mask otherwise.   */ -static unsigned int ata_read_log_page(struct ata_device *dev, -				      u8 page, void *buf, unsigned int sectors) +unsigned int ata_read_log_page(struct ata_device *dev, u8 log, +			       u8 page, void *buf, unsigned int sectors)  {  	struct ata_taskfile tf;  	unsigned int err_mask; -	DPRINTK("read log page - page %d\n", page); +	DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);  	ata_tf_init(dev, &tf);  	tf.command = ATA_CMD_READ_LOG_EXT; -	tf.lbal = page; +	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; @@ -1467,7 +1548,7 @@ static int ata_eh_read_log_10h(struct ata_device *dev,  	u8 csum;  	int i; -	err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1); +	err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, 0, buf, 1);  	if (err_mask)  		return -EIO; @@ -1475,8 +1556,8 @@ static int ata_eh_read_log_10h(struct ata_device *dev,  	for (i = 0; i < ATA_SECT_SIZE; i++)  		csum += buf[i];  	if (csum) -		ata_dev_printk(dev, KERN_WARNING, -			       "invalid checksum 0x%x on log page 10h\n", csum); +		ata_dev_warn(dev, "invalid checksum 0x%x on log page 10h\n", +			     csum);  	if (buf[0] & 0x80)  		return -ENOENT; @@ -1511,7 +1592,7 @@ static int ata_eh_read_log_10h(struct ata_device *dev,   *	RETURNS:   *	0 on success, AC_ERR_* mask on failure.   */ -static unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key) +unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key)  {  	u8 cdb[ATAPI_CDB_LEN] = { TEST_UNIT_READY, 0, 0, 0, 0, 0 };  	struct ata_taskfile tf; @@ -1544,7 +1625,7 @@ static unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key)   *	RETURNS:   *	0 on success, AC_ERR_* mask on failure   */ -static unsigned int atapi_eh_request_sense(struct ata_device *dev, +unsigned int atapi_eh_request_sense(struct ata_device *dev,  					   u8 *sense_buf, u8 dfl_sense_key)  {  	u8 cdb[ATAPI_CDB_LEN] = @@ -1618,7 +1699,7 @@ static void ata_eh_analyze_serror(struct ata_link *link)  	 * host links.  For disabled PMP links, only N bit is  	 * considered as X bit is left at 1 for link plugging.  	 */ -	if (link->lpm_policy != ATA_LPM_MAX_POWER) +	if (link->lpm_policy > ATA_LPM_MAX_POWER)  		hotplug_mask = 0;	/* hotplug doesn't work w/ LPM */  	else if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link))  		hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG; @@ -1676,14 +1757,14 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)  	memset(&tf, 0, sizeof(tf));  	rc = ata_eh_read_log_10h(dev, &tag, &tf);  	if (rc) { -		ata_link_printk(link, KERN_ERR, "failed to read log page 10h " -				"(errno=%d)\n", rc); +		ata_link_err(link, "failed to read log page 10h (errno=%d)\n", +			     rc);  		return;  	}  	if (!(link->sactive & (1 << tag))) { -		ata_link_printk(link, KERN_ERR, "log page 10h reported " -				"inactive tag %d\n", tag); +		ata_link_err(link, "log page 10h reported inactive tag %d\n", +			     tag);  		return;  	} @@ -1702,7 +1783,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)   *   *	Analyze taskfile of @qc and further determine cause of   *	failure.  This function also requests ATAPI sense data if - *	avaliable. + *	available.   *   *	LOCKING:   *	Kernel thread context (may sleep). @@ -1730,7 +1811,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,  	case ATA_DEV_ATA:  		if (err & ATA_ICRC)  			qc->err_mask |= AC_ERR_ATA_BUS; -		if (err & ATA_UNC) +		if (err & (ATA_UNC | ATA_AMNF))  			qc->err_mask |= AC_ERR_MEDIA;  		if (err & ATA_IDNF)  			qc->err_mask |= AC_ERR_INVALID; @@ -1853,7 +1934,7 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)   *	   occurred during last 5 mins, NCQ_OFF.   *   *	3. If more than 8 ATA_BUS, TOUT_HSM or UNK_DEV errors - *	   ocurred during last 5 mins, FALLBACK_TO_PIO + *	   occurred during last 5 mins, FALLBACK_TO_PIO   *   *	4. If more than 3 TOUT_HSM or UNK_DEV errors occurred   *	   during last 10 mins, NCQ_OFF. @@ -1948,8 +2029,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,  	    (dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ |  			   ATA_DFLAG_NCQ_OFF)) == ATA_DFLAG_NCQ) {  		dev->flags |= ATA_DFLAG_NCQ_OFF; -		ata_dev_printk(dev, KERN_WARNING, -			       "NCQ disabled due to excessive errors\n"); +		ata_dev_warn(dev, "NCQ disabled due to excessive errors\n");  		goto done;  	} @@ -2005,6 +2085,26 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,  }  /** + *	ata_eh_worth_retry - analyze error and decide whether to retry + *	@qc: qc to possibly retry + * + *	Look at the cause of the error and decide if a retry + * 	might be useful or not.  We don't want to retry media errors + *	because the drive itself has probably already taken 10-30 seconds + *	doing its own internal retries before reporting the failure. + */ +static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc) +{ +	if (qc->err_mask & AC_ERR_MEDIA) +		return 0;	/* don't retry media errors */ +	if (qc->flags & ATA_QCFLAG_IO) +		return 1;	/* otherwise retry anything from fs stack */ +	if (qc->err_mask & AC_ERR_INVALID) +		return 0;	/* don't retry these */ +	return qc->err_mask != AC_ERR_DEV;  /* retry if not dev error */ +} + +/**   *	ata_eh_link_autopsy - analyze error and determine recovery action   *	@link: host link to perform autopsy on   * @@ -2078,9 +2178,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)  			qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);  		/* determine whether the command is worth retrying */ -		if (qc->flags & ATA_QCFLAG_IO || -		    (!(qc->err_mask & AC_ERR_INVALID) && -		     qc->err_mask != AC_ERR_DEV)) +		if (ata_eh_worth_retry(qc))  			qc->flags |= ATA_QCFLAG_RETRY;  		/* accumulate error info */ @@ -2196,6 +2294,7 @@ const char *ata_get_cmd_descript(u8 command)  		{ ATA_CMD_IDLE, 		"IDLE" },  		{ ATA_CMD_EDD, 			"EXECUTE DEVICE DIAGNOSTIC" },  		{ ATA_CMD_DOWNLOAD_MICRO,   	"DOWNLOAD MICROCODE" }, +		{ ATA_CMD_DOWNLOAD_MICRO_DMA,	"DOWNLOAD MICROCODE DMA" },  		{ ATA_CMD_NOP,			"NOP" },  		{ ATA_CMD_FLUSH, 		"FLUSH CACHE" },  		{ ATA_CMD_FLUSH_EXT, 		"FLUSH CACHE EXT" }, @@ -2216,6 +2315,8 @@ const char *ata_get_cmd_descript(u8 command)  		{ ATA_CMD_WRITE_QUEUED_FUA_EXT, "WRITE DMA QUEUED FUA EXT" },  		{ ATA_CMD_FPDMA_READ,		"READ FPDMA QUEUED" },  		{ ATA_CMD_FPDMA_WRITE,		"WRITE FPDMA QUEUED" }, +		{ ATA_CMD_FPDMA_SEND,		"SEND FPDMA QUEUED" }, +		{ ATA_CMD_FPDMA_RECV,		"RECEIVE FPDMA QUEUED" },  		{ ATA_CMD_PIO_READ,		"READ SECTOR(S)" },  		{ ATA_CMD_PIO_READ_EXT,		"READ SECTOR(S) EXT" },  		{ ATA_CMD_PIO_WRITE,		"WRITE SECTOR(S)" }, @@ -2242,12 +2343,15 @@ const char *ata_get_cmd_descript(u8 command)  		{ ATA_CMD_WRITE_LOG_EXT,	"WRITE LOG EXT" },  		{ ATA_CMD_READ_LOG_DMA_EXT,	"READ LOG DMA EXT" },  		{ ATA_CMD_WRITE_LOG_DMA_EXT, 	"WRITE LOG DMA EXT" }, +		{ ATA_CMD_TRUSTED_NONDATA,	"TRUSTED NON-DATA" },  		{ ATA_CMD_TRUSTED_RCV,		"TRUSTED RECEIVE" },  		{ ATA_CMD_TRUSTED_RCV_DMA, 	"TRUSTED RECEIVE DMA" },  		{ ATA_CMD_TRUSTED_SND,		"TRUSTED SEND" },  		{ ATA_CMD_TRUSTED_SND_DMA, 	"TRUSTED SEND DMA" },  		{ ATA_CMD_PMP_READ,		"READ BUFFER" }, +		{ ATA_CMD_PMP_READ_DMA,		"READ BUFFER DMA" },  		{ ATA_CMD_PMP_WRITE,		"WRITE BUFFER" }, +		{ ATA_CMD_PMP_WRITE_DMA,	"WRITE BUFFER DMA" },  		{ ATA_CMD_CONF_OVERLAY,		"DEVICE CONFIGURATION OVERLAY" },  		{ ATA_CMD_SEC_SET_PASS,		"SECURITY SET PASSWORD" },  		{ ATA_CMD_SEC_UNLOCK,		"SECURITY UNLOCK" }, @@ -2266,6 +2370,8 @@ const char *ata_get_cmd_descript(u8 command)  		{ ATA_CMD_CFA_TRANS_SECT,	"CFA TRANSLATE SECTOR" },  		{ ATA_CMD_CFA_ERASE,		"CFA ERASE SECTORS" },  		{ ATA_CMD_CFA_WRITE_MULT_NE, 	"CFA WRITE MULTIPLE WITHOUT ERASE" }, +		{ ATA_CMD_REQ_SENSE_DATA,	"REQUEST SENSE DATA EXT" }, +		{ ATA_CMD_SANITIZE_DEVICE,	"SANITIZE DEVICE" },  		{ ATA_CMD_READ_LONG,		"READ LONG (with retries)" },  		{ ATA_CMD_READ_LONG_ONCE,	"READ LONG (without retries)" },  		{ ATA_CMD_WRITE_LONG,		"WRITE LONG (with retries)" }, @@ -2297,7 +2403,7 @@ static void ata_eh_link_report(struct ata_link *link)  	struct ata_port *ap = link->ap;  	struct ata_eh_context *ehc = &link->eh_context;  	const char *frozen, *desc; -	char tries_buf[6]; +	char tries_buf[6] = "";  	int tag, nr_failed = 0;  	if (ehc->i.flags & ATA_EHI_QUIET) @@ -2328,30 +2434,29 @@ static void ata_eh_link_report(struct ata_link *link)  	if (ap->pflags & ATA_PFLAG_FROZEN)  		frozen = " frozen"; -	memset(tries_buf, 0, sizeof(tries_buf));  	if (ap->eh_tries < ATA_EH_MAX_TRIES) -		snprintf(tries_buf, sizeof(tries_buf) - 1, " t%d", +		snprintf(tries_buf, sizeof(tries_buf), " t%d",  			 ap->eh_tries);  	if (ehc->i.dev) { -		ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x " -			       "SAct 0x%x SErr 0x%x action 0x%x%s%s\n", -			       ehc->i.err_mask, link->sactive, ehc->i.serror, -			       ehc->i.action, frozen, tries_buf); +		ata_dev_err(ehc->i.dev, "exception Emask 0x%x " +			    "SAct 0x%x SErr 0x%x action 0x%x%s%s\n", +			    ehc->i.err_mask, link->sactive, ehc->i.serror, +			    ehc->i.action, frozen, tries_buf);  		if (desc) -			ata_dev_printk(ehc->i.dev, KERN_ERR, "%s\n", desc); +			ata_dev_err(ehc->i.dev, "%s\n", desc);  	} else { -		ata_link_printk(link, KERN_ERR, "exception Emask 0x%x " -				"SAct 0x%x SErr 0x%x action 0x%x%s%s\n", -				ehc->i.err_mask, link->sactive, ehc->i.serror, -				ehc->i.action, frozen, tries_buf); +		ata_link_err(link, "exception Emask 0x%x " +			     "SAct 0x%x SErr 0x%x action 0x%x%s%s\n", +			     ehc->i.err_mask, link->sactive, ehc->i.serror, +			     ehc->i.action, frozen, tries_buf);  		if (desc) -			ata_link_printk(link, KERN_ERR, "%s\n", desc); +			ata_link_err(link, "%s\n", desc);  	}  #ifdef CONFIG_ATA_VERBOSE_ERROR  	if (ehc->i.serror) -		ata_link_printk(link, KERN_ERR, +		ata_link_err(link,  		  "SError: { %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n",  		  ehc->i.serror & SERR_DATA_RECOVERED ? "RecovData " : "",  		  ehc->i.serror & SERR_COMM_RECOVERED ? "RecovComm " : "", @@ -2416,11 +2521,11 @@ static void ata_eh_link_report(struct ata_link *link)  		} else {  			const char *descr = ata_get_cmd_descript(cmd->command);  			if (descr) -				ata_dev_printk(qc->dev, KERN_ERR, -					"failed command: %s\n", descr); +				ata_dev_err(qc->dev, "failed command: %s\n", +					    descr);  		} -		ata_dev_printk(qc->dev, KERN_ERR, +		ata_dev_err(qc->dev,  			"cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x "  			"tag %d%s\n         %s"  			"res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " @@ -2441,11 +2546,9 @@ static void ata_eh_link_report(struct ata_link *link)  		if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |  				    ATA_ERR)) {  			if (res->command & ATA_BUSY) -				ata_dev_printk(qc->dev, KERN_ERR, -				  "status: { Busy }\n"); +				ata_dev_err(qc->dev, "status: { Busy }\n");  			else -				ata_dev_printk(qc->dev, KERN_ERR, -				  "status: { %s%s%s%s}\n", +				ata_dev_err(qc->dev, "status: { %s%s%s%s}\n",  				  res->command & ATA_DRDY ? "DRDY " : "",  				  res->command & ATA_DF ? "DF " : "",  				  res->command & ATA_DRQ ? "DRQ " : "", @@ -2453,12 +2556,12 @@ static void ata_eh_link_report(struct ata_link *link)  		}  		if (cmd->command != ATA_CMD_PACKET && -		    (res->feature & (ATA_ICRC | ATA_UNC | ATA_IDNF | -				     ATA_ABORTED))) -			ata_dev_printk(qc->dev, KERN_ERR, -			  "error: { %s%s%s%s}\n", +		    (res->feature & (ATA_ICRC | ATA_UNC | ATA_AMNF | +				     ATA_IDNF | ATA_ABORTED))) +			ata_dev_err(qc->dev, "error: { %s%s%s%s%s}\n",  			  res->feature & ATA_ICRC ? "ICRC " : "",  			  res->feature & ATA_UNC ? "UNC " : "", +			  res->feature & ATA_AMNF ? "AMNF " : "",  			  res->feature & ATA_IDNF ? "IDNF " : "",  			  res->feature & ATA_ABORTED ? "ABRT " : "");  #endif @@ -2495,8 +2598,7 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,  	return reset(link, classes, deadline);  } -static int ata_eh_followup_srst_needed(struct ata_link *link, -				       int rc, const unsigned int *classes) +static int ata_eh_followup_srst_needed(struct ata_link *link, int rc)  {  	if ((link->flags & ATA_LFLAG_NO_SRST) || ata_link_offline(link))  		return 0; @@ -2532,12 +2634,14 @@ int ata_eh_reset(struct ata_link *link, int classify,  	 */  	while (ata_eh_reset_timeouts[max_tries] != ULONG_MAX)  		max_tries++; +	if (link->flags & ATA_LFLAG_RST_ONCE) +		max_tries = 1;  	if (link->flags & ATA_LFLAG_NO_HRST)  		hardreset = NULL;  	if (link->flags & ATA_LFLAG_NO_SRST)  		softreset = NULL; -	/* make sure each reset attemp is at least COOL_DOWN apart */ +	/* make sure each reset attempt is at least COOL_DOWN apart */  	if (ehc->i.flags & ATA_EHI_DID_RESET) {  		now = jiffies;  		WARN_ON(time_after(ehc->last_reset, now)); @@ -2562,6 +2666,7 @@ int ata_eh_reset(struct ata_link *link, int classify,  		 * bus as we may be talking too fast.  		 */  		dev->pio_mode = XFER_PIO_0; +		dev->dma_mode = 0xff;  		/* If the controller has a pio mode setup function  		 * then use it to set the chipset to rights. Don't @@ -2610,8 +2715,7 @@ int ata_eh_reset(struct ata_link *link, int classify,  		if (rc) {  			if (rc == -ENOENT) { -				ata_link_printk(link, KERN_DEBUG, -						"port disabled. ignoring.\n"); +				ata_link_dbg(link, "port disabled--ignoring\n");  				ehc->i.action &= ~ATA_EH_RESET;  				ata_for_each_dev(dev, link, ALL) @@ -2619,8 +2723,9 @@ int ata_eh_reset(struct ata_link *link, int classify,  				rc = 0;  			} else -				ata_link_printk(link, KERN_ERR, -					"prereset failed (errno=%d)\n", rc); +				ata_link_err(link, +					     "prereset failed (errno=%d)\n", +					     rc);  			goto out;  		} @@ -2649,8 +2754,8 @@ int ata_eh_reset(struct ata_link *link, int classify,  	if (reset) {  		if (verbose) -			ata_link_printk(link, KERN_INFO, "%s resetting link\n", -					reset == softreset ? "soft" : "hard"); +			ata_link_info(link, "%s resetting link\n", +				      reset == softreset ? "soft" : "hard");  		/* mark that this EH session started with reset */  		ehc->last_reset = jiffies; @@ -2670,8 +2775,7 @@ int ata_eh_reset(struct ata_link *link, int classify,  			int tmp;  			if (verbose) -				ata_link_printk(slave, KERN_INFO, -						"hard resetting link\n"); +				ata_link_info(slave, "hard resetting link\n");  			ata_eh_about_to_do(slave, NULL, ATA_EH_RESET);  			tmp = ata_do_reset(slave, reset, classes, deadline, @@ -2690,13 +2794,12 @@ int ata_eh_reset(struct ata_link *link, int classify,  		/* perform follow-up SRST if necessary */  		if (reset == hardreset && -		    ata_eh_followup_srst_needed(link, rc, classes)) { +		    ata_eh_followup_srst_needed(link, rc)) {  			reset = softreset;  			if (!reset) { -				ata_link_printk(link, KERN_ERR, -						"follow-up softreset required " -						"but no softreset avaliable\n"); +				ata_link_err(link, +	     "follow-up softreset required but no softreset available\n");  				failed_link = link;  				rc = -EINVAL;  				goto fail; @@ -2711,8 +2814,8 @@ int ata_eh_reset(struct ata_link *link, int classify,  		}  	} else {  		if (verbose) -			ata_link_printk(link, KERN_INFO, "no reset method " -					"available, skipping reset\n"); +			ata_link_info(link, +	"no reset method available, skipping reset\n");  		if (!(lflags & ATA_LFLAG_ASSUME_CLASS))  			lflags |= ATA_LFLAG_ASSUME_ATA;  	} @@ -2762,10 +2865,11 @@ int ata_eh_reset(struct ata_link *link, int classify,  	}  	/* -	 * Some controllers can't be frozen very well and may set -	 * spuruious error conditions during reset.  Clear accumulated -	 * error information.  As reset is the final recovery action, -	 * nothing is lost by doing this. +	 * Some controllers can't be frozen very well and may set spurious +	 * error conditions during reset.  Clear accumulated error +	 * information and re-thaw the port if frozen.  As reset is the +	 * final recovery action and we cross check link onlineness against +	 * device classification later, no hotplug event is lost by this.  	 */  	spin_lock_irqsave(link->ap->lock, flags);  	memset(&link->eh_info, 0, sizeof(link->eh_info)); @@ -2774,6 +2878,9 @@ int ata_eh_reset(struct ata_link *link, int classify,  	ap->pflags &= ~ATA_PFLAG_EH_PENDING;  	spin_unlock_irqrestore(link->ap->lock, flags); +	if (ap->pflags & ATA_PFLAG_FROZEN) +		ata_eh_thaw_port(ap); +  	/*  	 * Make sure onlineness and classification result correspond.  	 * Hotplug could have happened during reset and some @@ -2786,36 +2893,35 @@ int ata_eh_reset(struct ata_link *link, int classify,  	ata_for_each_dev(dev, link, ALL) {  		if (ata_phys_link_online(ata_dev_phys_link(dev))) {  			if (classes[dev->devno] == ATA_DEV_UNKNOWN) { -				ata_dev_printk(dev, KERN_DEBUG, "link online " -					       "but device misclassifed\n"); +				ata_dev_dbg(dev, "link online but device misclassified\n");  				classes[dev->devno] = ATA_DEV_NONE;  				nr_unknown++;  			}  		} else if (ata_phys_link_offline(ata_dev_phys_link(dev))) {  			if (ata_class_enabled(classes[dev->devno])) -				ata_dev_printk(dev, KERN_DEBUG, "link offline, " -					       "clearing class %d to NONE\n", -					       classes[dev->devno]); +				ata_dev_dbg(dev, +					    "link offline, clearing class %d to NONE\n", +					    classes[dev->devno]);  			classes[dev->devno] = ATA_DEV_NONE;  		} else if (classes[dev->devno] == ATA_DEV_UNKNOWN) { -			ata_dev_printk(dev, KERN_DEBUG, "link status unknown, " -				       "clearing UNKNOWN to NONE\n"); +			ata_dev_dbg(dev, +				    "link status unknown, clearing UNKNOWN to NONE\n");  			classes[dev->devno] = ATA_DEV_NONE;  		}  	}  	if (classify && nr_unknown) {  		if (try < max_tries) { -			ata_link_printk(link, KERN_WARNING, "link online but " -					"%d devices misclassified, retrying\n", -					nr_unknown); +			ata_link_warn(link, +				      "link online but %d devices misclassified, retrying\n", +				      nr_unknown);  			failed_link = link;  			rc = -EAGAIN;  			goto fail;  		} -		ata_link_printk(link, KERN_WARNING, -				"link online but %d devices misclassified, " -				"device detection might fail\n", nr_unknown); +		ata_link_warn(link, +			      "link online but %d devices misclassified, " +			      "device detection might fail\n", nr_unknown);  	}  	/* reset successful, schedule revalidation */ @@ -2845,14 +2951,23 @@ int ata_eh_reset(struct ata_link *link, int classify,  	    sata_scr_read(link, SCR_STATUS, &sstatus))  		rc = -ERESTART; -	if (rc == -ERESTART || try >= max_tries) +	if (try >= max_tries) { +		/* +		 * Thaw host port even if reset failed, so that the port +		 * can be retried on the next phy event.  This risks +		 * repeated EH runs but seems to be a better tradeoff than +		 * shutting down a port after a botched hotplug attempt. +		 */ +		if (ata_is_host_link(link)) +			ata_eh_thaw_port(ap);  		goto out; +	}  	now = jiffies;  	if (time_before(now, deadline)) {  		unsigned long delta = deadline - now; -		ata_link_printk(failed_link, KERN_WARNING, +		ata_link_warn(failed_link,  			"reset failed (errno=%d), retrying in %u secs\n",  			rc, DIV_ROUND_UP(jiffies_to_msecs(delta), 1000)); @@ -2862,6 +2977,16 @@ int ata_eh_reset(struct ata_link *link, int classify,  		ata_eh_acquire(ap);  	} +	/* +	 * While disks spinup behind PMP, some controllers fail sending SRST. +	 * They need to be reset - as well as the PMP - before retrying. +	 */ +	if (rc == -ERESTART) { +		if (ata_is_host_link(link)) +			ata_eh_thaw_port(ap); +		goto out; +	} +  	if (try == max_tries - 1) {  		sata_down_spd_limit(link, 0);  		if (slave) @@ -2893,7 +3018,7 @@ static inline void ata_eh_pull_park_action(struct ata_port *ap)  	 * ourselves at the beginning of each pass over the loop.  	 *  	 * Additionally, all write accesses to &ap->park_req_pending -	 * through INIT_COMPLETION() (see below) or complete_all() +	 * through reinit_completion() (see below) or complete_all()  	 * (see ata_scsi_park_store()) are protected by the host lock.  	 * As a result we have that park_req_pending.done is zero on  	 * exit from this function, i.e. when ATA_EH_PARK actions for @@ -2907,7 +3032,7 @@ static inline void ata_eh_pull_park_action(struct ata_port *ap)  	 */  	spin_lock_irqsave(ap->lock, flags); -	INIT_COMPLETION(ap->park_req_pending); +	reinit_completion(&ap->park_req_pending);  	ata_for_each_link(link, ap, EDGE) {  		ata_for_each_dev(dev, link, ALL) {  			struct ata_eh_info *ehi = &link->eh_info; @@ -2943,7 +3068,7 @@ static void ata_eh_park_issue_cmd(struct ata_device *dev, int park)  	tf.protocol |= ATA_PROT_NODATA;  	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);  	if (park && (err_mask || tf.lbal != 0xc4)) { -		ata_dev_printk(dev, KERN_ERR, "head unload failed!\n"); +		ata_dev_err(dev, "head unload failed!\n");  		ehc->unloaded_mask &= ~(1 << dev->devno);  	}  } @@ -3154,8 +3279,9 @@ static int atapi_eh_clear_ua(struct ata_device *dev)  		err_mask = atapi_eh_tur(dev, &sense_key);  		if (err_mask != 0 && err_mask != AC_ERR_DEV) { -			ata_dev_printk(dev, KERN_WARNING, "TEST_UNIT_READY " -				"failed (err_mask=0x%x)\n", err_mask); +			ata_dev_warn(dev, +				     "TEST_UNIT_READY failed (err_mask=0x%x)\n", +				     err_mask);  			return -EIO;  		} @@ -3164,14 +3290,14 @@ static int atapi_eh_clear_ua(struct ata_device *dev)  		err_mask = atapi_eh_request_sense(dev, sense_buffer, sense_key);  		if (err_mask) { -			ata_dev_printk(dev, KERN_WARNING, "failed to clear " +			ata_dev_warn(dev, "failed to clear "  				"UNIT ATTENTION (err_mask=0x%x)\n", err_mask);  			return -EIO;  		}  	} -	ata_dev_printk(dev, KERN_WARNING, -		"UNIT ATTENTION persists after %d tries\n", ATA_EH_UA_TRIES); +	ata_dev_warn(dev, "UNIT ATTENTION persists after %d tries\n", +		     ATA_EH_UA_TRIES);  	return 0;  } @@ -3222,7 +3348,7 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev)  	tf.flags |= ATA_TFLAG_DEVICE;  	tf.protocol = ATA_PROT_NODATA; -	ata_dev_printk(dev, KERN_WARNING, "retrying FLUSH 0x%x Emask 0x%x\n", +	ata_dev_warn(dev, "retrying FLUSH 0x%x Emask 0x%x\n",  		       tf.command, qc->err_mask);  	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); @@ -3237,7 +3363,7 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev)  		 */  		qc->scsicmd->allowed = max(qc->scsicmd->allowed, 1);  	} else { -		ata_dev_printk(dev, KERN_WARNING, "FLUSH failed Emask 0x%x\n", +		ata_dev_warn(dev, "FLUSH failed Emask 0x%x\n",  			       err_mask);  		rc = -EIO; @@ -3275,6 +3401,8 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,  	struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;  	struct ata_eh_context *ehc = &link->eh_context;  	struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL; +	enum ata_lpm_policy old_policy = link->lpm_policy; +	bool no_dipm = link->ap->flags & ATA_FLAG_NO_DIPM;  	unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;  	unsigned int err_mask;  	int rc; @@ -3291,7 +3419,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,  	 */  	ata_for_each_dev(dev, link, ENABLED) {  		bool hipm = ata_id_has_hipm(dev->id); -		bool dipm = ata_id_has_dipm(dev->id); +		bool dipm = ata_id_has_dipm(dev->id) && !no_dipm;  		/* find the first enabled and LPM enabled devices */  		if (!link_dev) @@ -3309,9 +3437,9 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,  			err_mask = ata_dev_set_feature(dev,  					SETFEATURES_SATA_DISABLE, SATA_DIPM);  			if (err_mask && err_mask != AC_ERR_DEV) { -				ata_dev_printk(dev, KERN_WARNING, -					"failed to disable DIPM, Emask 0x%x\n", -					err_mask); +				ata_dev_warn(dev, +					     "failed to disable DIPM, Emask 0x%x\n", +					     err_mask);  				rc = -EIO;  				goto fail;  			} @@ -3338,13 +3466,22 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,  		goto fail;  	} +	/* +	 * Low level driver acked the transition.  Issue DIPM command +	 * with the new policy set. +	 */ +	link->lpm_policy = policy; +	if (ap && ap->slave_link) +		ap->slave_link->lpm_policy = policy; +  	/* host config updated, enable DIPM if transitioning to MIN_POWER */  	ata_for_each_dev(dev, link, ENABLED) { -		if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) { +		if (policy == ATA_LPM_MIN_POWER && !no_dipm && +		    ata_id_has_dipm(dev->id)) {  			err_mask = ata_dev_set_feature(dev,  					SETFEATURES_SATA_ENABLE, SATA_DIPM);  			if (err_mask && err_mask != AC_ERR_DEV) { -				ata_dev_printk(dev, KERN_WARNING, +				ata_dev_warn(dev,  					"failed to enable DIPM, Emask 0x%x\n",  					err_mask);  				rc = -EIO; @@ -3353,16 +3490,17 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,  		}  	} -	link->lpm_policy = policy; -	if (ap && ap->slave_link) -		ap->slave_link->lpm_policy = policy;  	return 0;  fail: +	/* restore the old policy */ +	link->lpm_policy = old_policy; +	if (ap && ap->slave_link) +		ap->slave_link->lpm_policy = old_policy; +  	/* if no device or only one more chance is left, disable LPM */  	if (!dev || ehc->tries[dev->devno] <= 2) { -		ata_link_printk(link, KERN_WARNING, -				"disabling LPM on the link\n"); +		ata_link_warn(link, "disabling LPM on the link\n");  		link->flags |= ATA_LFLAG_NO_LPM;  	}  	if (r_failed_dev) @@ -3370,7 +3508,7 @@ fail:  	return rc;  } -static int ata_link_nr_enabled(struct ata_link *link) +int ata_link_nr_enabled(struct ata_link *link)  {  	struct ata_device *dev;  	int cnt = 0; @@ -3430,7 +3568,8 @@ static int ata_count_probe_trials_cb(struct ata_ering_entry *ent, void *void_arg  	u64 now = get_jiffies_64();  	int *trials = void_arg; -	if (ent->timestamp < now - min(now, interval)) +	if ((ent->eflags & ATA_EFLAG_OLD_ER) || +	    (ent->timestamp < now - min(now, interval)))  		return -1;  	(*trials)++; @@ -3633,8 +3772,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,  		rc = ata_eh_reset(link, ata_link_nr_vacant(link),  				  prereset, softreset, hardreset, postreset);  		if (rc) { -			ata_link_printk(link, KERN_ERR, -					"reset failed, giving up\n"); +			ata_link_err(link, "reset failed, giving up\n");  			goto out;  		}  	} @@ -3728,6 +3866,8 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,  				rc = atapi_eh_clear_ua(dev);  				if (rc)  					goto rest_fail; +				if (zpodd_dev_enabled(dev)) +					zpodd_post_poweron(dev);  			}  		} @@ -3893,11 +4033,12 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)  {  	unsigned long flags;  	int rc = 0; +	struct ata_device *dev;  	/* are we suspending? */  	spin_lock_irqsave(ap->lock, flags);  	if (!(ap->pflags & ATA_PFLAG_PM_PENDING) || -	    ap->pm_mesg.event == PM_EVENT_ON) { +	    ap->pm_mesg.event & PM_EVENT_RESUME) {  		spin_unlock_irqrestore(ap->lock, flags);  		return;  	} @@ -3905,6 +4046,18 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)  	WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED); +	/* +	 * If we have a ZPODD attached, check its zero +	 * power ready status before the port is frozen. +	 * Only needed for runtime suspend. +	 */ +	if (PMSG_IS_AUTO(ap->pm_mesg)) { +		ata_for_each_dev(dev, &ap->link, ENABLED) { +			if (zpodd_dev_enabled(dev)) +				zpodd_on_suspend(dev); +		} +	} +  	/* tell ACPI we're suspending */  	rc = ata_acpi_on_suspend(ap);  	if (rc) @@ -3916,9 +4069,9 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)  	if (ap->ops->port_suspend)  		rc = ap->ops->port_suspend(ap, ap->pm_mesg); -	ata_acpi_set_state(ap, PMSG_SUSPEND); +	ata_acpi_set_state(ap, ap->pm_mesg);   out: -	/* report result */ +	/* update the flags */  	spin_lock_irqsave(ap->lock, flags);  	ap->pflags &= ~ATA_PFLAG_PM_PENDING; @@ -3927,11 +4080,6 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)  	else if (ap->pflags & ATA_PFLAG_FROZEN)  		ata_port_schedule_eh(ap); -	if (ap->pm_result) { -		*ap->pm_result = rc; -		ap->pm_result = NULL; -	} -  	spin_unlock_irqrestore(ap->lock, flags);  	return; @@ -3956,7 +4104,7 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)  	/* are we resuming? */  	spin_lock_irqsave(ap->lock, flags);  	if (!(ap->pflags & ATA_PFLAG_PM_PENDING) || -	    ap->pm_mesg.event != PM_EVENT_ON) { +	    !(ap->pm_mesg.event & PM_EVENT_RESUME)) {  		spin_unlock_irqrestore(ap->lock, flags);  		return;  	} @@ -3975,7 +4123,7 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)  		ata_for_each_dev(dev, link, ALL)  			ata_ering_clear(&dev->ering); -	ata_acpi_set_state(ap, PMSG_ON); +	ata_acpi_set_state(ap, ap->pm_mesg);  	if (ap->ops->port_resume)  		rc = ap->ops->port_resume(ap); @@ -3983,13 +4131,9 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)  	/* tell ACPI that we're resuming */  	ata_acpi_on_resume(ap); -	/* report result */ +	/* update the flags */  	spin_lock_irqsave(ap->lock, flags);  	ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED); -	if (ap->pm_result) { -		*ap->pm_result = rc; -		ap->pm_result = NULL; -	}  	spin_unlock_irqrestore(ap->lock, flags);  }  #endif /* CONFIG_PM */ diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 3120596d4af..7ccc084bf1d 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -8,6 +8,7 @@   */  #include <linux/kernel.h> +#include <linux/export.h>  #include <linux/libata.h>  #include <linux/slab.h>  #include "libata.h" @@ -147,8 +148,8 @@ int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *r_val)  	err_mask = sata_pmp_read(link, reg, r_val);  	if (err_mask) { -		ata_link_printk(link, KERN_WARNING, "failed to read SCR %d " -				"(Emask=0x%x)\n", reg, err_mask); +		ata_link_warn(link, "failed to read SCR %d (Emask=0x%x)\n", +			      reg, err_mask);  		return -EIO;  	}  	return 0; @@ -178,8 +179,8 @@ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val)  	err_mask = sata_pmp_write(link, reg, val);  	if (err_mask) { -		ata_link_printk(link, KERN_WARNING, "failed to write SCR %d " -				"(Emask=0x%x)\n", reg, err_mask); +		ata_link_warn(link, "failed to write SCR %d (Emask=0x%x)\n", +			      reg, err_mask);  		return -EIO;  	}  	return 0; @@ -231,8 +232,8 @@ static int sata_pmp_read_gscr(struct ata_device *dev, u32 *gscr)  		err_mask = sata_pmp_read(dev->link, reg, &gscr[reg]);  		if (err_mask) { -			ata_dev_printk(dev, KERN_ERR, "failed to read PMP " -				"GSCR[%d] (Emask=0x%x)\n", reg, err_mask); +			ata_dev_err(dev, "failed to read PMP GSCR[%d] (Emask=0x%x)\n", +				    reg, err_mask);  			return -EIO;  		}  	} @@ -288,49 +289,48 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)  	/* Disable sending Early R_OK.  	 * With "cached read" HDD testing and multiple ports busy on a SATA -	 * host controller, 3726 PMP will very rarely drop a deferred +	 * host controller, 3x26 PMP will very rarely drop a deferred  	 * R_OK that was intended for the host. Symptom will be all  	 * 5 drives under test will timeout, get reset, and recover.  	 */ -	if (vendor == 0x1095 && devid == 0x3726) { +	if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {  		u32 reg;  		err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, ®);  		if (err_mask) {  			rc = -EIO; -			reason = "failed to read Sil3726 Private Register"; +			reason = "failed to read Sil3x26 Private Register";  			goto fail;  		}  		reg &= ~0x1;  		err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);  		if (err_mask) {  			rc = -EIO; -			reason = "failed to write Sil3726 Private Register"; +			reason = "failed to write Sil3x26 Private Register";  			goto fail;  		}  	}  	if (print_info) { -		ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, " -			       "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n", -			       sata_pmp_spec_rev_str(gscr), vendor, devid, -			       sata_pmp_gscr_rev(gscr), -			       nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN], -			       gscr[SATA_PMP_GSCR_FEAT]); +		ata_dev_info(dev, "Port Multiplier %s, " +			     "0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n", +			     sata_pmp_spec_rev_str(gscr), vendor, devid, +			     sata_pmp_gscr_rev(gscr), +			     nr_ports, gscr[SATA_PMP_GSCR_FEAT_EN], +			     gscr[SATA_PMP_GSCR_FEAT]);  		if (!(dev->flags & ATA_DFLAG_AN)) -			ata_dev_printk(dev, KERN_INFO, +			ata_dev_info(dev,  				"Asynchronous notification not supported, " -				"hotplug won't\n         work on fan-out " -				"ports. Use warm-plug instead.\n"); +				"hotplug won't work on fan-out ports. Use warm-plug instead.\n");  	}  	return 0;   fail: -	ata_dev_printk(dev, KERN_ERR, -		       "failed to configure Port Multiplier (%s, Emask=0x%x)\n", -		       reason, err_mask); +	ata_dev_err(dev, +		    "failed to configure Port Multiplier (%s, Emask=0x%x)\n", +		    reason, err_mask);  	return rc;  } @@ -383,14 +383,15 @@ static void sata_pmp_quirks(struct ata_port *ap)  	u16 devid = sata_pmp_gscr_devid(gscr);  	struct ata_link *link; -	if (vendor == 0x1095 && devid == 0x3726) { -		/* sil3726 quirks */ +	if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) { +		/* sil3x26 quirks */  		ata_for_each_link(link, ap, EDGE) {  			/* link reports offline after LPM */  			link->flags |= ATA_LFLAG_NO_LPM; -			/* Class code report is unreliable and SRST -			 * times out under certain configurations. +			/* +			 * Class code report is unreliable and SRST times +			 * out under certain configurations.  			 */  			if (link->pmp < 5)  				link->flags |= ATA_LFLAG_NO_SRST | @@ -402,20 +403,17 @@ static void sata_pmp_quirks(struct ata_port *ap)  					       ATA_LFLAG_ASSUME_SEMB;  		}  	} else if (vendor == 0x1095 && devid == 0x4723) { -		/* sil4723 quirks */ -		ata_for_each_link(link, ap, EDGE) { -			/* link reports offline after LPM */ -			link->flags |= ATA_LFLAG_NO_LPM; - -			/* class code report is unreliable */ -			if (link->pmp < 2) -				link->flags |= ATA_LFLAG_ASSUME_ATA; - -			/* the config device at port 2 locks up on SRST */ -			if (link->pmp == 2) -				link->flags |= ATA_LFLAG_NO_SRST | -					       ATA_LFLAG_ASSUME_ATA; -		} +		/* +		 * sil4723 quirks +		 * +		 * Link reports offline after LPM.  Class code report is +		 * unreliable.  SIMG PMPs never got SRST reliable and the +		 * config device at port 2 locks up on SRST. +		 */ +		ata_for_each_link(link, ap, EDGE) +			link->flags |= ATA_LFLAG_NO_LPM | +				       ATA_LFLAG_NO_SRST | +				       ATA_LFLAG_ASSUME_ATA;  	} else if (vendor == 0x1095 && devid == 0x4726) {  		/* sil4726 quirks */  		ata_for_each_link(link, ap, EDGE) { @@ -449,6 +447,19 @@ static void sata_pmp_quirks(struct ata_port *ap)  		 * otherwise.  Don't try hard to recover it.  		 */  		ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY; +	} else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325)) { +		/* +		 * 0x2352: found in Thermaltake BlackX Duet, jmicron JMB350? +		 * 0x0325: jmicron JMB394. +		 */ +		ata_for_each_link(link, ap, EDGE) { +			/* SRST breaks detection and disks get misclassified +			 * LPM disabled to avoid potential problems +			 */ +			link->flags |= ATA_LFLAG_NO_LPM | +				       ATA_LFLAG_NO_SRST | +				       ATA_LFLAG_ASSUME_ATA; +		}  	}  } @@ -475,20 +486,17 @@ int sata_pmp_attach(struct ata_device *dev)  	/* is it hanging off the right place? */  	if (!sata_pmp_supported(ap)) { -		ata_dev_printk(dev, KERN_ERR, -			       "host does not support Port Multiplier\n"); +		ata_dev_err(dev, "host does not support Port Multiplier\n");  		return -EINVAL;  	}  	if (!ata_is_host_link(link)) { -		ata_dev_printk(dev, KERN_ERR, -			       "Port Multipliers cannot be nested\n"); +		ata_dev_err(dev, "Port Multipliers cannot be nested\n");  		return -EINVAL;  	}  	if (dev->devno) { -		ata_dev_printk(dev, KERN_ERR, -			       "Port Multiplier must be the first device\n"); +		ata_dev_err(dev, "Port Multiplier must be the first device\n");  		return -EINVAL;  	} @@ -507,8 +515,7 @@ int sata_pmp_attach(struct ata_device *dev)  	rc = sata_pmp_init_links(ap, sata_pmp_gscr_ports(dev->gscr));  	if (rc) { -		ata_dev_printk(dev, KERN_INFO, -			       "failed to initialize PMP links\n"); +		ata_dev_info(dev, "failed to initialize PMP links\n");  		goto fail;  	} @@ -526,8 +533,6 @@ int sata_pmp_attach(struct ata_device *dev)  	ata_for_each_link(tlink, ap, EDGE)  		sata_link_init_spd(tlink); -	ata_acpi_associate_sata_port(ap); -  	return 0;   fail: @@ -552,7 +557,7 @@ static void sata_pmp_detach(struct ata_device *dev)  	struct ata_link *tlink;  	unsigned long flags; -	ata_dev_printk(dev, KERN_INFO, "Port Multiplier detaching\n"); +	ata_dev_info(dev, "Port Multiplier detaching\n");  	WARN_ON(!ata_is_host_link(link) || dev->devno ||  		link->pmp != SATA_PMP_CTRL_PORT); @@ -567,8 +572,6 @@ static void sata_pmp_detach(struct ata_device *dev)  	ap->nr_pmp_links = 0;  	link->pmp = 0;  	spin_unlock_irqrestore(ap->lock, flags); - -	ata_acpi_associate_sata_port(ap);  }  /** @@ -599,23 +602,23 @@ static int sata_pmp_same_pmp(struct ata_device *dev, const u32 *new_gscr)  	new_nr_ports = sata_pmp_gscr_ports(new_gscr);  	if (old_vendor != new_vendor) { -		ata_dev_printk(dev, KERN_INFO, "Port Multiplier " -			       "vendor mismatch '0x%x' != '0x%x'\n", -			       old_vendor, new_vendor); +		ata_dev_info(dev, +			     "Port Multiplier vendor mismatch '0x%x' != '0x%x'\n", +			     old_vendor, new_vendor);  		return 0;  	}  	if (old_devid != new_devid) { -		ata_dev_printk(dev, KERN_INFO, "Port Multiplier " -			       "device ID mismatch '0x%x' != '0x%x'\n", -			       old_devid, new_devid); +		ata_dev_info(dev, +			     "Port Multiplier device ID mismatch '0x%x' != '0x%x'\n", +			     old_devid, new_devid);  		return 0;  	}  	if (old_nr_ports != new_nr_ports) { -		ata_dev_printk(dev, KERN_INFO, "Port Multiplier " -			       "nr_ports mismatch '0x%x' != '0x%x'\n", -			       old_nr_ports, new_nr_ports); +		ata_dev_info(dev, +			     "Port Multiplier nr_ports mismatch '0x%x' != '0x%x'\n", +			     old_nr_ports, new_nr_ports);  		return 0;  	} @@ -681,8 +684,7 @@ static int sata_pmp_revalidate(struct ata_device *dev, unsigned int new_class)  	return 0;   fail: -	ata_dev_printk(dev, KERN_ERR, -		       "PMP revalidation failed (errno=%d)\n", rc); +	ata_dev_err(dev, "PMP revalidation failed (errno=%d)\n", rc);  	DPRINTK("EXIT, rc=%d\n", rc);  	return rc;  } @@ -706,13 +708,14 @@ static int sata_pmp_revalidate_quick(struct ata_device *dev)  	err_mask = sata_pmp_read(dev->link, SATA_PMP_GSCR_PROD_ID, &prod_id);  	if (err_mask) { -		ata_dev_printk(dev, KERN_ERR, "failed to read PMP product ID " -			       "(Emask=0x%x)\n", err_mask); +		ata_dev_err(dev, +			    "failed to read PMP product ID (Emask=0x%x)\n", +			    err_mask);  		return -EIO;  	}  	if (prod_id != dev->gscr[SATA_PMP_GSCR_PROD_ID]) { -		ata_dev_printk(dev, KERN_ERR, "PMP product ID mismatch\n"); +		ata_dev_err(dev, "PMP product ID mismatch\n");  		/* something weird is going on, request full PMP recovery */  		return -EIO;  	} @@ -767,8 +770,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,  		rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,  				  postreset);  		if (rc) { -			ata_link_printk(link, KERN_ERR, -					"failed to reset PMP, giving up\n"); +			ata_link_err(link, "failed to reset PMP, giving up\n");  			goto fail;  		} @@ -809,9 +811,9 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,  			ehc->i.action |= ATA_EH_RESET;  			goto retry;  		} else { -			ata_dev_printk(dev, KERN_ERR, "failed to recover PMP " -				       "after %d tries, giving up\n", -				       ATA_EH_PMP_TRIES); +			ata_dev_err(dev, +				    "failed to recover PMP after %d tries, giving up\n", +				    ATA_EH_PMP_TRIES);  			goto fail;  		}  	} @@ -857,8 +859,9 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap)  		/* unconditionally clear SError.N */  		rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);  		if (rc) { -			ata_link_printk(link, KERN_ERR, "failed to clear " -					"SError.N (errno=%d)\n", rc); +			ata_link_err(link, +				     "failed to clear SError.N (errno=%d)\n", +				     rc);  			return rc;  		} @@ -880,7 +883,7 @@ static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)  	/* disable this link */  	if (!(link->flags & ATA_LFLAG_DISABLED)) { -		ata_link_printk(link, KERN_WARNING, +		ata_link_warn(link,  			"failed to recover link after %d tries, disabling\n",  			ATA_EH_PMP_LINK_TRIES); @@ -964,7 +967,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)  		err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,  					  gscr[SATA_PMP_GSCR_FEAT_EN]);  		if (err_mask) { -			ata_link_printk(pmp_link, KERN_WARNING, +			ata_link_warn(pmp_link,  				"failed to disable NOTIFY (err_mask=0x%x)\n",  				err_mask);  			goto pmp_fail; @@ -1008,8 +1011,9 @@ static int sata_pmp_eh_recover(struct ata_port *ap)  		err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,  					  gscr[SATA_PMP_GSCR_FEAT_EN]);  		if (err_mask) { -			ata_dev_printk(pmp_dev, KERN_ERR, "failed to write " -				       "PMP_FEAT_EN (Emask=0x%x)\n", err_mask); +			ata_dev_err(pmp_dev, +				    "failed to write PMP_FEAT_EN (Emask=0x%x)\n", +				    err_mask);  			rc = -EIO;  			goto pmp_fail;  		} @@ -1018,8 +1022,9 @@ static int sata_pmp_eh_recover(struct ata_port *ap)  	/* check GSCR_ERROR */  	err_mask = sata_pmp_read(pmp_link, SATA_PMP_GSCR_ERROR, &gscr_error);  	if (err_mask) { -		ata_dev_printk(pmp_dev, KERN_ERR, "failed to read " -			       "PMP_GSCR_ERROR (Emask=0x%x)\n", err_mask); +		ata_dev_err(pmp_dev, +			    "failed to read PMP_GSCR_ERROR (Emask=0x%x)\n", +			    err_mask);  		rc = -EIO;  		goto pmp_fail;  	} @@ -1033,17 +1038,16 @@ static int sata_pmp_eh_recover(struct ata_port *ap)  			ata_ehi_hotplugged(&link->eh_context.i);  			cnt++;  		} else { -			ata_link_printk(link, KERN_WARNING, -				"PHY status changed but maxed out on retries, " -				"giving up\n"); -			ata_link_printk(link, KERN_WARNING, -				"Manully issue scan to resume this link\n"); +			ata_link_warn(link, +				"PHY status changed but maxed out on retries, giving up\n"); +			ata_link_warn(link, +				"Manually issue scan to resume this link\n");  		}  	}  	if (cnt) { -		ata_port_printk(ap, KERN_INFO, "PMP SError.N set for some " -				"ports, repeating recovery\n"); +		ata_port_info(ap, +			"PMP SError.N set for some ports, repeating recovery\n");  		goto retry;  	} @@ -1071,9 +1075,8 @@ static int sata_pmp_eh_recover(struct ata_port *ap)  		goto retry;  	} -	ata_port_printk(ap, KERN_ERR, -			"failed to recover PMP after %d tries, giving up\n", -			ATA_EH_PMP_TRIES); +	ata_port_err(ap, "failed to recover PMP after %d tries, giving up\n", +		     ATA_EH_PMP_TRIES);  	sata_pmp_detach(pmp_dev);  	ata_dev_disable(pmp_dev); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3f91c01c217..72691fd9394 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1,7 +1,7 @@  /*   *  libata-scsi.c - helper library for ATA   * - *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> + *  Maintained by:  Tejun Heo <tj@kernel.org>   *    		    Please ALWAYS copy linux-ide@vger.kernel.org   *		    on emails.   * @@ -37,6 +37,7 @@  #include <linux/kernel.h>  #include <linux/blkdev.h>  #include <linux/spinlock.h> +#include <linux/export.h>  #include <scsi/scsi.h>  #include <scsi/scsi_host.h>  #include <scsi/scsi_cmnd.h> @@ -110,12 +111,14 @@ static const char *ata_lpm_policy_names[] = {  	[ATA_LPM_MIN_POWER]	= "min_power",  }; -static ssize_t ata_scsi_lpm_store(struct device *dev, +static ssize_t ata_scsi_lpm_store(struct device *device,  				  struct device_attribute *attr,  				  const char *buf, size_t count)  { -	struct Scsi_Host *shost = class_to_shost(dev); +	struct Scsi_Host *shost = class_to_shost(device);  	struct ata_port *ap = ata_shost_to_port(shost); +	struct ata_link *link; +	struct ata_device *dev;  	enum ata_lpm_policy policy;  	unsigned long flags; @@ -131,10 +134,20 @@ static ssize_t ata_scsi_lpm_store(struct device *dev,  		return -EINVAL;  	spin_lock_irqsave(ap->lock, flags); + +	ata_for_each_link(link, ap, EDGE) { +		ata_for_each_dev(dev, &ap->link, ENABLED) { +			if (dev->horkage & ATA_HORKAGE_NOLPM) { +				count = -EOPNOTSUPP; +				goto out_unlock; +			} +		} +	} +  	ap->target_lpm_policy = policy;  	ata_port_schedule_eh(ap); +out_unlock:  	spin_unlock_irqrestore(ap->lock, flags); -  	return count;  } @@ -204,8 +217,10 @@ static ssize_t ata_scsi_park_store(struct device *device,  	unsigned long flags;  	int rc; -	rc = strict_strtol(buf, 10, &input); -	if (rc || input < -2) +	rc = kstrtol(buf, 10, &input); +	if (rc) +		return rc; +	if (input < -2)  		return -EINVAL;  	if (input > ATA_TMOUT_MAX_PARK) {  		rc = -EOVERFLOW; @@ -308,7 +323,8 @@ ata_scsi_activity_show(struct device *dev, struct device_attribute *attr,  	struct ata_port *ap = ata_shost_to_port(sdev->host);  	struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); -	if (ap->ops->sw_activity_show && (ap->flags & ATA_FLAG_SW_ACTIVITY)) +	if (atadev && ap->ops->sw_activity_show && +	    (ap->flags & ATA_FLAG_SW_ACTIVITY))  		return ap->ops->sw_activity_show(atadev, buf);  	return -EINVAL;  } @@ -323,7 +339,8 @@ ata_scsi_activity_store(struct device *dev, struct device_attribute *attr,  	enum sw_activity val;  	int rc; -	if (ap->ops->sw_activity_store && (ap->flags & ATA_FLAG_SW_ACTIVITY)) { +	if (atadev && ap->ops->sw_activity_store && +	    (ap->flags & ATA_FLAG_SW_ACTIVITY)) {  		val = simple_strtoul(buf, NULL, 0);  		switch (val) {  		case OFF: case BLINK_ON: case BLINK_OFF: @@ -346,12 +363,11 @@ struct device_attribute *ata_common_sdev_attrs[] = {  };  EXPORT_SYMBOL_GPL(ata_common_sdev_attrs); -static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, -				   void (*done)(struct scsi_cmnd *)) +static void ata_scsi_invalid_field(struct scsi_cmnd *cmd)  {  	ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);  	/* "Invalid field in cbd" */ -	done(cmd); +	cmd->scsi_done(cmd);  }  /** @@ -530,8 +546,8 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)  			struct scsi_sense_hdr sshdr;  			scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,  					     &sshdr); -			if (sshdr.sense_key == 0 && -			    sshdr.asc == 0 && sshdr.ascq == 0) +			if (sshdr.sense_key == RECOVERED_ERROR && +			    sshdr.asc == 0 && sshdr.ascq == 0x1d)  				cmd_result &= ~SAM_STAT_CHECK_CONDITION;  		} @@ -616,8 +632,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)  			struct scsi_sense_hdr sshdr;  			scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,  						&sshdr); -			if (sshdr.sense_key == 0 && -				sshdr.asc == 0 && sshdr.ascq == 0) +			if (sshdr.sense_key == RECOVERED_ERROR && +			    sshdr.asc == 0 && sshdr.ascq == 0x1d)  				cmd_result &= ~SAM_STAT_CHECK_CONDITION;  		} @@ -719,7 +735,6 @@ EXPORT_SYMBOL_GPL(ata_scsi_ioctl);   *	ata_scsi_qc_new - acquire new ata_queued_cmd reference   *	@dev: ATA device to which the new command is attached   *	@cmd: SCSI command that originated this ATA command - *	@done: SCSI command completion function   *   *	Obtain a reference to an unused ata_queued_cmd structure,   *	which is the basic libata structure representing a single @@ -736,21 +751,20 @@ EXPORT_SYMBOL_GPL(ata_scsi_ioctl);   *	Command allocated, or %NULL if none available.   */  static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, -					      struct scsi_cmnd *cmd, -					      void (*done)(struct scsi_cmnd *)) +					      struct scsi_cmnd *cmd)  {  	struct ata_queued_cmd *qc;  	qc = ata_qc_new_init(dev);  	if (qc) {  		qc->scsicmd = cmd; -		qc->scsidone = done; +		qc->scsidone = cmd->scsi_done;  		qc->sg = scsi_sglist(cmd);  		qc->n_elem = scsi_sg_count(cmd);  	} else {  		cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1); -		done(cmd); +		cmd->scsi_done(cmd);  	}  	return qc; @@ -848,25 +862,24 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,  		/*  Bad address mark */  		{0x01, 		MEDIUM_ERROR, 0x13, 0x00}, 	// Address mark not found       Address mark not found for data field  		/* TRK0 */ -		{0x02, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Track 0 not found		  Hardware error -		/* Abort & !ICRC */ -		{0x04, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Aborted command              Aborted command +		{0x02, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Track 0 not found		Hardware error +		/* Abort: 0x04 is not translated here, see below */  		/* Media change request */  		{0x08, 		NOT_READY, 0x04, 0x00}, 	// Media change request	  FIXME: faking offline -		/* SRV */ -		{0x10, 		ABORTED_COMMAND, 0x14, 0x00}, 	// ID not found                 Recorded entity not found -		/* Media change */ -		{0x08,  	NOT_READY, 0x04, 0x00}, 	// Media change		  FIXME: faking offline +		/* SRV/IDNF */ +		{0x10, 		ILLEGAL_REQUEST, 0x21, 0x00}, 	// ID not found                 Logical address out of range +		/* MC */ +		{0x20, 		UNIT_ATTENTION, 0x28, 0x00}, 	// Media Changed		Not ready to ready change, medium may have changed  		/* ECC */  		{0x40, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Uncorrectable ECC error      Unrecovered read error  		/* BBD - block marked bad */ -		{0x80, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Block marked bad		  Medium error, unrecovered read error +		{0x80, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Block marked bad		Medium error, unrecovered read error  		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark  	};  	static const unsigned char stat_table[][4] = {  		/* Must be first because BUSY means no other bits valid */  		{0x80, 		ABORTED_COMMAND, 0x47, 0x00},	// Busy, fake parity for now -		{0x20, 		HARDWARE_ERROR,  0x00, 0x00}, 	// Device fault +		{0x20, 		HARDWARE_ERROR,  0x44, 0x00}, 	// Device fault, internal target failure  		{0x08, 		ABORTED_COMMAND, 0x47, 0x00},	// Timed out in xfer, fake parity for now  		{0x04, 		RECOVERED_ERROR, 0x11, 0x00},	// Recovered ECC error	  Medium error, recovered  		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark @@ -891,13 +904,13 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,  				goto translate_done;  			}  		} -		/* No immediate match */ -		if (verbose) -			printk(KERN_WARNING "ata%u: no sense translation for " -			       "error 0x%02x\n", id, drv_err);  	} -	/* Fall back to interpreting status bits */ +	/* +	 * Fall back to interpreting status bits.  Note that if the drv_err +	 * has only the ABRT bit set, we decode drv_stat.  ABRT by itself +	 * is not descriptive enough. +	 */  	for (i = 0; stat_table[i][0] != 0xFF; i++) {  		if (stat_table[i][0] & drv_stat) {  			*sk = stat_table[i][1]; @@ -906,13 +919,11 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,  			goto translate_done;  		}  	} -	/* No error?  Undecoded? */ -	if (verbose) -		printk(KERN_WARNING "ata%u: no sense translation for " -		       "status: 0x%02x\n", id, drv_stat); -	/* We need a sensible error return here, which is tricky, and one -	   that won't cause people to do things like return a disk wrongly */ +	/* +	 * We need a sensible error return here, which is tricky, and one +	 * that won't cause people to do things like return a disk wrongly. +	 */  	*sk = ABORTED_COMMAND;  	*asc = 0x00;  	*ascq = 0x00; @@ -933,7 +944,11 @@ static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,   *	block specified for the ATA pass through commands.  Regardless   *	of whether the command errored or not, return a sense   *	block. Copy all controller registers into the sense - *	block. Clear sense key, ASC & ASCQ if there is no error. + *	block. If there was no error, we get the request from an ATA + *	passthrough command, so we use the following sense data: + *	sk = RECOVERED ERROR + *	asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE + *         *   *	LOCKING:   *	None. @@ -959,6 +974,10 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)  		ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature,  				   &sb[1], &sb[2], &sb[3], verbose);  		sb[1] &= 0x0f; +	} else { +		sb[1] = RECOVERED_ERROR; +		sb[2] = 0; +		sb[3] = 0x1D;  	}  	/* @@ -1002,7 +1021,7 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)   *	@qc: Command that we are erroring out   *   *	Generate sense block for a failed ATA command @qc.  Descriptor - *	format is used to accomodate LBA48 block address. + *	format is used to accommodate LBA48 block address.   *   *	LOCKING:   *	None. @@ -1054,6 +1073,8 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)  {  	sdev->use_10_for_rw = 1;  	sdev->use_10_for_ms = 1; +	sdev->no_report_opcodes = 1; +	sdev->no_write_same = 1;  	/* Schedule policy is determined by ->qc_defer() callback and  	 * it needs to see every deferred qc.  Set dev_blocked to 1 to @@ -1092,39 +1113,49 @@ static int atapi_drain_needed(struct request *rq)  static int ata_scsi_dev_config(struct scsi_device *sdev,  			       struct ata_device *dev)  { +	struct request_queue *q = sdev->request_queue; +  	if (!ata_id_has_unload(dev->id))  		dev->flags |= ATA_DFLAG_NO_UNLOAD;  	/* configure max sectors */ -	blk_queue_max_hw_sectors(sdev->request_queue, dev->max_sectors); +	blk_queue_max_hw_sectors(q, dev->max_sectors);  	if (dev->class == ATA_DEV_ATAPI) { -		struct request_queue *q = sdev->request_queue;  		void *buf; -		/* set the min alignment and padding */ -		blk_queue_update_dma_alignment(sdev->request_queue, -					       ATA_DMA_PAD_SZ - 1); -		blk_queue_update_dma_pad(sdev->request_queue, -					 ATA_DMA_PAD_SZ - 1); +		sdev->sector_size = ATA_SECT_SIZE; + +		/* set DMA padding */ +		blk_queue_update_dma_pad(q, ATA_DMA_PAD_SZ - 1);  		/* configure draining */  		buf = kmalloc(ATAPI_MAX_DRAIN, q->bounce_gfp | GFP_KERNEL);  		if (!buf) { -			ata_dev_printk(dev, KERN_ERR, -				       "drain buffer allocation failed\n"); +			ata_dev_err(dev, "drain buffer allocation failed\n");  			return -ENOMEM;  		}  		blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN);  	} else { -		/* ATA devices must be sector aligned */  		sdev->sector_size = ata_id_logical_sector_size(dev->id); -		blk_queue_update_dma_alignment(sdev->request_queue, -					       sdev->sector_size - 1);  		sdev->manage_start_stop = 1;  	} +	/* +	 * ata_pio_sectors() expects buffer for each sector to not cross +	 * page boundary.  Enforce it by requiring buffers to be sector +	 * aligned, which works iff sector_size is not larger than +	 * PAGE_SIZE.  ATAPI devices also need the alignment as +	 * IDENTIFY_PACKET is executed as ATA_PROT_PIO. +	 */ +	if (sdev->sector_size > PAGE_SIZE) +		ata_dev_warn(dev, +			"sector_size=%u > PAGE_SIZE, PIO may malfunction\n", +			sdev->sector_size); + +	blk_queue_update_dma_alignment(q, sdev->sector_size - 1); +  	if (dev->flags & ATA_DFLAG_AN)  		set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); @@ -1136,6 +1167,8 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,  		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);  	} +	blk_queue_flush_queueable(q, false); +  	dev->sdev = sdev;  	return 0;  } @@ -1206,25 +1239,19 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)  }  /** - *	ata_scsi_change_queue_depth - SCSI callback for queue depth config + *	__ata_change_queue_depth - helper for ata_scsi_change_queue_depth + *	@ap: ATA port to which the device change the queue depth   *	@sdev: SCSI device to configure queue depth for   *	@queue_depth: new queue depth   *	@reason: calling context   * - *	This is libata standard hostt->change_queue_depth callback. - *	SCSI will call into this callback when user tries to set queue - *	depth via sysfs. + *	libsas and libata have different approaches for associating a sdev to + *	its ata_port.   * - *	LOCKING: - *	SCSI layer (we don't care) - * - *	RETURNS: - *	Newly configured queue depth.   */ -int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth, -				int reason) +int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev, +			     int queue_depth, int reason)  { -	struct ata_port *ap = ata_shost_to_port(sdev->host);  	struct ata_device *dev;  	unsigned long flags; @@ -1260,6 +1287,30 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,  }  /** + *	ata_scsi_change_queue_depth - SCSI callback for queue depth config + *	@sdev: SCSI device to configure queue depth for + *	@queue_depth: new queue depth + *	@reason: calling context + * + *	This is libata standard hostt->change_queue_depth callback. + *	SCSI will call into this callback when user tries to set queue + *	depth via sysfs. + * + *	LOCKING: + *	SCSI layer (we don't care) + * + *	RETURNS: + *	Newly configured queue depth. + */ +int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth, +				int reason) +{ +	struct ata_port *ap = ata_shost_to_port(sdev->host); + +	return __ata_change_queue_depth(ap, sdev, queue_depth, reason); +} + +/**   *	ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command   *	@qc: Storage for translated ATA taskfile   * @@ -1627,7 +1678,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)  		if (unlikely(scmd->cmd_len < 10))  			goto invalid_fld;  		scsi_10_lba_len(cdb, &block, &n_block); -		if (unlikely(cdb[1] & (1 << 3))) +		if (cdb[1] & (1 << 3))  			tf_flags |= ATA_TFLAG_FUA;  		break;  	case READ_6: @@ -1647,7 +1698,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)  		if (unlikely(scmd->cmd_len < 16))  			goto invalid_fld;  		scsi_16_lba_len(cdb, &block, &n_block); -		if (unlikely(cdb[1] & (1 << 3))) +		if (cdb[1] & (1 << 3))  			tf_flags |= ATA_TFLAG_FUA;  		break;  	default: @@ -1701,10 +1752,12 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)  	/* For ATA pass thru (SAT) commands, generate a sense block if  	 * user mandated it or if there's an error.  Note that if we -	 * generate because the user forced us to, a check condition -	 * is generated and the ATA register values are returned +	 * generate because the user forced us to [CK_COND =1], a check +	 * condition is generated and the ATA register values are returned  	 * whether the command completed successfully or not. If there -	 * was no error, SK, ASC and ASCQ will all be zero. +	 * was no error, we use the following sense data: +	 * sk = RECOVERED ERROR +	 * asc,ascq = ATA PASS-THROUGH INFORMATION AVAILABLE  	 */  	if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&  	    ((cdb[2] & 0x20) || need_sense)) { @@ -1735,7 +1788,6 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)   *	ata_scsi_translate - Translate then issue SCSI command to ATA device   *	@dev: ATA device to which the command is addressed   *	@cmd: SCSI command to execute - *	@done: SCSI command completion function   *	@xlat_func: Actor which translates @cmd to an ATA taskfile   *   *	Our ->queuecommand() function has decided that the SCSI @@ -1759,7 +1811,6 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)   *	needs to be deferred.   */  static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, -			      void (*done)(struct scsi_cmnd *),  			      ata_xlat_func_t xlat_func)  {  	struct ata_port *ap = dev->link->ap; @@ -1768,7 +1819,7 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,  	VPRINTK("ENTER\n"); -	qc = ata_scsi_qc_new(dev, cmd, done); +	qc = ata_scsi_qc_new(dev, cmd);  	if (!qc)  		goto err_mem; @@ -1776,8 +1827,7 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,  	if (cmd->sc_data_direction == DMA_FROM_DEVICE ||  	    cmd->sc_data_direction == DMA_TO_DEVICE) {  		if (unlikely(scsi_bufflen(cmd) < 1)) { -			ata_dev_printk(dev, KERN_WARNING, -				       "WARNING: zero len r/w req\n"); +			ata_dev_warn(dev, "WARNING: zero len r/w req\n");  			goto err_did;  		} @@ -1804,14 +1854,14 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,  early_finish:  	ata_qc_free(qc); -	qc->scsidone(cmd); +	cmd->scsi_done(cmd);  	DPRINTK("EXIT - early finish (good or error)\n");  	return 0;  err_did:  	ata_qc_free(qc);  	cmd->result = (DID_ERROR << 16); -	qc->scsidone(cmd); +	cmd->scsi_done(cmd);  err_mem:  	DPRINTK("EXIT - internal\n");  	return 0; @@ -1943,7 +1993,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)  	memcpy(rbuf, hdr, sizeof(hdr));  	memcpy(&rbuf[8], "ATA     ", 8);  	ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16); -	ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4); + +	/* From SAT, use last 2 words from fw rev unless they are spaces */ +	ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV + 2, 4); +	if (strncmp(&rbuf[32], "    ", 4) == 0) +		ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);  	if (rbuf[32] == 0 || rbuf[32] == ' ')  		memcpy(&rbuf[32], "n/a ", 4); @@ -2049,6 +2103,17 @@ static unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf)  		      ATA_ID_SERNO_LEN);  	num += ATA_ID_SERNO_LEN; +	if (ata_id_has_wwn(args->id)) { +		/* SAT defined lu world wide name */ +		/* piv=0, assoc=lu, code_set=binary, designator=NAA */ +		rbuf[num + 0] = 1; +		rbuf[num + 1] = 3; +		rbuf[num + 3] = ATA_ID_WWN_LEN; +		num += 4; +		ata_id_string(args->id, (unsigned char *) rbuf + num, +			      ATA_ID_WWN, ATA_ID_WWN_LEN); +		num += ATA_ID_WWN_LEN; +	}  	rbuf[3] = num - 4;    /* page len (assume less than 256 bytes) */  	return 0;  } @@ -2076,7 +2141,6 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)  	memcpy(&rbuf[8], "linux   ", 8);  	memcpy(&rbuf[16], "libata          ", 16);  	memcpy(&rbuf[32], DRV_VERSION, 4); -	ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);  	/* we don't store the ATA device signature, so we fake it */ @@ -2120,7 +2184,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)  	 * with the unmap bit set.  	 */  	if (ata_id_has_trim(args->id)) { -		put_unaligned_be32(65535 * 512 / 8, &rbuf[20]); +		put_unaligned_be64(65535 * 512 / 8, &rbuf[36]);  		put_unaligned_be32(1, &rbuf[28]);  	} @@ -2169,9 +2233,33 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)  }  /** + *	modecpy - Prepare response for MODE SENSE + *	@dest: output buffer + *	@src: data being copied + *	@n: length of mode page + *	@changeable: whether changeable parameters are requested + * + *	Generate a generic MODE SENSE page for either current or changeable + *	parameters. + * + *	LOCKING: + *	None. + */ +static void modecpy(u8 *dest, const u8 *src, int n, bool changeable) +{ +	if (changeable) { +		memcpy(dest, src, 2); +		memset(dest + 2, 0, n - 2); +	} else { +		memcpy(dest, src, n); +	} +} + +/**   *	ata_msense_caching - Simulate MODE SENSE caching info page   *	@id: device IDENTIFY data   *	@buf: output buffer + *	@changeable: whether changeable parameters are requested   *   *	Generate a caching info page, which conditionally indicates   *	write caching to the SCSI layer, depending on device @@ -2180,12 +2268,12 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)   *	LOCKING:   *	None.   */ -static unsigned int ata_msense_caching(u16 *id, u8 *buf) +static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable)  { -	memcpy(buf, def_cache_mpage, sizeof(def_cache_mpage)); -	if (ata_id_wcache_enabled(id)) +	modecpy(buf, def_cache_mpage, sizeof(def_cache_mpage), changeable); +	if (changeable || ata_id_wcache_enabled(id))  		buf[2] |= (1 << 2);	/* write cache enable */ -	if (!ata_id_rahead_enabled(id)) +	if (!changeable && !ata_id_rahead_enabled(id))  		buf[12] |= (1 << 5);	/* disable read ahead */  	return sizeof(def_cache_mpage);  } @@ -2193,30 +2281,33 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf)  /**   *	ata_msense_ctl_mode - Simulate MODE SENSE control mode page   *	@buf: output buffer + *	@changeable: whether changeable parameters are requested   *   *	Generate a generic MODE SENSE control mode page.   *   *	LOCKING:   *	None.   */ -static unsigned int ata_msense_ctl_mode(u8 *buf) +static unsigned int ata_msense_ctl_mode(u8 *buf, bool changeable)  { -	memcpy(buf, def_control_mpage, sizeof(def_control_mpage)); +	modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable);  	return sizeof(def_control_mpage);  }  /**   *	ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page   *	@buf: output buffer + *	@changeable: whether changeable parameters are requested   *   *	Generate a generic MODE SENSE r/w error recovery page.   *   *	LOCKING:   *	None.   */ -static unsigned int ata_msense_rw_recovery(u8 *buf) +static unsigned int ata_msense_rw_recovery(u8 *buf, bool changeable)  { -	memcpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage)); +	modecpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage), +		changeable);  	return sizeof(def_rw_recovery_mpage);  } @@ -2280,11 +2371,11 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)  	page_control = scsicmd[2] >> 6;  	switch (page_control) {  	case 0: /* current */ +	case 1: /* changeable */ +	case 2: /* defaults */  		break;  /* supported */  	case 3: /* saved */  		goto saving_not_supp; -	case 1: /* changeable */ -	case 2: /* defaults */  	default:  		goto invalid_fld;  	} @@ -2305,21 +2396,21 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)  	switch(pg) {  	case RW_RECOVERY_MPAGE: -		p += ata_msense_rw_recovery(p); +		p += ata_msense_rw_recovery(p, page_control == 1);  		break;  	case CACHE_MPAGE: -		p += ata_msense_caching(args->id, p); +		p += ata_msense_caching(args->id, p, page_control == 1);  		break;  	case CONTROL_MPAGE: -		p += ata_msense_ctl_mode(p); +		p += ata_msense_ctl_mode(p, page_control == 1);  		break;  	case ALL_MPAGES: -		p += ata_msense_rw_recovery(p); -		p += ata_msense_caching(args->id, p); -		p += ata_msense_ctl_mode(p); +		p += ata_msense_rw_recovery(p, page_control == 1); +		p += ata_msense_caching(args->id, p, page_control == 1); +		p += ata_msense_ctl_mode(p, page_control == 1);  		break;  	default:		/* invalid page code */ @@ -2950,9 +3041,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)  		 * with the cached multi_count of libata  		 */  		if (multi_count != dev->multi_count) -			ata_dev_printk(dev, KERN_WARNING, -				       "invalid multi_count %u ignored\n", -				       multi_count); +			ata_dev_warn(dev, "invalid multi_count %u ignored\n", +				     multi_count);  	}  	/* @@ -3025,12 +3115,25 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)  	buf = page_address(sg_page(scsi_sglist(scmd)));  	size = ata_set_lba_range_entries(buf, 512, block, n_block); -	tf->protocol = ATA_PROT_DMA; -	tf->hob_feature = 0; -	tf->feature = ATA_DSM_TRIM; -	tf->hob_nsect = (size / 512) >> 8; -	tf->nsect = size / 512; -	tf->command = ATA_CMD_DSM; +	if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) { +		/* Newer devices support queued TRIM commands */ +		tf->protocol = ATA_PROT_NCQ; +		tf->command = ATA_CMD_FPDMA_SEND; +		tf->hob_nsect = ATA_SUBCMD_FPDMA_SEND_DSM & 0x1f; +		tf->nsect = qc->tag << 3; +		tf->hob_feature = (size / 512) >> 8; +		tf->feature = size / 512; + +		tf->auxiliary = 1; +	} else { +		tf->protocol = ATA_PROT_DMA; +		tf->hob_feature = 0; +		tf->feature = ATA_DSM_TRIM; +		tf->hob_nsect = (size / 512) >> 8; +		tf->nsect = size / 512; +		tf->command = ATA_CMD_DSM; +	} +  	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 |  		     ATA_TFLAG_WRITE; @@ -3045,6 +3148,188 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)  }  /** + *	ata_mselect_caching - Simulate MODE SELECT for caching info page + *	@qc: Storage for translated ATA taskfile + *	@buf: input buffer + *	@len: number of valid bytes in the input buffer + * + *	Prepare a taskfile to modify caching information for the device. + * + *	LOCKING: + *	None. + */ +static int ata_mselect_caching(struct ata_queued_cmd *qc, +			       const u8 *buf, int len) +{ +	struct ata_taskfile *tf = &qc->tf; +	struct ata_device *dev = qc->dev; +	char mpage[CACHE_MPAGE_LEN]; +	u8 wce; + +	/* +	 * The first two bytes of def_cache_mpage are a header, so offsets +	 * in mpage are off by 2 compared to buf.  Same for len. +	 */ + +	if (len != CACHE_MPAGE_LEN - 2) +		return -EINVAL; + +	wce = buf[0] & (1 << 2); + +	/* +	 * Check that read-only bits are not modified. +	 */ +	ata_msense_caching(dev->id, mpage, false); +	mpage[2] &= ~(1 << 2); +	mpage[2] |= wce; +	if (memcmp(mpage + 2, buf, CACHE_MPAGE_LEN - 2) != 0) +		return -EINVAL; + +	tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR; +	tf->protocol = ATA_PROT_NODATA; +	tf->nsect = 0; +	tf->command = ATA_CMD_SET_FEATURES; +	tf->feature = wce ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF; +	return 0; +} + +/** + *	ata_scsiop_mode_select - Simulate MODE SELECT 6, 10 commands + *	@qc: Storage for translated ATA taskfile + * + *	Converts a MODE SELECT command to an ATA SET FEATURES taskfile. + *	Assume this is invoked for direct access devices (e.g. disks) only. + *	There should be no block descriptor for other device types. + * + *	LOCKING: + *	spin_lock_irqsave(host lock) + */ +static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) +{ +	struct scsi_cmnd *scmd = qc->scsicmd; +	const u8 *cdb = scmd->cmnd; +	const u8 *p; +	u8 pg, spg; +	unsigned six_byte, pg_len, hdr_len, bd_len; +	int len; + +	VPRINTK("ENTER\n"); + +	six_byte = (cdb[0] == MODE_SELECT); +	if (six_byte) { +		if (scmd->cmd_len < 5) +			goto invalid_fld; + +		len = cdb[4]; +		hdr_len = 4; +	} else { +		if (scmd->cmd_len < 9) +			goto invalid_fld; + +		len = (cdb[7] << 8) + cdb[8]; +		hdr_len = 8; +	} + +	/* We only support PF=1, SP=0.  */ +	if ((cdb[1] & 0x11) != 0x10) +		goto invalid_fld; + +	/* Test early for possible overrun.  */ +	if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len) +		goto invalid_param_len; + +	p = page_address(sg_page(scsi_sglist(scmd))); + +	/* Move past header and block descriptors.  */ +	if (len < hdr_len) +		goto invalid_param_len; + +	if (six_byte) +		bd_len = p[3]; +	else +		bd_len = (p[6] << 8) + p[7]; + +	len -= hdr_len; +	p += hdr_len; +	if (len < bd_len) +		goto invalid_param_len; +	if (bd_len != 0 && bd_len != 8) +		goto invalid_param; + +	len -= bd_len; +	p += bd_len; +	if (len == 0) +		goto skip; + +	/* Parse both possible formats for the mode page headers.  */ +	pg = p[0] & 0x3f; +	if (p[0] & 0x40) { +		if (len < 4) +			goto invalid_param_len; + +		spg = p[1]; +		pg_len = (p[2] << 8) | p[3]; +		p += 4; +		len -= 4; +	} else { +		if (len < 2) +			goto invalid_param_len; + +		spg = 0; +		pg_len = p[1]; +		p += 2; +		len -= 2; +	} + +	/* +	 * No mode subpages supported (yet) but asking for _all_ +	 * subpages may be valid +	 */ +	if (spg && (spg != ALL_SUB_MPAGES)) +		goto invalid_param; +	if (pg_len > len) +		goto invalid_param_len; + +	switch (pg) { +	case CACHE_MPAGE: +		if (ata_mselect_caching(qc, p, pg_len) < 0) +			goto invalid_param; +		break; + +	default:		/* invalid page code */ +		goto invalid_param; +	} + +	/* +	 * Only one page has changeable data, so we only support setting one +	 * page at a time. +	 */ +	if (len > pg_len) +		goto invalid_param; + +	return 0; + + invalid_fld: +	/* "Invalid field in CDB" */ +	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); +	return 1; + + invalid_param: +	/* "Invalid field in parameter list" */ +	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x26, 0x0); +	return 1; + + invalid_param_len: +	/* "Parameter list length error" */ +	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x1a, 0x0); +	return 1; + + skip: +	scmd->result = SAM_STAT_GOOD; +	return 1; +} + +/**   *	ata_get_xlat_func - check if SCSI to ATA translation is possible   *	@dev: ATA device   *	@cmd: SCSI command opcode to consider @@ -3084,6 +3369,11 @@ 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 MODE_SELECT: +	case MODE_SELECT_10: +		return ata_scsi_mode_select_xlat; +		break; +  	case START_STOP:  		return ata_scsi_start_stop_xlat;  	} @@ -3116,7 +3406,6 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap,  }  static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd, -				      void (*done)(struct scsi_cmnd *),  				      struct ata_device *dev)  {  	u8 scsi_op = scmd->cmnd[0]; @@ -3150,9 +3439,9 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,  	}  	if (xlat_func) -		rc = ata_scsi_translate(dev, scmd, done, xlat_func); +		rc = ata_scsi_translate(dev, scmd, xlat_func);  	else -		ata_scsi_simulate(dev, scmd, done); +		ata_scsi_simulate(dev, scmd);  	return rc; @@ -3160,14 +3449,14 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,  	DPRINTK("bad CDB len=%u, scsi_op=0x%02x, max=%u\n",  		scmd->cmd_len, scsi_op, dev->cdb_len);  	scmd->result = DID_ERROR << 16; -	done(scmd); +	scmd->scsi_done(scmd);  	return 0;  }  /**   *	ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device + *	@shost: SCSI host of command to be sent   *	@cmd: SCSI command to be sent - *	@done: Completion function, called when command is complete   *   *	In some cases, this function translates SCSI commands into   *	ATA taskfiles, and queues the taskfiles to be sent to @@ -3177,37 +3466,36 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,   *	ATA and ATAPI devices appearing as SCSI devices.   *   *	LOCKING: - *	Releases scsi-layer-held lock, and obtains host lock. + *	ATA host lock   *   *	RETURNS:   *	Return value from __ata_scsi_queuecmd() if @cmd can be queued,   *	0 otherwise.   */ -int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) +int ata_scsi_queuecmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd)  {  	struct ata_port *ap;  	struct ata_device *dev;  	struct scsi_device *scsidev = cmd->device; -	struct Scsi_Host *shost = scsidev->host;  	int rc = 0; +	unsigned long irq_flags;  	ap = ata_shost_to_port(shost); -	spin_unlock(shost->host_lock); -	spin_lock(ap->lock); +	spin_lock_irqsave(ap->lock, irq_flags);  	ata_scsi_dump_cdb(ap, cmd);  	dev = ata_scsi_find_dev(ap, scsidev);  	if (likely(dev)) -		rc = __ata_scsi_queuecmd(cmd, done, dev); +		rc = __ata_scsi_queuecmd(cmd, dev);  	else {  		cmd->result = (DID_BAD_TARGET << 16); -		done(cmd); +		cmd->scsi_done(cmd);  	} -	spin_unlock(ap->lock); -	spin_lock(shost->host_lock); +	spin_unlock_irqrestore(ap->lock, irq_flags); +  	return rc;  } @@ -3215,7 +3503,6 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))   *	ata_scsi_simulate - simulate SCSI command on ATA device   *	@dev: the target device   *	@cmd: SCSI command being sent to device. - *	@done: SCSI command completion function.   *   *	Interprets and directly executes a select list of SCSI commands   *	that can be handled internally. @@ -3224,8 +3511,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))   *	spin_lock_irqsave(host lock)   */ -void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, -		      void (*done)(struct scsi_cmnd *)) +void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd)  {  	struct ata_scsi_args args;  	const u8 *scsicmd = cmd->cmnd; @@ -3234,17 +3520,17 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,  	args.dev = dev;  	args.id = dev->id;  	args.cmd = cmd; -	args.done = done; +	args.done = cmd->scsi_done;  	switch(scsicmd[0]) {  	/* TODO: worth improving? */  	case FORMAT_UNIT: -		ata_scsi_invalid_field(cmd, done); +		ata_scsi_invalid_field(cmd);  		break;  	case INQUIRY:  		if (scsicmd[1] & 2)	           /* is CmdDt set?  */ -			ata_scsi_invalid_field(cmd, done); +			ata_scsi_invalid_field(cmd);  		else if ((scsicmd[1] & 1) == 0)    /* is EVPD clear? */  			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);  		else switch (scsicmd[2]) { @@ -3270,7 +3556,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,  			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2);  			break;  		default: -			ata_scsi_invalid_field(cmd, done); +			ata_scsi_invalid_field(cmd);  			break;  		}  		break; @@ -3280,11 +3566,6 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,  		ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense);  		break; -	case MODE_SELECT:	/* unconditionally return */ -	case MODE_SELECT_10:	/* bad-field-in-cdb */ -		ata_scsi_invalid_field(cmd, done); -		break; -  	case READ_CAPACITY:  		ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);  		break; @@ -3293,7 +3574,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,  		if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)  			ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);  		else -			ata_scsi_invalid_field(cmd, done); +			ata_scsi_invalid_field(cmd);  		break;  	case REPORT_LUNS: @@ -3303,7 +3584,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,  	case REQUEST_SENSE:  		ata_scsi_set_sense(cmd, 0, 0, 0);  		cmd->result = (DRIVER_SENSE << 24); -		done(cmd); +		cmd->scsi_done(cmd);  		break;  	/* if we reach this, then writeback caching is disabled, @@ -3325,14 +3606,14 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,  		if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4]))  			ata_scsi_rbuf_fill(&args, ata_scsiop_noop);  		else -			ata_scsi_invalid_field(cmd, done); +			ata_scsi_invalid_field(cmd);  		break;  	/* all other commands */  	default:  		ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);  		/* "Invalid command operation code" */ -		done(cmd); +		cmd->scsi_done(cmd);  		break;  	}  } @@ -3350,6 +3631,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)  		if (!shost)  			goto err_alloc; +		shost->eh_noresume = 1;  		*(struct ata_port **)&shost->hostdata[0] = ap;  		ap->scsi_host = shost; @@ -3359,6 +3641,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)  		shost->max_lun = 1;  		shost->max_channel = 1;  		shost->max_cmd_len = 16; +		shost->no_write_same = 1;  		/* Schedule policy is determined by ->qc_defer()  		 * callback and it needs to see every deferred qc. @@ -3367,7 +3650,8 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)  		 */  		shost->max_host_blocked = 1; -		rc = scsi_add_host(ap->scsi_host, ap->host->dev); +		rc = scsi_add_host_with_dma(ap->scsi_host, +						&ap->tdev, ap->host->dev);  		if (rc)  			goto err_add;  	} @@ -3451,9 +3735,8 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)  			goto repeat;  		} -		ata_port_printk(ap, KERN_ERR, "WARNING: synchronous SCSI scan " -				"failed without making any progress,\n" -				"                  switching to async\n"); +		ata_port_err(ap, +			     "WARNING: synchronous SCSI scan failed without making any progress, switching to async\n");  	}  	queue_delayed_work(system_long_wq, &ap->hotplug_task, @@ -3535,8 +3818,8 @@ static void ata_scsi_remove_dev(struct ata_device *dev)  	mutex_unlock(&ap->scsi_host->scan_mutex);  	if (sdev) { -		ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n", -			       dev_name(&sdev->sdev_gendev)); +		ata_dev_info(dev, "detaching (SCSI %s)\n", +			     dev_name(&sdev->sdev_gendev));  		scsi_remove_device(sdev);  		scsi_device_put(sdev); @@ -3558,6 +3841,9 @@ static void ata_scsi_handle_link_detach(struct ata_link *link)  		dev->flags &= ~ATA_DFLAG_DETACHED;  		spin_unlock_irqrestore(ap->lock, flags); +		if (zpodd_dev_enabled(dev)) +			zpodd_exit(dev); +  		ata_scsi_remove_dev(dev);  	}  } @@ -3602,6 +3888,27 @@ void ata_scsi_hotplug(struct work_struct *work)  		return;  	} +	/* +	 * XXX - UGLY HACK +	 * +	 * The block layer suspend/resume path is fundamentally broken due +	 * to freezable kthreads and workqueue and may deadlock if a block +	 * device gets removed while resume is in progress.  I don't know +	 * what the solution is short of removing freezable kthreads and +	 * workqueues altogether. +	 * +	 * The following is an ugly hack to avoid kicking off device +	 * removal while freezer is active.  This is a joke but does avoid +	 * this particular deadlock scenario. +	 * +	 * https://bugzilla.kernel.org/show_bug.cgi?id=62801 +	 * http://marc.info/?l=linux-kernel&m=138695698516487 +	 */ +#ifdef CONFIG_FREEZER +	while (pm_freezing) +		msleep(10); +#endif +  	DPRINTK("ENTER\n");  	mutex_lock(&ap->scsi_scan_mutex); @@ -3756,7 +4063,7 @@ struct ata_port *ata_sas_port_alloc(struct ata_host *host,  		return NULL;  	ap->port_no = 0; -	ap->lock = shost->host_lock; +	ap->lock = &host->lock;  	ap->pio_mask = port_info->pio_mask;  	ap->mwdma_mask = port_info->mwdma_mask;  	ap->udma_mask = port_info->udma_mask; @@ -3782,6 +4089,12 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc);   */  int ata_sas_port_start(struct ata_port *ap)  { +	/* +	 * the port is marked as frozen at allocation time, but if we don't +	 * have new eh, we won't thaw it +	 */ +	if (!ap->ops->error_handler) +		ap->pflags &= ~ATA_PFLAG_FROZEN;  	return 0;  }  EXPORT_SYMBOL_GPL(ata_sas_port_start); @@ -3802,6 +4115,26 @@ void ata_sas_port_stop(struct ata_port *ap)  EXPORT_SYMBOL_GPL(ata_sas_port_stop);  /** + * ata_sas_async_probe - simply schedule probing and return + * @ap: Port to probe + * + * For batch scheduling of probe for sas attached ata devices, assumes + * the port has already been through ata_sas_port_init() + */ +void ata_sas_async_probe(struct ata_port *ap) +{ +	__ata_port_probe(ap); +} +EXPORT_SYMBOL_GPL(ata_sas_async_probe); + +int ata_sas_sync_probe(struct ata_port *ap) +{ +	return ata_port_probe(ap); +} +EXPORT_SYMBOL_GPL(ata_sas_sync_probe); + + +/**   *	ata_sas_port_init - Initialize a SATA device   *	@ap: SATA port to initialize   * @@ -3816,12 +4149,10 @@ int ata_sas_port_init(struct ata_port *ap)  {  	int rc = ap->ops->port_start(ap); -	if (!rc) { -		ap->print_id = ata_print_id++; -		rc = ata_bus_probe(ap); -	} - -	return rc; +	if (rc) +		return rc; +	ap->print_id = atomic_inc_return(&ata_print_id); +	return 0;  }  EXPORT_SYMBOL_GPL(ata_sas_port_init); @@ -3859,7 +4190,6 @@ EXPORT_SYMBOL_GPL(ata_sas_slave_configure);  /**   *	ata_sas_queuecmd - Issue SCSI cdb to libata-managed device   *	@cmd: SCSI command to be sent - *	@done: Completion function, called when command is complete   *	@ap:	ATA port to which the command is being sent   *   *	RETURNS: @@ -3867,18 +4197,17 @@ EXPORT_SYMBOL_GPL(ata_sas_slave_configure);   *	0 otherwise.   */ -int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), -		     struct ata_port *ap) +int ata_sas_queuecmd(struct scsi_cmnd *cmd, struct ata_port *ap)  {  	int rc = 0;  	ata_scsi_dump_cdb(ap, cmd);  	if (likely(ata_dev_enabled(ap->link.device))) -		rc = __ata_scsi_queuecmd(cmd, done, ap->link.device); +		rc = __ata_scsi_queuecmd(cmd, ap->link.device);  	else {  		cmd->result = (DID_BAD_TARGET << 16); -		done(cmd); +		cmd->scsi_done(cmd);  	}  	return rc;  } diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index d05387d1e14..1121153f1ec 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1,7 +1,7 @@  /*   *  libata-sff.c - helper library for PCI IDE BMDMA   * - *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> + *  Maintained by:  Tejun Heo <tj@kernel.org>   *    		    Please ALWAYS copy linux-ide@vger.kernel.org   *		    on emails.   * @@ -35,6 +35,7 @@  #include <linux/kernel.h>  #include <linux/gfp.h>  #include <linux/pci.h> +#include <linux/module.h>  #include <linux/libata.h>  #include <linux/highmem.h> @@ -227,9 +228,9 @@ int ata_sff_busy_sleep(struct ata_port *ap,  	}  	if (status != 0xff && (status & ATA_BUSY)) -		ata_port_printk(ap, KERN_WARNING, -				"port is slow to respond, please be patient " -				"(Status 0x%x)\n", status); +		ata_port_warn(ap, +			      "port is slow to respond, please be patient (Status 0x%x)\n", +			      status);  	timeout = ata_deadline(timer_start, tmout);  	while (status != 0xff && (status & ATA_BUSY) && @@ -242,9 +243,9 @@ int ata_sff_busy_sleep(struct ata_port *ap,  		return -ENODEV;  	if (status & ATA_BUSY) { -		ata_port_printk(ap, KERN_ERR, "port failed to respond " -				"(%lu secs, Status 0x%x)\n", -				DIV_ROUND_UP(tmout, 1000), status); +		ata_port_err(ap, +			     "port failed to respond (%lu secs, Status 0x%x)\n", +			     DIV_ROUND_UP(tmout, 1000), status);  		return -EBUSY;  	} @@ -350,8 +351,8 @@ static void ata_dev_select(struct ata_port *ap, unsigned int device,  			   unsigned int wait, unsigned int can_sleep)  {  	if (ata_msg_probe(ap)) -		ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, " -				"device %u, wait %u\n", device, wait); +		ata_port_info(ap, "ata_dev_select: ENTER, device %u, wait %u\n", +			      device, wait);  	if (wait)  		ata_wait_idle(ap); @@ -569,7 +570,7 @@ unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf,  	/* Transfer trailing byte, if any. */  	if (unlikely(buflen & 0x01)) { -		unsigned char pad[2]; +		unsigned char pad[2] = { };  		/* Point buf to the tail of buffer */  		buf += buflen - 1; @@ -628,7 +629,7 @@ unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,  	/* Transfer trailing bytes, if any */  	if (unlikely(slop)) { -		unsigned char pad[4]; +		unsigned char pad[4] = { };  		/* Point buf to the tail of buffer */  		buf += buflen - slop; @@ -678,7 +679,7 @@ unsigned int ata_sff_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,  	unsigned int consumed;  	local_irq_save(flags); -	consumed = ata_sff_data_xfer(dev, buf, buflen, rw); +	consumed = ata_sff_data_xfer32(dev, buf, buflen, rw);  	local_irq_restore(flags);  	return consumed; @@ -719,13 +720,13 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)  		/* FIXME: use a bounce buffer */  		local_irq_save(flags); -		buf = kmap_atomic(page, KM_IRQ0); +		buf = kmap_atomic(page);  		/* do the actual data transfer */  		ap->ops->sff_data_xfer(qc->dev, buf + offset, qc->sect_size,  				       do_write); -		kunmap_atomic(buf, KM_IRQ0); +		kunmap_atomic(buf);  		local_irq_restore(flags);  	} else {  		buf = page_address(page); @@ -864,13 +865,13 @@ next_sg:  		/* FIXME: use bounce buffer */  		local_irq_save(flags); -		buf = kmap_atomic(page, KM_IRQ0); +		buf = kmap_atomic(page);  		/* do the actual data transfer */  		consumed = ap->ops->sff_data_xfer(dev,  buf + offset,  								count, rw); -		kunmap_atomic(buf, KM_IRQ0); +		kunmap_atomic(buf);  		local_irq_restore(flags);  	} else {  		buf = page_address(page); @@ -928,11 +929,11 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)  	bytes = (bc_hi << 8) | bc_lo;  	/* shall be cleared to zero, indicating xfer of data */ -	if (unlikely(ireason & (1 << 0))) +	if (unlikely(ireason & ATAPI_COD))  		goto atapi_check;  	/* make sure transfer direction matches expected */ -	i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0; +	i_write = ((ireason & ATAPI_IO) == 0) ? 1 : 0;  	if (unlikely(do_write != i_write))  		goto atapi_check; @@ -1302,6 +1303,18 @@ fsm_start:  }  EXPORT_SYMBOL_GPL(ata_sff_hsm_move); +void ata_sff_queue_work(struct work_struct *work) +{ +	queue_work(ata_sff_wq, work); +} +EXPORT_SYMBOL_GPL(ata_sff_queue_work); + +void ata_sff_queue_delayed_work(struct delayed_work *dwork, unsigned long delay) +{ +	queue_delayed_work(ata_sff_wq, dwork, delay); +} +EXPORT_SYMBOL_GPL(ata_sff_queue_delayed_work); +  void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay)  {  	struct ata_port *ap = link->ap; @@ -1311,8 +1324,7 @@ void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay)  	ap->sff_pio_task_link = link;  	/* may fail if ata_sff_flush_pio_task() in progress */ -	queue_delayed_work(ata_sff_wq, &ap->sff_pio_task, -			   msecs_to_jiffies(delay)); +	ata_sff_queue_delayed_work(&ap->sff_pio_task, msecs_to_jiffies(delay));  }  EXPORT_SYMBOL_GPL(ata_sff_queue_pio_task); @@ -1320,11 +1332,12 @@ void ata_sff_flush_pio_task(struct ata_port *ap)  {  	DPRINTK("ENTER\n"); -	cancel_rearming_delayed_work(&ap->sff_pio_task); +	cancel_delayed_work_sync(&ap->sff_pio_task);  	ap->hsm_task_state = HSM_ST_IDLE; +	ap->sff_pio_task_link = NULL;  	if (ata_msg_ctl(ap)) -		ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __func__); +		ata_port_dbg(ap, "%s: EXIT\n", __func__);  }  static void ata_sff_pio_task(struct work_struct *work) @@ -1336,7 +1349,7 @@ static void ata_sff_pio_task(struct work_struct *work)  	u8 status;  	int poll_next; -	BUG_ON(ap->sff_pio_task_link == NULL);  +	BUG_ON(ap->sff_pio_task_link == NULL);  	/* qc can be NULL if timeout occurred */  	qc = ata_qc_from_tag(ap, link->active_tag);  	if (!qc) { @@ -1502,7 +1515,7 @@ static unsigned int ata_sff_idle_irq(struct ata_port *ap)  		ap->ops->sff_check_status(ap);  		if (ap->ops->sff_irq_clear)  			ap->ops->sff_irq_clear(ap); -		ata_port_printk(ap, KERN_WARNING, "irq trap\n"); +		ata_port_warn(ap, "irq trap\n");  		return 1;  	}  #endif @@ -1532,11 +1545,10 @@ static unsigned int __ata_sff_port_intr(struct ata_port *ap,  		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))  			return ata_sff_idle_irq(ap);  		break; -	case HSM_ST: -	case HSM_ST_LAST: -		break; -	default: +	case HSM_ST_IDLE:  		return ata_sff_idle_irq(ap); +	default: +		break;  	}  	/* check main status, clearing INTRQ if needed */ @@ -1701,7 +1713,7 @@ void ata_sff_lost_interrupt(struct ata_port *ap)  	/* There was a command running, we are no longer busy and we have  	   no interrupt. */ -	ata_port_printk(ap, KERN_WARNING, "lost interrupt (Status 0x%x)\n", +	ata_port_warn(ap, "lost interrupt (Status 0x%x)\n",  								status);  	/* Run the host interrupt logic as if the interrupt had not been  	   lost */ @@ -1788,8 +1800,9 @@ int ata_sff_prereset(struct ata_link *link, unsigned long deadline)  	if (!ata_link_offline(link)) {  		rc = ata_sff_wait_ready(link, deadline);  		if (rc && rc != -ENODEV) { -			ata_link_printk(link, KERN_WARNING, "device not ready " -					"(errno=%d), forcing hardreset\n", rc); +			ata_link_warn(link, +				      "device not ready (errno=%d), forcing hardreset\n", +				      rc);  			ehc->i.action |= ATA_EH_HARDRESET;  		}  	} @@ -2046,7 +2059,7 @@ int ata_sff_softreset(struct ata_link *link, unsigned int *classes,  	rc = ata_bus_softreset(ap, devmask, deadline);  	/* if link is occupied, -ENODEV too is an error */  	if (rc && (rc != -ENODEV || sata_scr_valid(link))) { -		ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc); +		ata_link_err(link, "SRST failed (errno=%d)\n", rc);  		return rc;  	} @@ -2160,8 +2173,7 @@ void ata_sff_drain_fifo(struct ata_queued_cmd *qc)  	/* Can become DEBUG later */  	if (count) -		ata_port_printk(ap, KERN_DEBUG, -			"drained %d bytes to clear DRQ.\n", count); +		ata_port_dbg(ap, "drained %d bytes to clear DRQ\n", count);  }  EXPORT_SYMBOL_GPL(ata_sff_drain_fifo); @@ -2306,9 +2318,9 @@ int ata_pci_sff_init_host(struct ata_host *host)  		rc = pcim_iomap_regions(pdev, 0x3 << base,  					dev_driver_string(gdev));  		if (rc) { -			dev_printk(KERN_WARNING, gdev, -				   "failed to request/iomap BARs for port %d " -				   "(errno=%d)\n", i, rc); +			dev_warn(gdev, +				 "failed to request/iomap BARs for port %d (errno=%d)\n", +				 i, rc);  			if (rc == -EBUSY)  				pcim_pin_device(pdev);  			ap->ops = &ata_dummy_port_ops; @@ -2330,7 +2342,7 @@ int ata_pci_sff_init_host(struct ata_host *host)  	}  	if (!mask) { -		dev_printk(KERN_ERR, gdev, "no available native port\n"); +		dev_err(gdev, "no available native port\n");  		return -ENODEV;  	} @@ -2365,8 +2377,7 @@ int ata_pci_sff_prepare_host(struct pci_dev *pdev,  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);  	if (!host) { -		dev_printk(KERN_ERR, &pdev->dev, -			   "failed to allocate ATA host\n"); +		dev_err(&pdev->dev, "failed to allocate ATA host\n");  		rc = -ENOMEM;  		goto err_out;  	} @@ -2422,28 +2433,24 @@ int ata_pci_sff_activate_host(struct ata_host *host,  		mask = (1 << 2) | (1 << 0);  		if ((tmp8 & mask) != mask)  			legacy_mode = 1; -#if defined(CONFIG_NO_ATA_LEGACY) -		/* Some platforms with PCI limits cannot address compat -		   port space. In that case we punt if their firmware has -		   left a device in compatibility mode */ -		if (legacy_mode) { -			printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n"); -			return -EOPNOTSUPP; -		} -#endif  	}  	if (!devres_open_group(dev, NULL, GFP_KERNEL))  		return -ENOMEM;  	if (!legacy_mode && pdev->irq) { +		int i; +  		rc = devm_request_irq(dev, pdev->irq, irq_handler,  				      IRQF_SHARED, drv_name, host);  		if (rc)  			goto out; -		ata_port_desc(host->ports[0], "irq %d", pdev->irq); -		ata_port_desc(host->ports[1], "irq %d", pdev->irq); +		for (i = 0; i < 2; i++) { +			if (ata_port_is_dummy(host->ports[i])) +				continue; +			ata_port_desc(host->ports[i], "irq %d", pdev->irq); +		}  	} else if (legacy_mode) {  		if (!ata_port_is_dummy(host->ports[0])) {  			rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev), @@ -2492,31 +2499,10 @@ static const struct ata_port_info *ata_sff_find_valid_pi(  	return NULL;  } -/** - *	ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller - *	@pdev: Controller to be initialized - *	@ppi: array of port_info, must be enough for two ports - *	@sht: scsi_host_template to use when registering the host - *	@host_priv: host private_data - *	@hflag: host flags - * - *	This is a helper function which can be called from a driver's - *	xxx_init_one() probe function if the hardware uses traditional - *	IDE taskfile registers and is PIO only. - * - *	ASSUMPTION: - *	Nobody makes a single channel controller that appears solely as - *	the secondary legacy port on PCI. - * - *	LOCKING: - *	Inherited from PCI layer (may sleep). - * - *	RETURNS: - *	Zero on success, negative on errno-based value on error. - */ -int ata_pci_sff_init_one(struct pci_dev *pdev, -		 const struct ata_port_info * const *ppi, -		 struct scsi_host_template *sht, void *host_priv, int hflag) +static int ata_pci_init_one(struct pci_dev *pdev, +		const struct ata_port_info * const *ppi, +		struct scsi_host_template *sht, void *host_priv, +		int hflags, bool bmdma)  {  	struct device *dev = &pdev->dev;  	const struct ata_port_info *pi; @@ -2527,8 +2513,7 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,  	pi = ata_sff_find_valid_pi(ppi);  	if (!pi) { -		dev_printk(KERN_ERR, &pdev->dev, -			   "no valid port_info specified\n"); +		dev_err(&pdev->dev, "no valid port_info specified\n");  		return -EINVAL;  	} @@ -2539,14 +2524,26 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,  	if (rc)  		goto out; -	/* prepare and activate SFF host */ -	rc = ata_pci_sff_prepare_host(pdev, ppi, &host); +#ifdef CONFIG_ATA_BMDMA +	if (bmdma) +		/* prepare and activate BMDMA host */ +		rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); +	else +#endif +		/* prepare and activate SFF host */ +		rc = ata_pci_sff_prepare_host(pdev, ppi, &host);  	if (rc)  		goto out;  	host->private_data = host_priv; -	host->flags |= hflag; +	host->flags |= hflags; -	rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht); +#ifdef CONFIG_ATA_BMDMA +	if (bmdma) { +		pci_set_master(pdev); +		rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht); +	} else +#endif +		rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);  out:  	if (rc == 0)  		devres_remove_group(&pdev->dev, NULL); @@ -2555,6 +2552,35 @@ out:  	return rc;  } + +/** + *	ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller + *	@pdev: Controller to be initialized + *	@ppi: array of port_info, must be enough for two ports + *	@sht: scsi_host_template to use when registering the host + *	@host_priv: host private_data + *	@hflag: host flags + * + *	This is a helper function which can be called from a driver's + *	xxx_init_one() probe function if the hardware uses traditional + *	IDE taskfile registers and is PIO only. + * + *	ASSUMPTION: + *	Nobody makes a single channel controller that appears solely as + *	the secondary legacy port on PCI. + * + *	LOCKING: + *	Inherited from PCI layer (may sleep). + * + *	RETURNS: + *	Zero on success, negative on errno-based value on error. + */ +int ata_pci_sff_init_one(struct pci_dev *pdev, +		 const struct ata_port_info * const *ppi, +		 struct scsi_host_template *sht, void *host_priv, int hflag) +{ +	return ata_pci_init_one(pdev, ppi, sht, host_priv, hflag, 0); +}  EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);  #endif /* CONFIG_PCI */ @@ -2829,7 +2855,7 @@ unsigned int ata_bmdma_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc)  		bmdma_stopped = true;  		if (unlikely(host_stat & ATA_DMA_ERR)) { -			/* error when transfering data to/from memory */ +			/* error when transferring data to/from memory */  			qc->err_mask |= AC_ERR_HOST_BUS;  			ap->hsm_task_state = HSM_ST_ERR;  		} @@ -3022,7 +3048,7 @@ void ata_bmdma_start(struct ata_queued_cmd *qc)  	 * Or maybe I'm just being paranoid.  	 *  	 * FIXME: The posting of this write means I/O starts are -	 * unneccessarily delayed for MMIO +	 * unnecessarily delayed for MMIO  	 */  }  EXPORT_SYMBOL_GPL(ata_bmdma_start); @@ -3149,8 +3175,7 @@ static void ata_bmdma_nodma(struct ata_host *host, const char *reason)  {  	int i; -	dev_printk(KERN_ERR, host->dev, "BMDMA: %s, falling back to PIO\n", -		   reason); +	dev_err(host->dev, "BMDMA: %s, falling back to PIO\n", reason);  	for (i = 0; i < 2; i++) {  		host->ports[i]->mwdma_mask = 0; @@ -3273,43 +3298,7 @@ int ata_pci_bmdma_init_one(struct pci_dev *pdev,  			   struct scsi_host_template *sht, void *host_priv,  			   int hflags)  { -	struct device *dev = &pdev->dev; -	const struct ata_port_info *pi; -	struct ata_host *host = NULL; -	int rc; - -	DPRINTK("ENTER\n"); - -	pi = ata_sff_find_valid_pi(ppi); -	if (!pi) { -		dev_printk(KERN_ERR, &pdev->dev, -			   "no valid port_info specified\n"); -		return -EINVAL; -	} - -	if (!devres_open_group(dev, NULL, GFP_KERNEL)) -		return -ENOMEM; - -	rc = pcim_enable_device(pdev); -	if (rc) -		goto out; - -	/* prepare and activate BMDMA host */ -	rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); -	if (rc) -		goto out; -	host->private_data = host_priv; -	host->flags |= hflags; - -	pci_set_master(pdev); -	rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht); - out: -	if (rc == 0) -		devres_remove_group(&pdev->dev, NULL); -	else -		devres_release_group(&pdev->dev, NULL); - -	return rc; +	return ata_pci_init_one(pdev, ppi, sht, host_priv, hflags, 1);  }  EXPORT_SYMBOL_GPL(ata_pci_bmdma_init_one); diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index ce9dc6207f3..e3741322822 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -32,11 +32,12 @@  #include <linux/libata.h>  #include <linux/hdreg.h>  #include <linux/uaccess.h> +#include <linux/pm_runtime.h>  #include "libata.h"  #include "libata-transport.h" -#define ATA_PORT_ATTRS		2 +#define ATA_PORT_ATTRS		3  #define ATA_LINK_ATTRS		3  #define ATA_DEV_ATTRS		9 @@ -215,6 +216,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_ata_port_##name, NULL)  ata_port_simple_attr(nr_pmp_links, nr_pmp_links, "%d\n", int);  ata_port_simple_attr(stats.idle_irq, idle_irq, "%ld\n", unsigned long); +ata_port_simple_attr(local_port_no, port_no, "%u\n", unsigned int);  static DECLARE_TRANSPORT_CLASS(ata_port_class,  			       "ata_port", NULL, NULL, NULL); @@ -231,7 +233,7 @@ static void ata_tport_release(struct device *dev)   * Returns:   *	%1 if the device represents a ATA Port, %0 else   */ -int ata_is_port(const struct device *dev) +static int ata_is_port(const struct device *dev)  {  	return dev->release == ata_tport_release;  } @@ -279,16 +281,23 @@ int ata_tport_add(struct device *parent,  	struct device *dev = &ap->tdev;  	device_initialize(dev); +	dev->type = &ata_port_type;  	dev->parent = get_device(parent);  	dev->release = ata_tport_release;  	dev_set_name(dev, "ata%d", ap->print_id);  	transport_setup_device(dev); +	ata_acpi_bind_port(ap);  	error = device_add(dev);  	if (error) {  		goto tport_err;  	} +	device_enable_async_suspend(dev); +	pm_runtime_set_active(dev); +	pm_runtime_enable(dev); +	pm_runtime_forbid(dev); +  	transport_add_device(dev);  	transport_configure_device(dev); @@ -312,25 +321,25 @@ int ata_tport_add(struct device *parent,  /*   * ATA link attributes   */ +static int noop(int x) { return x; } - -#define ata_link_show_linkspeed(field)					\ +#define ata_link_show_linkspeed(field, format)			        \  static ssize_t								\  show_ata_link_##field(struct device *dev,				\  		      struct device_attribute *attr, char *buf)		\  {									\  	struct ata_link *link = transport_class_to_link(dev);		\  									\ -	return sprintf(buf,"%s\n", sata_spd_string(fls(link->field)));	\ +	return sprintf(buf, "%s\n", sata_spd_string(format(link->field))); \  } -#define ata_link_linkspeed_attr(field)					\ -	ata_link_show_linkspeed(field)					\ +#define ata_link_linkspeed_attr(field, format)				\ +	ata_link_show_linkspeed(field, format)				\  static DEVICE_ATTR(field, S_IRUGO, show_ata_link_##field, NULL) -ata_link_linkspeed_attr(hw_sata_spd_limit); -ata_link_linkspeed_attr(sata_spd_limit); -ata_link_linkspeed_attr(sata_spd); +ata_link_linkspeed_attr(hw_sata_spd_limit, fls); +ata_link_linkspeed_attr(sata_spd_limit, fls); +ata_link_linkspeed_attr(sata_spd, noop);  static DECLARE_TRANSPORT_CLASS(ata_link_class, @@ -348,7 +357,7 @@ static void ata_tlink_release(struct device *dev)   * Returns:   *	%1 if the device represents a ATA link, %0 else   */ -int ata_is_link(const struct device *dev) +static int ata_is_link(const struct device *dev)  {  	return dev->release == ata_tlink_release;  } @@ -565,7 +574,7 @@ static void ata_tdev_release(struct device *dev)   * Returns:   *	%1 if the device represents a ATA device, %0 else   */ -int ata_is_ata_dev(const struct device *dev) +static int ata_is_ata_dev(const struct device *dev)  {  	return dev->release == ata_tdev_release;  } @@ -636,6 +645,7 @@ static int ata_tdev_add(struct ata_device *ata_dev)  		dev_set_name(dev, "dev%d.%d.0", ap->print_id, link->pmp);  	transport_setup_device(dev); +	ata_acpi_bind_dev(ata_dev);  	error = device_add(dev);  	if (error) {  		ata_tdev_free(ata_dev); @@ -702,6 +712,7 @@ struct scsi_transport_template *ata_attach_transport(void)  	count = 0;  	SETUP_PORT_ATTRIBUTE(nr_pmp_links);  	SETUP_PORT_ATTRIBUTE(idle_irq); +	SETUP_PORT_ATTRIBUTE(port_no);  	BUG_ON(count > ATA_PORT_ATTRS);  	i->port_attrs[count] = NULL; diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c new file mode 100644 index 00000000000..f3a65a3140d --- /dev/null +++ b/drivers/ata/libata-zpodd.c @@ -0,0 +1,283 @@ +#include <linux/libata.h> +#include <linux/cdrom.h> +#include <linux/pm_runtime.h> +#include <linux/module.h> +#include <linux/pm_qos.h> +#include <scsi/scsi_device.h> + +#include "libata.h" + +static int zpodd_poweroff_delay = 30; /* 30 seconds for power off delay */ +module_param(zpodd_poweroff_delay, int, 0644); +MODULE_PARM_DESC(zpodd_poweroff_delay, "Poweroff delay for ZPODD in seconds"); + +enum odd_mech_type { +	ODD_MECH_TYPE_SLOT, +	ODD_MECH_TYPE_DRAWER, +	ODD_MECH_TYPE_UNSUPPORTED, +}; + +struct zpodd { +	enum odd_mech_type	mech_type; /* init during probe, RO afterwards */ +	struct ata_device	*dev; + +	/* The following fields are synchronized by PM core. */ +	bool			from_notify; /* resumed as a result of +					      * acpi wake notification */ +	bool			zp_ready; /* ZP ready state */ +	unsigned long		last_ready; /* last ZP ready timestamp */ +	bool			zp_sampled; /* ZP ready state sampled */ +	bool			powered_off; /* ODD is powered off +					      *	during suspend */ +}; + +static int eject_tray(struct ata_device *dev) +{ +	struct ata_taskfile tf; +	const char cdb[] = {  GPCMD_START_STOP_UNIT, +		0, 0, 0, +		0x02,     /* LoEj */ +		0, 0, 0, 0, 0, 0, 0, +	}; + +	ata_tf_init(dev, &tf); +	tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; +	tf.command = ATA_CMD_PACKET; +	tf.protocol = ATAPI_PROT_NODATA; + +	return ata_exec_internal(dev, &tf, cdb, DMA_NONE, NULL, 0, 0); +} + +/* Per the spec, only slot type and drawer type ODD can be supported */ +static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev) +{ +	char buf[16]; +	unsigned int ret; +	struct rm_feature_desc *desc = (void *)(buf + 8); +	struct ata_taskfile tf; +	char cdb[] = {  GPCMD_GET_CONFIGURATION, +			2,      /* only 1 feature descriptor requested */ +			0, 3,   /* 3, removable medium feature */ +			0, 0, 0,/* reserved */ +			0, sizeof(buf), +			0, 0, 0, +	}; + +	ata_tf_init(dev, &tf); +	tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; +	tf.command = ATA_CMD_PACKET; +	tf.protocol = ATAPI_PROT_PIO; +	tf.lbam = sizeof(buf); + +	ret = ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE, +				buf, sizeof(buf), 0); +	if (ret) +		return ODD_MECH_TYPE_UNSUPPORTED; + +	if (be16_to_cpu(desc->feature_code) != 3) +		return ODD_MECH_TYPE_UNSUPPORTED; + +	if (desc->mech_type == 0 && desc->load == 0 && desc->eject == 1) +		return ODD_MECH_TYPE_SLOT; +	else if (desc->mech_type == 1 && desc->load == 0 && desc->eject == 1) +		return ODD_MECH_TYPE_DRAWER; +	else +		return ODD_MECH_TYPE_UNSUPPORTED; +} + +/* Test if ODD is zero power ready by sense code */ +static bool zpready(struct ata_device *dev) +{ +	u8 sense_key, *sense_buf; +	unsigned int ret, asc, ascq, add_len; +	struct zpodd *zpodd = dev->zpodd; + +	ret = atapi_eh_tur(dev, &sense_key); + +	if (!ret || sense_key != NOT_READY) +		return false; + +	sense_buf = dev->link->ap->sector_buf; +	ret = atapi_eh_request_sense(dev, sense_buf, sense_key); +	if (ret) +		return false; + +	/* sense valid */ +	if ((sense_buf[0] & 0x7f) != 0x70) +		return false; + +	add_len = sense_buf[7]; +	/* has asc and ascq */ +	if (add_len < 6) +		return false; + +	asc = sense_buf[12]; +	ascq = sense_buf[13]; + +	if (zpodd->mech_type == ODD_MECH_TYPE_SLOT) +		/* no media inside */ +		return asc == 0x3a; +	else +		/* no media inside and door closed */ +		return asc == 0x3a && ascq == 0x01; +} + +/* + * Update the zpodd->zp_ready field. This field will only be set + * if the ODD has stayed in ZP ready state for zpodd_poweroff_delay + * time, and will be used to decide if power off is allowed. If it + * is set, it will be cleared during resume from powered off state. + */ +void zpodd_on_suspend(struct ata_device *dev) +{ +	struct zpodd *zpodd = dev->zpodd; +	unsigned long expires; + +	if (!zpready(dev)) { +		zpodd->zp_sampled = false; +		zpodd->zp_ready = false; +		return; +	} + +	if (!zpodd->zp_sampled) { +		zpodd->zp_sampled = true; +		zpodd->last_ready = jiffies; +		return; +	} + +	expires = zpodd->last_ready + +		  msecs_to_jiffies(zpodd_poweroff_delay * 1000); +	if (time_before(jiffies, expires)) +		return; + +	zpodd->zp_ready = true; +} + +bool zpodd_zpready(struct ata_device *dev) +{ +	struct zpodd *zpodd = dev->zpodd; +	return zpodd->zp_ready; +} + +/* + * Enable runtime wake capability through ACPI and set the powered_off flag, + * this flag will be used during resume to decide what operations are needed + * to take. + * + * Also, media poll needs to be silenced, so that it doesn't bring the ODD + * back to full power state every few seconds. + */ +void zpodd_enable_run_wake(struct ata_device *dev) +{ +	struct zpodd *zpodd = dev->zpodd; + +	sdev_disable_disk_events(dev->sdev); + +	zpodd->powered_off = true; +	device_set_run_wake(&dev->tdev, true); +	acpi_pm_device_run_wake(&dev->tdev, true); +} + +/* Disable runtime wake capability if it is enabled */ +void zpodd_disable_run_wake(struct ata_device *dev) +{ +	struct zpodd *zpodd = dev->zpodd; + +	if (zpodd->powered_off) { +		acpi_pm_device_run_wake(&dev->tdev, false); +		device_set_run_wake(&dev->tdev, false); +	} +} + +/* + * Post power on processing after the ODD has been recovered. If the + * ODD wasn't powered off during suspend, it doesn't do anything. + * + * For drawer type ODD, if it is powered on due to user pressed the + * eject button, the tray needs to be ejected. This can only be done + * after the ODD has been recovered, i.e. link is initialized and + * device is able to process NON_DATA PIO command, as eject needs to + * send command for the ODD to process. + * + * The from_notify flag set in wake notification handler function + * zpodd_wake_dev represents if power on is due to user's action. + * + * For both types of ODD, several fields need to be reset. + */ +void zpodd_post_poweron(struct ata_device *dev) +{ +	struct zpodd *zpodd = dev->zpodd; + +	if (!zpodd->powered_off) +		return; + +	zpodd->powered_off = false; + +	if (zpodd->from_notify) { +		zpodd->from_notify = false; +		if (zpodd->mech_type == ODD_MECH_TYPE_DRAWER) +			eject_tray(dev); +	} + +	zpodd->zp_sampled = false; +	zpodd->zp_ready = false; + +	sdev_enable_disk_events(dev->sdev); +} + +static void zpodd_wake_dev(acpi_handle handle, u32 event, void *context) +{ +	struct ata_device *ata_dev = context; +	struct zpodd *zpodd = ata_dev->zpodd; +	struct device *dev = &ata_dev->sdev->sdev_gendev; + +	if (event == ACPI_NOTIFY_DEVICE_WAKE && pm_runtime_suspended(dev)) { +		zpodd->from_notify = true; +		pm_runtime_resume(dev); +	} +} + +static void ata_acpi_add_pm_notifier(struct ata_device *dev) +{ +	acpi_handle handle = ata_dev_acpi_handle(dev); +	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, +				    zpodd_wake_dev, dev); +} + +static void ata_acpi_remove_pm_notifier(struct ata_device *dev) +{ +	acpi_handle handle = ata_dev_acpi_handle(dev); +	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, zpodd_wake_dev); +} + +void zpodd_init(struct ata_device *dev) +{ +	struct acpi_device *adev = ACPI_COMPANION(&dev->tdev); +	enum odd_mech_type mech_type; +	struct zpodd *zpodd; + +	if (dev->zpodd || !adev || !acpi_device_can_poweroff(adev)) +		return; + +	mech_type = zpodd_get_mech_type(dev); +	if (mech_type == ODD_MECH_TYPE_UNSUPPORTED) +		return; + +	zpodd = kzalloc(sizeof(struct zpodd), GFP_KERNEL); +	if (!zpodd) +		return; + +	zpodd->mech_type = mech_type; + +	ata_acpi_add_pm_notifier(dev); +	zpodd->dev = dev; +	dev->zpodd = zpodd; +	dev_pm_qos_expose_flags(&dev->tdev, 0); +} + +void zpodd_exit(struct ata_device *dev) +{ +	ata_acpi_remove_pm_notifier(dev); +	kfree(dev->zpodd); +	dev->zpodd = NULL; +} diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index a9be110dbf5..45b5ab3a95d 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -53,11 +53,12 @@ enum {  	ATA_DNXFER_QUIET	= (1 << 31),  }; -extern unsigned int ata_print_id; +extern atomic_t ata_print_id;  extern int atapi_passthru16;  extern int libata_fua;  extern int libata_noacpi;  extern int libata_allow_tpm; +extern struct device_type ata_port_type;  extern struct ata_link *ata_dev_phys_link(struct ata_device *dev);  extern void ata_force_cbl(struct ata_port *ap);  extern u64 ata_tf_to_lba(const struct ata_taskfile *tf); @@ -103,22 +104,24 @@ extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);  extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);  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); + +#define to_ata_port(d) container_of(d, struct ata_port, tdev)  /* libata-acpi.c */  #ifdef CONFIG_ATA_ACPI  extern unsigned int ata_acpi_gtf_filter; - -extern void ata_acpi_associate_sata_port(struct ata_port *ap); -extern void ata_acpi_associate(struct ata_host *host);  extern void ata_acpi_dissociate(struct ata_host *host);  extern int ata_acpi_on_suspend(struct ata_port *ap);  extern void ata_acpi_on_resume(struct ata_port *ap);  extern int ata_acpi_on_devcfg(struct ata_device *dev);  extern void ata_acpi_on_disable(struct ata_device *dev);  extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state); +extern void ata_acpi_bind_port(struct ata_port *ap); +extern void ata_acpi_bind_dev(struct ata_device *dev); +extern acpi_handle ata_dev_acpi_handle(struct ata_device *dev);  #else -static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { } -static inline void ata_acpi_associate(struct ata_host *host) { }  static inline void ata_acpi_dissociate(struct ata_host *host) { }  static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }  static inline void ata_acpi_on_resume(struct ata_port *ap) { } @@ -126,6 +129,8 @@ static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; }  static inline void ata_acpi_on_disable(struct ata_device *dev) { }  static inline void ata_acpi_set_state(struct ata_port *ap,  				      pm_message_t state) { } +static inline void ata_acpi_bind_port(struct ata_port *ap) {} +static inline void ata_acpi_bind_dev(struct ata_device *dev) {}  #endif  /* libata-scsi.c */ @@ -149,7 +154,6 @@ extern void ata_eh_acquire(struct ata_port *ap);  extern void ata_eh_release(struct ata_port *ap);  extern enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);  extern void ata_scsi_error(struct Scsi_Host *host); -extern void ata_port_wait_eh(struct ata_port *ap);  extern void ata_eh_fastdrain_timerfn(unsigned long arg);  extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);  extern void ata_dev_disable(struct ata_device *dev); @@ -158,6 +162,8 @@ 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); @@ -173,6 +179,9 @@ extern void ata_eh_finish(struct ata_port *ap);  extern int ata_ering_map(struct ata_ering *ering,  			 int (*map_fn)(struct ata_ering_entry *, void *),  		  	 void *arg); +extern unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key); +extern unsigned int atapi_eh_request_sense(struct ata_device *dev, +					   u8 *sense_buf, u8 dfl_sense_key);  /* libata-pmp.c */  #ifdef CONFIG_SATA_PMP @@ -221,4 +230,28 @@ static inline void ata_sff_exit(void)  { }  #endif /* CONFIG_ATA_SFF */ +/* libata-zpodd.c */ +#ifdef CONFIG_SATA_ZPODD +void zpodd_init(struct ata_device *dev); +void zpodd_exit(struct ata_device *dev); +static inline bool zpodd_dev_enabled(struct ata_device *dev) +{ +	return dev->zpodd != NULL; +} +void zpodd_on_suspend(struct ata_device *dev); +bool zpodd_zpready(struct ata_device *dev); +void zpodd_enable_run_wake(struct ata_device *dev); +void zpodd_disable_run_wake(struct ata_device *dev); +void zpodd_post_poweron(struct ata_device *dev); +#else /* CONFIG_SATA_ZPODD */ +static inline void zpodd_init(struct ata_device *dev) {} +static inline void zpodd_exit(struct ata_device *dev) {} +static inline bool zpodd_dev_enabled(struct ata_device *dev) { return false; } +static inline void zpodd_on_suspend(struct ata_device *dev) {} +static inline bool zpodd_zpready(struct ata_device *dev) { return false; } +static inline void zpodd_enable_run_wake(struct ata_device *dev) {} +static inline void zpodd_disable_run_wake(struct ata_device *dev) {} +static inline void zpodd_post_poweron(struct ata_device *dev) {} +#endif /* CONFIG_SATA_ZPODD */ +  #endif /* __LIBATA_H__ */ diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index c8d47034d5e..b70fce2a38e 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -7,16 +7,14 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h>  #include <linux/gfp.h> -#include <scsi/scsi_host.h> -#include <acpi/acpi_bus.h> - +#include <linux/acpi.h>  #include <linux/libata.h>  #include <linux/ata.h> +#include <scsi/scsi_host.h>  #define DRV_NAME	"pata_acpi"  #define DRV_VERSION	"0.2.3" @@ -39,7 +37,7 @@ static int pacpi_pre_reset(struct ata_link *link, unsigned long deadline)  {  	struct ata_port *ap = link->ap;  	struct pata_acpi *acpi = ap->private_data; -	if (ap->acpi_handle == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0) +	if (ACPI_HANDLE(&ap->tdev) == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0)  		return -ENODEV;  	return ata_sff_prereset(link, deadline); @@ -195,9 +193,7 @@ static int pacpi_port_start(struct ata_port *ap)  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	struct pata_acpi *acpi; -	int ret; - -	if (ap->acpi_handle == NULL) +	if (ACPI_HANDLE(&ap->tdev) == NULL)  		return -ENODEV;  	acpi = ap->private_data = devm_kzalloc(&pdev->dev, sizeof(struct pata_acpi), GFP_KERNEL); @@ -205,11 +201,7 @@ static int pacpi_port_start(struct ata_port *ap)  		return -ENOMEM;  	acpi->mask[0] = pacpi_discover_modes(ap, &ap->link.device[0]);  	acpi->mask[1] = pacpi_discover_modes(ap, &ap->link.device[1]); -	ret = ata_bmdma_port_start(ap); -	if (ret < 0) -		return ret; - -	return ret; +	return ata_bmdma_port_start(ap);  }  static struct scsi_host_template pacpi_sht = { @@ -245,7 +237,7 @@ static struct ata_port_operations pacpi_ops = {  static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)  {  	static const struct ata_port_info info = { -		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, +		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4,  		.mwdma_mask	= ATA_MWDMA2, @@ -273,28 +265,16 @@ static struct pci_driver pacpi_pci_driver = {  	.id_table		= pacpi_pci_tbl,  	.probe			= pacpi_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ata_pci_device_resume,  #endif  }; -static int __init pacpi_init(void) -{ -	return pci_register_driver(&pacpi_pci_driver); -} - -static void __exit pacpi_exit(void) -{ -	pci_unregister_driver(&pacpi_pci_driver); -} - -module_init(pacpi_init); -module_exit(pacpi_exit); +module_pci_driver(pacpi_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("SCSI low-level driver for ATA in ACPI mode");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, pacpi_pci_tbl);  MODULE_VERSION(DRV_VERSION); - diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 794ec6e3275..d19cd88ed2d 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -56,7 +56,7 @@ static const struct dmi_system_id cable_dmi_table[] = {  		},  	},  	{ -		.ident = "Toshiba Satelite S1800-814", +		.ident = "Toshiba Satellite S1800-814",  		.matches = {  			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),  			DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"), @@ -287,10 +287,10 @@ static void ali_warn_atapi_dma(struct ata_device *adev)  	int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;  	if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) { -		ata_dev_printk(adev, KERN_WARNING, -			       "WARNING: ATAPI DMA disabled for reliability issues.  It can be enabled\n"); -		ata_dev_printk(adev, KERN_WARNING, -			       "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n"); +		ata_dev_warn(adev, +			     "WARNING: ATAPI DMA disabled for reliability issues.  It can be enabled\n"); +		ata_dev_warn(adev, +			     "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");  	}  } @@ -589,10 +589,10 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  		return ata_pci_bmdma_init_one(pdev, ppi, &ali_sht, NULL, 0);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int ali_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -616,7 +616,7 @@ static struct pci_driver ali_pci_driver = {  	.id_table	= ali,  	.probe 		= ali_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ali_reinit_one,  #endif diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 620a07cabe3..8d4d959a821 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -11,13 +11,12 @@   *	Power management on ports   *   * - *  Documentation publically available. + *  Documentation publicly available.   */  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -60,7 +59,7 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse  		UT = T / 2;  	if (ata_timing_compute(adev, speed, &at, T, UT) < 0) { -		dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", speed); +		dev_err(&pdev->dev, "unknown mode %d\n", speed);  		return;  	} @@ -311,7 +310,7 @@ static unsigned long nv_mode_filter(struct ata_device *dev,  	   cable detection result */  	limit |= ata_pack_xfermask(ATA_PIO4, ATA_MWDMA2, ATA_UDMA2); -	ata_port_printk(ap, KERN_DEBUG, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, " +	ata_port_dbg(ap, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, "  			"BIOS=0x%lx (0x%x) ACPI=0x%lx%s\n",  			xfer_mask, limit, xfer_mask & limit, bios_limit,  			saved_udma, acpi_limit, acpi_str); @@ -530,14 +529,12 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  		}  	};  	const struct ata_port_info *ppi[] = { NULL, NULL }; -	static int printed_version;  	int type = id->driver_data;  	void *hpriv = NULL;  	u8 fifo;  	int rc; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -577,10 +574,10 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  	return ata_pci_bmdma_init_one(pdev, ppi, &amd_sht, hpriv, 0);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int amd_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -628,27 +625,16 @@ static struct pci_driver amd_pci_driver = {  	.id_table	= amd,  	.probe 		= amd_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= amd_reinit_one,  #endif  }; -static int __init amd_init(void) -{ -	return pci_register_driver(&amd_pci_driver); -} - -static void __exit amd_exit(void) -{ -	pci_unregister_driver(&amd_pci_driver); -} +module_pci_driver(amd_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for AMD and Nvidia PATA IDE");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, amd);  MODULE_VERSION(DRV_VERSION); - -module_init(amd_init); -module_exit(amd_exit); diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c new file mode 100644 index 00000000000..4edb1a81f63 --- /dev/null +++ b/drivers/ata/pata_arasan_cf.c @@ -0,0 +1,976 @@ +/* + * drivers/ata/pata_arasan_cf.c + * + * Arasan Compact Flash host controller source file + * + * Copyright (C) 2011 ST Microelectronics + * Viresh Kumar <viresh.linux@gmail.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +/* + * The Arasan CompactFlash Device Controller IP core has three basic modes of + * operation: PC card ATA using I/O mode, PC card ATA using memory mode, PC card + * ATA using true IDE modes. This driver supports only True IDE mode currently. + * + * Arasan CF Controller shares global irq register with Arasan XD Controller. + * + * Tested on arch/arm/mach-spear13xx + */ + +#include <linux/ata.h> +#include <linux/clk.h> +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/dmaengine.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/libata.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/pata_arasan_cf_data.h> +#include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/types.h> +#include <linux/workqueue.h> + +#define DRIVER_NAME	"arasan_cf" +#define TIMEOUT		msecs_to_jiffies(3000) + +/* Registers */ +/* CompactFlash Interface Status */ +#define CFI_STS			0x000 +	#define STS_CHG				(1) +	#define BIN_AUDIO_OUT			(1 << 1) +	#define CARD_DETECT1			(1 << 2) +	#define CARD_DETECT2			(1 << 3) +	#define INP_ACK				(1 << 4) +	#define CARD_READY			(1 << 5) +	#define IO_READY			(1 << 6) +	#define B16_IO_PORT_SEL			(1 << 7) +/* IRQ */ +#define IRQ_STS			0x004 +/* Interrupt Enable */ +#define IRQ_EN			0x008 +	#define CARD_DETECT_IRQ			(1) +	#define STATUS_CHNG_IRQ			(1 << 1) +	#define MEM_MODE_IRQ			(1 << 2) +	#define IO_MODE_IRQ			(1 << 3) +	#define TRUE_IDE_MODE_IRQ		(1 << 8) +	#define PIO_XFER_ERR_IRQ		(1 << 9) +	#define BUF_AVAIL_IRQ			(1 << 10) +	#define XFER_DONE_IRQ			(1 << 11) +	#define IGNORED_IRQS	(STATUS_CHNG_IRQ | MEM_MODE_IRQ | IO_MODE_IRQ |\ +					TRUE_IDE_MODE_IRQ) +	#define TRUE_IDE_IRQS	(CARD_DETECT_IRQ | PIO_XFER_ERR_IRQ |\ +					BUF_AVAIL_IRQ | XFER_DONE_IRQ) +/* Operation Mode */ +#define OP_MODE			0x00C +	#define CARD_MODE_MASK			(0x3) +	#define MEM_MODE			(0x0) +	#define IO_MODE				(0x1) +	#define TRUE_IDE_MODE			(0x2) + +	#define CARD_TYPE_MASK			(1 << 2) +	#define CF_CARD				(0) +	#define CF_PLUS_CARD			(1 << 2) + +	#define CARD_RESET			(1 << 3) +	#define CFHOST_ENB			(1 << 4) +	#define OUTPUTS_TRISTATE		(1 << 5) +	#define ULTRA_DMA_ENB			(1 << 8) +	#define MULTI_WORD_DMA_ENB		(1 << 9) +	#define DRQ_BLOCK_SIZE_MASK		(0x3 << 11) +	#define DRQ_BLOCK_SIZE_512		(0) +	#define DRQ_BLOCK_SIZE_1024		(1 << 11) +	#define DRQ_BLOCK_SIZE_2048		(2 << 11) +	#define DRQ_BLOCK_SIZE_4096		(3 << 11) +/* CF Interface Clock Configuration */ +#define CLK_CFG			0x010 +	#define CF_IF_CLK_MASK			(0XF) +/* CF Timing Mode Configuration */ +#define TM_CFG			0x014 +	#define MEM_MODE_TIMING_MASK		(0x3) +	#define MEM_MODE_TIMING_250NS		(0x0) +	#define MEM_MODE_TIMING_120NS		(0x1) +	#define MEM_MODE_TIMING_100NS		(0x2) +	#define MEM_MODE_TIMING_80NS		(0x3) + +	#define IO_MODE_TIMING_MASK		(0x3 << 2) +	#define IO_MODE_TIMING_250NS		(0x0 << 2) +	#define IO_MODE_TIMING_120NS		(0x1 << 2) +	#define IO_MODE_TIMING_100NS		(0x2 << 2) +	#define IO_MODE_TIMING_80NS		(0x3 << 2) + +	#define TRUEIDE_PIO_TIMING_MASK		(0x7 << 4) +	#define TRUEIDE_PIO_TIMING_SHIFT	4 + +	#define TRUEIDE_MWORD_DMA_TIMING_MASK	(0x7 << 7) +	#define TRUEIDE_MWORD_DMA_TIMING_SHIFT	7 + +	#define ULTRA_DMA_TIMING_MASK		(0x7 << 10) +	#define ULTRA_DMA_TIMING_SHIFT		10 +/* CF Transfer Address */ +#define XFER_ADDR		0x014 +	#define XFER_ADDR_MASK			(0x7FF) +	#define MAX_XFER_COUNT			0x20000u +/* Transfer Control */ +#define XFER_CTR		0x01C +	#define XFER_COUNT_MASK			(0x3FFFF) +	#define ADDR_INC_DISABLE		(1 << 24) +	#define XFER_WIDTH_MASK			(1 << 25) +	#define XFER_WIDTH_8B			(0) +	#define XFER_WIDTH_16B			(1 << 25) + +	#define MEM_TYPE_MASK			(1 << 26) +	#define MEM_TYPE_COMMON			(0) +	#define MEM_TYPE_ATTRIBUTE		(1 << 26) + +	#define MEM_IO_XFER_MASK		(1 << 27) +	#define MEM_XFER			(0) +	#define IO_XFER				(1 << 27) + +	#define DMA_XFER_MODE			(1 << 28) + +	#define AHB_BUS_NORMAL_PIO_OPRTN	(~(1 << 29)) +	#define XFER_DIR_MASK			(1 << 30) +	#define XFER_READ			(0) +	#define XFER_WRITE			(1 << 30) + +	#define XFER_START			(1 << 31) +/* Write Data Port */ +#define WRITE_PORT		0x024 +/* Read Data Port */ +#define READ_PORT		0x028 +/* ATA Data Port */ +#define ATA_DATA_PORT		0x030 +	#define ATA_DATA_PORT_MASK		(0xFFFF) +/* ATA Error/Features */ +#define ATA_ERR_FTR		0x034 +/* ATA Sector Count */ +#define ATA_SC			0x038 +/* ATA Sector Number */ +#define ATA_SN			0x03C +/* ATA Cylinder Low */ +#define ATA_CL			0x040 +/* ATA Cylinder High */ +#define ATA_CH			0x044 +/* ATA Select Card/Head */ +#define ATA_SH			0x048 +/* ATA Status-Command */ +#define ATA_STS_CMD		0x04C +/* ATA Alternate Status/Device Control */ +#define ATA_ASTS_DCTR		0x050 +/* Extended Write Data Port 0x200-0x3FC */ +#define EXT_WRITE_PORT		0x200 +/* Extended Read Data Port 0x400-0x5FC */ +#define EXT_READ_PORT		0x400 +	#define FIFO_SIZE	0x200u +/* Global Interrupt Status */ +#define GIRQ_STS		0x800 +/* Global Interrupt Status enable */ +#define GIRQ_STS_EN		0x804 +/* Global Interrupt Signal enable */ +#define GIRQ_SGN_EN		0x808 +	#define GIRQ_CF		(1) +	#define GIRQ_XD		(1 << 1) + +/* Compact Flash Controller Dev Structure */ +struct arasan_cf_dev { +	/* pointer to ata_host structure */ +	struct ata_host *host; +	/* clk structure */ +	struct clk *clk; + +	/* physical base address of controller */ +	dma_addr_t pbase; +	/* virtual base address of controller */ +	void __iomem *vbase; +	/* irq number*/ +	int irq; + +	/* status to be updated to framework regarding DMA transfer */ +	u8 dma_status; +	/* Card is present or Not */ +	u8 card_present; + +	/* dma specific */ +	/* Completion for transfer complete interrupt from controller */ +	struct completion cf_completion; +	/* Completion for DMA transfer complete. */ +	struct completion dma_completion; +	/* Dma channel allocated */ +	struct dma_chan *dma_chan; +	/* Mask for DMA transfers */ +	dma_cap_mask_t mask; +	/* DMA transfer work */ +	struct work_struct work; +	/* DMA delayed finish work */ +	struct delayed_work dwork; +	/* qc to be transferred using DMA */ +	struct ata_queued_cmd *qc; +}; + +static struct scsi_host_template arasan_cf_sht = { +	ATA_BASE_SHT(DRIVER_NAME), +	.sg_tablesize = SG_NONE, +	.dma_boundary = 0xFFFFFFFFUL, +}; + +static void cf_dumpregs(struct arasan_cf_dev *acdev) +{ +	struct device *dev = acdev->host->dev; + +	dev_dbg(dev, ": =========== REGISTER DUMP ==========="); +	dev_dbg(dev, ": CFI_STS: %x", readl(acdev->vbase + CFI_STS)); +	dev_dbg(dev, ": IRQ_STS: %x", readl(acdev->vbase + IRQ_STS)); +	dev_dbg(dev, ": IRQ_EN: %x", readl(acdev->vbase + IRQ_EN)); +	dev_dbg(dev, ": OP_MODE: %x", readl(acdev->vbase + OP_MODE)); +	dev_dbg(dev, ": CLK_CFG: %x", readl(acdev->vbase + CLK_CFG)); +	dev_dbg(dev, ": TM_CFG: %x", readl(acdev->vbase + TM_CFG)); +	dev_dbg(dev, ": XFER_CTR: %x", readl(acdev->vbase + XFER_CTR)); +	dev_dbg(dev, ": GIRQ_STS: %x", readl(acdev->vbase + GIRQ_STS)); +	dev_dbg(dev, ": GIRQ_STS_EN: %x", readl(acdev->vbase + GIRQ_STS_EN)); +	dev_dbg(dev, ": GIRQ_SGN_EN: %x", readl(acdev->vbase + GIRQ_SGN_EN)); +	dev_dbg(dev, ": ====================================="); +} + +/* Enable/Disable global interrupts shared between CF and XD ctrlr. */ +static void cf_ginterrupt_enable(struct arasan_cf_dev *acdev, bool enable) +{ +	/* enable should be 0 or 1 */ +	writel(enable, acdev->vbase + GIRQ_STS_EN); +	writel(enable, acdev->vbase + GIRQ_SGN_EN); +} + +/* Enable/Disable CF interrupts */ +static inline void +cf_interrupt_enable(struct arasan_cf_dev *acdev, u32 mask, bool enable) +{ +	u32 val = readl(acdev->vbase + IRQ_EN); +	/* clear & enable/disable irqs */ +	if (enable) { +		writel(mask, acdev->vbase + IRQ_STS); +		writel(val | mask, acdev->vbase + IRQ_EN); +	} else +		writel(val & ~mask, acdev->vbase + IRQ_EN); +} + +static inline void cf_card_reset(struct arasan_cf_dev *acdev) +{ +	u32 val = readl(acdev->vbase + OP_MODE); + +	writel(val | CARD_RESET, acdev->vbase + OP_MODE); +	udelay(200); +	writel(val & ~CARD_RESET, acdev->vbase + OP_MODE); +} + +static inline void cf_ctrl_reset(struct arasan_cf_dev *acdev) +{ +	writel(readl(acdev->vbase + OP_MODE) & ~CFHOST_ENB, +			acdev->vbase + OP_MODE); +	writel(readl(acdev->vbase + OP_MODE) | CFHOST_ENB, +			acdev->vbase + OP_MODE); +} + +static void cf_card_detect(struct arasan_cf_dev *acdev, bool hotplugged) +{ +	struct ata_port *ap = acdev->host->ports[0]; +	struct ata_eh_info *ehi = &ap->link.eh_info; +	u32 val = readl(acdev->vbase + CFI_STS); + +	/* Both CD1 & CD2 should be low if card inserted completely */ +	if (!(val & (CARD_DETECT1 | CARD_DETECT2))) { +		if (acdev->card_present) +			return; +		acdev->card_present = 1; +		cf_card_reset(acdev); +	} else { +		if (!acdev->card_present) +			return; +		acdev->card_present = 0; +	} + +	if (hotplugged) { +		ata_ehi_hotplugged(ehi); +		ata_port_freeze(ap); +	} +} + +static int cf_init(struct arasan_cf_dev *acdev) +{ +	struct arasan_cf_pdata *pdata = dev_get_platdata(acdev->host->dev); +	unsigned int if_clk; +	unsigned long flags; +	int ret = 0; + +	ret = clk_prepare_enable(acdev->clk); +	if (ret) { +		dev_dbg(acdev->host->dev, "clock enable failed"); +		return ret; +	} + +	ret = clk_set_rate(acdev->clk, 166000000); +	if (ret) { +		dev_warn(acdev->host->dev, "clock set rate failed"); +		clk_disable_unprepare(acdev->clk); +		return ret; +	} + +	spin_lock_irqsave(&acdev->host->lock, flags); +	/* configure CF interface clock */ +	/* TODO: read from device tree */ +	if_clk = CF_IF_CLK_166M; +	if (pdata && pdata->cf_if_clk <= CF_IF_CLK_200M) +		if_clk = pdata->cf_if_clk; + +	writel(if_clk, acdev->vbase + CLK_CFG); + +	writel(TRUE_IDE_MODE | CFHOST_ENB, acdev->vbase + OP_MODE); +	cf_interrupt_enable(acdev, CARD_DETECT_IRQ, 1); +	cf_ginterrupt_enable(acdev, 1); +	spin_unlock_irqrestore(&acdev->host->lock, flags); + +	return ret; +} + +static void cf_exit(struct arasan_cf_dev *acdev) +{ +	unsigned long flags; + +	spin_lock_irqsave(&acdev->host->lock, flags); +	cf_ginterrupt_enable(acdev, 0); +	cf_interrupt_enable(acdev, TRUE_IDE_IRQS, 0); +	cf_card_reset(acdev); +	writel(readl(acdev->vbase + OP_MODE) & ~CFHOST_ENB, +			acdev->vbase + OP_MODE); +	spin_unlock_irqrestore(&acdev->host->lock, flags); +	clk_disable_unprepare(acdev->clk); +} + +static void dma_callback(void *dev) +{ +	struct arasan_cf_dev *acdev = dev; + +	complete(&acdev->dma_completion); +} + +static inline void dma_complete(struct arasan_cf_dev *acdev) +{ +	struct ata_queued_cmd *qc = acdev->qc; +	unsigned long flags; + +	acdev->qc = NULL; +	ata_sff_interrupt(acdev->irq, acdev->host); + +	spin_lock_irqsave(&acdev->host->lock, flags); +	if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol)) +		ata_ehi_push_desc(&qc->ap->link.eh_info, "DMA Failed: Timeout"); +	spin_unlock_irqrestore(&acdev->host->lock, flags); +} + +static inline int wait4buf(struct arasan_cf_dev *acdev) +{ +	if (!wait_for_completion_timeout(&acdev->cf_completion, TIMEOUT)) { +		u32 rw = acdev->qc->tf.flags & ATA_TFLAG_WRITE; + +		dev_err(acdev->host->dev, "%s TimeOut", rw ? "write" : "read"); +		return -ETIMEDOUT; +	} + +	/* Check if PIO Error interrupt has occurred */ +	if (acdev->dma_status & ATA_DMA_ERR) +		return -EAGAIN; + +	return 0; +} + +static int +dma_xfer(struct arasan_cf_dev *acdev, dma_addr_t src, dma_addr_t dest, u32 len) +{ +	struct dma_async_tx_descriptor *tx; +	struct dma_chan *chan = acdev->dma_chan; +	dma_cookie_t cookie; +	unsigned long flags = DMA_PREP_INTERRUPT; +	int ret = 0; + +	tx = chan->device->device_prep_dma_memcpy(chan, dest, src, len, flags); +	if (!tx) { +		dev_err(acdev->host->dev, "device_prep_dma_memcpy failed\n"); +		return -EAGAIN; +	} + +	tx->callback = dma_callback; +	tx->callback_param = acdev; +	cookie = tx->tx_submit(tx); + +	ret = dma_submit_error(cookie); +	if (ret) { +		dev_err(acdev->host->dev, "dma_submit_error\n"); +		return ret; +	} + +	chan->device->device_issue_pending(chan); + +	/* Wait for DMA to complete */ +	if (!wait_for_completion_timeout(&acdev->dma_completion, TIMEOUT)) { +		chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); +		dev_err(acdev->host->dev, "wait_for_completion_timeout\n"); +		return -ETIMEDOUT; +	} + +	return ret; +} + +static int sg_xfer(struct arasan_cf_dev *acdev, struct scatterlist *sg) +{ +	dma_addr_t dest = 0, src = 0; +	u32 xfer_cnt, sglen, dma_len, xfer_ctr; +	u32 write = acdev->qc->tf.flags & ATA_TFLAG_WRITE; +	unsigned long flags; +	int ret = 0; + +	sglen = sg_dma_len(sg); +	if (write) { +		src = sg_dma_address(sg); +		dest = acdev->pbase + EXT_WRITE_PORT; +	} else { +		dest = sg_dma_address(sg); +		src = acdev->pbase + EXT_READ_PORT; +	} + +	/* +	 * For each sg: +	 * MAX_XFER_COUNT data will be transferred before we get transfer +	 * complete interrupt. Between after FIFO_SIZE data +	 * buffer available interrupt will be generated. At this time we will +	 * fill FIFO again: max FIFO_SIZE data. +	 */ +	while (sglen) { +		xfer_cnt = min(sglen, MAX_XFER_COUNT); +		spin_lock_irqsave(&acdev->host->lock, flags); +		xfer_ctr = readl(acdev->vbase + XFER_CTR) & +			~XFER_COUNT_MASK; +		writel(xfer_ctr | xfer_cnt | XFER_START, +				acdev->vbase + XFER_CTR); +		spin_unlock_irqrestore(&acdev->host->lock, flags); + +		/* continue dma xfers until current sg is completed */ +		while (xfer_cnt) { +			/* wait for read to complete */ +			if (!write) { +				ret = wait4buf(acdev); +				if (ret) +					goto fail; +			} + +			/* read/write FIFO in chunk of FIFO_SIZE */ +			dma_len = min(xfer_cnt, FIFO_SIZE); +			ret = dma_xfer(acdev, src, dest, dma_len); +			if (ret) { +				dev_err(acdev->host->dev, "dma failed"); +				goto fail; +			} + +			if (write) +				src += dma_len; +			else +				dest += dma_len; + +			sglen -= dma_len; +			xfer_cnt -= dma_len; + +			/* wait for write to complete */ +			if (write) { +				ret = wait4buf(acdev); +				if (ret) +					goto fail; +			} +		} +	} + +fail: +	spin_lock_irqsave(&acdev->host->lock, flags); +	writel(readl(acdev->vbase + XFER_CTR) & ~XFER_START, +			acdev->vbase + XFER_CTR); +	spin_unlock_irqrestore(&acdev->host->lock, flags); + +	return ret; +} + +/* + * This routine uses External DMA controller to read/write data to FIFO of CF + * controller. There are two xfer related interrupt supported by CF controller: + * - buf_avail: This interrupt is generated as soon as we have buffer of 512 + *	bytes available for reading or empty buffer available for writing. + * - xfer_done: This interrupt is generated on transfer of "xfer_size" amount of + *	data to/from FIFO. xfer_size is programmed in XFER_CTR register. + * + * Max buffer size = FIFO_SIZE = 512 Bytes. + * Max xfer_size = MAX_XFER_COUNT = 256 KB. + */ +static void data_xfer(struct work_struct *work) +{ +	struct arasan_cf_dev *acdev = container_of(work, struct arasan_cf_dev, +			work); +	struct ata_queued_cmd *qc = acdev->qc; +	struct scatterlist *sg; +	unsigned long flags; +	u32 temp; +	int ret = 0; + +	/* request dma channels */ +	/* dma_request_channel may sleep, so calling from process context */ +	acdev->dma_chan = dma_request_slave_channel(acdev->host->dev, "data"); +	if (!acdev->dma_chan) { +		dev_err(acdev->host->dev, "Unable to get dma_chan\n"); +		goto chan_request_fail; +	} + +	for_each_sg(qc->sg, sg, qc->n_elem, temp) { +		ret = sg_xfer(acdev, sg); +		if (ret) +			break; +	} + +	dma_release_channel(acdev->dma_chan); + +	/* data xferred successfully */ +	if (!ret) { +		u32 status; + +		spin_lock_irqsave(&acdev->host->lock, flags); +		status = ioread8(qc->ap->ioaddr.altstatus_addr); +		spin_unlock_irqrestore(&acdev->host->lock, flags); +		if (status & (ATA_BUSY | ATA_DRQ)) { +			ata_sff_queue_delayed_work(&acdev->dwork, 1); +			return; +		} + +		goto sff_intr; +	} + +	cf_dumpregs(acdev); + +chan_request_fail: +	spin_lock_irqsave(&acdev->host->lock, flags); +	/* error when transferring data to/from memory */ +	qc->err_mask |= AC_ERR_HOST_BUS; +	qc->ap->hsm_task_state = HSM_ST_ERR; + +	cf_ctrl_reset(acdev); +	spin_unlock_irqrestore(qc->ap->lock, flags); +sff_intr: +	dma_complete(acdev); +} + +static void delayed_finish(struct work_struct *work) +{ +	struct arasan_cf_dev *acdev = container_of(work, struct arasan_cf_dev, +			dwork.work); +	struct ata_queued_cmd *qc = acdev->qc; +	unsigned long flags; +	u8 status; + +	spin_lock_irqsave(&acdev->host->lock, flags); +	status = ioread8(qc->ap->ioaddr.altstatus_addr); +	spin_unlock_irqrestore(&acdev->host->lock, flags); + +	if (status & (ATA_BUSY | ATA_DRQ)) +		ata_sff_queue_delayed_work(&acdev->dwork, 1); +	else +		dma_complete(acdev); +} + +static irqreturn_t arasan_cf_interrupt(int irq, void *dev) +{ +	struct arasan_cf_dev *acdev = ((struct ata_host *)dev)->private_data; +	unsigned long flags; +	u32 irqsts; + +	irqsts = readl(acdev->vbase + GIRQ_STS); +	if (!(irqsts & GIRQ_CF)) +		return IRQ_NONE; + +	spin_lock_irqsave(&acdev->host->lock, flags); +	irqsts = readl(acdev->vbase + IRQ_STS); +	writel(irqsts, acdev->vbase + IRQ_STS);		/* clear irqs */ +	writel(GIRQ_CF, acdev->vbase + GIRQ_STS);	/* clear girqs */ + +	/* handle only relevant interrupts */ +	irqsts &= ~IGNORED_IRQS; + +	if (irqsts & CARD_DETECT_IRQ) { +		cf_card_detect(acdev, 1); +		spin_unlock_irqrestore(&acdev->host->lock, flags); +		return IRQ_HANDLED; +	} + +	if (irqsts & PIO_XFER_ERR_IRQ) { +		acdev->dma_status = ATA_DMA_ERR; +		writel(readl(acdev->vbase + XFER_CTR) & ~XFER_START, +				acdev->vbase + XFER_CTR); +		spin_unlock_irqrestore(&acdev->host->lock, flags); +		complete(&acdev->cf_completion); +		dev_err(acdev->host->dev, "pio xfer err irq\n"); +		return IRQ_HANDLED; +	} + +	spin_unlock_irqrestore(&acdev->host->lock, flags); + +	if (irqsts & BUF_AVAIL_IRQ) { +		complete(&acdev->cf_completion); +		return IRQ_HANDLED; +	} + +	if (irqsts & XFER_DONE_IRQ) { +		struct ata_queued_cmd *qc = acdev->qc; + +		/* Send Complete only for write */ +		if (qc->tf.flags & ATA_TFLAG_WRITE) +			complete(&acdev->cf_completion); +	} + +	return IRQ_HANDLED; +} + +static void arasan_cf_freeze(struct ata_port *ap) +{ +	struct arasan_cf_dev *acdev = ap->host->private_data; + +	/* stop transfer and reset controller */ +	writel(readl(acdev->vbase + XFER_CTR) & ~XFER_START, +			acdev->vbase + XFER_CTR); +	cf_ctrl_reset(acdev); +	acdev->dma_status = ATA_DMA_ERR; + +	ata_sff_dma_pause(ap); +	ata_sff_freeze(ap); +} + +static void arasan_cf_error_handler(struct ata_port *ap) +{ +	struct arasan_cf_dev *acdev = ap->host->private_data; + +	/* +	 * DMA transfers using an external DMA controller may be scheduled. +	 * Abort them before handling error. Refer data_xfer() for further +	 * details. +	 */ +	cancel_work_sync(&acdev->work); +	cancel_delayed_work_sync(&acdev->dwork); +	return ata_sff_error_handler(ap); +} + +static void arasan_cf_dma_start(struct arasan_cf_dev *acdev) +{ +	struct ata_queued_cmd *qc = acdev->qc; +	struct ata_port *ap = qc->ap; +	struct ata_taskfile *tf = &qc->tf; +	u32 xfer_ctr = readl(acdev->vbase + XFER_CTR) & ~XFER_DIR_MASK; +	u32 write = tf->flags & ATA_TFLAG_WRITE; + +	xfer_ctr |= write ? XFER_WRITE : XFER_READ; +	writel(xfer_ctr, acdev->vbase + XFER_CTR); + +	ap->ops->sff_exec_command(ap, tf); +	ata_sff_queue_work(&acdev->work); +} + +static unsigned int arasan_cf_qc_issue(struct ata_queued_cmd *qc) +{ +	struct ata_port *ap = qc->ap; +	struct arasan_cf_dev *acdev = ap->host->private_data; + +	/* defer PIO handling to sff_qc_issue */ +	if (!ata_is_dma(qc->tf.protocol)) +		return ata_sff_qc_issue(qc); + +	/* select the device */ +	ata_wait_idle(ap); +	ata_sff_dev_select(ap, qc->dev->devno); +	ata_wait_idle(ap); + +	/* start the command */ +	switch (qc->tf.protocol) { +	case ATA_PROT_DMA: +		WARN_ON_ONCE(qc->tf.flags & ATA_TFLAG_POLLING); + +		ap->ops->sff_tf_load(ap, &qc->tf); +		acdev->dma_status = 0; +		acdev->qc = qc; +		arasan_cf_dma_start(acdev); +		ap->hsm_task_state = HSM_ST_LAST; +		break; + +	default: +		WARN_ON(1); +		return AC_ERR_SYSTEM; +	} + +	return 0; +} + +static void arasan_cf_set_piomode(struct ata_port *ap, struct ata_device *adev) +{ +	struct arasan_cf_dev *acdev = ap->host->private_data; +	u8 pio = adev->pio_mode - XFER_PIO_0; +	unsigned long flags; +	u32 val; + +	/* Arasan ctrl supports Mode0 -> Mode6 */ +	if (pio > 6) { +		dev_err(ap->dev, "Unknown PIO mode\n"); +		return; +	} + +	spin_lock_irqsave(&acdev->host->lock, flags); +	val = readl(acdev->vbase + OP_MODE) & +		~(ULTRA_DMA_ENB | MULTI_WORD_DMA_ENB | DRQ_BLOCK_SIZE_MASK); +	writel(val, acdev->vbase + OP_MODE); +	val = readl(acdev->vbase + TM_CFG) & ~TRUEIDE_PIO_TIMING_MASK; +	val |= pio << TRUEIDE_PIO_TIMING_SHIFT; +	writel(val, acdev->vbase + TM_CFG); + +	cf_interrupt_enable(acdev, BUF_AVAIL_IRQ | XFER_DONE_IRQ, 0); +	cf_interrupt_enable(acdev, PIO_XFER_ERR_IRQ, 1); +	spin_unlock_irqrestore(&acdev->host->lock, flags); +} + +static void arasan_cf_set_dmamode(struct ata_port *ap, struct ata_device *adev) +{ +	struct arasan_cf_dev *acdev = ap->host->private_data; +	u32 opmode, tmcfg, dma_mode = adev->dma_mode; +	unsigned long flags; + +	spin_lock_irqsave(&acdev->host->lock, flags); +	opmode = readl(acdev->vbase + OP_MODE) & +		~(MULTI_WORD_DMA_ENB | ULTRA_DMA_ENB); +	tmcfg = readl(acdev->vbase + TM_CFG); + +	if ((dma_mode >= XFER_UDMA_0) && (dma_mode <= XFER_UDMA_6)) { +		opmode |= ULTRA_DMA_ENB; +		tmcfg &= ~ULTRA_DMA_TIMING_MASK; +		tmcfg |= (dma_mode - XFER_UDMA_0) << ULTRA_DMA_TIMING_SHIFT; +	} else if ((dma_mode >= XFER_MW_DMA_0) && (dma_mode <= XFER_MW_DMA_4)) { +		opmode |= MULTI_WORD_DMA_ENB; +		tmcfg &= ~TRUEIDE_MWORD_DMA_TIMING_MASK; +		tmcfg |= (dma_mode - XFER_MW_DMA_0) << +			TRUEIDE_MWORD_DMA_TIMING_SHIFT; +	} else { +		dev_err(ap->dev, "Unknown DMA mode\n"); +		spin_unlock_irqrestore(&acdev->host->lock, flags); +		return; +	} + +	writel(opmode, acdev->vbase + OP_MODE); +	writel(tmcfg, acdev->vbase + TM_CFG); +	writel(DMA_XFER_MODE, acdev->vbase + XFER_CTR); + +	cf_interrupt_enable(acdev, PIO_XFER_ERR_IRQ, 0); +	cf_interrupt_enable(acdev, BUF_AVAIL_IRQ | XFER_DONE_IRQ, 1); +	spin_unlock_irqrestore(&acdev->host->lock, flags); +} + +static struct ata_port_operations arasan_cf_ops = { +	.inherits = &ata_sff_port_ops, +	.freeze = arasan_cf_freeze, +	.error_handler = arasan_cf_error_handler, +	.qc_issue = arasan_cf_qc_issue, +	.set_piomode = arasan_cf_set_piomode, +	.set_dmamode = arasan_cf_set_dmamode, +}; + +static int arasan_cf_probe(struct platform_device *pdev) +{ +	struct arasan_cf_dev *acdev; +	struct arasan_cf_pdata *pdata = dev_get_platdata(&pdev->dev); +	struct ata_host *host; +	struct ata_port *ap; +	struct resource *res; +	u32 quirk; +	irq_handler_t irq_handler = NULL; +	int ret = 0; + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!res) +		return -EINVAL; + +	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), +				DRIVER_NAME)) { +		dev_warn(&pdev->dev, "Failed to get memory region resource\n"); +		return -ENOENT; +	} + +	acdev = devm_kzalloc(&pdev->dev, sizeof(*acdev), GFP_KERNEL); +	if (!acdev) { +		dev_warn(&pdev->dev, "kzalloc fail\n"); +		return -ENOMEM; +	} + +	if (pdata) +		quirk = pdata->quirk; +	else +		quirk = CF_BROKEN_UDMA; /* as it is on spear1340 */ + +	/* if irq is 0, support only PIO */ +	acdev->irq = platform_get_irq(pdev, 0); +	if (acdev->irq) +		irq_handler = arasan_cf_interrupt; +	else +		quirk |= CF_BROKEN_MWDMA | CF_BROKEN_UDMA; + +	acdev->pbase = res->start; +	acdev->vbase = devm_ioremap_nocache(&pdev->dev, res->start, +			resource_size(res)); +	if (!acdev->vbase) { +		dev_warn(&pdev->dev, "ioremap fail\n"); +		return -ENOMEM; +	} + +	acdev->clk = clk_get(&pdev->dev, NULL); +	if (IS_ERR(acdev->clk)) { +		dev_warn(&pdev->dev, "Clock not found\n"); +		return PTR_ERR(acdev->clk); +	} + +	/* allocate host */ +	host = ata_host_alloc(&pdev->dev, 1); +	if (!host) { +		ret = -ENOMEM; +		dev_warn(&pdev->dev, "alloc host fail\n"); +		goto free_clk; +	} + +	ap = host->ports[0]; +	host->private_data = acdev; +	acdev->host = host; +	ap->ops = &arasan_cf_ops; +	ap->pio_mask = ATA_PIO6; +	ap->mwdma_mask = ATA_MWDMA4; +	ap->udma_mask = ATA_UDMA6; + +	init_completion(&acdev->cf_completion); +	init_completion(&acdev->dma_completion); +	INIT_WORK(&acdev->work, data_xfer); +	INIT_DELAYED_WORK(&acdev->dwork, delayed_finish); +	dma_cap_set(DMA_MEMCPY, acdev->mask); + +	/* Handle platform specific quirks */ +	if (quirk) { +		if (quirk & CF_BROKEN_PIO) { +			ap->ops->set_piomode = NULL; +			ap->pio_mask = 0; +		} +		if (quirk & CF_BROKEN_MWDMA) +			ap->mwdma_mask = 0; +		if (quirk & CF_BROKEN_UDMA) +			ap->udma_mask = 0; +	} +	ap->flags |= ATA_FLAG_PIO_POLLING | ATA_FLAG_NO_ATAPI; + +	ap->ioaddr.cmd_addr = acdev->vbase + ATA_DATA_PORT; +	ap->ioaddr.data_addr = acdev->vbase + ATA_DATA_PORT; +	ap->ioaddr.error_addr = acdev->vbase + ATA_ERR_FTR; +	ap->ioaddr.feature_addr = acdev->vbase + ATA_ERR_FTR; +	ap->ioaddr.nsect_addr = acdev->vbase + ATA_SC; +	ap->ioaddr.lbal_addr = acdev->vbase + ATA_SN; +	ap->ioaddr.lbam_addr = acdev->vbase + ATA_CL; +	ap->ioaddr.lbah_addr = acdev->vbase + ATA_CH; +	ap->ioaddr.device_addr = acdev->vbase + ATA_SH; +	ap->ioaddr.status_addr = acdev->vbase + ATA_STS_CMD; +	ap->ioaddr.command_addr = acdev->vbase + ATA_STS_CMD; +	ap->ioaddr.altstatus_addr = acdev->vbase + ATA_ASTS_DCTR; +	ap->ioaddr.ctl_addr = acdev->vbase + ATA_ASTS_DCTR; + +	ata_port_desc(ap, "phy_addr %llx virt_addr %p", +		      (unsigned long long) res->start, acdev->vbase); + +	ret = cf_init(acdev); +	if (ret) +		goto free_clk; + +	cf_card_detect(acdev, 0); + +	ret = ata_host_activate(host, acdev->irq, irq_handler, 0, +				&arasan_cf_sht); +	if (!ret) +		return 0; + +	cf_exit(acdev); +free_clk: +	clk_put(acdev->clk); +	return ret; +} + +static int arasan_cf_remove(struct platform_device *pdev) +{ +	struct ata_host *host = platform_get_drvdata(pdev); +	struct arasan_cf_dev *acdev = host->ports[0]->private_data; + +	ata_host_detach(host); +	cf_exit(acdev); +	clk_put(acdev->clk); + +	return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int arasan_cf_suspend(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	struct arasan_cf_dev *acdev = host->ports[0]->private_data; + +	if (acdev->dma_chan) +		acdev->dma_chan->device->device_control(acdev->dma_chan, +				DMA_TERMINATE_ALL, 0); + +	cf_exit(acdev); +	return ata_host_suspend(host, PMSG_SUSPEND); +} + +static int arasan_cf_resume(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	struct arasan_cf_dev *acdev = host->ports[0]->private_data; + +	cf_init(acdev); +	ata_host_resume(host); + +	return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(arasan_cf_pm_ops, arasan_cf_suspend, arasan_cf_resume); + +#ifdef CONFIG_OF +static const struct of_device_id arasan_cf_id_table[] = { +	{ .compatible = "arasan,cf-spear1340" }, +	{} +}; +MODULE_DEVICE_TABLE(of, arasan_cf_id_table); +#endif + +static struct platform_driver arasan_cf_driver = { +	.probe		= arasan_cf_probe, +	.remove		= arasan_cf_remove, +	.driver		= { +		.name	= DRIVER_NAME, +		.owner	= THIS_MODULE, +		.pm	= &arasan_cf_pm_ops, +		.of_match_table = of_match_ptr(arasan_cf_id_table), +	}, +}; + +module_platform_driver(arasan_cf_driver); + +MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_DESCRIPTION("Arasan ATA Compact Flash driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index 2215632e4b3..96c05c9494f 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c @@ -2,7 +2,7 @@   *    pata_artop.c - ARTOP ATA controller driver   *   *	(C) 2006 Red Hat - *	(C) 2007 Bartlomiej Zolnierkiewicz + *	(C) 2007,2011 Bartlomiej Zolnierkiewicz   *   *    Based in part on drivers/ide/pci/aec62xx.c   *	Copyright (C) 1999-2002	Andre Hedrick <andre@linux-ide.org> @@ -19,7 +19,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -28,7 +27,7 @@  #include <linux/ata.h>  #define DRV_NAME	"pata_artop" -#define DRV_VERSION	"0.4.5" +#define DRV_VERSION	"0.4.6"  /*   *	The ARTOP has 33 Mhz and "over clocked" timing tables. Until we @@ -39,31 +38,15 @@  static int clock = 0; -static int artop6210_pre_reset(struct ata_link *link, unsigned long deadline) -{ -	struct ata_port *ap = link->ap; -	struct pci_dev *pdev = to_pci_dev(ap->host->dev); -	const struct pci_bits artop_enable_bits[] = { -		{ 0x4AU, 1U, 0x02UL, 0x02UL },	/* port 0 */ -		{ 0x4AU, 1U, 0x04UL, 0x04UL },	/* port 1 */ -	}; - -	if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) -		return -ENOENT; - -	return ata_sff_prereset(link, deadline); -} -  /** - *	artop6260_pre_reset	-	check for 40/80 pin + *	artop62x0_pre_reset	-	probe begin   *	@link: link   *	@deadline: deadline jiffies for the operation   * - *	The ARTOP hardware reports the cable detect bits in register 0x49.   *	Nothing complicated needed here.   */ -static int artop6260_pre_reset(struct ata_link *link, unsigned long deadline) +static int artop62x0_pre_reset(struct ata_link *link, unsigned long deadline)  {  	static const struct pci_bits artop_enable_bits[] = {  		{ 0x4AU, 1U, 0x02UL, 0x02UL },	/* port 0 */ @@ -73,7 +56,7 @@ static int artop6260_pre_reset(struct ata_link *link, unsigned long deadline)  	struct ata_port *ap = link->ap;  	struct pci_dev *pdev = to_pci_dev(ap->host->dev); -	/* Odd numbered device ids are the units with enable bits (the -R cards) */ +	/* Odd numbered device ids are the units with enable bits. */  	if ((pdev->device & 1) &&  	    !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no]))  		return -ENOENT; @@ -317,7 +300,7 @@ static struct ata_port_operations artop6210_ops = {  	.cable_detect		= ata_cable_40wire,  	.set_piomode		= artop6210_set_piomode,  	.set_dmamode		= artop6210_set_dmamode, -	.prereset		= artop6210_pre_reset, +	.prereset		= artop62x0_pre_reset,  	.qc_defer		= artop6210_qc_defer,  }; @@ -326,9 +309,36 @@ static struct ata_port_operations artop6260_ops = {  	.cable_detect		= artop6260_cable_detect,  	.set_piomode		= artop6260_set_piomode,  	.set_dmamode		= artop6260_set_dmamode, -	.prereset		= artop6260_pre_reset, +	.prereset		= artop62x0_pre_reset,  }; +static void atp8xx_fixup(struct pci_dev *pdev) +{ +	if (pdev->device == 0x0005) +		/* BIOS may have left us in UDMA, clear it before libata probe */ +		pci_write_config_byte(pdev, 0x54, 0); +	else if (pdev->device == 0x0008 || pdev->device == 0x0009) { +		u8 reg; + +		/* Mac systems come up with some registers not set as we +		   will need them */ + +		/* Clear reset & test bits */ +		pci_read_config_byte(pdev, 0x49, ®); +		pci_write_config_byte(pdev, 0x49, reg & ~0x30); + +		/* PCI latency must be > 0x80 for burst mode, tweak it +		 * if required. +		 */ +		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, ®); +		if (reg <= 0x80) +			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90); + +		/* Enable IRQ output and burst mode */ +		pci_read_config_byte(pdev, 0x4a, ®); +		pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80); +	} +}  /**   *	artop_init_one - Register ARTOP ATA PCI device with kernel services @@ -346,7 +356,6 @@ static struct ata_port_operations artop6260_ops = {  static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)  { -	static int printed_version;  	static const struct ata_port_info info_6210 = {  		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4, @@ -378,50 +387,28 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)  	const struct ata_port_info *ppi[] = { NULL, NULL };  	int rc; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc)  		return rc; -	if (id->driver_data == 0) {	/* 6210 variant */ +	if (id->driver_data == 0)	/* 6210 variant */  		ppi[0] = &info_6210; -		/* BIOS may have left us in UDMA, clear it before libata probe */ -		pci_write_config_byte(pdev, 0x54, 0); -	}  	else if (id->driver_data == 1)	/* 6260 */  		ppi[0] = &info_626x;  	else if (id->driver_data == 2)	{ /* 6280 or 6280 + fast */  		unsigned long io = pci_resource_start(pdev, 4); -		u8 reg;  		ppi[0] = &info_628x;  		if (inb(io) & 0x10)  			ppi[0] = &info_628x_fast; -		/* Mac systems come up with some registers not set as we -		   will need them */ - -		/* Clear reset & test bits */ -		pci_read_config_byte(pdev, 0x49, ®); -		pci_write_config_byte(pdev, 0x49, reg & ~ 0x30); - -		/* PCI latency must be > 0x80 for burst mode, tweak it -		 * if required. -		 */ -		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, ®); -		if (reg <= 0x80) -			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90); - -		/* Enable IRQ output and burst mode */ -		pci_read_config_byte(pdev, 0x4a, ®); -		pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80); -  	}  	BUG_ON(ppi[0] == NULL); +	atp8xx_fixup(pdev); +  	return ata_pci_bmdma_init_one(pdev, ppi, &artop_sht, NULL, 0);  } @@ -435,29 +422,38 @@ static const struct pci_device_id artop_pci_tbl[] = {  	{ }	/* terminate list */  }; +#ifdef CONFIG_PM_SLEEP +static int atp8xx_reinit_one(struct pci_dev *pdev) +{ +	struct ata_host *host = pci_get_drvdata(pdev); +	int rc; + +	rc = ata_pci_device_do_resume(pdev); +	if (rc) +		return rc; + +	atp8xx_fixup(pdev); + +	ata_host_resume(host); +	return 0; +} +#endif +  static struct pci_driver artop_pci_driver = {  	.name			= DRV_NAME,  	.id_table		= artop_pci_tbl,  	.probe			= artop_init_one,  	.remove			= ata_pci_remove_one, +#ifdef CONFIG_PM_SLEEP +	.suspend		= ata_pci_device_suspend, +	.resume			= atp8xx_reinit_one, +#endif  }; -static int __init artop_init(void) -{ -	return pci_register_driver(&artop_pci_driver); -} +module_pci_driver(artop_pci_driver); -static void __exit artop_exit(void) -{ -	pci_unregister_driver(&artop_pci_driver); -} - -module_init(artop_init); -module_exit(artop_exit); - -MODULE_AUTHOR("Alan Cox"); +MODULE_AUTHOR("Alan Cox, Bartlomiej Zolnierkiewicz");  MODULE_DESCRIPTION("SCSI low-level driver for ARTOP PATA");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, artop_pci_tbl);  MODULE_VERSION(DRV_VERSION); - diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c index 66ce6a526f2..d59d5239405 100644 --- a/drivers/ata/pata_at32.c +++ b/drivers/ata/pata_at32.c @@ -194,7 +194,7 @@ static int __init pata_at32_init_one(struct device *dev,  	/* Setup ATA bindings */  	ap->ops	     = &at32_port_ops;  	ap->pio_mask = PIO_MASK; -	ap->flags   |= ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS; +	ap->flags   |= ATA_FLAG_SLAVE_POSS;  	/*  	 * Since all 8-bit taskfile transfers has to go on the lower @@ -271,7 +271,7 @@ static int __init pata_at32_probe(struct platform_device *pdev)  	struct device		 *dev = &pdev->dev;  	struct at32_ide_info	 *info; -	struct ide_platform_data *board = pdev->dev.platform_data; +	struct ide_platform_data *board = dev_get_platdata(&pdev->dev);  	struct resource		 *res;  	int irq; @@ -393,18 +393,7 @@ static struct platform_driver pata_at32_driver = {  	},  }; -static int __init pata_at32_init(void) -{ -	return platform_driver_probe(&pata_at32_driver, pata_at32_probe); -} - -static void __exit pata_at32_exit(void) -{ -	platform_driver_unregister(&pata_at32_driver); -} - -module_init(pata_at32_init); -module_exit(pata_at32_exit); +module_platform_driver_probe(pata_at32_driver, pata_at32_probe);  MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("AVR32 SMC/CFC PATA Driver"); diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c index 0da0dcc7dd0..8a66f23af4c 100644 --- a/drivers/ata/pata_at91.c +++ b/drivers/ata/pata_at91.c @@ -3,6 +3,7 @@   * with CompactFlash interface in True IDE mode   *   * Copyright (C) 2009 Matyukevich Sergey + *               2011 Igor Plyatov   *   * Based on:   *      * generic platform driver by Paul Mundt: drivers/ata/pata_platform.c @@ -17,7 +18,6 @@  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/gfp.h>  #include <scsi/scsi_host.h> @@ -26,31 +26,154 @@  #include <linux/libata.h>  #include <linux/platform_device.h>  #include <linux/ata_platform.h> +#include <linux/platform_data/atmel.h>  #include <mach/at91sam9_smc.h> -#include <mach/board.h> -#include <mach/gpio.h> +#include <asm/gpio.h> +#define DRV_NAME		"pata_at91" +#define DRV_VERSION		"0.3" -#define DRV_NAME "pata_at91" -#define DRV_VERSION "0.1" - -#define CF_IDE_OFFSET	    0x00c00000 -#define CF_ALT_IDE_OFFSET   0x00e00000 -#define CF_IDE_RES_SIZE     0x08 +#define CF_IDE_OFFSET		0x00c00000 +#define CF_ALT_IDE_OFFSET	0x00e00000 +#define CF_IDE_RES_SIZE		0x08 +#define CS_PULSE_MAXIMUM	319 +#define ER_SMC_CALC		1 +#define ER_SMC_RECALC		2  struct at91_ide_info {  	unsigned long mode;  	unsigned int cs; -  	struct clk *mck; -  	void __iomem *ide_addr;  	void __iomem *alt_addr;  }; -static const struct ata_timing initial_timing = -	{XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0}; +/** + * struct smc_range - range of valid values for SMC register. + */ +struct smc_range { +	int min; +	int max; +}; + +/** + * adjust_smc_value - adjust value for one of SMC registers. + * @value: adjusted value + * @range: array of SMC ranges with valid values + * @size: SMC ranges array size + * + * This returns the difference between input and output value or negative + * in case of invalid input value. + * If negative returned, then output value = maximal possible from ranges. + */ +static int adjust_smc_value(int *value, struct smc_range *range, int size) +{ +	int maximum = (range + size - 1)->max; +	int remainder; + +	do { +		if (*value < range->min) { +			remainder = range->min - *value; +			*value = range->min; /* nearest valid value */ +			return remainder; +		} else if ((range->min <= *value) && (*value <= range->max)) +			return 0; + +		range++; +	} while (--size); +	*value = maximum; + +	return -1; /* invalid value */ +} + +/** + * calc_smc_vals - calculate SMC register values + * @dev: ATA device + * @setup: SMC_SETUP register value + * @pulse: SMC_PULSE register value + * @cycle: SMC_CYCLE register value + * + * This returns negative in case of invalid values for SMC registers: + * -ER_SMC_RECALC - recalculation required for SMC values, + * -ER_SMC_CALC - calculation failed (invalid input values). + * + * SMC use special coding scheme, see "Coding and Range of Timing + * Parameters" table from AT91SAM9 datasheets. + * + *	SMC_SETUP = 128*setup[5] + setup[4:0] + *	SMC_PULSE = 256*pulse[6] + pulse[5:0] + *	SMC_CYCLE = 256*cycle[8:7] + cycle[6:0] + */ +static int calc_smc_vals(struct device *dev, +		int *setup, int *pulse, int *cycle, int *cs_pulse) +{ +	int ret_val; +	int err = 0; +	struct smc_range range_setup[] = {	/* SMC_SETUP valid values */ +		{.min = 0,	.max = 31},	/* first  range */ +		{.min = 128,	.max = 159}	/* second range */ +	}; +	struct smc_range range_pulse[] = {	/* SMC_PULSE valid values */ +		{.min = 0,	.max = 63},	/* first  range */ +		{.min = 256,	.max = 319}	/* second range */ +	}; +	struct smc_range range_cycle[] = {	/* SMC_CYCLE valid values */ +		{.min = 0,	.max = 127},	/* first  range */ +		{.min = 256,	.max = 383},	/* second range */ +		{.min = 512,	.max = 639},	/* third  range */ +		{.min = 768,	.max = 895}	/* fourth range */ +	}; + +	ret_val = adjust_smc_value(setup, range_setup, ARRAY_SIZE(range_setup)); +	if (ret_val < 0) +		dev_warn(dev, "maximal SMC Setup value\n"); +	else +		*cycle += ret_val; + +	ret_val = adjust_smc_value(pulse, range_pulse, ARRAY_SIZE(range_pulse)); +	if (ret_val < 0) +		dev_warn(dev, "maximal SMC Pulse value\n"); +	else +		*cycle += ret_val; + +	ret_val = adjust_smc_value(cycle, range_cycle, ARRAY_SIZE(range_cycle)); +	if (ret_val < 0) +		dev_warn(dev, "maximal SMC Cycle value\n"); + +	*cs_pulse = *cycle; +	if (*cs_pulse > CS_PULSE_MAXIMUM) { +		dev_err(dev, "unable to calculate valid SMC settings\n"); +		return -ER_SMC_CALC; +	} + +	ret_val = adjust_smc_value(cs_pulse, range_pulse, +					ARRAY_SIZE(range_pulse)); +	if (ret_val < 0) { +		dev_warn(dev, "maximal SMC CS Pulse value\n"); +	} else if (ret_val != 0) { +		*cycle = *cs_pulse; +		dev_warn(dev, "SMC Cycle extended\n"); +		err = -ER_SMC_RECALC; +	} + +	return err; +} + +/** + * to_smc_format - convert values into SMC format + * @setup: SETUP value of SMC Setup Register + * @pulse: PULSE value of SMC Pulse Register + * @cycle: CYCLE value of SMC Cycle Register + * @cs_pulse: NCS_PULSE value of SMC Pulse Register + */ +static void to_smc_format(int *setup, int *pulse, int *cycle, int *cs_pulse) +{ +	*setup = (*setup & 0x1f) | ((*setup & 0x80) >> 2); +	*pulse = (*pulse & 0x3f) | ((*pulse & 0x100) >> 2); +	*cycle = (*cycle & 0x7f) | ((*cycle & 0x300) >> 1); +	*cs_pulse = (*cs_pulse & 0x3f) | ((*cs_pulse & 0x100) >> 2); +}  static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz)  { @@ -69,80 +192,71 @@ static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz)  	return (ns * mul + 65536) >> 16;    /* rounding */  } -static void set_smc_mode(struct at91_ide_info *info) -{ -	at91_sys_write(AT91_SMC_MODE(info->cs), info->mode); -	return; -} - -static void set_smc_timing(struct device *dev, +/** + * set_smc_timing - SMC timings setup. + * @dev: device + * @info: AT91 IDE info + * @ata: ATA timings + * + * Its assumed that write timings are same as read timings, + * cs_setup = 0 and cs_pulse = cycle. + */ +static void set_smc_timing(struct device *dev, struct ata_device *adev,  		struct at91_ide_info *info, const struct ata_timing *ata)  { -	unsigned long read_cycle, write_cycle, active, recover; -	unsigned long nrd_setup, nrd_pulse, nrd_recover; -	unsigned long nwe_setup, nwe_pulse; - -	unsigned long ncs_write_setup, ncs_write_pulse; -	unsigned long ncs_read_setup, ncs_read_pulse; - -	unsigned long mck_hz; - -	read_cycle  = ata->cyc8b; -	nrd_setup   = ata->setup; -	nrd_pulse   = ata->act8b; -	nrd_recover = ata->rec8b; - +	int ret = 0; +	int use_iordy; +	struct sam9_smc_config smc; +	unsigned int t6z;         /* data tristate time in ns */ +	unsigned int cycle;       /* SMC Cycle width in MCK ticks */ +	unsigned int setup;       /* SMC Setup width in MCK ticks */ +	unsigned int pulse;       /* CFIOR and CFIOW pulse width in MCK ticks */ +	unsigned int cs_pulse;    /* CS4 or CS5 pulse width in MCK ticks*/ +	unsigned int tdf_cycles;  /* SMC TDF MCK ticks */ +	unsigned long mck_hz;     /* MCK frequency in Hz */ + +	t6z = (ata->mode < XFER_PIO_5) ? 30 : 20;  	mck_hz = clk_get_rate(info->mck); +	cycle = calc_mck_cycles(ata->cyc8b, mck_hz); +	setup = calc_mck_cycles(ata->setup, mck_hz); +	pulse = calc_mck_cycles(ata->act8b, mck_hz); +	tdf_cycles = calc_mck_cycles(t6z, mck_hz); + +	do { +		ret = calc_smc_vals(dev, &setup, &pulse, &cycle, &cs_pulse); +	} while (ret == -ER_SMC_RECALC); + +	if (ret == -ER_SMC_CALC) +		dev_err(dev, "Interface may not operate correctly\n"); + +	dev_dbg(dev, "SMC Setup=%u, Pulse=%u, Cycle=%u, CS Pulse=%u\n", +		setup, pulse, cycle, cs_pulse); +	to_smc_format(&setup, &pulse, &cycle, &cs_pulse); +	/* disable or enable waiting for IORDY signal */ +	use_iordy = ata_pio_need_iordy(adev); +	if (use_iordy) +		info->mode |= AT91_SMC_EXNWMODE_READY; + +	if (tdf_cycles > 15) { +		tdf_cycles = 15; +		dev_warn(dev, "maximal SMC TDF Cycles value\n"); +	} -	read_cycle  = calc_mck_cycles(read_cycle, mck_hz); -	nrd_setup   = calc_mck_cycles(nrd_setup, mck_hz); -	nrd_pulse   = calc_mck_cycles(nrd_pulse, mck_hz); -	nrd_recover = calc_mck_cycles(nrd_recover, mck_hz); - -	active  = nrd_setup + nrd_pulse; -	recover = read_cycle - active; - -	/* Need at least two cycles recovery */ -	if (recover < 2) -		read_cycle = active + 2; - -	/* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */ -	ncs_read_setup = 1; -	ncs_read_pulse = read_cycle - 2; - -	/* Write timings same as read timings */ -	write_cycle = read_cycle; -	nwe_setup = nrd_setup; -	nwe_pulse = nrd_pulse; -	ncs_write_setup = ncs_read_setup; -	ncs_write_pulse = ncs_read_pulse; - -	dev_dbg(dev, "ATA timings: nrd_setup = %lu nrd_pulse = %lu nrd_cycle = %lu\n", -			nrd_setup, nrd_pulse, read_cycle); -	dev_dbg(dev, "ATA timings: nwe_setup = %lu nwe_pulse = %lu nwe_cycle = %lu\n", -			nwe_setup, nwe_pulse, write_cycle); -	dev_dbg(dev, "ATA timings: ncs_read_setup = %lu ncs_read_pulse = %lu\n", -			ncs_read_setup, ncs_read_pulse); -	dev_dbg(dev, "ATA timings: ncs_write_setup = %lu ncs_write_pulse = %lu\n", -			ncs_write_setup, ncs_write_pulse); - -	at91_sys_write(AT91_SMC_SETUP(info->cs), -			AT91_SMC_NWESETUP_(nwe_setup) | -			AT91_SMC_NRDSETUP_(nrd_setup) | -			AT91_SMC_NCS_WRSETUP_(ncs_write_setup) | -			AT91_SMC_NCS_RDSETUP_(ncs_read_setup)); - -	at91_sys_write(AT91_SMC_PULSE(info->cs), -			AT91_SMC_NWEPULSE_(nwe_pulse) | -			AT91_SMC_NRDPULSE_(nrd_pulse) | -			AT91_SMC_NCS_WRPULSE_(ncs_write_pulse) | -			AT91_SMC_NCS_RDPULSE_(ncs_read_pulse)); - -	at91_sys_write(AT91_SMC_CYCLE(info->cs), -			AT91_SMC_NWECYCLE_(write_cycle) | -			AT91_SMC_NRDCYCLE_(read_cycle)); - -	return; +	dev_dbg(dev, "Use IORDY=%u, TDF Cycles=%u\n", use_iordy, tdf_cycles); + +	/* SMC Setup Register */ +	smc.nwe_setup = smc.nrd_setup = setup; +	smc.ncs_write_setup = smc.ncs_read_setup = 0; +	/* SMC Pulse Register */ +	smc.nwe_pulse = smc.nrd_pulse = pulse; +	smc.ncs_write_pulse = smc.ncs_read_pulse = cs_pulse; +	/* SMC Cycle Register */ +	smc.write_cycle = smc.read_cycle = cycle; +	/* SMC Mode Register*/ +	smc.tdf_cycles = tdf_cycles; +	smc.mode = info->mode; + +	sam9_smc_configure(0, info->cs, &smc);  }  static void pata_at91_set_piomode(struct ata_port *ap, struct ata_device *adev) @@ -156,15 +270,9 @@ static void pata_at91_set_piomode(struct ata_port *ap, struct ata_device *adev)  	if (ret) {  		dev_warn(ap->dev, "Failed to compute ATA timing %d, "  			 "set PIO_0 timing\n", ret); -		set_smc_timing(ap->dev, info, &initial_timing); -	} else { -		set_smc_timing(ap->dev, info, &timing); +		timing = *ata_timing_find_mode(XFER_PIO_0);  	} - -	/* Setup SMC mode */ -	set_smc_mode(info); - -	return; +	set_smc_timing(ap->dev, adev, info, &timing);  }  static unsigned int pata_at91_data_xfer_noirq(struct ata_device *dev, @@ -173,20 +281,20 @@ static unsigned int pata_at91_data_xfer_noirq(struct ata_device *dev,  	struct at91_ide_info *info = dev->link->ap->host->private_data;  	unsigned int consumed;  	unsigned long flags; -	unsigned int mode; +	struct sam9_smc_config smc;  	local_irq_save(flags); -	mode = at91_sys_read(AT91_SMC_MODE(info->cs)); +	sam9_smc_read_mode(0, info->cs, &smc);  	/* set 16bit mode before writing data */ -	at91_sys_write(AT91_SMC_MODE(info->cs), -			(mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_16); +	smc.mode = (smc.mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_16; +	sam9_smc_write_mode(0, info->cs, &smc);  	consumed = ata_sff_data_xfer(dev, buf, buflen, rw);  	/* restore 8bit mode after data is written */ -	at91_sys_write(AT91_SMC_MODE(info->cs), -			(mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_8); +	smc.mode = (smc.mode & ~AT91_SMC_DBW) | AT91_SMC_DBW_8; +	sam9_smc_write_mode(0, info->cs, &smc);  	local_irq_restore(flags);  	return consumed; @@ -204,9 +312,9 @@ static struct ata_port_operations pata_at91_port_ops = {  	.cable_detect	= ata_cable_40wire,  }; -static int __devinit pata_at91_probe(struct platform_device *pdev) +static int pata_at91_probe(struct platform_device *pdev)  { -	struct at91_cf_data *board = pdev->dev.platform_data; +	struct at91_cf_data *board = dev_get_platdata(&pdev->dev);  	struct device *dev = &pdev->dev;  	struct at91_ide_info *info;  	struct resource *mem_res; @@ -245,7 +353,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)  	ap->flags |= ATA_FLAG_SLAVE_POSS;  	ap->pio_mask = ATA_PIO4; -	if (!irq) { +	if (!gpio_is_valid(irq)) {  		ap->flags |= ATA_FLAG_PIO_POLLING;  		ata_port_desc(ap, "no IRQ, using PIO polling");  	} @@ -299,18 +407,22 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)  	host->private_data = info; -	return ata_host_activate(host, irq ? gpio_to_irq(irq) : 0, -			irq ? ata_sff_interrupt : NULL, -			irq_flags, &pata_at91_sht); +	ret = ata_host_activate(host, gpio_is_valid(irq) ? gpio_to_irq(irq) : 0, +				gpio_is_valid(irq) ? ata_sff_interrupt : NULL, +				irq_flags, &pata_at91_sht); +	if (ret) +		goto err_put; + +	return 0;  err_put:  	clk_put(info->mck);  	return ret;  } -static int __devexit pata_at91_remove(struct platform_device *pdev) +static int pata_at91_remove(struct platform_device *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = platform_get_drvdata(pdev);  	struct at91_ide_info *info;  	if (!host) @@ -329,27 +441,14 @@ static int __devexit pata_at91_remove(struct platform_device *pdev)  static struct platform_driver pata_at91_driver = {  	.probe		= pata_at91_probe, -	.remove		= __devexit_p(pata_at91_remove), -	.driver 	= { +	.remove		= pata_at91_remove, +	.driver		= {  		.name		= DRV_NAME,  		.owner		= THIS_MODULE,  	},  }; -static int __init pata_at91_init(void) -{ -	return platform_driver_register(&pata_at91_driver); -} - -static void __exit pata_at91_exit(void) -{ -	platform_driver_unregister(&pata_at91_driver); -} - - -module_init(pata_at91_init); -module_exit(pata_at91_exit); - +module_platform_driver(pata_at91_driver);  MODULE_LICENSE("GPL");  MODULE_DESCRIPTION("Driver for CF in True IDE mode on AT91SAM9260 SoC"); diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index 43755616dc5..970f7767e5f 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -15,11 +15,11 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h>  #include <linux/libata.h> +#include <linux/dmi.h>  #define DRV_NAME "pata_atiixp"  #define DRV_VERSION "0.4.6" @@ -33,11 +33,26 @@ enum {  	ATIIXP_IDE_UDMA_MODE 	= 0x56  }; +static const struct dmi_system_id attixp_cable_override_dmi_table[] = { +	{ +		/* Board has onboard PATA<->SATA converters */ +		.ident = "MSI E350DM-E33", +		.matches = { +			DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), +			DMI_MATCH(DMI_BOARD_NAME, "E350DM-E33(MS-7720)"), +		}, +	}, +	{ } +}; +  static int atiixp_cable_detect(struct ata_port *ap)  {  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	u8 udma; +	if (dmi_check_system(attixp_cable_override_dmi_table)) +		return ATA_CBL_PATA40_SHORT; +  	/* Hack from drivers/ide/pci. Really we want to know how to do the  	   raw detection not play follow the bios mode guess */  	pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ap->port_no, &udma); @@ -49,6 +64,31 @@ static int atiixp_cable_detect(struct ata_port *ap)  static DEFINE_SPINLOCK(atiixp_lock);  /** + *	atiixp_prereset	-	perform reset handling + *	@link: ATA link + *	@deadline: deadline jiffies for the operation + * + *	Reset sequence checking enable bits to see which ports are + *	active. + */ + +static int atiixp_prereset(struct ata_link *link, unsigned long deadline) +{ +	static const struct pci_bits atiixp_enable_bits[] = { +		{ 0x48, 1, 0x01, 0x00 }, +		{ 0x48, 1, 0x08, 0x00 } +	}; + +	struct ata_port *ap = link->ap; +	struct pci_dev *pdev = to_pci_dev(ap->host->dev); + +	if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no])) +		return -ENOENT; + +	return ata_sff_prereset(link, deadline); +} + +/**   *	atiixp_set_pio_timing	-	set initial PIO mode data   *	@ap: ATA interface   *	@adev: ATA device @@ -221,6 +261,7 @@ static struct ata_port_operations atiixp_port_ops = {  	.bmdma_start 	= atiixp_bmdma_start,  	.bmdma_stop	= atiixp_bmdma_stop, +	.prereset	= atiixp_prereset,  	.cable_detect	= atiixp_cable_detect,  	.set_piomode	= atiixp_set_piomode,  	.set_dmamode	= atiixp_set_dmamode, @@ -235,16 +276,7 @@ static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  		.udma_mask = ATA_UDMA5,  		.port_ops = &atiixp_port_ops  	}; -	static const struct pci_bits atiixp_enable_bits[] = { -		{ 0x48, 1, 0x01, 0x00 }, -		{ 0x48, 1, 0x08, 0x00 } -	};  	const struct ata_port_info *ppi[] = { &info, &info }; -	int i; - -	for (i = 0; i < 2; i++) -		if (!pci_test_config_bits(pdev, &atiixp_enable_bits[i])) -			ppi[i] = &ata_dummy_port_info;  	return ata_pci_bmdma_init_one(pdev, ppi, &atiixp_sht, NULL,  				      ATA_HOST_PARALLEL_SCAN); @@ -266,28 +298,16 @@ static struct pci_driver atiixp_pci_driver = {  	.id_table	= atiixp,  	.probe 		= atiixp_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.resume		= ata_pci_device_resume,  	.suspend	= ata_pci_device_suspend,  #endif  }; -static int __init atiixp_init(void) -{ -	return pci_register_driver(&atiixp_pci_driver); -} - - -static void __exit atiixp_exit(void) -{ -	pci_unregister_driver(&atiixp_pci_driver); -} +module_pci_driver(atiixp_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for ATI IXP200/300/400");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, atiixp);  MODULE_VERSION(DRV_VERSION); - -module_init(atiixp_init); -module_exit(atiixp_exit); diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index 95295935dd9..a705cfca90f 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c @@ -29,7 +29,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -470,7 +469,7 @@ static int atp867x_ata_pci_sff_init_host(struct ata_host *host)  	}  	if (!mask) { -		dev_printk(KERN_ERR, gdev, "no available native port\n"); +		dev_err(gdev, "no available native port\n");  		return -ENODEV;  	} @@ -487,7 +486,6 @@ static int atp867x_ata_pci_sff_init_host(struct ata_host *host)  static int atp867x_init_one(struct pci_dev *pdev,  	const struct pci_device_id *id)  { -	static int printed_version;  	static const struct ata_port_info info_867x = {  		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4, @@ -499,8 +497,7 @@ static int atp867x_init_one(struct pci_dev *pdev,  	const struct ata_port_info *ppi[] = { &info_867x, NULL };  	int rc; -	if (!printed_version++) -		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -511,15 +508,14 @@ static int atp867x_init_one(struct pci_dev *pdev,  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, ATP867X_NUM_PORTS);  	if (!host) { -		dev_printk(KERN_ERR, &pdev->dev, -			"failed to allocate ATA host\n"); +		dev_err(&pdev->dev, "failed to allocate ATA host\n");  		rc = -ENOMEM;  		goto err_out;  	}  	rc = atp867x_ata_pci_sff_init_host(host);  	if (rc) { -		dev_printk(KERN_ERR, &pdev->dev, "failed to init host\n"); +		dev_err(&pdev->dev, "failed to init host\n");  		goto err_out;  	} @@ -528,16 +524,16 @@ static int atp867x_init_one(struct pci_dev *pdev,  	rc = ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,  				IRQF_SHARED, &atp867x_sht);  	if (rc) -		dev_printk(KERN_ERR, &pdev->dev, "failed to activate host\n"); +		dev_err(&pdev->dev, "failed to activate host\n");  err_out:  	return rc;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int atp867x_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -562,27 +558,16 @@ static struct pci_driver atp867x_driver = {  	.id_table 	= atp867x_pci_tbl,  	.probe 		= atp867x_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= atp867x_reinit_one,  #endif  }; -static int __init atp867x_init(void) -{ -	return pci_register_driver(&atp867x_driver); -} - -static void __exit atp867x_exit(void) -{ -	pci_unregister_driver(&atp867x_driver); -} +module_pci_driver(atp867x_driver);  MODULE_AUTHOR("John(Jung-Ik) Lee, Google Inc.");  MODULE_DESCRIPTION("low level driver for Artop/Acard 867x ATA controller");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, atp867x_pci_tbl);  MODULE_VERSION(DRV_VERSION); - -module_init(atp867x_init); -module_exit(atp867x_exit); diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index 7aed5c79259..03f2f2bc83b 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -251,6 +251,8 @@ static const u32 udma_tenvmin = 20;  static const u32 udma_tackmin = 20;  static const u32 udma_tssmin = 50; +#define BFIN_MAX_SG_SEGMENTS 4 +  /**   *   *	Function:       num_clocks_min @@ -418,14 +420,6 @@ static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev)  					(tcyc_tdvs<<8 | tdvs));  				ATAPI_SET_ULTRA_TIM_2(base, (tmli<<8 | tss));  				ATAPI_SET_ULTRA_TIM_3(base, (trp<<8 | tzah)); - -				/* Enable host ATAPI Untra DMA interrupts */ -				ATAPI_SET_INT_MASK(base, -					ATAPI_GET_INT_MASK(base) -					| UDMAIN_DONE_MASK -					| UDMAOUT_DONE_MASK -					| UDMAIN_TERM_MASK -					| UDMAOUT_TERM_MASK);  			}  		}  	} @@ -470,10 +464,6 @@ static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev)  			ATAPI_SET_MULTI_TIM_0(base, (tm<<8 | td));  			ATAPI_SET_MULTI_TIM_1(base, (tkr<<8 | tkw));  			ATAPI_SET_MULTI_TIM_2(base, (teoc<<8 | th)); - -			/* Enable host ATAPI Multi DMA interrupts */ -			ATAPI_SET_INT_MASK(base, ATAPI_GET_INT_MASK(base) -				| MULTI_DONE_MASK | MULTI_TERM_MASK);  			SSYNC();  		}  	} @@ -841,79 +831,61 @@ static void bfin_set_devctl(struct ata_port *ap, u8 ctl)  static void bfin_bmdma_setup(struct ata_queued_cmd *qc)  { -	unsigned short config = WDSIZE_16; +	struct ata_port *ap = qc->ap; +	struct dma_desc_array *dma_desc_cpu = (struct dma_desc_array *)ap->bmdma_prd; +	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; +	unsigned short config = DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_16 | DMAEN;  	struct scatterlist *sg;  	unsigned int si; +	unsigned int channel; +	unsigned int dir; +	unsigned int size = 0;  	dev_dbg(qc->ap->dev, "in atapi dma setup\n");  	/* Program the ATA_CTRL register with dir */  	if (qc->tf.flags & ATA_TFLAG_WRITE) { -		/* fill the ATAPI DMA controller */ -		set_dma_config(CH_ATAPI_TX, config); -		set_dma_x_modify(CH_ATAPI_TX, 2); -		for_each_sg(qc->sg, sg, qc->n_elem, si) { -			set_dma_start_addr(CH_ATAPI_TX, sg_dma_address(sg)); -			set_dma_x_count(CH_ATAPI_TX, sg_dma_len(sg) >> 1); -		} +		channel = CH_ATAPI_TX; +		dir = DMA_TO_DEVICE;  	} else { +		channel = CH_ATAPI_RX; +		dir = DMA_FROM_DEVICE;  		config |= WNR; -		/* fill the ATAPI DMA controller */ -		set_dma_config(CH_ATAPI_RX, config); -		set_dma_x_modify(CH_ATAPI_RX, 2); -		for_each_sg(qc->sg, sg, qc->n_elem, si) { -			set_dma_start_addr(CH_ATAPI_RX, sg_dma_address(sg)); -			set_dma_x_count(CH_ATAPI_RX, sg_dma_len(sg) >> 1); -		}  	} -} -/** - *	bfin_bmdma_start - Start an IDE DMA transaction - *	@qc: Info associated with this ATA transaction. - * - *	Note: Original code is ata_bmdma_start(). - */ +	dma_map_sg(ap->dev, qc->sg, qc->n_elem, dir); -static void bfin_bmdma_start(struct ata_queued_cmd *qc) -{ -	struct ata_port *ap = qc->ap; -	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; -	struct scatterlist *sg; -	unsigned int si; +	/* fill the ATAPI DMA controller */ +	for_each_sg(qc->sg, sg, qc->n_elem, si) { +		dma_desc_cpu[si].start_addr = sg_dma_address(sg); +		dma_desc_cpu[si].cfg = config; +		dma_desc_cpu[si].x_count = sg_dma_len(sg) >> 1; +		dma_desc_cpu[si].x_modify = 2; +		size += sg_dma_len(sg); +	} -	dev_dbg(qc->ap->dev, "in atapi dma start\n"); -	if (!(ap->udma_mask || ap->mwdma_mask)) -		return; +	/* Set the last descriptor to stop mode */ +	dma_desc_cpu[qc->n_elem - 1].cfg &= ~(DMAFLOW | NDSIZE); -	/* start ATAPI DMA controller*/ -	if (qc->tf.flags & ATA_TFLAG_WRITE) { -		/* -		 * On blackfin arch, uncacheable memory is not -		 * allocated with flag GFP_DMA. DMA buffer from -		 * common kenel code should be flushed if WB -		 * data cache is enabled. Otherwise, this loop -		 * is an empty loop and optimized out. -		 */ -		for_each_sg(qc->sg, sg, qc->n_elem, si) { -			flush_dcache_range(sg_dma_address(sg), -				sg_dma_address(sg) + sg_dma_len(sg)); -		} -		enable_dma(CH_ATAPI_TX); -		dev_dbg(qc->ap->dev, "enable udma write\n"); +	flush_dcache_range((unsigned int)dma_desc_cpu, +		(unsigned int)dma_desc_cpu + +			qc->n_elem * sizeof(struct dma_desc_array)); + +	/* Enable ATA DMA operation*/ +	set_dma_curr_desc_addr(channel, (unsigned long *)ap->bmdma_prd_dma); +	set_dma_x_count(channel, 0); +	set_dma_x_modify(channel, 0); +	set_dma_config(channel, config); + +	SSYNC(); -		/* Send ATA DMA write command */ -		bfin_exec_command(ap, &qc->tf); +	/* Send ATA DMA command */ +	bfin_exec_command(ap, &qc->tf); +	if (qc->tf.flags & ATA_TFLAG_WRITE) {  		/* set ATA DMA write direction */  		ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base)  			| XFER_DIR));  	} else { -		enable_dma(CH_ATAPI_RX); -		dev_dbg(qc->ap->dev, "enable udma read\n"); - -		/* Send ATA DMA read command */ -		bfin_exec_command(ap, &qc->tf); -  		/* set ATA DMA read direction */  		ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base)  			& ~XFER_DIR)); @@ -925,12 +897,28 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)  	/* Set ATAPI state machine contorl in terminate sequence */  	ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | END_ON_TERM); -	/* Set transfer length to buffer len */ -	for_each_sg(qc->sg, sg, qc->n_elem, si) { -		ATAPI_SET_XFER_LEN(base, (sg_dma_len(sg) >> 1)); -	} +	/* Set transfer length to the total size of sg buffers */ +	ATAPI_SET_XFER_LEN(base, size >> 1); +} -	/* Enable ATA DMA operation*/ +/** + *	bfin_bmdma_start - Start an IDE DMA transaction + *	@qc: Info associated with this ATA transaction. + * + *	Note: Original code is ata_bmdma_start(). + */ + +static void bfin_bmdma_start(struct ata_queued_cmd *qc) +{ +	struct ata_port *ap = qc->ap; +	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; + +	dev_dbg(qc->ap->dev, "in atapi dma start\n"); + +	if (!(ap->udma_mask || ap->mwdma_mask)) +		return; + +	/* start ATAPI transfer*/  	if (ap->udma_mask)  		ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base)  			| ULTRA_START); @@ -947,34 +935,23 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)  static void bfin_bmdma_stop(struct ata_queued_cmd *qc)  {  	struct ata_port *ap = qc->ap; -	struct scatterlist *sg; -	unsigned int si; +	unsigned int dir;  	dev_dbg(qc->ap->dev, "in atapi dma stop\n"); +  	if (!(ap->udma_mask || ap->mwdma_mask))  		return;  	/* stop ATAPI DMA controller*/ -	if (qc->tf.flags & ATA_TFLAG_WRITE) +	if (qc->tf.flags & ATA_TFLAG_WRITE) { +		dir = DMA_TO_DEVICE;  		disable_dma(CH_ATAPI_TX); -	else { +	} else { +		dir = DMA_FROM_DEVICE;  		disable_dma(CH_ATAPI_RX); -		if (ap->hsm_task_state & HSM_ST_LAST) { -			/* -			 * On blackfin arch, uncacheable memory is not -			 * allocated with flag GFP_DMA. DMA buffer from -			 * common kenel code should be invalidated if -			 * data cache is enabled. Otherwise, this loop -			 * is an empty loop and optimized out. -			 */ -			for_each_sg(qc->sg, sg, qc->n_elem, si) { -				invalidate_dcache_range( -					sg_dma_address(sg), -					sg_dma_address(sg) -					+ sg_dma_len(sg)); -			} -		}  	} + +	dma_unmap_sg(ap->dev, qc->sg, qc->n_elem, dir);  }  /** @@ -1129,7 +1106,7 @@ static int bfin_softreset(struct ata_link *link, unsigned int *classes,  	/* issue bus reset */  	err_mask = bfin_bus_softreset(ap, devmask);  	if (err_mask) { -		ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n", +		ata_port_err(ap, "SRST failed (err_mask=0x%x)\n",  				err_mask);  		return -EIO;  	} @@ -1153,15 +1130,11 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)  {  	unsigned char host_stat = 0;  	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; -	unsigned short int_status = ATAPI_GET_INT_STATUS(base); -	if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON)) +	if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON | ULTRA_XFER_ON))  		host_stat |= ATA_DMA_ACTIVE; -	if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT| -		ATAPI_DEV_INT)) +	if (ATAPI_GET_INT_STATUS(base) & ATAPI_DEV_INT)  		host_stat |= ATA_DMA_INTR; -	if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT)) -		host_stat |= ATA_DMA_ERR|ATA_DMA_INTR;  	dev_dbg(ap->dev, "ATAPI: host_stat=0x%x\n", host_stat); @@ -1276,6 +1249,11 @@ static void bfin_port_stop(struct ata_port *ap)  {  	dev_dbg(ap->dev, "in atapi port stop\n");  	if (ap->udma_mask != 0 || ap->mwdma_mask != 0) { +		dma_free_coherent(ap->dev, +			BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array), +			ap->bmdma_prd, +			ap->bmdma_prd_dma); +  		free_dma(CH_ATAPI_RX);  		free_dma(CH_ATAPI_TX);  	} @@ -1287,14 +1265,29 @@ static int bfin_port_start(struct ata_port *ap)  	if (!(ap->udma_mask || ap->mwdma_mask))  		return 0; +	ap->bmdma_prd = dma_alloc_coherent(ap->dev, +				BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array), +				&ap->bmdma_prd_dma, +				GFP_KERNEL); + +	if (ap->bmdma_prd == NULL) { +		dev_info(ap->dev, "Unable to allocate DMA descriptor array.\n"); +		goto out; +	} +  	if (request_dma(CH_ATAPI_RX, "BFIN ATAPI RX DMA") >= 0) {  		if (request_dma(CH_ATAPI_TX,  			"BFIN ATAPI TX DMA") >= 0)  			return 0;  		free_dma(CH_ATAPI_RX); +		dma_free_coherent(ap->dev, +			BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array), +			ap->bmdma_prd, +			ap->bmdma_prd_dma);  	} +out:  	ap->udma_mask = 0;  	ap->mwdma_mask = 0;  	dev_err(ap->dev, "Unable to request ATAPI DMA!" @@ -1342,7 +1335,7 @@ static unsigned int bfin_ata_host_intr(struct ata_port *ap,  			ap->ops->bmdma_stop(qc);  			if (unlikely(host_stat & ATA_DMA_ERR)) { -				/* error when transfering data to/from memory */ +				/* error when transferring data to/from memory */  				qc->err_mask |= AC_ERR_HOST_BUS;  				ap->hsm_task_state = HSM_ST_ERR;  			} @@ -1382,7 +1375,7 @@ idle_irq:  #ifdef ATA_IRQ_TRAP  	if ((ap->stats.idle_irq % 1000) == 0) {  		ap->ops->irq_ack(ap, 0); /* debug trap */ -		ata_port_printk(ap, KERN_WARNING, "irq trap\n"); +		ata_port_warn(ap, "irq trap\n");  		return 1;  	}  #endif @@ -1416,7 +1409,7 @@ static irqreturn_t bfin_ata_interrupt(int irq, void *dev_instance)  static struct scsi_host_template bfin_sht = {  	ATA_BASE_SHT(DRV_NAME), -	.sg_tablesize		= SG_NONE, +	.sg_tablesize		= BFIN_MAX_SG_SEGMENTS,  	.dma_boundary		= ATA_DMA_BOUNDARY,  }; @@ -1454,9 +1447,7 @@ static struct ata_port_operations bfin_pata_ops = {  static struct ata_port_info bfin_port_info[] = {  	{ -		.flags		= ATA_FLAG_SLAVE_POSS -				| ATA_FLAG_MMIO -				| ATA_FLAG_NO_LEGACY, +		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4,  		.mwdma_mask	= 0,  		.udma_mask	= 0, @@ -1547,7 +1538,7 @@ static unsigned short atapi_io_port[] = {   *		- IRQ	   (IORESOURCE_IRQ)   *   */ -static int __devinit bfin_atapi_probe(struct platform_device *pdev) +static int bfin_atapi_probe(struct platform_device *pdev)  {  	int board_idx = 0;  	struct resource *res; @@ -1605,7 +1596,7 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	dev_set_drvdata(&pdev->dev, host); +	platform_set_drvdata(pdev, host);  	return 0;  } @@ -1617,23 +1608,21 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)   *	A bfin atapi device has been unplugged. Perform the needed   *	cleanup. Also called on module unload for any active devices.   */ -static int __devexit bfin_atapi_remove(struct platform_device *pdev) +static int bfin_atapi_remove(struct platform_device *pdev)  { -	struct device *dev = &pdev->dev; -	struct ata_host *host = dev_get_drvdata(dev); +	struct ata_host *host = platform_get_drvdata(pdev);  	ata_host_detach(host); -	dev_set_drvdata(&pdev->dev, NULL);  	peripheral_free_list(atapi_io_port);  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int bfin_atapi_suspend(struct platform_device *pdev, pm_message_t state)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = platform_get_drvdata(pdev);  	if (host)  		return ata_host_suspend(host, state);  	else @@ -1642,7 +1631,7 @@ static int bfin_atapi_suspend(struct platform_device *pdev, pm_message_t state)  static int bfin_atapi_resume(struct platform_device *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = platform_get_drvdata(pdev);  	int ret;  	if (host) { @@ -1663,7 +1652,7 @@ static int bfin_atapi_resume(struct platform_device *pdev)  static struct platform_driver bfin_atapi_driver = {  	.probe			= bfin_atapi_probe, -	.remove			= __devexit_p(bfin_atapi_remove), +	.remove			= bfin_atapi_remove,  	.suspend		= bfin_atapi_suspend,  	.resume			= bfin_atapi_resume,  	.driver = { diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c index 549d28dbf90..c47caa807fa 100644 --- a/drivers/ata/pata_cmd640.c +++ b/drivers/ata/pata_cmd640.c @@ -15,7 +15,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/gfp.h> @@ -232,10 +231,10 @@ static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  	return ata_pci_sff_init_one(pdev, ppi, &cmd640_sht, NULL, 0);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int cmd640_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -257,27 +256,16 @@ static struct pci_driver cmd640_pci_driver = {  	.id_table	= cmd640,  	.probe 		= cmd640_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= cmd640_reinit_one,  #endif  }; -static int __init cmd640_init(void) -{ -	return pci_register_driver(&cmd640_pci_driver); -} - -static void __exit cmd640_exit(void) -{ -	pci_unregister_driver(&cmd640_pci_driver); -} +module_pci_driver(cmd640_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for CMD640 PATA controllers");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, cmd640);  MODULE_VERSION(DRV_VERSION); - -module_init(cmd640_init); -module_exit(cmd640_exit); diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index 905ff76d3cb..13ca5883285 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -3,6 +3,7 @@   *			  (C) 2005 Red Hat Inc   *			  Alan Cox <alan@lxorguk.ukuu.org.uk>   *			  (C) 2009-2010 Bartlomiej Zolnierkiewicz + *			  (C) 2012 MontaVista Software, LLC <source@mvista.com>   *   * Based upon   * linux/drivers/ide/pci/cmd64x.c		Version 1.30	Sept 10, 2002 @@ -25,14 +26,13 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h>  #include <linux/libata.h>  #define DRV_NAME "pata_cmd64x" -#define DRV_VERSION "0.2.5" +#define DRV_VERSION "0.2.18"  /*   * CMD64x specific registers definition. @@ -41,6 +41,9 @@  enum {  	CFR 		= 0x50,  		CFR_INTR_CH0  = 0x04, +	CNTRL		= 0x51, +		CNTRL_CH0     = 0x04, +		CNTRL_CH1     = 0x08,  	CMDTIM 		= 0x52,  	ARTTIM0 	= 0x53,  	DRWTIM0 	= 0x54, @@ -79,7 +82,7 @@ static int cmd648_cable_detect(struct ata_port *ap)  }  /** - *	cmd64x_set_piomode	-	set PIO and MWDMA timing + *	cmd64x_set_timing	-	set PIO and MWDMA timing   *	@ap: ATA interface   *	@adev: ATA device   *	@mode: mode @@ -226,28 +229,85 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev)  }  /** - *	cmd648_dma_stop	-	DMA stop callback - *	@qc: Command in progress + *	cmd64x_sff_irq_check	-	check IDE interrupt + *	@ap: ATA interface   * - *	DMA has completed. + *	Check IDE interrupt in CFR/ARTTIM23 registers.   */ -static void cmd648_bmdma_stop(struct ata_queued_cmd *qc) +static bool cmd64x_sff_irq_check(struct ata_port *ap)  { -	struct ata_port *ap = qc->ap;  	struct pci_dev *pdev = to_pci_dev(ap->host->dev); -	u8 dma_intr; -	int dma_mask = ap->port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; -	int dma_reg = ap->port_no ? ARTTIM23 : CFR; +	int irq_mask = ap->port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; +	int irq_reg  = ap->port_no ? ARTTIM23 : CFR; +	u8 irq_stat; -	ata_bmdma_stop(qc); +	/* NOTE: reading the register should clear the interrupt */ +	pci_read_config_byte(pdev, irq_reg, &irq_stat); + +	return irq_stat & irq_mask; +} + +/** + *	cmd64x_sff_irq_clear	-	clear IDE interrupt + *	@ap: ATA interface + * + *	Clear IDE interrupt in CFR/ARTTIM23 and DMA status registers. + */ + +static void cmd64x_sff_irq_clear(struct ata_port *ap) +{ +	struct pci_dev *pdev = to_pci_dev(ap->host->dev); +	int irq_reg = ap->port_no ? ARTTIM23 : CFR; +	u8 irq_stat; + +	ata_bmdma_irq_clear(ap); + +	/* Reading the register should be enough to clear the interrupt */ +	pci_read_config_byte(pdev, irq_reg, &irq_stat); +} + +/** + *	cmd648_sff_irq_check	-	check IDE interrupt + *	@ap: ATA interface + * + *	Check IDE interrupt in MRDMODE register. + */ + +static bool cmd648_sff_irq_check(struct ata_port *ap) +{ +	struct pci_dev *pdev = to_pci_dev(ap->host->dev); +	unsigned long base = pci_resource_start(pdev, 4); +	int irq_mask = ap->port_no ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; +	u8 mrdmode = inb(base + 1); -	pci_read_config_byte(pdev, dma_reg, &dma_intr); -	pci_write_config_byte(pdev, dma_reg, dma_intr | dma_mask); +	return mrdmode & irq_mask;  }  /** - *	cmd646r1_dma_stop	-	DMA stop callback + *	cmd648_sff_irq_clear	-	clear IDE interrupt + *	@ap: ATA interface + * + *	Clear IDE interrupt in MRDMODE and DMA status registers. + */ + +static void cmd648_sff_irq_clear(struct ata_port *ap) +{ +	struct pci_dev *pdev = to_pci_dev(ap->host->dev); +	unsigned long base = pci_resource_start(pdev, 4); +	int irq_mask = ap->port_no ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; +	u8 mrdmode; + +	ata_bmdma_irq_clear(ap); + +	/* Clear this port's interrupt bit (leaving the other port alone) */ +	mrdmode  = inb(base + 1); +	mrdmode &= ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1); +	outb(mrdmode | irq_mask, base + 1); +} + +/** + *	cmd646r1_bmdma_stop	-	DMA stop callback   *	@qc: Command in progress   *   *	Stub for now while investigating the r1 quirk in the old driver. @@ -270,24 +330,52 @@ static const struct ata_port_operations cmd64x_base_ops = {  static struct ata_port_operations cmd64x_port_ops = {  	.inherits	= &cmd64x_base_ops, +	.sff_irq_check	= cmd64x_sff_irq_check, +	.sff_irq_clear	= cmd64x_sff_irq_clear,  	.cable_detect	= ata_cable_40wire,  };  static struct ata_port_operations cmd646r1_port_ops = {  	.inherits	= &cmd64x_base_ops, +	.sff_irq_check	= cmd64x_sff_irq_check, +	.sff_irq_clear	= cmd64x_sff_irq_clear,  	.bmdma_stop	= cmd646r1_bmdma_stop,  	.cable_detect	= ata_cable_40wire,  }; +static struct ata_port_operations cmd646r3_port_ops = { +	.inherits	= &cmd64x_base_ops, +	.sff_irq_check	= cmd648_sff_irq_check, +	.sff_irq_clear	= cmd648_sff_irq_clear, +	.cable_detect	= ata_cable_40wire, +}; +  static struct ata_port_operations cmd648_port_ops = {  	.inherits	= &cmd64x_base_ops, -	.bmdma_stop	= cmd648_bmdma_stop, +	.sff_irq_check	= cmd648_sff_irq_check, +	.sff_irq_clear	= cmd648_sff_irq_clear,  	.cable_detect	= cmd648_cable_detect,  }; +static void cmd64x_fixup(struct pci_dev *pdev) +{ +	u8 mrdmode; + +	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); +	pci_read_config_byte(pdev, MRDMODE, &mrdmode); +	mrdmode &= ~0x30;	/* IRQ set up */ +	mrdmode |= 0x02;	/* Memory read line enable */ +	pci_write_config_byte(pdev, MRDMODE, mrdmode); + +	/* PPC specific fixup copied from old driver */ +#ifdef CONFIG_PPC +	pci_write_config_byte(pdev, UDIDETCR0, 0xF0); +#endif +} +  static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  { -	static const struct ata_port_info cmd_info[6] = { +	static const struct ata_port_info cmd_info[7] = {  		{	/* CMD 643 - no UDMA */  			.flags = ATA_FLAG_SLAVE_POSS,  			.pio_mask = ATA_PIO4, @@ -300,12 +388,18 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  			.mwdma_mask = ATA_MWDMA2,  			.port_ops = &cmd64x_port_ops  		}, -		{	/* CMD 646 with working UDMA */ +		{	/* CMD 646U with broken UDMA */ +			.flags = ATA_FLAG_SLAVE_POSS, +			.pio_mask = ATA_PIO4, +			.mwdma_mask = ATA_MWDMA2, +			.port_ops = &cmd646r3_port_ops +		}, +		{	/* CMD 646U2 with working UDMA */  			.flags = ATA_FLAG_SLAVE_POSS,  			.pio_mask = ATA_PIO4,  			.mwdma_mask = ATA_MWDMA2,  			.udma_mask = ATA_UDMA2, -			.port_ops = &cmd64x_port_ops +			.port_ops = &cmd646r3_port_ops  		},  		{	/* CMD 646 rev 1  */  			.flags = ATA_FLAG_SLAVE_POSS, @@ -328,9 +422,19 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  			.port_ops = &cmd648_port_ops  		}  	}; -	const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL }; -	u8 mrdmode; +	const struct ata_port_info *ppi[] = { +		&cmd_info[id->driver_data], +		&cmd_info[id->driver_data], +		NULL +	}; +	u8 reg;  	int rc; +	struct pci_dev *bridge = pdev->bus->self; +	/* mobility split bridges don't report enabled ports correctly */ +	int port_ok = !(bridge && bridge->vendor == +			PCI_VENDOR_ID_MOBILITY_ELECTRONICS); +	/* all (with exceptions below) apart from 643 have CNTRL_CH0 bit */ +	int cntrl_ch0_ok = (id->driver_data != 0);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -339,50 +443,62 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  	if (id->driver_data == 0)	/* 643 */  		ata_pci_bmdma_clear_simplex(pdev); -	if (pdev->device == PCI_DEVICE_ID_CMD_646) { -		/* Does UDMA work ? */ -		if (pdev->revision > 4) -			ppi[0] = &cmd_info[2]; -		/* Early rev with other problems ? */ -		else if (pdev->revision == 1) +	if (pdev->device == PCI_DEVICE_ID_CMD_646) +		switch (pdev->revision) { +		/* UDMA works since rev 5 */ +		default:  			ppi[0] = &cmd_info[3]; -	} +			ppi[1] = &cmd_info[3]; +			break; +		/* Interrupts in MRDMODE since rev 3 */ +		case 3: +		case 4: +			ppi[0] = &cmd_info[2]; +			ppi[1] = &cmd_info[2]; +			break; +		/* Rev 1 with other problems? */ +		case 1: +			ppi[0] = &cmd_info[4]; +			ppi[1] = &cmd_info[4]; +			/* FALL THRU */ +		/* Early revs have no CNTRL_CH0 */ +		case 2: +		case 0: +			cntrl_ch0_ok = 0; +			break; +		} -	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); -	pci_read_config_byte(pdev, MRDMODE, &mrdmode); -	mrdmode &= ~ 0x30;	/* IRQ set up */ -	mrdmode |= 0x02;	/* Memory read line enable */ -	pci_write_config_byte(pdev, MRDMODE, mrdmode); +	cmd64x_fixup(pdev); -	/* Force PIO 0 here.. */ +	/* check for enabled ports */ +	pci_read_config_byte(pdev, CNTRL, ®); +	if (!port_ok) +		dev_notice(&pdev->dev, "Mobility Bridge detected, ignoring CNTRL port enable/disable\n"); +	if (port_ok && cntrl_ch0_ok && !(reg & CNTRL_CH0)) { +		dev_notice(&pdev->dev, "Primary port is disabled\n"); +		ppi[0] = &ata_dummy_port_info; -	/* PPC specific fixup copied from old driver */ -#ifdef CONFIG_PPC -	pci_write_config_byte(pdev, UDIDETCR0, 0xF0); -#endif +	} +	if (port_ok && !(reg & CNTRL_CH1)) { +		dev_notice(&pdev->dev, "Secondary port is disabled\n"); +		ppi[1] = &ata_dummy_port_info; +	}  	return ata_pci_bmdma_init_one(pdev, ppi, &cmd64x_sht, NULL, 0);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int cmd64x_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); -	u8 mrdmode; +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev);  	if (rc)  		return rc; -	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); -	pci_read_config_byte(pdev, MRDMODE, &mrdmode); -	mrdmode &= ~ 0x30;	/* IRQ set up */ -	mrdmode |= 0x02;	/* Memory read line enable */ -	pci_write_config_byte(pdev, MRDMODE, mrdmode); -#ifdef CONFIG_PPC -	pci_write_config_byte(pdev, UDIDETCR0, 0xF0); -#endif +	cmd64x_fixup(pdev); +  	ata_host_resume(host);  	return 0;  } @@ -391,8 +507,8 @@ static int cmd64x_reinit_one(struct pci_dev *pdev)  static const struct pci_device_id cmd64x[] = {  	{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 },  	{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 }, -	{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_648), 4 }, -	{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_649), 5 }, +	{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_648), 5 }, +	{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_649), 6 },  	{ },  }; @@ -402,27 +518,16 @@ static struct pci_driver cmd64x_pci_driver = {  	.id_table	= cmd64x,  	.probe 		= cmd64x_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= cmd64x_reinit_one,  #endif  }; -static int __init cmd64x_init(void) -{ -	return pci_register_driver(&cmd64x_pci_driver); -} - -static void __exit cmd64x_exit(void) -{ -	pci_unregister_driver(&cmd64x_pci_driver); -} +module_pci_driver(cmd64x_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for CMD64x series PATA controllers");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, cmd64x);  MODULE_VERSION(DRV_VERSION); - -module_init(cmd64x_init); -module_exit(cmd64x_exit); diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 030952f1f97..d65cb9d2fa8 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -29,12 +29,11 @@   * General Public License for more details.   *   * Documentation: - *	Not publically available. + *	Not publicly available.   */  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -115,7 +114,7 @@ static struct ata_port_operations cs5520_port_ops = {  	.set_piomode		= cs5520_set_piomode,  }; -static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id) +static int cs5520_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  {  	static const unsigned int cmd_port[] = { 0x1F0, 0x170 };  	static const unsigned int ctl_port[] = { 0x3F6, 0x376 }; @@ -149,8 +148,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi  		ppi[1] = π  	if ((pcicfg & 0x40) == 0) { -		dev_printk(KERN_WARNING, &pdev->dev, -			   "DMA mode disabled. Enabling.\n"); +		dev_warn(&pdev->dev, "DMA mode disabled. Enabling.\n");  		pci_write_config_byte(pdev, 0x60, pcicfg | 0x40);  	} @@ -231,7 +229,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi  	return ata_host_register(host, &cs5520_sht);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  /**   *	cs5520_reinit_one	-	device resume   *	@pdev: PCI device @@ -242,7 +240,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi  static int cs5520_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	u8 pcicfg;  	int rc; @@ -270,7 +268,7 @@ static int cs5520_reinit_one(struct pci_dev *pdev)  static int cs5520_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc = 0;  	rc = ata_host_suspend(host, mesg); @@ -280,7 +278,7 @@ static int cs5520_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)  	pci_save_state(pdev);  	return 0;  } -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */  /* For now keep DMA off. We can set it for all but A rev CS5510 once the     core ATA code can handle it */ @@ -297,28 +295,16 @@ static struct pci_driver cs5520_pci_driver = {  	.id_table	= pata_cs5520,  	.probe 		= cs5520_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= cs5520_pci_device_suspend,  	.resume		= cs5520_reinit_one,  #endif  }; -static int __init cs5520_init(void) -{ -	return pci_register_driver(&cs5520_pci_driver); -} - -static void __exit cs5520_exit(void) -{ -	pci_unregister_driver(&cs5520_pci_driver); -} +module_pci_driver(cs5520_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for Cyrix CS5510/5520");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, pata_cs5520);  MODULE_VERSION(DRV_VERSION); - -module_init(cs5520_init); -module_exit(cs5520_exit); - diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index f792330f0d8..48ae4b43447 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c @@ -26,7 +26,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -327,10 +326,10 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  	return ata_pci_bmdma_init_one(pdev, ppi, &cs5530_sht, NULL, 0);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int cs5530_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -344,7 +343,7 @@ static int cs5530_reinit_one(struct pci_dev *pdev)  	ata_host_resume(host);  	return 0;  } -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */  static const struct pci_device_id cs5530[] = {  	{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), }, @@ -357,27 +356,16 @@ static struct pci_driver cs5530_pci_driver = {  	.id_table	= cs5530,  	.probe 		= cs5530_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= cs5530_reinit_one,  #endif  }; -static int __init cs5530_init(void) -{ -	return pci_register_driver(&cs5530_pci_driver); -} - -static void __exit cs5530_exit(void) -{ -	pci_unregister_driver(&cs5530_pci_driver); -} +module_pci_driver(cs5530_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for the Cyrix/NS/AMD 5530");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, cs5530);  MODULE_VERSION(DRV_VERSION); - -module_init(cs5530_init); -module_exit(cs5530_exit); diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index 03a93186aa1..97584e8456d 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c @@ -31,14 +31,13 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h>  #include <linux/libata.h>  #include <asm/msr.h> -#define DRV_NAME	"cs5535" +#define DRV_NAME	"pata_cs5535"  #define DRV_VERSION	"0.2.12"  /* @@ -67,8 +66,6 @@  #define CS5535_CABLE_DETECT    0x48 -#define CS5535_BAD_PIO(timings) ( (timings&~0x80000000UL)==0x00009172 ) -  /**   *	cs5535_cable_detect	-	detect cable type   *	@ap: Port to detect on @@ -188,16 +185,6 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)  	};  	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; -	u32 timings, dummy; - -	/* Check the BIOS set the initial timing clock. If not set the -	   timings for PIO0 */ -	rdmsr(ATAC_CH0D0_PIO, timings, dummy); -	if (CS5535_BAD_PIO(timings)) -		wrmsr(ATAC_CH0D0_PIO, 0xF7F4F7F4UL, 0); -	rdmsr(ATAC_CH0D1_PIO, timings, dummy); -	if (CS5535_BAD_PIO(timings)) -		wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0);  	return ata_pci_bmdma_init_one(dev, ppi, &cs5535_sht, NULL, 0);  } @@ -213,27 +200,16 @@ static struct pci_driver cs5535_pci_driver = {  	.id_table	= cs5535,  	.probe 		= cs5535_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init cs5535_init(void) -{ -	return pci_register_driver(&cs5535_pci_driver); -} - -static void __exit cs5535_exit(void) -{ -	pci_unregister_driver(&cs5535_pci_driver); -} +module_pci_driver(cs5535_pci_driver);  MODULE_AUTHOR("Alan Cox, Jens Altmann, Wolfgan Zuleger, Alexander Kiausch"); -MODULE_DESCRIPTION("low-level driver for the NS/AMD 5530"); +MODULE_DESCRIPTION("low-level driver for the NS/AMD 5535");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, cs5535);  MODULE_VERSION(DRV_VERSION); - -module_init(cs5535_init); -module_exit(cs5535_exit); diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c index 21ee23f89e8..6c15a554efb 100644 --- a/drivers/ata/pata_cs5536.c +++ b/drivers/ata/pata_cs5536.c @@ -1,6 +1,7 @@  /*   * pata_cs5536.c	- CS5536 PATA for new ATA layer   *			  (C) 2007 Martin K. Petersen <mkp@mkp.net> + *			  (C) 2011 Bartlomiej Zolnierkiewicz   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License version 2 as @@ -32,35 +33,39 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/libata.h>  #include <scsi/scsi_host.h> +#include <linux/dmi.h> + +#ifdef CONFIG_X86_32  #include <asm/msr.h> +static int use_msr; +module_param_named(msr, use_msr, int, 0644); +MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)"); +#else +#undef rdmsr	/* avoid accidental MSR usage on, e.g. x86-64 */ +#undef wrmsr +#define rdmsr(x, y, z) do { } while (0) +#define wrmsr(x, y, z) do { } while (0) +#define use_msr 0 +#endif  #define DRV_NAME	"pata_cs5536" -#define DRV_VERSION	"0.0.7" +#define DRV_VERSION	"0.0.8"  enum { -	CFG			= 0, -	DTC			= 1, -	CAST			= 2, -	ETC			= 3, - -	MSR_IDE_BASE		= 0x51300000, -	MSR_IDE_CFG		= (MSR_IDE_BASE + 0x10), -	MSR_IDE_DTC		= (MSR_IDE_BASE + 0x12), -	MSR_IDE_CAST		= (MSR_IDE_BASE + 0x13), -	MSR_IDE_ETC		= (MSR_IDE_BASE + 0x14), - +	MSR_IDE_CFG		= 0x51300010,  	PCI_IDE_CFG		= 0x40, -	PCI_IDE_DTC		= 0x48, -	PCI_IDE_CAST		= 0x4c, -	PCI_IDE_ETC		= 0x50, -	IDE_CFG_CHANEN		= 0x2, -	IDE_CFG_CABLE		= 0x10000, +	CFG			= 0, +	DTC			= 2, +	CAST			= 3, +	ETC			= 4, + +	IDE_CFG_CHANEN		= (1 << 1), +	IDE_CFG_CABLE		= (1 << 17) | (1 << 16),  	IDE_D0_SHIFT		= 24,  	IDE_D1_SHIFT		= 16, @@ -72,47 +77,65 @@ enum {  	IDE_CAST_CMD_MASK	= 0xff,  	IDE_CAST_CMD_SHIFT	= 24, -	IDE_ETC_NODMA		= 0x03, +	IDE_ETC_UDMA_MASK	= 0xc0,  }; -static int use_msr; - -static const u32 msr_reg[4] = { -	MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC, -}; - -static const u8 pci_reg[4] = { -	PCI_IDE_CFG, PCI_IDE_DTC, PCI_IDE_CAST, PCI_IDE_ETC, +/* Some Bachmann OT200 devices have a non working UDMA support due a + * missing resistor. + */ +static const struct dmi_system_id udma_quirk_dmi_table[] = { +	{ +		.ident = "Bachmann electronic OT200", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Bachmann electronic"), +			DMI_MATCH(DMI_PRODUCT_NAME, "OT200"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "1") +		}, +	}, +	{ }  }; -static inline int cs5536_read(struct pci_dev *pdev, int reg, u32 *val) +static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)  {  	if (unlikely(use_msr)) { -		u32 dummy; +		u32 dummy __maybe_unused; -		rdmsr(msr_reg[reg], *val, dummy); +		rdmsr(MSR_IDE_CFG + reg, *val, dummy);  		return 0;  	} -	return pci_read_config_dword(pdev, pci_reg[reg], val); +	return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);  } -static inline int cs5536_write(struct pci_dev *pdev, int reg, int val) +static int cs5536_write(struct pci_dev *pdev, int reg, int val)  {  	if (unlikely(use_msr)) { -		wrmsr(msr_reg[reg], val, 0); +		wrmsr(MSR_IDE_CFG + reg, val, 0);  		return 0;  	} -	return pci_write_config_dword(pdev, pci_reg[reg], val); +	return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); +} + +static void cs5536_program_dtc(struct ata_device *adev, u8 tim) +{ +	struct pci_dev *pdev = to_pci_dev(adev->link->ap->host->dev); +	int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; +	u32 dtc; + +	cs5536_read(pdev, DTC, &dtc); +	dtc &= ~(IDE_DRV_MASK << dshift); +	dtc |= tim << dshift; +	cs5536_write(pdev, DTC, dtc);  }  /**   *	cs5536_cable_detect	-	detect cable type   *	@ap: Port to detect on   * - *	Perform cable detection for ATA66 capable cable. Return a libata - *	cable type. + *	Perform cable detection for ATA66 capable cable. + * + *	Returns a cable type.   */  static int cs5536_cable_detect(struct ata_port *ap) @@ -122,7 +145,7 @@ static int cs5536_cable_detect(struct ata_port *ap)  	cs5536_read(pdev, CFG, &cfg); -	if (cfg & (IDE_CFG_CABLE << ap->port_no)) +	if (cfg & IDE_CFG_CABLE)  		return ATA_CBL_PATA80;  	else  		return ATA_CBL_PATA40; @@ -152,19 +175,15 @@ static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev)  	struct ata_device *pair = ata_dev_pair(adev);  	int mode = adev->pio_mode - XFER_PIO_0;  	int cmdmode = mode; -	int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT;  	int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; -	u32 dtc, cast, etc; +	u32 cast;  	if (pair)  		cmdmode = min(mode, pair->pio_mode - XFER_PIO_0); -	cs5536_read(pdev, DTC, &dtc); -	cs5536_read(pdev, CAST, &cast); -	cs5536_read(pdev, ETC, &etc); +	cs5536_program_dtc(adev, drv_timings[mode]); -	dtc &= ~(IDE_DRV_MASK << dshift); -	dtc |= drv_timings[mode] << dshift; +	cs5536_read(pdev, CAST, &cast);  	cast &= ~(IDE_CAST_DRV_MASK << cshift);  	cast |= addr_timings[mode] << cshift; @@ -172,12 +191,7 @@ static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev)  	cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT);  	cast |= cmd_timings[cmdmode] << IDE_CAST_CMD_SHIFT; -	etc &= ~(IDE_DRV_MASK << dshift); -	etc |= IDE_ETC_NODMA << dshift; - -	cs5536_write(pdev, DTC, dtc);  	cs5536_write(pdev, CAST, cast); -	cs5536_write(pdev, ETC, etc);  }  /** @@ -198,25 +212,21 @@ static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev)  	};  	struct pci_dev *pdev = to_pci_dev(ap->host->dev); -	u32 dtc, etc; +	u32 etc;  	int mode = adev->dma_mode;  	int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; -	if (mode >= XFER_UDMA_0) { -		cs5536_read(pdev, ETC, &etc); +	cs5536_read(pdev, ETC, &etc); +	if (mode >= XFER_UDMA_0) {  		etc &= ~(IDE_DRV_MASK << dshift);  		etc |= udma_timings[mode - XFER_UDMA_0] << dshift; - -		cs5536_write(pdev, ETC, etc);  	} else { /* MWDMA */ -		cs5536_read(pdev, DTC, &dtc); - -		dtc &= ~(IDE_DRV_MASK << dshift); -		dtc |= mwdma_timings[mode - XFER_MW_DMA_0] << dshift; - -		cs5536_write(pdev, DTC, dtc); +		etc &= ~(IDE_ETC_UDMA_MASK << dshift); +		cs5536_program_dtc(adev, mwdma_timings[mode - XFER_MW_DMA_0]);  	} + +	cs5536_write(pdev, ETC, etc);  }  static struct scsi_host_template cs5536_sht = { @@ -247,9 +257,23 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)  		.port_ops = &cs5536_port_ops,  	}; -	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; +	static const struct ata_port_info no_udma_info = { +		.flags = ATA_FLAG_SLAVE_POSS, +		.pio_mask = ATA_PIO4, +		.port_ops = &cs5536_port_ops, +	}; + + +	const struct ata_port_info *ppi[2];  	u32 cfg; +	if (dmi_check_system(udma_quirk_dmi_table)) +		ppi[0] = &no_udma_info; +	else +		ppi[0] = &info; + +	ppi[1] = &ata_dummy_port_info; +  	if (use_msr)  		printk(KERN_ERR DRV_NAME ": Using MSR regs instead of PCI\n"); @@ -273,29 +297,16 @@ static struct pci_driver cs5536_pci_driver = {  	.id_table	= cs5536,  	.probe		= cs5536_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init cs5536_init(void) -{ -	return pci_register_driver(&cs5536_pci_driver); -} - -static void __exit cs5536_exit(void) -{ -	pci_unregister_driver(&cs5536_pci_driver); -} +module_pci_driver(cs5536_pci_driver);  MODULE_AUTHOR("Martin K. Petersen");  MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, cs5536);  MODULE_VERSION(DRV_VERSION); -module_param_named(msr, use_msr, int, 0644); -MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)"); - -module_init(cs5536_init); -module_exit(cs5536_exit); diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c index 6d915b063d9..793018460d8 100644 --- a/drivers/ata/pata_cypress.c +++ b/drivers/ata/pata_cypress.c @@ -11,7 +11,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -152,29 +151,16 @@ static struct pci_driver cy82c693_pci_driver = {  	.id_table	= cy82c693,  	.probe 		= cy82c693_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init cy82c693_init(void) -{ -	return pci_register_driver(&cy82c693_pci_driver); -} - - -static void __exit cy82c693_exit(void) -{ -	pci_unregister_driver(&cy82c693_pci_driver); -} - +module_pci_driver(cy82c693_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for the CY82C693 PATA controller");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, cy82c693);  MODULE_VERSION(DRV_VERSION); - -module_init(cy82c693_init); -module_exit(cy82c693_exit); diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index a08834758ea..4a57a6f032d 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c @@ -14,7 +14,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -73,7 +72,7 @@ static DEFINE_SPINLOCK(efar_lock);  /**   *	efar_set_piomode - Initialize host controller PATA PIO timings   *	@ap: Port whose timings we are configuring - *	@adev: um + *	@adev: Device to program   *   *	Set PIO mode for device, in host controller PCI config space.   * @@ -85,9 +84,9 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev)  {  	unsigned int pio	= adev->pio_mode - XFER_PIO_0;  	struct pci_dev *dev	= to_pci_dev(ap->host->dev); -	unsigned int idetm_port= ap->port_no ? 0x42 : 0x40; +	unsigned int master_port = ap->port_no ? 0x42 : 0x40;  	unsigned long flags; -	u16 idetm_data; +	u16 master_data;  	u8 udma_enable;  	int control = 0; @@ -113,20 +112,20 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev)  	spin_lock_irqsave(&efar_lock, flags); -	pci_read_config_word(dev, idetm_port, &idetm_data); +	pci_read_config_word(dev, master_port, &master_data);  	/* Set PPE, IE, and TIME as appropriate */  	if (adev->devno == 0) { -		idetm_data &= 0xCCF0; -		idetm_data |= control; -		idetm_data |= (timings[pio][0] << 12) | +		master_data &= 0xCCF0; +		master_data |= control; +		master_data |= (timings[pio][0] << 12) |  			(timings[pio][1] << 8);  	} else {  		int shift = 4 * ap->port_no;  		u8 slave_data; -		idetm_data &= 0xFF0F; -		idetm_data |= (control << 4); +		master_data &= 0xFF0F; +		master_data |= (control << 4);  		/* Slave timing in separate register */  		pci_read_config_byte(dev, 0x44, &slave_data); @@ -135,8 +134,8 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev)  		pci_write_config_byte(dev, 0x44, slave_data);  	} -	idetm_data |= 0x4000;	/* Ensure SITRE is set */ -	pci_write_config_word(dev, idetm_port, idetm_data); +	master_data |= 0x4000;	/* Ensure SITRE is set */ +	pci_write_config_word(dev, master_port, master_data);  	pci_read_config_byte(dev, 0x48, &udma_enable);  	udma_enable &= ~(1 << (2 * ap->port_no + adev->devno)); @@ -263,7 +262,6 @@ static struct ata_port_operations efar_ops = {  static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	static const struct ata_port_info info = {  		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4, @@ -273,9 +271,7 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  	};  	const struct ata_port_info *ppi[] = { &info, &info }; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	return ata_pci_bmdma_init_one(pdev, ppi, &efar_sht, NULL,  				      ATA_HOST_PARALLEL_SCAN); @@ -292,28 +288,16 @@ static struct pci_driver efar_pci_driver = {  	.id_table		= efar_pci_tbl,  	.probe			= efar_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ata_pci_device_resume,  #endif  }; -static int __init efar_init(void) -{ -	return pci_register_driver(&efar_pci_driver); -} - -static void __exit efar_exit(void) -{ -	pci_unregister_driver(&efar_pci_driver); -} - -module_init(efar_init); -module_exit(efar_exit); +module_pci_driver(efar_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("SCSI low-level driver for EFAR PIIX clones");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, efar_pci_tbl);  MODULE_VERSION(DRV_VERSION); - diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c new file mode 100644 index 00000000000..4d37c5415fc --- /dev/null +++ b/drivers/ata/pata_ep93xx.c @@ -0,0 +1,1037 @@ +/* + * EP93XX PATA controller driver. + * + * Copyright (c) 2012, Metasoft s.c. + *	Rafal Prylowski <prylowski@metasoft.pl> + * + * Based on pata_scc.c, pata_icside.c and on earlier version of EP93XX + * PATA driver by Lennert Buytenhek and Alessandro Zummo. + * Read/Write timings, resource management and other improvements + * from driver by Joao Ramos and Bartlomiej Zolnierkiewicz. + * DMA engine support based on spi-ep93xx.c by Mika Westerberg. + * + * Original copyrights: + * + * Support for Cirrus Logic's EP93xx (EP9312, EP9315) CPUs + * PATA host controller driver. + * + * Copyright (c) 2009, Bartlomiej Zolnierkiewicz + * + * Heavily based on the ep93xx-ide.c driver: + * + * Copyright (c) 2009, Joao Ramos <joao.ramos@inov.pt> + *		      INESC Inovacao (INOV) + * + * EP93XX PATA controller driver. + * Copyright (C) 2007 Lennert Buytenhek <buytenh@wantstofly.org> + * + * An ATA driver for the Cirrus Logic EP93xx PATA controller. + * + * Based on an earlier version by Alessandro Zummo, which is: + *   Copyright (C) 2006 Tower Technologies + */ + +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/blkdev.h> +#include <scsi/scsi_host.h> +#include <linux/ata.h> +#include <linux/libata.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/dmaengine.h> +#include <linux/ktime.h> + +#include <linux/platform_data/dma-ep93xx.h> +#include <mach/platform.h> + +#define DRV_NAME	"ep93xx-ide" +#define DRV_VERSION	"1.0" + +enum { +	/* IDE Control Register */ +	IDECTRL				= 0x00, +	IDECTRL_CS0N			= (1 << 0), +	IDECTRL_CS1N			= (1 << 1), +	IDECTRL_DIORN			= (1 << 5), +	IDECTRL_DIOWN			= (1 << 6), +	IDECTRL_INTRQ			= (1 << 9), +	IDECTRL_IORDY			= (1 << 10), +	/* +	 * the device IDE register to be accessed is selected through +	 * IDECTRL register's specific bitfields 'DA', 'CS1N' and 'CS0N': +	 *   b4   b3   b2    b1     b0 +	 *   A2   A1   A0   CS1N   CS0N +	 * the values filled in this structure allows the value to be directly +	 * ORed to the IDECTRL register, hence giving directly the A[2:0] and +	 * CS1N/CS0N values for each IDE register. +	 * The values correspond to the transformation: +	 *   ((real IDE address) << 2) | CS1N value << 1 | CS0N value +	 */ +	IDECTRL_ADDR_CMD		= 0 + 2, /* CS1 */ +	IDECTRL_ADDR_DATA		= (ATA_REG_DATA << 2) + 2, +	IDECTRL_ADDR_ERROR		= (ATA_REG_ERR << 2) + 2, +	IDECTRL_ADDR_FEATURE		= (ATA_REG_FEATURE << 2) + 2, +	IDECTRL_ADDR_NSECT		= (ATA_REG_NSECT << 2) + 2, +	IDECTRL_ADDR_LBAL		= (ATA_REG_LBAL << 2) + 2, +	IDECTRL_ADDR_LBAM		= (ATA_REG_LBAM << 2) + 2, +	IDECTRL_ADDR_LBAH		= (ATA_REG_LBAH << 2) + 2, +	IDECTRL_ADDR_DEVICE		= (ATA_REG_DEVICE << 2) + 2, +	IDECTRL_ADDR_STATUS		= (ATA_REG_STATUS << 2) + 2, +	IDECTRL_ADDR_COMMAND		= (ATA_REG_CMD << 2) + 2, +	IDECTRL_ADDR_ALTSTATUS		= (0x06 << 2) + 1, /* CS0 */ +	IDECTRL_ADDR_CTL		= (0x06 << 2) + 1, /* CS0 */ + +	/* IDE Configuration Register */ +	IDECFG				= 0x04, +	IDECFG_IDEEN			= (1 << 0), +	IDECFG_PIO			= (1 << 1), +	IDECFG_MDMA			= (1 << 2), +	IDECFG_UDMA			= (1 << 3), +	IDECFG_MODE_SHIFT		= 4, +	IDECFG_MODE_MASK		= (0xf << 4), +	IDECFG_WST_SHIFT		= 8, +	IDECFG_WST_MASK			= (0x3 << 8), + +	/* MDMA Operation Register */ +	IDEMDMAOP			= 0x08, + +	/* UDMA Operation Register */ +	IDEUDMAOP			= 0x0c, +	IDEUDMAOP_UEN			= (1 << 0), +	IDEUDMAOP_RWOP			= (1 << 1), + +	/* PIO/MDMA/UDMA Data Registers */ +	IDEDATAOUT			= 0x10, +	IDEDATAIN			= 0x14, +	IDEMDMADATAOUT			= 0x18, +	IDEMDMADATAIN			= 0x1c, +	IDEUDMADATAOUT			= 0x20, +	IDEUDMADATAIN			= 0x24, + +	/* UDMA Status Register */ +	IDEUDMASTS			= 0x28, +	IDEUDMASTS_DMAIDE		= (1 << 16), +	IDEUDMASTS_INTIDE		= (1 << 17), +	IDEUDMASTS_SBUSY		= (1 << 18), +	IDEUDMASTS_NDO			= (1 << 24), +	IDEUDMASTS_NDI			= (1 << 25), +	IDEUDMASTS_N4X			= (1 << 26), + +	/* UDMA Debug Status Register */ +	IDEUDMADEBUG			= 0x2c, +}; + +struct ep93xx_pata_data { +	const struct platform_device *pdev; +	void __iomem *ide_base; +	struct ata_timing t; +	bool iordy; + +	unsigned long udma_in_phys; +	unsigned long udma_out_phys; + +	struct dma_chan *dma_rx_channel; +	struct ep93xx_dma_data dma_rx_data; +	struct dma_chan *dma_tx_channel; +	struct ep93xx_dma_data dma_tx_data; +}; + +static void ep93xx_pata_clear_regs(void __iomem *base) +{ +	writel(IDECTRL_CS0N | IDECTRL_CS1N | IDECTRL_DIORN | +		IDECTRL_DIOWN, base + IDECTRL); + +	writel(0, base + IDECFG); +	writel(0, base + IDEMDMAOP); +	writel(0, base + IDEUDMAOP); +	writel(0, base + IDEDATAOUT); +	writel(0, base + IDEDATAIN); +	writel(0, base + IDEMDMADATAOUT); +	writel(0, base + IDEMDMADATAIN); +	writel(0, base + IDEUDMADATAOUT); +	writel(0, base + IDEUDMADATAIN); +	writel(0, base + IDEUDMADEBUG); +} + +static bool ep93xx_pata_check_iordy(void __iomem *base) +{ +	return !!(readl(base + IDECTRL) & IDECTRL_IORDY); +} + +/* + * According to EP93xx User's Guide, WST field of IDECFG specifies number + * of HCLK cycles to hold the data bus after a PIO write operation. + * It should be programmed to guarantee following delays: + * + * PIO Mode   [ns] + * 0          30 + * 1          20 + * 2          15 + * 3          10 + * 4          5 + * + * Maximum possible value for HCLK is 100MHz. + */ +static int ep93xx_pata_get_wst(int pio_mode) +{ +	int val; + +	if (pio_mode == 0) +		val = 3; +	else if (pio_mode < 3) +		val = 2; +	else +		val = 1; + +	return val << IDECFG_WST_SHIFT; +} + +static void ep93xx_pata_enable_pio(void __iomem *base, int pio_mode) +{ +	writel(IDECFG_IDEEN | IDECFG_PIO | +		ep93xx_pata_get_wst(pio_mode) | +		(pio_mode << IDECFG_MODE_SHIFT), base + IDECFG); +} + +/* + * Based on delay loop found in mach-pxa/mp900.c. + * + * Single iteration should take 5 cpu cycles. This is 25ns assuming the + * fastest ep93xx cpu speed (200MHz) and is better optimized for PIO4 timings + * than eg. 20ns. + */ +static void ep93xx_pata_delay(unsigned long count) +{ +	__asm__ volatile ( +		"0:\n" +		"mov r0, r0\n" +		"subs %0, %1, #1\n" +		"bge 0b\n" +		: "=r" (count) +		: "0" (count) +	); +} + +static unsigned long ep93xx_pata_wait_for_iordy(void __iomem *base, +						unsigned long t2) +{ +	/* +	 * According to ATA specification, IORDY pin can be first sampled +	 * tA = 35ns after activation of DIOR-/DIOW-. Maximum IORDY pulse +	 * width is tB = 1250ns. +	 * +	 * We are already t2 delay loop iterations after activation of +	 * DIOR-/DIOW-, so we set timeout to (1250 + 35) / 25 - t2 additional +	 * delay loop iterations. +	 */ +	unsigned long start = (1250 + 35) / 25 - t2; +	unsigned long counter = start; + +	while (!ep93xx_pata_check_iordy(base) && counter--) +		ep93xx_pata_delay(1); +	return start - counter; +} + +/* common part at start of ep93xx_pata_read/write() */ +static void ep93xx_pata_rw_begin(void __iomem *base, unsigned long addr, +				 unsigned long t1) +{ +	writel(IDECTRL_DIOWN | IDECTRL_DIORN | addr, base + IDECTRL); +	ep93xx_pata_delay(t1); +} + +/* common part at end of ep93xx_pata_read/write() */ +static void ep93xx_pata_rw_end(void __iomem *base, unsigned long addr, +			       bool iordy, unsigned long t0, unsigned long t2, +			       unsigned long t2i) +{ +	ep93xx_pata_delay(t2); +	/* lengthen t2 if needed */ +	if (iordy) +		t2 += ep93xx_pata_wait_for_iordy(base, t2); +	writel(IDECTRL_DIOWN | IDECTRL_DIORN | addr, base + IDECTRL); +	if (t0 > t2 && t0 - t2 > t2i) +		ep93xx_pata_delay(t0 - t2); +	else +		ep93xx_pata_delay(t2i); +} + +static u16 ep93xx_pata_read(struct ep93xx_pata_data *drv_data, +			    unsigned long addr, +			    bool reg) +{ +	void __iomem *base = drv_data->ide_base; +	const struct ata_timing *t = &drv_data->t; +	unsigned long t0 = reg ? t->cyc8b : t->cycle; +	unsigned long t2 = reg ? t->act8b : t->active; +	unsigned long t2i = reg ? t->rec8b : t->recover; + +	ep93xx_pata_rw_begin(base, addr, t->setup); +	writel(IDECTRL_DIOWN | addr, base + IDECTRL); +	/* +	 * The IDEDATAIN register is loaded from the DD pins at the positive +	 * edge of the DIORN signal. (EP93xx UG p27-14) +	 */ +	ep93xx_pata_rw_end(base, addr, drv_data->iordy, t0, t2, t2i); +	return readl(base + IDEDATAIN); +} + +/* IDE register read */ +static u16 ep93xx_pata_read_reg(struct ep93xx_pata_data *drv_data, +				unsigned long addr) +{ +	return ep93xx_pata_read(drv_data, addr, true); +} + +/* PIO data read */ +static u16 ep93xx_pata_read_data(struct ep93xx_pata_data *drv_data, +				 unsigned long addr) +{ +	return ep93xx_pata_read(drv_data, addr, false); +} + +static void ep93xx_pata_write(struct ep93xx_pata_data *drv_data, +			      u16 value, unsigned long addr, +			      bool reg) +{ +	void __iomem *base = drv_data->ide_base; +	const struct ata_timing *t = &drv_data->t; +	unsigned long t0 = reg ? t->cyc8b : t->cycle; +	unsigned long t2 = reg ? t->act8b : t->active; +	unsigned long t2i = reg ? t->rec8b : t->recover; + +	ep93xx_pata_rw_begin(base, addr, t->setup); +	/* +	 * Value from IDEDATAOUT register is driven onto the DD pins when +	 * DIOWN is low. (EP93xx UG p27-13) +	 */ +	writel(value, base + IDEDATAOUT); +	writel(IDECTRL_DIORN | addr, base + IDECTRL); +	ep93xx_pata_rw_end(base, addr, drv_data->iordy, t0, t2, t2i); +} + +/* IDE register write */ +static void ep93xx_pata_write_reg(struct ep93xx_pata_data *drv_data, +				  u16 value, unsigned long addr) +{ +	ep93xx_pata_write(drv_data, value, addr, true); +} + +/* PIO data write */ +static void ep93xx_pata_write_data(struct ep93xx_pata_data *drv_data, +				   u16 value, unsigned long addr) +{ +	ep93xx_pata_write(drv_data, value, addr, false); +} + +static void ep93xx_pata_set_piomode(struct ata_port *ap, +				    struct ata_device *adev) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; +	struct ata_device *pair = ata_dev_pair(adev); +	/* +	 * Calculate timings for the delay loop, assuming ep93xx cpu speed +	 * is 200MHz (maximum possible for ep93xx). If actual cpu speed is +	 * slower, we will wait a bit longer in each delay. +	 * Additional division of cpu speed by 5, because single iteration +	 * of our delay loop takes 5 cpu cycles (25ns). +	 */ +	unsigned long T = 1000000 / (200 / 5); + +	ata_timing_compute(adev, adev->pio_mode, &drv_data->t, T, 0); +	if (pair && pair->pio_mode) { +		struct ata_timing t; +		ata_timing_compute(pair, pair->pio_mode, &t, T, 0); +		ata_timing_merge(&t, &drv_data->t, &drv_data->t, +			ATA_TIMING_SETUP | ATA_TIMING_8BIT); +	} +	drv_data->iordy = ata_pio_need_iordy(adev); + +	ep93xx_pata_enable_pio(drv_data->ide_base, +			       adev->pio_mode - XFER_PIO_0); +} + +/* Note: original code is ata_sff_check_status */ +static u8 ep93xx_pata_check_status(struct ata_port *ap) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; + +	return ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_STATUS); +} + +static u8 ep93xx_pata_check_altstatus(struct ata_port *ap) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; + +	return ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_ALTSTATUS); +} + +/* Note: original code is ata_sff_tf_load */ +static void ep93xx_pata_tf_load(struct ata_port *ap, +				const struct ata_taskfile *tf) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; +	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; + +	if (tf->ctl != ap->last_ctl) { +		ep93xx_pata_write_reg(drv_data, tf->ctl, IDECTRL_ADDR_CTL); +		ap->last_ctl = tf->ctl; +		ata_wait_idle(ap); +	} + +	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { +		ep93xx_pata_write_reg(drv_data, tf->hob_feature, +			IDECTRL_ADDR_FEATURE); +		ep93xx_pata_write_reg(drv_data, tf->hob_nsect, +			IDECTRL_ADDR_NSECT); +		ep93xx_pata_write_reg(drv_data, tf->hob_lbal, +			IDECTRL_ADDR_LBAL); +		ep93xx_pata_write_reg(drv_data, tf->hob_lbam, +			IDECTRL_ADDR_LBAM); +		ep93xx_pata_write_reg(drv_data, tf->hob_lbah, +			IDECTRL_ADDR_LBAH); +	} + +	if (is_addr) { +		ep93xx_pata_write_reg(drv_data, tf->feature, +			IDECTRL_ADDR_FEATURE); +		ep93xx_pata_write_reg(drv_data, tf->nsect, IDECTRL_ADDR_NSECT); +		ep93xx_pata_write_reg(drv_data, tf->lbal, IDECTRL_ADDR_LBAL); +		ep93xx_pata_write_reg(drv_data, tf->lbam, IDECTRL_ADDR_LBAM); +		ep93xx_pata_write_reg(drv_data, tf->lbah, IDECTRL_ADDR_LBAH); +	} + +	if (tf->flags & ATA_TFLAG_DEVICE) +		ep93xx_pata_write_reg(drv_data, tf->device, +			IDECTRL_ADDR_DEVICE); + +	ata_wait_idle(ap); +} + +/* Note: original code is ata_sff_tf_read */ +static void ep93xx_pata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; + +	tf->command = ep93xx_pata_check_status(ap); +	tf->feature = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_FEATURE); +	tf->nsect = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_NSECT); +	tf->lbal = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAL); +	tf->lbam = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAM); +	tf->lbah = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAH); +	tf->device = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_DEVICE); + +	if (tf->flags & ATA_TFLAG_LBA48) { +		ep93xx_pata_write_reg(drv_data, tf->ctl | ATA_HOB, +			IDECTRL_ADDR_CTL); +		tf->hob_feature = ep93xx_pata_read_reg(drv_data, +			IDECTRL_ADDR_FEATURE); +		tf->hob_nsect = ep93xx_pata_read_reg(drv_data, +			IDECTRL_ADDR_NSECT); +		tf->hob_lbal = ep93xx_pata_read_reg(drv_data, +			IDECTRL_ADDR_LBAL); +		tf->hob_lbam = ep93xx_pata_read_reg(drv_data, +			IDECTRL_ADDR_LBAM); +		tf->hob_lbah = ep93xx_pata_read_reg(drv_data, +			IDECTRL_ADDR_LBAH); +		ep93xx_pata_write_reg(drv_data, tf->ctl, IDECTRL_ADDR_CTL); +		ap->last_ctl = tf->ctl; +	} +} + +/* Note: original code is ata_sff_exec_command */ +static void ep93xx_pata_exec_command(struct ata_port *ap, +				     const struct ata_taskfile *tf) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; + +	ep93xx_pata_write_reg(drv_data, tf->command, +			  IDECTRL_ADDR_COMMAND); +	ata_sff_pause(ap); +} + +/* Note: original code is ata_sff_dev_select */ +static void ep93xx_pata_dev_select(struct ata_port *ap, unsigned int device) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; +	u8 tmp = ATA_DEVICE_OBS; + +	if (device != 0) +		tmp |= ATA_DEV1; + +	ep93xx_pata_write_reg(drv_data, tmp, IDECTRL_ADDR_DEVICE); +	ata_sff_pause(ap);	/* needed; also flushes, for mmio */ +} + +/* Note: original code is ata_sff_set_devctl */ +static void ep93xx_pata_set_devctl(struct ata_port *ap, u8 ctl) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; + +	ep93xx_pata_write_reg(drv_data, ctl, IDECTRL_ADDR_CTL); +} + +/* Note: original code is ata_sff_data_xfer */ +static unsigned int ep93xx_pata_data_xfer(struct ata_device *adev, +					  unsigned char *buf, +					  unsigned int buflen, int rw) +{ +	struct ata_port *ap = adev->link->ap; +	struct ep93xx_pata_data *drv_data = ap->host->private_data; +	u16 *data = (u16 *)buf; +	unsigned int words = buflen >> 1; + +	/* Transfer multiple of 2 bytes */ +	while (words--) +		if (rw == READ) +			*data++ = cpu_to_le16( +				ep93xx_pata_read_data( +					drv_data, IDECTRL_ADDR_DATA)); +		else +			ep93xx_pata_write_data(drv_data, le16_to_cpu(*data++), +				IDECTRL_ADDR_DATA); + +	/* Transfer trailing 1 byte, if any. */ +	if (unlikely(buflen & 0x01)) { +		unsigned char pad[2] = { }; + +		buf += buflen - 1; + +		if (rw == READ) { +			*pad = cpu_to_le16( +				ep93xx_pata_read_data( +					drv_data, IDECTRL_ADDR_DATA)); +			*buf = pad[0]; +		} else { +			pad[0] = *buf; +			ep93xx_pata_write_data(drv_data, le16_to_cpu(*pad), +					  IDECTRL_ADDR_DATA); +		} +		words++; +	} + +	return words << 1; +} + +/* Note: original code is ata_devchk */ +static bool ep93xx_pata_device_is_present(struct ata_port *ap, +					  unsigned int device) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; +	u8 nsect, lbal; + +	ap->ops->sff_dev_select(ap, device); + +	ep93xx_pata_write_reg(drv_data, 0x55, IDECTRL_ADDR_NSECT); +	ep93xx_pata_write_reg(drv_data, 0xaa, IDECTRL_ADDR_LBAL); + +	ep93xx_pata_write_reg(drv_data, 0xaa, IDECTRL_ADDR_NSECT); +	ep93xx_pata_write_reg(drv_data, 0x55, IDECTRL_ADDR_LBAL); + +	ep93xx_pata_write_reg(drv_data, 0x55, IDECTRL_ADDR_NSECT); +	ep93xx_pata_write_reg(drv_data, 0xaa, IDECTRL_ADDR_LBAL); + +	nsect = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_NSECT); +	lbal = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAL); + +	if ((nsect == 0x55) && (lbal == 0xaa)) +		return true; + +	return false; +} + +/* Note: original code is ata_sff_wait_after_reset */ +static int ep93xx_pata_wait_after_reset(struct ata_link *link, +					unsigned int devmask, +					unsigned long deadline) +{ +	struct ata_port *ap = link->ap; +	struct ep93xx_pata_data *drv_data = ap->host->private_data; +	unsigned int dev0 = devmask & (1 << 0); +	unsigned int dev1 = devmask & (1 << 1); +	int rc, ret = 0; + +	ata_msleep(ap, ATA_WAIT_AFTER_RESET); + +	/* always check readiness of the master device */ +	rc = ata_sff_wait_ready(link, deadline); +	/* +	 * -ENODEV means the odd clown forgot the D7 pulldown resistor +	 * and TF status is 0xff, bail out on it too. +	 */ +	if (rc) +		return rc; + +	/* +	 * if device 1 was found in ata_devchk, wait for register +	 * access briefly, then wait for BSY to clear. +	 */ +	if (dev1) { +		int i; + +		ap->ops->sff_dev_select(ap, 1); + +		/* +		 * Wait for register access.  Some ATAPI devices fail +		 * to set nsect/lbal after reset, so don't waste too +		 * much time on it.  We're gonna wait for !BSY anyway. +		 */ +		for (i = 0; i < 2; i++) { +			u8 nsect, lbal; + +			nsect = ep93xx_pata_read_reg(drv_data, +				IDECTRL_ADDR_NSECT); +			lbal = ep93xx_pata_read_reg(drv_data, +				IDECTRL_ADDR_LBAL); +			if (nsect == 1 && lbal == 1) +				break; +			msleep(50);	/* give drive a breather */ +		} + +		rc = ata_sff_wait_ready(link, deadline); +		if (rc) { +			if (rc != -ENODEV) +				return rc; +			ret = rc; +		} +	} +	/* is all this really necessary? */ +	ap->ops->sff_dev_select(ap, 0); +	if (dev1) +		ap->ops->sff_dev_select(ap, 1); +	if (dev0) +		ap->ops->sff_dev_select(ap, 0); + +	return ret; +} + +/* Note: original code is ata_bus_softreset */ +static int ep93xx_pata_bus_softreset(struct ata_port *ap, unsigned int devmask, +				     unsigned long deadline) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; + +	ep93xx_pata_write_reg(drv_data, ap->ctl, IDECTRL_ADDR_CTL); +	udelay(20);		/* FIXME: flush */ +	ep93xx_pata_write_reg(drv_data, ap->ctl | ATA_SRST, IDECTRL_ADDR_CTL); +	udelay(20);		/* FIXME: flush */ +	ep93xx_pata_write_reg(drv_data, ap->ctl, IDECTRL_ADDR_CTL); +	ap->last_ctl = ap->ctl; + +	return ep93xx_pata_wait_after_reset(&ap->link, devmask, deadline); +} + +static void ep93xx_pata_release_dma(struct ep93xx_pata_data *drv_data) +{ +	if (drv_data->dma_rx_channel) { +		dma_release_channel(drv_data->dma_rx_channel); +		drv_data->dma_rx_channel = NULL; +	} +	if (drv_data->dma_tx_channel) { +		dma_release_channel(drv_data->dma_tx_channel); +		drv_data->dma_tx_channel = NULL; +	} +} + +static bool ep93xx_pata_dma_filter(struct dma_chan *chan, void *filter_param) +{ +	if (ep93xx_dma_chan_is_m2p(chan)) +		return false; + +	chan->private = filter_param; +	return true; +} + +static void ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data) +{ +	const struct platform_device *pdev = drv_data->pdev; +	dma_cap_mask_t mask; +	struct dma_slave_config conf; + +	dma_cap_zero(mask); +	dma_cap_set(DMA_SLAVE, mask); + +	/* +	 * Request two channels for IDE. Another possibility would be +	 * to request only one channel, and reprogram it's direction at +	 * start of new transfer. +	 */ +	drv_data->dma_rx_data.port = EP93XX_DMA_IDE; +	drv_data->dma_rx_data.direction = DMA_FROM_DEVICE; +	drv_data->dma_rx_data.name = "ep93xx-pata-rx"; +	drv_data->dma_rx_channel = dma_request_channel(mask, +		ep93xx_pata_dma_filter, &drv_data->dma_rx_data); +	if (!drv_data->dma_rx_channel) +		return; + +	drv_data->dma_tx_data.port = EP93XX_DMA_IDE; +	drv_data->dma_tx_data.direction = DMA_TO_DEVICE; +	drv_data->dma_tx_data.name = "ep93xx-pata-tx"; +	drv_data->dma_tx_channel = dma_request_channel(mask, +		ep93xx_pata_dma_filter, &drv_data->dma_tx_data); +	if (!drv_data->dma_tx_channel) { +		dma_release_channel(drv_data->dma_rx_channel); +		return; +	} + +	/* Configure receive channel direction and source address */ +	memset(&conf, 0, sizeof(conf)); +	conf.direction = DMA_FROM_DEVICE; +	conf.src_addr = drv_data->udma_in_phys; +	conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +	if (dmaengine_slave_config(drv_data->dma_rx_channel, &conf)) { +		dev_err(&pdev->dev, "failed to configure rx dma channel\n"); +		ep93xx_pata_release_dma(drv_data); +		return; +	} + +	/* Configure transmit channel direction and destination address */ +	memset(&conf, 0, sizeof(conf)); +	conf.direction = DMA_TO_DEVICE; +	conf.dst_addr = drv_data->udma_out_phys; +	conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +	if (dmaengine_slave_config(drv_data->dma_tx_channel, &conf)) { +		dev_err(&pdev->dev, "failed to configure tx dma channel\n"); +		ep93xx_pata_release_dma(drv_data); +	} +} + +static void ep93xx_pata_dma_start(struct ata_queued_cmd *qc) +{ +	struct dma_async_tx_descriptor *txd; +	struct ep93xx_pata_data *drv_data = qc->ap->host->private_data; +	void __iomem *base = drv_data->ide_base; +	struct ata_device *adev = qc->dev; +	u32 v = qc->dma_dir == DMA_TO_DEVICE ? IDEUDMAOP_RWOP : 0; +	struct dma_chan *channel = qc->dma_dir == DMA_TO_DEVICE +		? drv_data->dma_tx_channel : drv_data->dma_rx_channel; + +	txd = dmaengine_prep_slave_sg(channel, qc->sg, qc->n_elem, qc->dma_dir, +		DMA_CTRL_ACK); +	if (!txd) { +		dev_err(qc->ap->dev, "failed to prepare slave for sg dma\n"); +		return; +	} +	txd->callback = NULL; +	txd->callback_param = NULL; + +	if (dmaengine_submit(txd) < 0) { +		dev_err(qc->ap->dev, "failed to submit dma transfer\n"); +		return; +	} +	dma_async_issue_pending(channel); + +	/* +	 * When enabling UDMA operation, IDEUDMAOP register needs to be +	 * programmed in three step sequence: +	 * 1) set or clear the RWOP bit, +	 * 2) perform dummy read of the register, +	 * 3) set the UEN bit. +	 */ +	writel(v, base + IDEUDMAOP); +	readl(base + IDEUDMAOP); +	writel(v | IDEUDMAOP_UEN, base + IDEUDMAOP); + +	writel(IDECFG_IDEEN | IDECFG_UDMA | +		((adev->xfer_mode - XFER_UDMA_0) << IDECFG_MODE_SHIFT), +		base + IDECFG); +} + +static void ep93xx_pata_dma_stop(struct ata_queued_cmd *qc) +{ +	struct ep93xx_pata_data *drv_data = qc->ap->host->private_data; +	void __iomem *base = drv_data->ide_base; + +	/* terminate all dma transfers, if not yet finished */ +	dmaengine_terminate_all(drv_data->dma_rx_channel); +	dmaengine_terminate_all(drv_data->dma_tx_channel); + +	/* +	 * To properly stop IDE-DMA, IDEUDMAOP register must to be cleared +	 * and IDECTRL register must be set to default value. +	 */ +	writel(0, base + IDEUDMAOP); +	writel(readl(base + IDECTRL) | IDECTRL_DIOWN | IDECTRL_DIORN | +		IDECTRL_CS0N | IDECTRL_CS1N, base + IDECTRL); + +	ep93xx_pata_enable_pio(drv_data->ide_base, +		qc->dev->pio_mode - XFER_PIO_0); + +	ata_sff_dma_pause(qc->ap); +} + +static void ep93xx_pata_dma_setup(struct ata_queued_cmd *qc) +{ +	qc->ap->ops->sff_exec_command(qc->ap, &qc->tf); +} + +static u8 ep93xx_pata_dma_status(struct ata_port *ap) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; +	u32 val = readl(drv_data->ide_base + IDEUDMASTS); + +	/* +	 * UDMA Status Register bits: +	 * +	 * DMAIDE - DMA request signal from UDMA state machine, +	 * INTIDE - INT line generated by UDMA because of errors in the +	 *          state machine, +	 * SBUSY - UDMA state machine busy, not in idle state, +	 * NDO   - error for data-out not completed, +	 * NDI   - error for data-in not completed, +	 * N4X   - error for data transferred not multiplies of four +	 *         32-bit words. +	 * (EP93xx UG p27-17) +	 */ +	if (val & IDEUDMASTS_NDO || val & IDEUDMASTS_NDI || +	    val & IDEUDMASTS_N4X || val & IDEUDMASTS_INTIDE) +		return ATA_DMA_ERR; + +	/* read INTRQ (INT[3]) pin input state */ +	if (readl(drv_data->ide_base + IDECTRL) & IDECTRL_INTRQ) +		return ATA_DMA_INTR; + +	if (val & IDEUDMASTS_SBUSY || val & IDEUDMASTS_DMAIDE) +		return ATA_DMA_ACTIVE; + +	return 0; +} + +/* Note: original code is ata_sff_softreset */ +static int ep93xx_pata_softreset(struct ata_link *al, unsigned int *classes, +				 unsigned long deadline) +{ +	struct ata_port *ap = al->ap; +	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; +	unsigned int devmask = 0; +	int rc; +	u8 err; + +	/* determine if device 0/1 are present */ +	if (ep93xx_pata_device_is_present(ap, 0)) +		devmask |= (1 << 0); +	if (slave_possible && ep93xx_pata_device_is_present(ap, 1)) +		devmask |= (1 << 1); + +	/* select device 0 again */ +	ap->ops->sff_dev_select(al->ap, 0); + +	/* issue bus reset */ +	rc = ep93xx_pata_bus_softreset(ap, devmask, deadline); +	/* if link is ocuppied, -ENODEV too is an error */ +	if (rc && (rc != -ENODEV || sata_scr_valid(al))) { +		ata_link_err(al, "SRST failed (errno=%d)\n", rc); +		return rc; +	} + +	/* determine by signature whether we have ATA or ATAPI devices */ +	classes[0] = ata_sff_dev_classify(&al->device[0], devmask & (1 << 0), +					  &err); +	if (slave_possible && err != 0x81) +		classes[1] = ata_sff_dev_classify(&al->device[1], +						  devmask & (1 << 1), &err); + +	return 0; +} + +/* Note: original code is ata_sff_drain_fifo */ +static void ep93xx_pata_drain_fifo(struct ata_queued_cmd *qc) +{ +	int count; +	struct ata_port *ap; +	struct ep93xx_pata_data *drv_data; + +	/* We only need to flush incoming data when a command was running */ +	if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE) +		return; + +	ap = qc->ap; +	drv_data = ap->host->private_data; +	/* Drain up to 64K of data before we give up this recovery method */ +	for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ) +		     && count < 65536; count += 2) +		ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_DATA); + +	/* Can become DEBUG later */ +	if (count) +		ata_port_dbg(ap, "drained %d bytes to clear DRQ.\n", count); + +} + +static int ep93xx_pata_port_start(struct ata_port *ap) +{ +	struct ep93xx_pata_data *drv_data = ap->host->private_data; + +	/* +	 * Set timings to safe values at startup (= number of ns from ATA +	 * specification), we'll switch to properly calculated values later. +	 */ +	drv_data->t = *ata_timing_find_mode(XFER_PIO_0); +	return 0; +} + +static struct scsi_host_template ep93xx_pata_sht = { +	ATA_BASE_SHT(DRV_NAME), +	/* ep93xx dma implementation limit */ +	.sg_tablesize		= 32, +	/* ep93xx dma can't transfer 65536 bytes at once */ +	.dma_boundary		= 0x7fff, +}; + +static struct ata_port_operations ep93xx_pata_port_ops = { +	.inherits		= &ata_bmdma_port_ops, + +	.qc_prep		= ata_noop_qc_prep, + +	.softreset		= ep93xx_pata_softreset, +	.hardreset		= ATA_OP_NULL, + +	.sff_dev_select		= ep93xx_pata_dev_select, +	.sff_set_devctl		= ep93xx_pata_set_devctl, +	.sff_check_status	= ep93xx_pata_check_status, +	.sff_check_altstatus	= ep93xx_pata_check_altstatus, +	.sff_tf_load		= ep93xx_pata_tf_load, +	.sff_tf_read		= ep93xx_pata_tf_read, +	.sff_exec_command	= ep93xx_pata_exec_command, +	.sff_data_xfer		= ep93xx_pata_data_xfer, +	.sff_drain_fifo		= ep93xx_pata_drain_fifo, +	.sff_irq_clear		= ATA_OP_NULL, + +	.set_piomode		= ep93xx_pata_set_piomode, + +	.bmdma_setup		= ep93xx_pata_dma_setup, +	.bmdma_start		= ep93xx_pata_dma_start, +	.bmdma_stop		= ep93xx_pata_dma_stop, +	.bmdma_status		= ep93xx_pata_dma_status, + +	.cable_detect		= ata_cable_unknown, +	.port_start		= ep93xx_pata_port_start, +}; + +static int ep93xx_pata_probe(struct platform_device *pdev) +{ +	struct ep93xx_pata_data *drv_data; +	struct ata_host *host; +	struct ata_port *ap; +	int irq; +	struct resource *mem_res; +	void __iomem *ide_base; +	int err; + +	err = ep93xx_ide_acquire_gpio(pdev); +	if (err) +		return err; + +	/* INT[3] (IRQ_EP93XX_EXT3) line connected as pull down */ +	irq = platform_get_irq(pdev, 0); +	if (irq < 0) { +		err = -ENXIO; +		goto err_rel_gpio; +	} + +	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	ide_base = devm_ioremap_resource(&pdev->dev, mem_res); +	if (IS_ERR(ide_base)) { +		err = PTR_ERR(ide_base); +		goto err_rel_gpio; +	} + +	drv_data = devm_kzalloc(&pdev->dev, sizeof(*drv_data), GFP_KERNEL); +	if (!drv_data) { +		err = -ENXIO; +		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; +	drv_data->udma_out_phys = mem_res->start + IDEUDMADATAOUT; +	ep93xx_pata_dma_init(drv_data); + +	/* allocate host */ +	host = ata_host_alloc(&pdev->dev, 1); +	if (!host) { +		err = -ENXIO; +		goto err_rel_dma; +	} + +	ep93xx_pata_clear_regs(ide_base); + +	host->private_data = drv_data; + +	ap = host->ports[0]; +	ap->dev = &pdev->dev; +	ap->ops = &ep93xx_pata_port_ops; +	ap->flags |= ATA_FLAG_SLAVE_POSS; +	ap->pio_mask = ATA_PIO4; + +	/* +	 * Maximum UDMA modes: +	 * EP931x rev.E0 - UDMA2 +	 * EP931x rev.E1 - UDMA3 +	 * EP931x rev.E2 - UDMA4 +	 * +	 * MWDMA support was removed from EP931x rev.E2, +	 * so this driver supports only UDMA modes. +	 */ +	if (drv_data->dma_rx_channel && drv_data->dma_tx_channel) { +		int chip_rev = ep93xx_chip_revision(); + +		if (chip_rev == EP93XX_CHIP_REV_E1) +			ap->udma_mask = ATA_UDMA3; +		else if (chip_rev == EP93XX_CHIP_REV_E2) +			ap->udma_mask = ATA_UDMA4; +		else +			ap->udma_mask = ATA_UDMA2; +	} + +	/* defaults, pio 0 */ +	ep93xx_pata_enable_pio(ide_base, 0); + +	dev_info(&pdev->dev, "version " DRV_VERSION "\n"); + +	/* activate host */ +	err = ata_host_activate(host, irq, ata_bmdma_interrupt, 0, +		&ep93xx_pata_sht); +	if (err == 0) +		return 0; + +err_rel_dma: +	ep93xx_pata_release_dma(drv_data); +err_rel_gpio: +	ep93xx_ide_release_gpio(pdev); +	return err; +} + +static int ep93xx_pata_remove(struct platform_device *pdev) +{ +	struct ata_host *host = platform_get_drvdata(pdev); +	struct ep93xx_pata_data *drv_data = host->private_data; + +	ata_host_detach(host); +	ep93xx_pata_release_dma(drv_data); +	ep93xx_pata_clear_regs(drv_data->ide_base); +	ep93xx_ide_release_gpio(pdev); +	return 0; +} + +static struct platform_driver ep93xx_pata_platform_driver = { +	.driver = { +		.name = DRV_NAME, +		.owner = THIS_MODULE, +	}, +	.probe = ep93xx_pata_probe, +	.remove = ep93xx_pata_remove, +}; + +module_platform_driver(ep93xx_pata_platform_driver); + +MODULE_AUTHOR("Alessandro Zummo, Lennert Buytenhek, Joao Ramos, " +		"Bartlomiej Zolnierkiewicz, Rafal Prylowski"); +MODULE_DESCRIPTION("low-level driver for cirrus ep93xx IDE controller"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); +MODULE_ALIAS("platform:pata_ep93xx"); diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index 7688868557b..cbc3de793d1 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -14,18 +14,18 @@   *	Look into engine reset on timeout errors. Should not be required.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h>  #include <linux/libata.h>  #define DRV_NAME	"pata_hpt366" -#define DRV_VERSION	"0.6.8" +#define DRV_VERSION	"0.6.11"  struct hpt_clock {  	u8	xfer_mode; @@ -110,18 +110,45 @@ static const struct hpt_clock hpt366_25[] = {  	{	0,		0x01208585	}  }; -static const char *bad_ata33[] = { -	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", -	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", -	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", +/** + *	hpt36x_find_mode	-	find the hpt36x timing + *	@ap: ATA port + *	@speed: transfer mode + * + *	Return the 32bit register programming information for this channel + *	that matches the speed provided. + */ + +static u32 hpt36x_find_mode(struct ata_port *ap, int speed) +{ +	struct hpt_clock *clocks = ap->host->private_data; + +	while (clocks->xfer_mode) { +		if (clocks->xfer_mode == speed) +			return clocks->timing; +		clocks++; +	} +	BUG(); +	return 0xffffffffU;	/* silence compiler warning */ +} + +static const char * const bad_ata33[] = { +	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", +	"Maxtor 90845U3", "Maxtor 90650U2", +	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", +	"Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", +	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", +	"Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",  	"Maxtor 90510D4",  	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", -	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", -	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", +	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", +	"Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", +	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", +	"Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",  	NULL  }; -static const char *bad_ata66_4[] = { +static const char * const bad_ata66_4[] = {  	"IBM-DTLA-307075",  	"IBM-DTLA-307060",  	"IBM-DTLA-307045", @@ -140,12 +167,13 @@ static const char *bad_ata66_4[] = {  	NULL  }; -static const char *bad_ata66_3[] = { +static const char * const bad_ata66_3[] = {  	"WDC AC310200R",  	NULL  }; -static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[]) +static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, +			       const char * const list[])  {  	unsigned char model_num[ATA_ID_PROD_LEN + 1];  	int i = 0; @@ -154,7 +182,7 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, cons  	while (list[i] != NULL) {  		if (!strcmp(list[i], model_num)) { -			printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", +			pr_warn("%s is not supported for %s\n",  				modestr, list[i]);  			return 1;  		} @@ -203,10 +231,9 @@ static int hpt36x_cable_detect(struct ata_port *ap)  static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,  			    u8 mode)  { -	struct hpt_clock *clocks = ap->host->private_data;  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	u32 addr = 0x40 + 4 * adev->devno; -	u32 mask, reg; +	u32 mask, reg, t;  	/* determine timing mask and find matching clock entry */  	if (mode < XFER_MW_DMA_0) @@ -216,13 +243,7 @@ static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,  	else  		mask = 0x30070000; -	while (clocks->xfer_mode) { -		if (clocks->xfer_mode == mode) -			break; -		clocks++; -	} -	if (!clocks->xfer_mode) -		BUG(); +	t = hpt36x_find_mode(ap, mode);  	/*  	 * Combine new mode bits with old config bits and disable @@ -230,7 +251,7 @@ static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,  	 * problems handling I/O errors later.  	 */  	pci_read_config_dword(pdev, addr, ®); -	reg = ((reg & ~mask) | (clocks->timing & mask)) & ~0xc0000000; +	reg = ((reg & ~mask) | (t & mask)) & ~0xc0000000;  	pci_write_config_dword(pdev, addr, reg);  } @@ -288,6 +309,7 @@ static struct ata_port_operations hpt366_port_ops = {  static void hpt36x_init_chipset(struct pci_dev *dev)  {  	u8 drive_fast; +  	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));  	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);  	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); @@ -349,25 +371,25 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)  	/* PCI clocking determines the ATA timing values to use */  	/* info_hpt366 is safe against re-entry so we can scribble on it */ -	switch((reg1 & 0x700) >> 8) { -		case 9: -			hpriv = &hpt366_40; -			break; -		case 5: -			hpriv = &hpt366_25; -			break; -		default: -			hpriv = &hpt366_33; -			break; +	switch ((reg1 & 0x700) >> 8) { +	case 9: +		hpriv = &hpt366_40; +		break; +	case 5: +		hpriv = &hpt366_25; +		break; +	default: +		hpriv = &hpt366_33; +		break;  	}  	/* Now kick off ATA set up */  	return ata_pci_bmdma_init_one(dev, ppi, &hpt36x_sht, hpriv, 0);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int hpt36x_reinit_one(struct pci_dev *dev)  { -	struct ata_host *host = dev_get_drvdata(&dev->dev); +	struct ata_host *host = pci_get_drvdata(dev);  	int rc;  	rc = ata_pci_device_do_resume(dev); @@ -385,31 +407,20 @@ static const struct pci_device_id hpt36x[] = {  };  static struct pci_driver hpt36x_pci_driver = { -	.name 		= DRV_NAME, +	.name		= DRV_NAME,  	.id_table	= hpt36x, -	.probe 		= hpt36x_init_one, +	.probe		= hpt36x_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= hpt36x_reinit_one,  #endif  }; -static int __init hpt36x_init(void) -{ -	return pci_register_driver(&hpt36x_pci_driver); -} - -static void __exit hpt36x_exit(void) -{ -	pci_unregister_driver(&hpt36x_pci_driver); -} +module_pci_driver(hpt36x_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, hpt36x);  MODULE_VERSION(DRV_VERSION); - -module_init(hpt36x_init); -module_exit(hpt36x_exit); diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 9ae4c083057..3ba843f5cdc 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -8,23 +8,24 @@   * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>   * Portions Copyright (C) 2001	        Sun Microsystems, Inc.   * Portions Copyright (C) 2003		Red Hat Inc - * Portions Copyright (C) 2005-2009	MontaVista Software, Inc. + * Portions Copyright (C) 2005-2010	MontaVista Software, Inc.   *   * TODO   *	Look into engine reset on timeout errors. Should not be	required.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h>  #include <linux/libata.h>  #define DRV_NAME	"pata_hpt37x" -#define DRV_VERSION	"0.6.15" +#define DRV_VERSION	"0.6.23"  struct hpt_clock {  	u8	xfer_speed; @@ -210,7 +211,7 @@ static u32 hpt37x_find_mode(struct ata_port *ap, int speed)  {  	struct hpt_clock *clocks = ap->host->private_data; -	while(clocks->xfer_speed) { +	while (clocks->xfer_speed) {  		if (clocks->xfer_speed == speed)  			return clocks->timing;  		clocks++; @@ -219,7 +220,8 @@ static u32 hpt37x_find_mode(struct ata_port *ap, int speed)  	return 0xffffffffU;	/* silence compiler warning */  } -static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[]) +static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, +			       const char * const list[])  {  	unsigned char model_num[ATA_ID_PROD_LEN + 1];  	int i = 0; @@ -228,7 +230,7 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, cons  	while (list[i] != NULL) {  		if (!strcmp(list[i], model_num)) { -			printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", +			pr_warn("%s is not supported for %s\n",  				modestr, list[i]);  			return 1;  		} @@ -237,18 +239,23 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, cons  	return 0;  } -static const char *bad_ata33[] = { -	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", -	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", -	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", +static const char * const bad_ata33[] = { +	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", +	"Maxtor 90845U3", "Maxtor 90650U2", +	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", +	"Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", +	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", +	"Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",  	"Maxtor 90510D4",  	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", -	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", -	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", +	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", +	"Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", +	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", +	"Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",  	NULL  }; -static const char *bad_ata100_5[] = { +static const char * const bad_ata100_5[] = {  	"IBM-DTLA-307075",  	"IBM-DTLA-307060",  	"IBM-DTLA-307045", @@ -302,6 +309,22 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)  }  /** + *	hpt372_filter	-	mode selection filter + *	@adev: ATA device + *	@mask: mode mask + * + *	The Marvell bridge chips used on the HighPoint SATA cards do not seem + *	to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes... + */ +static unsigned long hpt372_filter(struct ata_device *adev, unsigned long mask) +{ +	if (ata_id_is_sata(adev->id)) +		mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA); + +	return mask; +} + +/**   *	hpt37x_cable_detect	-	Detect the cable type   *	@ap: ATA port to detect on   * @@ -373,6 +396,7 @@ static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline)  		{ 0x50, 1, 0x04, 0x04 },  		{ 0x54, 1, 0x04, 0x04 }  	}; +  	if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no]))  		return -ENOENT; @@ -586,11 +610,11 @@ static struct ata_port_operations hpt370a_port_ops = {  };  /* - *	Configuration for HPT372, HPT371, HPT302. Slightly different PIO - *	and DMA mode setting functionality. + *	Configuration for HPT371 and HPT302. Slightly different PIO and DMA + *	mode setting functionality.   */ -static struct ata_port_operations hpt372_port_ops = { +static struct ata_port_operations hpt302_port_ops = {  	.inherits	= &ata_bmdma_port_ops,  	.bmdma_stop	= hpt37x_bmdma_stop, @@ -602,14 +626,23 @@ static struct ata_port_operations hpt372_port_ops = {  };  /* - *	Configuration for HPT374. Mode setting works like 372 and friends + *	Configuration for HPT372. Mode setting works like 371 and 302 + *	but we have a mode filter. + */ + +static struct ata_port_operations hpt372_port_ops = { +	.inherits	= &hpt302_port_ops, +	.mode_filter	= hpt372_filter, +}; + +/* + *	Configuration for HPT374. Mode setting and filtering works like 372   *	but we have a different cable detection procedure for function 1.   */  static struct ata_port_operations hpt374_fn1_port_ops = {  	.inherits	= &hpt372_port_ops,  	.cable_detect	= hpt374_fn1_cable_detect, -	.prereset	= hpt37x_pre_reset,  };  /** @@ -647,12 +680,12 @@ static int hpt37x_calibrate_dpll(struct pci_dev *dev)  	u32 reg5c;  	int tries; -	for(tries = 0; tries < 0x5000; tries++) { +	for (tries = 0; tries < 0x5000; tries++) {  		udelay(50);  		pci_read_config_byte(dev, 0x5b, ®5b);  		if (reg5b & 0x80) {  			/* See if it stays set */ -			for(tries = 0; tries < 0x1000; tries ++) { +			for (tries = 0; tries < 0x1000; tries++) {  				pci_read_config_byte(dev, 0x5b, ®5b);  				/* Failed ? */  				if ((reg5b & 0x80) == 0) @@ -660,7 +693,7 @@ static int hpt37x_calibrate_dpll(struct pci_dev *dev)  			}  			/* Turn off tuning, we have the DPLL set */  			pci_read_config_dword(dev, 0x5c, ®5c); -			pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100); +			pci_write_config_dword(dev, 0x5c, reg5c & ~0x100);  			return 1;  		}  	} @@ -672,6 +705,7 @@ static u32 hpt374_read_freq(struct pci_dev *pdev)  {  	u32 freq;  	unsigned long io_base = pci_resource_start(pdev, 4); +  	if (PCI_FUNC(pdev->devfn) & 1) {  		struct pci_dev *pdev_0; @@ -737,23 +771,23 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)  		.udma_mask = ATA_UDMA5,  		.port_ops = &hpt370a_port_ops  	}; -	/* HPT370 - UDMA100 */ +	/* HPT370 - UDMA66 */  	static const struct ata_port_info info_hpt370_33 = {  		.flags = ATA_FLAG_SLAVE_POSS,  		.pio_mask = ATA_PIO4,  		.mwdma_mask = ATA_MWDMA2, -		.udma_mask = ATA_UDMA5, +		.udma_mask = ATA_UDMA4,  		.port_ops = &hpt370_port_ops  	}; -	/* HPT370A - UDMA100 */ +	/* HPT370A - UDMA66 */  	static const struct ata_port_info info_hpt370a_33 = {  		.flags = ATA_FLAG_SLAVE_POSS,  		.pio_mask = ATA_PIO4,  		.mwdma_mask = ATA_MWDMA2, -		.udma_mask = ATA_UDMA5, +		.udma_mask = ATA_UDMA4,  		.port_ops = &hpt370a_port_ops  	}; -	/* HPT371, 372 and friends - UDMA133 */ +	/* HPT372 - UDMA133 */  	static const struct ata_port_info info_hpt372 = {  		.flags = ATA_FLAG_SLAVE_POSS,  		.pio_mask = ATA_PIO4, @@ -761,7 +795,15 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)  		.udma_mask = ATA_UDMA6,  		.port_ops = &hpt372_port_ops  	}; -	/* HPT374 - UDMA100, function 1 uses different prereset method */ +	/* HPT371, 302 - UDMA133 */ +	static const struct ata_port_info info_hpt302 = { +		.flags = ATA_FLAG_SLAVE_POSS, +		.pio_mask = ATA_PIO4, +		.mwdma_mask = ATA_MWDMA2, +		.udma_mask = ATA_UDMA6, +		.port_ops = &hpt302_port_ops +	}; +	/* HPT374 - UDMA100, function 1 uses different cable_detect method */  	static const struct ata_port_info info_hpt374_fn0 = {  		.flags = ATA_FLAG_SLAVE_POSS,  		.pio_mask = ATA_PIO4, @@ -796,7 +838,8 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)  	if (rc)  		return rc; -	if (dev->device == PCI_DEVICE_ID_TTI_HPT366) { +	switch (dev->device) { +	case PCI_DEVICE_ID_TTI_HPT366:  		/* May be a later chip in disguise. Check */  		/* Older chips are in the HPT366 driver. Ignore them */  		if (rev < 3) @@ -805,66 +848,65 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)  		if (rev == 6)  			return -ENODEV; -		switch(rev) { -			case 3: -				ppi[0] = &info_hpt370; -				chip_table = &hpt370; -				prefer_dpll = 0; -				break; -			case 4: -				ppi[0] = &info_hpt370a; -				chip_table = &hpt370a; -				prefer_dpll = 0; -				break; -			case 5: -				ppi[0] = &info_hpt372; -				chip_table = &hpt372; -				break; -			default: -				printk(KERN_ERR "pata_hpt37x: Unknown HPT366 " -				       "subtype, please report (%d).\n", rev); -				return -ENODEV; -		} -	} else { -		switch(dev->device) { -			case PCI_DEVICE_ID_TTI_HPT372: -				/* 372N if rev >= 2*/ -				if (rev >= 2) -					return -ENODEV; -				ppi[0] = &info_hpt372; -				chip_table = &hpt372a; -				break; -			case PCI_DEVICE_ID_TTI_HPT302: -				/* 302N if rev > 1 */ -				if (rev > 1) -					return -ENODEV; -				ppi[0] = &info_hpt372; -				/* Check this */ -				chip_table = &hpt302; -				break; -			case PCI_DEVICE_ID_TTI_HPT371: -				if (rev > 1) -					return -ENODEV; -				ppi[0] = &info_hpt372; -				chip_table = &hpt371; -				/* Single channel device, master is not present -				   but the BIOS (or us for non x86) must mark it -				   absent */ -				pci_read_config_byte(dev, 0x50, &mcr1); -				mcr1 &= ~0x04; -				pci_write_config_byte(dev, 0x50, mcr1); -				break; -			case PCI_DEVICE_ID_TTI_HPT374: -				chip_table = &hpt374; -				if (!(PCI_FUNC(dev->devfn) & 1)) -					*ppi = &info_hpt374_fn0; -				else -					*ppi = &info_hpt374_fn1; -				break; -			default: -				printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device); -				return -ENODEV; +		switch (rev) { +		case 3: +			ppi[0] = &info_hpt370; +			chip_table = &hpt370; +			prefer_dpll = 0; +			break; +		case 4: +			ppi[0] = &info_hpt370a; +			chip_table = &hpt370a; +			prefer_dpll = 0; +			break; +		case 5: +			ppi[0] = &info_hpt372; +			chip_table = &hpt372; +			break; +		default: +			pr_err("Unknown HPT366 subtype, please report (%d)\n", +			       rev); +			return -ENODEV;  		} +		break; +	case PCI_DEVICE_ID_TTI_HPT372: +		/* 372N if rev >= 2 */ +		if (rev >= 2) +			return -ENODEV; +		ppi[0] = &info_hpt372; +		chip_table = &hpt372a; +		break; +	case PCI_DEVICE_ID_TTI_HPT302: +		/* 302N if rev > 1 */ +		if (rev > 1) +			return -ENODEV; +		ppi[0] = &info_hpt302; +		/* Check this */ +		chip_table = &hpt302; +		break; +	case PCI_DEVICE_ID_TTI_HPT371: +		if (rev > 1) +			return -ENODEV; +		ppi[0] = &info_hpt302; +		chip_table = &hpt371; +		/* +		 * Single channel device, master is not present but the BIOS +		 * (or us for non x86) must mark it absent +		 */ +		pci_read_config_byte(dev, 0x50, &mcr1); +		mcr1 &= ~0x04; +		pci_write_config_byte(dev, 0x50, mcr1); +		break; +	case PCI_DEVICE_ID_TTI_HPT374: +		chip_table = &hpt374; +		if (!(PCI_FUNC(dev->devfn) & 1)) +			*ppi = &info_hpt374_fn0; +		else +			*ppi = &info_hpt374_fn1; +		break; +	default: +		pr_err("PCI table is bogus, please report (%d)\n", dev->device); +		return -ENODEV;  	}  	/* Ok so this is a chip we support */ @@ -893,9 +935,11 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)  	if (chip_table == &hpt372a)  		outb(0x0e, iobase + 0x9c); -	/* Some devices do not let this value be accessed via PCI space -	   according to the old driver. In addition we must use the value -	   from FN 0 on the HPT374 */ +	/* +	 * Some devices do not let this value be accessed via PCI space +	 * according to the old driver. In addition we must use the value +	 * from FN 0 on the HPT374. +	 */  	if (chip_table == &hpt374) {  		freq = hpt374_read_freq(dev); @@ -909,10 +953,10 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)  		u8 sr;  		u32 total = 0; -		printk(KERN_WARNING "pata_hpt37x: BIOS has not set timing clocks.\n"); +		pr_warn("BIOS has not set timing clocks\n");  		/* This is the process the HPT371 BIOS is reported to use */ -		for(i = 0; i < 128; i++) { +		for (i = 0; i < 128; i++) {  			pci_read_config_byte(dev, 0x78, &sr);  			total += sr & 0x1FF;  			udelay(15); @@ -947,20 +991,25 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)  		/* Select the DPLL clock. */  		pci_write_config_byte(dev, 0x5b, 0x21); -		pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); +		pci_write_config_dword(dev, 0x5C, +				       (f_high << 16) | f_low | 0x100); -		for(adjust = 0; adjust < 8; adjust++) { +		for (adjust = 0; adjust < 8; adjust++) {  			if (hpt37x_calibrate_dpll(dev))  				break; -			/* See if it'll settle at a fractionally different clock */ +			/* +			 * See if it'll settle at a fractionally +			 * different clock +			 */  			if (adjust & 1)  				f_low -= adjust >> 1;  			else  				f_high += adjust >> 1; -			pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); +			pci_write_config_dword(dev, 0x5C, +					       (f_high << 16) | f_low | 0x100);  		}  		if (adjust == 8) { -			printk(KERN_ERR "pata_hpt37x: DPLL did not stabilize!\n"); +			pr_err("DPLL did not stabilize!\n");  			return -ENODEV;  		}  		if (dpll == 3) @@ -968,22 +1017,23 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)  		else  			private_data = (void *)hpt37x_timings_50; -		printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using %dMHz DPLL.\n", -		       MHz[clock_slot], MHz[dpll]); +		pr_info("bus clock %dMHz, using %dMHz DPLL\n", +			MHz[clock_slot], MHz[dpll]);  	} else {  		private_data = (void *)chip_table->clocks[clock_slot];  		/*  		 *	Perform a final fixup. Note that we will have used the  		 *	DPLL on the HPT372 which means we don't have to worry  		 *	about lack of UDMA133 support on lower clocks - 		 */ +		 */  		if (clock_slot < 2 && ppi[0] == &info_hpt370)  			ppi[0] = &info_hpt370_33;  		if (clock_slot < 2 && ppi[0] == &info_hpt370a)  			ppi[0] = &info_hpt370a_33; -		printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n", -		       chip_table->name, MHz[clock_slot]); + +		pr_info("%s using %dMHz bus clock\n", +			chip_table->name, MHz[clock_slot]);  	}  	/* Now kick off ATA set up */ @@ -1001,27 +1051,16 @@ static const struct pci_device_id hpt37x[] = {  };  static struct pci_driver hpt37x_pci_driver = { -	.name 		= DRV_NAME, +	.name		= DRV_NAME,  	.id_table	= hpt37x, -	.probe 		= hpt37x_init_one, +	.probe		= hpt37x_init_one,  	.remove		= ata_pci_remove_one  }; -static int __init hpt37x_init(void) -{ -	return pci_register_driver(&hpt37x_pci_driver); -} - -static void __exit hpt37x_exit(void) -{ -	pci_unregister_driver(&hpt37x_pci_driver); -} +module_pci_driver(hpt37x_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for the Highpoint HPT37x/30x");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, hpt37x);  MODULE_VERSION(DRV_VERSION); - -module_init(hpt37x_init); -module_exit(hpt37x_exit); diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index 32f3463216b..b93c0f0729e 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -1,5 +1,5 @@  /* - * Libata driver for the highpoint 372N and 302N UDMA66 ATA controllers. + * Libata driver for the HighPoint 371N, 372N, and 302N UDMA66 ATA controllers.   *   * This driver is heavily based upon:   * @@ -8,24 +8,25 @@   * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>   * Portions Copyright (C) 2001	        Sun Microsystems, Inc.   * Portions Copyright (C) 2003		Red Hat Inc - * Portions Copyright (C) 2005-2009	MontaVista Software, Inc. + * Portions Copyright (C) 2005-2010	MontaVista Software, Inc.   *   *   * TODO   *	Work out best PLL policy   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h>  #include <linux/libata.h>  #define DRV_NAME	"pata_hpt3x2n" -#define DRV_VERSION	"0.3.10" +#define DRV_VERSION	"0.3.15"  enum {  	HPT_PCI_FAST	=	(1 << 31), @@ -103,7 +104,7 @@ static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed)  {  	struct hpt_clock *clocks = hpt3x2n_clocks; -	while(clocks->xfer_speed) { +	while (clocks->xfer_speed) {  		if (clocks->xfer_speed == speed)  			return clocks->timing;  		clocks++; @@ -113,6 +114,22 @@ static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed)  }  /** + *	hpt372n_filter	-	mode selection filter + *	@adev: ATA device + *	@mask: mode mask + * + *	The Marvell bridge chips used on the HighPoint SATA cards do not seem + *	to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes... + */ +static unsigned long hpt372n_filter(struct ata_device *adev, unsigned long mask) +{ +	if (ata_id_is_sata(adev->id)) +		mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA); + +	return mask; +} + +/**   *	hpt3x2n_cable_detect	-	Detect the cable type   *	@ap: ATA port to detect on   * @@ -153,6 +170,7 @@ static int hpt3x2n_pre_reset(struct ata_link *link, unsigned long deadline)  {  	struct ata_port *ap = link->ap;  	struct pci_dev *pdev = to_pci_dev(ap->host->dev); +  	/* Reset the state machine */  	pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);  	udelay(100); @@ -328,10 +346,10 @@ static struct scsi_host_template hpt3x2n_sht = {  };  /* - *	Configuration for HPT3x2n. + *	Configuration for HPT302N/371N.   */ -static struct ata_port_operations hpt3x2n_port_ops = { +static struct ata_port_operations hpt3xxn_port_ops = {  	.inherits	= &ata_bmdma_port_ops,  	.bmdma_stop	= hpt3x2n_bmdma_stop, @@ -345,6 +363,15 @@ static struct ata_port_operations hpt3x2n_port_ops = {  	.prereset	= hpt3x2n_pre_reset,  }; +/* + *	Configuration for HPT372N. Same as 302N/371N but we have a mode filter. + */ + +static struct ata_port_operations hpt372n_port_ops = { +	.inherits	= &hpt3xxn_port_ops, +	.mode_filter	= &hpt372n_filter, +}; +  /**   *	hpt3xn_calibrate_dpll		-	Calibrate the DPLL loop   *	@dev: PCI device @@ -359,12 +386,12 @@ static int hpt3xn_calibrate_dpll(struct pci_dev *dev)  	u32 reg5c;  	int tries; -	for(tries = 0; tries < 0x5000; tries++) { +	for (tries = 0; tries < 0x5000; tries++) {  		udelay(50);  		pci_read_config_byte(dev, 0x5b, ®5b);  		if (reg5b & 0x80) {  			/* See if it stays set */ -			for(tries = 0; tries < 0x1000; tries ++) { +			for (tries = 0; tries < 0x1000; tries++) {  				pci_read_config_byte(dev, 0x5b, ®5b);  				/* Failed ? */  				if ((reg5b & 0x80) == 0) @@ -372,7 +399,7 @@ static int hpt3xn_calibrate_dpll(struct pci_dev *dev)  			}  			/* Turn off tuning, we have the DPLL set */  			pci_read_config_dword(dev, 0x5c, ®5c); -			pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100); +			pci_write_config_dword(dev, 0x5c, reg5c & ~0x100);  			return 1;  		}  	} @@ -388,8 +415,19 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev)  	fcnt = inl(iobase + 0x90);	/* Not PCI readable for some chips */  	if ((fcnt >> 12) != 0xABCDE) { -		printk(KERN_WARNING "hpt3xn: BIOS clock data not set.\n"); -		return 33;	/* Not BIOS set */ +		int i; +		u16 sr; +		u32 total = 0; + +		pr_warn("BIOS clock data not set\n"); + +		/* This is the process the HPT371 BIOS is reported to use */ +		for (i = 0; i < 128; i++) { +			pci_read_config_word(pdev, 0x78, &sr); +			total += sr & 0x1FF; +			udelay(15); +		} +		fcnt = total / 128;  	}  	fcnt &= 0x1FF; @@ -431,21 +469,27 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev)   *	HPT372N			9 (HPT372N)	*	UDMA133   *   *	(1) UDMA133 support depends on the bus clock - * - *	To pin down		HPT371N   */  static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)  { -	/* HPT372N and friends - UDMA133 */ -	static const struct ata_port_info info = { +	/* HPT372N - UDMA133 */ +	static const struct ata_port_info info_hpt372n = {  		.flags = ATA_FLAG_SLAVE_POSS,  		.pio_mask = ATA_PIO4,  		.mwdma_mask = ATA_MWDMA2,  		.udma_mask = ATA_UDMA6, -		.port_ops = &hpt3x2n_port_ops +		.port_ops = &hpt372n_port_ops  	}; -	const struct ata_port_info *ppi[] = { &info, NULL }; +	/* HPT302N and HPT371N - UDMA133 */ +	static const struct ata_port_info info_hpt3xxn = { +		.flags = ATA_FLAG_SLAVE_POSS, +		.pio_mask = ATA_PIO4, +		.mwdma_mask = ATA_MWDMA2, +		.udma_mask = ATA_UDMA6, +		.port_ops = &hpt3xxn_port_ops +	}; +	const struct ata_port_info *ppi[] = { &info_hpt3xxn, NULL };  	u8 rev = dev->revision;  	u8 irqmask;  	unsigned int pci_mhz; @@ -459,30 +503,34 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)  	if (rc)  		return rc; -	switch(dev->device) { -		case PCI_DEVICE_ID_TTI_HPT366: -			if (rev < 6) -				return -ENODEV; -			break; -		case PCI_DEVICE_ID_TTI_HPT371: -			if (rev < 2) -				return -ENODEV; -			/* 371N if rev > 1 */ -			break; -		case PCI_DEVICE_ID_TTI_HPT372: -			/* 372N if rev >= 2*/ -			if (rev < 2) -				return -ENODEV; -			break; -		case PCI_DEVICE_ID_TTI_HPT302: -			if (rev < 2) -				return -ENODEV; -			break; -		case PCI_DEVICE_ID_TTI_HPT372N: -			break; -		default: -			printk(KERN_ERR "pata_hpt3x2n: PCI table is bogus please report (%d).\n", dev->device); +	switch (dev->device) { +	case PCI_DEVICE_ID_TTI_HPT366: +		/* 372N if rev >= 6 */ +		if (rev < 6)  			return -ENODEV; +		goto hpt372n; +	case PCI_DEVICE_ID_TTI_HPT371: +		/* 371N if rev >= 2 */ +		if (rev < 2) +			return -ENODEV; +		break; +	case PCI_DEVICE_ID_TTI_HPT372: +		/* 372N if rev >= 2 */ +		if (rev < 2) +			return -ENODEV; +		goto hpt372n; +	case PCI_DEVICE_ID_TTI_HPT302: +		/* 302N if rev >= 2 */ +		if (rev < 2) +			return -ENODEV; +		break; +	case PCI_DEVICE_ID_TTI_HPT372N: +hpt372n: +		ppi[0] = &info_hpt372n; +		break; +	default: +		pr_err("PCI table is bogus, please report (%d)\n", dev->device); +		return -ENODEV;  	}  	/* Ok so this is a chip we support */ @@ -509,8 +557,10 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)  		pci_write_config_byte(dev, 0x50, mcr1);  	} -	/* Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or -	   50 for UDMA100. Right now we always use 66 */ +	/* +	 * Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or +	 * 50 for UDMA100. Right now we always use 66 +	 */  	pci_mhz = hpt3x2n_pci_clock(dev); @@ -522,20 +572,22 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)  	pci_write_config_byte(dev, 0x5B, 0x21);  	/* Unlike the 37x we don't try jiggling the frequency */ -	for(adjust = 0; adjust < 8; adjust++) { +	for (adjust = 0; adjust < 8; adjust++) {  		if (hpt3xn_calibrate_dpll(dev))  			break;  		pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low);  	}  	if (adjust == 8) { -		printk(KERN_ERR "pata_hpt3x2n: DPLL did not stabilize!\n"); +		pr_err("DPLL did not stabilize!\n");  		return -ENODEV;  	} -	printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using 66MHz DPLL.\n", -	       pci_mhz); -	/* Set our private data up. We only need a few flags so we use -	   it directly */ +	pr_info("bus clock %dMHz, using 66MHz DPLL\n", pci_mhz); + +	/* +	 * Set our private data up. We only need a few flags +	 * so we use it directly. +	 */  	if (pci_mhz > 60)  		hpriv = (void *)(PCI66 | USE_DPLL); @@ -562,27 +614,16 @@ static const struct pci_device_id hpt3x2n[] = {  };  static struct pci_driver hpt3x2n_pci_driver = { -	.name 		= DRV_NAME, +	.name		= DRV_NAME,  	.id_table	= hpt3x2n, -	.probe 		= hpt3x2n_init_one, +	.probe		= hpt3x2n_init_one,  	.remove		= ata_pci_remove_one  }; -static int __init hpt3x2n_init(void) -{ -	return pci_register_driver(&hpt3x2n_pci_driver); -} - -static void __exit hpt3x2n_exit(void) -{ -	pci_unregister_driver(&hpt3x2n_pci_driver); -} +module_pci_driver(hpt3x2n_pci_driver);  MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for the Highpoint HPT3x2n/30x"); +MODULE_DESCRIPTION("low-level driver for the Highpoint HPT3xxN");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, hpt3x2n);  MODULE_VERSION(DRV_VERSION); - -module_init(hpt3x2n_init); -module_exit(hpt3x2n_exit); diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index b63d5e2d462..d019cdd5bc9 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -16,7 +16,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -151,7 +150,7 @@ static struct ata_port_operations hpt3x3_port_ops = {  	.check_atapi_dma= hpt3x3_atapi_dma,  	.freeze		= hpt3x3_freeze,  #endif -	 +  };  /** @@ -185,7 +184,6 @@ static void hpt3x3_init_chipset(struct pci_dev *dev)  static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  { -	static int printed_version;  	static const struct ata_port_info info = {  		.flags = ATA_FLAG_SLAVE_POSS,  		.pio_mask = ATA_PIO4, @@ -206,8 +204,7 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  	hpt3x3_init_chipset(pdev); -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);  	if (!host) @@ -252,10 +249,10 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  				 IRQF_SHARED, &hpt3x3_sht);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int hpt3x3_reinit_one(struct pci_dev *dev)  { -	struct ata_host *host = dev_get_drvdata(&dev->dev); +	struct ata_host *host = pci_get_drvdata(dev);  	int rc;  	rc = ata_pci_device_do_resume(dev); @@ -280,29 +277,16 @@ static struct pci_driver hpt3x3_pci_driver = {  	.id_table	= hpt3x3,  	.probe 		= hpt3x3_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= hpt3x3_reinit_one,  #endif  }; -static int __init hpt3x3_init(void) -{ -	return pci_register_driver(&hpt3x3_pci_driver); -} - - -static void __exit hpt3x3_exit(void) -{ -	pci_unregister_driver(&hpt3x3_pci_driver); -} - +module_pci_driver(hpt3x3_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for the Highpoint HPT343/363");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, hpt3x3);  MODULE_VERSION(DRV_VERSION); - -module_init(hpt3x3_init); -module_exit(hpt3x3_exit); diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index 9f2889fe43b..d7c732042a4 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -210,8 +210,8 @@ static void pata_icside_set_dmamode(struct ata_port *ap, struct ata_device *adev  	else  		iomd_type = 'A', cycle = 562; -	ata_dev_printk(adev, KERN_INFO, "timings: act %dns rec %dns cyc %dns (%c)\n", -		t.active, t.recover, t.cycle, iomd_type); +	ata_dev_info(adev, "timings: act %dns rec %dns cyc %dns (%c)\n", +		     t.active, t.recover, t.cycle, iomd_type);  	state->port[ap->port_no].speed[adev->devno] = cycle;  } @@ -337,10 +337,9 @@ static struct ata_port_operations pata_icside_port_ops = {  	.port_start		= ATA_OP_NULL,	/* don't need PRD table */  }; -static void __devinit -pata_icside_setup_ioaddr(struct ata_port *ap, void __iomem *base, -			 struct pata_icside_info *info, -			 const struct portinfo *port) +static void pata_icside_setup_ioaddr(struct ata_port *ap, void __iomem *base, +				     struct pata_icside_info *info, +				     const struct portinfo *port)  {  	struct ata_ioports *ioaddr = &ap->ioaddr;  	void __iomem *cmd = base + port->dataoffset; @@ -368,7 +367,7 @@ pata_icside_setup_ioaddr(struct ata_port *ap, void __iomem *base,  		ata_port_desc(ap, "iocbase 0x%lx", info->raw_ioc_base);  } -static int __devinit pata_icside_register_v5(struct pata_icside_info *info) +static int pata_icside_register_v5(struct pata_icside_info *info)  {  	struct pata_icside_state *state = info->state;  	void __iomem *base; @@ -391,7 +390,7 @@ static int __devinit pata_icside_register_v5(struct pata_icside_info *info)  	return 0;  } -static int __devinit pata_icside_register_v6(struct pata_icside_info *info) +static int pata_icside_register_v6(struct pata_icside_info *info)  {  	struct pata_icside_state *state = info->state;  	struct expansion_card *ec = info->ec; @@ -434,7 +433,7 @@ static int __devinit pata_icside_register_v6(struct pata_icside_info *info)  	return icside_dma_init(info);  } -static int __devinit pata_icside_add_ports(struct pata_icside_info *info) +static int pata_icside_add_ports(struct pata_icside_info *info)  {  	struct expansion_card *ec = info->ec;  	struct ata_host *host; @@ -474,8 +473,8 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)  				 &pata_icside_sht);  } -static int __devinit -pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id) +static int pata_icside_probe(struct expansion_card *ec, +			     const struct ecard_id *id)  {  	struct pata_icside_state *state;  	struct pata_icside_info info; @@ -575,7 +574,7 @@ static void pata_icside_shutdown(struct expansion_card *ec)  	}  } -static void __devexit pata_icside_remove(struct expansion_card *ec) +static void pata_icside_remove(struct expansion_card *ec)  {  	struct ata_host *host = ecard_get_drvdata(ec);  	struct pata_icside_state *state = host->private_data; @@ -602,7 +601,7 @@ static const struct ecard_id pata_icside_ids[] = {  static struct ecard_driver pata_icside_driver = {  	.probe		= pata_icside_probe, -	.remove 	= __devexit_p(pata_icside_remove), +	.remove 	= pata_icside_remove,  	.shutdown	= pata_icside_shutdown,  	.id_table	= pata_icside_ids,  	.drv = { diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c new file mode 100644 index 00000000000..af424573c2f --- /dev/null +++ b/drivers/ata/pata_imx.c @@ -0,0 +1,258 @@ +/* + * Freescale iMX PATA driver + * + * Copyright (C) 2011 Arnaud Patard <arnaud.patard@rtp-net.org> + * + * Based on pata_platform - Copyright (C) 2006 - 2007  Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * TODO: + * - dmaengine support + * - check if timing stuff needed + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/blkdev.h> +#include <scsi/scsi_host.h> +#include <linux/ata.h> +#include <linux/libata.h> +#include <linux/platform_device.h> +#include <linux/clk.h> + +#define DRV_NAME "pata_imx" + +#define PATA_IMX_ATA_CONTROL		0x24 +#define PATA_IMX_ATA_CTRL_FIFO_RST_B	(1<<7) +#define PATA_IMX_ATA_CTRL_ATA_RST_B	(1<<6) +#define PATA_IMX_ATA_CTRL_IORDY_EN	(1<<0) +#define PATA_IMX_ATA_INT_EN		0x2C +#define PATA_IMX_ATA_INTR_ATA_INTRQ2	(1<<3) +#define PATA_IMX_DRIVE_DATA		0xA0 +#define PATA_IMX_DRIVE_CONTROL		0xD8 + +struct pata_imx_priv { +	struct clk *clk; +	/* timings/interrupt/control regs */ +	void __iomem *host_regs; +	u32 ata_ctl; +}; + +static int pata_imx_set_mode(struct ata_link *link, struct ata_device **unused) +{ +	struct ata_device *dev; +	struct ata_port *ap = link->ap; +	struct pata_imx_priv *priv = ap->host->private_data; +	u32 val; + +	ata_for_each_dev(dev, link, ENABLED) { +		dev->pio_mode = dev->xfer_mode = XFER_PIO_0; +		dev->xfer_shift = ATA_SHIFT_PIO; +		dev->flags |= ATA_DFLAG_PIO; + +		val = __raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL); +		if (ata_pio_need_iordy(dev)) +			val |= PATA_IMX_ATA_CTRL_IORDY_EN; +		else +			val &= ~PATA_IMX_ATA_CTRL_IORDY_EN; +		__raw_writel(val, priv->host_regs + PATA_IMX_ATA_CONTROL); + +		ata_dev_info(dev, "configured for PIO\n"); +	} +	return 0; +} + +static struct scsi_host_template pata_imx_sht = { +	ATA_PIO_SHT(DRV_NAME), +}; + +static struct ata_port_operations pata_imx_port_ops = { +	.inherits		= &ata_sff_port_ops, +	.sff_data_xfer		= ata_sff_data_xfer_noirq, +	.cable_detect		= ata_cable_unknown, +	.set_mode		= pata_imx_set_mode, +}; + +static void pata_imx_setup_port(struct ata_ioports *ioaddr) +{ +	/* Fixup the port shift for platforms that need it */ +	ioaddr->data_addr	= ioaddr->cmd_addr + (ATA_REG_DATA    << 2); +	ioaddr->error_addr	= ioaddr->cmd_addr + (ATA_REG_ERR     << 2); +	ioaddr->feature_addr	= ioaddr->cmd_addr + (ATA_REG_FEATURE << 2); +	ioaddr->nsect_addr	= ioaddr->cmd_addr + (ATA_REG_NSECT   << 2); +	ioaddr->lbal_addr	= ioaddr->cmd_addr + (ATA_REG_LBAL    << 2); +	ioaddr->lbam_addr	= ioaddr->cmd_addr + (ATA_REG_LBAM    << 2); +	ioaddr->lbah_addr	= ioaddr->cmd_addr + (ATA_REG_LBAH    << 2); +	ioaddr->device_addr	= ioaddr->cmd_addr + (ATA_REG_DEVICE  << 2); +	ioaddr->status_addr	= ioaddr->cmd_addr + (ATA_REG_STATUS  << 2); +	ioaddr->command_addr	= ioaddr->cmd_addr + (ATA_REG_CMD     << 2); +} + +static int pata_imx_probe(struct platform_device *pdev) +{ +	struct ata_host *host; +	struct ata_port *ap; +	struct pata_imx_priv *priv; +	int irq = 0; +	struct resource *io_res; +	int ret; + +	irq = platform_get_irq(pdev, 0); +	if (irq < 0) +		return irq; + +	priv = devm_kzalloc(&pdev->dev, +				sizeof(struct pata_imx_priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	priv->clk = devm_clk_get(&pdev->dev, NULL); +	if (IS_ERR(priv->clk)) { +		dev_err(&pdev->dev, "Failed to get clock\n"); +		return PTR_ERR(priv->clk); +	} + +	ret = clk_prepare_enable(priv->clk); +	if (ret) +		return ret; + +	host = ata_host_alloc(&pdev->dev, 1); +	if (!host) { +		ret = -ENOMEM; +		goto err; +	} + +	host->private_data = priv; +	ap = host->ports[0]; + +	ap->ops = &pata_imx_port_ops; +	ap->pio_mask = ATA_PIO0; +	ap->flags |= ATA_FLAG_SLAVE_POSS; + +	io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	priv->host_regs = devm_ioremap_resource(&pdev->dev, io_res); +	if (IS_ERR(priv->host_regs)) { +		ret = PTR_ERR(priv->host_regs); +		goto err; +	} + +	ap->ioaddr.cmd_addr = priv->host_regs + PATA_IMX_DRIVE_DATA; +	ap->ioaddr.ctl_addr = priv->host_regs + PATA_IMX_DRIVE_CONTROL; + +	ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr; + +	pata_imx_setup_port(&ap->ioaddr); + +	ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx", +		(unsigned long long)io_res->start + PATA_IMX_DRIVE_DATA, +		(unsigned long long)io_res->start + PATA_IMX_DRIVE_CONTROL); + +	/* deassert resets */ +	__raw_writel(PATA_IMX_ATA_CTRL_FIFO_RST_B | +			PATA_IMX_ATA_CTRL_ATA_RST_B, +			priv->host_regs + PATA_IMX_ATA_CONTROL); +	/* enable interrupts */ +	__raw_writel(PATA_IMX_ATA_INTR_ATA_INTRQ2, +			priv->host_regs + PATA_IMX_ATA_INT_EN); + +	/* activate */ +	ret = ata_host_activate(host, irq, ata_sff_interrupt, 0, +				&pata_imx_sht); + +	if (ret) +		goto err; + +	return 0; +err: +	clk_disable_unprepare(priv->clk); + +	return ret; +} + +static int pata_imx_remove(struct platform_device *pdev) +{ +	struct ata_host *host = platform_get_drvdata(pdev); +	struct pata_imx_priv *priv = host->private_data; + +	ata_host_detach(host); + +	__raw_writel(0, priv->host_regs + PATA_IMX_ATA_INT_EN); + +	clk_disable_unprepare(priv->clk); + +	return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int pata_imx_suspend(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	struct pata_imx_priv *priv = host->private_data; +	int ret; + +	ret = ata_host_suspend(host, PMSG_SUSPEND); +	if (!ret) { +		__raw_writel(0, priv->host_regs + PATA_IMX_ATA_INT_EN); +		priv->ata_ctl = +			__raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL); +		clk_disable_unprepare(priv->clk); +	} + +	return ret; +} + +static int pata_imx_resume(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	struct pata_imx_priv *priv = host->private_data; + +	int ret = clk_prepare_enable(priv->clk); +	if (ret) +		return ret; + +	__raw_writel(priv->ata_ctl, priv->host_regs + PATA_IMX_ATA_CONTROL); + +	__raw_writel(PATA_IMX_ATA_INTR_ATA_INTRQ2, +			priv->host_regs + PATA_IMX_ATA_INT_EN); + +	ata_host_resume(host); + +	return 0; +} + +static const struct dev_pm_ops pata_imx_pm_ops = { +	.suspend	= pata_imx_suspend, +	.resume		= pata_imx_resume, +}; +#endif + +static const struct of_device_id imx_pata_dt_ids[] = { +	{ +		.compatible = "fsl,imx27-pata", +	}, { +		/* sentinel */ +	} +}; +MODULE_DEVICE_TABLE(of, imx_pata_dt_ids); + +static struct platform_driver pata_imx_driver = { +	.probe		= pata_imx_probe, +	.remove		= pata_imx_remove, +	.driver = { +		.name		= DRV_NAME, +		.of_match_table	= imx_pata_dt_ids, +		.owner		= THIS_MODULE, +#ifdef CONFIG_PM_SLEEP +		.pm		= &pata_imx_pm_ops, +#endif +	}, +}; + +module_platform_driver(pata_imx_driver); + +MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); +MODULE_DESCRIPTION("low-level driver for iMX PATA"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index 4bceb8803a1..b33d1f99b3a 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -78,7 +78,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev  	ap->ioaddr.cmd_addr = cmd_addr; -	if (pnp_port_valid(idev, 1) == 0) { +	if (pnp_port_valid(idev, 1)) {  		ctl_addr = devm_ioport_map(&idev->dev,  					   pnp_port_start(idev, 1), 1);  		ap->ioaddr.altstatus_addr = ctl_addr; diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c index 4d142a2ab8f..4f97d1e52f8 100644 --- a/drivers/ata/pata_it8213.c +++ b/drivers/ata/pata_it8213.c @@ -10,7 +10,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -76,8 +75,8 @@ static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev)  {  	unsigned int pio	= adev->pio_mode - XFER_PIO_0;  	struct pci_dev *dev	= to_pci_dev(ap->host->dev); -	unsigned int idetm_port= ap->port_no ? 0x42 : 0x40; -	u16 idetm_data; +	unsigned int master_port = ap->port_no ? 0x42 : 0x40; +	u16 master_data;  	int control = 0;  	/* @@ -100,19 +99,19 @@ static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev)  	if (adev->class != ATA_DEV_ATA)  		control |= 4;	/* PPE */ -	pci_read_config_word(dev, idetm_port, &idetm_data); +	pci_read_config_word(dev, master_port, &master_data);  	/* Set PPE, IE, and TIME as appropriate */  	if (adev->devno == 0) { -		idetm_data &= 0xCCF0; -		idetm_data |= control; -		idetm_data |= (timings[pio][0] << 12) | +		master_data &= 0xCCF0; +		master_data |= control; +		master_data |= (timings[pio][0] << 12) |  			(timings[pio][1] << 8);  	} else {  		u8 slave_data; -		idetm_data &= 0xFF0F; -		idetm_data |= (control << 4); +		master_data &= 0xFF0F; +		master_data |= (control << 4);  		/* Slave timing in separate register */  		pci_read_config_byte(dev, 0x44, &slave_data); @@ -121,8 +120,8 @@ static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev)  		pci_write_config_byte(dev, 0x44, slave_data);  	} -	idetm_data |= 0x4000;	/* Ensure SITRE is set */ -	pci_write_config_word(dev, idetm_port, idetm_data); +	master_data |= 0x4000;	/* Ensure SITRE is set */ +	pci_write_config_word(dev, master_port, master_data);  }  /** @@ -163,7 +162,7 @@ static void it8213_set_dmamode (struct ata_port *ap, struct ata_device *adev)  		/* Clocks follow the PIIX style */  		u_speed = min(2 - (udma & 1), udma); -		if (udma == 5) +		if (udma > 4)  			u_clock = 0x1000;	/* 100Mhz */  		else if (udma > 2)  			u_clock = 1;		/* 66Mhz */ @@ -258,20 +257,17 @@ static struct ata_port_operations it8213_ops = {  static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	static const struct ata_port_info info = {  		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4,  		.mwdma_mask	= ATA_MWDMA12_ONLY, -		.udma_mask 	= ATA_UDMA4, /* FIXME: want UDMA 100? */ +		.udma_mask	= ATA_UDMA6,  		.port_ops	= &it8213_ops,  	};  	/* Current IT8213 stuff is single port */  	const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	return ata_pci_bmdma_init_one(pdev, ppi, &it8213_sht, NULL, 0);  } @@ -287,24 +283,13 @@ static struct pci_driver it8213_pci_driver = {  	.id_table		= it8213_pci_tbl,  	.probe			= it8213_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ata_pci_device_resume,  #endif  }; -static int __init it8213_init(void) -{ -	return pci_register_driver(&it8213_pci_driver); -} - -static void __exit it8213_exit(void) -{ -	pci_unregister_driver(&it8213_pci_driver); -} - -module_init(it8213_init); -module_exit(it8213_exit); +module_pci_driver(it8213_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("SCSI low-level driver for the ITE 8213"); diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index aa0e0c51cc0..a5088ecb349 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -72,7 +72,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/slab.h> @@ -473,12 +472,12 @@ static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unus  		/* We do need the right mode information for DMA or PIO  		   and this comes from the current configuration flags */  		if (ata_id_has_dma(dev->id)) { -			ata_dev_printk(dev, KERN_INFO, "configured for DMA\n"); +			ata_dev_info(dev, "configured for DMA\n");  			dev->xfer_mode = XFER_MW_DMA_0;  			dev->xfer_shift = ATA_SHIFT_MWDMA;  			dev->flags &= ~ATA_DFLAG_PIO;  		} else { -			ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); +			ata_dev_info(dev, "configured for PIO\n");  			dev->xfer_mode = XFER_PIO_0;  			dev->xfer_shift = ATA_SHIFT_PIO;  			dev->flags |= ATA_DFLAG_PIO; @@ -508,12 +507,12 @@ static void it821x_dev_config(struct ata_device *adev)  	if (strstr(model_num, "Integrated Technology Express")) {  		/* RAID mode */ -		ata_dev_printk(adev, KERN_INFO, "%sRAID%d volume", -			adev->id[147]?"Bootable ":"", -			adev->id[129]); +		ata_dev_info(adev, "%sRAID%d volume", +			     adev->id[147] ? "Bootable " : "", +			     adev->id[129]);  		if (adev->id[129] != 1) -			printk("(%dK stripe)", adev->id[146]); -		printk(".\n"); +			pr_cont("(%dK stripe)", adev->id[146]); +		pr_cont("\n");  	}  	/* This is a controller firmware triggered funny, don't  	   report the drive faulty! */ @@ -610,13 +609,13 @@ static void it821x_display_disk(int n, u8 *buf)  	char *cbl = "(40 wire cable)";  	static const char *types[5] = { -		"RAID0", "RAID1" "RAID 0+1", "JBOD", "DISK" +		"RAID0", "RAID1", "RAID 0+1", "JBOD", "DISK"  	};  	if (buf[52] > 4)	/* No Disk */  		return; -	ata_id_c_string((u16 *)buf, id, 0, 41);  +	ata_id_c_string((u16 *)buf, id, 0, 41);  	if (buf[51]) {  		mode = ffs(buf[51]); @@ -910,7 +909,7 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  	rc = pcim_enable_device(pdev);  	if (rc)  		return rc; -		 +  	if (pdev->vendor == PCI_VENDOR_ID_RDC) {  		/* Deal with Vortex86SX */  		if (pdev->revision == 0x11) @@ -936,10 +935,10 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  	return ata_pci_bmdma_init_one(pdev, ppi, &it821x_sht, NULL, 0);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int it821x_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -966,21 +965,13 @@ static struct pci_driver it821x_pci_driver = {  	.id_table	= it821x,  	.probe 		= it821x_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= it821x_reinit_one,  #endif  }; -static int __init it821x_init(void) -{ -	return pci_register_driver(&it821x_pci_driver); -} - -static void __exit it821x_exit(void) -{ -	pci_unregister_driver(&it821x_pci_driver); -} +module_pci_driver(it821x_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for the IT8211/IT8212 IDE RAID controller"); @@ -988,9 +979,5 @@ MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, it821x);  MODULE_VERSION(DRV_VERSION); -  module_param_named(noraid, it8212_noraid, int, S_IRUGO);  MODULE_PARM_DESC(noraid, "Force card into bypass mode"); - -module_init(it821x_init); -module_exit(it821x_exit); diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index ba54b089f98..ddf470c2341 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -31,7 +31,7 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)  	struct ata_device *dev;  	ata_for_each_dev(dev, link, ENABLED) { -		ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); +		ata_dev_info(dev, "configured for PIO0\n");  		dev->pio_mode = XFER_PIO_0;  		dev->xfer_mode = XFER_PIO_0;  		dev->xfer_shift = ATA_SHIFT_PIO; @@ -48,7 +48,7 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,  	u16 *buf16 = (u16 *) buf;  	struct ata_port *ap = dev->link->ap;  	void __iomem *mmio = ap->ioaddr.data_addr; -	struct ixp4xx_pata_data *data = ap->host->dev->platform_data; +	struct ixp4xx_pata_data *data = dev_get_platdata(ap->host->dev);  	/* set the expansion bus in 16bit mode and restore  	 * 8 bit mode after the transaction. @@ -137,13 +137,14 @@ static void ixp4xx_setup_port(struct ata_port *ap,  	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", raw_cmd, raw_ctl);  } -static __devinit int ixp4xx_pata_probe(struct platform_device *pdev) +static int ixp4xx_pata_probe(struct platform_device *pdev)  {  	unsigned int irq;  	struct resource *cs0, *cs1;  	struct ata_host *host;  	struct ata_port *ap; -	struct ixp4xx_pata_data *data = pdev->dev.platform_data; +	struct ixp4xx_pata_data *data = dev_get_platdata(&pdev->dev); +	int ret;  	cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); @@ -157,7 +158,9 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)  		return -ENOMEM;  	/* acquire resources and fill host */ -	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); +	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); +	if (ret) +		return ret;  	data->cs0 = devm_ioremap(&pdev->dev, cs0->start, 0x1000);  	data->cs1 = devm_ioremap(&pdev->dev, cs1->start, 0x1000); @@ -167,7 +170,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)  	irq = platform_get_irq(pdev, 0);  	if (irq) -		set_irq_type(irq, IRQ_TYPE_EDGE_RISING); +		irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);  	/* Setup expansion bus chip selects */  	*data->cs0_cfg = data->cs0_bits; @@ -177,49 +180,29 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)  	ap->ops	= &ixp4xx_port_ops;  	ap->pio_mask = ATA_PIO4; -	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI; +	ap->flags |= ATA_FLAG_NO_ATAPI;  	ixp4xx_setup_port(ap, data, cs0->start, cs1->start); -	dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* activate host */  	return ata_host_activate(host, irq, ata_sff_interrupt, 0, &ixp4xx_sht);  } -static __devexit int ixp4xx_pata_remove(struct platform_device *dev) -{ -	struct ata_host *host = platform_get_drvdata(dev); - -	ata_host_detach(host); - -	return 0; -} -  static struct platform_driver ixp4xx_pata_platform_driver = {  	.driver	 = {  		.name   = DRV_NAME,  		.owner  = THIS_MODULE,  	},  	.probe		= ixp4xx_pata_probe, -	.remove		= __devexit_p(ixp4xx_pata_remove), +	.remove		= ata_platform_remove_one,  }; -static int __init ixp4xx_pata_init(void) -{ -	return platform_driver_register(&ixp4xx_pata_platform_driver); -} - -static void __exit ixp4xx_pata_exit(void) -{ -	platform_driver_unregister(&ixp4xx_pata_platform_driver); -} +module_platform_driver(ixp4xx_pata_platform_driver);  MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");  MODULE_DESCRIPTION("low-level driver for ixp4xx Compact Flash PATA");  MODULE_LICENSE("GPL");  MODULE_VERSION(DRV_VERSION);  MODULE_ALIAS("platform:" DRV_NAME); - -module_init(ixp4xx_pata_init); -module_exit(ixp4xx_pata_exit); diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index cb3babbb703..4d1a5d2c428 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -10,7 +10,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -158,24 +157,13 @@ static struct pci_driver jmicron_pci_driver = {  	.id_table		= jmicron_pci_tbl,  	.probe			= jmicron_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ata_pci_device_resume,  #endif  }; -static int __init jmicron_init(void) -{ -	return pci_register_driver(&jmicron_pci_driver); -} - -static void __exit jmicron_exit(void) -{ -	pci_unregister_driver(&jmicron_pci_driver); -} - -module_init(jmicron_init); -module_exit(jmicron_exit); +module_pci_driver(jmicron_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("SCSI low-level driver for Jmicron PATA ports"); diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 6bd9425ba5a..bce2a8ca467 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -79,15 +79,6 @@ static int all;  module_param(all, int, 0444);  MODULE_PARM_DESC(all, "Grab all legacy port devices, even if PCI(0=off, 1=on)"); -struct legacy_data { -	unsigned long timing; -	u8 clock[2]; -	u8 last; -	int fast; -	struct platform_device *platform_dev; - -}; -  enum controller {  	BIOS = 0,  	SNOOP = 1, @@ -104,6 +95,14 @@ enum controller {  	UNKNOWN = -1  }; +struct legacy_data { +	unsigned long timing; +	u8 clock[2]; +	u8 last; +	int fast; +	enum controller type; +	struct platform_device *platform_dev; +};  struct legacy_probe {  	unsigned char *name; @@ -137,11 +136,17 @@ static int ht6560a;		/* HT 6560A on primary 1, second 2, both 3 */  static int ht6560b;		/* HT 6560A on primary 1, second 2, both 3 */  static int opti82c611a;		/* Opti82c611A on primary 1, sec 2, both 3 */  static int opti82c46x;		/* Opti 82c465MV present(pri/sec autodetect) */ -static int qdi;			/* Set to probe QDI controllers */  static int autospeed;		/* Chip present which snoops speed changes */  static int pio_mask = ATA_PIO4;	/* PIO range for autospeed devices */  static int iordy_mask = 0xFFFFFFFF;	/* Use iordy if available */ +/* Set to probe QDI controllers */ +#ifdef CONFIG_PATA_QDI_MODULE +static int qdi = 1; +#else +static int qdi; +#endif +  #ifdef CONFIG_PATA_WINBOND_VLB_MODULE  static int winbond = 1;		/* Set to probe Winbond controllers,  					give I/O port if non standard */ @@ -213,7 +218,7 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)  	struct ata_device *dev;  	ata_for_each_dev(dev, link, ENABLED) { -		ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); +		ata_dev_info(dev, "configured for PIO\n");  		dev->pio_mode = XFER_PIO_0;  		dev->xfer_mode = XFER_PIO_0;  		dev->xfer_shift = ATA_SHIFT_PIO; @@ -396,8 +401,7 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)  	ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);  	active = clamp_val(t.active, 2, 15); -	recover = clamp_val(t.recover, 2, 16); -	recover &= 0x15; +	recover = clamp_val(t.recover, 2, 16) & 0x0F;  	inb(0x3E6);  	inb(0x3E6); @@ -538,7 +542,7 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)  	u8 sysclk;  	/* Get the clock */ -	sysclk = opti_syscfg(0xAC) & 0xC0;	/* BIOS set */ +	sysclk = (opti_syscfg(0xAC) & 0xC0) >> 6;	/* BIOS set */  	/* Enter configuration mode */  	ioread16(ap->ioaddr.error_addr); @@ -631,40 +635,20 @@ static struct ata_port_operations opti82c46x_port_ops = {  	.qc_issue	= opti82c46x_qc_issue,  }; -static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ -	struct ata_timing t; -	struct legacy_data *ld_qdi = ap->host->private_data; -	int active, recovery; -	u8 timing; - -	/* Get the timing data in cycles */ -	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); - -	if (ld_qdi->fast) { -		active = 8 - clamp_val(t.active, 1, 8); -		recovery = 18 - clamp_val(t.recover, 3, 18); -	} else { -		active = 9 - clamp_val(t.active, 2, 9); -		recovery = 15 - clamp_val(t.recover, 0, 15); -	} -	timing = (recovery << 4) | active | 0x08; - -	ld_qdi->clock[adev->devno] = timing; - -	outb(timing, ld_qdi->timing); -} -  /** - *	qdi6580dp_set_piomode		-	PIO setup for dual channel + *	qdi65x0_set_piomode		-	PIO setup for QDI65x0   *	@ap: Port   *	@adev: Device   * + *	In single channel mode the 6580 has one clock per device and we can + *	avoid the requirement to clock switch. We also have to load the timing + *	into the right clock according to whether we are master or slave. + *   *	In dual channel mode the 6580 has one clock per channel and we have   *	to software clockswitch in qc_issue.   */ -static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev) +static void qdi65x0_set_piomode(struct ata_port *ap, struct ata_device *adev)  {  	struct ata_timing t;  	struct legacy_data *ld_qdi = ap->host->private_data; @@ -682,47 +666,15 @@ static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)  		recovery = 15 - clamp_val(t.recover, 0, 15);  	}  	timing = (recovery << 4) | active | 0x08; -  	ld_qdi->clock[adev->devno] = timing; -	outb(timing, ld_qdi->timing + 2 * ap->port_no); -	/* Clear the FIFO */ -	if (adev->class != ATA_DEV_ATA) -		outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3); -} - -/** - *	qdi6580_set_piomode		-	PIO setup for single channel - *	@ap: Port - *	@adev: Device - * - *	In single channel mode the 6580 has one clock per device and we can - *	avoid the requirement to clock switch. We also have to load the timing - *	into the right clock according to whether we are master or slave. - */ - -static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ -	struct ata_timing t; -	struct legacy_data *ld_qdi = ap->host->private_data; -	int active, recovery; -	u8 timing; - -	/* Get the timing data in cycles */ -	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); +	if (ld_qdi->type == QDI6580) +		outb(timing, ld_qdi->timing + 2 * adev->devno); +	else +		outb(timing, ld_qdi->timing + 2 * ap->port_no); -	if (ld_qdi->fast) { -		active = 8 - clamp_val(t.active, 1, 8); -		recovery = 18 - clamp_val(t.recover, 3, 18); -	} else { -		active = 9 - clamp_val(t.active, 2, 9); -		recovery = 15 - clamp_val(t.recover, 0, 15); -	} -	timing = (recovery << 4) | active | 0x08; -	ld_qdi->clock[adev->devno] = timing; -	outb(timing, ld_qdi->timing + 2 * adev->devno);  	/* Clear the FIFO */ -	if (adev->class != ATA_DEV_ATA) +	if (ld_qdi->type != QDI6500 && adev->class != ATA_DEV_ATA)  		outb(0x5F, (ld_qdi->timing & 0xFFF0) + 3);  } @@ -789,20 +741,20 @@ static int qdi_port(struct platform_device *dev,  static struct ata_port_operations qdi6500_port_ops = {  	.inherits	= &legacy_base_port_ops, -	.set_piomode	= qdi6500_set_piomode, +	.set_piomode	= qdi65x0_set_piomode,  	.qc_issue	= qdi_qc_issue,  	.sff_data_xfer	= vlb32_data_xfer,  };  static struct ata_port_operations qdi6580_port_ops = {  	.inherits	= &legacy_base_port_ops, -	.set_piomode	= qdi6580_set_piomode, +	.set_piomode	= qdi65x0_set_piomode,  	.sff_data_xfer	= vlb32_data_xfer,  };  static struct ata_port_operations qdi6580dp_port_ops = {  	.inherits	= &legacy_base_port_ops, -	.set_piomode	= qdi6580dp_set_piomode, +	.set_piomode	= qdi65x0_set_piomode,  	.qc_issue	= qdi_qc_issue,  	.sff_data_xfer	= vlb32_data_xfer,  }; @@ -879,29 +831,29 @@ static struct ata_port_operations winbond_port_ops = {  };  static struct legacy_controller controllers[] = { -	{"BIOS",	&legacy_port_ops, 	0x1F, +	{"BIOS",	&legacy_port_ops, 	ATA_PIO4,  			ATA_FLAG_NO_IORDY,	0,			NULL }, -	{"Snooping", 	&simple_port_ops, 	0x1F, +	{"Snooping", 	&simple_port_ops, 	ATA_PIO4,  			0,			0,			NULL }, -	{"PDC20230",	&pdc20230_port_ops,	0x7, +	{"PDC20230",	&pdc20230_port_ops,	ATA_PIO2,  			ATA_FLAG_NO_IORDY,  			ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,	NULL }, -	{"HT6560A",	&ht6560a_port_ops,	0x07, +	{"HT6560A",	&ht6560a_port_ops,	ATA_PIO2,  			ATA_FLAG_NO_IORDY,	0,			NULL }, -	{"HT6560B",	&ht6560b_port_ops,	0x1F, +	{"HT6560B",	&ht6560b_port_ops,	ATA_PIO4,  			ATA_FLAG_NO_IORDY,	0,			NULL }, -	{"OPTI82C611A",	&opti82c611a_port_ops,	0x0F, +	{"OPTI82C611A",	&opti82c611a_port_ops,	ATA_PIO3,  			0,			0,			NULL }, -	{"OPTI82C46X",	&opti82c46x_port_ops,	0x0F, +	{"OPTI82C46X",	&opti82c46x_port_ops,	ATA_PIO3,  			0,			0,			NULL }, -	{"QDI6500",	&qdi6500_port_ops,	0x07, +	{"QDI6500",	&qdi6500_port_ops,	ATA_PIO2,  			ATA_FLAG_NO_IORDY,  			ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,    qdi_port }, -	{"QDI6580",	&qdi6580_port_ops,	0x1F, +	{"QDI6580",	&qdi6580_port_ops,	ATA_PIO4,  			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port }, -	{"QDI6580DP",	&qdi6580dp_port_ops,	0x1F, +	{"QDI6580DP",	&qdi6580dp_port_ops,	ATA_PIO4,  			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE, qdi_port }, -	{"W83759A",	&winbond_port_ops,	0x1F, +	{"W83759A",	&winbond_port_ops,	ATA_PIO4,  			0, ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE,  								winbond_port }  }; @@ -964,7 +916,6 @@ static __init int probe_chip_type(struct legacy_probe *probe)  			local_irq_restore(flags);  			return BIOS;  		} -		local_irq_restore(flags);  	}  	if (ht6560a & mask) @@ -1022,6 +973,7 @@ static __init int legacy_init_one(struct legacy_probe *probe)  	ctrl_addr = devm_ioport_map(&pdev->dev, io + 0x0206, 1);  	if (!io_addr || !ctrl_addr)  		goto fail; +	ld->type = probe->type;  	if (controller->setup)  		if (controller->setup(pdev, probe, ld) < 0)  			goto fail; @@ -1306,6 +1258,7 @@ MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for legacy ATA");  MODULE_LICENSE("GPL");  MODULE_VERSION(DRV_VERSION); +MODULE_ALIAS("pata_qdi");  MODULE_ALIAS("pata_winbond");  module_param(probe_all, int, 0); diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c index 75b49d01780..a02f76fdcfc 100644 --- a/drivers/ata/pata_macio.c +++ b/drivers/ata/pata_macio.c @@ -772,8 +772,9 @@ static void pata_macio_reset_hw(struct pata_macio_priv *priv, int resume)  		pci_restore_state(priv->pdev);  		rc = pcim_enable_device(priv->pdev);  		if (rc) -			dev_printk(KERN_ERR, &priv->pdev->dev, -				   "Failed to enable device after resume (%d)\n", rc); +			dev_err(&priv->pdev->dev, +				"Failed to enable device after resume (%d)\n", +				rc);  		else  			pci_set_master(priv->pdev);  	} @@ -812,7 +813,7 @@ static int pata_macio_slave_config(struct scsi_device *sdev)  		blk_queue_update_dma_pad(sdev->request_queue, 31);  		/* Tell the world about it */ -		ata_dev_printk(dev, KERN_INFO, "OHare alignment limits applied\n"); +		ata_dev_info(dev, "OHare alignment limits applied\n");  		return 0;  	} @@ -838,15 +839,13 @@ static int pata_macio_slave_config(struct scsi_device *sdev)  				      cmd | PCI_COMMAND_INVALIDATE);  		/* Tell the world about it */ -		ata_dev_printk(dev, KERN_INFO, -			       "K2/Shasta alignment limits applied\n"); +		ata_dev_info(dev, "K2/Shasta alignment limits applied\n");  	}  	return 0;  } -#ifdef CONFIG_PM - +#ifdef CONFIG_PM_SLEEP  static int pata_macio_do_suspend(struct pata_macio_priv *priv, pm_message_t mesg)  {  	int rc; @@ -907,8 +906,7 @@ static int pata_macio_do_resume(struct pata_macio_priv *priv)  	return 0;  } - -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */  static struct scsi_host_template pata_macio_sht = {  	ATA_BASE_SHT(DRV_NAME), @@ -935,7 +933,7 @@ static struct ata_port_operations pata_macio_ops = {  	.sff_irq_clear		= pata_macio_irq_clear,  }; -static void __devinit pata_macio_invariants(struct pata_macio_priv *priv) +static void pata_macio_invariants(struct pata_macio_priv *priv)  {  	const int *bidp; @@ -976,9 +974,8 @@ static void __devinit pata_macio_invariants(struct pata_macio_priv *priv)  		priv->aapl_bus_id = 1;  } -static void __devinit pata_macio_setup_ios(struct ata_ioports *ioaddr, -					   void __iomem * base, -					   void __iomem * dma) +static void pata_macio_setup_ios(struct ata_ioports *ioaddr, +				 void __iomem * base, void __iomem * dma)  {  	/* cmd_addr is the base of regs for that port */  	ioaddr->cmd_addr	= base; @@ -999,8 +996,8 @@ static void __devinit pata_macio_setup_ios(struct ata_ioports *ioaddr,  	ioaddr->bmdma_addr	= dma;  } -static void __devinit pmac_macio_calc_timing_masks(struct pata_macio_priv *priv, -						   struct ata_port_info   *pinfo) +static void pmac_macio_calc_timing_masks(struct pata_macio_priv *priv, +					 struct ata_port_info *pinfo)  {  	int i = 0; @@ -1027,11 +1024,11 @@ static void __devinit pmac_macio_calc_timing_masks(struct pata_macio_priv *priv,  		pinfo->pio_mask, pinfo->mwdma_mask, pinfo->udma_mask);  } -static int __devinit pata_macio_common_init(struct pata_macio_priv	*priv, -					    resource_size_t		tfregs, -					    resource_size_t		dmaregs, -					    resource_size_t		fcregs, -					    unsigned long		irq) +static int pata_macio_common_init(struct pata_macio_priv *priv, +				  resource_size_t tfregs, +				  resource_size_t dmaregs, +				  resource_size_t fcregs, +				  unsigned long irq)  {  	struct ata_port_info		pinfo;  	const struct ata_port_info	*ppi[] = { &pinfo, NULL }; @@ -1053,8 +1050,7 @@ static int __devinit pata_macio_common_init(struct pata_macio_priv	*priv,  	/* Allocate libata host for 1 port */  	memset(&pinfo, 0, sizeof(struct ata_port_info));  	pmac_macio_calc_timing_masks(priv, &pinfo); -	pinfo.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | -				  ATA_FLAG_NO_LEGACY; +	pinfo.flags		= ATA_FLAG_SLAVE_POSS;  	pinfo.port_ops		= &pata_macio_ops;  	pinfo.private_data	= priv; @@ -1114,8 +1110,8 @@ static int __devinit pata_macio_common_init(struct pata_macio_priv	*priv,  				 &pata_macio_sht);  } -static int __devinit pata_macio_attach(struct macio_dev *mdev, -				       const struct of_device_id *match) +static int pata_macio_attach(struct macio_dev *mdev, +			     const struct of_device_id *match)  {  	struct pata_macio_priv	*priv;  	resource_size_t		tfregs, dmaregs = 0; @@ -1191,7 +1187,7 @@ static int __devinit pata_macio_attach(struct macio_dev *mdev,  	return rc;  } -static int __devexit pata_macio_detach(struct macio_dev *mdev) +static int pata_macio_detach(struct macio_dev *mdev)  {  	struct ata_host *host = macio_get_drvdata(mdev);  	struct pata_macio_priv *priv = host->private_data; @@ -1210,8 +1206,7 @@ static int __devexit pata_macio_detach(struct macio_dev *mdev)  	return 0;  } -#ifdef CONFIG_PM - +#ifdef CONFIG_PM_SLEEP  static int pata_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)  {  	struct ata_host *host = macio_get_drvdata(mdev); @@ -1225,8 +1220,7 @@ static int pata_macio_resume(struct macio_dev *mdev)  	return pata_macio_do_resume(host->private_data);  } - -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */  #ifdef CONFIG_PMAC_MEDIABAY  static void pata_macio_mb_event(struct macio_dev* mdev, int mb_state) @@ -1258,8 +1252,8 @@ static void pata_macio_mb_event(struct macio_dev* mdev, int mb_state)  #endif /* CONFIG_PMAC_MEDIABAY */ -static int __devinit pata_macio_pci_attach(struct pci_dev *pdev, -					   const struct pci_device_id *id) +static int pata_macio_pci_attach(struct pci_dev *pdev, +				 const struct pci_device_id *id)  {  	struct pata_macio_priv	*priv;  	struct device_node	*np; @@ -1311,30 +1305,28 @@ static int __devinit pata_macio_pci_attach(struct pci_dev *pdev,  	return 0;  } -static void __devexit pata_macio_pci_detach(struct pci_dev *pdev) +static void pata_macio_pci_detach(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	ata_host_detach(host);  } -#ifdef CONFIG_PM - +#ifdef CONFIG_PM_SLEEP  static int pata_macio_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	return pata_macio_do_suspend(host->private_data, mesg);  }  static int pata_macio_pci_resume(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	return pata_macio_do_resume(host->private_data);  } - -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */  static struct of_device_id pata_macio_match[] =  { @@ -1362,7 +1354,7 @@ static struct macio_driver pata_macio_driver =  	},  	.probe		= pata_macio_attach,  	.remove		= pata_macio_detach, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= pata_macio_suspend,  	.resume		= pata_macio_resume,  #endif @@ -1385,7 +1377,7 @@ static struct pci_driver pata_macio_pci_driver = {  	.id_table	= pata_macio_pci_match,  	.probe		= pata_macio_pci_attach,  	.remove		= pata_macio_pci_detach, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= pata_macio_pci_suspend,  	.resume		= pata_macio_pci_resume,  #endif diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index dd38083dcbe..ae9feb1ba8f 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -11,7 +11,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -38,7 +37,7 @@ static int marvell_pata_active(struct pci_dev *pdev)  	/* We don't yet know how to do this for other devices */  	if (pdev->device != 0x6145) -		return 1;	 +		return 1;  	barp = pci_iomap(pdev, 5, 0x10);  	if (barp == NULL) @@ -161,6 +160,9 @@ static const struct pci_device_id marvell_pci_tbl[] = {  	{ PCI_DEVICE(0x11AB, 0x6121), },  	{ PCI_DEVICE(0x11AB, 0x6123), },  	{ PCI_DEVICE(0x11AB, 0x6145), }, +	{ PCI_DEVICE(0x1B4B, 0x91A0), }, +	{ PCI_DEVICE(0x1B4B, 0x91A4), }, +  	{ }	/* terminate list */  }; @@ -169,28 +171,16 @@ static struct pci_driver marvell_pci_driver = {  	.id_table		= marvell_pci_tbl,  	.probe			= marvell_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ata_pci_device_resume,  #endif  }; -static int __init marvell_init(void) -{ -	return pci_register_driver(&marvell_pci_driver); -} - -static void __exit marvell_exit(void) -{ -	pci_unregister_driver(&marvell_pci_driver); -} - -module_init(marvell_init); -module_exit(marvell_exit); +module_pci_driver(marvell_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("SCSI low-level driver for Marvell ATA in legacy mode");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, marvell_pci_tbl);  MODULE_VERSION(DRV_VERSION); - diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index 8cc536e49a0..ccd1c83a05c 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -26,9 +26,9 @@  #include <asm/prom.h>  #include <asm/mpc52xx.h> -#include <sysdev/bestcomm/bestcomm.h> -#include <sysdev/bestcomm/bestcomm_priv.h> -#include <sysdev/bestcomm/ata.h> +#include <linux/fsl/bestcomm/bestcomm.h> +#include <linux/fsl/bestcomm/bestcomm_priv.h> +#include <linux/fsl/bestcomm/ata.h>  #define DRV_NAME	"mpc52xx_ata" @@ -610,7 +610,7 @@ static struct scsi_host_template mpc52xx_ata_sht = {  };  static struct ata_port_operations mpc52xx_ata_port_ops = { -	.inherits		= &ata_sff_port_ops, +	.inherits		= &ata_bmdma_port_ops,  	.sff_dev_select		= mpc52xx_ata_dev_select,  	.set_piomode		= mpc52xx_ata_set_piomode,  	.set_dmamode		= mpc52xx_ata_set_dmamode, @@ -621,9 +621,10 @@ static struct ata_port_operations mpc52xx_ata_port_ops = {  	.qc_prep		= ata_noop_qc_prep,  }; -static int __devinit -mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv, -		     unsigned long raw_ata_regs, int mwdma_mask, int udma_mask) +static int mpc52xx_ata_init_one(struct device *dev, +				struct mpc52xx_ata_priv *priv, +				unsigned long raw_ata_regs, +				int mwdma_mask, int udma_mask)  {  	struct ata_host *host;  	struct ata_port *ap; @@ -663,35 +664,22 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv,  				 &mpc52xx_ata_sht);  } -static struct mpc52xx_ata_priv * -mpc52xx_ata_remove_one(struct device *dev) -{ -	struct ata_host *host = dev_get_drvdata(dev); -	struct mpc52xx_ata_priv *priv = host->private_data; - -	ata_host_detach(host); - -	return priv; -} - -  /* ======================================================================== */  /* OF Platform driver                                                       */  /* ======================================================================== */ -static int __devinit -mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match) +static int mpc52xx_ata_probe(struct platform_device *op)  {  	unsigned int ipb_freq;  	struct resource res_mem;  	int ata_irq = 0;  	struct mpc52xx_ata __iomem *ata_regs;  	struct mpc52xx_ata_priv *priv = NULL; -	int rv, ret, task_irq = 0; +	int rv, task_irq;  	int mwdma_mask = 0, udma_mask = 0;  	const __be32 *prop;  	int proplen; -	struct bcom_task *dmatsk = NULL; +	struct bcom_task *dmatsk;  	/* Get ipb frequency */  	ipb_freq = mpc5xxx_get_bus_frequency(op->dev.of_node); @@ -717,8 +705,7 @@ mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match)  	ata_regs = devm_ioremap(&op->dev, res_mem.start, sizeof(*ata_regs));  	if (!ata_regs) {  		dev_err(&op->dev, "error mapping device registers\n"); -		rv = -ENOMEM; -		goto err; +		return -ENOMEM;  	}  	/* @@ -753,7 +740,7 @@ mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match)  	if (!priv) {  		dev_err(&op->dev, "error allocating private structure\n");  		rv = -ENOMEM; -		goto err; +		goto err1;  	}  	priv->ipb_period = 1000000000 / (ipb_freq / 1000); @@ -776,15 +763,15 @@ mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match)  	if (!dmatsk) {  		dev_err(&op->dev, "bestcomm initialization failed\n");  		rv = -ENOMEM; -		goto err; +		goto err1;  	}  	task_irq = bcom_get_task_irq(dmatsk); -	ret = request_irq(task_irq, &mpc52xx_ata_task_irq, IRQF_DISABLED, +	rv = devm_request_irq(&op->dev, task_irq, &mpc52xx_ata_task_irq, 0,  				"ATA task", priv); -	if (ret) { +	if (rv) {  		dev_err(&op->dev, "error requesting DMA IRQ\n"); -		goto err; +		goto err2;  	}  	priv->dmatsk = dmatsk; @@ -792,7 +779,7 @@ mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match)  	rv = mpc52xx_ata_hw_init(priv);  	if (rv) {  		dev_err(&op->dev, "error initializing hardware\n"); -		goto err; +		goto err2;  	}  	/* Register ourselves to libata */ @@ -800,34 +787,28 @@ mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match)  				  mwdma_mask, udma_mask);  	if (rv) {  		dev_err(&op->dev, "error registering with ATA layer\n"); -		goto err; +		goto err2;  	}  	return 0; - err: -	devm_release_mem_region(&op->dev, res_mem.start, sizeof(*ata_regs)); -	if (ata_irq) -		irq_dispose_mapping(ata_irq); -	if (task_irq) -		irq_dispose_mapping(task_irq); -	if (dmatsk) -		bcom_ata_release(dmatsk); -	if (ata_regs) -		devm_iounmap(&op->dev, ata_regs); -	if (priv) -		devm_kfree(&op->dev, priv); + err2: +	irq_dispose_mapping(task_irq); +	bcom_ata_release(dmatsk); + err1: +	irq_dispose_mapping(ata_irq);  	return rv;  }  static int  mpc52xx_ata_remove(struct platform_device *op)  { -	struct mpc52xx_ata_priv *priv; +	struct ata_host *host = platform_get_drvdata(op); +	struct mpc52xx_ata_priv *priv = host->private_data;  	int task_irq;  	/* Deregister the ATA interface */ -	priv = mpc52xx_ata_remove_one(&op->dev); +	ata_platform_remove_one(op);  	/* Clean up DMA */  	task_irq = bcom_get_task_irq(priv->dmatsk); @@ -835,22 +816,14 @@ mpc52xx_ata_remove(struct platform_device *op)  	bcom_ata_release(priv->dmatsk);  	irq_dispose_mapping(priv->ata_irq); -	/* Clear up IO allocations */ -	devm_iounmap(&op->dev, priv->ata_regs); -	devm_release_mem_region(&op->dev, priv->ata_regs_pa, -				sizeof(*priv->ata_regs)); -	devm_kfree(&op->dev, priv); -  	return 0;  } - -#ifdef CONFIG_PM - +#ifdef CONFIG_PM_SLEEP  static int  mpc52xx_ata_suspend(struct platform_device *op, pm_message_t state)  { -	struct ata_host *host = dev_get_drvdata(&op->dev); +	struct ata_host *host = platform_get_drvdata(op);  	return ata_host_suspend(host, state);  } @@ -858,7 +831,7 @@ mpc52xx_ata_suspend(struct platform_device *op, pm_message_t state)  static int  mpc52xx_ata_resume(struct platform_device *op)  { -	struct ata_host *host = dev_get_drvdata(&op->dev); +	struct ata_host *host = platform_get_drvdata(op);  	struct mpc52xx_ata_priv *priv = host->private_data;  	int rv; @@ -872,10 +845,8 @@ mpc52xx_ata_resume(struct platform_device *op)  	return 0;  } -  #endif -  static struct of_device_id mpc52xx_ata_of_match[] = {  	{ .compatible = "fsl,mpc5200-ata", },  	{ .compatible = "mpc5200-ata", }, @@ -883,10 +854,10 @@ static struct of_device_id mpc52xx_ata_of_match[] = {  }; -static struct of_platform_driver mpc52xx_ata_of_platform_driver = { +static struct platform_driver mpc52xx_ata_of_platform_driver = {  	.probe		= mpc52xx_ata_probe,  	.remove		= mpc52xx_ata_remove, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= mpc52xx_ata_suspend,  	.resume		= mpc52xx_ata_resume,  #endif @@ -897,26 +868,7 @@ static struct of_platform_driver mpc52xx_ata_of_platform_driver = {  	},  }; - -/* ======================================================================== */ -/* Module                                                                   */ -/* ======================================================================== */ - -static int __init -mpc52xx_ata_init(void) -{ -	printk(KERN_INFO "ata: MPC52xx IDE/ATA libata driver\n"); -	return of_register_platform_driver(&mpc52xx_ata_of_platform_driver); -} - -static void __exit -mpc52xx_ata_exit(void) -{ -	of_unregister_platform_driver(&mpc52xx_ata_of_platform_driver); -} - -module_init(mpc52xx_ata_init); -module_exit(mpc52xx_ata_exit); +module_platform_driver(mpc52xx_ata_of_platform_driver);  MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");  MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver"); diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c index b21f0021f54..202b4d60139 100644 --- a/drivers/ata/pata_mpiix.c +++ b/drivers/ata/pata_mpiix.c @@ -15,7 +15,7 @@   * with PCI IDE and also that we do not disable the device when our driver is   * unloaded (as it has many other functions).   * - * The driver conciously keeps this logic internally to avoid pushing quirky + * The driver consciously keeps this logic internally to avoid pushing quirky   * PATA history into the clean libata layer.   *   * Thinkpad specific note: If you boot an MPIIX using a thinkpad with a PCMCIA @@ -28,7 +28,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -152,15 +151,13 @@ static struct ata_port_operations mpiix_port_ops = {  static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)  {  	/* Single threaded by the PCI probe logic */ -	static int printed_version;  	struct ata_host *host;  	struct ata_port *ap;  	void __iomem *cmd_addr, *ctl_addr;  	u16 idetim;  	int cmd, ctl, irq; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&dev->dev, DRV_VERSION);  	host = ata_host_alloc(&dev->dev, 1);  	if (!host) @@ -226,27 +223,16 @@ static struct pci_driver mpiix_pci_driver = {  	.id_table	= mpiix,  	.probe 		= mpiix_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init mpiix_init(void) -{ -	return pci_register_driver(&mpiix_pci_driver); -} - -static void __exit mpiix_exit(void) -{ -	pci_unregister_driver(&mpiix_pci_driver); -} +module_pci_driver(mpiix_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for Intel MPIIX");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, mpiix);  MODULE_VERSION(DRV_VERSION); - -module_init(mpiix_init); -module_exit(mpiix_exit); diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c index 3eb921c746a..0ea18331d46 100644 --- a/drivers/ata/pata_netcell.c +++ b/drivers/ata/pata_netcell.c @@ -7,7 +7,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -57,7 +56,6 @@ static struct ata_port_operations netcell_ops = {  static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	static const struct ata_port_info info = {  		.flags		= ATA_FLAG_SLAVE_POSS,  		/* Actually we don't really care about these as the @@ -70,9 +68,7 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e  	const struct ata_port_info *port_info[] = { &info, NULL };  	int rc; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -96,28 +92,16 @@ static struct pci_driver netcell_pci_driver = {  	.id_table		= netcell_pci_tbl,  	.probe			= netcell_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ata_pci_device_resume,  #endif  }; -static int __init netcell_init(void) -{ -	return pci_register_driver(&netcell_pci_driver); -} - -static void __exit netcell_exit(void) -{ -	pci_unregister_driver(&netcell_pci_driver); -} - -module_init(netcell_init); -module_exit(netcell_exit); +module_pci_driver(netcell_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("SCSI low-level driver for Netcell PATA RAID");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, netcell_pci_tbl);  MODULE_VERSION(DRV_VERSION); - diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c index cc50bd09aa2..efb272da856 100644 --- a/drivers/ata/pata_ninja32.c +++ b/drivers/ata/pata_ninja32.c @@ -37,7 +37,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -153,11 +152,10 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)  				 IRQF_SHARED, &ninja32_sht);  } -#ifdef CONFIG_PM - +#ifdef CONFIG_PM_SLEEP  static int ninja32_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -165,7 +163,7 @@ static int ninja32_reinit_one(struct pci_dev *pdev)  		return rc;  	ninja32_program(host->iomap[0]);  	ata_host_resume(host); -	return 0;			 +	return 0;  }  #endif @@ -184,27 +182,16 @@ static struct pci_driver ninja32_pci_driver = {  	.id_table	= ninja32,  	.probe 		= ninja32_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ninja32_reinit_one,  #endif  }; -static int __init ninja32_init(void) -{ -	return pci_register_driver(&ninja32_pci_driver); -} - -static void __exit ninja32_exit(void) -{ -	pci_unregister_driver(&ninja32_pci_driver); -} +module_pci_driver(ninja32_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for Ninja32 ATA");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, ninja32);  MODULE_VERSION(DRV_VERSION); - -module_init(ninja32_init); -module_exit(ninja32_exit); diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c index 2110863bb3d..200e1eb23a2 100644 --- a/drivers/ata/pata_ns87410.c +++ b/drivers/ata/pata_ns87410.c @@ -20,7 +20,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -86,7 +85,7 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)  		idefr &= ~0x04;  	if (ata_timing_compute(adev, adev->pio_mode, &at, 30303, 1) < 0) { -		dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", adev->pio_mode); +		dev_err(&pdev->dev, "unknown mode %d\n", adev->pio_mode);  		return;  	} @@ -162,27 +161,16 @@ static struct pci_driver ns87410_pci_driver = {  	.id_table	= ns87410,  	.probe 		= ns87410_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init ns87410_init(void) -{ -	return pci_register_driver(&ns87410_pci_driver); -} - -static void __exit ns87410_exit(void) -{ -	pci_unregister_driver(&ns87410_pci_driver); -} +module_pci_driver(ns87410_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for Nat Semi 87410");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, ns87410);  MODULE_VERSION(DRV_VERSION); - -module_init(ns87410_init); -module_exit(ns87410_exit); diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c index 605f198f958..84c6b225b56 100644 --- a/drivers/ata/pata_ns87415.c +++ b/drivers/ata/pata_ns87415.c @@ -25,7 +25,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -350,7 +349,6 @@ static void ns87415_fixup(struct pci_dev *pdev)  static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	static const struct ata_port_info info = {  		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4, @@ -370,9 +368,7 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e  	if (PCI_SLOT(pdev->devfn) == 0x0E)  		ppi[0] = &info87560;  #endif -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -389,10 +385,10 @@ static const struct pci_device_id ns87415_pci_tbl[] = {  	{ }	/* terminate list */  }; -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int ns87415_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -411,24 +407,13 @@ static struct pci_driver ns87415_pci_driver = {  	.id_table		= ns87415_pci_tbl,  	.probe			= ns87415_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ns87415_reinit_one,  #endif  }; -static int __init ns87415_init(void) -{ -	return pci_register_driver(&ns87415_pci_driver); -} - -static void __exit ns87415_exit(void) -{ -	pci_unregister_driver(&ns87415_pci_driver); -} - -module_init(ns87415_init); -module_exit(ns87415_exit); +module_pci_driver(ns87415_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("ATA low-level driver for NS87415 controllers"); diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index fa1b95a9a7f..2a97d3a531e 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -5,19 +5,22 @@   * License.  See the file "COPYING" in the main directory of this archive   * for more details.   * - * Copyright (C) 2005 - 2009 Cavium Networks + * Copyright (C) 2005 - 2012 Cavium Inc.   * Copyright (C) 2008 Wind River Systems   */  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/libata.h> -#include <linux/irq.h> +#include <linux/hrtimer.h>  #include <linux/slab.h> +#include <linux/irq.h> +#include <linux/of.h> +#include <linux/of_platform.h>  #include <linux/platform_device.h> -#include <linux/workqueue.h>  #include <scsi/scsi_host.h> +#include <asm/byteorder.h>  #include <asm/octeon/octeon.h>  /* @@ -34,20 +37,36 @@   */  #define DRV_NAME	"pata_octeon_cf" -#define DRV_VERSION	"2.1" +#define DRV_VERSION	"2.2" + +/* Poll interval in nS. */ +#define OCTEON_CF_BUSY_POLL_INTERVAL 500000 +#define DMA_CFG 0 +#define DMA_TIM 0x20 +#define DMA_INT 0x38 +#define DMA_INT_EN 0x50  struct octeon_cf_port { -	struct workqueue_struct *wq; -	struct delayed_work delayed_finish; +	struct hrtimer delayed_finish;  	struct ata_port *ap;  	int dma_finished; +	void		*c0; +	unsigned int cs0; +	unsigned int cs1; +	bool is_true_ide; +	u64 dma_base;  };  static struct scsi_host_template octeon_cf_sht = {  	ATA_PIO_SHT(DRV_NAME),  }; +static int enable_dma; +module_param(enable_dma, int, 0444); +MODULE_PARM_DESC(enable_dma, +		 "Enable use of DMA on interfaces that support it (0=no dma [default], 1=use dma)"); +  /**   * Convert nanosecond based time to setting used in the   * boot bus timing register, based on timing multiple @@ -66,12 +85,29 @@ static unsigned int ns_to_tim_reg(unsigned int tim_mult, unsigned int nsecs)  	return val;  } -static void octeon_cf_set_boot_reg_cfg(int cs) +static void octeon_cf_set_boot_reg_cfg(int cs, unsigned int multiplier)  {  	union cvmx_mio_boot_reg_cfgx reg_cfg; +	unsigned int tim_mult; + +	switch (multiplier) { +	case 8: +		tim_mult = 3; +		break; +	case 4: +		tim_mult = 0; +		break; +	case 2: +		tim_mult = 2; +		break; +	default: +		tim_mult = 1; +		break; +	} +  	reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));  	reg_cfg.s.dmack = 0;	/* Don't assert DMACK on access */ -	reg_cfg.s.tim_mult = 2;	/* Timing mutiplier 2x */ +	reg_cfg.s.tim_mult = tim_mult;	/* Timing mutiplier */  	reg_cfg.s.rd_dly = 0;	/* Sample on falling edge of BOOT_OE */  	reg_cfg.s.sam = 0;	/* Don't combine write and output enable */  	reg_cfg.s.we_ext = 0;	/* No write enable extension */ @@ -92,12 +128,12 @@ static void octeon_cf_set_boot_reg_cfg(int cs)   */  static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)  { -	struct octeon_cf_data *ocd = ap->dev->platform_data; +	struct octeon_cf_port *cf_port = ap->private_data;  	union cvmx_mio_boot_reg_timx reg_tim; -	int cs = ocd->base_region;  	int T;  	struct ata_timing timing; +	unsigned int div;  	int use_iordy;  	int trh;  	int pause; @@ -106,7 +142,15 @@ static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)  	int t2;  	int t2i; -	T = (int)(2000000000000LL / octeon_get_clock_rate()); +	/* +	 * A divisor value of four will overflow the timing fields at +	 * clock rates greater than 800MHz +	 */ +	if (octeon_get_io_clock_rate() <= 800000000) +		div = 4; +	else +		div = 8; +	T = (int)((1000000000000LL * div) / octeon_get_io_clock_rate());  	if (ata_timing_compute(dev, dev->pio_mode, &timing, T, T))  		BUG(); @@ -121,23 +165,26 @@ static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)  	if (t2i)  		t2i--; -	trh = ns_to_tim_reg(2, 20); +	trh = ns_to_tim_reg(div, 20);  	if (trh)  		trh--; -	pause = timing.cycle - timing.active - timing.setup - trh; +	pause = (int)timing.cycle - (int)timing.active - +		(int)timing.setup - trh; +	if (pause < 0) +		pause = 0;  	if (pause)  		pause--; -	octeon_cf_set_boot_reg_cfg(cs); -	if (ocd->dma_engine >= 0) +	octeon_cf_set_boot_reg_cfg(cf_port->cs0, div); +	if (cf_port->is_true_ide)  		/* True IDE mode, program both chip selects.  */ -		octeon_cf_set_boot_reg_cfg(cs + 1); +		octeon_cf_set_boot_reg_cfg(cf_port->cs1, div);  	use_iordy = ata_pio_need_iordy(dev); -	reg_tim.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_TIMX(cs)); +	reg_tim.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs0));  	/* Disable page mode */  	reg_tim.s.pagem = 0;  	/* Enable dynamic timing */ @@ -161,20 +208,22 @@ static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)  	/* How long read enable is asserted */  	reg_tim.s.oe = t2;  	/* Time after CE that read/write starts */ -	reg_tim.s.ce = ns_to_tim_reg(2, 5); +	reg_tim.s.ce = ns_to_tim_reg(div, 5);  	/* Time before CE that address is valid */  	reg_tim.s.adr = 0;  	/* Program the bootbus region timing for the data port chip select. */ -	cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cs), reg_tim.u64); -	if (ocd->dma_engine >= 0) +	cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs0), reg_tim.u64); +	if (cf_port->is_true_ide)  		/* True IDE mode, program both chip selects.  */ -		cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cs + 1), reg_tim.u64); +		cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs1), +			       reg_tim.u64);  }  static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev)  { -	struct octeon_cf_data *ocd = dev->link->ap->dev->platform_data; +	struct octeon_cf_port *cf_port = ap->private_data; +	union cvmx_mio_boot_pin_defs pin_defs;  	union cvmx_mio_boot_dma_timx dma_tim;  	unsigned int oe_a;  	unsigned int oe_n; @@ -183,6 +232,7 @@ static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev)  	unsigned int pause;  	unsigned int T0, Tkr, Td;  	unsigned int tim_mult; +	int c;  	const struct ata_timing *timing; @@ -199,13 +249,19 @@ static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev)  	/* not spec'ed, value in eclocks, not affected by tim_mult */  	dma_arq = 8;  	pause = 25 - dma_arq * 1000 / -		(octeon_get_clock_rate() / 1000000); /* Tz */ +		(octeon_get_io_clock_rate() / 1000000); /* Tz */  	oe_a = Td;  	/* Tkr from cf spec, lengthened to meet T0 */  	oe_n = max(T0 - oe_a, Tkr); -	dma_tim.s.dmack_pi = 1; +	pin_defs.u64 = cvmx_read_csr(CVMX_MIO_BOOT_PIN_DEFS); + +	/* DMA channel number. */ +	c = (cf_port->dma_base & 8) >> 3; + +	/* Invert the polarity if the default is 0*/ +	dma_tim.s.dmack_pi = (pin_defs.u64 & (1ull << (11 + c))) ? 0 : 1;  	dma_tim.s.oe_n = ns_to_tim_reg(tim_mult, oe_n);  	dma_tim.s.oe_a = ns_to_tim_reg(tim_mult, oe_a); @@ -228,14 +284,11 @@ static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev)  	pr_debug("ns to ticks (mult %d) of %d is: %d\n", tim_mult, 60,  		 ns_to_tim_reg(tim_mult, 60)); -	pr_debug("oe_n: %d, oe_a: %d, dmack_s: %d, dmack_h: " -		 "%d, dmarq: %d, pause: %d\n", +	pr_debug("oe_n: %d, oe_a: %d, dmack_s: %d, dmack_h: %d, dmarq: %d, pause: %d\n",  		 dma_tim.s.oe_n, dma_tim.s.oe_a, dma_tim.s.dmack_s,  		 dma_tim.s.dmack_h, dma_tim.s.dmarq, dma_tim.s.pause); -	cvmx_write_csr(CVMX_MIO_BOOT_DMA_TIMX(ocd->dma_engine), -		       dma_tim.u64); - +	cvmx_write_csr(cf_port->dma_base + DMA_TIM, dma_tim.u64);  }  /** @@ -405,7 +458,7 @@ static int octeon_cf_softreset16(struct ata_link *link, unsigned int *classes,  	rc = ata_sff_wait_after_reset(link, 1, deadline);  	if (rc) { -		ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc); +		ata_link_err(link, "SRST failed (errno=%d)\n", rc);  		return rc;  	} @@ -489,13 +542,8 @@ static void octeon_cf_exec_command16(struct ata_port *ap,  	ata_wait_idle(ap);  } -static void octeon_cf_irq_on(struct ata_port *ap) -{ -} - -static void octeon_cf_irq_clear(struct ata_port *ap) +static void octeon_cf_ata_port_noaction(struct ata_port *ap)  { -	return;  }  static void octeon_cf_dma_setup(struct ata_queued_cmd *qc) @@ -519,7 +567,7 @@ static void octeon_cf_dma_setup(struct ata_queued_cmd *qc)   */  static void octeon_cf_dma_start(struct ata_queued_cmd *qc)  { -	struct octeon_cf_data *ocd = qc->ap->dev->platform_data; +	struct octeon_cf_port *cf_port = qc->ap->private_data;  	union cvmx_mio_boot_dma_cfgx mio_boot_dma_cfg;  	union cvmx_mio_boot_dma_intx mio_boot_dma_int;  	struct scatterlist *sg; @@ -535,15 +583,16 @@ static void octeon_cf_dma_start(struct ata_queued_cmd *qc)  	 */  	mio_boot_dma_int.u64 = 0;  	mio_boot_dma_int.s.done = 1; -	cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine), -		       mio_boot_dma_int.u64); +	cvmx_write_csr(cf_port->dma_base + DMA_INT, mio_boot_dma_int.u64);  	/* Enable the interrupt.  */ -	cvmx_write_csr(CVMX_MIO_BOOT_DMA_INT_ENX(ocd->dma_engine), -		       mio_boot_dma_int.u64); +	cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, mio_boot_dma_int.u64);  	/* Set the direction of the DMA */  	mio_boot_dma_cfg.u64 = 0; +#ifdef __LITTLE_ENDIAN +	mio_boot_dma_cfg.s.endian = 1; +#endif  	mio_boot_dma_cfg.s.en = 1;  	mio_boot_dma_cfg.s.rw = ((qc->tf.flags & ATA_TFLAG_WRITE) != 0); @@ -569,8 +618,7 @@ static void octeon_cf_dma_start(struct ata_queued_cmd *qc)  		(mio_boot_dma_cfg.s.rw) ? "write" : "read", sg->length,  		(void *)(unsigned long)mio_boot_dma_cfg.s.adr); -	cvmx_write_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine), -		       mio_boot_dma_cfg.u64); +	cvmx_write_csr(cf_port->dma_base + DMA_CFG, mio_boot_dma_cfg.u64);  }  /** @@ -583,10 +631,9 @@ static unsigned int octeon_cf_dma_finished(struct ata_port *ap,  					struct ata_queued_cmd *qc)  {  	struct ata_eh_info *ehi = &ap->link.eh_info; -	struct octeon_cf_data *ocd = ap->dev->platform_data; +	struct octeon_cf_port *cf_port = ap->private_data;  	union cvmx_mio_boot_dma_cfgx dma_cfg;  	union cvmx_mio_boot_dma_intx dma_int; -	struct octeon_cf_port *cf_port;  	u8 status;  	VPRINTK("ata%u: protocol %d task_state %d\n", @@ -596,9 +643,7 @@ static unsigned int octeon_cf_dma_finished(struct ata_port *ap,  	if (ap->hsm_task_state != HSM_ST_LAST)  		return 0; -	cf_port = ap->private_data; - -	dma_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine)); +	dma_cfg.u64 = cvmx_read_csr(cf_port->dma_base + DMA_CFG);  	if (dma_cfg.s.size != 0xfffff) {  		/* Error, the transfer was not complete.  */  		qc->err_mask |= AC_ERR_HOST_BUS; @@ -608,15 +653,15 @@ static unsigned int octeon_cf_dma_finished(struct ata_port *ap,  	/* Stop and clear the dma engine.  */  	dma_cfg.u64 = 0;  	dma_cfg.s.size = -1; -	cvmx_write_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine), dma_cfg.u64); +	cvmx_write_csr(cf_port->dma_base + DMA_CFG, dma_cfg.u64);  	/* Disable the interrupt.  */  	dma_int.u64 = 0; -	cvmx_write_csr(CVMX_MIO_BOOT_DMA_INT_ENX(ocd->dma_engine), dma_int.u64); +	cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, dma_int.u64);  	/* Clear the DMA complete status */  	dma_int.s.done = 1; -	cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine), dma_int.u64); +	cvmx_write_csr(cf_port->dma_base + DMA_INT, dma_int.u64);  	status = ap->ops->sff_check_status(ap); @@ -649,69 +694,68 @@ static irqreturn_t octeon_cf_interrupt(int irq, void *dev_instance)  		struct ata_queued_cmd *qc;  		union cvmx_mio_boot_dma_intx dma_int;  		union cvmx_mio_boot_dma_cfgx dma_cfg; -		struct octeon_cf_data *ocd;  		ap = host->ports[i]; -		ocd = ap->dev->platform_data;  		cf_port = ap->private_data; -		dma_int.u64 = -			cvmx_read_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine)); -		dma_cfg.u64 = -			cvmx_read_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine)); + +		dma_int.u64 = cvmx_read_csr(cf_port->dma_base + DMA_INT); +		dma_cfg.u64 = cvmx_read_csr(cf_port->dma_base + DMA_CFG);  		qc = ata_qc_from_tag(ap, ap->link.active_tag); -		if (qc && !(qc->tf.flags & ATA_TFLAG_POLLING)) { -			if (dma_int.s.done && !dma_cfg.s.en) { -				if (!sg_is_last(qc->cursg)) { -					qc->cursg = sg_next(qc->cursg); -					handled = 1; -					octeon_cf_dma_start(qc); -					continue; -				} else { -					cf_port->dma_finished = 1; -				} -			} -			if (!cf_port->dma_finished) -				continue; -			status = ioread8(ap->ioaddr.altstatus_addr); -			if (status & (ATA_BUSY | ATA_DRQ)) { -				/* -				 * We are busy, try to handle it -				 * later.  This is the DMA finished -				 * interrupt, and it could take a -				 * little while for the card to be -				 * ready for more commands. -				 */ -				/* Clear DMA irq. */ -				dma_int.u64 = 0; -				dma_int.s.done = 1; -				cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine), -					       dma_int.u64); - -				queue_delayed_work(cf_port->wq, -						   &cf_port->delayed_finish, 1); +		if (!qc || (qc->tf.flags & ATA_TFLAG_POLLING)) +			continue; + +		if (dma_int.s.done && !dma_cfg.s.en) { +			if (!sg_is_last(qc->cursg)) { +				qc->cursg = sg_next(qc->cursg);  				handled = 1; +				octeon_cf_dma_start(qc); +				continue;  			} else { -				handled |= octeon_cf_dma_finished(ap, qc); +				cf_port->dma_finished = 1;  			}  		} +		if (!cf_port->dma_finished) +			continue; +		status = ioread8(ap->ioaddr.altstatus_addr); +		if (status & (ATA_BUSY | ATA_DRQ)) { +			/* +			 * We are busy, try to handle it later.  This +			 * is the DMA finished interrupt, and it could +			 * take a little while for the card to be +			 * ready for more commands. +			 */ +			/* Clear DMA irq. */ +			dma_int.u64 = 0; +			dma_int.s.done = 1; +			cvmx_write_csr(cf_port->dma_base + DMA_INT, +				       dma_int.u64); +			hrtimer_start_range_ns(&cf_port->delayed_finish, +					       ns_to_ktime(OCTEON_CF_BUSY_POLL_INTERVAL), +					       OCTEON_CF_BUSY_POLL_INTERVAL / 5, +					       HRTIMER_MODE_REL); +			handled = 1; +		} else { +			handled |= octeon_cf_dma_finished(ap, qc); +		}  	}  	spin_unlock_irqrestore(&host->lock, flags);  	DPRINTK("EXIT\n");  	return IRQ_RETVAL(handled);  } -static void octeon_cf_delayed_finish(struct work_struct *work) +static enum hrtimer_restart octeon_cf_delayed_finish(struct hrtimer *hrt)  { -	struct octeon_cf_port *cf_port = container_of(work, +	struct octeon_cf_port *cf_port = container_of(hrt,  						      struct octeon_cf_port, -						      delayed_finish.work); +						      delayed_finish);  	struct ata_port *ap = cf_port->ap;  	struct ata_host *host = ap->host;  	struct ata_queued_cmd *qc;  	unsigned long flags;  	u8 status; +	enum hrtimer_restart rv = HRTIMER_NORESTART;  	spin_lock_irqsave(&host->lock, flags); @@ -726,15 +770,17 @@ static void octeon_cf_delayed_finish(struct work_struct *work)  	status = ioread8(ap->ioaddr.altstatus_addr);  	if (status & (ATA_BUSY | ATA_DRQ)) {  		/* Still busy, try again. */ -		queue_delayed_work(cf_port->wq, -				   &cf_port->delayed_finish, 1); +		hrtimer_forward_now(hrt, +				    ns_to_ktime(OCTEON_CF_BUSY_POLL_INTERVAL)); +		rv = HRTIMER_RESTART;  		goto out;  	}  	qc = ata_qc_from_tag(ap, ap->link.active_tag); -	if (qc && !(qc->tf.flags & ATA_TFLAG_POLLING)) +	if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))  		octeon_cf_dma_finished(ap, qc);  out:  	spin_unlock_irqrestore(&host->lock, flags); +	return rv;  }  static void octeon_cf_dev_config(struct ata_device *dev) @@ -786,81 +832,138 @@ static struct ata_port_operations octeon_cf_ops = {  	.qc_prep		= ata_noop_qc_prep,  	.qc_issue		= octeon_cf_qc_issue,  	.sff_dev_select		= octeon_cf_dev_select, -	.sff_irq_on		= octeon_cf_irq_on, -	.sff_irq_clear		= octeon_cf_irq_clear, +	.sff_irq_on		= octeon_cf_ata_port_noaction, +	.sff_irq_clear		= octeon_cf_ata_port_noaction,  	.cable_detect		= ata_cable_40wire,  	.set_piomode		= octeon_cf_set_piomode,  	.set_dmamode		= octeon_cf_set_dmamode,  	.dev_config		= octeon_cf_dev_config,  }; -static int __devinit octeon_cf_probe(struct platform_device *pdev) +static int octeon_cf_probe(struct platform_device *pdev)  {  	struct resource *res_cs0, *res_cs1; +	bool is_16bit; +	const __be32 *cs_num; +	struct property *reg_prop; +	int n_addr, n_size, reg_len; +	struct device_node *node; +	const void *prop;  	void __iomem *cs0;  	void __iomem *cs1 = NULL;  	struct ata_host *host;  	struct ata_port *ap; -	struct octeon_cf_data *ocd;  	int irq = 0;  	irq_handler_t irq_handler = NULL;  	void __iomem *base;  	struct octeon_cf_port *cf_port; +	int rv = -ENOMEM; -	res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res_cs0) +	node = pdev->dev.of_node; +	if (node == NULL)  		return -EINVAL; -	ocd = pdev->dev.platform_data; +	cf_port = devm_kzalloc(&pdev->dev, sizeof(*cf_port), GFP_KERNEL); +	if (!cf_port) +		return -ENOMEM; -	cs0 = devm_ioremap_nocache(&pdev->dev, res_cs0->start, -				   resource_size(res_cs0)); +	cf_port->is_true_ide = (of_find_property(node, "cavium,true-ide", NULL) != NULL); -	if (!cs0) -		return -ENOMEM; +	prop = of_get_property(node, "cavium,bus-width", NULL); +	if (prop) +		is_16bit = (be32_to_cpup(prop) == 16); +	else +		is_16bit = false; + +	n_addr = of_n_addr_cells(node); +	n_size = of_n_size_cells(node); + +	reg_prop = of_find_property(node, "reg", ®_len); +	if (!reg_prop || reg_len < sizeof(__be32)) +		return -EINVAL; -	/* Determine from availability of DMA if True IDE mode or not */ -	if (ocd->dma_engine >= 0) { +	cs_num = reg_prop->value; +	cf_port->cs0 = be32_to_cpup(cs_num); + +	if (cf_port->is_true_ide) { +		struct device_node *dma_node; +		dma_node = of_parse_phandle(node, +					    "cavium,dma-engine-handle", 0); +		if (dma_node) { +			struct platform_device *dma_dev; +			dma_dev = of_find_device_by_node(dma_node); +			if (dma_dev) { +				struct resource *res_dma; +				int i; +				res_dma = platform_get_resource(dma_dev, IORESOURCE_MEM, 0); +				if (!res_dma) { +					of_node_put(dma_node); +					return -EINVAL; +				} +				cf_port->dma_base = (u64)devm_ioremap_nocache(&pdev->dev, res_dma->start, +									 resource_size(res_dma)); +				if (!cf_port->dma_base) { +					of_node_put(dma_node); +					return -EINVAL; +				} + +				irq_handler = octeon_cf_interrupt; +				i = platform_get_irq(dma_dev, 0); +				if (i > 0) +					irq = i; +			} +			of_node_put(dma_node); +		}  		res_cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);  		if (!res_cs1)  			return -EINVAL;  		cs1 = devm_ioremap_nocache(&pdev->dev, res_cs1->start,  					   resource_size(res_cs1)); -  		if (!cs1) -			return -ENOMEM; +			return rv; + +		if (reg_len < (n_addr + n_size + 1) * sizeof(__be32)) +			return -EINVAL; + +		cs_num += n_addr + n_size; +		cf_port->cs1 = be32_to_cpup(cs_num);  	} -	cf_port = kzalloc(sizeof(*cf_port), GFP_KERNEL); -	if (!cf_port) -		return -ENOMEM; +	res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!res_cs0) +		return -EINVAL; + +	cs0 = devm_ioremap_nocache(&pdev->dev, res_cs0->start, +				   resource_size(res_cs0)); +	if (!cs0) +		return rv;  	/* allocate host */  	host = ata_host_alloc(&pdev->dev, 1);  	if (!host) -		goto free_cf_port; +		return rv;  	ap = host->ports[0];  	ap->private_data = cf_port; +	pdev->dev.platform_data = cf_port;  	cf_port->ap = ap;  	ap->ops = &octeon_cf_ops;  	ap->pio_mask = ATA_PIO6; -	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY -		  | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING; +	ap->flags |= ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING; -	base = cs0 + ocd->base_region_bias; -	if (!ocd->is16bit) { +	if (!is_16bit) { +		base = cs0 + 0x800;  		ap->ioaddr.cmd_addr	= base;  		ata_sff_std_ports(&ap->ioaddr);  		ap->ioaddr.altstatus_addr = base + 0xe;  		ap->ioaddr.ctl_addr	= base + 0xe;  		octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer8; -	} else if (cs1) { -		/* Presence of cs1 indicates True IDE mode.  */ +	} else if (cf_port->is_true_ide) { +		base = cs0;  		ap->ioaddr.cmd_addr	= base + (ATA_REG_CMD << 1) + 1;  		ap->ioaddr.data_addr	= base + (ATA_REG_DATA << 1);  		ap->ioaddr.error_addr	= base + (ATA_REG_ERR << 1) + 1; @@ -876,19 +979,15 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)  		ap->ioaddr.ctl_addr	= cs1 + (6 << 1) + 1;  		octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16; -		ap->mwdma_mask	= ATA_MWDMA4; -		irq = platform_get_irq(pdev, 0); -		irq_handler = octeon_cf_interrupt; - -		/* True IDE mode needs delayed work to poll for not-busy.  */ -		cf_port->wq = create_singlethread_workqueue(DRV_NAME); -		if (!cf_port->wq) -			goto free_cf_port; -		INIT_DELAYED_WORK(&cf_port->delayed_finish, -				  octeon_cf_delayed_finish); +		ap->mwdma_mask	= enable_dma ? ATA_MWDMA4 : 0; +		/* True IDE mode needs a timer to poll for not-busy.  */ +		hrtimer_init(&cf_port->delayed_finish, CLOCK_MONOTONIC, +			     HRTIMER_MODE_REL); +		cf_port->delayed_finish.function = octeon_cf_delayed_finish;  	} else {  		/* 16 bit but not True IDE */ +		base = cs0 + 0x800;  		octeon_cf_ops.sff_data_xfer	= octeon_cf_data_xfer16;  		octeon_cf_ops.softreset		= octeon_cf_softreset16;  		octeon_cf_ops.sff_check_status	= octeon_cf_check_status16; @@ -902,27 +1001,67 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)  		ap->ioaddr.ctl_addr	= base + 0xe;  		ap->ioaddr.altstatus_addr = base + 0xe;  	} +	cf_port->c0 = ap->ioaddr.ctl_addr; -	ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr); +	rv = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); +	if (rv) +		return rv; +	ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr);  	dev_info(&pdev->dev, "version " DRV_VERSION" %d bit%s.\n", -		 (ocd->is16bit) ? 16 : 8, -		 (cs1) ? ", True IDE" : ""); +		 is_16bit ? 16 : 8, +		 cf_port->is_true_ide ? ", True IDE" : ""); +	return ata_host_activate(host, irq, irq_handler, +				 IRQF_SHARED, &octeon_cf_sht); +} -	return ata_host_activate(host, irq, irq_handler, 0, &octeon_cf_sht); +static void octeon_cf_shutdown(struct device *dev) +{ +	union cvmx_mio_boot_dma_cfgx dma_cfg; +	union cvmx_mio_boot_dma_intx dma_int; + +	struct octeon_cf_port *cf_port = dev_get_platdata(dev); + +	if (cf_port->dma_base) { +		/* Stop and clear the dma engine.  */ +		dma_cfg.u64 = 0; +		dma_cfg.s.size = -1; +		cvmx_write_csr(cf_port->dma_base + DMA_CFG, dma_cfg.u64); + +		/* Disable the interrupt.  */ +		dma_int.u64 = 0; +		cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, dma_int.u64); + +		/* Clear the DMA complete status */ +		dma_int.s.done = 1; +		cvmx_write_csr(cf_port->dma_base + DMA_INT, dma_int.u64); -free_cf_port: -	kfree(cf_port); -	return -ENOMEM; +		__raw_writeb(0, cf_port->c0); +		udelay(20); +		__raw_writeb(ATA_SRST, cf_port->c0); +		udelay(20); +		__raw_writeb(0, cf_port->c0); +		mdelay(100); +	}  } +static struct of_device_id octeon_cf_match[] = { +	{ +		.compatible = "cavium,ebt3000-compact-flash", +	}, +	{}, +}; +MODULE_DEVICE_TABLE(of, octeon_i2c_match); +  static struct platform_driver octeon_cf_driver = {  	.probe		= octeon_cf_probe,  	.driver		= {  		.name	= DRV_NAME,  		.owner	= THIS_MODULE, +		.of_match_table = octeon_cf_match, +		.shutdown = octeon_cf_shutdown  	},  }; diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c index 480e043ce6b..a7e95a54c78 100644 --- a/drivers/ata/pata_of_platform.c +++ b/drivers/ata/pata_of_platform.c @@ -11,17 +11,18 @@  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/of_platform.h> +#include <linux/of_address.h> +#include <linux/platform_device.h>  #include <linux/ata_platform.h> +#include <linux/libata.h> -static int __devinit pata_of_platform_probe(struct platform_device *ofdev, -					    const struct of_device_id *match) +static int pata_of_platform_probe(struct platform_device *ofdev)  {  	int ret;  	struct device_node *dn = ofdev->dev.of_node;  	struct resource io_res;  	struct resource ctl_res; -	struct resource irq_res; +	struct resource *irq_res;  	unsigned int reg_shift = 0;  	int pio_mode = 0;  	int pio_mask; @@ -50,19 +51,17 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev,  		}  	} -	ret = of_irq_to_resource(dn, 0, &irq_res); -	if (ret == NO_IRQ) -		irq_res.start = irq_res.end = 0; -	else -		irq_res.flags = 0; +	irq_res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0); +	if (irq_res) +		irq_res->flags = 0;  	prop = of_get_property(dn, "reg-shift", NULL);  	if (prop) -		reg_shift = *prop; +		reg_shift = be32_to_cpup(prop);  	prop = of_get_property(dn, "pio-mode", NULL);  	if (prop) { -		pio_mode = *prop; +		pio_mode = be32_to_cpup(prop);  		if (pio_mode > 6) {  			dev_err(&ofdev->dev, "invalid pio-mode\n");  			return -EINVAL; @@ -74,15 +73,10 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev,  	pio_mask = 1 << pio_mode;  	pio_mask |= (1 << pio_mode) - 1; -	return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res, +	return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, irq_res,  				     reg_shift, pio_mask);  } -static int __devexit pata_of_platform_remove(struct platform_device *ofdev) -{ -	return __pata_platform_remove(&ofdev->dev); -} -  static struct of_device_id pata_of_platform_match[] = {  	{ .compatible = "ata-generic", },  	{ .compatible = "electra-ide", }, @@ -90,27 +84,17 @@ static struct of_device_id pata_of_platform_match[] = {  };  MODULE_DEVICE_TABLE(of, pata_of_platform_match); -static struct of_platform_driver pata_of_platform_driver = { +static struct platform_driver pata_of_platform_driver = {  	.driver = {  		.name = "pata_of_platform",  		.owner = THIS_MODULE,  		.of_match_table = pata_of_platform_match,  	},  	.probe		= pata_of_platform_probe, -	.remove		= __devexit_p(pata_of_platform_remove), +	.remove		= ata_platform_remove_one,  }; -static int __init pata_of_platform_init(void) -{ -	return of_register_platform_driver(&pata_of_platform_driver); -} -module_init(pata_of_platform_init); - -static void __exit pata_of_platform_exit(void) -{ -	of_unregister_platform_driver(&pata_of_platform_driver); -} -module_exit(pata_of_platform_exit); +module_platform_driver(pata_of_platform_driver);  MODULE_DESCRIPTION("OF-platform PATA driver");  MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index b811c163620..b9bf78b7d48 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -16,7 +16,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -235,7 +234,6 @@ static struct ata_port_operations oldpiix_pata_ops = {  static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	static const struct ata_port_info info = {  		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4, @@ -244,9 +242,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e  	};  	const struct ata_port_info *ppi[] = { &info, NULL }; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	return ata_pci_bmdma_init_one(pdev, ppi, &oldpiix_sht, NULL, 0);  } @@ -262,28 +258,16 @@ static struct pci_driver oldpiix_pci_driver = {  	.id_table		= oldpiix_pci_tbl,  	.probe			= oldpiix_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ata_pci_device_resume,  #endif  }; -static int __init oldpiix_init(void) -{ -	return pci_register_driver(&oldpiix_pci_driver); -} - -static void __exit oldpiix_exit(void) -{ -	pci_unregister_driver(&oldpiix_pci_driver); -} - -module_init(oldpiix_init); -module_exit(oldpiix_exit); +module_pci_driver(oldpiix_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("SCSI low-level driver for early PIIX series controllers");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, oldpiix_pci_tbl);  MODULE_VERSION(DRV_VERSION); - diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c index 00c5a02a94f..3a944a02926 100644 --- a/drivers/ata/pata_opti.c +++ b/drivers/ata/pata_opti.c @@ -26,7 +26,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -167,10 +166,8 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)  		.port_ops = &opti_port_ops  	};  	const struct ata_port_info *ppi[] = { &info, NULL }; -	static int printed_version; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&dev->dev, DRV_VERSION);  	return ata_pci_sff_init_one(dev, ppi, &opti_sht, NULL, 0);  } @@ -187,28 +184,16 @@ static struct pci_driver opti_pci_driver = {  	.id_table	= opti,  	.probe 		= opti_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init opti_init(void) -{ -	return pci_register_driver(&opti_pci_driver); -} - -static void __exit opti_exit(void) -{ -	pci_unregister_driver(&opti_pci_driver); -} - +module_pci_driver(opti_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for Opti 621/621X");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, opti);  MODULE_VERSION(DRV_VERSION); - -module_init(opti_init); -module_exit(opti_exit); diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index 0852cd07de0..bdec7efa464 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c @@ -25,7 +25,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -411,11 +410,9 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)  		.port_ops = &optiplus_port_ops  	};  	const struct ata_port_info *ppi[] = { &info_82c700, NULL }; -	static int printed_version;  	int rc; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&dev->dev, DRV_VERSION);  	rc = pcim_enable_device(dev);  	if (rc) @@ -443,27 +440,16 @@ static struct pci_driver optidma_pci_driver = {  	.id_table	= optidma,  	.probe 		= optidma_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init optidma_init(void) -{ -	return pci_register_driver(&optidma_pci_driver); -} - -static void __exit optidma_exit(void) -{ -	pci_unregister_driver(&optidma_pci_driver); -} +module_pci_driver(optidma_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for Opti Firestar/Firestar Plus");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, optidma);  MODULE_VERSION(DRV_VERSION); - -module_init(optidma_init); -module_exit(optidma_exit); diff --git a/drivers/ata/pata_palmld.c b/drivers/ata/pata_palmld.c index 11fb4ccc74b..df2bb7504fc 100644 --- a/drivers/ata/pata_palmld.c +++ b/drivers/ata/pata_palmld.c @@ -33,6 +33,11 @@  #define DRV_NAME "pata_palmld" +static struct gpio palmld_hdd_gpios[] = { +	{ GPIO_NR_PALMLD_IDE_PWEN,	GPIOF_INIT_HIGH,	"HDD Power" }, +	{ GPIO_NR_PALMLD_IDE_RESET,	GPIOF_INIT_LOW,		"HDD Reset" }, +}; +  static struct scsi_host_template palmld_sht = {  	ATA_PIO_SHT(DRV_NAME),  }; @@ -43,7 +48,7 @@ static struct ata_port_operations palmld_port_ops = {  	.cable_detect		= ata_cable_40wire,  }; -static __devinit int palmld_pata_probe(struct platform_device *pdev) +static int palmld_pata_probe(struct platform_device *pdev)  {  	struct ata_host *host;  	struct ata_port *ap; @@ -52,28 +57,23 @@ static __devinit int palmld_pata_probe(struct platform_device *pdev)  	/* allocate host */  	host = ata_host_alloc(&pdev->dev, 1); -	if (!host) -		return -ENOMEM; +	if (!host) { +		ret = -ENOMEM; +		goto err1; +	}  	/* remap drive's physical memory address */  	mem = devm_ioremap(&pdev->dev, PALMLD_IDE_PHYS, 0x1000); -	if (!mem) -		return -ENOMEM; +	if (!mem) { +		ret = -ENOMEM; +		goto err1; +	}  	/* request and activate power GPIO, IRQ GPIO */ -	ret = gpio_request(GPIO_NR_PALMLD_IDE_PWEN, "HDD PWR"); +	ret = gpio_request_array(palmld_hdd_gpios, +				ARRAY_SIZE(palmld_hdd_gpios));  	if (ret)  		goto err1; -	ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_PWEN, 1); -	if (ret) -		goto err2; - -	ret = gpio_request(GPIO_NR_PALMLD_IDE_RESET, "HDD RST"); -	if (ret) -		goto err2; -	ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_RESET, 0); -	if (ret) -		goto err3;  	/* reset the drive */  	gpio_set_value(GPIO_NR_PALMLD_IDE_RESET, 0); @@ -85,7 +85,7 @@ static __devinit int palmld_pata_probe(struct platform_device *pdev)  	ap = host->ports[0];  	ap->ops	= &palmld_port_ops;  	ap->pio_mask = ATA_PIO4; -	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_PIO_POLLING; +	ap->flags |= ATA_FLAG_PIO_POLLING;  	/* memory mapping voodoo */  	ap->ioaddr.cmd_addr = mem + 0x10; @@ -96,28 +96,27 @@ static __devinit int palmld_pata_probe(struct platform_device *pdev)  	ata_sff_std_ports(&ap->ioaddr);  	/* activate host */ -	return ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING, +	ret = ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING,  					&palmld_sht); +	if (ret) +		goto err2; + +	return ret; -err3: -	gpio_free(GPIO_NR_PALMLD_IDE_RESET);  err2: -	gpio_free(GPIO_NR_PALMLD_IDE_PWEN); +	gpio_free_array(palmld_hdd_gpios, ARRAY_SIZE(palmld_hdd_gpios));  err1:  	return ret;  } -static __devexit int palmld_pata_remove(struct platform_device *dev) +static int palmld_pata_remove(struct platform_device *dev)  { -	struct ata_host *host = platform_get_drvdata(dev); - -	ata_host_detach(host); +	ata_platform_remove_one(dev);  	/* power down the HDD */  	gpio_set_value(GPIO_NR_PALMLD_IDE_PWEN, 0); -	gpio_free(GPIO_NR_PALMLD_IDE_RESET); -	gpio_free(GPIO_NR_PALMLD_IDE_PWEN); +	gpio_free_array(palmld_hdd_gpios, ARRAY_SIZE(palmld_hdd_gpios));  	return 0;  } @@ -128,23 +127,12 @@ static struct platform_driver palmld_pata_platform_driver = {  		.owner  = THIS_MODULE,  	},  	.probe		= palmld_pata_probe, -	.remove		= __devexit_p(palmld_pata_remove), +	.remove		= palmld_pata_remove,  }; -static int __init palmld_pata_init(void) -{ -	return platform_driver_register(&palmld_pata_platform_driver); -} - -static void __exit palmld_pata_exit(void) -{ -	platform_driver_unregister(&palmld_pata_platform_driver); -} +module_platform_driver(palmld_pata_platform_driver);  MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");  MODULE_DESCRIPTION("PalmLD PATA driver");  MODULE_LICENSE("GPL");  MODULE_ALIAS("platform:" DRV_NAME); - -module_init(palmld_pata_init); -module_exit(palmld_pata_exit); diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 806292160b3..bcc4b968c04 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -26,7 +26,6 @@  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/slab.h> @@ -68,7 +67,7 @@ static int pcmcia_set_mode(struct ata_link *link, struct ata_device **r_failed_d  		   the same vendor - check serial */  		if (memcmp(master->id + ATA_ID_SERNO, slave->id + ATA_ID_SERNO,  			   ATA_ID_SERNO_LEN) == 0 && master->id[ATA_ID_SERNO] >> 8) { -			ata_dev_printk(slave, KERN_WARNING, "is a ghost device, ignoring.\n"); +			ata_dev_warn(slave, "is a ghost device, ignoring\n");  			ata_dev_disable(slave);  		}  	} @@ -124,7 +123,7 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev,   *	reset will recover the device.   *   */ -  +  static void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc)  {  	int count; @@ -142,8 +141,7 @@ static void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc)  		ioread8(ap->ioaddr.data_addr);  	if (count) -		ata_port_printk(ap, KERN_WARNING, "drained %d bytes to clear DRQ.\n", -								count); +		ata_port_warn(ap, "drained %d bytes to clear DRQ\n", count);  } @@ -171,7 +169,8 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)  {  	int *is_kme = priv_data; -	if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) { +	if ((pdev->resource[0]->flags & IO_DATA_PATH_WIDTH) +	    != IO_DATA_PATH_WIDTH_8) {  		pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;  		pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;  	} @@ -309,7 +308,7 @@ static void pcmcia_remove_one(struct pcmcia_device *pdev)  	pcmcia_disable_device(pdev);  } -static struct pcmcia_device_id pcmcia_devices[] = { +static const struct pcmcia_device_id pcmcia_devices[] = {  	PCMCIA_DEVICE_FUNC_ID(4),  	PCMCIA_DEVICE_MANF_CARD(0x0000, 0x0000),	/* Corsair */  	PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000),	/* Hitachi */ @@ -387,21 +386,9 @@ static struct pcmcia_driver pcmcia_driver = {  	.probe		= pcmcia_init_one,  	.remove		= pcmcia_remove_one,  }; - -static int __init pcmcia_init(void) -{ -	return pcmcia_register_driver(&pcmcia_driver); -} - -static void __exit pcmcia_exit(void) -{ -	pcmcia_unregister_driver(&pcmcia_driver); -} +module_pcmcia_driver(pcmcia_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for PCMCIA ATA");  MODULE_LICENSE("GPL");  MODULE_VERSION(DRV_VERSION); - -module_init(pcmcia_init); -module_exit(pcmcia_exit); diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index b1835112252..4d06a5cda98 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -25,7 +25,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -63,6 +62,9 @@ enum {  };  static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); +#ifdef CONFIG_PM_SLEEP +static int pdc2027x_reinit_one(struct pci_dev *pdev); +#endif  static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline);  static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);  static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev); @@ -126,6 +128,10 @@ static struct pci_driver pdc2027x_pci_driver = {  	.id_table		= pdc2027x_pci_tbl,  	.probe			= pdc2027x_init_one,  	.remove			= ata_pci_remove_one, +#ifdef CONFIG_PM_SLEEP +	.suspend		= ata_pci_device_suspend, +	.resume			= pdc2027x_reinit_one, +#endif  };  static struct scsi_host_template pdc2027x_sht = { @@ -150,8 +156,7 @@ static struct ata_port_operations pdc2027x_pata133_ops = {  static struct ata_port_info pdc2027x_port_info[] = {  	/* PDC_UDMA_100 */  	{ -		.flags		= ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | -		                  ATA_FLAG_MMIO, +		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4,  		.mwdma_mask	= ATA_MWDMA2,  		.udma_mask	= ATA_UDMA5, @@ -159,8 +164,7 @@ static struct ata_port_info pdc2027x_port_info[] = {  	},  	/* PDC_UDMA_133 */  	{ -		.flags		= ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | -                        	  ATA_FLAG_MMIO, +		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4,  		.mwdma_mask	= ATA_MWDMA2,  		.udma_mask	= ATA_UDMA6, @@ -657,7 +661,7 @@ static int pdc_hardware_init(struct ata_host *host, unsigned int board_idx)  	 */  	pll_clock = pdc_detect_pll_input_clock(host); -	dev_printk(KERN_INFO, host->dev, "PLL input clock %ld kHz\n", pll_clock/1000); +	dev_info(host->dev, "PLL input clock %ld kHz\n", pll_clock/1000);  	/* Adjust PLL control register */  	pdc_adjust_pll(host, pll_clock, board_idx); @@ -697,9 +701,9 @@ static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base)   * @pdev: instance of pci_dev found   * @ent:  matching entry in the id_tbl[]   */ -static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +static int pdc2027x_init_one(struct pci_dev *pdev, +			     const struct pci_device_id *ent)  { -	static int printed_version;  	static const unsigned long cmd_offset[] = { 0x17c0, 0x15c0 };  	static const unsigned long bmdma_offset[] = { 0x1000, 0x1008 };  	unsigned int board_idx = (unsigned int) ent->driver_data; @@ -709,8 +713,7 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de  	void __iomem *mmio_base;  	int i, rc; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* alloc host */  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); @@ -758,21 +761,29 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de  				 IRQF_SHARED, &pdc2027x_sht);  } -/** - * pdc2027x_init - Called after this module is loaded into the kernel. - */ -static int __init pdc2027x_init(void) +#ifdef CONFIG_PM_SLEEP +static int pdc2027x_reinit_one(struct pci_dev *pdev)  { -	return pci_register_driver(&pdc2027x_pci_driver); -} +	struct ata_host *host = pci_get_drvdata(pdev); +	unsigned int board_idx; +	int rc; -/** - * pdc2027x_exit - Called before this module unloaded from the kernel - */ -static void __exit pdc2027x_exit(void) -{ -	pci_unregister_driver(&pdc2027x_pci_driver); +	rc = ata_pci_device_do_resume(pdev); +	if (rc) +		return rc; + +	if (pdev->device == PCI_DEVICE_ID_PROMISE_20268 || +	    pdev->device == PCI_DEVICE_ID_PROMISE_20270) +		board_idx = PDC_UDMA_100; +	else +		board_idx = PDC_UDMA_133; + +	if (pdc_hardware_init(host, board_idx)) +		return -EIO; + +	ata_host_resume(host); +	return 0;  } +#endif -module_init(pdc2027x_init); -module_exit(pdc2027x_exit); +module_pci_driver(pdc2027x_pci_driver); diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index c2ed5868dda..9001991d283 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -15,7 +15,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -378,27 +377,16 @@ static struct pci_driver pdc202xx_pci_driver = {  	.id_table	= pdc202xx,  	.probe 		= pdc202xx_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init pdc202xx_init(void) -{ -	return pci_register_driver(&pdc202xx_pci_driver); -} - -static void __exit pdc202xx_exit(void) -{ -	pci_unregister_driver(&pdc202xx_pci_driver); -} +module_pci_driver(pdc202xx_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for Promise 2024x and 20262-20267");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, pdc202xx);  MODULE_VERSION(DRV_VERSION); - -module_init(pdc202xx_init); -module_exit(pdc202xx_exit); diff --git a/drivers/ata/pata_piccolo.c b/drivers/ata/pata_piccolo.c index cb01bf9496f..35cb0e26323 100644 --- a/drivers/ata/pata_piccolo.c +++ b/drivers/ata/pata_piccolo.c @@ -18,7 +18,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -111,30 +110,16 @@ static struct pci_driver ata_tosh_pci_driver = {  	.id_table	= ata_tosh,  	.probe 		= ata_tosh_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init ata_tosh_init(void) -{ -	return pci_register_driver(&ata_tosh_pci_driver); -} - - -static void __exit ata_tosh_exit(void) -{ -	pci_unregister_driver(&ata_tosh_pci_driver); -} - +module_pci_driver(ata_tosh_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("Low level driver for Toshiba Piccolo ATA");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, ata_tosh);  MODULE_VERSION(DRV_VERSION); - -module_init(ata_tosh_init); -module_exit(ata_tosh_exit); - diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index 50400fa120f..a5579b55e33 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -13,7 +13,6 @@   */  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <scsi/scsi_host.h>  #include <linux/ata.h> @@ -39,7 +38,7 @@ static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unu  		dev->pio_mode = dev->xfer_mode = XFER_PIO_0;  		dev->xfer_shift = ATA_SHIFT_PIO;  		dev->flags |= ATA_DFLAG_PIO; -		ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); +		ata_dev_info(dev, "configured for PIO\n");  	}  	return 0;  } @@ -98,12 +97,9 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,   *   *	If no IRQ resource is present, PIO polling mode is used instead.   */ -int __devinit __pata_platform_probe(struct device *dev, -				    struct resource *io_res, -				    struct resource *ctl_res, -				    struct resource *irq_res, -				    unsigned int ioport_shift, -				    int __pio_mask) +int __pata_platform_probe(struct device *dev, struct resource *io_res, +			  struct resource *ctl_res, struct resource *irq_res, +			  unsigned int ioport_shift, int __pio_mask)  {  	struct ata_host *host;  	struct ata_port *ap; @@ -178,29 +174,12 @@ int __devinit __pata_platform_probe(struct device *dev,  }  EXPORT_SYMBOL_GPL(__pata_platform_probe); -/** - *	__pata_platform_remove		-	unplug a platform interface - *	@dev: device - * - *	A platform bus ATA device has been unplugged. Perform the needed - *	cleanup. Also called on module unload for any active devices. - */ -int __pata_platform_remove(struct device *dev) -{ -	struct ata_host *host = dev_get_drvdata(dev); - -	ata_host_detach(host); - -	return 0; -} -EXPORT_SYMBOL_GPL(__pata_platform_remove); - -static int __devinit pata_platform_probe(struct platform_device *pdev) +static int pata_platform_probe(struct platform_device *pdev)  {  	struct resource *io_res;  	struct resource *ctl_res;  	struct resource *irq_res; -	struct pata_platform_info *pp_info = pdev->dev.platform_data; +	struct pata_platform_info *pp_info = dev_get_platdata(&pdev->dev);  	/*  	 * Simple resource validation .. @@ -242,31 +221,16 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)  				     pio_mask);  } -static int __devexit pata_platform_remove(struct platform_device *pdev) -{ -	return __pata_platform_remove(&pdev->dev); -} -  static struct platform_driver pata_platform_driver = {  	.probe		= pata_platform_probe, -	.remove		= __devexit_p(pata_platform_remove), +	.remove		= ata_platform_remove_one,  	.driver = {  		.name		= DRV_NAME,  		.owner		= THIS_MODULE,  	},  }; -static int __init pata_platform_init(void) -{ -	return platform_driver_register(&pata_platform_driver); -} - -static void __exit pata_platform_exit(void) -{ -	platform_driver_unregister(&pata_platform_driver); -} -module_init(pata_platform_init); -module_exit(pata_platform_exit); +module_platform_driver(pata_platform_driver);  module_param(pio_mask, int, 0); diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c index 1898c6ed4b4..73259bfda1e 100644 --- a/drivers/ata/pata_pxa.c +++ b/drivers/ata/pata_pxa.c @@ -20,7 +20,6 @@  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/ata.h>  #include <linux/libata.h> @@ -32,7 +31,7 @@  #include <scsi/scsi_host.h>  #include <mach/pxa2xx-regs.h> -#include <mach/pata_pxa.h> +#include <linux/platform_data/ata-pxa.h>  #include <mach/dma.h>  #define DRV_NAME	"pata_pxa" @@ -229,7 +228,7 @@ static void pxa_ata_dma_irq(int dma, void *port)  		complete(&pd->dma_done);  } -static int __devinit pxa_ata_probe(struct platform_device *pdev) +static int pxa_ata_probe(struct platform_device *pdev)  {  	struct ata_host *host;  	struct ata_port *ap; @@ -238,7 +237,7 @@ static int __devinit pxa_ata_probe(struct platform_device *pdev)  	struct resource *ctl_res;  	struct resource *dma_res;  	struct resource *irq_res; -	struct pata_pxa_pdata *pdata = pdev->dev.platform_data; +	struct pata_pxa_pdata *pdata = dev_get_platdata(&pdev->dev);  	int ret = 0;  	/* @@ -292,7 +291,6 @@ static int __devinit pxa_ata_probe(struct platform_device *pdev)  	ap->ops		= &pxa_ata_port_ops;  	ap->pio_mask	= ATA_PIO4;  	ap->mwdma_mask	= ATA_MWDMA2; -	ap->flags	= ATA_FLAG_MMIO;  	ap->ioaddr.cmd_addr	= devm_ioremap(&pdev->dev, cmd_res->start,  						resource_size(cmd_res)); @@ -370,9 +368,9 @@ static int __devinit pxa_ata_probe(struct platform_device *pdev)  	return ret;  } -static int __devexit pxa_ata_remove(struct platform_device *pdev) +static int pxa_ata_remove(struct platform_device *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = platform_get_drvdata(pdev);  	struct pata_pxa_data *data = host->ports[0]->private_data;  	pxa_free_dma(data->dma_channel); @@ -384,25 +382,14 @@ static int __devexit pxa_ata_remove(struct platform_device *pdev)  static struct platform_driver pxa_ata_driver = {  	.probe		= pxa_ata_probe, -	.remove		= __devexit_p(pxa_ata_remove), +	.remove		= pxa_ata_remove,  	.driver		= {  		.name		= DRV_NAME,  		.owner		= THIS_MODULE,  	},  }; -static int __init pxa_ata_init(void) -{ -	return platform_driver_register(&pxa_ata_driver); -} - -static void __exit pxa_ata_exit(void) -{ -	platform_driver_unregister(&pxa_ata_driver); -} - -module_init(pxa_ata_init); -module_exit(pxa_ata_exit); +module_platform_driver(pxa_ata_driver);  MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");  MODULE_DESCRIPTION("DMA-capable driver for PATA on PXA CPU"); diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c deleted file mode 100644 index 45879dc6fa4..00000000000 --- a/drivers/ata/pata_qdi.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - *    pata_qdi.c - QDI VLB ATA controllers - *	(C) 2006 Red Hat - * - * This driver mostly exists as a proof of concept for non PCI devices under - * libata. While the QDI6580 was 'neat' in 1993 it is no longer terribly - * useful. - * - * Tuning code written from the documentation at - * http://www.ryston.cz/petr/vlb/qd6500.html - * http://www.ryston.cz/petr/vlb/qd6580.html - * - * Probe code based on drivers/ide/legacy/qd65xx.c - * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by - * Samuel Thibault <samuel.thibault@ens-lyon.org> - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/blkdev.h> -#include <linux/delay.h> -#include <scsi/scsi_host.h> -#include <linux/libata.h> -#include <linux/platform_device.h> - -#define DRV_NAME "pata_qdi" -#define DRV_VERSION "0.3.1" - -#define NR_HOST 4	/* Two 6580s */ - -struct qdi_data { -	unsigned long timing; -	u8 clock[2]; -	u8 last; -	int fast; -	struct platform_device *platform_dev; - -}; - -static struct ata_host *qdi_host[NR_HOST]; -static struct qdi_data qdi_data[NR_HOST]; -static int nr_qdi_host; - -#ifdef MODULE -static int probe_qdi = 1; -#else -static int probe_qdi; -#endif - -static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ -	struct ata_timing t; -	struct qdi_data *qdi = ap->host->private_data; -	int active, recovery; -	u8 timing; - -	/* Get the timing data in cycles */ -	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); - -	if (qdi->fast) { -		active = 8 - clamp_val(t.active, 1, 8); -		recovery = 18 - clamp_val(t.recover, 3, 18); -	} else { -		active = 9 - clamp_val(t.active, 2, 9); -		recovery = 15 - clamp_val(t.recover, 0, 15); -	} -	timing = (recovery << 4) | active | 0x08; - -	qdi->clock[adev->devno] = timing; - -	outb(timing, qdi->timing); -} - -static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ -	struct ata_timing t; -	struct qdi_data *qdi = ap->host->private_data; -	int active, recovery; -	u8 timing; - -	/* Get the timing data in cycles */ -	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); - -	if (qdi->fast) { -		active = 8 - clamp_val(t.active, 1, 8); -		recovery = 18 - clamp_val(t.recover, 3, 18); -	} else { -		active = 9 - clamp_val(t.active, 2, 9); -		recovery = 15 - clamp_val(t.recover, 0, 15); -	} -	timing = (recovery << 4) | active | 0x08; - -	qdi->clock[adev->devno] = timing; - -	outb(timing, qdi->timing); - -	/* Clear the FIFO */ -	if (adev->class != ATA_DEV_ATA) -		outb(0x5F, (qdi->timing & 0xFFF0) + 3); -} - -/** - *	qdi_qc_issue		-	command issue - *	@qc: command pending - * - *	Called when the libata layer is about to issue a command. We wrap - *	this interface so that we can load the correct ATA timings. - */ - -static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc) -{ -	struct ata_port *ap = qc->ap; -	struct ata_device *adev = qc->dev; -	struct qdi_data *qdi = ap->host->private_data; - -	if (qdi->clock[adev->devno] != qdi->last) { -		if (adev->pio_mode) { -			qdi->last = qdi->clock[adev->devno]; -			outb(qdi->clock[adev->devno], qdi->timing); -		} -	} -	return ata_sff_qc_issue(qc); -} - -static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf, -				  unsigned int buflen, int rw) -{ -	if (ata_id_has_dword_io(dev->id)) { -		struct ata_port *ap = dev->link->ap; -		int slop = buflen & 3; - -		if (rw == READ) -			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); -		else -			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); - -		if (unlikely(slop)) { -			__le32 pad; -			if (rw == READ) { -				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); -				memcpy(buf + buflen - slop, &pad, slop); -			} else { -				memcpy(&pad, buf + buflen - slop, slop); -				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); -			} -			buflen += 4 - slop; -		} -	} else -		buflen = ata_sff_data_xfer(dev, buf, buflen, rw); - -	return buflen; -} - -static struct scsi_host_template qdi_sht = { -	ATA_PIO_SHT(DRV_NAME), -}; - -static struct ata_port_operations qdi6500_port_ops = { -	.inherits	= &ata_sff_port_ops, -	.qc_issue	= qdi_qc_issue, -	.sff_data_xfer	= qdi_data_xfer, -	.cable_detect	= ata_cable_40wire, -	.set_piomode	= qdi6500_set_piomode, -}; - -static struct ata_port_operations qdi6580_port_ops = { -	.inherits	= &qdi6500_port_ops, -	.set_piomode	= qdi6580_set_piomode, -}; - -/** - *	qdi_init_one		-	attach a qdi interface - *	@type: Type to display - *	@io: I/O port start - *	@irq: interrupt line - *	@fast: True if on a > 33Mhz VLB - * - *	Register an ISA bus IDE interface. Such interfaces are PIO and we - *	assume do not support IRQ sharing. - */ - -static __init int qdi_init_one(unsigned long port, int type, unsigned long io, int irq, int fast) -{ -	unsigned long ctl = io + 0x206; -	struct platform_device *pdev; -	struct ata_host *host; -	struct ata_port *ap; -	void __iomem *io_addr, *ctl_addr; -	int ret; - -	/* -	 *	Fill in a probe structure first of all -	 */ - -	pdev = platform_device_register_simple(DRV_NAME, nr_qdi_host, NULL, 0); -	if (IS_ERR(pdev)) -		return PTR_ERR(pdev); - -	ret = -ENOMEM; -	io_addr = devm_ioport_map(&pdev->dev, io, 8); -	ctl_addr = devm_ioport_map(&pdev->dev, ctl, 1); -	if (!io_addr || !ctl_addr) -		goto fail; - -	ret = -ENOMEM; -	host = ata_host_alloc(&pdev->dev, 1); -	if (!host) -		goto fail; -	ap = host->ports[0]; - -	if (type == 6580) { -		ap->ops = &qdi6580_port_ops; -		ap->pio_mask = ATA_PIO4; -		ap->flags |= ATA_FLAG_SLAVE_POSS; -	} else { -		ap->ops = &qdi6500_port_ops; -		ap->pio_mask = ATA_PIO2; /* Actually PIO3 !IORDY is possible */ -		ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY; -	} - -	ap->ioaddr.cmd_addr = io_addr; -	ap->ioaddr.altstatus_addr = ctl_addr; -	ap->ioaddr.ctl_addr = ctl_addr; -	ata_sff_std_ports(&ap->ioaddr); - -	ata_port_desc(ap, "cmd %lx ctl %lx", io, ctl); - -	/* -	 *	Hook in a private data structure per channel -	 */ -	ap->private_data = &qdi_data[nr_qdi_host]; - -	qdi_data[nr_qdi_host].timing = port; -	qdi_data[nr_qdi_host].fast = fast; -	qdi_data[nr_qdi_host].platform_dev = pdev; - -	printk(KERN_INFO DRV_NAME": qd%d at 0x%lx.\n", type, io); - -	/* activate */ -	ret = ata_host_activate(host, irq, ata_sff_interrupt, 0, &qdi_sht); -	if (ret) -		goto fail; - -	qdi_host[nr_qdi_host++] = dev_get_drvdata(&pdev->dev); -	return 0; - - fail: -	platform_device_unregister(pdev); -	return ret; -} - -/** - *	qdi_init		-	attach qdi interfaces - * - *	Attach qdi IDE interfaces by scanning the ports it may occupy. - */ - -static __init int qdi_init(void) -{ -	unsigned long flags; -	static const unsigned long qd_port[2] = { 0x30, 0xB0 }; -	static const unsigned long ide_port[2] = { 0x170, 0x1F0 }; -	static const int ide_irq[2] = { 14, 15 }; - -	int ct = 0; -	int i; - -	if (probe_qdi == 0) -		return -ENODEV; - -	/* - 	 *	Check each possible QD65xx base address -	 */ - -	for (i = 0; i < 2; i++) { -		unsigned long port = qd_port[i]; -		u8 r, res; - - -		if (request_region(port, 2, "pata_qdi")) { -			/* Check for a card */ -			local_irq_save(flags); -			r = inb_p(port); -			outb_p(0x19, port); -			res = inb_p(port); -			outb_p(r, port); -			local_irq_restore(flags); - -			/* Fail */ -			if (res == 0x19) -			{ -				release_region(port, 2); -				continue; -			} - -			/* Passes the presence test */ -			r = inb_p(port + 1);	/* Check port agrees with port set */ -			if ((r & 2) >> 1 != i) { -				release_region(port, 2); -				continue; -			} - -			/* Check card type */ -			if ((r & 0xF0) == 0xC0) { -				/* QD6500: single channel */ -				if (r & 8) { -					/* Disabled ? */ -					release_region(port, 2); -					continue; -				} -				if (qdi_init_one(port, 6500, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0) -					ct++; -			} -			if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) { -				/* QD6580: dual channel */ -				if (!request_region(port + 2 , 2, "pata_qdi")) -				{ -					release_region(port, 2); -					continue; -				} -				res = inb(port + 3); -				if (res & 1) { -					/* Single channel mode */ -					if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0) -						ct++; -				} else { -					/* Dual channel mode */ -					if (qdi_init_one(port, 6580, 0x1F0, 14, r & 0x04) == 0) -						ct++; -					if (qdi_init_one(port + 2, 6580, 0x170, 15, r & 0x04) == 0) -						ct++; -				} -			} -		} -	} -	if (ct != 0) -		return 0; -	return -ENODEV; -} - -static __exit void qdi_exit(void) -{ -	int i; - -	for (i = 0; i < nr_qdi_host; i++) { -		ata_host_detach(qdi_host[i]); -		/* Free the control resource. The 6580 dual channel has the resources -		 * claimed as a pair of 2 byte resources so we need no special cases... -		 */ -		release_region(qdi_data[i].timing, 2); -		platform_device_unregister(qdi_data[i].platform_dev); -	} -} - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for qdi ATA"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_init(qdi_init); -module_exit(qdi_exit); - -module_param(probe_qdi, int, 0); - diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 8574b31f177..a3f1123d17a 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -15,7 +15,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -213,7 +212,6 @@ static struct ata_port_operations radisys_pata_ops = {  static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	static const struct ata_port_info info = {  		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4, @@ -223,9 +221,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e  	};  	const struct ata_port_info *ppi[] = { &info, NULL }; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	return ata_pci_bmdma_init_one(pdev, ppi, &radisys_sht, NULL, 0);  } @@ -241,28 +237,16 @@ static struct pci_driver radisys_pci_driver = {  	.id_table		= radisys_pci_tbl,  	.probe			= radisys_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ata_pci_device_resume,  #endif  }; -static int __init radisys_init(void) -{ -	return pci_register_driver(&radisys_pci_driver); -} - -static void __exit radisys_exit(void) -{ -	pci_unregister_driver(&radisys_pci_driver); -} - -module_init(radisys_init); -module_exit(radisys_exit); +module_pci_driver(radisys_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("SCSI low-level driver for Radisys R82600 controllers");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, radisys_pci_tbl);  MODULE_VERSION(DRV_VERSION); - diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 0ffd631000b..3c5eb8fa6bd 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -60,10 +60,10 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)  	struct rb532_cf_info *info = ah->private_data;  	if (gpio_get_value(info->gpio_line)) { -		set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW); +		irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);  		ata_sff_interrupt(info->irq, dev_instance);  	} else { -		set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH); +		irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);  	}  	return IRQ_HANDLED; @@ -91,7 +91,6 @@ static void rb532_pata_setup_ports(struct ata_host *ah)  	ap->ops		= &rb532_pata_port_ops;  	ap->pio_mask	= ATA_PIO4; -	ap->flags	= ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;  	ap->ioaddr.cmd_addr	= info->iobase + RB500_CF_REG_BASE;  	ap->ioaddr.ctl_addr	= info->iobase + RB500_CF_REG_CTRL; @@ -103,7 +102,7 @@ static void rb532_pata_setup_ports(struct ata_host *ah)  	ap->ioaddr.error_addr	= info->iobase + RB500_CF_REG_ERR;  } -static __devinit int rb532_pata_driver_probe(struct platform_device *pdev) +static int rb532_pata_driver_probe(struct platform_device *pdev)  {  	int irq;  	int gpio; @@ -178,7 +177,7 @@ err_free_gpio:  	return ret;  } -static __devexit int rb532_pata_driver_remove(struct platform_device *pdev) +static int rb532_pata_driver_remove(struct platform_device *pdev)  {  	struct ata_host *ah = platform_get_drvdata(pdev);  	struct rb532_cf_info *info = ah->private_data; @@ -189,39 +188,22 @@ static __devexit int rb532_pata_driver_remove(struct platform_device *pdev)  	return 0;  } -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:" DRV_NAME); -  static struct platform_driver rb532_pata_platform_driver = {  	.probe		= rb532_pata_driver_probe, -	.remove		= __devexit_p(rb532_pata_driver_remove), +	.remove		= rb532_pata_driver_remove,  	.driver	 = {  		.name   = DRV_NAME,  		.owner  = THIS_MODULE,  	},  }; -/* ------------------------------------------------------------------------ */ -  #define DRV_INFO DRV_DESC " version " DRV_VERSION -static int __init rb532_pata_module_init(void) -{ -	printk(KERN_INFO DRV_INFO "\n"); - -	return platform_driver_register(&rb532_pata_platform_driver); -} - -static void __exit rb532_pata_module_exit(void) -{ -	platform_driver_unregister(&rb532_pata_platform_driver); -} +module_platform_driver(rb532_pata_platform_driver);  MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");  MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");  MODULE_DESCRIPTION(DRV_DESC);  MODULE_VERSION(DRV_VERSION);  MODULE_LICENSE("GPL"); - -module_init(rb532_pata_module_init); -module_exit(rb532_pata_module_exit); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c index 5fbe9b166c6..9ce5952216b 100644 --- a/drivers/ata/pata_rdc.c +++ b/drivers/ata/pata_rdc.c @@ -24,7 +24,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -86,6 +85,8 @@ static int rdc_pata_prereset(struct ata_link *link, unsigned long deadline)  	return ata_sff_prereset(link, deadline);  } +static DEFINE_SPINLOCK(rdc_lock); +  /**   *	rdc_set_piomode - Initialize host controller PATA PIO timings   *	@ap: Port whose timings we are configuring @@ -101,6 +102,7 @@ static void rdc_set_piomode(struct ata_port *ap, struct ata_device *adev)  {  	unsigned int pio	= adev->pio_mode - XFER_PIO_0;  	struct pci_dev *dev	= to_pci_dev(ap->host->dev); +	unsigned long flags;  	unsigned int is_slave	= (adev->devno != 0);  	unsigned int master_port= ap->port_no ? 0x42 : 0x40;  	unsigned int slave_port	= 0x44; @@ -124,6 +126,8 @@ static void rdc_set_piomode(struct ata_port *ap, struct ata_device *adev)  	if (adev->class == ATA_DEV_ATA)  		control |= 4;	/* PPE enable */ +	spin_lock_irqsave(&rdc_lock, flags); +  	/* PIO configuration clears DTE unconditionally.  It will be  	 * programmed in set_dmamode which is guaranteed to be called  	 * after set_piomode if any DMA mode is available. @@ -161,6 +165,8 @@ static void rdc_set_piomode(struct ata_port *ap, struct ata_device *adev)  	pci_read_config_byte(dev, 0x48, &udma_enable);  	udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));  	pci_write_config_byte(dev, 0x48, udma_enable); + +	spin_unlock_irqrestore(&rdc_lock, flags);  }  /** @@ -177,6 +183,7 @@ static void rdc_set_piomode(struct ata_port *ap, struct ata_device *adev)  static void rdc_set_dmamode(struct ata_port *ap, struct ata_device *adev)  {  	struct pci_dev *dev	= to_pci_dev(ap->host->dev); +	unsigned long flags;  	u8 master_port		= ap->port_no ? 0x42 : 0x40;  	u16 master_data;  	u8 speed		= adev->dma_mode; @@ -190,6 +197,8 @@ static void rdc_set_dmamode(struct ata_port *ap, struct ata_device *adev)  			    { 2, 1 },  			    { 2, 3 }, }; +	spin_lock_irqsave(&rdc_lock, flags); +  	pci_read_config_word(dev, master_port, &master_data);  	pci_read_config_byte(dev, 0x48, &udma_enable); @@ -271,6 +280,8 @@ static void rdc_set_dmamode(struct ata_port *ap, struct ata_device *adev)  		pci_write_config_word(dev, master_port, master_data);  	}  	pci_write_config_byte(dev, 0x48, udma_enable); + +	spin_unlock_irqrestore(&rdc_lock, flags);  }  static struct ata_port_operations rdc_pata_ops = { @@ -309,27 +320,20 @@ static struct scsi_host_template rdc_sht = {   *	Zero on success, or -ERRNO value.   */ -static int __devinit rdc_init_one(struct pci_dev *pdev, -				   const struct pci_device_id *ent) +static int rdc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	struct device *dev = &pdev->dev;  	struct ata_port_info port_info[2];  	const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] }; -	unsigned long port_flags;  	struct ata_host *host;  	struct rdc_host_priv *hpriv;  	int rc; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	port_info[0] = rdc_port_info;  	port_info[1] = rdc_port_info; -	port_flags = port_info[0].flags; -  	/* enable device and prepare host */  	rc = pcim_enable_device(pdev);  	if (rc) @@ -359,7 +363,7 @@ static int __devinit rdc_init_one(struct pci_dev *pdev,  static void rdc_remove_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	struct rdc_host_priv *hpriv = host->private_data;  	pci_write_config_dword(pdev, 0x54, hpriv->saved_iocfg); @@ -378,21 +382,14 @@ static struct pci_driver rdc_pci_driver = {  	.id_table		= rdc_pci_tbl,  	.probe			= rdc_init_one,  	.remove			= rdc_remove_one, +#ifdef CONFIG_PM_SLEEP +	.suspend		= ata_pci_device_suspend, +	.resume			= ata_pci_device_resume, +#endif  }; -static int __init rdc_init(void) -{ -	return pci_register_driver(&rdc_pci_driver); -} - -static void __exit rdc_exit(void) -{ -	pci_unregister_driver(&rdc_pci_driver); -} - -module_init(rdc_init); -module_exit(rdc_exit); +module_pci_driver(rdc_pci_driver);  MODULE_AUTHOR("Alan Cox (based on ata_piix)");  MODULE_DESCRIPTION("SCSI low-level driver for RDC PATA controllers"); diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index 4a454a88aa9..b3ec18c6bcc 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c @@ -14,7 +14,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -44,7 +43,7 @@ static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused)  		dev->xfer_mode = XFER_PIO_0;  		dev->xfer_shift = ATA_SHIFT_PIO;  		dev->flags |= ATA_DFLAG_PIO; -		ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); +		ata_dev_info(dev, "configured for PIO\n");  	}  	return 0;  } @@ -92,7 +91,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en  	};  	const struct ata_port_info *ppi[] = { &info, NULL }; -	printk_once(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	if (rz1000_fifo_disable(pdev) == 0)  		return ata_pci_sff_init_one(pdev, ppi, &rz1000_sht, NULL, 0); @@ -102,17 +101,17 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en  	return -ENODEV;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int rz1000_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev);  	if (rc)  		return rc; -	/* If this fails on resume (which is a "cant happen" case), we +	/* If this fails on resume (which is a "can't happen" case), we  	   must stop as any progress risks data loss */  	if (rz1000_fifo_disable(pdev))  		panic("rz1000 fifo"); @@ -134,28 +133,16 @@ static struct pci_driver rz1000_pci_driver = {  	.id_table	= pata_rz1000,  	.probe 		= rz1000_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= rz1000_reinit_one,  #endif  }; -static int __init rz1000_init(void) -{ -	return pci_register_driver(&rz1000_pci_driver); -} - -static void __exit rz1000_exit(void) -{ -	pci_unregister_driver(&rz1000_pci_driver); -} +module_pci_driver(rz1000_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for RZ1000 PCI ATA");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, pata_rz1000);  MODULE_VERSION(DRV_VERSION); - -module_init(rz1000_init); -module_exit(rz1000_exit); - diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c index 8a51d673e5b..fb528831fb9 100644 --- a/drivers/ata/pata_samsung_cf.c +++ b/drivers/ata/pata_samsung_cf.c @@ -23,12 +23,35 @@  #include <linux/platform_device.h>  #include <linux/slab.h> -#include <plat/ata.h> -#include <plat/regs-ata.h> +#include <linux/platform_data/ata-samsung_cf.h>  #define DRV_NAME "pata_samsung_cf"  #define DRV_VERSION "0.1" +#define S3C_CFATA_REG(x)	(x) +#define S3C_CFATA_MUX		S3C_CFATA_REG(0x0) +#define S3C_ATA_CTRL		S3C_CFATA_REG(0x0) +#define S3C_ATA_CMD		S3C_CFATA_REG(0x8) +#define S3C_ATA_IRQ		S3C_CFATA_REG(0x10) +#define S3C_ATA_IRQ_MSK		S3C_CFATA_REG(0x14) +#define S3C_ATA_CFG		S3C_CFATA_REG(0x18) + +#define S3C_ATA_PIO_TIME	S3C_CFATA_REG(0x2c) +#define S3C_ATA_PIO_DTR		S3C_CFATA_REG(0x54) +#define S3C_ATA_PIO_FED		S3C_CFATA_REG(0x58) +#define S3C_ATA_PIO_SCR		S3C_CFATA_REG(0x5c) +#define S3C_ATA_PIO_LLR		S3C_CFATA_REG(0x60) +#define S3C_ATA_PIO_LMR		S3C_CFATA_REG(0x64) +#define S3C_ATA_PIO_LHR		S3C_CFATA_REG(0x68) +#define S3C_ATA_PIO_DVR		S3C_CFATA_REG(0x6c) +#define S3C_ATA_PIO_CSD		S3C_CFATA_REG(0x70) +#define S3C_ATA_PIO_DAD		S3C_CFATA_REG(0x74) +#define S3C_ATA_PIO_RDATA	S3C_CFATA_REG(0x7c) + +#define S3C_CFATA_MUX_TRUEIDE	0x01 +#define S3C_ATA_CFG_SWAP	0x40 +#define S3C_ATA_CFG_IORDYEN	0x02 +  enum s3c_cpu_type {  	TYPE_S3C64XX,  	TYPE_S5PC100, @@ -241,8 +264,8 @@ static u8 pata_s3c_check_altstatus(struct ata_port *ap)  /*   * pata_s3c_data_xfer - Transfer data by PIO   */ -unsigned int pata_s3c_data_xfer(struct ata_device *dev, unsigned char *buf, -				unsigned int buflen, int rw) +static unsigned int pata_s3c_data_xfer(struct ata_device *dev, +				unsigned char *buf, unsigned int buflen, int rw)  {  	struct ata_port *ap = dev->link->ap;  	struct s3c_ide_info *info = ap->host->private_data; @@ -376,7 +399,7 @@ static int pata_s3c_softreset(struct ata_link *link, unsigned int *classes,  	rc = pata_s3c_bus_softreset(ap, deadline);  	/* if link is occupied, -ENODEV too is an error */  	if (rc && rc != -ENODEV) { -		ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc); +		ata_link_err(link, "SRST failed (errno=%d)\n", rc);  		return rc;  	} @@ -418,7 +441,7 @@ static struct ata_port_operations pata_s5p_port_ops = {  	.set_piomode		= pata_s3c_set_piomode,  }; -static void pata_s3c_enable(void *s3c_ide_regbase, bool state) +static void pata_s3c_enable(void __iomem *s3c_ide_regbase, bool state)  {  	u32 temp = readl(s3c_ide_regbase + S3C_ATA_CTRL);  	temp = state ? (temp | 1) : (temp & ~1); @@ -475,7 +498,7 @@ static void pata_s3c_hwinit(struct s3c_ide_info *info,  static int __init pata_s3c_probe(struct platform_device *pdev)  { -	struct s3c_ide_platdata *pdata = pdev->dev.platform_data; +	struct s3c_ide_platdata *pdata = dev_get_platdata(&pdev->dev);  	struct device *dev = &pdev->dev;  	struct s3c_ide_info *info;  	struct resource *res; @@ -495,24 +518,12 @@ static int __init pata_s3c_probe(struct platform_device *pdev)  	info->irq = platform_get_irq(pdev, 0);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (res == NULL) { -		dev_err(dev, "failed to get mem resource\n"); -		return -EINVAL; -	} - -	if (!devm_request_mem_region(dev, res->start, -				resource_size(res), DRV_NAME)) { -		dev_err(dev, "error requesting register region\n"); -		return -EBUSY; -	} -	info->ide_addr = devm_ioremap(dev, res->start, resource_size(res)); -	if (!info->ide_addr) { -		dev_err(dev, "failed to map IO base address\n"); -		return -ENOMEM; -	} +	info->ide_addr = devm_ioremap_resource(dev, res); +	if (IS_ERR(info->ide_addr)) +		return PTR_ERR(info->ide_addr); -	info->clk = clk_get(&pdev->dev, "cfcon"); +	info->clk = devm_clk_get(&pdev->dev, "cfcon");  	if (IS_ERR(info->clk)) {  		dev_err(dev, "failed to get access to cf controller clock\n");  		ret = PTR_ERR(info->clk); @@ -531,7 +542,6 @@ static int __init pata_s3c_probe(struct platform_device *pdev)  	}  	ap = host->ports[0]; -	ap->flags |= ATA_FLAG_MMIO;  	ap->pio_mask = ATA_PIO4;  	if (cpu_type == TYPE_S3C64XX) { @@ -584,13 +594,16 @@ static int __init pata_s3c_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, host); -	return ata_host_activate(host, info->irq, -			info->irq ? pata_s3c_irq : NULL, -			0, &pata_s3c_sht); +	ret = ata_host_activate(host, info->irq, +				info->irq ? pata_s3c_irq : NULL, +				0, &pata_s3c_sht); +	if (ret) +		goto stop_clk; + +	return 0;  stop_clk:  	clk_disable(info->clk); -	clk_put(info->clk);  	return ret;  } @@ -602,12 +615,11 @@ static int __exit pata_s3c_remove(struct platform_device *pdev)  	ata_host_detach(host);  	clk_disable(info->clk); -	clk_put(info->clk);  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int pata_s3c_suspend(struct device *dev)  {  	struct platform_device *pdev = to_platform_device(dev); @@ -620,7 +632,7 @@ static int pata_s3c_resume(struct device *dev)  {  	struct platform_device *pdev = to_platform_device(dev);  	struct ata_host *host = platform_get_drvdata(pdev); -	struct s3c_ide_platdata *pdata = pdev->dev.platform_data; +	struct s3c_ide_platdata *pdata = dev_get_platdata(&pdev->dev);  	struct s3c_ide_info *info = host->private_data;  	pata_s3c_hwinit(info, pdata); @@ -658,24 +670,13 @@ static struct platform_driver pata_s3c_driver = {  	.driver		= {  		.name	= DRV_NAME,  		.owner	= THIS_MODULE, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  		.pm	= &pata_s3c_pm_ops,  #endif  	},  }; -static int __init pata_s3c_init(void) -{ -	return platform_driver_probe(&pata_s3c_driver, pata_s3c_probe); -} - -static void __exit pata_s3c_exit(void) -{ -	platform_driver_unregister(&pata_s3c_driver); -} - -module_init(pata_s3c_init); -module_exit(pata_s3c_exit); +module_platform_driver_probe(pata_s3c_driver, pata_s3c_probe);  MODULE_AUTHOR("Abhilash Kesavan, <a.kesavan@samsung.com>");  MODULE_DESCRIPTION("low-level driver for Samsung PATA controller"); diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index e2c18257adf..c71de5d680d 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -32,13 +32,12 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h>  #include <linux/libata.h> -#define DRV_NAME	"sc1200" +#define DRV_NAME	"pata_sc1200"  #define DRV_VERSION	"0.2.6"  #define SC1200_REV_A	0x00 @@ -86,10 +85,14 @@ static int sc1200_clock(void)  static void sc1200_set_piomode(struct ata_port *ap, struct ata_device *adev)  {  	static const u32 pio_timings[4][5] = { -		{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},	// format0  33Mhz -		{0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010},	// format1, 33Mhz -		{0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021},	// format1, 48Mhz -		{0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}	// format1, 66Mhz +		/* format0, 33Mhz */ +		{ 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 }, +		/* format1, 33Mhz */ +		{ 0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010 }, +		/* format1, 48Mhz */ +		{ 0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021 }, +		/* format1, 66Mhz */ +		{ 0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131 }  	};  	struct pci_dev *pdev = to_pci_dev(ap->host->dev); @@ -251,27 +254,16 @@ static struct pci_driver sc1200_pci_driver = {  	.id_table	= sc1200,  	.probe 		= sc1200_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init sc1200_init(void) -{ -	return pci_register_driver(&sc1200_pci_driver); -} - -static void __exit sc1200_exit(void) -{ -	pci_unregister_driver(&sc1200_pci_driver); -} +module_pci_driver(sc1200_pci_driver);  MODULE_AUTHOR("Alan Cox, Mark Lord");  MODULE_DESCRIPTION("low-level driver for the NS/AMD SC1200");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, sc1200);  MODULE_VERSION(DRV_VERSION); - -module_init(sc1200_init); -module_exit(sc1200_exit); diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 093715c3273..4e006d74bef 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -35,7 +35,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -637,8 +636,7 @@ static int scc_softreset(struct ata_link *link, unsigned int *classes,  	DPRINTK("about to softreset, devmask=%x\n", devmask);  	err_mask = scc_bus_softreset(ap, devmask, deadline);  	if (err_mask) { -		ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n", -				err_mask); +		ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", err_mask);  		return -EIO;  	} @@ -827,18 +825,6 @@ static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,  }  /** - *	scc_pata_prereset - prepare for reset - *	@ap: ATA port to be reset - *	@deadline: deadline jiffies for the operation - */ - -static int scc_pata_prereset(struct ata_link *link, unsigned long deadline) -{ -	link->ap->cbl = ATA_CBL_PATA80; -	return ata_sff_prereset(link, deadline); -} - -/**   *	scc_postreset - standard postreset callback   *	@ap: the target ata_port   *	@classes: classes of attached devices @@ -947,7 +933,7 @@ static struct ata_port_operations scc_pata_ops = {  	.bmdma_status		= scc_bmdma_status,  	.sff_data_xfer		= scc_data_xfer, -	.prereset		= scc_pata_prereset, +	.cable_detect		= ata_cable_80wire,  	.softreset		= scc_softreset,  	.postreset		= scc_postreset, @@ -959,7 +945,7 @@ static struct ata_port_operations scc_pata_ops = {  static struct ata_port_info scc_port_info[] = {  	{ -		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY, +		.flags		= ATA_FLAG_SLAVE_POSS,  		.pio_mask	= ATA_PIO4,  		/* No MWDMA */  		.udma_mask	= ATA_UDMA6, @@ -1072,15 +1058,12 @@ static int scc_host_init(struct ata_host *host)  static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	unsigned int board_idx = (unsigned int) ent->driver_data;  	const struct ata_port_info *ppi[] = { &scc_port_info[board_idx], NULL };  	struct ata_host *host;  	int rc; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 1);  	if (!host) @@ -1113,32 +1096,13 @@ static struct pci_driver scc_pci_driver = {  	.id_table		= scc_pci_tbl,  	.probe			= scc_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ata_pci_device_resume,  #endif  }; -static int __init scc_init (void) -{ -	int rc; - -	DPRINTK("pci_register_driver\n"); -	rc = pci_register_driver(&scc_pci_driver); -	if (rc) -		return rc; - -	DPRINTK("done\n"); -	return 0; -} - -static void __exit scc_exit (void) -{ -	pci_unregister_driver(&scc_pci_driver); -} - -module_init(scc_init); -module_exit(scc_exit); +module_pci_driver(scc_pci_driver);  MODULE_AUTHOR("Toshiba corp");  MODULE_DESCRIPTION("SCSI low-level driver for Toshiba SCC PATA controller"); diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c index e97b32f03a6..b920c3407f8 100644 --- a/drivers/ata/pata_sch.c +++ b/drivers/ata/pata_sch.c @@ -27,7 +27,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -65,7 +64,7 @@ static struct pci_driver sch_pci_driver = {  	.id_table		= sch_pci_tbl,  	.probe			= sch_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ata_pci_device_resume,  #endif @@ -169,28 +168,13 @@ static void sch_set_dmamode(struct ata_port *ap, struct ata_device *adev)   *	Zero on success, or -ERRNO value.   */ -static int __devinit sch_init_one(struct pci_dev *pdev, -				   const struct pci_device_id *ent) +static int sch_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	const struct ata_port_info *ppi[] = { &sch_port_info, NULL }; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	return ata_pci_bmdma_init_one(pdev, ppi, &sch_sht, NULL, 0);  } -static int __init sch_init(void) -{ -	return pci_register_driver(&sch_pci_driver); -} - -static void __exit sch_exit(void) -{ -	pci_unregister_driver(&sch_pci_driver); -} - -module_init(sch_init); -module_exit(sch_exit); +module_pci_driver(sch_pci_driver); diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 86dd714e3e1..fc5f31d4828 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -34,7 +34,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -58,31 +57,15 @@ static const char *csb_bad_ata100[] = {  };  /** - *	dell_cable	-	Dell serverworks cable detection + *	oem_cable	-	Dell/Sun serverworks cable detection   *	@ap: ATA port to do cable detect   * - *	Dell hide the 40/80 pin select for their interfaces in the top two - *	bits of the subsystem ID. + *	Dell PowerEdge and Sun Cobalt 'Alpine' hide the 40/80 pin select + *	for their interfaces in the top two bits of the subsystem ID.   */ -static int dell_cable(struct ata_port *ap) { -	struct pci_dev *pdev = to_pci_dev(ap->host->dev); - -	if (pdev->subsystem_device & (1 << (ap->port_no + 14))) -		return ATA_CBL_PATA80; -	return ATA_CBL_PATA40; -} - -/** - *	sun_cable	-	Sun Cobalt 'Alpine' cable detection - *	@ap: ATA port to do cable select - * - *	Cobalt CSB5 IDE hides the 40/80pin in the top two bits of the - *	subsystem ID the same as dell. We could use one function but we may - *	need to extend the Dell one in future - */ - -static int sun_cable(struct ata_port *ap) { +static int oem_cable(struct ata_port *ap) +{  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	if (pdev->subsystem_device & (1 << (ap->port_no + 14))) @@ -90,49 +73,21 @@ static int sun_cable(struct ata_port *ap) {  	return ATA_CBL_PATA40;  } -/** - *	osb4_cable	-	OSB4 cable detect - *	@ap: ATA port to check - * - *	The OSB4 isn't UDMA66 capable so this is easy - */ - -static int osb4_cable(struct ata_port *ap) { -	return ATA_CBL_PATA40; -} - -/** - *	csb_cable	-	CSB5/6 cable detect - *	@ap: ATA port to check - * - *	Serverworks default arrangement is to use the drive side detection - *	only. - */ - -static int csb_cable(struct ata_port *ap) { -	return ATA_CBL_PATA_UNK; -} -  struct sv_cable_table {  	int device;  	int subvendor;  	int (*cable_detect)(struct ata_port *ap);  }; -/* - *	Note that we don't copy the old serverworks code because the old - *	code contains obvious mistakes - */ -  static struct sv_cable_table cable_detect[] = { -	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, dell_cable }, -	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, dell_cable }, -	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN,  sun_cable }, -	{ PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, osb4_cable }, -	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, csb_cable }, -	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, csb_cable }, -	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, csb_cable }, -	{ PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, csb_cable }, +	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_VENDOR_ID_DELL, oem_cable }, +	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE,   PCI_VENDOR_ID_DELL, oem_cable }, +	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_VENDOR_ID_SUN,  oem_cable }, +	{ PCI_DEVICE_ID_SERVERWORKS_OSB4IDE,   PCI_ANY_ID, ata_cable_40wire  }, +	{ PCI_DEVICE_ID_SERVERWORKS_CSB5IDE,   PCI_ANY_ID, ata_cable_unknown }, +	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE,   PCI_ANY_ID, ata_cable_unknown }, +	{ PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2,  PCI_ANY_ID, ata_cable_unknown }, +	{ PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, ata_cable_unknown },  	{ }  }; @@ -393,6 +348,31 @@ static void serverworks_fixup_ht1000(struct pci_dev *pdev)  	pci_write_config_byte(pdev, 0x5A, btr);  } +static int serverworks_fixup(struct pci_dev *pdev) +{ +	int rc = 0; + +	/* Force master latency timer to 64 PCI clocks */ +	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); + +	switch (pdev->device) { +	case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: +		rc = serverworks_fixup_osb4(pdev); +		break; +	case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: +		ata_pci_bmdma_clear_simplex(pdev); +		/* fall through */ +	case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: +	case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: +		rc = serverworks_fixup_csb(pdev); +		break; +	case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE: +		serverworks_fixup_ht1000(pdev); +		break; +	} + +	return rc; +}  static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  { @@ -430,13 +410,12 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id  	if (rc)  		return rc; -	/* Force master latency timer to 64 PCI clocks */ -	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); +	rc = serverworks_fixup(pdev);  	/* OSB4 : South Bridge and IDE */  	if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {  		/* Select non UDMA capable OSB4 if we can't do fixups */ -		if ( serverworks_fixup_osb4(pdev) < 0) +		if (rc < 0)  			ppi[0] = &info[1];  	}  	/* setup CSB5/CSB6 : South Bridge and IDE option RAID */ @@ -446,51 +425,28 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id  		 /* If the returned btr is the newer revision then  		    select the right info block */ -		 if (serverworks_fixup_csb(pdev) == 3) +		 if (rc == 3)  		 	ppi[0] = &info[3];  		/* Is this the 3rd channel CSB6 IDE ? */  		if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)  			ppi[1] = &ata_dummy_port_info;  	} -	/* setup HT1000E */ -	else if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) -		serverworks_fixup_ht1000(pdev); - -	if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) -		ata_pci_bmdma_clear_simplex(pdev);  	return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int serverworks_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev);  	if (rc)  		return rc; -	/* Force master latency timer to 64 PCI clocks */ -	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); - -	switch (pdev->device) { -		case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: -			serverworks_fixup_osb4(pdev); -			break; -		case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: -			ata_pci_bmdma_clear_simplex(pdev); -			/* fall through */ -		case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: -		case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: -			serverworks_fixup_csb(pdev); -			break; -		case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE: -			serverworks_fixup_ht1000(pdev); -			break; -	} +	(void)serverworks_fixup(pdev);  	ata_host_resume(host);  	return 0; @@ -512,27 +468,16 @@ static struct pci_driver serverworks_pci_driver = {  	.id_table	= serverworks,  	.probe 		= serverworks_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= serverworks_reinit_one,  #endif  }; -static int __init serverworks_init(void) -{ -	return pci_register_driver(&serverworks_pci_driver); -} - -static void __exit serverworks_exit(void) -{ -	pci_unregister_driver(&serverworks_pci_driver); -} +module_pci_driver(serverworks_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for Serverworks OSB4/CSB5/CSB6");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, serverworks);  MODULE_VERSION(DRV_VERSION); - -module_init(serverworks_init); -module_exit(serverworks_exit); diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 00eefbd84b3..f597edccede 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -11,7 +11,7 @@   *   *  May be copied or modified under the terms of the GNU General Public License   * - *  Documentation publically available. + *  Documentation publicly available.   *   *	If you have strange problems with nVidia chipset systems please   *	see the SI support documentation and update your system BIOS @@ -25,7 +25,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -38,12 +37,13 @@  /**   *	sil680_selreg		-	return register base - *	@hwif: interface + *	@ap: ATA interface   *	@r: config offset   * - *	Turn a config register offset into the right address in either - *	PCI space or MMIO space to access the control register in question - *	Thankfully this is a configuration operation so isnt performance + *	Turn a config register offset into the right address in PCI space + *	to access the control register in question. + * + *	Thankfully this is a configuration operation so isn't performance   *	criticial.   */ @@ -56,12 +56,12 @@ static unsigned long sil680_selreg(struct ata_port *ap, int r)  /**   *	sil680_seldev		-	return register base - *	@hwif: interface + *	@ap: ATA interface   *	@r: config offset   * - *	Turn a config register offset into the right address in either - *	PCI space or MMIO space to access the control register in question - *	including accounting for the unit shift. + *	Turn a config register offset into the right address in PCI space + *	to access the control register in question including accounting for + *	the unit shift.   */  static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev, int r) @@ -81,7 +81,8 @@ static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev,   *	space for us.   */ -static int sil680_cable_detect(struct ata_port *ap) { +static int sil680_cable_detect(struct ata_port *ap) +{  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	unsigned long addr = sil680_selreg(ap, 0);  	u8 ata66; @@ -93,7 +94,7 @@ static int sil680_cable_detect(struct ata_port *ap) {  }  /** - *	sil680_set_piomode	-	set initial PIO mode data + *	sil680_set_piomode	-	set PIO mode data   *	@ap: ATA interface   *	@adev: ATA device   * @@ -104,8 +105,12 @@ static int sil680_cable_detect(struct ata_port *ap) {  static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev)  { -	static u16 speed_p[5] = { 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 }; -	static u16 speed_t[5] = { 0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1 }; +	static const u16 speed_p[5] = { +		0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 +	}; +	static const u16 speed_t[5] = { +		0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1 +	};  	unsigned long tfaddr = sil680_selreg(ap, 0x02);  	unsigned long addr = sil680_seldev(ap, adev, 0x04); @@ -140,22 +145,23 @@ static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev)  }  /** - *	sil680_set_dmamode	-	set initial DMA mode data + *	sil680_set_dmamode	-	set DMA mode data   *	@ap: ATA interface   *	@adev: ATA device   * - *	Program the MWDMA/UDMA modes for the sil680 k - *	chipset. The MWDMA mode values are pulled from a lookup table + *	Program the MWDMA/UDMA modes for the sil680 chipset. + * + *	The MWDMA mode values are pulled from a lookup table   *	while the chipset uses mode number for UDMA.   */  static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev)  { -	static u8 ultra_table[2][7] = { +	static const u8 ultra_table[2][7] = {  		{ 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01, 0xFF },	/* 100MHz */  		{ 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 },	/* 133Mhz */  	}; -	static u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 }; +	static const u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 };  	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	unsigned long ma = sil680_seldev(ap, adev, 0x08); @@ -175,7 +181,7 @@ static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev)  	mode &= ~(0x03 << port_shift);  	/* Extract scsc */ -	scsc = (scsc & 0x30) ? 1: 0; +	scsc = (scsc & 0x30) ? 1 : 0;  	if (adev->dma_mode >= XFER_UDMA_0) {  		multi = 0x10C1; @@ -248,7 +254,7 @@ static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio)  {  	u8 tmpbyte	= 0; -        /* FIXME: double check */ +	/* FIXME: double check */  	pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE,  			      pdev->revision ? 1 : 255); @@ -266,22 +272,22 @@ static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio)  		*try_mmio = (tmpbyte & 1) || pci_resource_start(pdev, 5);  #endif -	switch(tmpbyte & 0x30) { -		case 0x00: -			/* 133 clock attempt to force it on */ -			pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10); -			break; -		case 0x30: -			/* if clocking is disabled */ -			/* 133 clock attempt to force it on */ -			pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20); -			break; -		case 0x10: -			/* 133 already */ -			break; -		case 0x20: -			/* BIOS set PCI x2 clocking */ -			break; +	switch (tmpbyte & 0x30) { +	case 0x00: +		/* 133 clock attempt to force it on */ +		pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10); +		break; +	case 0x30: +		/* if clocking is disabled */ +		/* 133 clock attempt to force it on */ +		pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20); +		break; +	case 0x10: +		/* 133 already */ +		break; +	case 0x20: +		/* BIOS set PCI x2 clocking */ +		break;  	}  	pci_read_config_byte(pdev,   0x8A, &tmpbyte); @@ -299,18 +305,24 @@ static u8 sil680_init_chip(struct pci_dev *pdev, int *try_mmio)  	pci_write_config_dword(pdev, 0xB8, 0x43924392);  	pci_write_config_dword(pdev, 0xBC, 0x40094009); -	switch(tmpbyte & 0x30) { -		case 0x00: printk(KERN_INFO "sil680: 100MHz clock.\n");break; -		case 0x10: printk(KERN_INFO "sil680: 133MHz clock.\n");break; -		case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break; -		/* This last case is _NOT_ ok */ -		case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n"); +	switch (tmpbyte & 0x30) { +	case 0x00: +		printk(KERN_INFO "sil680: 100MHz clock.\n"); +		break; +	case 0x10: +		printk(KERN_INFO "sil680: 133MHz clock.\n"); +		break; +	case 0x20: +		printk(KERN_INFO "sil680: Using PCI clock.\n"); +		break; +	/* This last case is _NOT_ ok */ +	case 0x30: +		printk(KERN_ERR "sil680: Clock disabled ?\n");  	}  	return tmpbyte & 0x30;  } -static int __devinit sil680_init_one(struct pci_dev *pdev, -				     const struct pci_device_id *id) +static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  {  	static const struct ata_port_info info = {  		.flags = ATA_FLAG_SLAVE_POSS, @@ -327,13 +339,11 @@ static int __devinit sil680_init_one(struct pci_dev *pdev,  		.port_ops = &sil680_port_ops  	};  	const struct ata_port_info *ppi[] = { &info, NULL }; -	static int printed_version;  	struct ata_host *host;  	void __iomem *mmio_base;  	int rc, try_mmio; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -393,10 +403,10 @@ use_ioports:  	return ata_pci_bmdma_init_one(pdev, ppi, &sil680_sht, NULL, 0);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int sil680_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int try_mmio, rc;  	rc = ata_pci_device_do_resume(pdev); @@ -419,27 +429,16 @@ static struct pci_driver sil680_pci_driver = {  	.id_table	= sil680,  	.probe 		= sil680_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= sil680_reinit_one,  #endif  }; -static int __init sil680_init(void) -{ -	return pci_register_driver(&sil680_pci_driver); -} - -static void __exit sil680_exit(void) -{ -	pci_unregister_driver(&sil680_pci_driver); -} +module_pci_driver(sil680_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for SI680 PATA");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, sil680);  MODULE_VERSION(DRV_VERSION); - -module_init(sil680_init); -module_exit(sil680_exit); diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index 60cea13cccc..626f989d5c6 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -26,7 +26,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -55,7 +54,7 @@ static const struct sis_laptop sis_laptop[] = {  	/* devid, subvendor, subdev */  	{ 0x5513, 0x1043, 0x1107 },	/* ASUS A6K */  	{ 0x5513, 0x1734, 0x105F },	/* FSC Amilo A1630 */ -	{ 0x5513, 0x1071, 0x8640 },     /* EasyNote K5305 */ +	{ 0x5513, 0x1071, 0x8640 },	/* EasyNote K5305 */  	/* end marker */  	{ 0, }  }; @@ -76,7 +75,7 @@ static int sis_short_ata40(struct pci_dev *dev)  }  /** - *	sis_old_port_base		-	return PCI configuration base for dev + *	sis_old_port_base - return PCI configuration base for dev   *	@adev: device   *   *	Returns the base of the PCI configuration registers for this port @@ -85,11 +84,34 @@ static int sis_short_ata40(struct pci_dev *dev)  static int sis_old_port_base(struct ata_device *adev)  { -	return  0x40 + (4 * adev->link->ap->port_no) +  (2 * adev->devno); +	return 0x40 + (4 * adev->link->ap->port_no) + (2 * adev->devno);  }  /** - *	sis_133_cable_detect	-	check for 40/80 pin + *	sis_port_base - return PCI configuration base for dev + *	@adev: device + * + *	Returns the base of the PCI configuration registers for this port + *	number. + */ + +static int sis_port_base(struct ata_device *adev) +{ +	struct ata_port *ap = adev->link->ap; +	struct pci_dev *pdev = to_pci_dev(ap->host->dev); +	int port = 0x40; +	u32 reg54; + +	/* If bit 30 is set then the registers are mapped at 0x70 not 0x40 */ +	pci_read_config_dword(pdev, 0x54, ®54); +	if (reg54 & 0x40000000) +		port = 0x70; + +	return port + (8 * ap->port_no) + (4 * adev->devno); +} + +/** + *	sis_133_cable_detect - check for 40/80 pin   *	@ap: Port   *	@deadline: deadline jiffies for the operation   * @@ -110,7 +132,7 @@ static int sis_133_cable_detect(struct ata_port *ap)  }  /** - *	sis_66_cable_detect	-	check for 40/80 pin + *	sis_66_cable_detect - check for 40/80 pin   *	@ap: Port   *   *	Perform cable detection on the UDMA66, UDMA100 and early UDMA133 @@ -132,7 +154,7 @@ static int sis_66_cable_detect(struct ata_port *ap)  /** - *	sis_pre_reset		-	probe begin + *	sis_pre_reset - probe begin   *	@link: ATA link   *	@deadline: deadline jiffies for the operation   * @@ -160,7 +182,7 @@ static int sis_pre_reset(struct ata_link *link, unsigned long deadline)  /** - *	sis_set_fifo	-	Set RWP fifo bits for this device + *	sis_set_fifo - Set RWP fifo bits for this device   *	@ap: Port   *	@adev: Device   * @@ -203,13 +225,13 @@ static void sis_set_fifo(struct ata_port *ap, struct ata_device *adev)  static void sis_old_set_piomode (struct ata_port *ap, struct ata_device *adev)  { -	struct pci_dev *pdev	= to_pci_dev(ap->host->dev); +	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	int port = sis_old_port_base(adev);  	u8 t1, t2;  	int speed = adev->pio_mode - XFER_PIO_0; -	const u8 active[]   = { 0x00, 0x07, 0x04, 0x03, 0x01 }; -	const u8 recovery[] = { 0x00, 0x06, 0x04, 0x03, 0x03 }; +	static const u8 active[]   = { 0x00, 0x07, 0x04, 0x03, 0x01 }; +	static const u8 recovery[] = { 0x00, 0x06, 0x04, 0x03, 0x03 };  	sis_set_fifo(ap, adev); @@ -240,11 +262,11 @@ static void sis_old_set_piomode (struct ata_port *ap, struct ata_device *adev)  static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev)  { -	struct pci_dev *pdev	= to_pci_dev(ap->host->dev); +	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	int port = sis_old_port_base(adev);  	int speed = adev->pio_mode - XFER_PIO_0; -	const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 }; +	static const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };  	sis_set_fifo(ap, adev); @@ -265,20 +287,19 @@ static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev)  static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)  { -	struct pci_dev *pdev	= to_pci_dev(ap->host->dev); -	int port = 0x40; +	struct pci_dev *pdev = to_pci_dev(ap->host->dev); +	int port;  	u32 t1; -	u32 reg54;  	int speed = adev->pio_mode - XFER_PIO_0; -	const u32 timing133[] = { +	static const u32 timing133[] = {  		0x28269000,	/* Recovery << 24 | Act << 16 | Ini << 12 */  		0x0C266000,  		0x04263000,  		0x0C0A3000,  		0x05093000  	}; -	const u32 timing100[] = { +	static const u32 timing100[] = {  		0x1E1C6000,	/* Recovery << 24 | Act << 16 | Ini << 12 */  		0x091C4000,  		0x031C2000, @@ -288,12 +309,7 @@ static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)  	sis_set_fifo(ap, adev); -	/* If bit 14 is set then the registers are mapped at 0x70 not 0x40 */ -	pci_read_config_dword(pdev, 0x54, ®54); -	if (reg54 & 0x40000000) -		port = 0x70; -	port += 8 * ap->port_no +  4 * adev->devno; - +	port = sis_port_base(adev);  	pci_read_config_dword(pdev, port, &t1);  	t1 &= 0xC0C00FFF;	/* Mask out timing */ @@ -319,19 +335,19 @@ static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)  static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev)  { -	struct pci_dev *pdev	= to_pci_dev(ap->host->dev); +	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	int speed = adev->dma_mode - XFER_MW_DMA_0;  	int drive_pci = sis_old_port_base(adev);  	u16 timing; -	const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 }; -	const u16 udma_bits[]  = { 0xE000, 0xC000, 0xA000 }; +	static const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 }; +	static const u16 udma_bits[]  = { 0xE000, 0xC000, 0xA000 };  	pci_read_config_word(pdev, drive_pci, &timing);  	if (adev->dma_mode < XFER_UDMA_0) {  		/* bits 3-0 hold recovery timing bits 8-10 active timing and -		   the higher bits are dependant on the device */ +		   the higher bits are dependent on the device */  		timing &= ~0x870F;  		timing |= mwdma_bits[speed];  	} else { @@ -358,20 +374,20 @@ static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev)  static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)  { -	struct pci_dev *pdev	= to_pci_dev(ap->host->dev); +	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	int speed = adev->dma_mode - XFER_MW_DMA_0;  	int drive_pci = sis_old_port_base(adev);  	u16 timing;  	/* MWDMA 0-2 and UDMA 0-5 */ -	const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 }; -	const u16 udma_bits[]  = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000, 0x8000 }; +	static const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 }; +	static const u16 udma_bits[]  = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000, 0x8000 };  	pci_read_config_word(pdev, drive_pci, &timing);  	if (adev->dma_mode < XFER_UDMA_0) {  		/* bits 3-0 hold recovery timing bits 8-10 active timing and -		   the higher bits are dependant on the device, bit 15 udma */ +		   the higher bits are dependent on the device, bit 15 udma */  		timing &= ~0x870F;  		timing |= mwdma_bits[speed];  	} else { @@ -397,12 +413,12 @@ static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)  static void sis_100_set_dmamode (struct ata_port *ap, struct ata_device *adev)  { -	struct pci_dev *pdev	= to_pci_dev(ap->host->dev); +	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	int speed = adev->dma_mode - XFER_MW_DMA_0;  	int drive_pci = sis_old_port_base(adev);  	u8 timing; -	const u8 udma_bits[]  = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81}; +	static const u8 udma_bits[]  = { 0x8B, 0x87, 0x85, 0x83, 0x82, 0x81};  	pci_read_config_byte(pdev, drive_pci + 1, &timing); @@ -431,7 +447,7 @@ static void sis_100_set_dmamode (struct ata_port *ap, struct ata_device *adev)  static void sis_133_early_set_dmamode (struct ata_port *ap, struct ata_device *adev)  { -	struct pci_dev *pdev	= to_pci_dev(ap->host->dev); +	struct pci_dev *pdev = to_pci_dev(ap->host->dev);  	int speed = adev->dma_mode - XFER_MW_DMA_0;  	int drive_pci = sis_old_port_base(adev);  	u8 timing; @@ -464,32 +480,34 @@ static void sis_133_early_set_dmamode (struct ata_port *ap, struct ata_device *a  static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev)  { -	struct pci_dev *pdev	= to_pci_dev(ap->host->dev); -	int speed = adev->dma_mode - XFER_MW_DMA_0; -	int port = 0x40; +	struct pci_dev *pdev = to_pci_dev(ap->host->dev); +	int port;  	u32 t1; -	u32 reg54; - -	/* bits 4- cycle time 8 - cvs time */ -	static const u32 timing_u100[] = { 0x6B0, 0x470, 0x350, 0x140, 0x120, 0x110, 0x000 }; -	static const u32 timing_u133[] = { 0x9F0, 0x6A0, 0x470, 0x250, 0x230, 0x220, 0x210 }; - -	/* If bit 14 is set then the registers are mapped at 0x70 not 0x40 */ -	pci_read_config_dword(pdev, 0x54, ®54); -	if (reg54 & 0x40000000) -		port = 0x70; -	port += (8 * ap->port_no) +  (4 * adev->devno); +	port = sis_port_base(adev);  	pci_read_config_dword(pdev, port, &t1);  	if (adev->dma_mode < XFER_UDMA_0) { +		/* Recovery << 24 | Act << 16 | Ini << 12, like PIO modes */ +		static const u32 timing_u100[] = { 0x19154000, 0x06072000, 0x04062000 }; +		static const u32 timing_u133[] = { 0x221C6000, 0x0C0A3000, 0x05093000 }; +		int speed = adev->dma_mode - XFER_MW_DMA_0; + +		t1 &= 0xC0C00FFF; +		/* disable UDMA */  		t1 &= ~0x00000004; -		/* FIXME: need data sheet to add MWDMA here. Also lacking on -		   ide/pci driver */ +		if (t1 & 0x08) +			t1 |= timing_u133[speed]; +		else +			t1 |= timing_u100[speed];  	} else { -		speed = adev->dma_mode - XFER_UDMA_0; -		/* if & 8 no UDMA133 - need info for ... */ +		/* bits 4- cycle time 8 - cvs time */ +		static const u32 timing_u100[] = { 0x6B0, 0x470, 0x350, 0x140, 0x120, 0x110, 0x000 }; +		static const u32 timing_u133[] = { 0x9F0, 0x6A0, 0x470, 0x250, 0x230, 0x220, 0x210 }; +		int speed = adev->dma_mode - XFER_UDMA_0; +  		t1 &= ~0x00000FF0; +		/* enable UDMA */  		t1 |= 0x00000004;  		if (t1 & 0x08)  			t1 |= timing_u133[speed]; @@ -499,6 +517,27 @@ static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev)  	pci_write_config_dword(pdev, port, t1);  } +/** + *	sis_133_mode_filter - mode selection filter + *	@adev: ATA device + * + *	Block UDMA6 on devices that do not support it. + */ + +static unsigned long sis_133_mode_filter(struct ata_device *adev, unsigned long mask) +{ +	struct ata_port *ap = adev->link->ap; +	struct pci_dev *pdev = to_pci_dev(ap->host->dev); +	int port = sis_port_base(adev); +	u32 t1; + +	pci_read_config_dword(pdev, port, &t1); +	/* if ATA133 is disabled, mask it out */ +	if (!(t1 & 0x08)) +		mask &= ~(0xC0 << ATA_SHIFT_UDMA); +	return mask; +} +  static struct scsi_host_template sis_sht = {  	ATA_BMDMA_SHT(DRV_NAME),  }; @@ -520,6 +559,7 @@ static struct ata_port_operations sis_133_ops = {  	.set_piomode		= sis_133_set_piomode,  	.set_dmamode		= sis_133_set_dmamode,  	.cable_detect		= sis_133_cable_detect, +	.mode_filter		= sis_133_mode_filter,  };  static struct ata_port_operations sis_133_early_ops = { @@ -588,12 +628,12 @@ static const struct ata_port_info sis_info100_early = {  static const struct ata_port_info sis_info133 = {  	.flags		= ATA_FLAG_SLAVE_POSS,  	.pio_mask	= ATA_PIO4, -	/* No MWDMA */ +	.mwdma_mask	= ATA_MWDMA2,  	.udma_mask	= ATA_UDMA6,  	.port_ops	= &sis_133_ops,  };  const struct ata_port_info sis_info133_for_sata = { -	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, +	.flags		= ATA_FLAG_SLAVE_POSS,  	.pio_mask	= ATA_PIO4,  	/* No MWDMA */  	.udma_mask	= ATA_UDMA6, @@ -669,7 +709,7 @@ static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis)   *	@pdev: PCI device to register   *	@ent: Entry in sis_pci_tbl matching with @pdev   * - *	Called from kernel PCI layer.  We probe for combined mode (sigh), + *	Called from kernel PCI layer. We probe for combined mode (sigh),   *	and then hand over control to libata, for it to do the rest.   *   *	LOCKING: @@ -681,7 +721,6 @@ static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis)  static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	const struct ata_port_info *ppi[] = { NULL, NULL };  	struct pci_dev *host = NULL;  	struct sis_chipset *chipset = NULL; @@ -735,9 +774,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  		0x0, &sis_info100  	}; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -772,17 +809,20 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  		switch(trueid) {  		case 0x5518:	/* SIS 962/963 */ +			dev_info(&pdev->dev, +				 "SiS 962/963 MuTIOL IDE UDMA133 controller\n");  			chipset = &sis133;  			if ((idemisc & 0x40000000) == 0) {  				pci_write_config_dword(pdev, 0x54, idemisc | 0x40000000); -				printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n"); +				dev_info(&pdev->dev, +					 "Switching to 5513 register mapping\n");  			}  			break;  		case 0x0180:	/* SIS 965/965L */ -			chipset =  &sis133; +			chipset = &sis133;  			break;  		case 0x1180:	/* SIS 966/966L */ -			chipset =  &sis133; +			chipset = &sis133;  			break;  		}  	} @@ -829,10 +869,10 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)  	return ata_pci_bmdma_init_one(pdev, ppi, &sis_sht, chipset, 0);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int sis_reinit_one(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -859,28 +899,16 @@ static struct pci_driver sis_pci_driver = {  	.id_table		= sis_pci_tbl,  	.probe			= sis_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= sis_reinit_one,  #endif  }; -static int __init sis_init(void) -{ -	return pci_register_driver(&sis_pci_driver); -} - -static void __exit sis_exit(void) -{ -	pci_unregister_driver(&sis_pci_driver); -} - -module_init(sis_init); -module_exit(sis_exit); +module_pci_driver(sis_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("SCSI low-level driver for SiS ATA");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, sis_pci_tbl);  MODULE_VERSION(DRV_VERSION); - diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c index 7f5d020ed56..4935f61f629 100644 --- a/drivers/ata/pata_sl82c105.c +++ b/drivers/ata/pata_sl82c105.c @@ -1,6 +1,7 @@  /*   * pata_sl82c105.c 	- SL82C105 PATA for new ATA layer   *			  (C) 2005 Red Hat Inc + *			  (C) 2011 Bartlomiej Zolnierkiewicz   *   * Based in part on linux/drivers/ide/pci/sl82c105.c   * 		SL82C105/Winbond 553 IDE driver @@ -18,7 +19,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -289,6 +289,14 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)  	return bridge->revision;  } +static void sl82c105_fixup(struct pci_dev *pdev) +{ +	u32 val; + +	pci_read_config_dword(pdev, 0x40, &val); +	val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; +	pci_write_config_dword(pdev, 0x40, val); +}  static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)  { @@ -306,7 +314,6 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id  	/* for now use only the first port */  	const struct ata_port_info *ppi[] = { &info_early,  					       NULL }; -	u32 val;  	int rev;  	int rc; @@ -317,19 +324,36 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id  	rev = sl82c105_bridge_revision(dev);  	if (rev == -1) -		dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Unable to find bridge, disabling DMA.\n"); +		dev_warn(&dev->dev, +			 "pata_sl82c105: Unable to find bridge, disabling DMA\n");  	else if (rev <= 5) -		dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Early bridge revision, no DMA available.\n"); +		dev_warn(&dev->dev, +			 "pata_sl82c105: Early bridge revision, no DMA available\n");  	else  		ppi[0] = &info_dma; -	pci_read_config_dword(dev, 0x40, &val); -	val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; -	pci_write_config_dword(dev, 0x40, val); +	sl82c105_fixup(dev);  	return ata_pci_bmdma_init_one(dev, ppi, &sl82c105_sht, NULL, 0);  } +#ifdef CONFIG_PM_SLEEP +static int sl82c105_reinit_one(struct pci_dev *pdev) +{ +	struct ata_host *host = pci_get_drvdata(pdev); +	int rc; + +	rc = ata_pci_device_do_resume(pdev); +	if (rc) +		return rc; + +	sl82c105_fixup(pdev); + +	ata_host_resume(host); +	return 0; +} +#endif +  static const struct pci_device_id sl82c105[] = {  	{ PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), }, @@ -340,24 +364,17 @@ static struct pci_driver sl82c105_pci_driver = {  	.name 		= DRV_NAME,  	.id_table	= sl82c105,  	.probe 		= sl82c105_init_one, -	.remove		= ata_pci_remove_one +	.remove		= ata_pci_remove_one, +#ifdef CONFIG_PM_SLEEP +	.suspend	= ata_pci_device_suspend, +	.resume		= sl82c105_reinit_one, +#endif  }; -static int __init sl82c105_init(void) -{ -	return pci_register_driver(&sl82c105_pci_driver); -} - -static void __exit sl82c105_exit(void) -{ -	pci_unregister_driver(&sl82c105_pci_driver); -} +module_pci_driver(sl82c105_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for Sl82c105");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, sl82c105);  MODULE_VERSION(DRV_VERSION); - -module_init(sl82c105_init); -module_exit(sl82c105_exit); diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c index 0d1f89e571d..d9364af8eb6 100644 --- a/drivers/ata/pata_triflex.c +++ b/drivers/ata/pata_triflex.c @@ -30,13 +30,12 @@   * Loosely based on the piix & svwks drivers.   *   * Documentation: - *	Not publically available. + *	Not publicly available.   */  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <scsi/scsi_host.h> @@ -196,10 +195,8 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)  		.port_ops = &triflex_port_ops  	};  	const struct ata_port_info *ppi[] = { &info, NULL }; -	static int printed_version; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&dev->dev, DRV_VERSION);  	return ata_pci_bmdma_init_one(dev, ppi, &triflex_sht, NULL, 0);  } @@ -210,32 +207,42 @@ static const struct pci_device_id triflex[] = {  	{ },  }; +#ifdef CONFIG_PM_SLEEP +static int triflex_ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ +	struct ata_host *host = pci_get_drvdata(pdev); +	int rc = 0; + +	rc = ata_host_suspend(host, mesg); +	if (rc) +		return rc; + +	/* +	 * We must not disable or powerdown the device. +	 * APM bios refuses to suspend if IDE is not accessible. +	 */ +	pci_save_state(pdev); + +	return 0; +} + +#endif +  static struct pci_driver triflex_pci_driver = {  	.name 		= DRV_NAME,  	.id_table	= triflex,  	.probe 		= triflex_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM -	.suspend	= ata_pci_device_suspend, +#ifdef CONFIG_PM_SLEEP +	.suspend	= triflex_ata_pci_device_suspend,  	.resume		= ata_pci_device_resume,  #endif  }; -static int __init triflex_init(void) -{ -	return pci_register_driver(&triflex_pci_driver); -} - -static void __exit triflex_exit(void) -{ -	pci_unregister_driver(&triflex_pci_driver); -} +module_pci_driver(triflex_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for Compaq Triflex");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, triflex);  MODULE_VERSION(DRV_VERSION); - -module_init(triflex_init); -module_exit(triflex_exit); diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index ac8d7d97e40..1ca6bcab369 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -55,7 +55,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/gfp.h> @@ -124,6 +123,17 @@ static const struct via_isa_bridge {  	{ NULL }  }; +static const struct dmi_system_id no_atapi_dma_dmi_table[] = { +	{ +		.ident = "AVERATEC 3200", +		.matches = { +			DMI_MATCH(DMI_BOARD_VENDOR, "AVERATEC"), +			DMI_MATCH(DMI_BOARD_NAME, "3200"), +		}, +	}, +	{ } +}; +  struct via_port {  	u8 cached_device;  }; @@ -350,11 +360,18 @@ static unsigned long via_mode_filter(struct ata_device *dev, unsigned long mask)  	if (config->id == PCI_DEVICE_ID_VIA_82C586_0) {  		ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));  		if (strcmp(model_num, "TS64GSSD25-M") == 0) { -			ata_dev_printk(dev, KERN_WARNING, -	"disabling UDMA mode due to reported lockups with this device.\n"); +			ata_dev_warn(dev, +	"disabling UDMA mode due to reported lockups with this device\n");  			mask &= ~ ATA_MASK_UDMA;  		}  	} + +	if (dev->class == ATA_DEV_ATAPI && +	    dmi_check_system(no_atapi_dma_dmi_table)) { +		ata_dev_warn(dev, "controller locks up on ATAPI DMA, forcing PIO\n"); +		mask &= ATA_MASK_PIO; +	} +  	return mask;  } @@ -491,6 +508,27 @@ static void via_config_fifo(struct pci_dev *pdev, unsigned int flags)  	}  } +static void via_fixup(struct pci_dev *pdev, const struct via_isa_bridge *config) +{ +	u32 timing; + +	/* Initialise the FIFO for the enabled channels. */ +	via_config_fifo(pdev, config->flags); + +	if (config->udma_mask == ATA_UDMA4) { +		/* The 66 MHz devices require we enable the clock */ +		pci_read_config_dword(pdev, 0x50, &timing); +		timing |= 0x80008; +		pci_write_config_dword(pdev, 0x50, timing); +	} +	if (config->flags & VIA_BAD_CLK66) { +		/* Disable the 66MHz clock on problem devices */ +		pci_read_config_dword(pdev, 0x50, &timing); +		timing &= ~0x80008; +		pci_write_config_dword(pdev, 0x50, timing); +	} +} +  /**   *	via_init_one		-	discovery callback   *	@pdev: PCI device @@ -551,14 +589,11 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  	const struct ata_port_info *ppi[] = { NULL, NULL };  	struct pci_dev *isa;  	const struct via_isa_bridge *config; -	static int printed_version;  	u8 enable; -	u32 timing;  	unsigned long flags = id->driver_data;  	int rc; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -593,9 +628,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  			return -ENODEV;  	} -	/* Initialise the FIFO for the enabled channels. */ -	via_config_fifo(pdev, config->flags); -  	/* Clock set up */  	switch (config->udma_mask) {  	case 0x00: @@ -621,18 +653,13 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  		return -ENODEV;   	} -	if (config->flags & VIA_BAD_CLK66) { -		/* Disable the 66MHz clock on problem devices */ -		pci_read_config_dword(pdev, 0x50, &timing); -		timing &= ~0x80008; -		pci_write_config_dword(pdev, 0x50, timing); -	} +	via_fixup(pdev, config);  	/* We have established the device type, now fire it up */  	return ata_pci_bmdma_init_one(pdev, ppi, &via_sht, (void *)config, 0);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  /**   *	via_reinit_one		-	reinit after resume   *	@pdev; PCI device @@ -645,29 +672,14 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  static int via_reinit_one(struct pci_dev *pdev)  { -	u32 timing; -	struct ata_host *host = dev_get_drvdata(&pdev->dev); -	const struct via_isa_bridge *config = host->private_data; +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev);  	if (rc)  		return rc; -	via_config_fifo(pdev, config->flags); - -	if (config->udma_mask == ATA_UDMA4) { -		/* The 66 MHz devices require we enable the clock */ -		pci_read_config_dword(pdev, 0x50, &timing); -		timing |= 0x80008; -		pci_write_config_dword(pdev, 0x50, timing); -	} -	if (config->flags & VIA_BAD_CLK66) { -		/* Disable the 66MHz clock on problem devices */ -		pci_read_config_dword(pdev, 0x50, &timing); -		timing &= ~0x80008; -		pci_write_config_dword(pdev, 0x50, timing); -	} +	via_fixup(pdev, host->private_data);  	ata_host_resume(host);  	return 0; @@ -692,27 +704,16 @@ static struct pci_driver via_pci_driver = {  	.id_table	= via,  	.probe 		= via_init_one,  	.remove		= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= via_reinit_one,  #endif  }; -static int __init via_init(void) -{ -	return pci_register_driver(&via_pci_driver); -} - -static void __exit via_exit(void) -{ -	pci_unregister_driver(&via_pci_driver); -} +module_pci_driver(via_pci_driver);  MODULE_AUTHOR("Alan Cox");  MODULE_DESCRIPTION("low-level driver for VIA PATA");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, via);  MODULE_VERSION(DRV_VERSION); - -module_init(via_init); -module_exit(via_exit); diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index adbe0426c8f..f10631beffa 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -1,7 +1,7 @@  /*   *  pdc_adma.c - Pacific Digital Corporation ADMA   * - *  Maintained by:  Mark Lord <mlord@pobox.com> + *  Maintained by:  Tejun Heo <tj@kernel.org>   *   *  Copyright 2005 Mark Lord   * @@ -36,7 +36,6 @@  #include <linux/module.h>  #include <linux/gfp.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -166,9 +165,7 @@ static struct ata_port_operations adma_ata_ops = {  static struct ata_port_info adma_port_info[] = {  	/* board_1841_idx */  	{ -		.flags		= ATA_FLAG_SLAVE_POSS | -				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | -				  ATA_FLAG_PIO_POLLING, +		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_POLLING,  		.pio_mask	= ATA_PIO4_ONLY,  		.udma_mask	= ATA_UDMA4,  		.port_ops	= &adma_ata_ops, @@ -598,14 +595,12 @@ static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)  	rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));  	if (rc) { -		dev_printk(KERN_ERR, &pdev->dev, -			"32-bit DMA enable failed\n"); +		dev_err(&pdev->dev, "32-bit DMA enable failed\n");  		return rc;  	}  	rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));  	if (rc) { -		dev_printk(KERN_ERR, &pdev->dev, -			"32-bit consistent DMA enable failed\n"); +		dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n");  		return rc;  	}  	return 0; @@ -614,15 +609,13 @@ static int adma_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)  static int adma_ata_init_one(struct pci_dev *pdev,  			     const struct pci_device_id *ent)  { -	static int printed_version;  	unsigned int board_idx = (unsigned int) ent->driver_data;  	const struct ata_port_info *ppi[] = { &adma_port_info[board_idx], NULL };  	struct ata_host *host;  	void __iomem *mmio_base;  	int rc, port_no; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* alloc host */  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, ADMA_PORTS); @@ -666,21 +659,10 @@ static int adma_ata_init_one(struct pci_dev *pdev,  				 &adma_ata_sht);  } -static int __init adma_ata_init(void) -{ -	return pci_register_driver(&adma_ata_pci_driver); -} - -static void __exit adma_ata_exit(void) -{ -	pci_unregister_driver(&adma_ata_pci_driver); -} +module_pci_driver(adma_ata_pci_driver);  MODULE_AUTHOR("Mark Lord");  MODULE_DESCRIPTION("Pacific Digital Corporation ADMA low-level driver");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, adma_ata_pci_tbl);  MODULE_VERSION(DRV_VERSION); - -module_init(adma_ata_init); -module_exit(adma_ata_exit); diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 6cf57c5c2b5..0bb2cabd219 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -29,8 +29,9 @@  #include <linux/kernel.h>  #include <linux/module.h> -#include <linux/init.h>  #include <linux/device.h> +#include <linux/of_address.h> +#include <linux/of_irq.h>  #include <linux/of_platform.h>  #include <linux/platform_device.h>  #include <linux/libata.h> @@ -40,8 +41,12 @@  #include <scsi/scsi_host.h>  #include <scsi/scsi_cmnd.h> +/* These two are defined in "libata.h" */ +#undef	DRV_NAME +#undef	DRV_VERSION +  #define DRV_NAME        "sata-dwc" -#define DRV_VERSION     "1.0" +#define DRV_VERSION     "1.3"  /* SATA DMA driver Globals */  #define DMA_NUM_CHANS		1 @@ -155,6 +160,7 @@ enum {  /* Assign HW handshaking interface (x) to destination / source peripheral */  #define	DMA_CFG_HW_HS_DEST(int_num) (((int_num) & 0xF) << 11)  #define	DMA_CFG_HW_HS_SRC(int_num) (((int_num) & 0xF) << 7) +#define	DMA_CFG_HW_CH_PRIOR(int_num) (((int_num) & 0xF) << 5)  #define	DMA_LLP_LMS(addr, master) (((addr) & 0xfffffffc) | (master))  /* @@ -315,6 +321,7 @@ struct sata_dwc_host_priv {  	u32	dma_interrupt_count;  	struct	ahb_dma_regs	*sata_dma_regs;  	struct	device	*dwc_dev; +	int	dma_channel;  };  struct sata_dwc_host_priv host_pvt;  /* @@ -333,11 +340,47 @@ static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,  			      void __iomem *addr, int dir);  static void dma_dwc_xfer_start(int dma_ch); +static const char *get_prot_descript(u8 protocol) +{ +	switch ((enum ata_tf_protocols)protocol) { +	case ATA_PROT_NODATA: +		return "ATA no data"; +	case ATA_PROT_PIO: +		return "ATA PIO"; +	case ATA_PROT_DMA: +		return "ATA DMA"; +	case ATA_PROT_NCQ: +		return "ATA NCQ"; +	case ATAPI_PROT_NODATA: +		return "ATAPI no data"; +	case ATAPI_PROT_PIO: +		return "ATAPI PIO"; +	case ATAPI_PROT_DMA: +		return "ATAPI DMA"; +	default: +		return "unknown"; +	} +} + +static const char *get_dma_dir_descript(int dma_dir) +{ +	switch ((enum dma_data_direction)dma_dir) { +	case DMA_BIDIRECTIONAL: +		return "bidirectional"; +	case DMA_TO_DEVICE: +		return "to device"; +	case DMA_FROM_DEVICE: +		return "from device"; +	default: +		return "none"; +	} +} +  static void sata_dwc_tf_dump(struct ata_taskfile *tf)  {  	dev_vdbg(host_pvt.dwc_dev, "taskfile cmd: 0x%02x protocol: %s flags:" -		"0x%lx device: %x\n", tf->command, ata_get_cmd_descript\ -		(tf->protocol), tf->flags, tf->device); +		"0x%lx device: %x\n", tf->command, +		get_prot_descript(tf->protocol), tf->flags, tf->device);  	dev_vdbg(host_pvt.dwc_dev, "feature: 0x%02x nsect: 0x%x lbal: 0x%x "  		"lbam: 0x%x lbah: 0x%x\n", tf->feature, tf->nsect, tf->lbal,  		 tf->lbam, tf->lbah); @@ -350,7 +393,7 @@ static void sata_dwc_tf_dump(struct ata_taskfile *tf)  /*   * Function: get_burst_length_encode   * arguments: datalength: length in bytes of data - * returns value to be programmed in register corrresponding to data length + * returns value to be programmed in register corresponding to data length   * This value is effectively the log(base 2) of the length   */  static  int get_burst_length_encode(int datalength) @@ -398,15 +441,12 @@ static  void clear_chan_interrupts(int c)   */  static int dma_request_channel(void)  { -	int i; - -	for (i = 0; i < DMA_NUM_CHANS; i++) { -		if (!(in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) &\ -			DMA_CHANNEL(i))) -			return i; -	} -	dev_err(host_pvt.dwc_dev, "%s NO channel chan_en: 0x%08x\n", __func__, -		in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low))); +	/* Check if the channel is not currently in use */ +	if (!(in_le32(&(host_pvt.sata_dma_regs->dma_chan_en.low)) & +		DMA_CHANNEL(host_pvt.dma_channel))) +		return host_pvt.dma_channel; +	dev_err(host_pvt.dwc_dev, "%s Channel %d is currently in use\n", +		__func__, host_pvt.dma_channel);  	return -1;  } @@ -421,8 +461,7 @@ static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance)  	int chan;  	u32 tfr_reg, err_reg;  	unsigned long flags; -	struct sata_dwc_device *hsdev = -		(struct sata_dwc_device *)hsdev_instance; +	struct sata_dwc_device *hsdev = hsdev_instance;  	struct ata_host *host = (struct ata_host *)hsdev->host;  	struct ata_port *ap;  	struct sata_dwc_device_port *hsdevp; @@ -442,7 +481,8 @@ static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance)  	dev_dbg(ap->dev, "eot=0x%08x err=0x%08x pending=%d active port=%d\n",  		tfr_reg, err_reg, hsdevp->dma_pending[tag], port); -	for (chan = 0; chan < DMA_NUM_CHANS; chan++) { +	chan = host_pvt.dma_channel; +	if (chan >= 0) {  		/* Check for end-of-transfer interrupt. */  		if (tfr_reg & DMA_CHANNEL(chan)) {  			/* @@ -495,9 +535,9 @@ static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance)  static int dma_request_interrupts(struct sata_dwc_device *hsdev, int irq)  {  	int retval = 0; -	int chan; +	int chan = host_pvt.dma_channel; -	for (chan = 0; chan < DMA_NUM_CHANS; chan++) { +	if (chan >= 0) {  		/* Unmask error interrupt */  		out_le32(&(host_pvt.sata_dma_regs)->interrupt_mask.error.low,  			 DMA_ENABLE_CHAN(chan)); @@ -536,7 +576,10 @@ static int map_sg_to_lli(struct scatterlist *sg, int num_elems,  	int fis_len = 0;  	dma_addr_t next_llp;  	int bl; +	int sms_val, dms_val; +	sms_val = 0; +	dms_val = 1 + host_pvt.dma_channel;  	dev_dbg(host_pvt.dwc_dev, "%s: sg=%p nelem=%d lli=%p dma_lli=0x%08x"  		" dmadr=0x%08x\n", __func__, sg, num_elems, lli, (u32)dma_lli,  		(u32)dmadr_addr); @@ -596,8 +639,8 @@ static int map_sg_to_lli(struct scatterlist *sg, int num_elems,  				lli[idx].ctl.low = cpu_to_le32(  					DMA_CTL_TTFC(DMA_CTL_TTFC_P2M_DMAC) | -					DMA_CTL_SMS(0) | -					DMA_CTL_DMS(1) | +					DMA_CTL_SMS(sms_val) | +					DMA_CTL_DMS(dms_val) |  					DMA_CTL_SRC_MSIZE(bl) |  					DMA_CTL_DST_MSIZE(bl) |  					DMA_CTL_SINC_NOCHANGE | @@ -612,8 +655,8 @@ static int map_sg_to_lli(struct scatterlist *sg, int num_elems,  				lli[idx].ctl.low = cpu_to_le32(  					DMA_CTL_TTFC(DMA_CTL_TTFC_M2P_PER) | -					DMA_CTL_SMS(1) | -					DMA_CTL_DMS(0) | +					DMA_CTL_SMS(dms_val) | +					DMA_CTL_DMS(sms_val) |  					DMA_CTL_SRC_MSIZE(bl) |  					DMA_CTL_DST_MSIZE(bl) |  					DMA_CTL_DINC_NOCHANGE | @@ -705,8 +748,10 @@ static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,  	/* Program the CFG register. */  	out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.high), +		 DMA_CFG_HW_HS_SRC(dma_ch) | DMA_CFG_HW_HS_DEST(dma_ch) |  		 DMA_CFG_PROTCTL | DMA_CFG_FCMOD_REQ); -	out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.low), 0); +	out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].cfg.low), +		 DMA_CFG_HW_CH_PRIOR(dma_ch));  	/* Program the address of the linked list */  	out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].llp.low), @@ -715,7 +760,7 @@ static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,  	/* Program the CTL register with src enable / dst enable */  	out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].ctl.low),  		 DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN); -	return 0; +	return dma_ch;  }  /* @@ -727,11 +772,15 @@ static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,  static void dma_dwc_exit(struct sata_dwc_device *hsdev)  {  	dev_dbg(host_pvt.dwc_dev, "%s:\n", __func__); -	if (host_pvt.sata_dma_regs) +	if (host_pvt.sata_dma_regs) {  		iounmap(host_pvt.sata_dma_regs); +		host_pvt.sata_dma_regs = NULL; +	} -	if (hsdev->irq_dma) +	if (hsdev->irq_dma) {  		free_irq(hsdev->irq_dma, hsdev); +		hsdev->irq_dma = 0; +	}  }  /* @@ -967,7 +1016,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)  		}  		dev_dbg(ap->dev, "%s non-NCQ cmd interrupt, protocol: %s\n", -			__func__, ata_get_cmd_descript(qc->tf.protocol)); +			__func__, get_prot_descript(qc->tf.protocol));  DRVSTILLBUSY:  		if (ata_is_dma(qc->tf.protocol)) {  			/* @@ -1057,7 +1106,7 @@ DRVSTILLBUSY:  		/* Process completed command */  		dev_dbg(ap->dev, "%s NCQ command, protocol: %s\n", __func__, -			ata_get_cmd_descript(qc->tf.protocol)); +			get_prot_descript(qc->tf.protocol));  		if (ata_is_dma(qc->tf.protocol)) {  			host_pvt.dma_interrupt_count++;  			if (hsdevp->dma_pending[tag] == \ @@ -1142,8 +1191,8 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status)  	if (tag > 0) {  		dev_info(ap->dev, "%s tag=%u cmd=0x%02x dma dir=%s proto=%s "  			 "dmacr=0x%08x\n", __func__, qc->tag, qc->tf.command, -			 ata_get_cmd_descript(qc->dma_dir), -			 ata_get_cmd_descript(qc->tf.protocol), +			 get_dma_dir_descript(qc->dma_dir), +			 get_prot_descript(qc->tf.protocol),  			 in_le32(&(hsdev->sata_dwc_regs->dmacr)));  	}  #endif @@ -1286,7 +1335,7 @@ static int sata_dwc_port_start(struct ata_port *ap)  			dev_err(ap->dev, "%s: dma_alloc_coherent failed\n",  				 __func__);  			err = -ENOMEM; -			goto CLEANUP; +			goto CLEANUP_ALLOC;  		}  	} @@ -1306,15 +1355,13 @@ static int sata_dwc_port_start(struct ata_port *ap)  	/* Clear any error bits before libata starts issuing commands */  	clear_serror();  	ap->private_data = hsdevp; +	dev_dbg(ap->dev, "%s: done\n", __func__); +	return 0; +CLEANUP_ALLOC: +	kfree(hsdevp);  CLEANUP: -	if (err) { -		sata_dwc_port_stop(ap); -		dev_dbg(ap->dev, "%s: fail\n", __func__); -	} else { -		dev_dbg(ap->dev, "%s: done\n", __func__); -	} - +	dev_dbg(ap->dev, "%s: fail. ap->id = %d\n", __func__, ap->print_id);  	return err;  } @@ -1354,7 +1401,7 @@ static void sata_dwc_exec_command_by_tag(struct ata_port *ap,  	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);  	dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d\n", __func__, tf->command, -		ata_get_cmd_descript(tf), tag); +		ata_get_cmd_descript(tf->command), tag);  	spin_lock_irqsave(&ap->host->lock, flags);  	hsdevp->cmd_issued[tag] = cmd_issued; @@ -1413,7 +1460,7 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag)  	dev_dbg(ap->dev, "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s "  		"start_dma? %x\n", __func__, qc, tag, qc->tf.command, -		ata_get_cmd_descript(qc->dma_dir), start_dma); +		get_dma_dir_descript(qc->dma_dir), start_dma);  	sata_dwc_tf_dump(&(qc->tf));  	if (start_dma) { @@ -1462,10 +1509,9 @@ static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag)  	int dma_chan;  	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);  	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); -	int err;  	dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n", -		__func__, ap->port_no, ata_get_cmd_descript(qc->dma_dir), +		__func__, ap->port_no, get_dma_dir_descript(qc->dma_dir),  		 qc->n_elem);  	dma_chan = dma_dwc_xfer_setup(sg, qc->n_elem, hsdevp->llit[tag], @@ -1474,7 +1520,7 @@ static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag)  				      dmadr), qc->dma_dir);  	if (dma_chan < 0) {  		dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns err %d\n", -			__func__, err); +			__func__, dma_chan);  		return;  	}  	hsdevp->dma_chan[tag] = dma_chan; @@ -1491,8 +1537,8 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)  		dev_info(ap->dev, "%s ap id=%d cmd(0x%02x)=%s qc tag=%d "  			 "prot=%s ap active_tag=0x%08x ap sactive=0x%08x\n",  			 __func__, ap->print_id, qc->tf.command, -			 ata_get_cmd_descript(&qc->tf), -			 qc->tag, ata_get_cmd_descript(qc->tf.protocol), +			 ata_get_cmd_descript(qc->tf.command), +			 qc->tag, get_prot_descript(qc->tf.protocol),  			 ap->link.active_tag, ap->link.sactive);  #endif @@ -1533,7 +1579,7 @@ static void sata_dwc_qc_prep(struct ata_queued_cmd *qc)  #ifdef DEBUG_NCQ  	if (qc->tag > 0)  		dev_info(qc->ap->dev, "%s: qc->tag=%d ap->active_tag=0x%08x\n", -			 __func__, tag, qc->ap->link.active_tag); +			 __func__, qc->tag, qc->ap->link.active_tag);  	return ;  #endif @@ -1541,10 +1587,31 @@ static void sata_dwc_qc_prep(struct ata_queued_cmd *qc)  static void sata_dwc_error_handler(struct ata_port *ap)  { -	ap->link.flags |= ATA_LFLAG_NO_HRST;  	ata_sff_error_handler(ap);  } +int sata_dwc_hardreset(struct ata_link *link, unsigned int *class, +			unsigned long deadline) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(link->ap); +	int ret; + +	ret = sata_sff_hardreset(link, class, deadline); + +	sata_dwc_enable_interrupts(hsdev); + +	/* Reconfigure the DMA control register */ +	out_le32(&hsdev->sata_dwc_regs->dmacr, +		 SATA_DWC_DMACR_TXRXCH_CLEAR); + +	/* Reconfigure the DMA Burst Transaction Size register */ +	out_le32(&hsdev->sata_dwc_regs->dbtsr, +		 SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) | +		 SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)); + +	return ret; +} +  /*   * scsi mid-layer and libata interface structures   */ @@ -1564,6 +1631,7 @@ static struct ata_port_operations sata_dwc_ops = {  	.inherits		= &ata_sff_port_ops,  	.error_handler		= sata_dwc_error_handler, +	.hardreset		= sata_dwc_hardreset,  	.qc_prep		= sata_dwc_qc_prep,  	.qc_issue		= sata_dwc_qc_issue, @@ -1580,16 +1648,14 @@ static struct ata_port_operations sata_dwc_ops = {  static const struct ata_port_info sata_dwc_port_info[] = {  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO | ATA_FLAG_NCQ, -		.pio_mask	= 0x1f,	/* pio 0-4 */ +		.flags		= ATA_FLAG_SATA | ATA_FLAG_NCQ, +		.pio_mask	= ATA_PIO4,  		.udma_mask	= ATA_UDMA6,  		.port_ops	= &sata_dwc_ops,  	},  }; -static int sata_dwc_probe(struct platform_device *ofdev, -			const struct of_device_id *match) +static int sata_dwc_probe(struct platform_device *ofdev)  {  	struct sata_dwc_device *hsdev;  	u32 idr, versionr; @@ -1600,15 +1666,23 @@ static int sata_dwc_probe(struct platform_device *ofdev,  	struct ata_host *host;  	struct ata_port_info pi = sata_dwc_port_info[0];  	const struct ata_port_info *ppi[] = { &pi, NULL }; +	struct device_node *np = ofdev->dev.of_node; +	u32 dma_chan;  	/* Allocate DWC SATA device */ -	hsdev = kmalloc(sizeof(*hsdev), GFP_KERNEL); +	hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL);  	if (hsdev == NULL) {  		dev_err(&ofdev->dev, "kmalloc failed for hsdev\n");  		err = -ENOMEM; -		goto error_out; +		goto error;  	} -	memset(hsdev, 0, sizeof(*hsdev)); + +	if (of_property_read_u32(np, "dma-channel", &dma_chan)) { +		dev_warn(&ofdev->dev, "no dma-channel property set." +			 " Use channel 0\n"); +		dma_chan = 0; +	} +	host_pvt.dma_channel = dma_chan;  	/* Ioremap SATA registers */  	base = of_iomap(ofdev->dev.of_node, 0); @@ -1616,7 +1690,7 @@ static int sata_dwc_probe(struct platform_device *ofdev,  		dev_err(&ofdev->dev, "ioremap failed for SATA register"  			" address\n");  		err = -ENODEV; -		goto error_out; +		goto error_kmalloc;  	}  	hsdev->reg_base = base;  	dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n"); @@ -1629,7 +1703,7 @@ static int sata_dwc_probe(struct platform_device *ofdev,  	if (!host) {  		dev_err(&ofdev->dev, "ata_host_alloc_pinfo failed\n");  		err = -ENOMEM; -		goto error_out; +		goto error_iomap;  	}  	host->private_data = hsdev; @@ -1697,8 +1771,11 @@ error_out:  	/* Free SATA DMA resources */  	dma_dwc_exit(hsdev); -	if (base) -		iounmap(base); +error_iomap: +	iounmap(base); +error_kmalloc: +	kfree(hsdev); +error:  	return err;  } @@ -1727,7 +1804,7 @@ static const struct of_device_id sata_dwc_match[] = {  };  MODULE_DEVICE_TABLE(of, sata_dwc_match); -static struct of_platform_driver sata_dwc_driver = { +static struct platform_driver sata_dwc_driver = {  	.driver = {  		.name = DRV_NAME,  		.owner = THIS_MODULE, @@ -1737,18 +1814,7 @@ static struct of_platform_driver sata_dwc_driver = {  	.remove = sata_dwc_remove,  }; -static int __init sata_dwc_init(void) -{ -	return	of_register_platform_driver(&sata_dwc_driver); -} - -static void __exit sata_dwc_exit(void) -{ -	of_unregister_platform_driver(&sata_dwc_driver); -} - -module_init(sata_dwc_init); -module_exit(sata_dwc_exit); +module_platform_driver(sata_dwc_driver);  MODULE_LICENSE("GPL");  MODULE_AUTHOR("Mark Miesfeld <mmiesfeld@amcc.com>"); diff --git a/drivers/ata/sata_dwc_pmp.c b/drivers/ata/sata_dwc_pmp.c new file mode 100644 index 00000000000..3ff190af8d2 --- /dev/null +++ b/drivers/ata/sata_dwc_pmp.c @@ -0,0 +1,3041 @@ +/* + * drivers/ata/sata_dwc.c + * + * Synopsys DesignWare Cores (DWC) SATA host driver + * + * Author: Mark Miesfeld <mmiesfeld@amcc.com> + * + * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de> + * Copyright 2008 DENX Software Engineering + * + * Based on versions provided by AMCC and Synopsys which are: + *          Copyright 2006 Applied Micro Circuits Corporation + *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED + * + * This program is free software; you can redistribute  it and/or modify it + * under  the terms of  the GNU General  Public License as published by the + * Free Software Foundation;  either version 2 of the  License, or (at your + * option) any later version. + * + */ + + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/libata.h> +#include <linux/rtc.h> + +#include <scsi/scsi_host.h> +#include <scsi/scsi_cmnd.h> + + +#ifdef CONFIG_SATA_DWC_DEBUG +#define dwc_dev_dbg(dev, format, arg...) \ +	({ if (0) dev_printk(KERN_INFO, dev, format, ##arg); 0; }) +#define dwc_port_dbg(ap, format, arg...) \ +	ata_port_printk(ap, KERN_INFO, format, ##arg) +#define dwc_link_dbg(link, format, arg...) \ +	ata_link_printk(link, KERN_INFO, format, ##arg) +#else +#define dwc_dev_dbg(dev, format, arg...) \ +	({ 0; }) +#define dwc_port_dbg(ap, format, arg...) \ +	({ 0; }) +#define dwc_link_dbg(link, format, arg...) \ +	({ 0; }) +#endif + +#ifdef CONFIG_SATA_DWC_VDEBUG +#define DEBUG_NCQ +#define dwc_dev_vdbg(dev, format, arg...) \ +	({ if (0) dev_printk(KERN_INFO, dev, format, ##arg); 0; }) +#define dwc_port_vdbg(ap, format, arg...) \ +	ata_port_printk(ap, KERN_INFO, format, ##arg) +#define dwc_link_vdbg(link, format, arg...) \ +	ata_link_printk(link, KERN_INFO, format, ##arg) +#else +#define dwc_dev_vdbg(dev, format, arg...) \ +	({ 0; }) +#define dwc_port_vdbg(ap, format, arg...) \ +	({ 0; }) +#define dwc_link_vdbg(link, format, arg...) \ +	({ 0; }) +#endif + +#define dwc_dev_info(dev, format, arg...) \ +	({ if (0) dev_printk(KERN_INFO, dev, format, ##arg); 0; }) +#define dwc_port_info(ap, format, arg...) \ +	ata_port_printk(ap, KERN_INFO, format, ##arg) +#define dwc_link_info(link, format, arg...) \ +	ata_link_printk(link, KERN_INFO, format, ##arg) + +/* These two are defined in "libata.h" */ +#undef DRV_NAME +#undef DRV_VERSION +#define DRV_NAME        "sata-dwc" +#define DRV_VERSION     "2.0" + +/* Port Multiplier discovery Signature */ +#define PSCR_SCONTROL_DET_ENABLE	0x00000001 +#define PSCR_SSTATUS_DET_PRESENT	0x00000001 +#define PSCR_SERROR_DIAG_X		0x04000000 + +/* Port multiplier port entry in SCONTROL register */ +#define SCONTROL_PMP_MASK		0x000f0000 +#define PMP_TO_SCONTROL(p)		((p << 16) & 0x000f0000) +#define SCONTROL_TO_PMP(p)		(((p) & 0x000f0000) >> 16) + + +/* SATA DMA driver Globals */ +#if defined(CONFIG_APM821xx) +#define DMA_NUM_CHANS			2 +#else +#define DMA_NUM_CHANS			1 +#endif + +#define DMA_NUM_CHAN_REGS		8 + +/* SATA DMA Register definitions */ +#if defined(CONFIG_APM821xx) +#define AHB_DMA_BRST_DFLT       64  /* 16 data items burst length */ +#else +#define AHB_DMA_BRST_DFLT		64	/* 16 data items burst length */ +#endif + +#if defined(CONFIG_APOLLO3G) +extern void signal_hdd_led(int, int); +#endif +struct dmareg { +	u32 low;		/* Low bits 0-31 */ +	u32 high;		/* High bits 32-63 */ +}; + +/* DMA Per Channel registers */ + +struct dma_chan_regs { +	struct dmareg sar;	/* Source Address */ +	struct dmareg dar;	/* Destination address */ +	struct dmareg llp;	/* Linked List Pointer */ +	struct dmareg ctl;	/* Control */ +	struct dmareg sstat;	/* Source Status not implemented in core */ +	struct dmareg dstat;	/* Destination Status not implemented in core */ +	struct dmareg sstatar;	/* Source Status Address not impl in core */ +	struct dmareg dstatar;	/* Destination Status Address not implemented */ +	struct dmareg cfg;	/* Config */ +	struct dmareg sgr;	/* Source Gather */ +	struct dmareg dsr;	/* Destination Scatter */ +}; + +/* Generic Interrupt Registers */ +struct dma_interrupt_regs { +	struct dmareg tfr;	/* Transfer Interrupt */ +	struct dmareg block;	/* Block Interrupt */ +	struct dmareg srctran;	/* Source Transfer Interrupt */ +	struct dmareg dsttran;	/* Dest Transfer Interrupt */ +	struct dmareg error;	/* Error */ +}; + +struct ahb_dma_regs { +	struct dma_chan_regs	chan_regs[DMA_NUM_CHAN_REGS]; +	struct dma_interrupt_regs interrupt_raw;	/* Raw Interrupt */ +	struct dma_interrupt_regs interrupt_status;	/* Interrupt Status */ +	struct dma_interrupt_regs interrupt_mask;	/* Interrupt Mask */ +	struct dma_interrupt_regs interrupt_clear;	/* Interrupt Clear */ +	struct dmareg		statusInt;		/* Interrupt combined */ +	struct dmareg		rq_srcreg;		/* Src Trans Req */ +	struct dmareg		rq_dstreg;		/* Dst Trans Req */ +	struct dmareg		rq_sgl_srcreg;		/* Sngl Src Trans Req */ +	struct dmareg		rq_sgl_dstreg;		/* Sngl Dst Trans Req */ +	struct dmareg		rq_lst_srcreg;		/* Last Src Trans Req */ +	struct dmareg		rq_lst_dstreg;		/* Last Dst Trans Req */ +	struct dmareg		dma_cfg;		/* DMA Config */ +	struct dmareg		dma_chan_en;		/* DMA Channel Enable */ +	struct dmareg		dma_id;			/* DMA ID */ +	struct dmareg		dma_test;		/* DMA Test */ +	struct dmareg		res1;			/* reserved */ +	struct dmareg		res2;			/* reserved */ + +	/* DMA Comp Params +	 * Param 6 = dma_param[0], Param 5 = dma_param[1], +	 * Param 4 = dma_param[2] ... +	 */ +	struct dmareg		dma_params[6]; +}; + +/* Data structure for linked list item */ +struct lli { +	u32		sar;		/* Source Address */ +	u32		dar;		/* Destination address */ +	u32		llp;		/* Linked List Pointer */ +	struct dmareg	ctl;		/* Control */ +#if defined(CONFIG_APM821xx) +	u32             dstat;          /* Source status is not supported */ +#else +	struct dmareg	dstat;		/* Destination Status */ +#endif +}; + +#define SATA_DWC_DMAC_LLI_SZ		(sizeof(struct lli)) +#define SATA_DWC_DMAC_LLI_NUM		256 +#define SATA_DWC_DMAC_TWIDTH_BYTES	4 +#define SATA_DWC_DMAC_LLI_TBL_SZ	\ +	(SATA_DWC_DMAC_LLI_SZ * SATA_DWC_DMAC_LLI_NUM) +#if defined(CONFIG_APM821xx) +#define SATA_DWC_DMAC_CTRL_TSIZE_MAX    \ +        (0x00000800 * SATA_DWC_DMAC_TWIDTH_BYTES) +#else +#define SATA_DWC_DMAC_CTRL_TSIZE_MAX	\ +	(0x00000800 * SATA_DWC_DMAC_TWIDTH_BYTES) +#endif +/* DMA Register Operation Bits */ +#define DMA_EN              0x00000001		/* Enable AHB DMA */ +#define DMA_CHANNEL(ch)		(0x00000001 << (ch))	/* Select channel */ +#define DMA_ENABLE_CHAN(ch)	((0x00000001 << (ch)) |			\ +				 ((0x000000001 << (ch)) << 8)) +#define DMA_DISABLE_CHAN(ch)	(0x00000000 | ((0x000000001 << (ch)) << 8)) + +/* Channel Control Register */ +#define DMA_CTL_BLK_TS(size)	((size) & 0x000000FFF)	/* Blk Transfer size */ +#define DMA_CTL_LLP_SRCEN	0x10000000	/* Blk chain enable Src */ +#define DMA_CTL_LLP_DSTEN	0x08000000	/* Blk chain enable Dst */ +/* + * This define is used to set block chaining disabled in the control low + * register.  It is already in little endian format so it can be &'d dirctly. + * It is essentially: cpu_to_le32(~(DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN)) + */ +#define DMA_CTL_LLP_DISABLE_LE32 0xffffffe7 +#define DMA_CTL_SMS(num)	((num & 0x3) << 25)	/*Src Master Select*/ +#define DMA_CTL_DMS(num)	((num & 0x3) << 23)	/*Dst Master Select*/ +#define DMA_CTL_TTFC(type)	((type & 0x7) << 20)	/*Type&Flow cntr*/ +#define DMA_CTL_TTFC_P2M_DMAC	0x00000002		/*Per mem,DMAC cntr*/ +#define DMA_CTL_TTFC_M2P_PER	0x00000003		/*Mem per,peri cntr*/ +#define DMA_CTL_SRC_MSIZE(size)	((size & 0x7) << 14)	/*Src Burst Len*/ +#define DMA_CTL_DST_MSIZE(size)	((size & 0x7) << 11)	/*Dst Burst Len*/ +#define DMA_CTL_SINC_INC	0x00000000		/*Src addr incr*/ +#define DMA_CTL_SINC_DEC	0x00000200 +#define DMA_CTL_SINC_NOCHANGE	0x00000400 +#define DMA_CTL_DINC_INC	0x00000000		/*Dst addr incr*/ +#define DMA_CTL_DINC_DEC	0x00000080 +#define DMA_CTL_DINC_NOCHANGE	0x00000100 +#define DMA_CTL_SRC_TRWID(size)	((size & 0x7) << 4)	/*Src Trnsfr Width*/ +#define DMA_CTL_DST_TRWID(size)	((size & 0x7) << 1)	/*Dst Trnsfr Width*/ +#define DMA_CTL_INT_EN		0x00000001		/*Interrupt Enable*/ + +/* Channel Configuration Register high bits */ +#define DMA_CFG_FCMOD_REQ	0x00000001		/*Flow cntrl req*/ +#define DMA_CFG_PROTCTL		(0x00000003 << 2)	/*Protection cntrl*/ + +/* Channel Configuration Register low bits */ +#define DMA_CFG_RELD_DST	0x80000000		/*Reload Dst/Src Addr*/ +#define DMA_CFG_RELD_SRC	0x40000000 +#define DMA_CFG_HS_SELSRC	0x00000800		/*SW hndshk Src/Dst*/ +#define DMA_CFG_HS_SELDST	0x00000400 +#define DMA_CFG_FIFOEMPTY       (0x00000001 << 9)	/*FIFO Empty bit*/ + +/* Assign hardware handshaking interface (x) to dst / sre peripheral */ +#define DMA_CFG_HW_HS_DEST(int_num)	((int_num & 0xF) << 11) +#define DMA_CFG_HW_HS_SRC(int_num)	((int_num & 0xF) << 7) + +/* Channel Linked List Pointer Register */ +#define DMA_LLP_LMS(addr, master)	(((addr) & 0xfffffffc) | (master)) +#define DMA_LLP_AHBMASTER1		0	/* List Master Select */ +#define DMA_LLP_AHBMASTER2		1 + +#define SATA_DWC_MAX_PORTS	1 + +#define SATA_DWC_SCR_OFFSET	0x24 +#define SATA_DWC_REG_OFFSET	0x64 + +/* DWC SATA Registers */ +struct sata_dwc_regs { +	u32 fptagr;		/* 1st party DMA tag */ +	u32 fpbor;		/* 1st party DMA buffer offset */ +	u32 fptcr;		/* 1st party DMA Xfr count */ +	u32 dmacr;		/* DMA Control */ +	u32 dbtsr;		/* DMA Burst Transac size */ +	u32 intpr;		/* Interrupt Pending */ +	u32 intmr;		/* Interrupt Mask */ +	u32 errmr;		/* Error Mask */ +	u32 llcr;		/* Link Layer Control */ +	u32 phycr;		/* PHY Control */ +	u32 physr;		/* PHY Status */ +	u32 rxbistpd;		/* Recvd BIST pattern def register */ +	u32 rxbistpd1;		/* Recvd BIST data dword1 */ +	u32 rxbistpd2;		/* Recvd BIST pattern data dword2 */ +	u32 txbistpd;		/* Trans BIST pattern def register */ +	u32 txbistpd1;		/* Trans BIST data dword1 */ +	u32 txbistpd2;		/* Trans BIST data dword2 */ +	u32 bistcr;		/* BIST Control Register */ +	u32 bistfctr;		/* BIST FIS Count Register */ +	u32 bistsr;		/* BIST Status Register */ +	u32 bistdecr;		/* BIST Dword Error count register */ +	u32 res[15];		/* Reserved locations */ +	u32 testr;		/* Test Register */ +	u32 versionr;		/* Version Register */ +	u32 idr;		/* ID Register */ +	u32 unimpl[192];	/* Unimplemented */ +	u32 dmadr[256];	/* FIFO Locations in DMA Mode */ +}; + +#define SCR_SCONTROL_DET_ENABLE		0x00000001 +#define SCR_SSTATUS_DET_PRESENT		0x00000001 +#define SCR_SERROR_DIAG_X		0x04000000 + +/* DWC SATA Register Operations */ +#define	SATA_DWC_TXFIFO_DEPTH		0x01FF +#define	SATA_DWC_RXFIFO_DEPTH		0x01FF + +#define SATA_DWC_DMACR_TMOD_TXCHEN	0x00000004 +#define	SATA_DWC_DMACR_TXCHEN		(0x00000001 | \ +						SATA_DWC_DMACR_TMOD_TXCHEN) +#define	SATA_DWC_DMACR_RXCHEN		(0x00000002 | \ +						SATA_DWC_DMACR_TMOD_TXCHEN) +#define SATA_DWC_DMACR_TX_CLEAR(v)	(((v) & ~SATA_DWC_DMACR_TXCHEN) | \ +						SATA_DWC_DMACR_TMOD_TXCHEN) +#define SATA_DWC_DMACR_RX_CLEAR(v)	(((v) & ~SATA_DWC_DMACR_RXCHEN) | \ +						SATA_DWC_DMACR_TMOD_TXCHEN) +#define SATA_DWC_DMACR_TXRXCH_CLEAR	SATA_DWC_DMACR_TMOD_TXCHEN + +#define SATA_DWC_DBTSR_MWR(size)	((size/4) & \ +						SATA_DWC_TXFIFO_DEPTH) +#define SATA_DWC_DBTSR_MRD(size)	(((size/4) & \ +						SATA_DWC_RXFIFO_DEPTH) << 16) + +// SATA DWC Interrupts +#define	SATA_DWC_INTPR_DMAT			0x00000001 +#define SATA_DWC_INTPR_NEWFP		0x00000002 +#define SATA_DWC_INTPR_PMABRT		0x00000004 +#define SATA_DWC_INTPR_ERR			0x00000008 +#define SATA_DWC_INTPR_NEWBIST		0x00000010 +#define SATA_DWC_INTPR_IPF			0x80000000 +// Interrupt masks +#define	SATA_DWC_INTMR_DMATM		0x00000001 +#define SATA_DWC_INTMR_NEWFPM		0x00000002 +#define SATA_DWC_INTMR_PMABRTM		0x00000004 +#define SATA_DWC_INTMR_ERRM			0x00000008 +#define SATA_DWC_INTMR_NEWBISTM		0x00000010 +#define SATA_DWC_INTMR_PRIMERRM		0x00000020 +#define SATA_DWC_INTPR_CMDGOOD		0x00000080 +#define SATA_DWC_INTPR_CMDABORT		0x00000040 + +#define SATA_DWC_LLCR_SCRAMEN		0x00000001 +#define SATA_DWC_LLCR_DESCRAMEN		0x00000002 +#define SATA_DWC_LLCR_RPDEN			0x00000004 + +// Defines for SError register +#define SATA_DWC_SERR_ERRI      0x00000001 // Recovered data integrity error +#define SATA_DWC_SERR_ERRM      0x00000002 // Recovered communication error +#define SATA_DWC_SERR_ERRT      0x00000100 // Non-recovered transient data integrity error +#define SATA_DWC_SERR_ERRC      0x00000200 // Non-recovered persistent communication or data integrity error +#define SATA_DWC_SERR_ERRP      0x00000400 // Protocol error +#define SATA_DWC_SERR_ERRE      0x00000800 // Internal host adapter error +#define SATA_DWC_SERR_DIAGN     0x00010000 // PHYRdy change +#define SATA_DWC_SERR_DIAGI     0x00020000 // PHY internal error +#define SATA_DWC_SERR_DIAGW     0x00040000 // Phy COMWAKE signal is detected +#define SATA_DWC_SERR_DIAGB     0x00080000 // 10b to 8b decoder err +#define SATA_DWC_SERR_DIAGT     0x00100000 // Disparity error +#define SATA_DWC_SERR_DIAGC		0x00200000 // CRC error +#define SATA_DWC_SERR_DIAGH		0x00400000 // Handshake error +#define SATA_DWC_SERR_DIAGL		0x00800000 // Link sequence (illegal transition) error +#define SATA_DWC_SERR_DIAGS		0x01000000 // Transport state transition error +#define SATA_DWC_SERR_DIAGF		0x02000000 // Unrecognized FIS type +#define SATA_DWC_SERR_DIAGX		0x04000000 // Exchanged error - Set when PHY COMINIT signal is detected. +#define SATA_DWC_SERR_DIAGA		0x08000000 // Port Selector Presence detected + +/* This is all error bits, zero's are reserved fields. */ +#define SATA_DWC_SERR_ERR_BITS	0x0FFF0F03 + +#define SATA_DWC_SCR0_SPD_GET(v)	((v >> 4) & 0x0000000F) + +struct sata_dwc_device { +	struct resource reg;            /* Resource for register */ +	struct device		*dev;		/* generic device struct */ +	struct ata_probe_ent	*pe;		/* ptr to probe-ent */ +	struct ata_host		*host; +	u8			*reg_base; +	struct sata_dwc_regs	*sata_dwc_regs;	/* DW Synopsys SATA specific */ +	u8     			*scr_base; +	int    			dma_channel;	/* DWC SATA DMA channel  */ +	int			irq_dma; +	struct timer_list an_timer; +}; + +#define SATA_DWC_QCMD_MAX	32 + +struct sata_dwc_device_port { +	struct sata_dwc_device	*hsdev; +	int			cmd_issued[SATA_DWC_QCMD_MAX]; +	struct lli		*llit[SATA_DWC_QCMD_MAX]; +	dma_addr_t		llit_dma[SATA_DWC_QCMD_MAX]; +	u32			dma_chan[SATA_DWC_QCMD_MAX]; +	int			dma_pending[SATA_DWC_QCMD_MAX]; +	u32 			sata_dwc_sactive_issued;	/* issued queued ops */ +	u32 			sata_dwc_sactive_queued;	/* queued ops */ +	u32 			dma_interrupt_count; + +}; + +static struct sata_dwc_device* dwc_dev_list[2]; +static int dma_intr_registered = 0; +/* + * Commonly used DWC SATA driver Macros + */ +#define HSDEV_FROM_HOST(host)	((struct sata_dwc_device *) \ +					(host)->private_data) +#define HSDEV_FROM_AP(ap)	((struct sata_dwc_device *) \ +					(ap)->host->private_data) +#define HSDEVP_FROM_AP(ap)	((struct sata_dwc_device_port *) \ +					(ap)->private_data) +#define HSDEV_FROM_QC(qc)	((struct sata_dwc_device *) \ +					(qc)->ap->host->private_data) +#define HSDEV_FROM_HSDEVP(p)	((struct sata_dwc_device *) \ +					(hsdevp)->hsdev) + +enum { +	SATA_DWC_CMD_ISSUED_NOT		= 0, +	SATA_DWC_CMD_ISSUED_PENDING	= 1, +	SATA_DWC_CMD_ISSUED_EXEC	= 2, +	SATA_DWC_CMD_ISSUED_NODATA	= 3, + +	SATA_DWC_DMA_PENDING_NONE	= 0, +	SATA_DWC_DMA_PENDING_TX		= 1, +	SATA_DWC_DMA_PENDING_RX		= 2, +}; + +/* + * Globals + */ +static struct ahb_dma_regs *sata_dma_regs = 0; + +/* + * Prototypes + */ +static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag); +static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc, +				u32 check_status); +static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status); +static void sata_dwc_port_stop(struct ata_port *ap); +static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag); + +static int dma_dwc_init(struct sata_dwc_device *hsdev); +static void dma_dwc_exit(struct sata_dwc_device *hsdev); +static int dma_dwc_xfer_setup(struct ata_queued_cmd *qc, +			      struct lli *lli, dma_addr_t dma_lli, +			      void __iomem *addr); +static void dma_dwc_xfer_start(int dma_ch); +static void dma_dwc_terminate_dma(struct ata_port *ap, int dma_ch); +static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev); +static void sata_dwc_init_port ( struct ata_port *ap ); +u8 sata_dwc_check_status(struct ata_port *ap); + + + + +static const char *dir_2_txt(enum dma_data_direction dir) +{ +	switch (dir) { +	case DMA_BIDIRECTIONAL: +		return "bi"; +	case DMA_FROM_DEVICE: +		return "from"; +	case DMA_TO_DEVICE: +		return "to"; +	case DMA_NONE: +		return "none"; +	default: +		return "err"; +	} +} + +static const char *prot_2_txt(enum ata_tf_protocols protocol) +{ +	switch (protocol) { +	case ATA_PROT_UNKNOWN: +		return "unknown"; +	case ATA_PROT_NODATA: +		return "nodata"; +	case ATA_PROT_PIO: +		return "pio"; +	case ATA_PROT_DMA: +		return "dma"; +	case ATA_PROT_NCQ: +		return "ncq"; +	case ATAPI_PROT_PIO: +		return "atapi pio"; +	case ATAPI_PROT_NODATA: +		return "atapi nodata"; +	case ATAPI_PROT_DMA: +		return "atapi dma"; +	default: +		return "err"; +	} +} + +inline const char *ata_cmd_2_txt(const struct ata_taskfile *tf) +{ +	switch (tf->command) { +	case ATA_CMD_CHK_POWER: +		return "ATA_CMD_CHK_POWER"; +	case ATA_CMD_EDD: +		return "ATA_CMD_EDD"; +	case ATA_CMD_FLUSH: +		return "ATA_CMD_FLUSH"; +	case ATA_CMD_FLUSH_EXT: +		return "ATA_CMD_FLUSH_EXT"; +	case ATA_CMD_ID_ATA: +		return "ATA_CMD_ID_ATA"; +	case ATA_CMD_ID_ATAPI: +		return "ATA_CMD_ID_ATAPI"; +	case ATA_CMD_FPDMA_READ: +		return "ATA_CMD_FPDMA_READ"; +	case ATA_CMD_FPDMA_WRITE: +		return "ATA_CMD_FPDMA_WRITE"; +	case ATA_CMD_READ: +		return "ATA_CMD_READ"; +	case ATA_CMD_READ_EXT: +		return "ATA_CMD_READ_EXT"; +	case ATA_CMD_READ_NATIVE_MAX_EXT : +		return "ATA_CMD_READ_NATIVE_MAX_EXT"; +	case ATA_CMD_VERIFY_EXT : +		return "ATA_CMD_VERIFY_EXT"; +	case ATA_CMD_WRITE: +		return "ATA_CMD_WRITE"; +	case ATA_CMD_WRITE_EXT: +		return "ATA_CMD_WRITE_EXT"; +	case ATA_CMD_PIO_READ: +		return "ATA_CMD_PIO_READ"; +	case ATA_CMD_PIO_READ_EXT: +		return "ATA_CMD_PIO_READ_EXT"; +	case ATA_CMD_PIO_WRITE: +		return "ATA_CMD_PIO_WRITE"; +	case ATA_CMD_PIO_WRITE_EXT: +		return "ATA_CMD_PIO_WRITE_EXT"; +	case ATA_CMD_SET_FEATURES: +		return "ATA_CMD_SET_FEATURES"; +	case ATA_CMD_PACKET: +		return "ATA_CMD_PACKET"; +	case ATA_CMD_PMP_READ: +		return "ATA_CMD_PMP_READ"; +	case ATA_CMD_PMP_WRITE: +		return "ATA_CMD_PMP_WRITE"; +	default: +		return "ATA_CMD_???"; +	} +} + +/*  + * Dump content of the taskfile + */ +static void sata_dwc_tf_dump(struct device *dwc_dev, struct ata_taskfile *tf) +{ +	dwc_dev_vdbg(dwc_dev, "taskfile cmd: 0x%02x protocol: %s flags: 0x%lx" +			"device: %x\n", tf->command, prot_2_txt(tf->protocol), +			tf->flags, tf->device); +	dwc_dev_vdbg(dwc_dev, "feature: 0x%02x nsect: 0x%x lbal: 0x%x lbam:" +			"0x%x lbah: 0x%x\n", tf->feature, tf->nsect, tf->lbal, +			tf->lbam, tf->lbah); +	dwc_dev_vdbg(dwc_dev, "hob_feature: 0x%02x hob_nsect: 0x%x hob_lbal: 0x%x " +			"hob_lbam: 0x%x hob_lbah: 0x%x\n", tf->hob_feature, +			tf->hob_nsect, tf->hob_lbal, tf->hob_lbam, +			tf->hob_lbah); +} + +/* + * Function: get_burst_length_encode + * arguments: datalength: length in bytes of data + * returns value to be programmed in register corresponding to data length + * This value is effectively the log(base 2) of the length + */ +static inline int get_burst_length_encode(int datalength) +{ +	int items = datalength >> 2;	/* div by 4 to get lword count */ + +	if (items >= 64) +		return 5; + +	if (items >= 32) +		return 4; + +	if (items >= 16) +		return 3; + +	if (items >= 8) +		return 2; + +	if (items >= 4) +		return 1; + +	return 0; +} + +/* + * Clear Interrupts on a DMA channel + */ +static inline void clear_chan_interrupts(int c) +{ +	out_le32(&(sata_dma_regs->interrupt_clear.tfr.low), DMA_CHANNEL(c)); +	out_le32(&(sata_dma_regs->interrupt_clear.block.low), DMA_CHANNEL(c)); +	out_le32(&(sata_dma_regs->interrupt_clear.srctran.low), DMA_CHANNEL(c)); +	out_le32(&(sata_dma_regs->interrupt_clear.dsttran.low), DMA_CHANNEL(c)); +	out_le32(&(sata_dma_regs->interrupt_clear.error.low), DMA_CHANNEL(c)); +} + +/* + * Function: dma_request_channel + * arguments: None + * returns channel number if available else -1 + * This function assigns the next available DMA channel from the list to the + * requester + */ +static int dma_request_channel(struct ata_port *ap) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); + +	if (!(in_le32(&(sata_dma_regs->dma_chan_en.low)) & DMA_CHANNEL(hsdev->dma_channel))) { +		dwc_port_vdbg(ap, "%s Successfully requested DMA channel %d\n",  +				__func__, hsdev->dma_channel); +		return (hsdev->dma_channel); +	} +	 +	return -1; +} + + + +/* + * Function: dma_dwc_interrupt + * arguments: irq, dev_id, pt_regs + * returns channel number if available else -1 + * Interrupt Handler for DW AHB SATA DMA + */ +static int dma_dwc_interrupt(int irq, void *hsdev_instance) +{ +	volatile u32 tfr_reg, err_reg; +	unsigned long flags; +	struct sata_dwc_device *hsdev = hsdev_instance; +	struct ata_host *host = (struct ata_host *)hsdev->host; +	struct ata_port *ap; +	struct sata_dwc_device_port *hsdevp; +	u8 tag = 0; +	int chan; +	unsigned int port = 0; +	spin_lock_irqsave(&host->lock, flags); + +	ap = host->ports[port]; +	hsdevp = HSDEVP_FROM_AP(ap); +	tag = ap->link.active_tag; + +	dwc_port_vdbg(ap, "%s: DMA interrupt in channel %d\n", __func__, hsdev->dma_channel); + +	tfr_reg = in_le32(&(sata_dma_regs->interrupt_status.tfr.low)); +	err_reg = in_le32(&(sata_dma_regs->interrupt_status.error.low)); + +	dwc_port_vdbg(ap, "eot=0x%08x err=0x%08x pending=%d active port=%d\n", +		tfr_reg, err_reg, hsdevp->dma_pending[tag], port); +	chan = hsdev->dma_channel;				 +	 +	if (tfr_reg & DMA_CHANNEL(chan)) { +		/* +		 *Each DMA command produces 2 interrupts.  Only +		 * complete the command after both interrupts have been +		 * seen. (See sata_dwc_isr()) +		 */ +		hsdevp->dma_interrupt_count++; +		sata_dwc_clear_dmacr(hsdevp, tag); + +		if (unlikely(hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE)) { +			dev_err(ap->dev, "DMA not pending eot=0x%08x " +				"err=0x%08x tag=0x%02x pending=%d\n", +				tfr_reg, err_reg, tag, +				hsdevp->dma_pending[tag]); +		} + +		// Do remain jobs after DMA transfer complete +		if ((hsdevp->dma_interrupt_count % 2) == 0) +			sata_dwc_dma_xfer_complete(ap, 1); + +		/* Clear the interrupt */ +		out_le32(&(sata_dma_regs->interrupt_clear.tfr.low), +			  DMA_CHANNEL(chan)); +	} + +	/* Process error interrupt. */ +	// We do not expect error happen +	if (unlikely(err_reg & DMA_CHANNEL(chan))) { +		/* TODO Need error handler ! */ +		dev_err(ap->dev, "error interrupt err_reg=0x%08x\n", +				err_reg); + +		spin_lock_irqsave(ap->lock, flags); +		//if (ata_is_dma(qc->tf.protocol)) { +			/* disable DMAC */ +			dma_dwc_terminate_dma(ap, chan); +		//} +		spin_unlock_irqrestore(ap->lock, flags); + +		/* Clear the interrupt. */ +		out_le32(&(sata_dma_regs->interrupt_clear.error.low), +			  DMA_CHANNEL(chan)); +	} + +	spin_unlock_irqrestore(&host->lock, flags); +	return IRQ_HANDLED; +} + +static irqreturn_t dma_dwc_handler(int irq, void *hsdev_instance) +{ +	volatile u32 tfr_reg, err_reg; +	int chan; + +	tfr_reg = in_le32(&(sata_dma_regs->interrupt_status.tfr.low));	 +	err_reg = in_le32(&(sata_dma_regs->interrupt_status.error.low)); + +	for (chan = 0; chan < DMA_NUM_CHANS; chan++) { +		/* Check for end-of-transfer interrupt. */ + +		if (tfr_reg & DMA_CHANNEL(chan)) { +			dma_dwc_interrupt(0, dwc_dev_list[chan]);		 +		} +		else + +		/* Check for error interrupt. */ +		if (err_reg & DMA_CHANNEL(chan)) { +			dma_dwc_interrupt(0, dwc_dev_list[chan]); +		} +	} + +	return IRQ_HANDLED; +} + +static int dma_register_interrupt (struct sata_dwc_device *hsdev) +{ +	int retval = 0; +	int irq = hsdev->irq_dma; +	/*  +	 * FIXME: 2 SATA controllers share the same DMA engine so +	 * currently, they also share same DMA interrupt +	 */ +	if (!dma_intr_registered) { +		printk("%s register irq (%d)\n", __func__, irq); +		retval = request_irq(irq, dma_dwc_handler, IRQF_SHARED, "SATA DMA", hsdev); +		//retval = request_irq(irq, dma_dwc_handler, IRQF_DISABLED, "SATA DMA", NULL); +		if (retval) { +			dev_err(hsdev->dev, "%s: could not get IRQ %d\n", __func__, irq); +			return -ENODEV; +		} +		//dma_intr_registered = 1; +	} +	return retval; +} + +/* + * Function: dma_request_interrupts + * arguments: hsdev + * returns status + * This function registers ISR for a particular DMA channel interrupt + */ +static int dma_request_interrupts(struct sata_dwc_device *hsdev, int irq) +{ +	int retval = 0; +	int dma_chan = hsdev->dma_channel; + +	/* Unmask error interrupt */ +	out_le32(&sata_dma_regs->interrupt_mask.error.low, +			 in_le32(&sata_dma_regs->interrupt_mask.error.low) | DMA_ENABLE_CHAN(dma_chan)); + +	/* Unmask end-of-transfer interrupt */ +	out_le32(&sata_dma_regs->interrupt_mask.tfr.low, +			in_le32(&sata_dma_regs->interrupt_mask.tfr.low) | DMA_ENABLE_CHAN(dma_chan)); + +	dwc_dev_vdbg(hsdev->dev, "Current value of interrupt_mask.error=0x%0x\n", in_le32(&sata_dma_regs->interrupt_mask.error.low)); +	dwc_dev_vdbg(hsdev->dev, "Current value of interrupt_mask.tfr=0x%0x\n", in_le32(&sata_dma_regs->interrupt_mask.tfr.low)); +#if 0 +	out_le32(&sata_dma_regs->interrupt_mask.block.low, +			DMA_ENABLE_CHAN(dma_chan)); + +	out_le32(&sata_dma_regs->interrupt_mask.srctran.low, +			DMA_ENABLE_CHAN(dma_chan)); + +	out_le32(&sata_dma_regs->interrupt_mask.dsttran.low, +			DMA_ENABLE_CHAN(dma_chan)); +#endif +	return retval; +} + +/* + * Function: map_sg_to_lli + * arguments: sg: scatter/gather list(sg) + *	      num_elems: no of elements in sg list + *	      dma_lli: LLI table + *	      dest: destination address + *	      read: whether the transfer is read or write + * returns array of AHB DMA Linked List Items + * This function creates a list of LLIs for DMA Xfr and returns the number + * of elements in the DMA linked list. + * + * Note that the Synopsis driver has a comment proposing that better performance + * is possible by only enabling interrupts on the last item in the linked list. + * However, it seems that could be a problem if an error happened on one of the + * first items.  The transfer would halt, but no error interrupt would occur. + * + * Currently this function sets interrupts enabled for each linked list item: + * DMA_CTL_INT_EN. + */ +static int map_sg_to_lli(struct ata_queued_cmd *qc, struct lli *lli, +			 dma_addr_t dma_lli, void __iomem *dmadr_addr) +{ +	struct scatterlist *sg = qc->sg; +	struct device *dwc_dev = qc->ap->dev; +	int num_elems = qc->n_elem; +	int dir = qc->dma_dir; +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(qc->ap); +	 +	int i, idx = 0; +	int fis_len = 0; +	dma_addr_t next_llp; +	int bl; +	unsigned int dma_ts = 0; + +	dwc_port_vdbg(qc->ap, "%s: sg=%p nelem=%d lli=%p dma_lli=0x%08x " +		"dmadr=0x%08x\n", __func__, sg, num_elems, lli, (u32)dma_lli, +		(u32)dmadr_addr); + +	bl = get_burst_length_encode(AHB_DMA_BRST_DFLT); + +	for (i = 0; i < num_elems; i++, sg++) { +		u32 addr, offset; +		u32 sg_len, len; + +		addr = (u32) sg_dma_address(sg); +		sg_len = sg_dma_len(sg); + +		dwc_port_vdbg(qc->ap, "%s: elem=%d sg_addr=0x%x sg_len=%d\n", +			__func__, i, addr, sg_len); + +		while (sg_len) { + +			if (unlikely(idx >= SATA_DWC_DMAC_LLI_NUM)) { +				/* The LLI table is not large enough. */ +				dev_err(dwc_dev, "LLI table overrun (idx=%d)\n", +						idx); +				break; +			} +			len = (sg_len > SATA_DWC_DMAC_CTRL_TSIZE_MAX) ? +				SATA_DWC_DMAC_CTRL_TSIZE_MAX : sg_len; + +			offset = addr & 0xffff; +			if ((offset + sg_len) > 0x10000) +				len = 0x10000 - offset; + +			/* +			 * Make sure a LLI block is not created that will span a +			 * 8K max FIS boundary.  If the block spans such a FIS +			 * boundary, there is a chance that a DMA burst will +			 * cross that boundary -- this results in an error in +			 * the host controller. +			 */ +			if (unlikely(fis_len + len > 8192)) { +				dwc_port_vdbg(qc->ap, "SPLITTING: fis_len=%d(0x%x) " +					"len=%d(0x%x)\n", fis_len, fis_len, +					len, len); +				len = 8192 - fis_len; +				fis_len = 0; +			} else { +				fis_len += len; +			} +			if (fis_len == 8192) +				fis_len = 0; + +			/* +			 * Set DMA addresses and lower half of control register +			 * based on direction. +			 */ +			dwc_port_vdbg(qc->ap, "%s: sg_len = %d, len = %d\n", __func__, sg_len, len); + +#if defined(CONFIG_APM821xx) +			 if (dir == DMA_FROM_DEVICE) { +                                lli[idx].dar = cpu_to_le32(addr); +                                lli[idx].sar = cpu_to_le32((u32)dmadr_addr); +				if (hsdevp->hsdev->dma_channel == 0) {/* DMA channel 0 */ +		                        lli[idx].ctl.low = cpu_to_le32( +                                        DMA_CTL_TTFC(DMA_CTL_TTFC_P2M_DMAC) | +                                        DMA_CTL_SMS(1) |	/* Source: Master 2 */ +                                        DMA_CTL_DMS(0) |	/* Dest: Master 1 */ +                                        DMA_CTL_SRC_MSIZE(bl) | +                                        DMA_CTL_DST_MSIZE(bl) | +                                        DMA_CTL_SINC_NOCHANGE | +                                        DMA_CTL_SRC_TRWID(2) | +                                        DMA_CTL_DST_TRWID(2) | +                                        DMA_CTL_INT_EN | +                                        DMA_CTL_LLP_SRCEN | +                                        DMA_CTL_LLP_DSTEN); +				} else if (hsdevp->hsdev->dma_channel == 1) {/* DMA channel 1 */ +					lli[idx].ctl.low = cpu_to_le32( +                                        DMA_CTL_TTFC(DMA_CTL_TTFC_P2M_DMAC) | +                                        DMA_CTL_SMS(2) |	/* Source: Master 3 */ +                                        DMA_CTL_DMS(0) |	/* Dest: Master 1 */ +                                        DMA_CTL_SRC_MSIZE(bl) | +                                        DMA_CTL_DST_MSIZE(bl) | +                                        DMA_CTL_SINC_NOCHANGE | +                                        DMA_CTL_SRC_TRWID(2) | +                                        DMA_CTL_DST_TRWID(2) | +                                        DMA_CTL_INT_EN | +                                        DMA_CTL_LLP_SRCEN | +                                        DMA_CTL_LLP_DSTEN); +				} +                        } else {        /* DMA_TO_DEVICE */ +                                lli[idx].sar = cpu_to_le32(addr); +                                lli[idx].dar = cpu_to_le32((u32)dmadr_addr); +				if (hsdevp->hsdev->dma_channel == 0) {/* DMA channel 0 */ +	                                lli[idx].ctl.low = cpu_to_le32( +                                        DMA_CTL_TTFC(DMA_CTL_TTFC_M2P_PER) | +                                        DMA_CTL_SMS(0) | +                                        DMA_CTL_DMS(1) | +                                        DMA_CTL_SRC_MSIZE(bl) | +                                        DMA_CTL_DST_MSIZE(bl) | +                                        DMA_CTL_DINC_NOCHANGE | +                                        DMA_CTL_SRC_TRWID(2) | +                                        DMA_CTL_DST_TRWID(2) | +                                        DMA_CTL_INT_EN | +                                        DMA_CTL_LLP_SRCEN | +                                        DMA_CTL_LLP_DSTEN); +				} else if (hsdevp->hsdev->dma_channel == 1) {/* DMA channel 1 */ +	                                lli[idx].ctl.low = cpu_to_le32( +                                        DMA_CTL_TTFC(DMA_CTL_TTFC_M2P_PER) | +                                        DMA_CTL_SMS(0) | +                                        DMA_CTL_DMS(2) | +                                        DMA_CTL_SRC_MSIZE(bl) | +                                        DMA_CTL_DST_MSIZE(bl) | +                                        DMA_CTL_DINC_NOCHANGE | +                                        DMA_CTL_SRC_TRWID(2) | +                                        DMA_CTL_DST_TRWID(2) | +                                        DMA_CTL_INT_EN | +                                        DMA_CTL_LLP_SRCEN | +                                        DMA_CTL_LLP_DSTEN); +				} +                        } +#else +			if (dir == DMA_FROM_DEVICE) { +				lli[idx].dar = cpu_to_le32(addr); +				lli[idx].sar = cpu_to_le32((u32)dmadr_addr); + +				lli[idx].ctl.low = cpu_to_le32( +					DMA_CTL_TTFC(DMA_CTL_TTFC_P2M_DMAC) | +					DMA_CTL_SMS(0) | +					DMA_CTL_DMS(1) | +					DMA_CTL_SRC_MSIZE(bl) | +					DMA_CTL_DST_MSIZE(bl) | +					DMA_CTL_SINC_NOCHANGE | +					DMA_CTL_SRC_TRWID(2) | +					DMA_CTL_DST_TRWID(2) | +					DMA_CTL_INT_EN | +					DMA_CTL_LLP_SRCEN | +					DMA_CTL_LLP_DSTEN); +			} else {	/* DMA_TO_DEVICE */ +				lli[idx].sar = cpu_to_le32(addr); +				lli[idx].dar = cpu_to_le32((u32)dmadr_addr); + +				lli[idx].ctl.low = cpu_to_le32( +					DMA_CTL_TTFC(DMA_CTL_TTFC_M2P_PER) | +					DMA_CTL_SMS(1) | +					DMA_CTL_DMS(0) | +					DMA_CTL_SRC_MSIZE(bl) | +					DMA_CTL_DST_MSIZE(bl) | +					DMA_CTL_DINC_NOCHANGE | +					DMA_CTL_SRC_TRWID(2) | +					DMA_CTL_DST_TRWID(2) | +					DMA_CTL_INT_EN | +					DMA_CTL_LLP_SRCEN | +					DMA_CTL_LLP_DSTEN); +			} +#endif +			dwc_port_vdbg(qc->ap, "%s setting ctl.high len: 0x%08x val: " +					"0x%08x\n", __func__, len, +					DMA_CTL_BLK_TS(len / 4)); + +			/* Program the LLI CTL high register */ +			dma_ts = DMA_CTL_BLK_TS(len / 4); +			lli[idx].ctl.high = cpu_to_le32(dma_ts); + +			/* +			 *Program the next pointer.  The next pointer must be +			 * the physical address, not the virtual address. +			 */ +			next_llp = (dma_lli + ((idx + 1) * sizeof(struct lli))); + +			/* The last 2 bits encode the list master select. */ +#if defined(CONFIG_APM821xx) +			next_llp = DMA_LLP_LMS(next_llp, DMA_LLP_AHBMASTER1); +#else +			next_llp = DMA_LLP_LMS(next_llp, DMA_LLP_AHBMASTER2); +#endif + +			lli[idx].llp = cpu_to_le32(next_llp); + +			dwc_port_vdbg(qc->ap, "%s: index %d\n", __func__, idx); +			dwc_port_vdbg(qc->ap, "%s setting ctl.high with val: 0x%08x\n", __func__, lli[idx].ctl.high); +			dwc_port_vdbg(qc->ap, "%s setting ctl.low with val: 0x%08x\n", __func__, lli[idx].ctl.low); +			dwc_port_vdbg(qc->ap, "%s setting lli.dar with val: 0x%08x\n", __func__, lli[idx].dar); +			dwc_port_vdbg(qc->ap, "%s setting lli.sar with val: 0x%08x\n", __func__, lli[idx].sar); +			dwc_port_vdbg(qc->ap, "%s setting next_llp with val: 0x%08x\n", __func__, lli[idx].llp); + +			idx++; +			sg_len -= len; +			addr += len; +		} +	} + +	/* +	 * The last next ptr has to be zero and the last control low register +	 * has to have LLP_SRC_EN and LLP_DST_EN (linked list pointer source +	 * and destination enable) set back to 0 (disabled.)  This is what tells +	 * the core that this is the last item in the linked list. +	 */ +	if (likely(idx)) { +		lli[idx-1].llp = 0x00000000; +		lli[idx-1].ctl.low &= DMA_CTL_LLP_DISABLE_LE32; + +		/* Flush cache to memory */ +		dma_cache_sync(NULL, lli, (sizeof(struct lli) * idx), +			       DMA_BIDIRECTIONAL); +	} + +	dwc_port_vdbg(qc->ap, "%s: Final index %d\n", __func__, idx-1); +	dwc_port_vdbg(qc->ap, "%s setting ctl.high with val: 0x%08x\n", __func__, lli[idx-1].ctl.high); +	dwc_port_vdbg(qc->ap, "%s setting ctl.low with val: 0x%08x\n", __func__, lli[idx-1].ctl.low); +	dwc_port_vdbg(qc->ap, "%s setting lli.dar with val: 0x%08x\n", __func__, lli[idx-1].dar); +	dwc_port_vdbg(qc->ap, "%s setting lli.sar with val: 0x%08x\n", __func__, lli[idx-1].sar); +	dwc_port_vdbg(qc->ap, "%s setting next_llp with val: 0x%08x\n", __func__, lli[idx-1].llp); + +	return idx; +} + +/* + * Function: dma_dwc_xfer_start + * arguments: Channel number + * Return : None + * Enables the DMA channel + */ +static void dma_dwc_xfer_start(int dma_ch) +{ +	/* Enable the DMA channel */ +	out_le32(&(sata_dma_regs->dma_chan_en.low), +		 in_le32(&(sata_dma_regs->dma_chan_en.low)) | +		 DMA_ENABLE_CHAN(dma_ch)); + +#if defined(CONFIG_SATA_DWC_VDEBUG) +	printk("DMA CFG = 0x%08x\n", in_le32(&(sata_dma_regs->dma_cfg.low))); +	printk("%s: setting sata_dma_regs->dma_chan_en.low with val: 0x%08x\n", +                __func__, in_le32(&(sata_dma_regs->dma_chan_en.low))); +#endif + +   +#if defined(CONFIG_APOLLO3G) +	signal_hdd_led(1 /*blink=yes*/, 2 /* _3G_LED_GREEN */); +#endif + +} + +/* + * Check if the selected DMA channel is currently enabled. + */ +static int dma_dwc_channel_enabled(int ch) +{ +	u32 dma_chan; + +	// Read the DMA channel register +	dma_chan = in_le32(&(sata_dma_regs->dma_chan_en.low)); +	if (dma_chan & DMA_CHANNEL(ch)) +		return 1; + +	return 0; +} + +/* + * Terminate the current DMA transaction + */ +static void dma_dwc_terminate_dma(struct ata_port *ap, int dma_ch) +{ +	int enabled = dma_dwc_channel_enabled(dma_ch); + +	dev_info(ap->dev, "%s terminate DMA on channel=%d enabled=%d\n", +		 __func__, dma_ch, enabled); + +	if (enabled)  { +		// Disable the selected channel +		out_le32(&(sata_dma_regs->dma_chan_en.low), +			 in_le32(&(sata_dma_regs->dma_chan_en.low)) | DMA_DISABLE_CHAN(dma_ch)); + +		// Wait for the channel is disabled +		do { +			enabled = dma_dwc_channel_enabled(dma_ch); +			msleep(10); +		} while (enabled); +	} +} + + +/* + * Setup data and DMA configuration ready for DMA transfer + */ +static int dma_dwc_xfer_setup(struct ata_queued_cmd *qc, +			      struct lli *lli, dma_addr_t dma_lli, +			      void __iomem *addr) +{ +	int dma_ch; +	int num_lli; + +	/* Acquire DMA channel */ +	dma_ch = dma_request_channel(qc->ap); +	if (unlikely(dma_ch == -1)) { +		dev_err(qc->ap->dev, "%s: dma channel unavailable\n", __func__); +		return -EAGAIN; +	} +	dwc_port_vdbg(qc->ap, "%s: Got channel %d\n", __func__, dma_ch); + +	/* Convert SG list to linked list of items (LLIs) for AHB DMA */ +	num_lli = map_sg_to_lli(qc, lli, dma_lli, addr); + +	dwc_port_vdbg(qc->ap, "%s sg: 0x%p, count: %d lli: %p dma_lli: 0x%0xlx addr:" +		" %p lli count: %d\n", __func__, qc->sg, qc->n_elem, lli, +		(u32)dma_lli, addr, num_lli); + +	/* Clear channel interrupts */ +	clear_chan_interrupts(dma_ch); +	 +	/* Program the CFG register. */ +#if defined(CONFIG_APM821xx) +	if (dma_ch == 0) { +		/* Buffer mode enabled, FIFO_MODE=0 */ +		out_le32(&(sata_dma_regs->chan_regs[dma_ch].cfg.high), 0x0000009); +		/* Channel 0 bit[7:5] */ +		out_le32(&(sata_dma_regs->chan_regs[dma_ch].cfg.low), 0x00000020); +	} else if (dma_ch == 1) { +		/* Buffer mode enabled, FIFO_MODE=0 */ +		out_le32(&(sata_dma_regs->chan_regs[dma_ch].cfg.high), 0x0000088d); +		/* Channel 1 bit[7:5] */ +		out_le32(&(sata_dma_regs->chan_regs[dma_ch].cfg.low), 0x00000020); +	} +#else +	out_le32(&(sata_dma_regs->chan_regs[dma_ch].cfg.high), +		 DMA_CFG_PROTCTL | DMA_CFG_FCMOD_REQ); +	out_le32(&(sata_dma_regs->chan_regs[dma_ch].cfg.low), 0); +#endif + +	/* Program the address of the linked list */ +#if defined(CONFIG_APM821xx) +	out_le32(&(sata_dma_regs->chan_regs[dma_ch].llp.low), +                 DMA_LLP_LMS(dma_lli, DMA_LLP_AHBMASTER1)); +#else +	out_le32(&(sata_dma_regs->chan_regs[dma_ch].llp.low), +		 DMA_LLP_LMS(dma_lli, DMA_LLP_AHBMASTER2)); +#endif + +	/* Program the CTL register with src enable / dst enable */ +	//out_le32(&(sata_dma_regs->chan_regs[dma_ch].ctl.low), +	//	 DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN); +	out_le32(&(sata_dma_regs->chan_regs[dma_ch].ctl.low), 0x18000000); + +	dwc_port_vdbg(qc->ap, "%s DMA channel %d is ready\n", __func__, dma_ch); +	dwc_port_vdbg(qc->ap, "%s setting cfg.high of channel %d with val: 0x%08x\n", __func__, dma_ch, in_le32(&(sata_dma_regs->chan_regs[dma_ch].cfg.high))); +	dwc_port_vdbg(qc->ap, "%s setting cfg.low of channel %d with val: 0x%08x\n", __func__, dma_ch, in_le32(&(sata_dma_regs->chan_regs[dma_ch].cfg.low))); +	dwc_port_vdbg(qc->ap, "%s setting llp.low of channel %d with val: 0x%08x\n", __func__, dma_ch, in_le32(&(sata_dma_regs->chan_regs[dma_ch].llp.low))); +	dwc_port_vdbg(qc->ap, "%s setting ctl.low of channel %d with val: 0x%08x\n", __func__, dma_ch, in_le32(&(sata_dma_regs->chan_regs[dma_ch].ctl.low))); + +	return dma_ch; +} + +/* + * Function: dma_dwc_exit + * arguments: None + * returns status + * This function exits the SATA DMA driver + */ +static void dma_dwc_exit(struct sata_dwc_device *hsdev) +{ +	dwc_dev_vdbg(hsdev->dev, "%s:\n", __func__); +	if (sata_dma_regs) +		iounmap(sata_dma_regs); + +	if (hsdev->irq_dma) +		free_irq(hsdev->irq_dma, hsdev); +} + +/* + * Function: dma_dwc_init + * arguments: hsdev + * returns status + * This function initializes the SATA DMA driver + */ +static int dma_dwc_init(struct sata_dwc_device *hsdev) +{ +	int err; +	int irq = hsdev->irq_dma; + +	err = dma_request_interrupts(hsdev, irq); +	if (err) { +		dev_err(hsdev->dev, "%s: dma_request_interrupts returns %d\n", +			__func__, err); +		goto error_out; +	} + +	/* Enabe DMA */ +	out_le32(&(sata_dma_regs->dma_cfg.low), DMA_EN); + +	dev_notice(hsdev->dev, "DMA initialized\n"); +	dev_notice(hsdev->dev, "DMA CFG = 0x%08x\n", in_le32(&(sata_dma_regs->dma_cfg.low))); +	dwc_dev_vdbg(hsdev->dev, "SATA DMA registers=0x%p\n", sata_dma_regs); + +	return 0; + +error_out: +	dma_dwc_exit(hsdev); + +	return err; +} + + +static void sata_dwc_dev_config(struct ata_device *adev) +{ +	/* +	 * Does not support NCQ over a port multiplier +	 *  (no FIS-based switching). +	 */ +	if (adev->flags & ATA_DFLAG_NCQ) { +		/* +		 * TODO: debug why enabling NCQ makes the linux crashed  +		 * in hot plug after the first hot unplug action. +		 * --> need to investigate more +		 */ +		adev->flags &= ~ATA_DFLAG_NCQ; +		if (sata_pmp_attached(adev->link->ap)) { +			adev->flags &= ~ATA_DFLAG_NCQ; +			ata_dev_printk(adev, KERN_INFO, +				"NCQ disabled for command-based switching\n"); +		} +	} + +	/* +	 * Since the sata_pmp_error_handler function in libata-pmp  +	 * make FLAG_AN disabled in the first time SATA port is configured. +	 * Asynchronous notification is not configured. +	 * This will enable the AN feature manually. +	 */ +	adev->flags |= ATA_DFLAG_AN; +} + + +static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) +{ +	if (unlikely(scr > SCR_NOTIFICATION)) { +		dev_err(link->ap->dev, "%s: Incorrect SCR offset 0x%02x\n", +				__func__, scr); +		return -EINVAL; +	} + +	*val = in_le32((void *)link->ap->ioaddr.scr_addr + (scr * 4)); +	dwc_dev_vdbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n", +		__func__, link->ap->print_id, scr, *val); + +	return 0; +} + +static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val) +{ +	dwc_dev_vdbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n", +		__func__, link->ap->print_id, scr, val); +	if (unlikely(scr > SCR_NOTIFICATION)) { +		dev_err(link->ap->dev, "%s: Incorrect SCR offset 0x%02x\n", +				__func__, scr); +		return -EINVAL; +	} +	out_le32((void *)link->ap->ioaddr.scr_addr + (scr * 4), val); + +	return 0; +} + +static inline u32 sata_dwc_core_scr_read ( struct ata_port *ap, unsigned int scr) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	return in_le32((void __iomem *)hsdev->scr_base + (scr * 4)); +} + + +static inline void sata_dwc_core_scr_write ( struct ata_port *ap, unsigned int scr, u32 val) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	out_le32((void __iomem *)hsdev->scr_base + (scr * 4), val); +} + +static inline void clear_serror(struct ata_port *ap) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	out_le32( (void __iomem *)hsdev->scr_base + 4, +		in_le32((void __iomem *)hsdev->scr_base + 4)); +} + +static inline void clear_intpr(struct sata_dwc_device *hsdev) +{ +	out_le32(&hsdev->sata_dwc_regs->intpr, +		 in_le32(&hsdev->sata_dwc_regs->intpr)); +} + +static inline void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) +{ +	out_le32(&hsdev->sata_dwc_regs->intpr, bit); +		// in_le32(&hsdev->sata_dwc_regs->intpr)); +} + + +static inline void enable_err_irq(struct sata_dwc_device *hsdev) +{ +	out_le32(&hsdev->sata_dwc_regs->intmr, +		 in_le32(&hsdev->sata_dwc_regs->intmr) | SATA_DWC_INTMR_ERRM); +	out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERR_ERR_BITS); +} + +static inline u32 qcmd_tag_to_mask(u8 tag) +{ +	return 0x00000001 << (tag & 0x1f); +} + + +/* + * Timer to monitor SCR_NOTIFICATION registers on the  + * SATA port + */ +static void sata_dwc_an_chk(unsigned long arg) +{ +	struct ata_port *ap = (void *)arg; +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	unsigned long flags; +	int rc = 0x0; +	u32 sntf = 0x0; + +	spin_lock_irqsave(ap->lock, flags); +	rc = sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf); + +	// If some changes on the SCR4, call asynchronous notification +	if ( (rc == 0) & (sntf  != 0)) { +		dwc_port_dbg(ap, "Call assynchronous notification sntf=0x%08x\n", sntf); +		sata_async_notification(ap); +		hsdev->an_timer.expires = jiffies + msecs_to_jiffies(8000); +	} else { +		hsdev->an_timer.expires = jiffies + msecs_to_jiffies(3000); +	} +	add_timer(&hsdev->an_timer); +	spin_unlock_irqrestore(ap->lock, flags); +} + + +/* + *   sata_dwc_pmp_select - Set the PMP field in SControl to the specified port number. + * + *   @port: The value (port number) to set the PMP field to. + * + *   @return: The old value of the PMP field. + */ +static u32 sata_dwc_pmp_select(struct ata_port *ap, u32 port) +{ +	u32 scontrol, old_port; +	if (sata_pmp_supported(ap)) { +		scontrol = sata_dwc_core_scr_read(ap, SCR_CONTROL); +		old_port = SCONTROL_TO_PMP(scontrol); + +		// Select new PMP port +		if ( port != old_port )  { +			scontrol &= ~SCONTROL_PMP_MASK; +			sata_dwc_core_scr_write(ap, SCR_CONTROL, scontrol | PMP_TO_SCONTROL(port)); +			dwc_port_dbg(ap, "%s: old port=%d new port=%d\n", __func__, old_port, port); +		} +		return old_port; +	}  +	else +		return port; +} + +/* + * Get the current PMP port + */ +static inline u32 current_pmp(struct ata_port *ap) +{ +	return SCONTROL_TO_PMP(sata_dwc_core_scr_read(ap, SCR_CONTROL)); +} + + +/*  + * Process when a PMP card is attached in the SATA port. + * Since our SATA port support command base switching only, + * NCQ will not be available. + * We disable the NCQ feature in SATA port. + */ +static void sata_dwc_pmp_attach ( struct ata_port *ap) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); + +	dev_info(ap->dev, "Attach SATA port multiplier with %d ports\n", ap->nr_pmp_links); +	// Disable NCQ +	ap->flags &= ~ATA_FLAG_NCQ; + +	// Initialize timer for checking AN +	init_timer(&hsdev->an_timer); +	hsdev->an_timer.expires = jiffies + msecs_to_jiffies(20000); +	hsdev->an_timer.function = sata_dwc_an_chk; +	hsdev->an_timer.data = (unsigned long)(ap); +	add_timer(&hsdev->an_timer); +} + +/* + * Process when PMP card is removed from the SATA port. + * Re-enable NCQ for using by the SATA drive in the future + */ +static void sata_dwc_pmp_detach ( struct ata_port *ap) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); + +	dev_info(ap->dev, "Detach SATA port\n"); +	// Re-enable NCQ +	// TODO: remove the below comment out when NCQ problem fixed +	//ap->flags |= ATA_FLAG_NCQ; + +	sata_dwc_pmp_select(ap, 0); + +	// Delete timer since PMP card is detached +	del_timer(&hsdev->an_timer); +} + + + +// Check the link to be ready +int sata_dwc_check_ready ( struct ata_link *link ) { +	u8 status; +	struct ata_port *ap = link->ap; +	status = ioread8(ap->ioaddr.status_addr); +	return ata_check_ready(status); +} + + +/* + * Do soft reset on the current SATA link. + */ +static int sata_dwc_softreset(struct ata_link *link, unsigned int *classes, +				unsigned long deadline) +{ +	int rc; +	struct ata_port *ap = link->ap; +	struct ata_ioports *ioaddr = &ap->ioaddr; +	struct ata_taskfile tf; + +	sata_dwc_pmp_select(link->ap, sata_srst_pmp(link)); + +	/* Issue bus reset */ +	iowrite8(ap->ctl, ioaddr->ctl_addr); +	udelay(20);	/* FIXME: flush */ +	iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); +	udelay(20);	/* FIXME: flush */ +	iowrite8(ap->ctl, ioaddr->ctl_addr); +	ap->last_ctl = ap->ctl; + +	/* Always check readiness of the master device */ +	rc = ata_wait_after_reset(link, deadline, sata_dwc_check_ready); + +	// Classify the ata_port +	*classes = ATA_DEV_NONE; +	/* Verify if SStatus indicates device presence */ +	if (ata_link_online(link)) { +		memset(&tf, 0, sizeof(tf)); +		ata_sff_tf_read(ap, &tf); +		*classes = ata_dev_classify(&tf); +	} + +	if ( *classes == ATA_DEV_PMP) +		dwc_link_dbg(link, "-->found PMP device by sig\n"); + +	clear_serror(link->ap); + +	return rc; +} + + + + +/* + * sata_dwc_hardreset - Do hardreset the SATA controller + */ +static int sata_dwc_hardreset(struct ata_link *link, unsigned int *classes, +			   unsigned long deadline) +{ +	int rc; +	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); +	bool online; +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(link->ap); + +	dwc_link_dbg(link, "%s\n", __func__); +	sata_dwc_pmp_select(link->ap, sata_srst_pmp(link)); +	dwc_port_vdbg(link->ap, "dmacr=0x%08x\n",in_le32(&(hsdev->sata_dwc_regs->dmacr))); + +	// Call standard hard reset +	rc = sata_link_hardreset(link, timing, deadline, &online, NULL); + +	// Reconfigure the port after hard reset +	if ( ata_link_online(link) ) +		sata_dwc_init_port(link->ap); + +	return online ? -EAGAIN : rc; +} + +/* + * Do hard reset on each PMP link + */ +static int sata_dwc_pmp_hardreset(struct ata_link *link, unsigned int *classes, +			   unsigned long deadline) +{ +	int rc = 0; +	sata_dwc_pmp_select(link->ap, sata_srst_pmp(link)); +	rc = sata_std_hardreset(link, classes, deadline); +	return rc; +} + +/* See ahci.c */ +/* + * Process error when the SATAn_INTPR's ERR bit is set + * The processing is based on SCR_ERROR register content + */ +static void sata_dwc_error_intr(struct ata_port *ap, +				struct sata_dwc_device *hsdev, uint intpr) +{ +	struct ata_eh_info *ehi; +	struct ata_link *link; +	struct ata_queued_cmd *active_qc = NULL; +	u32 serror; +	bool freeze = false, abort = false; +	int pmp, ret; +	unsigned int err_mask = 0, action = 0; +#if defined(CONFIG_SATA_DWC_VDEBUG) +	int dma_chan = hsdev->dma_channel; +#endif + +	link = &ap->link; +	ehi = &link->eh_info; + +	/* Record irq stat */ +	ata_ehi_clear_desc(ehi); +	ata_ehi_push_desc(ehi, "irq_stat 0x%08x", intpr); + +	// Record SERROR +	serror = sata_dwc_core_scr_read(ap, SCR_ERROR); +	dwc_port_dbg(ap, "%s serror = 0x%08x\n", __func__, serror); + +	// Clear SERROR and interrupt bit +	clear_serror(ap); +	clear_intpr(hsdev); + +	// Print out for test only +	if ( serror ) { +		dwc_port_info(ap, "Detect errors:"); +		if ( serror & SATA_DWC_SERR_ERRI ) +			printk(" ERRI"); +		if ( serror & SATA_DWC_SERR_ERRM ) +			printk(" ERRM"); +		if ( serror & SATA_DWC_SERR_ERRT ) +			printk(" ERRT"); +		if ( serror & SATA_DWC_SERR_ERRC ) +			printk(" ERRC"); +		if ( serror & SATA_DWC_SERR_ERRP ) +			printk(" ERRP"); +		if ( serror & SATA_DWC_SERR_ERRE ) +			printk(" ERRE"); +		if ( serror & SATA_DWC_SERR_DIAGN ) +			printk(" DIAGN"); +		if ( serror & SATA_DWC_SERR_DIAGI ) +			printk(" DIAGI"); +		if ( serror & SATA_DWC_SERR_DIAGW ) +			printk(" DIAGW"); +		if ( serror & SATA_DWC_SERR_DIAGB ) +			printk(" DIAGB"); +		if ( serror & SATA_DWC_SERR_DIAGT ) +			printk(" DIAGT"); +		if ( serror & SATA_DWC_SERR_DIAGC ) +			printk(" DIAGC"); +		if ( serror & SATA_DWC_SERR_DIAGH ) +			printk(" DIAGH"); +		if ( serror & SATA_DWC_SERR_DIAGL ) +			printk(" DIAGL"); +		if ( serror & SATA_DWC_SERR_DIAGS ) +			printk(" DIAGS"); +		if ( serror & SATA_DWC_SERR_DIAGF ) +			printk(" DIAGF"); +		if ( serror & SATA_DWC_SERR_DIAGX ) +			printk(" DIAGX"); +		if ( serror & SATA_DWC_SERR_DIAGA ) +			printk(" DIAGA"); +		printk("\n"); +	} + +#if defined(CONFIG_SATA_DWC_VDEBUG) +        printk("%s reading cfg.high of channel %d with val: 0x%08x\n", __func__, dma_chan, in_le32(&(sata_dma_regs->chan_regs[dma_chan].cfg.high))); +        printk("%s reading cfg.low of channel %d with val: 0x%08x\n", __func__, dma_chan, in_le32(&(sata_dma_regs->chan_regs[dma_chan].cfg.low))); +        printk("%s reading llp.low of channel %d with val: 0x%08x\n", __func__, dma_chan, in_le32(&(sata_dma_regs->chan_regs[dma_chan].llp.low))); +        printk("%s reading ctl.low of channel %d with val: 0x%08x\n", __func__, dma_chan, in_le32(&(sata_dma_regs->chan_regs[dma_chan].ctl.low))); +        printk("%s reading sar.low of channel %d with val: 0x%08x\n", __func__, dma_chan, in_le32(&(sata_dma_regs->chan_regs[dma_chan].sar.low))); +        printk("%s reading sar.high of channel %d with val: 0x%08x\n", __func__, dma_chan, in_le32(&(sata_dma_regs->chan_regs[dma_chan].sar.high))); +        printk("%s reading dar.low of channel %d with val: 0x%08x\n", __func__, dma_chan, in_le32(&(sata_dma_regs->chan_regs[dma_chan].dar.low))); +        printk("%s reading dar.high of channel %d with val: 0x%08x\n", __func__, dma_chan, in_le32(&(sata_dma_regs->chan_regs[dma_chan].dar.high))); +#endif + +	// Process hotplug for SATA port +	if ( serror & (SATA_DWC_SERR_DIAGX | SATA_DWC_SERR_DIAGW)) { +		dwc_port_info(ap, "Detect hot plug signal\n"); +		ata_ehi_hotplugged(ehi); +		ata_ehi_push_desc(ehi, serror & SATA_DWC_SERR_DIAGN ? "PHY RDY changed" : "device exchanged"); +		freeze = true; +	} + +	// Process PHY internal error / Link sequence (illegal transition) error +	if ( serror & (SATA_DWC_SERR_DIAGI | SATA_DWC_SERR_DIAGL)) { +		ehi->err_mask |= AC_ERR_HSM; +		ehi->action |= ATA_EH_RESET; +		freeze = true; +	} + +	// Process Internal host adapter error +	if ( serror & SATA_DWC_SERR_ERRE ) { +		dev_err(ap->dev, "Detect Internal host adapter error\n"); +		// --> need to review +		ehi->err_mask |= AC_ERR_HOST_BUS; +		ehi->action |= ATA_EH_RESET; +		freeze = true; +	} + +	// Process Protocol Error +	if ( serror & SATA_DWC_SERR_ERRP ) { +		dev_err(ap->dev, "Detect Protocol error\n"); +		ehi->err_mask |= AC_ERR_HSM; +		ehi->action |= ATA_EH_RESET; +		freeze = true; +	} + +	// Process non-recovered persistent communication error +	if ( serror & SATA_DWC_SERR_ERRC ) { +		dev_err(ap->dev, "Detect non-recovered persistent communication error\n"); +		// --> TODO: review processing error +		ehi->err_mask |= AC_ERR_ATA_BUS; +		ehi->action |= ATA_EH_SOFTRESET; +		//ehi->flags |= ATA_EHI_NO_AUTOPSY; +		//freeze = true; +	} + +	// Non-recovered transient data integrity error +	if ( serror & SATA_DWC_SERR_ERRT ) { +		dev_err(ap->dev, "Detect non-recovered transient data integrity error\n"); +		ehi->err_mask |= AC_ERR_ATA_BUS; +		//ehi->err_mask |= AC_ERR_DEV; +		ehi->action |= ATA_EH_SOFTRESET; +		//ehi->flags |= ATA_EHI_NO_AUTOPSY; +	} + +	// Since below errors have been recovered by hardware +	// they don't need any error processing. +	if ( serror & SATA_DWC_SERR_ERRM ) { +		dev_warn(ap->dev, "Detect recovered communication error"); +	} +	if ( serror & SATA_DWC_SERR_ERRI ) { +		dev_warn(ap->dev, "Detect recovered data integrity error"); +	} + +	// If any error occur, process the qc +	if (serror & (SATA_DWC_SERR_ERRT | SATA_DWC_SERR_ERRC)) { +	//if (serror & 0x03f60f0) { +		abort = true; +		/* find out the offending link and qc */ +		if (sata_pmp_attached(ap)) { +			pmp = current_pmp(ap); +			// If we are working on the PMP port +			if ( pmp < ap->nr_pmp_links ) { +				link = &ap->pmp_link[pmp]; +				ehi = &link->eh_info; +				active_qc = ata_qc_from_tag(ap, link->active_tag); +				err_mask |= AC_ERR_DEV; +				ata_ehi_clear_desc(ehi); +				ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); +			} else { +				err_mask |= AC_ERR_HSM; +				action |= ATA_EH_RESET; +				freeze = true; +			} +		 +		} +		// Work on SATA port +		else { +			freeze = true; +			active_qc = ata_qc_from_tag(ap, link->active_tag); +		} + +		if ( active_qc) { +			active_qc->err_mask |= err_mask; +		} else { +			ehi->err_mask = err_mask; +		} +	} + +	if ( freeze | abort ) { +		//sata_dwc_qc_complete(ap, active_qc, 1); +		// Terminate DMA channel if it is currenly in use +		if ( dma_request_channel(ap) != -1 ) { +			dwc_port_dbg(ap, "Terminate DMA channel %d for handling error\n", hsdev->dma_channel); +			dma_dwc_terminate_dma(ap, hsdev->dma_channel); +		} +	} + +	if (freeze) { +		ret = ata_port_freeze(ap); +		ata_port_printk(ap, KERN_INFO, "Freeze port with %d QCs aborted\n", ret); +	} +	else if (abort) { +		if (active_qc) { +			ret = ata_link_abort(active_qc->dev->link); +			ata_link_printk(link, KERN_INFO, "Abort %d QCs\n", ret); +		} else { +			ret = ata_port_abort(ap); +			ata_port_printk(ap, KERN_INFO, "Abort %d QCs on the SATA port\n", ret); +		} +	} +} + + +/* + * Function : sata_dwc_isr + * arguments : irq, void *dev_instance, struct pt_regs *regs + * Return value : irqreturn_t - status of IRQ + * This Interrupt handler called via port ops registered function. + * .irq_handler = sata_dwc_isr + */ +static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) +{ +	struct ata_host *host = (struct ata_host *)dev_instance; +	struct sata_dwc_device *hsdev = HSDEV_FROM_HOST(host); +	struct ata_port *ap; +	struct ata_queued_cmd *qc; +	unsigned long flags; +	u8 status, tag; +	int handled, num_processed, port = 0; +	u32 intpr, sactive, sactive2, tag_mask; +	struct sata_dwc_device_port *hsdevp; + +	spin_lock_irqsave(&host->lock, flags); + +	/* Read the interrupt register */ +	intpr = in_le32(&hsdev->sata_dwc_regs->intpr); + +	ap = host->ports[port]; +	hsdevp = HSDEVP_FROM_AP(ap); + +	dwc_port_dbg(ap,"%s\n",__func__); +	if ( intpr != 0x80000080) +		dwc_port_dbg(ap, "%s intpr=0x%08x active_tag=%d\n", __func__, intpr, ap->link.active_tag); +	//dwc_port_dbg(ap, "%s: INTMR=0x%08x, ERRMR=0x%08x\n", __func__, in_le32(&hsdev->sata_dwc_regs->intmr), in_le32(&hsdev->sata_dwc_regs->errmr)); + +	/* Check for error interrupt */ +	if (intpr & SATA_DWC_INTPR_ERR) { +		sata_dwc_error_intr(ap, hsdev, intpr); +		handled = 1; +#if defined(CONFIG_APOLLO3G) +		signal_hdd_led(0 /*off blink*/, 1 /*red color*/); +#endif +		goto done_irqrestore; +	} + +	/* Check for DMA SETUP FIS (FP DMA) interrupt */ +	if (intpr & SATA_DWC_INTPR_NEWFP) { +		dwc_port_dbg(ap, "%s: NEWFP INTERRUPT in HSDEV with DMA channel %d\n", __func__, hsdev->dma_channel); +		clear_interrupt_bit(hsdev, SATA_DWC_INTPR_NEWFP); + +		tag = (u8)(in_le32(&hsdev->sata_dwc_regs->fptagr)); +		dwc_dev_dbg(ap->dev, "%s: NEWFP tag=%d\n", __func__, tag); +		if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PENDING) +			dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag); + +		hsdevp->sata_dwc_sactive_issued |= qcmd_tag_to_mask(tag); + +		qc = ata_qc_from_tag(ap, tag); +		/* +		 * Start FP DMA for NCQ command.  At this point the tag is the +		 * active tag.  It is the tag that matches the command about to +		 * be completed. +		 */ +		qc->ap->link.active_tag = tag; +		sata_dwc_bmdma_start_by_tag(qc, tag); +		qc->ap->hsm_task_state = HSM_ST_LAST; + +		handled = 1; +		goto done_irqrestore; +	} + +	sactive = sata_dwc_core_scr_read(ap, SCR_ACTIVE); +	tag_mask = (hsdevp->sata_dwc_sactive_issued | sactive) ^ sactive; + +	/* If no sactive issued and tag_mask is zero then this is not NCQ */ +	if (hsdevp->sata_dwc_sactive_issued == 0 && tag_mask == 0) { +		if (ap->link.active_tag == ATA_TAG_POISON) +			tag = 0; +		else +			tag = ap->link.active_tag; +		qc = ata_qc_from_tag(ap, tag); + +		/* DEV interrupt w/ no active qc? */ +		if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { +			dev_err(ap->dev, "%s intr with no active qc qc=%p\n", +				__func__, qc); +			ap->ops->sff_check_status(ap); +			handled = 1; +			goto done_irqrestore; +		} + +		status = ap->ops->sff_check_status(ap); + +		qc->ap->link.active_tag = tag; +		hsdevp->cmd_issued[tag] = SATA_DWC_CMD_ISSUED_NOT; + +		if (status & ATA_ERR) { +			dwc_dev_dbg(ap->dev, "interrupt ATA_ERR (0x%x)\n", status); +			sata_dwc_qc_complete(ap, qc, 1); +			handled = 1; +			goto done_irqrestore; +		} + +		dwc_dev_dbg(ap->dev, "%s non-NCQ cmd interrupt, protocol: %s\n", +			__func__, prot_2_txt(qc->tf.protocol)); +drv_still_busy: +		if (ata_is_dma(qc->tf.protocol)) { +			int dma_flag = hsdevp->dma_pending[tag]; +			/* +			 * Each DMA transaction produces 2 interrupts.  The DMAC +			 * transfer complete interrupt and the SATA controller +			 * operation done interrupt. The command should be +			 * completed only after both interrupts are seen. +			 */ +			hsdevp->dma_interrupt_count++; +			if (unlikely(dma_flag == SATA_DWC_DMA_PENDING_NONE)) { +				dev_err(ap->dev, "%s: DMA not pending " +					"intpr=0x%08x status=0x%08x pend=%d\n", +					__func__, intpr, status, dma_flag); +			} + +			if ((hsdevp->dma_interrupt_count % 2) == 0) +				sata_dwc_dma_xfer_complete(ap, 1); +		} else if (ata_is_pio(qc->tf.protocol)) { +			ata_sff_hsm_move(ap, qc, status, 0); +			handled = 1; +			goto done_irqrestore; +		} else { +			if (unlikely(sata_dwc_qc_complete(ap, qc, 1))) +				goto drv_still_busy; +		} + +		handled = 1; +		goto done_irqrestore; +	} + +	/* +	 * This is a NCQ command.  At this point we need to figure out for which +	 * tags we have gotten a completion interrupt.  One interrupt may serve +	 * as completion for more than one operation when commands are queued +	 * (NCQ).  We need to process each completed command. +	 */ + +process_cmd:  /* process completed commands */ +	sactive = sata_dwc_core_scr_read(ap, SCR_ACTIVE); +	tag_mask = (hsdevp->sata_dwc_sactive_issued | sactive) ^ sactive; + +	if (sactive != 0 || hsdevp->sata_dwc_sactive_issued > 1 || tag_mask > 1) { +		dwc_dev_dbg(ap->dev, "%s NCQ: sactive=0x%08x  sactive_issued=0x%08x" +			" tag_mask=0x%08x\n", __func__, sactive, +			hsdevp->sata_dwc_sactive_issued, tag_mask); +	} + +	if (unlikely((tag_mask | hsdevp->sata_dwc_sactive_issued) != hsdevp->sata_dwc_sactive_issued)) { +		dev_warn(ap->dev, "Bad tag mask?  sactive=0x%08x " +			 "sata_dwc_sactive_issued=0x%08x  tag_mask=0x%08x\n", +			 sactive, hsdevp->sata_dwc_sactive_issued, tag_mask); +	} + +	/* read just to clear ... not bad if currently still busy */ +	status = ap->ops->sff_check_status(ap); +	dwc_dev_dbg(ap->dev, "%s ATA status register=0x%x, tag_mask=0x%x\n", __func__, status, tag_mask); + +	tag = 0; +	num_processed = 0; +	while (tag_mask) { +		num_processed++; +		while (!(tag_mask & 0x00000001)) { +			tag++; +			tag_mask <<= 1; +		} +		tag_mask &= (~0x00000001); +		qc = ata_qc_from_tag(ap, tag); + +		/* To be picked up by completion functions */ +		qc->ap->link.active_tag = tag; +		hsdevp->cmd_issued[tag] = SATA_DWC_CMD_ISSUED_NOT; + +		/* Let libata/scsi layers handle error */ +		if (unlikely(status & ATA_ERR)) { +			dwc_dev_vdbg(ap->dev, "%s ATA_ERR (0x%x)\n", +					 __func__, status); + +			sata_dwc_qc_complete(ap, qc, 1); +			handled = 1; +			goto done_irqrestore; +		} + +		/* Process completed command */ +		dwc_dev_dbg(ap->dev, "%s NCQ command, protocol: %s\n", __func__, +			prot_2_txt(qc->tf.protocol)); +		if (ata_is_dma(qc->tf.protocol)) { +			hsdevp->dma_interrupt_count++; +			if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE) +				dev_warn(ap->dev, +					"%s: DMA not pending?\n", __func__); +			if ((hsdevp->dma_interrupt_count % 2) == 0) +				sata_dwc_dma_xfer_complete(ap, 1); +		} else { +			if (unlikely(sata_dwc_qc_complete(ap, qc, 1))) +				goto still_busy; +		} +		continue; + +still_busy: +		ap->stats.idle_irq++; +		dev_warn(ap->dev, "STILL BUSY IRQ ata%d: irq trap\n", +				ap->print_id); +	} /* while tag_mask */ + +	/* +	 * Check to see if any commands completed while we were processing our +	 * initial set of completed commands (reading of status clears +	 * interrupts, so we might miss a completed command interrupt if one +	 * came in while we were processing: +	 * we read status as part of processing a completed command). +	 */ +	sactive2 = sata_dwc_core_scr_read(ap, SCR_ACTIVE); +	if (sactive2 != sactive) { +		dwc_dev_dbg(ap->dev, "More finished - sactive=0x%x sactive2=0x%x\n", +			sactive, sactive2); +		goto process_cmd; +	} +	handled = 1; + +done_irqrestore: +	spin_unlock_irqrestore(&host->lock, flags); +#if defined(CONFIG_APOLLO3G) +	signal_hdd_led(0 /*off blink*/, -1 /* no color */); +#endif +	return IRQ_RETVAL(handled); +} + + +/* + * Clear DMA Control Register after completing transferring data + * using AHB DMA. + */ +static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp); + +	if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) { +		// Clear receive channel enable bit +		out_le32(&(hsdev->sata_dwc_regs->dmacr), +			 SATA_DWC_DMACR_RX_CLEAR( +				 in_le32(&(hsdev->sata_dwc_regs->dmacr)))); +	} else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) { +		// Clear transmit channel enable bit +		out_le32(&(hsdev->sata_dwc_regs->dmacr), +			 SATA_DWC_DMACR_TX_CLEAR( +				 in_le32(&(hsdev->sata_dwc_regs->dmacr)))); +	} else { +		/* +		 * This should not happen, it indicates the driver is out of +		 * sync.  If it does happen, clear dmacr anyway. +		 */ +		dev_err(hsdev->dev, "%s DMA protocol RX and TX DMA not pending " +			"tag=0x%02x pending=%d dmacr: 0x%08x\n", +			__func__, tag, hsdevp->dma_pending[tag], +			in_le32(&(hsdev->sata_dwc_regs->dmacr))); + +		// Clear all transmit and receive bit, but TXMOD bit is set to 1 +		out_le32(&(hsdev->sata_dwc_regs->dmacr), +				SATA_DWC_DMACR_TXRXCH_CLEAR); +	} +} + +/* + * + */ +static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status) +{ +	struct ata_queued_cmd *qc; +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	u8 tag = 0; + +	tag = ap->link.active_tag; +	qc = ata_qc_from_tag(ap, tag); + +#ifdef DEBUG_NCQ +	if (tag > 0) { +		dev_info(ap->dev, "%s tag=%u cmd=0x%02x dma dir=%s proto=%s " +			 "dmacr=0x%08x\n", __func__, qc->tag, qc->tf.command, +			 dir_2_txt(qc->dma_dir), prot_2_txt(qc->tf.protocol), +			 in_le32(&(hsdev->sata_dwc_regs->dmacr))); +	} +#endif + +	if (ata_is_dma(qc->tf.protocol)) { +		// DMA out of sync error +		if (unlikely(hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_NONE)) { +			dev_err(ap->dev, "%s DMA protocol RX and TX DMA not " +				"pending dmacr: 0x%08x\n", __func__, +				in_le32(&(hsdev->sata_dwc_regs->dmacr))); +		} + +		hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_NONE; +		sata_dwc_qc_complete(ap, qc, check_status); +		ap->link.active_tag = ATA_TAG_POISON; +	} else { +		sata_dwc_qc_complete(ap, qc, check_status); +	} +} + +/* + * + */ +static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc, +				u32 check_status) +{ +	u8 status = 0; +	int i = 0; +	u32 mask = 0x0; +	u8 tag = qc->tag; +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	u32 serror; +	int dma_ch; + +	dwc_dev_vdbg(ap->dev, "%s checkstatus? %x\n", __func__, check_status); + +	if (unlikely(hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX)) +		dev_err(ap->dev, "TX DMA PENDINGING\n"); +	else if (unlikely(hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX)) +		dev_err(ap->dev, "RX DMA PENDINGING\n"); + +	if (check_status) { +		i = 0; +		do { +			/* check main status, clearing INTRQ */ +			status = ap->ops->sff_check_status(ap); +			if (status & ATA_BUSY) { +				dwc_dev_vdbg(ap->dev, "STATUS BUSY (0x%02x) [%d]\n", +						status, i); +			} +			if (++i > 10) +				break; +		} while (status & ATA_BUSY); + +		status = ap->ops->sff_check_status(ap); +		if (unlikely(status & ATA_BUSY)) +			dev_err(ap->dev, "QC complete cmd=0x%02x STATUS BUSY " +				"(0x%02x) [%d]\n", qc->tf.command, status, i); + + +		// Check error ==> need to process error here +		serror = sata_dwc_core_scr_read(ap, SCR_ERROR); +		if (unlikely(serror & SATA_DWC_SERR_ERR_BITS)) +		{ +			dev_err(ap->dev, "****** SERROR=0x%08x ******\n", serror); +			ap->link.eh_context.i.action |= ATA_EH_RESET; +			if (ata_is_dma(qc->tf.protocol)) { +				dma_ch = hsdevp->dma_chan[tag]; +				dma_dwc_terminate_dma(ap, dma_ch); +			} else { +				dma_ch = hsdevp->dma_chan[0]; +				dma_dwc_terminate_dma(ap, dma_ch); +			} +		} +	} +	dwc_dev_vdbg(ap->dev, "QC complete cmd=0x%02x status=0x%02x ata%u: " +		"protocol=%d\n", qc->tf.command, status, ap->print_id, +		qc->tf.protocol); + +	/* clear active bit */ +	mask = (~(qcmd_tag_to_mask(tag))); +	hsdevp->sata_dwc_sactive_queued = hsdevp->sata_dwc_sactive_queued & mask; +	hsdevp->sata_dwc_sactive_issued = hsdevp->sata_dwc_sactive_issued & mask; +	dwc_port_vdbg(ap, "%s - sata_dwc_sactive_queued=0x%08x, sata_dwc_sactive_issued=0x%08x\n",__func__, hsdevp->sata_dwc_sactive_queued, hsdevp->sata_dwc_sactive_issued); +	dwc_port_vdbg(ap, "dmacr=0x%08x\n",in_le32(&(hsdev->sata_dwc_regs->dmacr))); + +	/* Complete taskfile transaction (does not read SCR registers) */ +	ata_qc_complete(qc); + +	return 0; +} + +/* + * Clear interrupt and error flags in DMA status register. + */ +void sata_dwc_irq_clear (struct ata_port *ap) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	dwc_port_dbg(ap,"%s\n",__func__); + +	// Clear DMA interrupts +	clear_chan_interrupts(hsdev->dma_channel); +	//sata_dma_regs +	//out_le32(&hsdev->sata_dwc_regs->intmr, +	//	 in_le32(&hsdev->sata_dwc_regs->intmr) & ~SATA_DWC_INTMR_ERRM); +	//out_le32(&hsdev->sata_dwc_regs->errmr, 0x0); +	//sata_dwc_check_status(ap); +} + +/* + * Turn on IRQ + */ +void sata_dwc_irq_on(struct ata_port *ap) +{ +	struct ata_ioports *ioaddr = &ap->ioaddr; +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	u8 tmp; + +	dwc_port_dbg(ap,"%s\n",__func__); +	ap->ctl &= ~ATA_NIEN; +	ap->last_ctl = ap->ctl; + +	if (ioaddr->ctl_addr) +		iowrite8(ap->ctl, ioaddr->ctl_addr); +	tmp = ata_wait_idle(ap); + +	ap->ops->sff_irq_clear(ap); +	enable_err_irq(hsdev); +} + + +/* + * This function enables the interrupts in IMR and unmasks them in ERRMR + *  + */ +static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev) +{ +	// Enable interrupts +	out_le32(&hsdev->sata_dwc_regs->intmr, +		 SATA_DWC_INTMR_ERRM | +		 SATA_DWC_INTMR_NEWFPM | +		 SATA_DWC_INTMR_PMABRTM | +		 SATA_DWC_INTMR_DMATM); + +	/* +	 * Unmask the error bits that should trigger an error interrupt by +	 * setting the error mask register. +	 */ +	out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERR_ERR_BITS); + +	dwc_dev_dbg(hsdev->dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n", __func__, +		in_le32(&hsdev->sata_dwc_regs->intmr), +		in_le32(&hsdev->sata_dwc_regs->errmr)); +} + +/*  + * Configure DMA and interrupts on SATA port. This should be called after + * hardreset is executed on the SATA port. + */ +static void sata_dwc_init_port ( struct ata_port *ap ) { +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); + +	// Configure DMA +	if (ap->port_no == 0)  { +		dwc_dev_dbg(ap->dev, "%s: clearing TXCHEN, RXCHEN in DMAC\n", +				__func__); + +		// Clear all transmit/receive bits +		out_le32(&hsdev->sata_dwc_regs->dmacr, +			 SATA_DWC_DMACR_TXRXCH_CLEAR); + +		dwc_dev_dbg(ap->dev, "%s: setting burst size in DBTSR\n", __func__); +		out_le32(&hsdev->sata_dwc_regs->dbtsr, +			 (SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) | +			  SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT))); +	} + +	// Enable interrupts +	sata_dwc_enable_interrupts(hsdev); +} + + +/* + * Setup SATA ioport with corresponding register addresses + */ +static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base) +{ +	port->cmd_addr = (void *)base + 0x00; +	port->data_addr = (void *)base + 0x00; + +	port->error_addr = (void *)base + 0x04; +	port->feature_addr = (void *)base + 0x04; + +	port->nsect_addr = (void *)base + 0x08; + +	port->lbal_addr = (void *)base + 0x0c; +	port->lbam_addr = (void *)base + 0x10; +	port->lbah_addr = (void *)base + 0x14; + +	port->device_addr = (void *)base + 0x18; +	port->command_addr = (void *)base + 0x1c; +	port->status_addr = (void *)base + 0x1c; + +	port->altstatus_addr = (void *)base + 0x20; +	port->ctl_addr = (void *)base + 0x20; +} + + +/* + * Function : sata_dwc_port_start + * arguments : struct ata_ioports *port + * Return value : returns 0 if success, error code otherwise + * This function allocates the scatter gather LLI table for AHB DMA + */ +static int sata_dwc_port_start(struct ata_port *ap) +{ +	int err = 0; +	struct sata_dwc_device *hsdev; +	struct sata_dwc_device_port *hsdevp = NULL; +	struct device *pdev; +	u32 sstatus; +	int i; + +	hsdev = HSDEV_FROM_AP(ap); + +	dwc_dev_dbg(ap->dev, "%s: port_no=%d\n", __func__, ap->port_no); + +	hsdev->host = ap->host; +	pdev = ap->host->dev; +	if (!pdev) { +		dev_err(ap->dev, "%s: no ap->host->dev\n", __func__); +		err = -ENODEV; +		goto cleanup_exit; +	} + +	/* Allocate Port Struct */ +	hsdevp = kzalloc(sizeof(*hsdevp), GFP_KERNEL); +	if (!hsdevp) { +		dev_err(ap->dev, "%s: kmalloc failed for hsdevp\n", __func__); +		err = -ENOMEM; +		goto cleanup_exit; +	} +	hsdevp->hsdev = hsdev; + +	for (i = 0; i < SATA_DWC_QCMD_MAX; i++) +		hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT; + +	ap->bmdma_prd = 0;	/* set these so libata doesn't use them */ +	ap->bmdma_prd_dma = 0; + +	/* +	 * DMA - Assign scatter gather LLI table. We can't use the libata +	 * version since it's PRD is IDE PCI specific. +	 */ +	for (i = 0; i < SATA_DWC_QCMD_MAX; i++) { +		hsdevp->llit[i] = dma_alloc_coherent(pdev, +						     SATA_DWC_DMAC_LLI_TBL_SZ, +						     &(hsdevp->llit_dma[i]), +						     GFP_ATOMIC); +		if (!hsdevp->llit[i]) { +			dev_err(ap->dev, "%s: dma_alloc_coherent failed size " +				"0x%x\n", __func__, SATA_DWC_DMAC_LLI_TBL_SZ); +			err = -ENOMEM; +			goto cleanup_exit; +		} +	} + +	if (ap->port_no == 0)  { +		dwc_dev_vdbg(ap->dev, "%s: clearing TXCHEN, RXCHEN in DMAC\n", +				__func__); + +		out_le32(&hsdev->sata_dwc_regs->dmacr, +			 SATA_DWC_DMACR_TXRXCH_CLEAR); + +		dwc_dev_vdbg(ap->dev, "%s: setting burst size in DBTSR\n", __func__); +		out_le32(&hsdev->sata_dwc_regs->dbtsr, +			 (SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) | +			  SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT))); +		 ata_port_printk(ap, KERN_INFO, "%s: setting burst size in DBTSR: 0x%08x\n",  +			__func__, in_le32(&hsdev->sata_dwc_regs->dbtsr)); +	} + +	/* Clear any error bits before libata starts issuing commands */ +	clear_serror(ap); + +	ap->private_data = hsdevp; + +	/* Are we in Gen I or II */ +	sstatus = sata_dwc_core_scr_read(ap, SCR_STATUS); +	switch (SATA_DWC_SCR0_SPD_GET(sstatus)) { +	case 0x0: +		dev_info(ap->dev, "**** No neg speed (nothing attached?) \n"); +		break; +	case 0x1: +		dev_info(ap->dev, "**** GEN I speed rate negotiated \n"); +		break; +	case 0x2: +		dev_info(ap->dev, "**** GEN II speed rate negotiated \n"); +		break; +	} + +cleanup_exit: +	if (err) { +		kfree(hsdevp); +		sata_dwc_port_stop(ap); +		dwc_dev_vdbg(ap->dev, "%s: fail\n", __func__); +	} else { +		dwc_dev_vdbg(ap->dev, "%s: done\n", __func__); +	} + +	return err; +} + + +static void sata_dwc_port_stop(struct ata_port *ap) +{ +	int i; +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); + +	dwc_port_dbg(ap, "%s: stop port\n", __func__); + +	if (hsdevp && hsdev) { +		/* deallocate LLI table */ +		for (i = 0; i < SATA_DWC_QCMD_MAX; i++) { +			dma_free_coherent(ap->host->dev, +					  SATA_DWC_DMAC_LLI_TBL_SZ, +					  hsdevp->llit[i], hsdevp->llit_dma[i]); +		} + +		kfree(hsdevp); +	} +	ap->private_data = NULL; +} + +/* + * Since the SATA DWC is master only. The dev select operation will  + * be removed. + */ +void sata_dwc_dev_select(struct ata_port *ap, unsigned int device) +{ +	// Do nothing +	ndelay(100); +} + +/* + * Function : sata_dwc_exec_command_by_tag + * arguments : ata_port *ap, ata_taskfile *tf, u8 tag, u32 cmd_issued + * Return value : None + * This function keeps track of individual command tag ids and calls + * ata_exec_command in libata + */ +static void sata_dwc_exec_command_by_tag(struct ata_port *ap, +					 struct ata_taskfile *tf, +					 u8 tag, u32 cmd_issued) +{ +	unsigned long flags; +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); + +	dwc_dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d, ap->link->tag=0x%08x\n", __func__, tf->command, +		ata_cmd_2_txt(tf), tag, ap->link.active_tag); + +	spin_lock_irqsave(&ap->host->lock, flags); +	hsdevp->cmd_issued[tag] = cmd_issued; +	spin_unlock_irqrestore(&ap->host->lock, flags); + +	/* +	 * Clear SError before executing a new command. +	 * +	 * TODO if we read a PM's registers now, we will throw away the task +	 * file values loaded into the shadow registers for this command. +	 * +	 * sata_dwc_scr_write and read can not be used here. Clearing the PM +	 * managed SError register for the disk needs to be done before the +	 * task file is loaded. +	 */ +	clear_serror(ap); +	ata_sff_exec_command(ap, tf); +} + +static void sata_dwc_bmdma_setup_by_tag(struct ata_queued_cmd *qc, u8 tag) +{ +	sata_dwc_exec_command_by_tag(qc->ap, &qc->tf, tag, +				     SATA_DWC_CMD_ISSUED_PENDING); +} + +static void sata_dwc_bmdma_setup(struct ata_queued_cmd *qc) +{ +	u8 tag = qc->tag; + +	dwc_port_dbg(qc->ap, "%s\n", __func__); +	if (ata_is_ncq(qc->tf.protocol)) { +		dwc_dev_vdbg(qc->ap->dev, "%s: ap->link.sactive=0x%08x tag=%d\n", +			__func__, qc->ap->link.sactive, tag); +	} else { +		tag = 0; +	} + +	sata_dwc_bmdma_setup_by_tag(qc, tag); +} + +static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag) +{ +	volatile int start_dma; +	u32 reg, dma_chan; +	struct sata_dwc_device *hsdev = HSDEV_FROM_QC(qc); +	struct ata_port *ap = qc->ap; +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); +	int dir = qc->dma_dir; +	dma_chan = hsdevp->dma_chan[tag]; + +	/* Used for ata_bmdma_start(qc) -- we are not BMDMA compatible */ + +	if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_NOT) { +		start_dma = 1; +		if (dir == DMA_TO_DEVICE) +			hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_TX; +		else +			hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_RX; +	} else { +		dev_err(ap->dev, "%s: Command not pending cmd_issued=%d " +			"(tag=%d) - DMA NOT started\n", __func__, +			hsdevp->cmd_issued[tag], tag); +		start_dma = 0; +	} + +	dwc_dev_dbg(ap->dev, "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s " +			"start_dma? %x\n", __func__, qc, tag, qc->tf.command, +			dir_2_txt(qc->dma_dir), start_dma); +	sata_dwc_tf_dump(hsdev->dev, &(qc->tf)); + +	// Start DMA transfer +	if (start_dma) { +		reg = sata_dwc_core_scr_read(ap, SCR_ERROR); +		if (unlikely(reg & SATA_DWC_SERR_ERR_BITS)) { +			dev_err(ap->dev, "%s: ****** SError=0x%08x ******\n", +				__func__, reg); +			//sata_async_notification(ap); +			//return; +		} + +		// Set DMA control registers +		if (dir == DMA_TO_DEVICE) +			out_le32(&hsdev->sata_dwc_regs->dmacr, +					SATA_DWC_DMACR_TXCHEN); +		else +			out_le32(&hsdev->sata_dwc_regs->dmacr, +					SATA_DWC_DMACR_RXCHEN); + +		dwc_dev_vdbg(ap->dev, "%s: setting DMACR: 0x%08x\n", __func__, in_le32(&hsdev->sata_dwc_regs->dmacr)); +		/* Enable AHB DMA transfer on the specified channel */ +		dma_dwc_xfer_start(dma_chan); +	} +} + + +static void sata_dwc_bmdma_start(struct ata_queued_cmd *qc) +{ +	u8 tag = qc->tag; + +	if (ata_is_ncq(qc->tf.protocol)) { +		dwc_dev_vdbg(qc->ap->dev, "%s: ap->link.sactive=0x%08x tag=%d\n", +			__func__, qc->ap->link.sactive, tag); +	} else { +		tag = 0; +	} + +	dwc_port_dbg(qc->ap, "%s, tag=0x%08x\n", __func__, tag); +	sata_dwc_bmdma_start_by_tag(qc, tag); +} + +/* + * Function : sata_dwc_qc_prep_by_tag + * arguments : ata_queued_cmd *qc, u8 tag + * Return value : None + * qc_prep for a particular queued command based on tag + */ +static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag) +{ +	struct ata_port *ap = qc->ap; +	int dma_chan; +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); +	int dir; + +	// DMA direction +	dir = qc->dma_dir; + +	if ((dir == DMA_NONE) || (qc->tf.protocol == ATA_PROT_PIO)) +		return; + +	dwc_dev_vdbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n", +		__func__, ap->port_no, dir_2_txt(dir), qc->n_elem); + +	// Setup DMA for transfer +	dma_chan = dma_dwc_xfer_setup(qc, hsdevp->llit[tag], +			hsdevp->llit_dma[tag], +			(void *__iomem)(&hsdev->sata_dwc_regs->dmadr)); + +	if (unlikely(dma_chan < 0)) { +		dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns err %d\n", +			__func__, dma_chan); +		return; +	} + +	hsdevp->dma_chan[tag] = dma_chan; +} + + + +/** + *	ata_sff_exec_command - issue ATA command to host controller + *	@ap: port to which command is being issued + *	@tf: ATA taskfile register set + * + *	Issues ATA command, with proper synchronization with interrupt + *	handler / other threads. + * + *	LOCKING: + *	spin_lock_irqsave(host lock) + */ +void sata_dwc_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) +{ +	iowrite8(tf->command, ap->ioaddr.command_addr); +	/*	If we have an mmio device with no ctl and no altstatus +	 *	method this will fail. No such devices are known to exist. +	 */ +	if (ap->ioaddr.altstatus_addr) +		ioread8(ap->ioaddr.altstatus_addr); +	ndelay(400); +} + +/** + *	sata_dwc_tf_to_host - issue ATA taskfile to host controller + *	@ap: port to which command is being issued + *	@tf: ATA taskfile register set + * + *	Issues ATA taskfile register set to ATA host controller, + *	with proper synchronization with interrupt handler and + *	other threads. + * + *	LOCKING: + *	spin_lock_irqsave(host lock) + */ +static inline void sata_dwc_tf_to_host(struct ata_port *ap, +				  const struct ata_taskfile *tf) +{ +	dwc_port_dbg(ap,"%s\n",__func__); +	ap->ops->sff_tf_load(ap, tf); +	sata_dwc_exec_command(ap, tf); +} + + +/* + * Process command queue issue + */ +static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) +{ +	struct ata_port *ap = qc->ap; +	int ret = 0; +	struct ata_eh_info *ehi; +	u32 scontrol, sstatus; +	scontrol = sata_dwc_core_scr_read(ap, SCR_CONTROL); + +	ehi = &ap->link.eh_info; +	/* +	 * Fix the problem when PMP card is unplugged from the SATA port. +	 * QC is still issued but no device present. Ignore the current QC. +	 * and pass error to error handler +	 */ +	sstatus = sata_dwc_core_scr_read(ap, SCR_STATUS); +	if ( sstatus == 0x0) { +		ata_port_printk(ap, KERN_INFO, "Detect connection lost while commands are executing --> ignore current command\n"); +		ata_ehi_hotplugged(ehi); +		ap->link.eh_context.i.action |= ATA_EH_RESET; +		return ret; +	} + +	// Set PMP field in the SCONTROL register +	if ( sata_pmp_attached(ap) ) +		sata_dwc_pmp_select(ap, qc->dev->link->pmp); + +#ifdef DEBUG_NCQ +	if (qc->tag > 0 || ap->link.sactive > 1) { +		dev_info(ap->dev, "%s ap id=%d cmd(0x%02x)=%s qc tag=%d prot=%s" +			" ap active_tag=0x%08x ap sactive=0x%08x\n", +			__func__, ap->print_id, qc->tf.command, +			ata_cmd_2_txt(&qc->tf), qc->tag, +			prot_2_txt(qc->tf.protocol), ap->link.active_tag, +			ap->link.sactive); +	} +#endif + +	// Process NCQ +	if (ata_is_ncq(qc->tf.protocol)) { +		dwc_link_dbg(qc->dev->link, "%s --> process NCQ , ap->link.active_tag=0x%08x, active_tag=0%08x\n", __func__, ap->link.active_tag, qc->tag); +		ap->link.active_tag = qc->tag; +		ap->ops->sff_tf_load(ap, &qc->tf); +		sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag, +					     SATA_DWC_CMD_ISSUED_PENDING); +	} else { +		dwc_link_dbg(qc->dev->link, "%s --> non NCQ process, ap->link.active_tag=%d, active_tag=0%08x\n", __func__, ap->link.active_tag, qc->tag); +		// Sync ata_port with qc->tag +		ap->link.active_tag = qc->tag; +		ret = ata_bmdma_qc_issue(qc); +	} + +	return ret; +} + +#if 0 +/* + * Function : sata_dwc_eng_timeout + * arguments : ata_port *ap + * Return value : None + * error handler for DMA time out + * ata_eng_timeout(ap) -- this does bmdma stuff which can not be done by this + * driver. SEE ALSO ata_qc_timeout(ap) + */ +static void sata_dwc_eng_timeout(struct ata_port *ap) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); +	struct ata_queued_cmd *qc; +	u8  tag; +	uint mask = 0x0; +	unsigned long flags; +	u32 serror, intpr, dma_ch; + +	tag = ap->link.active_tag; +	dma_ch = hsdevp->dma_chan[tag]; +	qc = ata_qc_from_tag(ap, tag); + +	dev_err(ap->dev, "%s: id=%d active_tag=%d qc=%p dma_chan=%d\n", +		__func__, ap->print_id, tag, qc, dma_ch); + +	intpr = in_le32(&hsdev->sata_dwc_regs->intpr); +	serror = sata_dwc_core_scr_read(ap, SCR_ERROR); + +	dev_err(ap->dev, "intpr=0x%08x serror=0x%08x\n", intpr, serror); + +	/* If there are no error bits set, can we just pass this on to eh? */ +	if (!(serror & SATA_DWC_SERR_ERR_BITS) && +	    !(intpr & SATA_DWC_INTPR_ERR)) { + +		spin_lock_irqsave(&ap->host->lock, flags); +		if (dma_dwc_channel_enabled(dma_ch)) +			dma_dwc_terminate_dma(ap, dma_ch); + +		hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_NONE; + +		/* clear active bit */ +		mask = (~(qcmd_tag_to_mask(tag))); +		hsdevp->sata_dwc_sactive_queued = hsdevp->sata_dwc_sactive_queued & mask; +		hsdevp->sata_dwc_sactive_issued = hsdevp->sata_dwc_sactive_issued & mask; + +		spin_unlock_irqrestore(&ap->host->lock, flags); +	} else { +		/* This is wrong, what really needs to be done is a reset. */ + +		spin_lock_irqsave(ap->lock, flags); + +		if (ata_is_dma(qc->tf.protocol)) { +			/* disable DMAC */ +			dma_dwc_terminate_dma(ap, dma_ch); +		} + +		spin_unlock_irqrestore(ap->lock, flags); +	} +	WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); +	if (qc->flags & ATA_QCFLAG_ACTIVE) { +		qc->err_mask |= AC_ERR_TIMEOUT; +		/* +		 * test-only: The original code (AMCC: 2.6.19) called +		 * ata_eng_timeout(ap) here. This function is not available +		 * anymore. So what to do now? +		 */ +	} +} +#endif +/* + * Function : sata_dwc_qc_prep + * arguments : ata_queued_cmd *qc + * Return value : None + * qc_prep for a particular queued command + */ +static void sata_dwc_qc_prep(struct ata_queued_cmd *qc) +{ +	u32 sactive; +	u8 tag = qc->tag; + +	 if ((qc->dma_dir == DMA_NONE) || (qc->tf.protocol == ATA_PROT_PIO)) +                return; + +#ifdef DEBUG_NCQ +	if (qc->tag > 0) { +		dev_info(qc->ap->dev, "%s: qc->tag=%d ap->active_tag=0x%08x\n", +			 __func__, qc->tag, qc->ap->link.active_tag); +	} +#endif + +	if (qc->tf.protocol == ATA_PROT_NCQ) { +		sactive = sata_dwc_core_scr_read(qc->ap, SCR_ACTIVE); +		sactive |= (0x00000001 << tag); +		sata_dwc_core_scr_write(qc->ap, SCR_ACTIVE, sactive); +		dwc_dev_vdbg(qc->ap->dev, "%s: tag=%d ap->link.sactive = 0x%08x " +			"sactive=0x%08x\n", __func__, tag, qc->ap->link.sactive, +			sactive); +	} else { +		tag = 0; +	} + +	sata_dwc_qc_prep_by_tag(qc, tag);	 +} + + + +static void sata_dwc_post_internal_cmd(struct ata_queued_cmd *qc) +{ +	if (qc->flags & ATA_QCFLAG_FAILED) +		ata_eh_freeze_port(qc->ap); +} + +static void sata_dwc_error_handler(struct ata_port *ap) +{ +	u32 serror; +	u32 intmr, errmr; +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); + +	serror = sata_dwc_core_scr_read(ap, SCR_ERROR); +	intmr = in_le32(&hsdev->sata_dwc_regs->intmr); +	errmr = in_le32(&hsdev->sata_dwc_regs->errmr); + +	//sata_dwc_dma_xfer_complete(ap,1); +	dwc_port_dbg(ap, "%s: SERROR=0x%08x, INTMR=0x%08x, ERRMR=0x%08x\n", __func__, serror, intmr, errmr); + +	dwc_port_vdbg(ap, "%s - sata_dwc_sactive_queued=0x%08x, sata_dwc_sactive_issued=0x%08x\n",__func__, hsdevp->sata_dwc_sactive_queued, hsdevp->sata_dwc_sactive_issued); +	dwc_port_vdbg(ap, "dmacr=0x%08x\n",in_le32(&(hsdev->sata_dwc_regs->dmacr))); +	dwc_port_vdbg(ap, "qc_active=0x%08x, qc_allocated=0x%08x, active_tag=%d\n", ap->qc_active, ap->qc_allocated, ap->link.active_tag); + +	sata_pmp_error_handler(ap); +} + +/* + * sata_dwc_check_status - Get value of the Status Register + * @ap: Port to check + * + * Output content of the status register (CDR7) + */ +u8 sata_dwc_check_status(struct ata_port *ap) +{ +	return ioread8(ap->ioaddr.status_addr); +} + + +/* + * Freeze the port by clear interrupt + * @ap: Port to freeze + */ +void sata_dwc_freeze(struct ata_port *ap) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); +	dwc_port_dbg(ap, "call %s ...\n",__func__); +	// turn IRQ off +	clear_intpr(hsdev); +	clear_serror(ap); +	out_le32(&hsdev->sata_dwc_regs->intmr, 0x0); +} + +/* + * Thaw the port by turning IRQ on + */ +void sata_dwc_thaw(struct ata_port *ap) +{ +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); + +	dwc_port_dbg(ap, "call %s ...\n",__func__); +	// Clear IRQ +	clear_intpr(hsdev); +	// Turn IRQ back on +	sata_dwc_enable_interrupts(hsdev); +} + + +/* + * scsi mid-layer and libata interface structures + */ +static struct scsi_host_template sata_dwc_sht = { +	ATA_NCQ_SHT(DRV_NAME), +	/* +	 * test-only: Currently this driver doesn't handle NCQ +	 * correctly. We enable NCQ but set the queue depth to a +	 * max of 1. This will get fixed in in a future release. +	 */ +//        .sg_tablesize           = LIBATA_MAX_PRD, +	.can_queue 		= ATA_DEF_QUEUE,	/* ATA_MAX_QUEUE */ +	.dma_boundary 		= ATA_DMA_BOUNDARY, +}; + + +static struct ata_port_operations sata_dwc_ops = { +	.inherits		= &sata_pmp_port_ops, +	.dev_config		= sata_dwc_dev_config, +	 +	.error_handler	= sata_dwc_error_handler, +	.softreset		= sata_dwc_softreset, +	.hardreset		= sata_dwc_hardreset, +	.pmp_softreset	= sata_dwc_softreset, +	.pmp_hardreset	= sata_dwc_pmp_hardreset, + +	.qc_defer		= sata_pmp_qc_defer_cmd_switch, +	.qc_prep		= sata_dwc_qc_prep, +	.qc_issue		= sata_dwc_qc_issue, +	.qc_fill_rtf	= ata_sff_qc_fill_rtf, + +	.scr_read		= sata_dwc_scr_read, +	.scr_write		= sata_dwc_scr_write, + +	.port_start		= sata_dwc_port_start, +	.port_stop		= sata_dwc_port_stop, + +	.bmdma_setup	= sata_dwc_bmdma_setup, +	.bmdma_start	= sata_dwc_bmdma_start, +	// Reuse some SFF functions +	.sff_check_status	= sata_dwc_check_status, +	.sff_tf_read	= ata_sff_tf_read, +	.sff_data_xfer	= ata_sff_data_xfer, +	.sff_tf_load	= ata_sff_tf_load, +	.sff_dev_select	= sata_dwc_dev_select, +	.sff_exec_command	= sata_dwc_exec_command, + +	.sff_irq_on		= sata_dwc_irq_on, +/*	.sff_irq_clear	= sata_dwc_irq_clear, +	.freeze			= sata_dwc_freeze, +	.thaw			= sata_dwc_thaw, +	.sff_irq_on		= ata_sff_irq_on, +	*/ +	.sff_irq_clear	= ata_bmdma_irq_clear, +	.freeze			= ata_sff_freeze, +	.thaw			= ata_sff_thaw, +	.pmp_attach		= sata_dwc_pmp_attach, +	.pmp_detach		= sata_dwc_pmp_detach, +	.post_internal_cmd	= sata_dwc_post_internal_cmd, + +	/* test-only: really needed? */ +	//.eng_timeout		= sata_dwc_eng_timeout, +}; + +static const struct ata_port_info sata_dwc_port_info[] = { +	{ +		/* +		 * test-only: Currently this driver doesn't handle NCQ +		 * correctly. So we disable NCQ here for now. To enable +		 * it ATA_FLAG_NCQ needs to be added to the flags below. +		 */ +		.flags		= ATA_FLAG_SATA | +				  ATA_FLAG_NCQ | +				  ATA_FLAG_PMP | ATA_FLAG_AN,  +		.pio_mask	= ATA_PIO4,	/* pio 0-4 */  +		.udma_mask	= ATA_UDMA6, +		.port_ops	= &sata_dwc_ops, +	}, +}; + +static int sata_dwc_probe(struct platform_device *ofdev) +{ +	struct sata_dwc_device *hsdev; +	u32 idr, versionr; +	char *ver = (char *)&versionr; +	u8 *base = NULL; +	int err = 0; +	int irq; +	struct ata_host *host; +	struct ata_port_info pi = sata_dwc_port_info[0]; +	const struct ata_port_info *ppi[] = { &pi, NULL }; +	struct device_node *np = ofdev->dev.of_node; +	const unsigned int *dma_channel; +	/* +	 * Check if device is enabled +	 */ +	if (!of_device_is_available(np)) { +		printk(KERN_INFO "%s: Port disabled via device-tree\n",  +			np->full_name); +		return 0; +	} + +	/* Allocate DWC SATA device */ +	hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL); +	if (hsdev == NULL) { +		dev_err(&ofdev->dev, "kmalloc failed for hsdev\n"); +		err = -ENOMEM; +		goto error; +	} + + +	// Identify SATA DMA channel used for the current SATA device +	dma_channel = of_get_property(np, "dma-channel", NULL); +	if ( dma_channel ) { +		dev_notice(&ofdev->dev, "Gettting DMA channel %d\n", *dma_channel); +		hsdev->dma_channel = *dma_channel; +	} else +		hsdev->dma_channel = 0; + +	/* Ioremap SATA registers */ +	base = of_iomap(np, 0); +	if (!base) { +		dev_err(&ofdev->dev, "ioremap failed for SATA register address\n"); +		err = -ENODEV; +		goto error_kmalloc; +	} +	hsdev->reg_base = base; +	dwc_dev_vdbg(&ofdev->dev, "ioremap done for SATA register address\n"); + +	/* Synopsys DWC SATA specific Registers */ +	hsdev->sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET); + +	/* Allocate and fill host */ +	host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_DWC_MAX_PORTS); +	if (!host) { +		dev_err(&ofdev->dev, "ata_host_alloc_pinfo failed\n"); +		err = -ENOMEM; +		goto error_iomap; +	} + +	host->private_data = hsdev; + +	/* Setup port */ +	host->ports[0]->ioaddr.cmd_addr = base; +	host->ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET; +	hsdev->scr_base = (u8 *)(base + SATA_DWC_SCR_OFFSET); +	sata_dwc_setup_port(&host->ports[0]->ioaddr, (unsigned long)base); + +	/* Read the ID and Version Registers */ +	idr = in_le32(&hsdev->sata_dwc_regs->idr); +	versionr = in_le32(&hsdev->sata_dwc_regs->versionr); +	dev_notice(&ofdev->dev, "id %d, controller version %c.%c%c\n", +		   idr, ver[0], ver[1], ver[2]); + +	/* Get SATA DMA interrupt number */ +	irq = irq_of_parse_and_map(np, 1); +	if (irq == NO_IRQ) { +		dev_err(&ofdev->dev, "no SATA DMA irq\n"); +		err = -ENODEV; +		goto error_out; +	} + +	/* Get physical SATA DMA register base address */ +	if (!sata_dma_regs) { +	sata_dma_regs = of_iomap(np, 1); +		if (!sata_dma_regs) { +			dev_err(&ofdev->dev, "ioremap failed for AHBDMA register address\n"); +			err = -ENODEV; +			goto error_out; +		} +	} +	/* Save dev for later use in dev_xxx() routines */ +	hsdev->dev = &ofdev->dev; + +	/* Init glovbal dev list */ +	dwc_dev_list[hsdev->dma_channel] = hsdev; + +	/* Initialize AHB DMAC */ +	hsdev->irq_dma = irq; +	dma_dwc_init(hsdev); +	dma_register_interrupt(hsdev); + + +	/* Enable SATA Interrupts */ +	sata_dwc_enable_interrupts(hsdev); + +	/* Get SATA interrupt number */ +	irq = irq_of_parse_and_map(np, 0); +	if (irq == NO_IRQ) { +		dev_err(&ofdev->dev, "no SATA irq\n"); +		err = -ENODEV; +		goto error_out; +	} + +	/* +	 * Now, register with libATA core, this will also initiate the +	 * device discovery process, invoking our port_start() handler & +	 * error_handler() to execute a dummy Softreset EH session +	 */ +	ata_host_activate(host, irq, sata_dwc_isr, 0, &sata_dwc_sht); + +	dev_set_drvdata(&ofdev->dev, host); + +	/* Everything is fine */ +	return 0; + +error_out: +	/* Free SATA DMA resources */ +	dma_dwc_exit(hsdev); + +error_iomap: +	iounmap(base); +error_kmalloc: +	kfree(hsdev); +error: +	return err; +} + +static int sata_dwc_remove(struct platform_device *ofdev) +{ +	struct device *dev = &ofdev->dev; +	struct ata_host *host = dev_get_drvdata(dev); +	struct sata_dwc_device *hsdev = host->private_data; + +	ata_host_detach(host); + +	dev_set_drvdata(dev, NULL); + +	/* Free SATA DMA resources */ +	dma_dwc_exit(hsdev); + +	iounmap(hsdev->reg_base); +	kfree(hsdev); +	kfree(host); + +	dwc_dev_vdbg(&ofdev->dev, "done\n"); + +	return 0; +} + +static const struct of_device_id sata_dwc_match[] = { +	{ .compatible = "amcc,sata-460ex", }, +	{ .compatible = "amcc,sata-apm82181", }, +	{} +}; +MODULE_DEVICE_TABLE(of, sata_dwc_match); + +static struct platform_driver sata_dwc_driver = { +	.driver = { +		.name = DRV_NAME, +		.owner = THIS_MODULE, +		.of_match_table = sata_dwc_match, +	}, +	.probe = sata_dwc_probe, +	.remove = sata_dwc_remove, +}; + +module_platform_driver(sata_dwc_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mark Miesfeld <mmiesfeld@amcc.com>"); +MODULE_DESCRIPTION("DesignWare Cores SATA controller driver"); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index b0214d00d50..616a6d2ac20 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -6,7 +6,7 @@   * Author: Ashish Kalra <ashish.kalra@freescale.com>   * Li Yang <leoli@freescale.com>   * - * Copyright (c) 2006-2007 Freescale Semiconductor, Inc. + * Copyright (c) 2006-2007, 2011-2012 Freescale Semiconductor, Inc.   *   * This program is free software; you can redistribute  it and/or modify it   * under  the terms of  the GNU General  Public License as published by the @@ -24,8 +24,19 @@  #include <scsi/scsi_cmnd.h>  #include <linux/libata.h>  #include <asm/io.h> +#include <linux/of_address.h> +#include <linux/of_irq.h>  #include <linux/of_platform.h> +static unsigned int intr_coalescing_count; +module_param(intr_coalescing_count, int, S_IRUGO); +MODULE_PARM_DESC(intr_coalescing_count, +				 "INT coalescing count threshold (1..31)"); + +static unsigned int intr_coalescing_ticks; +module_param(intr_coalescing_ticks, int, S_IRUGO); +MODULE_PARM_DESC(intr_coalescing_ticks, +				 "INT coalescing timer threshold in AHB ticks");  /* Controller information */  enum {  	SATA_FSL_QUEUE_DEPTH	= 16, @@ -33,8 +44,7 @@ enum {  	SATA_FSL_MAX_PRD_USABLE	= SATA_FSL_MAX_PRD - 1,  	SATA_FSL_MAX_PRD_DIRECT	= 16,	/* Direct PRDT entries */ -	SATA_FSL_HOST_FLAGS	= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | +	SATA_FSL_HOST_FLAGS	= (ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |  				ATA_FLAG_PMP | ATA_FLAG_NCQ | ATA_FLAG_AN),  	SATA_FSL_MAX_CMDS	= SATA_FSL_QUEUE_DEPTH, @@ -43,7 +53,7 @@ enum {  	/*  	 * SATA-FSL host controller supports a max. of (15+1) direct PRDEs, and -	 * chained indirect PRDEs upto a max count of 63. +	 * chained indirect PRDEs up to a max count of 63.  	 * We are allocating an array of 63 PRDEs contiguously, but PRDE#15 will  	 * be setup as an indirect descriptor, pointing to it's next  	 * (contiguous) PRDE. Though chained indirect PRDE arrays are @@ -84,6 +94,16 @@ enum {  };  /* + * Interrupt Coalescing Control Register bitdefs  */ +enum { +	ICC_MIN_INT_COUNT_THRESHOLD	= 1, +	ICC_MAX_INT_COUNT_THRESHOLD	= ((1 << 5) - 1), +	ICC_MIN_INT_TICKS_THRESHOLD	= 0, +	ICC_MAX_INT_TICKS_THRESHOLD	= ((1 << 19) - 1), +	ICC_SAFE_INT_TICKS		= 1, +}; + +/*  * Host Controller command register set - per port  */  enum { @@ -105,6 +125,7 @@ enum {  	ONLINE = (1 << 31),  	GOING_OFFLINE = (1 << 30),  	BIST_ERR = (1 << 29), +	CLEAR_ERROR = (1 << 27),  	FATAL_ERR_HC_MASTER_ERR = (1 << 18),  	FATAL_ERR_PARITY_ERR_TX = (1 << 17), @@ -125,6 +146,7 @@ enum {  	    FATAL_ERR_CRC_ERR_RX |  	    FATAL_ERR_FIFO_OVRFL_TX | FATAL_ERR_FIFO_OVRFL_RX, +	INT_ON_DATA_LENGTH_MISMATCH = (1 << 12),  	INT_ON_FATAL_ERR = (1 << 5),  	INT_ON_PHYRDY_CHG = (1 << 4), @@ -141,6 +163,7 @@ enum {  	 */  	HCONTROL_ONLINE_PHY_RST = (1 << 31),  	HCONTROL_FORCE_OFFLINE = (1 << 30), +	HCONTROL_LEGACY = (1 << 28),  	HCONTROL_PARITY_PROT_MOD = (1 << 14),  	HCONTROL_DPATH_PARITY = (1 << 12),  	HCONTROL_SNOOP_ENABLE = (1 << 10), @@ -158,7 +181,8 @@ enum {  	    IE_ON_SINGL_DEVICE_ERR | IE_ON_CMD_COMPLETE,  	EXT_INDIRECT_SEG_PRD_FLAG = (1 << 31), -	DATA_SNOOP_ENABLE = (1 << 22), +	DATA_SNOOP_ENABLE_V1 = (1 << 22), +	DATA_SNOOP_ENABLE_V2 = (1 << 28),  };  /* @@ -186,6 +210,11 @@ enum {  	COMMANDSTAT = 0x20,  }; +/* TRANSCFG (transport-layer) configuration control */ +enum { +	TRANSCFG_RX_WATER_MARK = (1 << 4), +}; +  /* PHY (link-layer) configuration control */  enum {  	PHY_BIST_ENABLE = 0x01, @@ -256,8 +285,110 @@ struct sata_fsl_host_priv {  	void __iomem *ssr_base;  	void __iomem *csr_base;  	int irq; +	int data_snoop; +	struct device_attribute intr_coalescing; +	struct device_attribute rx_watermark;  }; +static void fsl_sata_set_irq_coalescing(struct ata_host *host, +		unsigned int count, unsigned int ticks) +{ +	struct sata_fsl_host_priv *host_priv = host->private_data; +	void __iomem *hcr_base = host_priv->hcr_base; +	unsigned long flags; + +	if (count > ICC_MAX_INT_COUNT_THRESHOLD) +		count = ICC_MAX_INT_COUNT_THRESHOLD; +	else if (count < ICC_MIN_INT_COUNT_THRESHOLD) +		count = ICC_MIN_INT_COUNT_THRESHOLD; + +	if (ticks > ICC_MAX_INT_TICKS_THRESHOLD) +		ticks = ICC_MAX_INT_TICKS_THRESHOLD; +	else if ((ICC_MIN_INT_TICKS_THRESHOLD == ticks) && +			(count > ICC_MIN_INT_COUNT_THRESHOLD)) +		ticks = ICC_SAFE_INT_TICKS; + +	spin_lock_irqsave(&host->lock, flags); +	iowrite32((count << 24 | ticks), hcr_base + ICC); + +	intr_coalescing_count = count; +	intr_coalescing_ticks = ticks; +	spin_unlock_irqrestore(&host->lock, flags); + +	DPRINTK("interrupt coalescing, count = 0x%x, ticks = %x\n", +			intr_coalescing_count, intr_coalescing_ticks); +	DPRINTK("ICC register status: (hcr base: 0x%x) = 0x%x\n", +			hcr_base, ioread32(hcr_base + ICC)); +} + +static ssize_t fsl_sata_intr_coalescing_show(struct device *dev, +		struct device_attribute *attr, char *buf) +{ +	return sprintf(buf, "%d	%d\n", +			intr_coalescing_count, intr_coalescing_ticks); +} + +static ssize_t fsl_sata_intr_coalescing_store(struct device *dev, +		struct device_attribute *attr, +		const char *buf, size_t count) +{ +	unsigned int coalescing_count,	coalescing_ticks; + +	if (sscanf(buf, "%d%d", +				&coalescing_count, +				&coalescing_ticks) != 2) { +		printk(KERN_ERR "fsl-sata: wrong parameter format.\n"); +		return -EINVAL; +	} + +	fsl_sata_set_irq_coalescing(dev_get_drvdata(dev), +			coalescing_count, coalescing_ticks); + +	return strlen(buf); +} + +static ssize_t fsl_sata_rx_watermark_show(struct device *dev, +		struct device_attribute *attr, char *buf) +{ +	unsigned int rx_watermark; +	unsigned long flags; +	struct ata_host *host = dev_get_drvdata(dev); +	struct sata_fsl_host_priv *host_priv = host->private_data; +	void __iomem *csr_base = host_priv->csr_base; + +	spin_lock_irqsave(&host->lock, flags); +	rx_watermark = ioread32(csr_base + TRANSCFG); +	rx_watermark &= 0x1f; + +	spin_unlock_irqrestore(&host->lock, flags); +	return sprintf(buf, "%d\n", rx_watermark); +} + +static ssize_t fsl_sata_rx_watermark_store(struct device *dev, +		struct device_attribute *attr, +		const char *buf, size_t count) +{ +	unsigned int rx_watermark; +	unsigned long flags; +	struct ata_host *host = dev_get_drvdata(dev); +	struct sata_fsl_host_priv *host_priv = host->private_data; +	void __iomem *csr_base = host_priv->csr_base; +	u32 temp; + +	if (sscanf(buf, "%d", &rx_watermark) != 1) { +		printk(KERN_ERR "fsl-sata: wrong parameter format.\n"); +		return -EINVAL; +	} + +	spin_lock_irqsave(&host->lock, flags); +	temp = ioread32(csr_base + TRANSCFG); +	temp &= 0xffffffe0; +	iowrite32(temp | rx_watermark, csr_base + TRANSCFG); + +	spin_unlock_irqrestore(&host->lock, flags); +	return strlen(buf); +} +  static inline unsigned int sata_fsl_tag(unsigned int tag,  					void __iomem *hcr_base)  { @@ -308,7 +439,8 @@ static void sata_fsl_setup_cmd_hdr_entry(struct sata_fsl_port_priv *pp,  }  static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc, -				     u32 *ttl, dma_addr_t cmd_desc_paddr) +				     u32 *ttl, dma_addr_t cmd_desc_paddr, +				     int data_snoop)  {  	struct scatterlist *sg;  	unsigned int num_prde = 0; @@ -338,13 +470,12 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,  			(unsigned long long)sg_addr, sg_len);  		/* warn if each s/g element is not dword aligned */ -		if (sg_addr & 0x03) -			ata_port_printk(qc->ap, KERN_ERR, -					"s/g addr unaligned : 0x%llx\n", -					(unsigned long long)sg_addr); -		if (sg_len & 0x03) -			ata_port_printk(qc->ap, KERN_ERR, -					"s/g len unaligned : 0x%x\n", sg_len); +		if (unlikely(sg_addr & 0x03)) +			ata_port_err(qc->ap, "s/g addr unaligned : 0x%llx\n", +				     (unsigned long long)sg_addr); +		if (unlikely(sg_len & 0x03)) +			ata_port_err(qc->ap, "s/g len unaligned : 0x%x\n", +				     sg_len);  		if (num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1) &&  		    sg_next(sg) != NULL) { @@ -358,8 +489,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,  		ttl_dwords += sg_len;  		prd->dba = cpu_to_le32(sg_addr); -		prd->ddc_and_ext = -		    cpu_to_le32(DATA_SNOOP_ENABLE | (sg_len & ~0x03)); +		prd->ddc_and_ext = cpu_to_le32(data_snoop | (sg_len & ~0x03));  		VPRINTK("sg_fill, ttl=%d, dba=0x%x, ddc=0x%x\n",  			ttl_dwords, prd->dba, prd->ddc_and_ext); @@ -374,7 +504,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,  		/* set indirect extension flag along with indirect ext. size */  		prd_ptr_to_indirect_ext->ddc_and_ext =  		    cpu_to_le32((EXT_INDIRECT_SEG_PRD_FLAG | -				 DATA_SNOOP_ENABLE | +				 data_snoop |  				 (indirect_ext_segment_sz & ~0x03)));  	} @@ -417,7 +547,8 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)  	if (qc->flags & ATA_QCFLAG_DMAMAP)  		num_prde = sata_fsl_fill_sg(qc, (void *)cd, -					    &ttl_dwords, cd_paddr); +					    &ttl_dwords, cd_paddr, +					    host_priv->data_snoop);  	if (qc->tf.protocol == ATA_PROT_NCQ)  		desc_info |= FPDMA_QUEUED_CMD; @@ -643,21 +774,6 @@ static int sata_fsl_port_start(struct ata_port *ap)  	VPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL));  	VPRINTK("CHBA  = 0x%x\n", ioread32(hcr_base + CHBA)); -#ifdef CONFIG_MPC8315_DS -	/* -	 * Workaround for 8315DS board 3gbps link-up issue, -	 * currently limit SATA port to GEN1 speed -	 */ -	sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp); -	temp &= ~(0xF << 4); -	temp |= (0x1 << 4); -	sata_fsl_scr_write(&ap->link, SCR_CONTROL, temp); - -	sata_fsl_scr_read(&ap->link, SCR_CONTROL, &temp); -	dev_printk(KERN_WARNING, dev, "scr_control, speed limited to %x\n", -			temp); -#endif -  	return 0;  } @@ -733,8 +849,7 @@ try_offline_again:  				 1, 500);  	if (temp & ONLINE) { -		ata_port_printk(ap, KERN_ERR, -				"Hardreset failed, not off-lined %d\n", i); +		ata_port_err(ap, "Hardreset failed, not off-lined %d\n", i);  		/*  		 * Try to offline controller atleast twice @@ -770,8 +885,7 @@ try_offline_again:  	temp = ata_wait_register(ap, hcr_base + HSTATUS, ONLINE, 0, 1, 500);  	if (!(temp & ONLINE)) { -		ata_port_printk(ap, KERN_ERR, -				"Hardreset failed, not on-lined\n"); +		ata_port_err(ap, "Hardreset failed, not on-lined\n");  		goto err;  	} @@ -787,9 +901,8 @@ try_offline_again:  	temp = ata_wait_register(ap, hcr_base + HSTATUS, 0xFF, 0, 1, 500);  	if ((!(temp & 0x10)) || ata_link_offline(link)) { -		ata_port_printk(ap, KERN_WARNING, -				"No Device OR PHYRDY change,Hstatus = 0x%x\n", -				ioread32(hcr_base + HSTATUS)); +		ata_port_warn(ap, "No Device OR PHYRDY change,Hstatus = 0x%x\n", +			      ioread32(hcr_base + HSTATUS));  		*class = ATA_DEV_NONE;  		return 0;  	} @@ -802,13 +915,12 @@ try_offline_again:  			500, jiffies_to_msecs(deadline - start_jiffies));  	if ((temp & 0xFF) != 0x18) { -		ata_port_printk(ap, KERN_WARNING, "No Signature Update\n"); +		ata_port_warn(ap, "No Signature Update\n");  		*class = ATA_DEV_NONE;  		goto do_followup_srst;  	} else { -		ata_port_printk(ap, KERN_INFO, -				"Signature Update detected @ %d msecs\n", -				jiffies_to_msecs(jiffies - start_jiffies)); +		ata_port_info(ap, "Signature Update detected @ %d msecs\n", +			      jiffies_to_msecs(jiffies - start_jiffies));  		*class = sata_fsl_dev_classify(ap);  		return 0;  	} @@ -883,7 +995,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,  	temp = ata_wait_register(ap, CQ + hcr_base, 0x1, 0x1, 1, 5000);  	if (temp & 0x1) { -		ata_port_printk(ap, KERN_WARNING, "ATA_SRST issue failed\n"); +		ata_port_warn(ap, "ATA_SRST issue failed\n");  		DPRINTK("Softreset@5000,CQ=0x%x,CA=0x%x,CC=0x%x\n",  			ioread32(CQ + hcr_base), @@ -900,7 +1012,7 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,  	ata_msleep(ap, 1);  	/* -	 * SATA device enters reset state after receving a Control register +	 * SATA device enters reset state after receiving a Control register  	 * FIS with SRST bit asserted and it awaits another H2D Control reg.  	 * FIS with SRST bit cleared, then the device does internal diags &  	 * initialization, followed by indicating it's initialization status @@ -1040,12 +1152,15 @@ static void sata_fsl_error_intr(struct ata_port *ap)  		/* find out the offending link and qc */  		if (ap->nr_pmp_links) { +			unsigned int dev_num; +  			dereg = ioread32(hcr_base + DE);  			iowrite32(dereg, hcr_base + DE);  			iowrite32(cereg, hcr_base + CE); -			if (dereg < ap->nr_pmp_links) { -				link = &ap->pmp_link[dereg]; +			dev_num = ffs(dereg) - 1; +			if (dev_num < ap->nr_pmp_links && dereg != 0) { +				link = &ap->pmp_link[dev_num];  				ehi = &link->eh_info;  				qc = ata_qc_from_tag(ap, link->active_tag);  				/* @@ -1100,25 +1215,54 @@ static void sata_fsl_host_intr(struct ata_port *ap)  	u32 hstatus, done_mask = 0;  	struct ata_queued_cmd *qc;  	u32 SError; +	u32 tag; +	u32 status_mask = INT_ON_ERROR;  	hstatus = ioread32(hcr_base + HSTATUS);  	sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError); +	/* Read command completed register */ +	done_mask = ioread32(hcr_base + CC); + +	/* Workaround for data length mismatch errata */ +	if (unlikely(hstatus & INT_ON_DATA_LENGTH_MISMATCH)) { +		for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { +			qc = ata_qc_from_tag(ap, tag); +			if (qc && ata_is_atapi(qc->tf.protocol)) { +				u32 hcontrol; +				/* Set HControl[27] to clear error registers */ +				hcontrol = ioread32(hcr_base + HCONTROL); +				iowrite32(hcontrol | CLEAR_ERROR, +						hcr_base + HCONTROL); + +				/* Clear HControl[27] */ +				iowrite32(hcontrol & ~CLEAR_ERROR, +						hcr_base + HCONTROL); + +				/* Clear SError[E] bit */ +				sata_fsl_scr_write(&ap->link, SCR_ERROR, +						SError); + +				/* Ignore fatal error and device error */ +				status_mask &= ~(INT_ON_SINGL_DEVICE_ERR +						| INT_ON_FATAL_ERR); +				break; +			} +		} +	} +  	if (unlikely(SError & 0xFFFF0000)) {  		DPRINTK("serror @host_intr : 0x%x\n", SError);  		sata_fsl_error_intr(ap);  	} -	if (unlikely(hstatus & INT_ON_ERROR)) { +	if (unlikely(hstatus & status_mask)) {  		DPRINTK("error interrupt!!\n");  		sata_fsl_error_intr(ap);  		return;  	} -	/* Read command completed register */ -	done_mask = ioread32(hcr_base + CC); -  	VPRINTK("Status of all queues :\n");  	VPRINTK("done_mask/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n",  		done_mask, @@ -1192,8 +1336,7 @@ static irqreturn_t sata_fsl_interrupt(int irq, void *dev_instance)  	if (ap) {  		sata_fsl_host_intr(ap);  	} else { -		dev_printk(KERN_WARNING, host->dev, -			   "interrupt on disabled port 0\n"); +		dev_warn(host->dev, "interrupt on disabled port 0\n");  	}  	iowrite32(interrupt_enables, hcr_base + HSTATUS); @@ -1220,6 +1363,10 @@ static int sata_fsl_init_controller(struct ata_host *host)  	 * part of the port_start() callback  	 */ +	/* sata controller to operate in enterprise mode */ +	temp = ioread32(hcr_base + HCONTROL); +	iowrite32(temp & ~HCONTROL_LEGACY, hcr_base + HCONTROL); +  	/* ack. any pending IRQs for this controller/port */  	temp = ioread32(hcr_base + HSTATUS);  	if (temp & 0x3F) @@ -1237,6 +1384,13 @@ static int sata_fsl_init_controller(struct ata_host *host)  	iowrite32(0x00000FFFF, hcr_base + CE);  	iowrite32(0x00000FFFF, hcr_base + DE); + 	/* +	 * reset the number of command complete bits which will cause the +	 * interrupt to be signaled +	 */ +	fsl_sata_set_irq_coalescing(host, intr_coalescing_count, +			intr_coalescing_ticks); +  	/*  	 * host controller will be brought on-line, during xx_port_start()  	 * callback, that should also initiate the OOB, COMINIT sequence @@ -1293,8 +1447,7 @@ static const struct ata_port_info sata_fsl_port_info[] = {  	 },  }; -static int sata_fsl_probe(struct platform_device *ofdev, -			const struct of_device_id *match) +static int sata_fsl_probe(struct platform_device *ofdev)  {  	int retval = -ENXIO;  	void __iomem *hcr_base = NULL; @@ -1302,13 +1455,13 @@ static int sata_fsl_probe(struct platform_device *ofdev,  	void __iomem *csr_base = NULL;  	struct sata_fsl_host_priv *host_priv = NULL;  	int irq; -	struct ata_host *host; +	struct ata_host *host = NULL; +	u32 temp;  	struct ata_port_info pi = sata_fsl_port_info[0];  	const struct ata_port_info *ppi[] = { &pi, NULL }; -	dev_printk(KERN_INFO, &ofdev->dev, -		   "Sata FSL Platform/CSB Driver init\n"); +	dev_info(&ofdev->dev, "Sata FSL Platform/CSB Driver init\n");  	hcr_base = of_iomap(ofdev->dev.of_node, 0);  	if (!hcr_base) @@ -1317,6 +1470,12 @@ static int sata_fsl_probe(struct platform_device *ofdev,  	ssr_base = hcr_base + 0x100;  	csr_base = hcr_base + 0x140; +	if (!of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc8315-sata")) { +		temp = ioread32(csr_base + TRANSCFG); +		temp = temp & 0xffffffe0; +		iowrite32(temp | TRANSCFG_RX_WATER_MARK, csr_base + TRANSCFG); +	} +  	DPRINTK("@reset i/o = 0x%x\n", ioread32(csr_base + TRANSCFG));  	DPRINTK("sizeof(cmd_desc) = %d\n", sizeof(struct command_desc));  	DPRINTK("sizeof(#define cmd_desc) = %d\n", SATA_FSL_CMD_DESC_SIZE); @@ -1331,13 +1490,22 @@ static int sata_fsl_probe(struct platform_device *ofdev,  	irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);  	if (irq < 0) { -		dev_printk(KERN_ERR, &ofdev->dev, "invalid irq from platform\n"); +		dev_err(&ofdev->dev, "invalid irq from platform\n");  		goto error_exit_with_cleanup;  	}  	host_priv->irq = irq; +	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,pq-sata-v2")) +		host_priv->data_snoop = DATA_SNOOP_ENABLE_V2; +	else +		host_priv->data_snoop = DATA_SNOOP_ENABLE_V1; +  	/* allocate host structure */  	host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS); +	if (!host) { +		retval = -ENOMEM; +		goto error_exit_with_cleanup; +	}  	/* host->iomap is not used currently */  	host->private_data = host_priv; @@ -1353,28 +1521,51 @@ static int sata_fsl_probe(struct platform_device *ofdev,  	ata_host_activate(host, irq, sata_fsl_interrupt, SATA_FSL_IRQ_FLAG,  			  &sata_fsl_sht); -	dev_set_drvdata(&ofdev->dev, host); +	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); +	host_priv->intr_coalescing.attr.name = "intr_coalescing"; +	host_priv->intr_coalescing.attr.mode = S_IRUGO | S_IWUSR; +	retval = device_create_file(host->dev, &host_priv->intr_coalescing); +	if (retval) +		goto error_exit_with_cleanup; + +	host_priv->rx_watermark.show = fsl_sata_rx_watermark_show; +	host_priv->rx_watermark.store = fsl_sata_rx_watermark_store; +	sysfs_attr_init(&host_priv->rx_watermark.attr); +	host_priv->rx_watermark.attr.name = "rx_watermark"; +	host_priv->rx_watermark.attr.mode = S_IRUGO | S_IWUSR; +	retval = device_create_file(host->dev, &host_priv->rx_watermark); +	if (retval) { +		device_remove_file(&ofdev->dev, &host_priv->intr_coalescing); +		goto error_exit_with_cleanup; +	}  	return 0;  error_exit_with_cleanup: +	if (host) +		ata_host_detach(host); +  	if (hcr_base)  		iounmap(hcr_base); -	if (host_priv) -		kfree(host_priv); +	kfree(host_priv);  	return retval;  }  static int sata_fsl_remove(struct platform_device *ofdev)  { -	struct ata_host *host = dev_get_drvdata(&ofdev->dev); +	struct ata_host *host = platform_get_drvdata(ofdev);  	struct sata_fsl_host_priv *host_priv = host->private_data; -	ata_host_detach(host); +	device_remove_file(&ofdev->dev, &host_priv->intr_coalescing); +	device_remove_file(&ofdev->dev, &host_priv->rx_watermark); -	dev_set_drvdata(&ofdev->dev, NULL); +	ata_host_detach(host);  	irq_dispose_mapping(host_priv->irq);  	iounmap(host_priv->hcr_base); @@ -1383,16 +1574,16 @@ static int sata_fsl_remove(struct platform_device *ofdev)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int sata_fsl_suspend(struct platform_device *op, pm_message_t state)  { -	struct ata_host *host = dev_get_drvdata(&op->dev); +	struct ata_host *host = platform_get_drvdata(op);  	return ata_host_suspend(host, state);  }  static int sata_fsl_resume(struct platform_device *op)  { -	struct ata_host *host = dev_get_drvdata(&op->dev); +	struct ata_host *host = platform_get_drvdata(op);  	struct sata_fsl_host_priv *host_priv = host->private_data;  	int ret;  	void __iomem *hcr_base = host_priv->hcr_base; @@ -1401,14 +1592,19 @@ static int sata_fsl_resume(struct platform_device *op)  	ret = sata_fsl_init_controller(host);  	if (ret) { -		dev_printk(KERN_ERR, &op->dev, -			"Error initialize hardware\n"); +		dev_err(&op->dev, "Error initializing hardware\n");  		return ret;  	}  	/* Recovery the CHBA register in host controller cmd register set */  	iowrite32(pp->cmdslot_paddr & 0xffffffff, hcr_base + CHBA); +	iowrite32((ioread32(hcr_base + HCONTROL) +				| HCONTROL_ONLINE_PHY_RST +				| HCONTROL_SNOOP_ENABLE +				| HCONTROL_PMP_ATTACHED), +			hcr_base + HCONTROL); +  	ata_host_resume(host);  	return 0;  } @@ -1418,12 +1614,15 @@ static struct of_device_id fsl_sata_match[] = {  	{  		.compatible = "fsl,pq-sata",  	}, +	{ +		.compatible = "fsl,pq-sata-v2", +	},  	{},  };  MODULE_DEVICE_TABLE(of, fsl_sata_match); -static struct of_platform_driver fsl_sata_driver = { +static struct platform_driver fsl_sata_driver = {  	.driver = {  		.name = "fsl-sata",  		.owner = THIS_MODULE, @@ -1431,27 +1630,15 @@ static struct of_platform_driver fsl_sata_driver = {  	},  	.probe		= sata_fsl_probe,  	.remove		= sata_fsl_remove, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= sata_fsl_suspend,  	.resume		= sata_fsl_resume,  #endif  }; -static int __init sata_fsl_init(void) -{ -	of_register_platform_driver(&fsl_sata_driver); -	return 0; -} - -static void __exit sata_fsl_exit(void) -{ -	of_unregister_platform_driver(&fsl_sata_driver); -} +module_platform_driver(fsl_sata_driver);  MODULE_LICENSE("GPL");  MODULE_AUTHOR("Ashish Kalra, Freescale Semiconductor");  MODULE_DESCRIPTION("Freescale 3.0Gbps SATA controller low level driver");  MODULE_VERSION("1.10"); - -module_init(sata_fsl_init); -module_exit(sata_fsl_exit); diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c new file mode 100644 index 00000000000..65965cf5af0 --- /dev/null +++ b/drivers/ata/sata_highbank.c @@ -0,0 +1,650 @@ +/* + * Calxeda Highbank AHCI SATA platform driver + * Copyright 2012 Calxeda, Inc. + * + * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program.  If not, see <http://www.gnu.org/licenses/>. + */ +#include <linux/kernel.h> +#include <linux/gfp.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/spinlock.h> +#include <linux/device.h> +#include <linux/of_device.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/libata.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/export.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> + +#include "ahci.h" + +#define CPHY_MAP(dev, addr) ((((dev) & 0x1f) << 7) | (((addr) >> 9) & 0x7f)) +#define CPHY_ADDR(addr) (((addr) & 0x1ff) << 2) +#define SERDES_CR_CTL			0x80a0 +#define SERDES_CR_ADDR			0x80a1 +#define SERDES_CR_DATA			0x80a2 +#define CR_BUSY				0x0001 +#define CR_START			0x0001 +#define CR_WR_RDN			0x0002 +#define CPHY_TX_INPUT_STS		0x2001 +#define CPHY_RX_INPUT_STS		0x2002 +#define CPHY_SATA_TX_OVERRIDE		0x8000 +#define CPHY_SATA_RX_OVERRIDE	 	0x4000 +#define CPHY_TX_OVERRIDE		0x2004 +#define CPHY_RX_OVERRIDE		0x2005 +#define SPHY_LANE			0x100 +#define SPHY_HALF_RATE			0x0001 +#define CPHY_SATA_DPLL_MODE		0x0700 +#define CPHY_SATA_DPLL_SHIFT		8 +#define CPHY_SATA_DPLL_RESET		(1 << 11) +#define CPHY_SATA_TX_ATTEN		0x1c00 +#define CPHY_SATA_TX_ATTEN_SHIFT	10 +#define CPHY_PHY_COUNT			6 +#define CPHY_LANE_COUNT			4 +#define CPHY_PORT_COUNT			(CPHY_PHY_COUNT * CPHY_LANE_COUNT) + +static DEFINE_SPINLOCK(cphy_lock); +/* Each of the 6 phys can have up to 4 sata ports attached to i. Map 0-based + * sata ports to their phys and then to their lanes within the phys + */ +struct phy_lane_info { +	void __iomem *phy_base; +	u8 lane_mapping; +	u8 phy_devs; +	u8 tx_atten; +}; +static struct phy_lane_info port_data[CPHY_PORT_COUNT]; + +static DEFINE_SPINLOCK(sgpio_lock); +#define SCLOCK				0 +#define SLOAD				1 +#define SDATA				2 +#define SGPIO_PINS			3 +#define SGPIO_PORTS			8 + +struct ecx_plat_data { +	u32		n_ports; +	/* number of extra clocks that the SGPIO PIC controller expects */ +	u32		pre_clocks; +	u32		post_clocks; +	unsigned	sgpio_gpio[SGPIO_PINS]; +	u32		sgpio_pattern; +	u32		port_to_sgpio[SGPIO_PORTS]; +}; + +#define SGPIO_SIGNALS			3 +#define ECX_ACTIVITY_BITS		0x300000 +#define ECX_ACTIVITY_SHIFT		0 +#define ECX_LOCATE_BITS			0x80000 +#define ECX_LOCATE_SHIFT		1 +#define ECX_FAULT_BITS			0x400000 +#define ECX_FAULT_SHIFT			2 +static inline int sgpio_bit_shift(struct ecx_plat_data *pdata, u32 port, +				u32 shift) +{ +	return 1 << (3 * pdata->port_to_sgpio[port] + shift); +} + +static void ecx_parse_sgpio(struct ecx_plat_data *pdata, u32 port, u32 state) +{ +	if (state & ECX_ACTIVITY_BITS) +		pdata->sgpio_pattern |= sgpio_bit_shift(pdata, port, +						ECX_ACTIVITY_SHIFT); +	else +		pdata->sgpio_pattern &= ~sgpio_bit_shift(pdata, port, +						ECX_ACTIVITY_SHIFT); +	if (state & ECX_LOCATE_BITS) +		pdata->sgpio_pattern |= sgpio_bit_shift(pdata, port, +						ECX_LOCATE_SHIFT); +	else +		pdata->sgpio_pattern &= ~sgpio_bit_shift(pdata, port, +						ECX_LOCATE_SHIFT); +	if (state & ECX_FAULT_BITS) +		pdata->sgpio_pattern |= sgpio_bit_shift(pdata, port, +						ECX_FAULT_SHIFT); +	else +		pdata->sgpio_pattern &= ~sgpio_bit_shift(pdata, port, +						ECX_FAULT_SHIFT); +} + +/* + * Tell the LED controller that the signal has changed by raising the clock + * line for 50 uS and then lowering it for 50 uS. + */ +static void ecx_led_cycle_clock(struct ecx_plat_data *pdata) +{ +	gpio_set_value(pdata->sgpio_gpio[SCLOCK], 1); +	udelay(50); +	gpio_set_value(pdata->sgpio_gpio[SCLOCK], 0); +	udelay(50); +} + +static ssize_t ecx_transmit_led_message(struct ata_port *ap, u32 state, +					ssize_t size) +{ +	struct ahci_host_priv *hpriv =  ap->host->private_data; +	struct ecx_plat_data *pdata = hpriv->plat_data; +	struct ahci_port_priv *pp = ap->private_data; +	unsigned long flags; +	int pmp, i; +	struct ahci_em_priv *emp; +	u32 sgpio_out; + +	/* get the slot number from the message */ +	pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; +	if (pmp < EM_MAX_SLOTS) +		emp = &pp->em_priv[pmp]; +	else +		return -EINVAL; + +	if (!(hpriv->em_msg_type & EM_MSG_TYPE_LED)) +		return size; + +	spin_lock_irqsave(&sgpio_lock, flags); +	ecx_parse_sgpio(pdata, ap->port_no, state); +	sgpio_out = pdata->sgpio_pattern; +	for (i = 0; i < pdata->pre_clocks; i++) +		ecx_led_cycle_clock(pdata); + +	gpio_set_value(pdata->sgpio_gpio[SLOAD], 1); +	ecx_led_cycle_clock(pdata); +	gpio_set_value(pdata->sgpio_gpio[SLOAD], 0); +	/* +	 * bit-bang out the SGPIO pattern, by consuming a bit and then +	 * clocking it out. +	 */ +	for (i = 0; i < (SGPIO_SIGNALS * pdata->n_ports); i++) { +		gpio_set_value(pdata->sgpio_gpio[SDATA], sgpio_out & 1); +		sgpio_out >>= 1; +		ecx_led_cycle_clock(pdata); +	} +	for (i = 0; i < pdata->post_clocks; i++) +		ecx_led_cycle_clock(pdata); + +	/* save off new led state for port/slot */ +	emp->led_state = state; + +	spin_unlock_irqrestore(&sgpio_lock, flags); +	return size; +} + +static void highbank_set_em_messages(struct device *dev, +					struct ahci_host_priv *hpriv, +					struct ata_port_info *pi) +{ +	struct device_node *np = dev->of_node; +	struct ecx_plat_data *pdata = hpriv->plat_data; +	int i; +	int err; + +	for (i = 0; i < SGPIO_PINS; i++) { +		err = of_get_named_gpio(np, "calxeda,sgpio-gpio", i); +		if (IS_ERR_VALUE(err)) +			return; + +		pdata->sgpio_gpio[i] = err; +		err = gpio_request(pdata->sgpio_gpio[i], "CX SGPIO"); +		if (err) { +			pr_err("sata_highbank gpio_request %d failed: %d\n", +					i, err); +			return; +		} +		gpio_direction_output(pdata->sgpio_gpio[i], 1); +	} +	of_property_read_u32_array(np, "calxeda,led-order", +						pdata->port_to_sgpio, +						pdata->n_ports); +	if (of_property_read_u32(np, "calxeda,pre-clocks", &pdata->pre_clocks)) +		pdata->pre_clocks = 0; +	if (of_property_read_u32(np, "calxeda,post-clocks", +				&pdata->post_clocks)) +		pdata->post_clocks = 0; + +	/* store em_loc */ +	hpriv->em_loc = 0; +	hpriv->em_buf_sz = 4; +	hpriv->em_msg_type = EM_MSG_TYPE_LED; +	pi->flags |= ATA_FLAG_EM | ATA_FLAG_SW_ACTIVITY; +} + +static u32 __combo_phy_reg_read(u8 sata_port, u32 addr) +{ +	u32 data; +	u8 dev = port_data[sata_port].phy_devs; +	spin_lock(&cphy_lock); +	writel(CPHY_MAP(dev, addr), port_data[sata_port].phy_base + 0x800); +	data = readl(port_data[sata_port].phy_base + CPHY_ADDR(addr)); +	spin_unlock(&cphy_lock); +	return data; +} + +static void __combo_phy_reg_write(u8 sata_port, u32 addr, u32 data) +{ +	u8 dev = port_data[sata_port].phy_devs; +	spin_lock(&cphy_lock); +	writel(CPHY_MAP(dev, addr), port_data[sata_port].phy_base + 0x800); +	writel(data, port_data[sata_port].phy_base + CPHY_ADDR(addr)); +	spin_unlock(&cphy_lock); +} + +static void combo_phy_wait_for_ready(u8 sata_port) +{ +	while (__combo_phy_reg_read(sata_port, SERDES_CR_CTL) & CR_BUSY) +		udelay(5); +} + +static u32 combo_phy_read(u8 sata_port, u32 addr) +{ +	combo_phy_wait_for_ready(sata_port); +	__combo_phy_reg_write(sata_port, SERDES_CR_ADDR, addr); +	__combo_phy_reg_write(sata_port, SERDES_CR_CTL, CR_START); +	combo_phy_wait_for_ready(sata_port); +	return __combo_phy_reg_read(sata_port, SERDES_CR_DATA); +} + +static void combo_phy_write(u8 sata_port, u32 addr, u32 data) +{ +	combo_phy_wait_for_ready(sata_port); +	__combo_phy_reg_write(sata_port, SERDES_CR_ADDR, addr); +	__combo_phy_reg_write(sata_port, SERDES_CR_DATA, data); +	__combo_phy_reg_write(sata_port, SERDES_CR_CTL, CR_WR_RDN | CR_START); +} + +static void highbank_cphy_disable_overrides(u8 sata_port) +{ +	u8 lane = port_data[sata_port].lane_mapping; +	u32 tmp; +	if (unlikely(port_data[sata_port].phy_base == NULL)) +		return; +	tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); +	tmp &= ~CPHY_SATA_RX_OVERRIDE; +	combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); +} + +static void cphy_override_tx_attenuation(u8 sata_port, u32 val) +{ +	u8 lane = port_data[sata_port].lane_mapping; +	u32 tmp; + +	if (val & 0x8) +		return; + +	tmp = combo_phy_read(sata_port, CPHY_TX_INPUT_STS + lane * SPHY_LANE); +	tmp &= ~CPHY_SATA_TX_OVERRIDE; +	combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp); + +	tmp |= CPHY_SATA_TX_OVERRIDE; +	combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp); + +	tmp |= (val << CPHY_SATA_TX_ATTEN_SHIFT) & CPHY_SATA_TX_ATTEN; +	combo_phy_write(sata_port, CPHY_TX_OVERRIDE + lane * SPHY_LANE, tmp); +} + +static void cphy_override_rx_mode(u8 sata_port, u32 val) +{ +	u8 lane = port_data[sata_port].lane_mapping; +	u32 tmp; +	tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE); +	tmp &= ~CPHY_SATA_RX_OVERRIDE; +	combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); + +	tmp |= CPHY_SATA_RX_OVERRIDE; +	combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); + +	tmp &= ~CPHY_SATA_DPLL_MODE; +	tmp |= val << CPHY_SATA_DPLL_SHIFT; +	combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); + +	tmp |= CPHY_SATA_DPLL_RESET; +	combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); + +	tmp &= ~CPHY_SATA_DPLL_RESET; +	combo_phy_write(sata_port, CPHY_RX_OVERRIDE + lane * SPHY_LANE, tmp); + +	msleep(15); +} + +static void highbank_cphy_override_lane(u8 sata_port) +{ +	u8 lane = port_data[sata_port].lane_mapping; +	u32 tmp, k = 0; + +	if (unlikely(port_data[sata_port].phy_base == NULL)) +		return; +	do { +		tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + +						lane * SPHY_LANE); +	} while ((tmp & SPHY_HALF_RATE) && (k++ < 1000)); +	cphy_override_rx_mode(sata_port, 3); +	cphy_override_tx_attenuation(sata_port, port_data[sata_port].tx_atten); +} + +static int highbank_initialize_phys(struct device *dev, void __iomem *addr) +{ +	struct device_node *sata_node = dev->of_node; +	int phy_count = 0, phy, port = 0, i; +	void __iomem *cphy_base[CPHY_PHY_COUNT] = {}; +	struct device_node *phy_nodes[CPHY_PHY_COUNT] = {}; +	u32 tx_atten[CPHY_PORT_COUNT] = {}; + +	memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT); + +	do { +		u32 tmp; +		struct of_phandle_args phy_data; +		if (of_parse_phandle_with_args(sata_node, +				"calxeda,port-phys", "#phy-cells", +				port, &phy_data)) +			break; +		for (phy = 0; phy < phy_count; phy++) { +			if (phy_nodes[phy] == phy_data.np) +				break; +		} +		if (phy_nodes[phy] == NULL) { +			phy_nodes[phy] = phy_data.np; +			cphy_base[phy] = of_iomap(phy_nodes[phy], 0); +			if (cphy_base[phy] == NULL) { +				return 0; +			} +			phy_count += 1; +		} +		port_data[port].lane_mapping = phy_data.args[0]; +		of_property_read_u32(phy_nodes[phy], "phydev", &tmp); +		port_data[port].phy_devs = tmp; +		port_data[port].phy_base = cphy_base[phy]; +		of_node_put(phy_data.np); +		port += 1; +	} while (port < CPHY_PORT_COUNT); +	of_property_read_u32_array(sata_node, "calxeda,tx-atten", +				tx_atten, port); +	for (i = 0; i < port; i++) +		port_data[i].tx_atten = (u8) tx_atten[i]; +	return 0; +} + +/* + * The Calxeda SATA phy intermittently fails to bring up a link with Gen3 + * Retrying the phy hard reset can work around the issue, but the drive + * may fail again. In less than 150 out of 15000 test runs, it took more + * than 10 tries for the link to be established (but never more than 35). + * Triple the maximum observed retry count to provide plenty of margin for + * rare events and to guarantee that the link is established. + * + * Also, the default 2 second time-out on a failed drive is too long in + * this situation. The uboot implementation of the same driver function + * uses a much shorter time-out period and never experiences a time out + * issue. Reducing the time-out to 500ms improves the responsiveness. + * The other timing constants were kept the same as the stock AHCI driver. + * This change was also tested 15000 times on 24 drives and none of them + * experienced a time out. + */ +static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class, +				unsigned long deadline) +{ +	static const unsigned long timing[] = { 5, 100, 500}; +	struct ata_port *ap = link->ap; +	struct ahci_port_priv *pp = ap->private_data; +	struct ahci_host_priv *hpriv = ap->host->private_data; +	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; +	struct ata_taskfile tf; +	bool online; +	u32 sstatus; +	int rc; +	int retry = 100; + +	ahci_stop_engine(ap); + +	/* clear D2H reception area to properly wait for D2H FIS */ +	ata_tf_init(link->device, &tf); +	tf.command = ATA_BUSY; +	ata_tf_to_fis(&tf, 0, 0, d2h_fis); + +	do { +		highbank_cphy_disable_overrides(link->ap->port_no); +		rc = sata_link_hardreset(link, timing, deadline, &online, NULL); +		highbank_cphy_override_lane(link->ap->port_no); + +		/* If the status is 1, we are connected, but the link did not +		 * come up. So retry resetting the link again. +		 */ +		if (sata_scr_read(link, SCR_STATUS, &sstatus)) +			break; +		if (!(sstatus & 0x3)) +			break; +	} while (!online && retry--); + +	hpriv->start_engine(ap); + +	if (online) +		*class = ahci_dev_classify(ap); + +	return rc; +} + +static struct ata_port_operations ahci_highbank_ops = { +	.inherits		= &ahci_ops, +	.hardreset		= ahci_highbank_hardreset, +	.transmit_led_message   = ecx_transmit_led_message, +}; + +static const struct ata_port_info ahci_highbank_port_info = { +	.flags          = AHCI_FLAG_COMMON, +	.pio_mask       = ATA_PIO4, +	.udma_mask      = ATA_UDMA6, +	.port_ops       = &ahci_highbank_ops, +}; + +static struct scsi_host_template ahci_highbank_platform_sht = { +	AHCI_SHT("sata_highbank"), +}; + +static const struct of_device_id ahci_of_match[] = { +	{ .compatible = "calxeda,hb-ahci" }, +	{}, +}; +MODULE_DEVICE_TABLE(of, ahci_of_match); + +static int ahci_highbank_probe(struct platform_device *pdev) +{ +	struct device *dev = &pdev->dev; +	struct ahci_host_priv *hpriv; +	struct ecx_plat_data *pdata; +	struct ata_host *host; +	struct resource *mem; +	int irq; +	int i; +	int rc; +	u32 n_ports; +	struct ata_port_info pi = ahci_highbank_port_info; +	const struct ata_port_info *ppi[] = { &pi, NULL }; + +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!mem) { +		dev_err(dev, "no mmio space\n"); +		return -EINVAL; +	} + +	irq = platform_get_irq(pdev, 0); +	if (irq <= 0) { +		dev_err(dev, "no irq\n"); +		return -EINVAL; +	} + +	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); +	if (!hpriv) { +		dev_err(dev, "can't alloc ahci_host_priv\n"); +		return -ENOMEM; +	} +	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); +	if (!pdata) { +		dev_err(dev, "can't alloc ecx_plat_data\n"); +		return -ENOMEM; +	} + +	hpriv->flags |= (unsigned long)pi.private_data; + +	hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem)); +	if (!hpriv->mmio) { +		dev_err(dev, "can't map %pR\n", mem); +		return -ENOMEM; +	} + +	rc = highbank_initialize_phys(dev, hpriv->mmio); +	if (rc) +		return rc; + + +	ahci_save_initial_config(dev, hpriv, 0, 0); + +	/* prepare host */ +	if (hpriv->cap & HOST_CAP_NCQ) +		pi.flags |= ATA_FLAG_NCQ; + +	if (hpriv->cap & HOST_CAP_PMP) +		pi.flags |= ATA_FLAG_PMP; + +	if (hpriv->cap & HOST_CAP_64) +		dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); + +	/* CAP.NP sometimes indicate the index of the last enabled +	 * port, at other times, that of the last possible port, so +	 * determining the maximum port number requires looking at +	 * both CAP.NP and port_map. +	 */ +	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); + +	pdata->n_ports = n_ports; +	hpriv->plat_data = pdata; +	highbank_set_em_messages(dev, hpriv, &pi); + +	host = ata_host_alloc_pinfo(dev, ppi, n_ports); +	if (!host) { +		rc = -ENOMEM; +		goto err0; +	} + +	host->private_data = hpriv; + +	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) +		host->flags |= ATA_HOST_PARALLEL_SCAN; + +	for (i = 0; i < host->n_ports; i++) { +		struct ata_port *ap = host->ports[i]; + +		ata_port_desc(ap, "mmio %pR", mem); +		ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); + +		/* set enclosure management message type */ +		if (ap->flags & ATA_FLAG_EM) +			ap->em_message_type = hpriv->em_msg_type; + +		/* disabled/not-implemented port */ +		if (!(hpriv->port_map & (1 << i))) +			ap->ops = &ata_dummy_port_ops; +	} + +	rc = ahci_reset_controller(host); +	if (rc) +		goto err0; + +	ahci_init_controller(host); +	ahci_print_info(host, "platform"); + +	rc = ata_host_activate(host, irq, ahci_interrupt, 0, +					&ahci_highbank_platform_sht); +	if (rc) +		goto err0; + +	return 0; +err0: +	return rc; +} + +#ifdef CONFIG_PM_SLEEP +static int ahci_highbank_suspend(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	struct ahci_host_priv *hpriv = host->private_data; +	void __iomem *mmio = hpriv->mmio; +	u32 ctl; +	int rc; + +	if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { +		dev_err(dev, "firmware update required for suspend/resume\n"); +		return -EIO; +	} + +	/* +	 * AHCI spec rev1.1 section 8.3.3: +	 * Software must disable interrupts prior to requesting a +	 * transition of the HBA to D3 state. +	 */ +	ctl = readl(mmio + HOST_CTL); +	ctl &= ~HOST_IRQ_EN; +	writel(ctl, mmio + HOST_CTL); +	readl(mmio + HOST_CTL); /* flush */ + +	rc = ata_host_suspend(host, PMSG_SUSPEND); +	if (rc) +		return rc; + +	return 0; +} + +static int ahci_highbank_resume(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	int rc; + +	if (dev->power.power_state.event == PM_EVENT_SUSPEND) { +		rc = ahci_reset_controller(host); +		if (rc) +			return rc; + +		ahci_init_controller(host); +	} + +	ata_host_resume(host); + +	return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops, +		  ahci_highbank_suspend, ahci_highbank_resume); + +static struct platform_driver ahci_highbank_driver = { +	.remove = ata_platform_remove_one, +        .driver = { +                .name = "highbank-ahci", +                .owner = THIS_MODULE, +                .of_match_table = ahci_of_match, +                .pm = &ahci_highbank_pm_ops, +        }, +	.probe = ahci_highbank_probe, +}; + +module_platform_driver(ahci_highbank_driver); + +MODULE_DESCRIPTION("Calxeda Highbank AHCI SATA platform driver"); +MODULE_AUTHOR("Mark Langsdorf <mark.langsdorf@calxeda.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("sata:highbank"); diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 83a44471b18..069827826b2 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -6,6 +6,18 @@   *   * This file is released under GPL v2.   * + * **** WARNING **** + * + * This driver never worked properly and unfortunately data corruption is + * relatively common.  There isn't anyone working on the driver and there's + * no support from the vendor.  Do not use this driver in any production + * environment. + * + * http://thread.gmane.org/gmane.linux.debian.devel.bugs.rc/378525/focus=54491 + * https://bugzilla.kernel.org/show_bug.cgi?id=60565 + * + * ***************** + *   * This controller is eccentric and easily locks up if something isn't   * right.  Documentation is available at initio's website but it only   * documents registers (not programming model). @@ -273,12 +285,10 @@ static void inic_reset_port(void __iomem *port_base)  static int inic_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)  {  	void __iomem *scr_addr = inic_port_base(link->ap) + PORT_SCR; -	void __iomem *addr;  	if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))  		return -EINVAL; -	addr = scr_addr + scr_map[sc_reg] * 4;  	*val = readl(scr_addr + scr_map[sc_reg] * 4);  	/* this controller has stuck DIAG.N, ignore it */ @@ -396,9 +406,8 @@ static void inic_host_intr(struct ata_port *ap)  	}   spurious: -	ata_port_printk(ap, KERN_WARNING, "unhandled interrupt: " -			"cmd=0x%x irq_stat=0x%x idma_stat=0x%x\n", -			qc ? qc->tf.command : 0xff, irq_stat, idma_stat); +	ata_port_warn(ap, "unhandled interrupt: cmd=0x%x irq_stat=0x%x idma_stat=0x%x\n", +		      qc ? qc->tf.command : 0xff, irq_stat, idma_stat);  }  static irqreturn_t inic_interrupt(int irq, void *dev_instance) @@ -619,8 +628,9 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,  	rc = sata_link_resume(link, timing, deadline);  	if (rc) { -		ata_link_printk(link, KERN_WARNING, "failed to resume " -				"link after reset (errno=%d)\n", rc); +		ata_link_warn(link, +			      "failed to resume link after reset (errno=%d)\n", +			      rc);  		return rc;  	} @@ -632,8 +642,9 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,  		rc = ata_wait_after_reset(link, deadline, inic_check_ready);  		/* link occupied, -ENODEV too is an error */  		if (rc) { -			ata_link_printk(link, KERN_WARNING, "device not ready " -					"after hardreset (errno=%d)\n", rc); +			ata_link_warn(link, +				      "device not ready after hardreset (errno=%d)\n", +				      rc);  			return rc;  		} @@ -774,10 +785,10 @@ static int init_controller(void __iomem *mmio_base, u16 hctl)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int inic_pci_device_resume(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	struct inic_host_priv *hpriv = host->private_data;  	int rc; @@ -799,7 +810,6 @@ static int inic_pci_device_resume(struct pci_dev *pdev)  static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	const struct ata_port_info *ppi[] = { &inic_port_info, NULL };  	struct ata_host *host;  	struct inic_host_priv *hpriv; @@ -807,8 +817,9 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	int mmio_bar;  	int i, rc; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION); + +	dev_alert(&pdev->dev, "inic162x support is broken with common data corruption issues and will be disabled by default, contact linux-ide@vger.kernel.org if in production use\n");  	/* alloc host */  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, NR_PORTS); @@ -847,15 +858,13 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	/* Set dma_mask.  This devices doesn't support 64bit addressing. */  	rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));  	if (rc) { -		dev_printk(KERN_ERR, &pdev->dev, -			   "32-bit DMA enable failed\n"); +		dev_err(&pdev->dev, "32-bit DMA enable failed\n");  		return rc;  	}  	rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));  	if (rc) { -		dev_printk(KERN_ERR, &pdev->dev, -			   "32-bit consistent DMA enable failed\n"); +		dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n");  		return rc;  	} @@ -866,15 +875,13 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	 */  	rc = pci_set_dma_max_seg_size(pdev, 65536 - 512);  	if (rc) { -		dev_printk(KERN_ERR, &pdev->dev, -			   "failed to set the maximum segment size.\n"); +		dev_err(&pdev->dev, "failed to set the maximum segment size\n");  		return rc;  	}  	rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);  	if (rc) { -		dev_printk(KERN_ERR, &pdev->dev, -			   "failed to initialize controller\n"); +		dev_err(&pdev->dev, "failed to initialize controller\n");  		return rc;  	} @@ -891,7 +898,7 @@ static const struct pci_device_id inic_pci_tbl[] = {  static struct pci_driver inic_pci_driver = {  	.name 		= DRV_NAME,  	.id_table	= inic_pci_tbl, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend	= ata_pci_device_suspend,  	.resume		= inic_pci_device_resume,  #endif @@ -899,21 +906,10 @@ static struct pci_driver inic_pci_driver = {  	.remove		= ata_pci_remove_one,  }; -static int __init inic_init(void) -{ -	return pci_register_driver(&inic_pci_driver); -} - -static void __exit inic_exit(void) -{ -	pci_unregister_driver(&inic_pci_driver); -} +module_pci_driver(inic_pci_driver);  MODULE_AUTHOR("Tejun Heo");  MODULE_DESCRIPTION("low-level driver for Initio 162x SATA");  MODULE_LICENSE("GPL v2");  MODULE_DEVICE_TABLE(pci, inic_pci_tbl);  MODULE_VERSION(DRV_VERSION); - -module_init(inic_init); -module_exit(inic_exit); diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index bf74a36d3cc..391cfda1e83 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -60,11 +60,14 @@  #include <linux/dma-mapping.h>  #include <linux/device.h>  #include <linux/clk.h> +#include <linux/phy/phy.h>  #include <linux/platform_device.h>  #include <linux/ata_platform.h>  #include <linux/mbus.h>  #include <linux/bitops.h>  #include <linux/gfp.h> +#include <linux/of.h> +#include <linux/of_irq.h>  #include <scsi/scsi_host.h>  #include <scsi/scsi_cmnd.h>  #include <scsi/scsi_device.h> @@ -77,8 +80,8 @@   * module options   */ -static int msi;  #ifdef CONFIG_PCI +static int msi;  module_param(msi, int, S_IRUGO);  MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");  #endif @@ -160,8 +163,7 @@ enum {  	/* Host Flags */  	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */ -	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, +	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_PIO_POLLING,  	MV_GEN_I_FLAGS		= MV_COMMON_FLAGS | ATA_FLAG_NO_ATAPI, @@ -303,6 +305,7 @@ enum {  	MV5_LTMODE		= 0x30,  	MV5_PHY_CTL		= 0x0C,  	SATA_IFCFG		= 0x050, +	LP_PHY_CTL		= 0x058,  	MV_M2_PREAMP_MASK	= 0x7e0, @@ -430,6 +433,7 @@ enum {  	MV_HP_CUT_THROUGH	= (1 << 10),	/* can use EDMA cut-through */  	MV_HP_FLAG_SOC		= (1 << 11),	/* SystemOnChip, no PCI */  	MV_HP_QUIRK_LED_BLINK_EN = (1 << 12),	/* is led blinking enabled? */ +	MV_HP_FIX_LP_PHY_CTL	= (1 << 13),	/* fix speed in LP_PHY_CTL ? */  	/* Port private flags (pp_flags) */  	MV_PP_FLAG_EDMA_EN	= (1 << 0),	/* is EDMA engine enabled? */ @@ -552,9 +556,21 @@ struct mv_host_priv {  	u32			irq_mask_offset;  	u32			unmask_all_irqs; -#if defined(CONFIG_HAVE_CLK) +	/* +	 * Needed on some devices that require their clocks to be enabled. +	 * These are optional: if the platform device does not have any +	 * clocks, they won't be used.  Also, if the underlying hardware +	 * does not support the common clock framework (CONFIG_HAVE_CLK=n), +	 * all the clock operations become no-ops (see clk.h). +	 */  	struct clk		*clk; -#endif +	struct clk              **port_clks; +	/* +	 * Some devices have a SATA PHY which can be enabled/disabled +	 * in order to save power. These are optional: if the platform +	 * devices does not have any phy, they won't be used. +	 */ +	struct phy		**port_phys;  	/*  	 * These consistent DMA memory pools give us guaranteed  	 * alignment for hardware-accessed data structures, @@ -650,12 +666,13 @@ static u8 mv_sff_check_status(struct ata_port *ap);   * because we have to allow room for worst case splitting of   * PRDs for 64K boundaries in mv_fill_sg().   */ +#ifdef CONFIG_PCI  static struct scsi_host_template mv5_sht = {  	ATA_BASE_SHT(DRV_NAME),  	.sg_tablesize		= MV_MAX_SG_CT / 2,  	.dma_boundary		= MV_DMA_BOUNDARY,  }; - +#endif  static struct scsi_host_template mv6_sht = {  	ATA_NCQ_SHT(DRV_NAME),  	.can_queue		= MV_MAX_Q_DEPTH - 1, @@ -1191,7 +1208,7 @@ static void mv_wait_for_edma_empty_idle(struct ata_port *ap)  			break;  		udelay(per_loop);  	} -	/* ata_port_printk(ap, KERN_INFO, "%s: %u+ usecs\n", __func__, i); */ +	/* ata_port_info(ap, "%s: %u+ usecs\n", __func__, i); */  }  /** @@ -1229,7 +1246,7 @@ static int mv_stop_edma(struct ata_port *ap)  	pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;  	mv_wait_for_edma_empty_idle(ap);  	if (mv_stop_edma_engine(port_mmio)) { -		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); +		ata_port_err(ap, "Unable to stop eDMA\n");  		err = -EIO;  	}  	mv_edma_cfg(ap, 0, 0); @@ -1250,7 +1267,7 @@ static void mv_dump_mem(void __iomem *start, unsigned bytes)  	}  }  #endif - +#if defined(ATA_DEBUG) || defined(CONFIG_PCI)  static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)  {  #ifdef ATA_DEBUG @@ -1267,6 +1284,7 @@ static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)  	}  #endif  } +#endif  static void mv_dump_all_regs(void __iomem *mmio_base, int port,  			     struct pci_dev *pdev)  { @@ -1349,11 +1367,12 @@ static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val)  	if (ofs != 0xffffffffU) {  		void __iomem *addr = mv_ap_base(link->ap) + ofs; +		struct mv_host_priv *hpriv = link->ap->host->private_data;  		if (sc_reg_in == SCR_CONTROL) {  			/*  			 * Workaround for 88SX60x1 FEr SATA#26:  			 * -			 * COMRESETs have to take care not to accidently +			 * COMRESETs have to take care not to accidentally  			 * put the drive to sleep when writing SCR_CONTROL.  			 * Setting bits 12..15 prevents this problem.  			 * @@ -1365,6 +1384,18 @@ static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val)  			 */  			if ((val & 0xf) == 1 || (readl(addr) & 0xf) == 1)  				val |= 0xf000; + +			if (hpriv->hp_flags & MV_HP_FIX_LP_PHY_CTL) { +				void __iomem *lp_phy_addr = +					mv_ap_base(link->ap) + LP_PHY_CTL; +				/* +				 * Set PHY speed according to SControl speed. +				 */ +				if ((val & 0xf0) == 0x10) +					writelfl(0x7, lp_phy_addr); +				else +					writelfl(0x227, lp_phy_addr); +			}  		}  		writelfl(val, addr);  		return 0; @@ -1383,7 +1414,7 @@ static void mv6_dev_config(struct ata_device *adev)  	if (adev->flags & ATA_DFLAG_NCQ) {  		if (sata_pmp_attached(adev->link->ap)) {  			adev->flags &= ~ATA_DFLAG_NCQ; -			ata_dev_printk(adev, KERN_INFO, +			ata_dev_info(adev,  				"NCQ disabled for command-based switching\n");  		}  	} @@ -2045,7 +2076,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)  	cw = &pp->crqb[in_index].ata_cmd[0]; -	/* Sadly, the CRQB cannot accomodate all registers--there are +	/* Sadly, the CRQB cannot accommodate all registers--there are  	 * only 11 bytes...so we must pick and choose required  	 * registers based on the command.  So, we drop feature and  	 * hob_feature for [RW] DMA commands, but they are needed for @@ -2226,9 +2257,8 @@ static unsigned int mv_send_fis(struct ata_port *ap, u32 *fis, int nwords)  	/* See if it worked */  	if ((ifstat & 0x3000) != 0x1000) { -		ata_port_printk(ap, KERN_WARNING, -				"%s transmission error, ifstat=%08x\n", -				__func__, ifstat); +		ata_port_warn(ap, "%s transmission error, ifstat=%08x\n", +			      __func__, ifstat);  		return AC_ERR_OTHER;  	}  	return 0; @@ -2343,9 +2373,9 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)  		 */  		if (limit_warnings > 0 && (qc->nbytes / qc->sect_size) > 1) {  			--limit_warnings; -			ata_link_printk(qc->dev->link, KERN_WARNING, DRV_NAME -					": attempting PIO w/multiple DRQ: " -					"this may fail due to h/w errata\n"); +			ata_link_warn(qc->dev->link, DRV_NAME +				      ": attempting PIO w/multiple DRQ: " +				      "this may fail due to h/w errata\n");  		}  		/* drop through */  	case ATA_PROT_NODATA: @@ -2500,20 +2530,20 @@ static int mv_handle_fbs_ncq_dev_err(struct ata_port *ap)  	}  	failed_links = hweight16(new_map); -	ata_port_printk(ap, KERN_INFO, "%s: pmp_map=%04x qc_map=%04x " -			"failed_links=%d nr_active_links=%d\n", -			__func__, pp->delayed_eh_pmp_map, -			ap->qc_active, failed_links, -			ap->nr_active_links); +	ata_port_info(ap, +		      "%s: pmp_map=%04x qc_map=%04x failed_links=%d nr_active_links=%d\n", +		      __func__, pp->delayed_eh_pmp_map, +		      ap->qc_active, failed_links, +		      ap->nr_active_links);  	if (ap->nr_active_links <= failed_links && mv_req_q_empty(ap)) {  		mv_process_crpb_entries(ap, pp);  		mv_stop_edma(ap);  		mv_eh_freeze(ap); -		ata_port_printk(ap, KERN_INFO, "%s: done\n", __func__); +		ata_port_info(ap, "%s: done\n", __func__);  		return 1;	/* handled */  	} -	ata_port_printk(ap, KERN_INFO, "%s: waiting\n", __func__); +	ata_port_info(ap, "%s: waiting\n", __func__);  	return 1;	/* handled */  } @@ -2555,9 +2585,8 @@ static int mv_handle_dev_err(struct ata_port *ap, u32 edma_err_cause)  		 * and we cannot handle it here.  		 */  		if (edma_err_cause & EDMA_ERR_SELF_DIS) { -			ata_port_printk(ap, KERN_WARNING, -				"%s: err_cause=0x%x pp_flags=0x%x\n", -				__func__, edma_err_cause, pp->pp_flags); +			ata_port_warn(ap, "%s: err_cause=0x%x pp_flags=0x%x\n", +				      __func__, edma_err_cause, pp->pp_flags);  			return 0; /* not handled */  		}  		return mv_handle_fbs_ncq_dev_err(ap); @@ -2568,9 +2597,8 @@ static int mv_handle_dev_err(struct ata_port *ap, u32 edma_err_cause)  		 * and we cannot handle it here.  		 */  		if (!(edma_err_cause & EDMA_ERR_SELF_DIS)) { -			ata_port_printk(ap, KERN_WARNING, -				"%s: err_cause=0x%x pp_flags=0x%x\n", -				__func__, edma_err_cause, pp->pp_flags); +			ata_port_warn(ap, "%s: err_cause=0x%x pp_flags=0x%x\n", +				      __func__, edma_err_cause, pp->pp_flags);  			return 0; /* not handled */  		}  		return mv_handle_fbs_non_ncq_dev_err(ap); @@ -2931,8 +2959,7 @@ static int mv_pci_error(struct ata_host *host, void __iomem *mmio)  	err_cause = readl(mmio + hpriv->irq_cause_offset); -	dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n", -		   err_cause); +	dev_err(host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n", err_cause);  	DPRINTK("All regs @ PCI error\n");  	mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev)); @@ -3761,8 +3788,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)  			hp_flags |= MV_HP_ERRATA_50XXB2;  			break;  		default: -			dev_printk(KERN_WARNING, &pdev->dev, -			   "Applying 50XXB2 workarounds to unknown rev\n"); +			dev_warn(&pdev->dev, +				 "Applying 50XXB2 workarounds to unknown rev\n");  			hp_flags |= MV_HP_ERRATA_50XXB2;  			break;  		} @@ -3781,8 +3808,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)  			hp_flags |= MV_HP_ERRATA_50XXB2;  			break;  		default: -			dev_printk(KERN_WARNING, &pdev->dev, -			   "Applying B2 workarounds to unknown rev\n"); +			dev_warn(&pdev->dev, +				 "Applying B2 workarounds to unknown rev\n");  			hp_flags |= MV_HP_ERRATA_50XXB2;  			break;  		} @@ -3802,8 +3829,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)  			hp_flags |= MV_HP_ERRATA_60X1C0;  			break;  		default: -			dev_printk(KERN_WARNING, &pdev->dev, -				   "Applying B2 workarounds to unknown rev\n"); +			dev_warn(&pdev->dev, +				 "Applying B2 workarounds to unknown rev\n");  			hp_flags |= MV_HP_ERRATA_60X1B2;  			break;  		} @@ -3852,8 +3879,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)  			hp_flags |= MV_HP_ERRATA_60X1C0;  			break;  		default: -			dev_printk(KERN_WARNING, &pdev->dev, -			   "Applying 60X1C0 workarounds to unknown rev\n"); +			dev_warn(&pdev->dev, +				 "Applying 60X1C0 workarounds to unknown rev\n");  			hp_flags |= MV_HP_ERRATA_60X1C0;  			break;  		} @@ -3868,8 +3895,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)  		break;  	default: -		dev_printk(KERN_ERR, host->dev, -			   "BUG: invalid board index %u\n", board_idx); +		dev_err(host->dev, "BUG: invalid board index %u\n", board_idx);  		return 1;  	} @@ -3994,7 +4020,7 @@ static int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev)  }  static void mv_conf_mbus_windows(struct mv_host_priv *hpriv, -				 struct mbus_dram_target_info *dram) +				 const struct mbus_dram_target_info *dram)  {  	int i; @@ -4004,7 +4030,7 @@ static void mv_conf_mbus_windows(struct mv_host_priv *hpriv,  	}  	for (i = 0; i < dram->num_cs; i++) { -		struct mbus_dram_window *cs = dram->cs + i; +		const struct mbus_dram_window *cs = dram->cs + i;  		writel(((cs->size - 1) & 0xffff0000) |  			(cs->mbus_attr << 8) | @@ -4024,17 +4050,18 @@ static void mv_conf_mbus_windows(struct mv_host_priv *hpriv,   */  static int mv_platform_probe(struct platform_device *pdev)  { -	static int printed_version;  	const struct mv_sata_platform_data *mv_platform_data; +	const struct mbus_dram_target_info *dram;  	const struct ata_port_info *ppi[] =  	    { &mv_port_info[chip_soc], NULL };  	struct ata_host *host;  	struct mv_host_priv *hpriv;  	struct resource *res; -	int n_ports, rc; +	int n_ports = 0, irq = 0; +	int rc; +	int port; -	if (!printed_version++) -		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/*  	 * Simple resource validation .. @@ -4052,16 +4079,31 @@ static int mv_platform_probe(struct platform_device *pdev)  		return -EINVAL;  	/* allocate host */ -	mv_platform_data = pdev->dev.platform_data; -	n_ports = mv_platform_data->n_ports; +	if (pdev->dev.of_node) { +		of_property_read_u32(pdev->dev.of_node, "nr-ports", &n_ports); +		irq = irq_of_parse_and_map(pdev->dev.of_node, 0); +	} else { +		mv_platform_data = dev_get_platdata(&pdev->dev); +		n_ports = mv_platform_data->n_ports; +		irq = platform_get_irq(pdev, 0); +	}  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);  	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);  	if (!host || !hpriv)  		return -ENOMEM; +	hpriv->port_clks = devm_kzalloc(&pdev->dev, +					sizeof(struct clk *) * n_ports, +					GFP_KERNEL); +	if (!hpriv->port_clks) +		return -ENOMEM; +	hpriv->port_phys = devm_kzalloc(&pdev->dev, +					sizeof(struct phy *) * n_ports, +					GFP_KERNEL); +	if (!hpriv->port_phys) +		return -ENOMEM;  	host->private_data = hpriv; -	hpriv->n_ports = n_ports;  	hpriv->board_idx = chip_soc;  	host->iomap = NULL; @@ -4069,42 +4111,83 @@ static int mv_platform_probe(struct platform_device *pdev)  				   resource_size(res));  	hpriv->base -= SATAHC0_REG_BASE; -#if defined(CONFIG_HAVE_CLK)  	hpriv->clk = clk_get(&pdev->dev, NULL);  	if (IS_ERR(hpriv->clk)) -		dev_notice(&pdev->dev, "cannot get clkdev\n"); +		dev_notice(&pdev->dev, "cannot get optional clkdev\n");  	else -		clk_enable(hpriv->clk); -#endif +		clk_prepare_enable(hpriv->clk); + +	for (port = 0; port < n_ports; port++) { +		char port_number[16]; +		sprintf(port_number, "%d", port); +		hpriv->port_clks[port] = clk_get(&pdev->dev, port_number); +		if (!IS_ERR(hpriv->port_clks[port])) +			clk_prepare_enable(hpriv->port_clks[port]); + +		sprintf(port_number, "port%d", port); +		hpriv->port_phys[port] = devm_phy_optional_get(&pdev->dev, +							       port_number); +		if (IS_ERR(hpriv->port_phys[port])) { +			rc = PTR_ERR(hpriv->port_phys[port]); +			hpriv->port_phys[port] = NULL; +			if (rc != -EPROBE_DEFER) +				dev_warn(&pdev->dev, "error getting phy %d", rc); + +			/* Cleanup only the initialized ports */ +			hpriv->n_ports = port; +			goto err; +		} else +			phy_power_on(hpriv->port_phys[port]); +	} + +	/* All the ports have been initialized */ +	hpriv->n_ports = n_ports;  	/*  	 * (Re-)program MBUS remapping windows if we are asked to.  	 */ -	if (mv_platform_data->dram != NULL) -		mv_conf_mbus_windows(hpriv, mv_platform_data->dram); +	dram = mv_mbus_dram_info(); +	if (dram) +		mv_conf_mbus_windows(hpriv, dram);  	rc = mv_create_dma_pools(hpriv, &pdev->dev);  	if (rc)  		goto err; +	/* +	 * To allow disk hotplug on Armada 370/XP SoCs, the PHY speed must be +	 * updated in the LP_PHY_CTL register. +	 */ +	if (pdev->dev.of_node && +		of_device_is_compatible(pdev->dev.of_node, +					"marvell,armada-370-sata")) +		hpriv->hp_flags |= MV_HP_FIX_LP_PHY_CTL; +  	/* initialize adapter */  	rc = mv_init_host(host);  	if (rc)  		goto err; -	dev_printk(KERN_INFO, &pdev->dev, -		   "slots %u ports %d\n", (unsigned)MV_MAX_Q_DEPTH, -		   host->n_ports); +	dev_info(&pdev->dev, "slots %u ports %d\n", +		 (unsigned)MV_MAX_Q_DEPTH, host->n_ports); + +	rc = ata_host_activate(host, irq, mv_interrupt, IRQF_SHARED, &mv6_sht); +	if (!rc) +		return 0; -	return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt, -				 IRQF_SHARED, &mv6_sht);  err: -#if defined(CONFIG_HAVE_CLK)  	if (!IS_ERR(hpriv->clk)) { -		clk_disable(hpriv->clk); +		clk_disable_unprepare(hpriv->clk);  		clk_put(hpriv->clk);  	} -#endif +	for (port = 0; port < hpriv->n_ports; port++) { +		if (!IS_ERR(hpriv->port_clks[port])) { +			clk_disable_unprepare(hpriv->port_clks[port]); +			clk_put(hpriv->port_clks[port]); +		} +		if (hpriv->port_phys[port]) +			phy_power_off(hpriv->port_phys[port]); +	}  	return rc;  } @@ -4117,28 +4200,32 @@ err:   *      A platform bus SATA device has been unplugged. Perform the needed   *      cleanup. Also called on module unload for any active devices.   */ -static int __devexit mv_platform_remove(struct platform_device *pdev) +static int mv_platform_remove(struct platform_device *pdev)  { -	struct device *dev = &pdev->dev; -	struct ata_host *host = dev_get_drvdata(dev); -#if defined(CONFIG_HAVE_CLK) +	struct ata_host *host = platform_get_drvdata(pdev);  	struct mv_host_priv *hpriv = host->private_data; -#endif +	int port;  	ata_host_detach(host); -#if defined(CONFIG_HAVE_CLK)  	if (!IS_ERR(hpriv->clk)) { -		clk_disable(hpriv->clk); +		clk_disable_unprepare(hpriv->clk);  		clk_put(hpriv->clk);  	} -#endif +	for (port = 0; port < host->n_ports; port++) { +		if (!IS_ERR(hpriv->port_clks[port])) { +			clk_disable_unprepare(hpriv->port_clks[port]); +			clk_put(hpriv->port_clks[port]); +		} +		if (hpriv->port_phys[port]) +			phy_power_off(hpriv->port_phys[port]); +	}  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int mv_platform_suspend(struct platform_device *pdev, pm_message_t state)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = platform_get_drvdata(pdev);  	if (host)  		return ata_host_suspend(host, state);  	else @@ -4147,18 +4234,19 @@ static int mv_platform_suspend(struct platform_device *pdev, pm_message_t state)  static int mv_platform_resume(struct platform_device *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = platform_get_drvdata(pdev); +	const struct mbus_dram_target_info *dram;  	int ret;  	if (host) {  		struct mv_host_priv *hpriv = host->private_data; -		const struct mv_sata_platform_data *mv_platform_data = \ -			pdev->dev.platform_data; +  		/*  		 * (Re-)program MBUS remapping windows if we are asked to.  		 */ -		if (mv_platform_data->dram != NULL) -			mv_conf_mbus_windows(hpriv, mv_platform_data->dram); +		dram = mv_mbus_dram_info(); +		if (dram) +			mv_conf_mbus_windows(hpriv, dram);  		/* initialize adapter */  		ret = mv_init_host(host); @@ -4176,22 +4264,32 @@ static int mv_platform_resume(struct platform_device *pdev)  #define mv_platform_resume NULL  #endif +#ifdef CONFIG_OF +static struct of_device_id mv_sata_dt_ids[] = { +	{ .compatible = "marvell,armada-370-sata", }, +	{ .compatible = "marvell,orion-sata", }, +	{}, +}; +MODULE_DEVICE_TABLE(of, mv_sata_dt_ids); +#endif +  static struct platform_driver mv_platform_driver = { -	.probe			= mv_platform_probe, -	.remove			= __devexit_p(mv_platform_remove), -	.suspend		= mv_platform_suspend, -	.resume			= mv_platform_resume, -	.driver			= { -				   .name = DRV_NAME, -				   .owner = THIS_MODULE, -				  }, +	.probe		= mv_platform_probe, +	.remove		= mv_platform_remove, +	.suspend	= mv_platform_suspend, +	.resume		= mv_platform_resume, +	.driver		= { +		.name = DRV_NAME, +		.owner = THIS_MODULE, +		.of_match_table = of_match_ptr(mv_sata_dt_ids), +	},  };  #ifdef CONFIG_PCI  static int mv_pci_init_one(struct pci_dev *pdev,  			   const struct pci_device_id *ent); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int mv_pci_device_resume(struct pci_dev *pdev);  #endif @@ -4201,7 +4299,7 @@ static struct pci_driver mv_pci_driver = {  	.id_table		= mv_pci_tbl,  	.probe			= mv_pci_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= mv_pci_device_resume,  #endif @@ -4218,22 +4316,21 @@ static int pci_go_64(struct pci_dev *pdev)  		if (rc) {  			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));  			if (rc) { -				dev_printk(KERN_ERR, &pdev->dev, -					   "64-bit DMA enable failed\n"); +				dev_err(&pdev->dev, +					"64-bit DMA enable failed\n");  				return rc;  			}  		}  	} else {  		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));  		if (rc) { -			dev_printk(KERN_ERR, &pdev->dev, -				   "32-bit DMA enable failed\n"); +			dev_err(&pdev->dev, "32-bit DMA enable failed\n");  			return rc;  		}  		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));  		if (rc) { -			dev_printk(KERN_ERR, &pdev->dev, -				   "32-bit consistent DMA enable failed\n"); +			dev_err(&pdev->dev, +				"32-bit consistent DMA enable failed\n");  			return rc;  		}  	} @@ -4277,10 +4374,9 @@ static void mv_print_info(struct ata_host *host)  	else  		gen = "?"; -	dev_printk(KERN_INFO, &pdev->dev, -	       "Gen-%s %u slots %u ports %s mode IRQ via %s\n", -	       gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports, -	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx"); +	dev_info(&pdev->dev, "Gen-%s %u slots %u ports %s mode IRQ via %s\n", +		 gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports, +		 scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");  }  /** @@ -4294,15 +4390,13 @@ static void mv_print_info(struct ata_host *host)  static int mv_pci_init_one(struct pci_dev *pdev,  			   const struct pci_device_id *ent)  { -	static int printed_version;  	unsigned int board_idx = (unsigned int)ent->driver_data;  	const struct ata_port_info *ppi[] = { &mv_port_info[board_idx], NULL };  	struct ata_host *host;  	struct mv_host_priv *hpriv;  	int n_ports, port, rc; -	if (!printed_version++) -		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* allocate host */  	n_ports = mv_get_hc_count(ppi[0]->flags) * MV_PORTS_PER_HC; @@ -4363,10 +4457,10 @@ static int mv_pci_init_one(struct pci_dev *pdev,  				 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int mv_pci_device_resume(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -4385,9 +4479,6 @@ static int mv_pci_device_resume(struct pci_dev *pdev)  #endif  #endif -static int mv_platform_probe(struct platform_device *pdev); -static int __devexit mv_platform_remove(struct platform_device *pdev); -  static int __init mv_init(void)  {  	int rc = -ENODEV; diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 7254e255fd7..cdf99fac139 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -40,7 +40,6 @@  #include <linux/module.h>  #include <linux/gfp.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -296,7 +295,7 @@ struct nv_swncq_port_priv {  #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & (1 << (19 + (12 * (PORT)))))  static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int nv_pci_device_resume(struct pci_dev *pdev);  #endif  static void nv_ck804_host_stop(struct ata_host *host); @@ -380,7 +379,7 @@ static struct pci_driver nv_pci_driver = {  	.name			= DRV_NAME,  	.id_table		= nv_pci_tbl,  	.probe			= nv_init_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= nv_pci_device_resume,  #endif @@ -539,7 +538,7 @@ struct nv_pi_priv {  static const struct ata_port_info nv_port_info[] = {  	/* generic */  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, +		.flags		= ATA_FLAG_SATA,  		.pio_mask	= NV_PIO_MASK,  		.mwdma_mask	= NV_MWDMA_MASK,  		.udma_mask	= NV_UDMA_MASK, @@ -548,7 +547,7 @@ static const struct ata_port_info nv_port_info[] = {  	},  	/* nforce2/3 */  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, +		.flags		= ATA_FLAG_SATA,  		.pio_mask	= NV_PIO_MASK,  		.mwdma_mask	= NV_MWDMA_MASK,  		.udma_mask	= NV_UDMA_MASK, @@ -557,7 +556,7 @@ static const struct ata_port_info nv_port_info[] = {  	},  	/* ck804 */  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, +		.flags		= ATA_FLAG_SATA,  		.pio_mask	= NV_PIO_MASK,  		.mwdma_mask	= NV_MWDMA_MASK,  		.udma_mask	= NV_UDMA_MASK, @@ -566,8 +565,7 @@ static const struct ata_port_info nv_port_info[] = {  	},  	/* ADMA */  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO | ATA_FLAG_NCQ, +		.flags		= ATA_FLAG_SATA | ATA_FLAG_NCQ,  		.pio_mask	= NV_PIO_MASK,  		.mwdma_mask	= NV_MWDMA_MASK,  		.udma_mask	= NV_UDMA_MASK, @@ -576,7 +574,7 @@ static const struct ata_port_info nv_port_info[] = {  	},  	/* MCP5x */  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, +		.flags		= ATA_FLAG_SATA,  		.pio_mask	= NV_PIO_MASK,  		.mwdma_mask	= NV_MWDMA_MASK,  		.udma_mask	= NV_UDMA_MASK, @@ -585,8 +583,7 @@ static const struct ata_port_info nv_port_info[] = {  	},  	/* SWNCQ */  	{ -		.flags	        = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_NCQ, +		.flags	        = ATA_FLAG_SATA | ATA_FLAG_NCQ,  		.pio_mask	= NV_PIO_MASK,  		.mwdma_mask	= NV_MWDMA_MASK,  		.udma_mask	= NV_UDMA_MASK, @@ -601,9 +598,9 @@ MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, nv_pci_tbl);  MODULE_VERSION(DRV_VERSION); -static int adma_enabled; -static int swncq_enabled = 1; -static int msi_enabled; +static bool adma_enabled; +static bool swncq_enabled = 1; +static bool msi_enabled;  static void nv_adma_register_mode(struct ata_port *ap)  { @@ -622,9 +619,8 @@ static void nv_adma_register_mode(struct ata_port *ap)  		count++;  	}  	if (count == 20) -		ata_port_printk(ap, KERN_WARNING, -			"timeout waiting for ADMA IDLE, stat=0x%hx\n", -			status); +		ata_port_warn(ap, "timeout waiting for ADMA IDLE, stat=0x%hx\n", +			      status);  	tmp = readw(mmio + NV_ADMA_CTL);  	writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL); @@ -637,9 +633,9 @@ static void nv_adma_register_mode(struct ata_port *ap)  		count++;  	}  	if (count == 20) -		ata_port_printk(ap, KERN_WARNING, -			 "timeout waiting for ADMA LEGACY, stat=0x%hx\n", -			 status); +		ata_port_warn(ap, +			      "timeout waiting for ADMA LEGACY, stat=0x%hx\n", +			      status);  	pp->flags |= NV_ADMA_PORT_REGISTER_MODE;  } @@ -667,7 +663,7 @@ static void nv_adma_mode(struct ata_port *ap)  		count++;  	}  	if (count == 20) -		ata_port_printk(ap, KERN_WARNING, +		ata_port_warn(ap,  			"timeout waiting for ADMA LEGACY clear and IDLE, stat=0x%hx\n",  			status); @@ -774,10 +770,10 @@ static int nv_adma_slave_config(struct scsi_device *sdev)  	blk_queue_segment_boundary(sdev->request_queue, segment_boundary);  	blk_queue_max_segments(sdev->request_queue, sg_tablesize); -	ata_port_printk(ap, KERN_INFO, -		"DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n", -		(unsigned long long)*ap->host->dev->dma_mask, -		segment_boundary, sg_tablesize); +	ata_port_info(ap, +		      "DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n", +		      (unsigned long long)*ap->host->dev->dma_mask, +		      segment_boundary, sg_tablesize);  	spin_unlock_irqrestore(ap->lock, flags); @@ -1445,8 +1441,7 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)  	   existing commands. */  	if (unlikely(qc->tf.protocol == ATA_PROT_NCQ &&  		     (qc->flags & ATA_QCFLAG_RESULT_TF))) { -		ata_dev_printk(qc->dev, KERN_ERR, -			"NCQ w/ RESULT_TF not allowed\n"); +		ata_dev_err(qc->dev, "NCQ w/ RESULT_TF not allowed\n");  		return AC_ERR_SYSTEM;  	} @@ -1583,15 +1578,15 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class,  		int rc;  		if (!(ehc->i.flags & ATA_EHI_QUIET)) -			ata_link_printk(link, KERN_INFO, "nv: skipping " -					"hardreset on occupied port\n"); +			ata_link_info(link, +				      "nv: skipping hardreset on occupied port\n");  		/* make sure the link is online */  		rc = sata_link_resume(link, timing, deadline);  		/* whine about phy resume failure but proceed */  		if (rc && rc != -EOPNOTSUPP) -			ata_link_printk(link, KERN_WARNING, "failed to resume " -					"link (errno=%d)\n", rc); +			ata_link_warn(link, "failed to resume link (errno=%d)\n", +				      rc);  	}  	/* device signature acquisition is unreliable */ @@ -1688,7 +1683,7 @@ static void nv_adma_error_handler(struct ata_port *ap)  			u8 cpb_count = readb(mmio + NV_ADMA_CPB_COUNT);  			u8 next_cpb_idx = readb(mmio + NV_ADMA_NEXT_CPB_IDX); -			ata_port_printk(ap, KERN_ERR, +			ata_port_err(ap,  				"EH in ADMA mode, notifier 0x%X "  				"notifier_error 0x%X gen_ctl 0x%X status 0x%X "  				"next cpb count 0x%X next cpb idx 0x%x\n", @@ -1699,7 +1694,7 @@ static void nv_adma_error_handler(struct ata_port *ap)  				struct nv_adma_cpb *cpb = &pp->cpb[i];  				if ((ata_tag_valid(ap->link.active_tag) && i == ap->link.active_tag) ||  				    ap->link.sactive & (1 << i)) -					ata_port_printk(ap, KERN_ERR, +					ata_port_err(ap,  						"CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",  						i, cpb->ctl_flags, cpb->resp_flags);  			} @@ -1801,23 +1796,22 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)  	u32 sactive;  	u32 done_mask; -	ata_port_printk(ap, KERN_ERR, -			"EH in SWNCQ mode,QC:qc_active 0x%X sactive 0x%X\n", -			ap->qc_active, ap->link.sactive); -	ata_port_printk(ap, KERN_ERR, +	ata_port_err(ap, "EH in SWNCQ mode,QC:qc_active 0x%X sactive 0x%X\n", +		     ap->qc_active, ap->link.sactive); +	ata_port_err(ap,  		"SWNCQ:qc_active 0x%X defer_bits 0x%X last_issue_tag 0x%x\n  "  		"dhfis 0x%X dmafis 0x%X sdbfis 0x%X\n",  		pp->qc_active, pp->defer_queue.defer_bits, pp->last_issue_tag,  		pp->dhfis_bits, pp->dmafis_bits, pp->sdbfis_bits); -	ata_port_printk(ap, KERN_ERR, "ATA_REG 0x%X ERR_REG 0x%X\n", -			ap->ops->sff_check_status(ap), -			ioread8(ap->ioaddr.error_addr)); +	ata_port_err(ap, "ATA_REG 0x%X ERR_REG 0x%X\n", +		     ap->ops->sff_check_status(ap), +		     ioread8(ap->ioaddr.error_addr));  	sactive = readl(pp->sactive_block);  	done_mask = pp->qc_active ^ sactive; -	ata_port_printk(ap, KERN_ERR, "tag : dhfis dmafis sdbfis sacitve\n"); +	ata_port_err(ap, "tag : dhfis dmafis sdbfis sactive\n");  	for (i = 0; i < ATA_MAX_QUEUE; i++) {  		u8 err = 0;  		if (pp->qc_active & (1 << i)) @@ -1827,13 +1821,13 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)  		else  			continue; -		ata_port_printk(ap, KERN_ERR, -				"tag 0x%x: %01x %01x %01x %01x %s\n", i, -				(pp->dhfis_bits >> i) & 0x1, -				(pp->dmafis_bits >> i) & 0x1, -				(pp->sdbfis_bits >> i) & 0x1, -				(sactive >> i) & 0x1, -				(err ? "error! tag doesn't exit" : " ")); +		ata_port_err(ap, +			     "tag 0x%x: %01x %01x %01x %01x %s\n", i, +			     (pp->dhfis_bits >> i) & 0x1, +			     (pp->dmafis_bits >> i) & 0x1, +			     (pp->sdbfis_bits >> i) & 0x1, +			     (sactive >> i) & 0x1, +			     (err ? "error! tag doesn't exit" : " "));  	}  	nv_swncq_pp_reinit(ap); @@ -1958,8 +1952,8 @@ static int nv_swncq_slave_config(struct scsi_device *sdev)  	if (strncmp(model_num, "Maxtor", 6) == 0) {  		ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_DEFAULT); -		ata_dev_printk(dev, KERN_NOTICE, -			"Disabling SWNCQ mode (depth %x)\n", sdev->queue_depth); +		ata_dev_notice(dev, "Disabling SWNCQ mode (depth %x)\n", +			       sdev->queue_depth);  	}  	return rc; @@ -2123,7 +2117,7 @@ static int nv_swncq_sdbfis(struct ata_port *ap)  	host_stat = ap->ops->bmdma_status(ap);  	if (unlikely(host_stat & ATA_DMA_ERR)) { -		/* error when transfering data to/from memory */ +		/* error when transferring data to/from memory */  		ata_ehi_clear_desc(ehi);  		ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);  		ehi->err_mask |= AC_ERR_HOST_BUS; @@ -2358,7 +2352,6 @@ static irqreturn_t nv_swncq_interrupt(int irq, void *dev_instance)  static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	const struct ata_port_info *ppi[] = { NULL, NULL };  	struct nv_pi_priv *ipriv;  	struct ata_host *host; @@ -2375,8 +2368,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  		if (pci_resource_start(pdev, bar) == 0)  			return -ENODEV; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -2384,10 +2376,10 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	/* determine type and allocate host */  	if (type == CK804 && adma_enabled) { -		dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n"); +		dev_notice(&pdev->dev, "Using ADMA mode\n");  		type = ADMA;  	} else if (type == MCP5x && swncq_enabled) { -		dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n"); +		dev_notice(&pdev->dev, "Using SWNCQ mode\n");  		type = SWNCQ;  	} @@ -2431,7 +2423,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  		nv_swncq_host_init(host);  	if (msi_enabled) { -		dev_printk(KERN_NOTICE, &pdev->dev, "Using MSI\n"); +		dev_notice(&pdev->dev, "Using MSI\n");  		pci_enable_msi(pdev);  	} @@ -2439,10 +2431,10 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	return ata_pci_sff_activate_host(host, ipriv->irq_handler, ipriv->sht);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int nv_pci_device_resume(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	struct nv_host_priv *hpriv = host->private_data;  	int rc; @@ -2517,22 +2509,11 @@ static void nv_adma_host_stop(struct ata_host *host)  	nv_ck804_host_stop(host);  } -static int __init nv_init(void) -{ -	return pci_register_driver(&nv_pci_driver); -} - -static void __exit nv_exit(void) -{ -	pci_unregister_driver(&nv_pci_driver); -} +module_pci_driver(nv_pci_driver); -module_init(nv_init); -module_exit(nv_exit);  module_param_named(adma, adma_enabled, bool, 0444);  MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)");  module_param_named(swncq, swncq_enabled, bool, 0444);  MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");  module_param_named(msi, msi_enabled, bool, 0444);  MODULE_PARM_DESC(msi, "Enable use of MSI (Default: false)"); - diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index f03ad48273f..3638887476f 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -1,8 +1,8 @@  /*   *  sata_promise.c - Promise SATA   * - *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> - *		    Mikael Pettersson <mikpe@it.uu.se> + *  Maintained by:  Tejun Heo <tj@kernel.org> + *		    Mikael Pettersson   *  		    Please ALWAYS copy linux-ide@vger.kernel.org   *		    on emails.   * @@ -35,7 +35,6 @@  #include <linux/module.h>  #include <linux/gfp.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -134,9 +133,7 @@ enum {  	PDC_IRQ_DISABLE		= (1 << 10),  	PDC_RESET		= (1 << 11), /* HDMA reset */ -	PDC_COMMON_FLAGS	= ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO | -				  ATA_FLAG_PIO_POLLING, +	PDC_COMMON_FLAGS	= ATA_FLAG_PIO_POLLING,  	/* ap->flags bits */  	PDC_FLAG_GEN_II		= (1 << 24), @@ -149,6 +146,10 @@ struct pdc_port_priv {  	dma_addr_t		pkt_dma;  }; +struct pdc_host_priv { +	spinlock_t hard_reset_lock; +}; +  static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);  static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);  static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -803,9 +804,10 @@ static void pdc_hard_reset_port(struct ata_port *ap)  	void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR];  	void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1;  	unsigned int ata_no = pdc_ata_port_to_ata_no(ap); +	struct pdc_host_priv *hpriv = ap->host->private_data;  	u8 tmp; -	spin_lock(&ap->host->lock); +	spin_lock(&hpriv->hard_reset_lock);  	tmp = readb(pcictl_b1_mmio);  	tmp &= ~(0x10 << ata_no); @@ -816,7 +818,7 @@ static void pdc_hard_reset_port(struct ata_port *ap)  	writeb(tmp, pcictl_b1_mmio);  	readb(pcictl_b1_mmio); /* flush */ -	spin_unlock(&ap->host->lock); +	spin_unlock(&hpriv->hard_reset_lock);  }  static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, @@ -1181,16 +1183,15 @@ static void pdc_host_init(struct ata_host *host)  static int pdc_ata_init_one(struct pci_dev *pdev,  			    const struct pci_device_id *ent)  { -	static int printed_version;  	const struct ata_port_info *pi = &pdc_port_info[ent->driver_data];  	const struct ata_port_info *ppi[PDC_MAX_PORTS];  	struct ata_host *host; +	struct pdc_host_priv *hpriv;  	void __iomem *host_mmio;  	int n_ports, i, rc;  	int is_sataii_tx4; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* enable and acquire resources */  	rc = pcim_enable_device(pdev); @@ -1219,9 +1220,14 @@ static int pdc_ata_init_one(struct pci_dev *pdev,  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);  	if (!host) { -		dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host\n"); +		dev_err(&pdev->dev, "failed to allocate host\n");  		return -ENOMEM;  	} +	hpriv = devm_kzalloc(&pdev->dev, sizeof *hpriv, GFP_KERNEL); +	if (!hpriv) +		return -ENOMEM; +	spin_lock_init(&hpriv->hard_reset_lock); +	host->private_data = hpriv;  	host->iomap = pcim_iomap_table(pdev);  	is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags); @@ -1253,21 +1259,10 @@ static int pdc_ata_init_one(struct pci_dev *pdev,  				 &pdc_ata_sht);  } -static int __init pdc_ata_init(void) -{ -	return pci_register_driver(&pdc_ata_pci_driver); -} - -static void __exit pdc_ata_exit(void) -{ -	pci_unregister_driver(&pdc_ata_pci_driver); -} +module_pci_driver(pdc_ata_pci_driver);  MODULE_AUTHOR("Jeff Garzik");  MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, pdc_ata_pci_tbl);  MODULE_VERSION(DRV_VERSION); - -module_init(pdc_ata_init); -module_exit(pdc_ata_exit); diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index daeebf19a6a..9a6bd4cd29a 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -31,7 +31,6 @@  #include <linux/module.h>  #include <linux/gfp.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -155,8 +154,7 @@ static struct ata_port_operations qs_ata_ops = {  static const struct ata_port_info qs_port_info[] = {  	/* board_2068_idx */  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, +		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_POLLING,  		.pio_mask	= ATA_PIO4_ONLY,  		.udma_mask	= ATA_UDMA6,  		.port_ops	= &qs_ata_ops, @@ -564,21 +562,20 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)  		if (rc) {  			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));  			if (rc) { -				dev_printk(KERN_ERR, &pdev->dev, -					   "64-bit DMA enable failed\n"); +				dev_err(&pdev->dev, +					"64-bit DMA enable failed\n");  				return rc;  			}  		}  	} else {  		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));  		if (rc) { -			dev_printk(KERN_ERR, &pdev->dev, -				"32-bit DMA enable failed\n"); +			dev_err(&pdev->dev, "32-bit DMA enable failed\n");  			return rc;  		}  		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));  		if (rc) { -			dev_printk(KERN_ERR, &pdev->dev, +			dev_err(&pdev->dev,  				"32-bit consistent DMA enable failed\n");  			return rc;  		} @@ -589,14 +586,12 @@ static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)  static int qs_ata_init_one(struct pci_dev *pdev,  				const struct pci_device_id *ent)  { -	static int printed_version;  	unsigned int board_idx = (unsigned int) ent->driver_data;  	const struct ata_port_info *ppi[] = { &qs_port_info[board_idx], NULL };  	struct ata_host *host;  	int rc, port_no; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* alloc host */  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, QS_PORTS); @@ -639,21 +634,10 @@ static int qs_ata_init_one(struct pci_dev *pdev,  				 &qs_ata_sht);  } -static int __init qs_ata_init(void) -{ -	return pci_register_driver(&qs_ata_pci_driver); -} - -static void __exit qs_ata_exit(void) -{ -	pci_unregister_driver(&qs_ata_pci_driver); -} +module_pci_driver(qs_ata_pci_driver);  MODULE_AUTHOR("Mark Lord");  MODULE_DESCRIPTION("Pacific Digital Corporation QStor SATA low-level driver");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, qs_ata_pci_tbl);  MODULE_VERSION(DRV_VERSION); - -module_init(qs_ata_init); -module_exit(qs_ata_exit); diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c new file mode 100644 index 00000000000..61eb6d77dac --- /dev/null +++ b/drivers/ata/sata_rcar.c @@ -0,0 +1,1004 @@ +/* + * Renesas R-Car SATA driver + * + * Author: Vladimir Barinov <source@cogentembedded.com> + * Copyright (C) 2013 Cogent Embedded, Inc. + * Copyright (C) 2013 Renesas Solutions Corp. + * + * This program is free software; you can redistribute  it and/or modify it + * under  the terms of  the GNU General  Public License as published by the + * Free Software Foundation;  either version 2 of the  License, or (at your + * option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/ata.h> +#include <linux/libata.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/err.h> + +#define DRV_NAME "sata_rcar" + +/* SH-Navi2G/ATAPI-ATA compatible task registers */ +#define DATA_REG			0x100 +#define SDEVCON_REG			0x138 + +/* SH-Navi2G/ATAPI module compatible control registers */ +#define ATAPI_CONTROL1_REG		0x180 +#define ATAPI_STATUS_REG		0x184 +#define ATAPI_INT_ENABLE_REG		0x188 +#define ATAPI_DTB_ADR_REG		0x198 +#define ATAPI_DMA_START_ADR_REG		0x19C +#define ATAPI_DMA_TRANS_CNT_REG		0x1A0 +#define ATAPI_CONTROL2_REG		0x1A4 +#define ATAPI_SIG_ST_REG		0x1B0 +#define ATAPI_BYTE_SWAP_REG		0x1BC + +/* ATAPI control 1 register (ATAPI_CONTROL1) bits */ +#define ATAPI_CONTROL1_ISM		BIT(16) +#define ATAPI_CONTROL1_DTA32M		BIT(11) +#define ATAPI_CONTROL1_RESET		BIT(7) +#define ATAPI_CONTROL1_DESE		BIT(3) +#define ATAPI_CONTROL1_RW		BIT(2) +#define ATAPI_CONTROL1_STOP		BIT(1) +#define ATAPI_CONTROL1_START		BIT(0) + +/* ATAPI status register (ATAPI_STATUS) bits */ +#define ATAPI_STATUS_SATAINT		BIT(11) +#define ATAPI_STATUS_DNEND		BIT(6) +#define ATAPI_STATUS_DEVTRM		BIT(5) +#define ATAPI_STATUS_DEVINT		BIT(4) +#define ATAPI_STATUS_ERR		BIT(2) +#define ATAPI_STATUS_NEND		BIT(1) +#define ATAPI_STATUS_ACT		BIT(0) + +/* Interrupt enable register (ATAPI_INT_ENABLE) bits */ +#define ATAPI_INT_ENABLE_SATAINT	BIT(11) +#define ATAPI_INT_ENABLE_DNEND		BIT(6) +#define ATAPI_INT_ENABLE_DEVTRM		BIT(5) +#define ATAPI_INT_ENABLE_DEVINT		BIT(4) +#define ATAPI_INT_ENABLE_ERR		BIT(2) +#define ATAPI_INT_ENABLE_NEND		BIT(1) +#define ATAPI_INT_ENABLE_ACT		BIT(0) + +/* Access control registers for physical layer control register */ +#define SATAPHYADDR_REG			0x200 +#define SATAPHYWDATA_REG		0x204 +#define SATAPHYACCEN_REG		0x208 +#define SATAPHYRESET_REG		0x20C +#define SATAPHYRDATA_REG		0x210 +#define SATAPHYACK_REG			0x214 + +/* Physical layer control address command register (SATAPHYADDR) bits */ +#define SATAPHYADDR_PHYRATEMODE		BIT(10) +#define SATAPHYADDR_PHYCMD_READ		BIT(9) +#define SATAPHYADDR_PHYCMD_WRITE	BIT(8) + +/* Physical layer control enable register (SATAPHYACCEN) bits */ +#define SATAPHYACCEN_PHYLANE		BIT(0) + +/* Physical layer control reset register (SATAPHYRESET) bits */ +#define SATAPHYRESET_PHYRST		BIT(1) +#define SATAPHYRESET_PHYSRES		BIT(0) + +/* Physical layer control acknowledge register (SATAPHYACK) bits */ +#define SATAPHYACK_PHYACK		BIT(0) + +/* Serial-ATA HOST control registers */ +#define BISTCONF_REG			0x102C +#define SDATA_REG			0x1100 +#define SSDEVCON_REG			0x1204 + +#define SCRSSTS_REG			0x1400 +#define SCRSERR_REG			0x1404 +#define SCRSCON_REG			0x1408 +#define SCRSACT_REG			0x140C + +#define SATAINTSTAT_REG			0x1508 +#define SATAINTMASK_REG			0x150C + +/* SATA INT status register (SATAINTSTAT) bits */ +#define SATAINTSTAT_SERR		BIT(3) +#define SATAINTSTAT_ATA			BIT(0) + +/* SATA INT mask register (SATAINTSTAT) bits */ +#define SATAINTMASK_SERRMSK		BIT(3) +#define SATAINTMASK_ERRMSK		BIT(2) +#define SATAINTMASK_ERRCRTMSK		BIT(1) +#define SATAINTMASK_ATAMSK		BIT(0) + +#define SATA_RCAR_INT_MASK		(SATAINTMASK_SERRMSK | \ +					 SATAINTMASK_ATAMSK) + +/* Physical Layer Control Registers */ +#define SATAPCTLR1_REG			0x43 +#define SATAPCTLR2_REG			0x52 +#define SATAPCTLR3_REG			0x5A +#define SATAPCTLR4_REG			0x60 + +/* Descriptor table word 0 bit (when DTA32M = 1) */ +#define SATA_RCAR_DTEND			BIT(0) + +#define SATA_RCAR_DMA_BOUNDARY		0x1FFFFFFEUL + +/* Gen2 Physical Layer Control Registers */ +#define RCAR_GEN2_PHY_CTL1_REG		0x1704 +#define RCAR_GEN2_PHY_CTL1		0x34180002 +#define RCAR_GEN2_PHY_CTL1_SS		0xC180	/* Spread Spectrum */ + +#define RCAR_GEN2_PHY_CTL2_REG		0x170C +#define RCAR_GEN2_PHY_CTL2		0x00002303 + +#define RCAR_GEN2_PHY_CTL3_REG		0x171C +#define RCAR_GEN2_PHY_CTL3		0x000B0194 + +#define RCAR_GEN2_PHY_CTL4_REG		0x1724 +#define RCAR_GEN2_PHY_CTL4		0x00030994 + +#define RCAR_GEN2_PHY_CTL5_REG		0x1740 +#define RCAR_GEN2_PHY_CTL5		0x03004001 +#define RCAR_GEN2_PHY_CTL5_DC		BIT(1)	/* DC connection */ +#define RCAR_GEN2_PHY_CTL5_TR		BIT(2)	/* Termination Resistor */ + +enum sata_rcar_type { +	RCAR_GEN1_SATA, +	RCAR_GEN2_SATA, +}; + +struct sata_rcar_priv { +	void __iomem *base; +	struct clk *clk; +	enum sata_rcar_type type; +}; + +static void sata_rcar_gen1_phy_preinit(struct sata_rcar_priv *priv) +{ +	void __iomem *base = priv->base; + +	/* idle state */ +	iowrite32(0, base + SATAPHYADDR_REG); +	/* reset */ +	iowrite32(SATAPHYRESET_PHYRST, base + SATAPHYRESET_REG); +	udelay(10); +	/* deassert reset */ +	iowrite32(0, base + SATAPHYRESET_REG); +} + +static void sata_rcar_gen1_phy_write(struct sata_rcar_priv *priv, u16 reg, +				     u32 val, int group) +{ +	void __iomem *base = priv->base; +	int timeout; + +	/* deassert reset */ +	iowrite32(0, base + SATAPHYRESET_REG); +	/* lane 1 */ +	iowrite32(SATAPHYACCEN_PHYLANE, base + SATAPHYACCEN_REG); +	/* write phy register value */ +	iowrite32(val, base + SATAPHYWDATA_REG); +	/* set register group */ +	if (group) +		reg |= SATAPHYADDR_PHYRATEMODE; +	/* write command */ +	iowrite32(SATAPHYADDR_PHYCMD_WRITE | reg, base + SATAPHYADDR_REG); +	/* wait for ack */ +	for (timeout = 0; timeout < 100; timeout++) { +		val = ioread32(base + SATAPHYACK_REG); +		if (val & SATAPHYACK_PHYACK) +			break; +	} +	if (timeout >= 100) +		pr_err("%s timeout\n", __func__); +	/* idle state */ +	iowrite32(0, base + SATAPHYADDR_REG); +} + +static void sata_rcar_gen1_phy_init(struct sata_rcar_priv *priv) +{ +	sata_rcar_gen1_phy_preinit(priv); +	sata_rcar_gen1_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 0); +	sata_rcar_gen1_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 1); +	sata_rcar_gen1_phy_write(priv, SATAPCTLR3_REG, 0x0000A061, 0); +	sata_rcar_gen1_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 0); +	sata_rcar_gen1_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 1); +	sata_rcar_gen1_phy_write(priv, SATAPCTLR4_REG, 0x28E80000, 0); +} + +static void sata_rcar_gen2_phy_init(struct sata_rcar_priv *priv) +{ +	void __iomem *base = priv->base; + +	iowrite32(RCAR_GEN2_PHY_CTL1, base + RCAR_GEN2_PHY_CTL1_REG); +	iowrite32(RCAR_GEN2_PHY_CTL2, base + RCAR_GEN2_PHY_CTL2_REG); +	iowrite32(RCAR_GEN2_PHY_CTL3, base + RCAR_GEN2_PHY_CTL3_REG); +	iowrite32(RCAR_GEN2_PHY_CTL4, base + RCAR_GEN2_PHY_CTL4_REG); +	iowrite32(RCAR_GEN2_PHY_CTL5 | RCAR_GEN2_PHY_CTL5_DC | +		  RCAR_GEN2_PHY_CTL5_TR, base + RCAR_GEN2_PHY_CTL5_REG); +} + +static void sata_rcar_freeze(struct ata_port *ap) +{ +	struct sata_rcar_priv *priv = ap->host->private_data; + +	/* mask */ +	iowrite32(0x7ff, priv->base + SATAINTMASK_REG); + +	ata_sff_freeze(ap); +} + +static void sata_rcar_thaw(struct ata_port *ap) +{ +	struct sata_rcar_priv *priv = ap->host->private_data; +	void __iomem *base = priv->base; + +	/* ack */ +	iowrite32(~(u32)SATA_RCAR_INT_MASK, base + SATAINTSTAT_REG); + +	ata_sff_thaw(ap); + +	/* unmask */ +	iowrite32(0x7ff & ~SATA_RCAR_INT_MASK, base + SATAINTMASK_REG); +} + +static void sata_rcar_ioread16_rep(void __iomem *reg, void *buffer, int count) +{ +	u16 *ptr = buffer; + +	while (count--) { +		u16 data = ioread32(reg); + +		*ptr++ = data; +	} +} + +static void sata_rcar_iowrite16_rep(void __iomem *reg, void *buffer, int count) +{ +	const u16 *ptr = buffer; + +	while (count--) +		iowrite32(*ptr++, reg); +} + +static u8 sata_rcar_check_status(struct ata_port *ap) +{ +	return ioread32(ap->ioaddr.status_addr); +} + +static u8 sata_rcar_check_altstatus(struct ata_port *ap) +{ +	return ioread32(ap->ioaddr.altstatus_addr); +} + +static void sata_rcar_set_devctl(struct ata_port *ap, u8 ctl) +{ +	iowrite32(ctl, ap->ioaddr.ctl_addr); +} + +static void sata_rcar_dev_select(struct ata_port *ap, unsigned int device) +{ +	iowrite32(ATA_DEVICE_OBS, ap->ioaddr.device_addr); +	ata_sff_pause(ap);	/* needed; also flushes, for mmio */ +} + +static unsigned int sata_rcar_ata_devchk(struct ata_port *ap, +					 unsigned int device) +{ +	struct ata_ioports *ioaddr = &ap->ioaddr; +	u8 nsect, lbal; + +	sata_rcar_dev_select(ap, device); + +	iowrite32(0x55, ioaddr->nsect_addr); +	iowrite32(0xaa, ioaddr->lbal_addr); + +	iowrite32(0xaa, ioaddr->nsect_addr); +	iowrite32(0x55, ioaddr->lbal_addr); + +	iowrite32(0x55, ioaddr->nsect_addr); +	iowrite32(0xaa, ioaddr->lbal_addr); + +	nsect = ioread32(ioaddr->nsect_addr); +	lbal  = ioread32(ioaddr->lbal_addr); + +	if (nsect == 0x55 && lbal == 0xaa) +		return 1;	/* found a device */ + +	return 0;		/* nothing found */ +} + +static int sata_rcar_wait_after_reset(struct ata_link *link, +				      unsigned long deadline) +{ +	struct ata_port *ap = link->ap; + +	ata_msleep(ap, ATA_WAIT_AFTER_RESET); + +	return ata_sff_wait_ready(link, deadline); +} + +static int sata_rcar_bus_softreset(struct ata_port *ap, unsigned long deadline) +{ +	struct ata_ioports *ioaddr = &ap->ioaddr; + +	DPRINTK("ata%u: bus reset via SRST\n", ap->print_id); + +	/* software reset.  causes dev0 to be selected */ +	iowrite32(ap->ctl, ioaddr->ctl_addr); +	udelay(20); +	iowrite32(ap->ctl | ATA_SRST, ioaddr->ctl_addr); +	udelay(20); +	iowrite32(ap->ctl, ioaddr->ctl_addr); +	ap->last_ctl = ap->ctl; + +	/* wait the port to become ready */ +	return sata_rcar_wait_after_reset(&ap->link, deadline); +} + +static int sata_rcar_softreset(struct ata_link *link, unsigned int *classes, +			       unsigned long deadline) +{ +	struct ata_port *ap = link->ap; +	unsigned int devmask = 0; +	int rc; +	u8 err; + +	/* determine if device 0 is present */ +	if (sata_rcar_ata_devchk(ap, 0)) +		devmask |= 1 << 0; + +	/* issue bus reset */ +	DPRINTK("about to softreset, devmask=%x\n", devmask); +	rc = sata_rcar_bus_softreset(ap, deadline); +	/* if link is occupied, -ENODEV too is an error */ +	if (rc && (rc != -ENODEV || sata_scr_valid(link))) { +		ata_link_err(link, "SRST failed (errno=%d)\n", rc); +		return rc; +	} + +	/* determine by signature whether we have ATA or ATAPI devices */ +	classes[0] = ata_sff_dev_classify(&link->device[0], devmask, &err); + +	DPRINTK("classes[0]=%u\n", classes[0]); +	return 0; +} + +static void sata_rcar_tf_load(struct ata_port *ap, +			      const struct ata_taskfile *tf) +{ +	struct ata_ioports *ioaddr = &ap->ioaddr; +	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; + +	if (tf->ctl != ap->last_ctl) { +		iowrite32(tf->ctl, ioaddr->ctl_addr); +		ap->last_ctl = tf->ctl; +		ata_wait_idle(ap); +	} + +	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { +		iowrite32(tf->hob_feature, ioaddr->feature_addr); +		iowrite32(tf->hob_nsect, ioaddr->nsect_addr); +		iowrite32(tf->hob_lbal, ioaddr->lbal_addr); +		iowrite32(tf->hob_lbam, ioaddr->lbam_addr); +		iowrite32(tf->hob_lbah, ioaddr->lbah_addr); +		VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", +			tf->hob_feature, +			tf->hob_nsect, +			tf->hob_lbal, +			tf->hob_lbam, +			tf->hob_lbah); +	} + +	if (is_addr) { +		iowrite32(tf->feature, ioaddr->feature_addr); +		iowrite32(tf->nsect, ioaddr->nsect_addr); +		iowrite32(tf->lbal, ioaddr->lbal_addr); +		iowrite32(tf->lbam, ioaddr->lbam_addr); +		iowrite32(tf->lbah, ioaddr->lbah_addr); +		VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", +			tf->feature, +			tf->nsect, +			tf->lbal, +			tf->lbam, +			tf->lbah); +	} + +	if (tf->flags & ATA_TFLAG_DEVICE) { +		iowrite32(tf->device, ioaddr->device_addr); +		VPRINTK("device 0x%X\n", tf->device); +	} + +	ata_wait_idle(ap); +} + +static void sata_rcar_tf_read(struct ata_port *ap, struct ata_taskfile *tf) +{ +	struct ata_ioports *ioaddr = &ap->ioaddr; + +	tf->command = sata_rcar_check_status(ap); +	tf->feature = ioread32(ioaddr->error_addr); +	tf->nsect = ioread32(ioaddr->nsect_addr); +	tf->lbal = ioread32(ioaddr->lbal_addr); +	tf->lbam = ioread32(ioaddr->lbam_addr); +	tf->lbah = ioread32(ioaddr->lbah_addr); +	tf->device = ioread32(ioaddr->device_addr); + +	if (tf->flags & ATA_TFLAG_LBA48) { +		iowrite32(tf->ctl | ATA_HOB, ioaddr->ctl_addr); +		tf->hob_feature = ioread32(ioaddr->error_addr); +		tf->hob_nsect = ioread32(ioaddr->nsect_addr); +		tf->hob_lbal = ioread32(ioaddr->lbal_addr); +		tf->hob_lbam = ioread32(ioaddr->lbam_addr); +		tf->hob_lbah = ioread32(ioaddr->lbah_addr); +		iowrite32(tf->ctl, ioaddr->ctl_addr); +		ap->last_ctl = tf->ctl; +	} +} + +static void sata_rcar_exec_command(struct ata_port *ap, +				   const struct ata_taskfile *tf) +{ +	DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command); + +	iowrite32(tf->command, ap->ioaddr.command_addr); +	ata_sff_pause(ap); +} + +static unsigned int sata_rcar_data_xfer(struct ata_device *dev, +					      unsigned char *buf, +					      unsigned int buflen, int rw) +{ +	struct ata_port *ap = dev->link->ap; +	void __iomem *data_addr = ap->ioaddr.data_addr; +	unsigned int words = buflen >> 1; + +	/* Transfer multiple of 2 bytes */ +	if (rw == READ) +		sata_rcar_ioread16_rep(data_addr, buf, words); +	else +		sata_rcar_iowrite16_rep(data_addr, buf, words); + +	/* Transfer trailing byte, if any. */ +	if (unlikely(buflen & 0x01)) { +		unsigned char pad[2] = { }; + +		/* Point buf to the tail of buffer */ +		buf += buflen - 1; + +		/* +		 * Use io*16_rep() accessors here as well to avoid pointlessly +		 * swapping bytes to and from on the big endian machines... +		 */ +		if (rw == READ) { +			sata_rcar_ioread16_rep(data_addr, pad, 1); +			*buf = pad[0]; +		} else { +			pad[0] = *buf; +			sata_rcar_iowrite16_rep(data_addr, pad, 1); +		} +		words++; +	} + +	return words << 1; +} + +static void sata_rcar_drain_fifo(struct ata_queued_cmd *qc) +{ +	int count; +	struct ata_port *ap; + +	/* We only need to flush incoming data when a command was running */ +	if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE) +		return; + +	ap = qc->ap; +	/* Drain up to 64K of data before we give up this recovery method */ +	for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ) && +			count < 65536; count += 2) +		ioread32(ap->ioaddr.data_addr); + +	/* Can become DEBUG later */ +	if (count) +		ata_port_dbg(ap, "drained %d bytes to clear DRQ\n", count); +} + +static int sata_rcar_scr_read(struct ata_link *link, unsigned int sc_reg, +			      u32 *val) +{ +	if (sc_reg > SCR_ACTIVE) +		return -EINVAL; + +	*val = ioread32(link->ap->ioaddr.scr_addr + (sc_reg << 2)); +	return 0; +} + +static int sata_rcar_scr_write(struct ata_link *link, unsigned int sc_reg, +			       u32 val) +{ +	if (sc_reg > SCR_ACTIVE) +		return -EINVAL; + +	iowrite32(val, link->ap->ioaddr.scr_addr + (sc_reg << 2)); +	return 0; +} + +static void sata_rcar_bmdma_fill_sg(struct ata_queued_cmd *qc) +{ +	struct ata_port *ap = qc->ap; +	struct ata_bmdma_prd *prd = ap->bmdma_prd; +	struct scatterlist *sg; +	unsigned int si; + +	for_each_sg(qc->sg, sg, qc->n_elem, si) { +		u32 addr, sg_len; + +		/* +		 * Note: h/w doesn't support 64-bit, so we unconditionally +		 * truncate dma_addr_t to u32. +		 */ +		addr = (u32)sg_dma_address(sg); +		sg_len = sg_dma_len(sg); + +		prd[si].addr = cpu_to_le32(addr); +		prd[si].flags_len = cpu_to_le32(sg_len); +		VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", si, addr, sg_len); +	} + +	/* end-of-table flag */ +	prd[si - 1].addr |= cpu_to_le32(SATA_RCAR_DTEND); +} + +static void sata_rcar_qc_prep(struct ata_queued_cmd *qc) +{ +	if (!(qc->flags & ATA_QCFLAG_DMAMAP)) +		return; + +	sata_rcar_bmdma_fill_sg(qc); +} + +static void sata_rcar_bmdma_setup(struct ata_queued_cmd *qc) +{ +	struct ata_port *ap = qc->ap; +	unsigned int rw = qc->tf.flags & ATA_TFLAG_WRITE; +	struct sata_rcar_priv *priv = ap->host->private_data; +	void __iomem *base = priv->base; +	u32 dmactl; + +	/* load PRD table addr. */ +	mb();   /* make sure PRD table writes are visible to controller */ +	iowrite32(ap->bmdma_prd_dma, base + ATAPI_DTB_ADR_REG); + +	/* specify data direction, triple-check start bit is clear */ +	dmactl = ioread32(base + ATAPI_CONTROL1_REG); +	dmactl &= ~(ATAPI_CONTROL1_RW | ATAPI_CONTROL1_STOP); +	if (dmactl & ATAPI_CONTROL1_START) { +		dmactl &= ~ATAPI_CONTROL1_START; +		dmactl |= ATAPI_CONTROL1_STOP; +	} +	if (!rw) +		dmactl |= ATAPI_CONTROL1_RW; +	iowrite32(dmactl, base + ATAPI_CONTROL1_REG); + +	/* issue r/w command */ +	ap->ops->sff_exec_command(ap, &qc->tf); +} + +static void sata_rcar_bmdma_start(struct ata_queued_cmd *qc) +{ +	struct ata_port *ap = qc->ap; +	struct sata_rcar_priv *priv = ap->host->private_data; +	void __iomem *base = priv->base; +	u32 dmactl; + +	/* start host DMA transaction */ +	dmactl = ioread32(base + ATAPI_CONTROL1_REG); +	dmactl &= ~ATAPI_CONTROL1_STOP; +	dmactl |= ATAPI_CONTROL1_START; +	iowrite32(dmactl, base + ATAPI_CONTROL1_REG); +} + +static void sata_rcar_bmdma_stop(struct ata_queued_cmd *qc) +{ +	struct ata_port *ap = qc->ap; +	struct sata_rcar_priv *priv = ap->host->private_data; +	void __iomem *base = priv->base; +	u32 dmactl; + +	/* force termination of DMA transfer if active */ +	dmactl = ioread32(base + ATAPI_CONTROL1_REG); +	if (dmactl & ATAPI_CONTROL1_START) { +		dmactl &= ~ATAPI_CONTROL1_START; +		dmactl |= ATAPI_CONTROL1_STOP; +		iowrite32(dmactl, base + ATAPI_CONTROL1_REG); +	} + +	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ +	ata_sff_dma_pause(ap); +} + +static u8 sata_rcar_bmdma_status(struct ata_port *ap) +{ +	struct sata_rcar_priv *priv = ap->host->private_data; +	u8 host_stat = 0; +	u32 status; + +	status = ioread32(priv->base + ATAPI_STATUS_REG); +	if (status & ATAPI_STATUS_DEVINT) +		host_stat |= ATA_DMA_INTR; +	if (status & ATAPI_STATUS_ACT) +		host_stat |= ATA_DMA_ACTIVE; + +	return host_stat; +} + +static struct scsi_host_template sata_rcar_sht = { +	ATA_BASE_SHT(DRV_NAME), +	/* +	 * This controller allows transfer chunks up to 512MB which cross 64KB +	 * boundaries, therefore the DMA limits are more relaxed than standard +	 * ATA SFF. +	 */ +	.sg_tablesize		= ATA_MAX_PRD, +	.dma_boundary		= SATA_RCAR_DMA_BOUNDARY, +}; + +static struct ata_port_operations sata_rcar_port_ops = { +	.inherits		= &ata_bmdma_port_ops, + +	.freeze			= sata_rcar_freeze, +	.thaw			= sata_rcar_thaw, +	.softreset		= sata_rcar_softreset, + +	.scr_read		= sata_rcar_scr_read, +	.scr_write		= sata_rcar_scr_write, + +	.sff_dev_select		= sata_rcar_dev_select, +	.sff_set_devctl		= sata_rcar_set_devctl, +	.sff_check_status	= sata_rcar_check_status, +	.sff_check_altstatus	= sata_rcar_check_altstatus, +	.sff_tf_load		= sata_rcar_tf_load, +	.sff_tf_read		= sata_rcar_tf_read, +	.sff_exec_command	= sata_rcar_exec_command, +	.sff_data_xfer		= sata_rcar_data_xfer, +	.sff_drain_fifo		= sata_rcar_drain_fifo, + +	.qc_prep		= sata_rcar_qc_prep, + +	.bmdma_setup		= sata_rcar_bmdma_setup, +	.bmdma_start		= sata_rcar_bmdma_start, +	.bmdma_stop		= sata_rcar_bmdma_stop, +	.bmdma_status		= sata_rcar_bmdma_status, +}; + +static void sata_rcar_serr_interrupt(struct ata_port *ap) +{ +	struct sata_rcar_priv *priv = ap->host->private_data; +	struct ata_eh_info *ehi = &ap->link.eh_info; +	int freeze = 0; +	u32 serror; + +	serror = ioread32(priv->base + SCRSERR_REG); +	if (!serror) +		return; + +	DPRINTK("SError @host_intr: 0x%x\n", serror); + +	/* first, analyze and record host port events */ +	ata_ehi_clear_desc(ehi); + +	if (serror & (SERR_DEV_XCHG | SERR_PHYRDY_CHG)) { +		/* Setup a soft-reset EH action */ +		ata_ehi_hotplugged(ehi); +		ata_ehi_push_desc(ehi, "%s", "hotplug"); + +		freeze = serror & SERR_COMM_WAKE ? 0 : 1; +	} + +	/* freeze or abort */ +	if (freeze) +		ata_port_freeze(ap); +	else +		ata_port_abort(ap); +} + +static void sata_rcar_ata_interrupt(struct ata_port *ap) +{ +	struct ata_queued_cmd *qc; +	int handled = 0; + +	qc = ata_qc_from_tag(ap, ap->link.active_tag); +	if (qc) +		handled |= ata_bmdma_port_intr(ap, qc); + +	/* be sure to clear ATA interrupt */ +	if (!handled) +		sata_rcar_check_status(ap); +} + +static irqreturn_t sata_rcar_interrupt(int irq, void *dev_instance) +{ +	struct ata_host *host = dev_instance; +	struct sata_rcar_priv *priv = host->private_data; +	void __iomem *base = priv->base; +	unsigned int handled = 0; +	struct ata_port *ap; +	u32 sataintstat; +	unsigned long flags; + +	spin_lock_irqsave(&host->lock, flags); + +	sataintstat = ioread32(base + SATAINTSTAT_REG); +	sataintstat &= SATA_RCAR_INT_MASK; +	if (!sataintstat) +		goto done; +	/* ack */ +	iowrite32(~sataintstat & 0x7ff, base + SATAINTSTAT_REG); + +	ap = host->ports[0]; + +	if (sataintstat & SATAINTSTAT_ATA) +		sata_rcar_ata_interrupt(ap); + +	if (sataintstat & SATAINTSTAT_SERR) +		sata_rcar_serr_interrupt(ap); + +	handled = 1; +done: +	spin_unlock_irqrestore(&host->lock, flags); + +	return IRQ_RETVAL(handled); +} + +static void sata_rcar_setup_port(struct ata_host *host) +{ +	struct ata_port *ap = host->ports[0]; +	struct ata_ioports *ioaddr = &ap->ioaddr; +	struct sata_rcar_priv *priv = host->private_data; +	void __iomem *base = priv->base; + +	ap->ops		= &sata_rcar_port_ops; +	ap->pio_mask	= ATA_PIO4; +	ap->udma_mask	= ATA_UDMA6; +	ap->flags	|= ATA_FLAG_SATA; + +	ioaddr->cmd_addr = base + SDATA_REG; +	ioaddr->ctl_addr = base + SSDEVCON_REG; +	ioaddr->scr_addr = base + SCRSSTS_REG; +	ioaddr->altstatus_addr = ioaddr->ctl_addr; + +	ioaddr->data_addr	= ioaddr->cmd_addr + (ATA_REG_DATA << 2); +	ioaddr->error_addr	= ioaddr->cmd_addr + (ATA_REG_ERR << 2); +	ioaddr->feature_addr	= ioaddr->cmd_addr + (ATA_REG_FEATURE << 2); +	ioaddr->nsect_addr	= ioaddr->cmd_addr + (ATA_REG_NSECT << 2); +	ioaddr->lbal_addr	= ioaddr->cmd_addr + (ATA_REG_LBAL << 2); +	ioaddr->lbam_addr	= ioaddr->cmd_addr + (ATA_REG_LBAM << 2); +	ioaddr->lbah_addr	= ioaddr->cmd_addr + (ATA_REG_LBAH << 2); +	ioaddr->device_addr	= ioaddr->cmd_addr + (ATA_REG_DEVICE << 2); +	ioaddr->status_addr	= ioaddr->cmd_addr + (ATA_REG_STATUS << 2); +	ioaddr->command_addr	= ioaddr->cmd_addr + (ATA_REG_CMD << 2); +} + +static void sata_rcar_init_controller(struct ata_host *host) +{ +	struct sata_rcar_priv *priv = host->private_data; +	void __iomem *base = priv->base; +	u32 val; + +	/* reset and setup phy */ +	switch (priv->type) { +	case RCAR_GEN1_SATA: +		sata_rcar_gen1_phy_init(priv); +		break; +	case RCAR_GEN2_SATA: +		sata_rcar_gen2_phy_init(priv); +		break; +	default: +		dev_warn(host->dev, "SATA phy is not initialized\n"); +		break; +	} + +	/* SATA-IP reset state */ +	val = ioread32(base + ATAPI_CONTROL1_REG); +	val |= ATAPI_CONTROL1_RESET; +	iowrite32(val, base + ATAPI_CONTROL1_REG); + +	/* ISM mode, PRD mode, DTEND flag at bit 0 */ +	val = ioread32(base + ATAPI_CONTROL1_REG); +	val |= ATAPI_CONTROL1_ISM; +	val |= ATAPI_CONTROL1_DESE; +	val |= ATAPI_CONTROL1_DTA32M; +	iowrite32(val, base + ATAPI_CONTROL1_REG); + +	/* Release the SATA-IP from the reset state */ +	val = ioread32(base + ATAPI_CONTROL1_REG); +	val &= ~ATAPI_CONTROL1_RESET; +	iowrite32(val, base + ATAPI_CONTROL1_REG); + +	/* ack and mask */ +	iowrite32(0, base + SATAINTSTAT_REG); +	iowrite32(0x7ff, base + SATAINTMASK_REG); +	/* enable interrupts */ +	iowrite32(ATAPI_INT_ENABLE_SATAINT, base + ATAPI_INT_ENABLE_REG); +} + +static struct of_device_id sata_rcar_match[] = { +	{ +		/* Deprecated by "renesas,sata-r8a7779" */ +		.compatible = "renesas,rcar-sata", +		.data = (void *)RCAR_GEN1_SATA, +	}, +	{ +		.compatible = "renesas,sata-r8a7779", +		.data = (void *)RCAR_GEN1_SATA, +	}, +	{ +		.compatible = "renesas,sata-r8a7790", +		.data = (void *)RCAR_GEN2_SATA +	}, +	{ +		.compatible = "renesas,sata-r8a7791", +		.data = (void *)RCAR_GEN2_SATA +	}, +	{ }, +}; +MODULE_DEVICE_TABLE(of, sata_rcar_match); + +static const struct platform_device_id sata_rcar_id_table[] = { +	{ "sata_rcar", RCAR_GEN1_SATA }, /* Deprecated by "sata-r8a7779" */ +	{ "sata-r8a7779", RCAR_GEN1_SATA }, +	{ "sata-r8a7790", RCAR_GEN2_SATA }, +	{ "sata-r8a7791", RCAR_GEN2_SATA }, +	{ }, +}; +MODULE_DEVICE_TABLE(platform, sata_rcar_id_table); + +static int sata_rcar_probe(struct platform_device *pdev) +{ +	const struct of_device_id *of_id; +	struct ata_host *host; +	struct sata_rcar_priv *priv; +	struct resource *mem; +	int irq; +	int ret = 0; + +	irq = platform_get_irq(pdev, 0); +	if (irq <= 0) +		return -EINVAL; + +	priv = devm_kzalloc(&pdev->dev, sizeof(struct sata_rcar_priv), +			   GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	of_id = of_match_device(sata_rcar_match, &pdev->dev); +	if (of_id) +		priv->type = (enum sata_rcar_type)of_id->data; +	else +		priv->type = platform_get_device_id(pdev)->driver_data; + +	priv->clk = devm_clk_get(&pdev->dev, NULL); +	if (IS_ERR(priv->clk)) { +		dev_err(&pdev->dev, "failed to get access to sata clock\n"); +		return PTR_ERR(priv->clk); +	} +	clk_prepare_enable(priv->clk); + +	host = ata_host_alloc(&pdev->dev, 1); +	if (!host) { +		dev_err(&pdev->dev, "ata_host_alloc failed\n"); +		ret = -ENOMEM; +		goto cleanup; +	} + +	host->private_data = priv; + +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	priv->base = devm_ioremap_resource(&pdev->dev, mem); +	if (IS_ERR(priv->base)) { +		ret = PTR_ERR(priv->base); +		goto cleanup; +	} + +	/* setup port */ +	sata_rcar_setup_port(host); + +	/* initialize host controller */ +	sata_rcar_init_controller(host); + +	ret = ata_host_activate(host, irq, sata_rcar_interrupt, 0, +				&sata_rcar_sht); +	if (!ret) +		return 0; + +cleanup: +	clk_disable_unprepare(priv->clk); + +	return ret; +} + +static int sata_rcar_remove(struct platform_device *pdev) +{ +	struct ata_host *host = platform_get_drvdata(pdev); +	struct sata_rcar_priv *priv = host->private_data; +	void __iomem *base = priv->base; + +	ata_host_detach(host); + +	/* disable interrupts */ +	iowrite32(0, base + ATAPI_INT_ENABLE_REG); +	/* ack and mask */ +	iowrite32(0, base + SATAINTSTAT_REG); +	iowrite32(0x7ff, base + SATAINTMASK_REG); + +	clk_disable_unprepare(priv->clk); + +	return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int sata_rcar_suspend(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	struct sata_rcar_priv *priv = host->private_data; +	void __iomem *base = priv->base; +	int ret; + +	ret = ata_host_suspend(host, PMSG_SUSPEND); +	if (!ret) { +		/* disable interrupts */ +		iowrite32(0, base + ATAPI_INT_ENABLE_REG); +		/* mask */ +		iowrite32(0x7ff, base + SATAINTMASK_REG); + +		clk_disable_unprepare(priv->clk); +	} + +	return ret; +} + +static int sata_rcar_resume(struct device *dev) +{ +	struct ata_host *host = dev_get_drvdata(dev); +	struct sata_rcar_priv *priv = host->private_data; +	void __iomem *base = priv->base; + +	clk_prepare_enable(priv->clk); + +	/* ack and mask */ +	iowrite32(0, base + SATAINTSTAT_REG); +	iowrite32(0x7ff, base + SATAINTMASK_REG); +	/* enable interrupts */ +	iowrite32(ATAPI_INT_ENABLE_SATAINT, base + ATAPI_INT_ENABLE_REG); + +	ata_host_resume(host); + +	return 0; +} + +static const struct dev_pm_ops sata_rcar_pm_ops = { +	.suspend	= sata_rcar_suspend, +	.resume		= sata_rcar_resume, +}; +#endif + +static struct platform_driver sata_rcar_driver = { +	.probe		= sata_rcar_probe, +	.remove		= sata_rcar_remove, +	.id_table	= sata_rcar_id_table, +	.driver = { +		.name		= DRV_NAME, +		.owner		= THIS_MODULE, +		.of_match_table	= sata_rcar_match, +#ifdef CONFIG_PM_SLEEP +		.pm		= &sata_rcar_pm_ops, +#endif +	}, +}; + +module_platform_driver(sata_rcar_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Vladimir Barinov"); +MODULE_DESCRIPTION("Renesas R-Car SATA controller low level driver"); diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 3a4f8421971..40b76b2d18c 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -1,7 +1,7 @@  /*   *  sata_sil.c - Silicon Image SATA   * - *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> + *  Maintained by:  Tejun Heo <tj@kernel.org>   *  		    Please ALWAYS copy linux-ide@vger.kernel.org   *		    on emails.   * @@ -37,7 +37,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -61,8 +60,7 @@ enum {  	SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),  	SIL_FLAG_MOD15WRITE	= (1 << 30), -	SIL_DFL_PORT_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO, +	SIL_DFL_PORT_FLAGS	= ATA_FLAG_SATA,  	/*  	 * Controller IDs @@ -114,7 +112,7 @@ enum {  };  static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int sil_pci_device_resume(struct pci_dev *pdev);  #endif  static void sil_dev_config(struct ata_device *dev); @@ -158,6 +156,7 @@ static const struct sil_drivelist {  	{ "ST380011ASL",	SIL_QUIRK_MOD15WRITE },  	{ "ST3120022ASL",	SIL_QUIRK_MOD15WRITE },  	{ "ST3160021ASL",	SIL_QUIRK_MOD15WRITE }, +	{ "TOSHIBA MK2561GSYN",	SIL_QUIRK_MOD15WRITE },  	{ "Maxtor 4D060H3",	SIL_QUIRK_UDMA5MAX },  	{ }  }; @@ -167,7 +166,7 @@ static struct pci_driver sil_pci_driver = {  	.id_table		= sil_pci_tbl,  	.probe			= sil_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= sil_pci_device_resume,  #endif @@ -439,7 +438,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)  	u8 status;  	if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) { -		u32 serror; +		u32 serror = 0xffffffff;  		/* SIEN doesn't mask SATA IRQs on some 3112s.  Those  		 * controllers continue to assert IRQ as long as @@ -644,8 +643,8 @@ static void sil_dev_config(struct ata_device *dev)  	    ((ap->flags & SIL_FLAG_MOD15WRITE) &&  	     (quirks & SIL_QUIRK_MOD15WRITE))) {  		if (print_info) -			ata_dev_printk(dev, KERN_INFO, "applying Seagate " -				       "errata fix (mod15write workaround)\n"); +			ata_dev_info(dev, +		"applying Seagate errata fix (mod15write workaround)\n");  		dev->max_sectors = 15;  		return;  	} @@ -653,8 +652,8 @@ static void sil_dev_config(struct ata_device *dev)  	/* limit to udma5 */  	if (quirks & SIL_QUIRK_UDMA5MAX) {  		if (print_info) -			ata_dev_printk(dev, KERN_INFO, "applying Maxtor " -				       "errata fix %s\n", model_num); +			ata_dev_info(dev, "applying Maxtor errata fix %s\n", +				     model_num);  		dev->udma_mask &= ATA_UDMA5;  		return;  	} @@ -677,8 +676,8 @@ static void sil_init_controller(struct ata_host *host)  			writew(cls << 8 | cls,  			       mmio_base + sil_port[i].fifo_cfg);  	} else -		dev_printk(KERN_WARNING, &pdev->dev, -			   "cache line size not set.  Driver may not function\n"); +		dev_warn(&pdev->dev, +			 "cache line size not set.  Driver may not function\n");  	/* Apply R_ERR on DMA activate FIS errata workaround */  	if (host->ports[0]->flags & SIL_FLAG_RERR_ON_DMA_ACT) { @@ -689,9 +688,8 @@ static void sil_init_controller(struct ata_host *host)  			if ((tmp & 0x3) != 0x01)  				continue;  			if (!cnt) -				dev_printk(KERN_INFO, &pdev->dev, -					   "Applying R_ERR on DMA activate " -					   "FIS errata fix\n"); +				dev_info(&pdev->dev, +					 "Applying R_ERR on DMA activate FIS errata fix\n");  			writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg);  			cnt++;  		} @@ -734,7 +732,6 @@ static bool sil_broken_system_poweroff(struct pci_dev *pdev)  static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	int board_id = ent->driver_data;  	struct ata_port_info pi = sil_port_info[board_id];  	const struct ata_port_info *ppi[] = { &pi, NULL }; @@ -743,8 +740,7 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	int n_ports, rc;  	unsigned int i; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* allocate host */  	n_ports = 2; @@ -806,10 +802,10 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  				 &sil_sht);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int sil_pci_device_resume(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	int rc;  	rc = ata_pci_device_do_resume(pdev); @@ -823,16 +819,4 @@ static int sil_pci_device_resume(struct pci_dev *pdev)  }  #endif -static int __init sil_init(void) -{ -	return pci_register_driver(&sil_pci_driver); -} - -static void __exit sil_exit(void) -{ -	pci_unregister_driver(&sil_pci_driver); -} - - -module_init(sil_init); -module_exit(sil_exit); +module_pci_driver(sil_pci_driver); diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index af41c6fd125..0534890f118 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -244,8 +244,7 @@ enum {  	BID_SIL3131		= 2,  	/* host flags */ -	SIL24_COMMON_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | +	SIL24_COMMON_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |  				  ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |  				  ATA_FLAG_AN | ATA_FLAG_PMP,  	SIL24_FLAG_PCIX_IRQ_WOC	= (1 << 24), /* IRQ loss errata on PCI-X */ @@ -269,7 +268,7 @@ union sil24_cmd_block {  	struct sil24_atapi_block atapi;  }; -static struct sil24_cerr_info { +static const struct sil24_cerr_info {  	unsigned int err_mask, action;  	const char *desc;  } sil24_cerr_db[] = { @@ -354,8 +353,10 @@ static void sil24_error_handler(struct ata_port *ap);  static void sil24_post_internal_cmd(struct ata_queued_cmd *qc);  static int sil24_port_start(struct ata_port *ap);  static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int sil24_pci_device_resume(struct pci_dev *pdev); +#endif +#ifdef CONFIG_PM  static int sil24_port_resume(struct ata_port *ap);  #endif @@ -376,7 +377,7 @@ static struct pci_driver sil24_pci_driver = {  	.id_table		= sil24_pci_tbl,  	.probe			= sil24_init_one,  	.remove			= ata_pci_remove_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= sil24_pci_device_resume,  #endif @@ -418,7 +419,7 @@ static struct ata_port_operations sil24_ops = {  #endif  }; -static int sata_sil24_msi;    /* Disable MSI */ +static bool sata_sil24_msi;    /* Disable MSI */  module_param_named(msi, sata_sil24_msi, bool, S_IRUGO);  MODULE_PARM_DESC(msi, "Enable MSI (Default: false)"); @@ -507,8 +508,6 @@ static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)  	void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL;  	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { -		void __iomem *addr; -		addr = scr_addr + sil24_scr_map[sc_reg] * 4;  		*val = readl(scr_addr + sil24_scr_map[sc_reg] * 4);  		return 0;  	} @@ -520,8 +519,6 @@ static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val)  	void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL;  	if (sc_reg < ARRAY_SIZE(sil24_scr_map)) { -		void __iomem *addr; -		addr = scr_addr + sil24_scr_map[sc_reg] * 4;  		writel(val, scr_addr + sil24_scr_map[sc_reg] * 4);  		return 0;  	} @@ -695,7 +692,7 @@ static int sil24_softreset(struct ata_link *link, unsigned int *class,  	return 0;   err: -	ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason); +	ata_link_err(link, "softreset failed (%s)\n", reason);  	return -EIO;  } @@ -715,8 +712,8 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class,  	 * This happens often after PM DMA CS errata.  	 */  	if (pp->do_port_rst) { -		ata_port_printk(ap, KERN_WARNING, "controller in dubious " -				"state, performing PORT_RST\n"); +		ata_port_warn(ap, +			      "controller in dubious state, performing PORT_RST\n");  		writel(PORT_CS_PORT_RST, port + PORT_CTRL_STAT);  		ata_msleep(ap, 10); @@ -774,7 +771,7 @@ static int sil24_hardreset(struct ata_link *link, unsigned int *class,  		goto retry;  	} -	ata_link_printk(link, KERN_ERR, "hardreset failed (%s)\n", reason); +	ata_link_err(link, "hardreset failed (%s)\n", reason);  	return -EIO;  } @@ -926,7 +923,7 @@ static void sil24_pmp_attach(struct ata_port *ap)  	if (sata_pmp_gscr_vendor(gscr) == 0x11ab &&  	    sata_pmp_gscr_devid(gscr) == 0x4140) { -		ata_port_printk(ap, KERN_INFO, +		ata_port_info(ap,  			"disabling NCQ support due to sil24-mv4140 quirk\n");  		ap->flags &= ~ATA_FLAG_NCQ;  	} @@ -947,8 +944,7 @@ static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,  	rc = sil24_init_port(link->ap);  	if (rc) { -		ata_link_printk(link, KERN_ERR, -				"hardreset failed (port not ready)\n"); +		ata_link_err(link, "hardreset failed (port not ready)\n");  		return rc;  	} @@ -1021,7 +1017,7 @@ static void sil24_error_intr(struct ata_port *ap)  	/* deal with command error */  	if (irq_stat & PORT_IRQ_ERROR) { -		struct sil24_cerr_info *ci = NULL; +		const struct sil24_cerr_info *ci = NULL;  		unsigned int err_mask = 0, action = 0;  		u32 context, cerr;  		int pmp; @@ -1142,8 +1138,8 @@ static inline void sil24_host_intr(struct ata_port *ap)  	/* spurious interrupts are expected if PCIX_IRQ_WOC */  	if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit()) -		ata_port_printk(ap, KERN_INFO, "spurious interrupt " -			"(slot_stat 0x%x active_tag %d sactive 0x%x)\n", +		ata_port_info(ap, +			"spurious interrupt (slot_stat 0x%x active_tag %d sactive 0x%x)\n",  			slot_stat, ap->link.active_tag, ap->link.sactive);  } @@ -1257,8 +1253,8 @@ static void sil24_init_controller(struct ata_host *host)  						PORT_CS_PORT_RST,  						PORT_CS_PORT_RST, 10, 100);  			if (tmp & PORT_CS_PORT_RST) -				dev_printk(KERN_ERR, host->dev, -					   "failed to clear port RST\n"); +				dev_err(host->dev, +					"failed to clear port RST\n");  		}  		/* configure port */ @@ -1272,7 +1268,6 @@ static void sil24_init_controller(struct ata_host *host)  static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  {  	extern int __MARKER__sil24_cmd_block_is_sized_wrongly; -	static int printed_version;  	struct ata_port_info pi = sil24_port_info[ent->driver_data];  	const struct ata_port_info *ppi[] = { &pi, NULL };  	void __iomem * const *iomap; @@ -1284,8 +1279,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (sizeof(union sil24_cmd_block) != PAGE_SIZE)  		__MARKER__sil24_cmd_block_is_sized_wrongly = 1; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* acquire resources */  	rc = pcim_enable_device(pdev); @@ -1303,9 +1297,8 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (pi.flags & SIL24_FLAG_PCIX_IRQ_WOC) {  		tmp = readl(iomap[SIL24_HOST_BAR] + HOST_CTRL);  		if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL)) -			dev_printk(KERN_INFO, &pdev->dev, -				   "Applying completion IRQ loss on PCI-X " -				   "errata fix\n"); +			dev_info(&pdev->dev, +				 "Applying completion IRQ loss on PCI-X errata fix\n");  		else  			pi.flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;  	} @@ -1323,22 +1316,21 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  		if (rc) {  			rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));  			if (rc) { -				dev_printk(KERN_ERR, &pdev->dev, -					   "64-bit DMA enable failed\n"); +				dev_err(&pdev->dev, +					"64-bit DMA enable failed\n");  				return rc;  			}  		}  	} else {  		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));  		if (rc) { -			dev_printk(KERN_ERR, &pdev->dev, -				   "32-bit DMA enable failed\n"); +			dev_err(&pdev->dev, "32-bit DMA enable failed\n");  			return rc;  		}  		rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));  		if (rc) { -			dev_printk(KERN_ERR, &pdev->dev, -				   "32-bit consistent DMA enable failed\n"); +			dev_err(&pdev->dev, +				"32-bit consistent DMA enable failed\n");  			return rc;  		}  	} @@ -1351,7 +1343,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	sil24_init_controller(host);  	if (sata_sil24_msi && !pci_enable_msi(pdev)) { -		dev_printk(KERN_INFO, &pdev->dev, "Using MSI\n"); +		dev_info(&pdev->dev, "Using MSI\n");  		pci_intx(pdev, 0);  	} @@ -1360,10 +1352,10 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  				 &sil24_sht);  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int sil24_pci_device_resume(struct pci_dev *pdev)  { -	struct ata_host *host = dev_get_drvdata(&pdev->dev); +	struct ata_host *host = pci_get_drvdata(pdev);  	void __iomem *host_base = host->iomap[SIL24_HOST_BAR];  	int rc; @@ -1380,7 +1372,9 @@ static int sil24_pci_device_resume(struct pci_dev *pdev)  	return 0;  } +#endif +#ifdef CONFIG_PM  static int sil24_port_resume(struct ata_port *ap)  {  	sil24_config_pmp(ap, ap->nr_pmp_links); @@ -1388,20 +1382,9 @@ static int sil24_port_resume(struct ata_port *ap)  }  #endif -static int __init sil24_init(void) -{ -	return pci_register_driver(&sil24_pci_driver); -} - -static void __exit sil24_exit(void) -{ -	pci_unregister_driver(&sil24_pci_driver); -} +module_pci_driver(sil24_pci_driver);  MODULE_AUTHOR("Tejun Heo");  MODULE_DESCRIPTION("Silicon Image 3124/3132 SATA low-level driver");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, sil24_pci_tbl); - -module_init(sil24_init); -module_exit(sil24_exit); diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 2bfe3ae0397..d1637ac40a7 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -33,7 +33,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -83,6 +82,10 @@ static struct pci_driver sis_pci_driver = {  	.id_table		= sis_pci_tbl,  	.probe			= sis_init_one,  	.remove			= ata_pci_remove_one, +#ifdef CONFIG_PM_SLEEP +	.suspend		= ata_pci_device_suspend, +	.resume			= ata_pci_device_resume, +#endif  };  static struct scsi_host_template sis_sht = { @@ -96,7 +99,7 @@ static struct ata_port_operations sis_ops = {  };  static const struct ata_port_info sis_port_info = { -	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, +	.flags		= ATA_FLAG_SATA,  	.pio_mask	= ATA_PIO4,  	.mwdma_mask	= ATA_MWDMA2,  	.udma_mask	= ATA_UDMA6, @@ -104,7 +107,7 @@ static const struct ata_port_info sis_port_info = {  };  MODULE_AUTHOR("Uwe Koziolek"); -MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller"); +MODULE_DESCRIPTION("low-level driver for Silicon Integrated Systems SATA controller");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, sis_pci_tbl);  MODULE_VERSION(DRV_VERSION); @@ -193,7 +196,6 @@ static int sis_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)  static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	struct ata_port_info pi = sis_port_info;  	const struct ata_port_info *ppi[] = { &pi, &pi };  	struct ata_host *host; @@ -202,8 +204,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	u8 port2_start = 0x20;  	int i, rc; -	if (!printed_version++) -		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -241,12 +242,12 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  			break;  		}  		if ((pmr & SIS_PMR_COMBINED) == 0) { -			dev_printk(KERN_INFO, &pdev->dev, -				   "Detected SiS 180/181/964 chipset in SATA mode\n"); +			dev_info(&pdev->dev, +				 "Detected SiS 180/181/964 chipset in SATA mode\n");  			port2_start = 64;  		} else { -			dev_printk(KERN_INFO, &pdev->dev, -				   "Detected SiS 180/181 chipset in combined mode\n"); +			dev_info(&pdev->dev, +				 "Detected SiS 180/181 chipset in combined mode\n");  			port2_start = 0;  			pi.flags |= ATA_FLAG_SLAVE_POSS;  		} @@ -256,24 +257,22 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	case 0x0183:  		pci_read_config_dword(pdev, 0x6C, &val);  		if (val & (1L << 31)) { -			dev_printk(KERN_INFO, &pdev->dev, -				   "Detected SiS 182/965 chipset\n"); +			dev_info(&pdev->dev, "Detected SiS 182/965 chipset\n");  			pi.flags |= ATA_FLAG_SLAVE_POSS;  		} else { -			dev_printk(KERN_INFO, &pdev->dev, -				   "Detected SiS 182/965L chipset\n"); +			dev_info(&pdev->dev, "Detected SiS 182/965L chipset\n");  		}  		break;  	case 0x1182: -		dev_printk(KERN_INFO, &pdev->dev, -			   "Detected SiS 1182/966/680 SATA controller\n"); +		dev_info(&pdev->dev, +			 "Detected SiS 1182/966/680 SATA controller\n");  		pi.flags |= ATA_FLAG_SLAVE_POSS;  		break;  	case 0x1183: -		dev_printk(KERN_INFO, &pdev->dev, -			   "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n"); +		dev_info(&pdev->dev, +			 "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n");  		ppi[0] = &sis_info133_for_sata;  		ppi[1] = &sis_info133_for_sata;  		break; @@ -312,15 +311,4 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  				 IRQF_SHARED, &sis_sht);  } -static int __init sis_init(void) -{ -	return pci_register_driver(&sis_pci_driver); -} - -static void __exit sis_exit(void) -{ -	pci_unregister_driver(&sis_pci_driver); -} - -module_init(sis_init); -module_exit(sis_exit); +module_pci_driver(sis_pci_driver); diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index 7d9db4aaf07..c630fa81262 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -39,7 +39,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -142,6 +141,39 @@ static int k2_sata_scr_write(struct ata_link *link,  	return 0;  } +static int k2_sata_softreset(struct ata_link *link, +			     unsigned int *class, unsigned long deadline) +{ +	u8 dmactl; +	void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + +	dmactl = readb(mmio + ATA_DMA_CMD); + +	/* Clear the start bit */ +	if (dmactl & ATA_DMA_START) { +		dmactl &= ~ATA_DMA_START; +		writeb(dmactl, mmio + ATA_DMA_CMD); +	} + +	return ata_sff_softreset(link, class, deadline); +} + +static int k2_sata_hardreset(struct ata_link *link, +			     unsigned int *class, unsigned long deadline) +{ +	u8 dmactl; +	void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + +	dmactl = readb(mmio + ATA_DMA_CMD); + +	/* Clear the start bit */ +	if (dmactl & ATA_DMA_START) { +		dmactl &= ~ATA_DMA_START; +		writeb(dmactl, mmio + ATA_DMA_CMD); +	} + +	return sata_sff_hardreset(link, class, deadline); +}  static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)  { @@ -289,23 +321,11 @@ static u8 k2_stat_check_status(struct ata_port *ap)  }  #ifdef CONFIG_PPC_OF -/* - * k2_sata_proc_info - * inout : decides on the direction of the dataflow and the meaning of the - *	   variables - * buffer: If inout==FALSE data is being written to it else read from it - * *start: If inout==FALSE start of the valid data in the buffer - * offset: If inout==FALSE offset from the beginning of the imaginary file - *	   from which we start writing into the buffer - * length: If inout==FALSE max number of bytes to be written into the buffer - *	   else number of bytes in the buffer - */ -static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, -			     off_t offset, int count, int inout) +static int k2_sata_show_info(struct seq_file *m, struct Scsi_Host *shost)  {  	struct ata_port *ap;  	struct device_node *np; -	int len, index; +	int index;  	/* Find  the ata_port */  	ap = ata_shost_to_port(shost); @@ -323,15 +343,12 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,  		const u32 *reg = of_get_property(np, "reg", NULL);  		if (!reg)  			continue; -		if (index == *reg) +		if (index == *reg) { +			seq_printf(m, "devspec: %s\n", np->full_name);  			break; +		}  	} -	if (np == NULL) -		return 0; - -	len = sprintf(page, "devspec: %s\n", np->full_name); - -	return len; +	return 0;  }  #endif /* CONFIG_PPC_OF */ @@ -339,13 +356,15 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,  static struct scsi_host_template k2_sata_sht = {  	ATA_BMDMA_SHT(DRV_NAME),  #ifdef CONFIG_PPC_OF -	.proc_info		= k2_sata_proc_info, +	.show_info		= k2_sata_show_info,  #endif  };  static struct ata_port_operations k2_sata_ops = {  	.inherits		= &ata_bmdma_port_ops, +	.softreset              = k2_sata_softreset, +	.hardreset              = k2_sata_hardreset,  	.sff_tf_load		= k2_sata_tf_load,  	.sff_tf_read		= k2_sata_tf_read,  	.sff_check_status	= k2_stat_check_status, @@ -359,8 +378,7 @@ static struct ata_port_operations k2_sata_ops = {  static const struct ata_port_info k2_port_info[] = {  	/* chip_svw4 */  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA, +		.flags		= ATA_FLAG_SATA | K2_FLAG_NO_ATAPI_DMA,  		.pio_mask	= ATA_PIO4,  		.mwdma_mask	= ATA_MWDMA2,  		.udma_mask	= ATA_UDMA6, @@ -368,8 +386,7 @@ static const struct ata_port_info k2_port_info[] = {  	},  	/* chip_svw8 */  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA | +		.flags		= ATA_FLAG_SATA | K2_FLAG_NO_ATAPI_DMA |  				  K2_FLAG_SATA_8_PORTS,  		.pio_mask	= ATA_PIO4,  		.mwdma_mask	= ATA_MWDMA2, @@ -378,8 +395,7 @@ static const struct ata_port_info k2_port_info[] = {  	},  	/* chip_svw42 */  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO | K2_FLAG_BAR_POS_3, +		.flags		= ATA_FLAG_SATA | K2_FLAG_BAR_POS_3,  		.pio_mask	= ATA_PIO4,  		.mwdma_mask	= ATA_MWDMA2,  		.udma_mask	= ATA_UDMA6, @@ -387,8 +403,7 @@ static const struct ata_port_info k2_port_info[] = {  	},  	/* chip_svw43 */  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO, +		.flags		= ATA_FLAG_SATA,  		.pio_mask	= ATA_PIO4,  		.mwdma_mask	= ATA_MWDMA2,  		.udma_mask	= ATA_UDMA6, @@ -418,15 +433,13 @@ static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base)  static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	const struct ata_port_info *ppi[] =  		{ &k2_port_info[ent->driver_data], NULL };  	struct ata_host *host;  	void __iomem *mmio_base;  	int n_ports, i, rc, bar_pos; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* allocate host */  	n_ports = 4; @@ -531,21 +544,10 @@ static struct pci_driver k2_sata_pci_driver = {  	.remove			= ata_pci_remove_one,  }; -static int __init k2_sata_init(void) -{ -	return pci_register_driver(&k2_sata_pci_driver); -} - -static void __exit k2_sata_exit(void) -{ -	pci_unregister_driver(&k2_sata_pci_driver); -} +module_pci_driver(k2_sata_pci_driver);  MODULE_AUTHOR("Benjamin Herrenschmidt");  MODULE_DESCRIPTION("low-level driver for K2 SATA controller");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, k2_sata_pci_tbl);  MODULE_VERSION(DRV_VERSION); - -module_init(k2_sata_init); -module_exit(k2_sata_exit); diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index bedd5188e5b..39b5de60a1f 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -1,7 +1,7 @@  /*   *  sata_sx4.c - Promise SATA   * - *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> + *  Maintained by:  Tejun Heo <tj@kernel.org>   *  		    Please ALWAYS copy linux-ide@vger.kernel.org   *		    on emails.   * @@ -82,7 +82,6 @@  #include <linux/module.h>  #include <linux/pci.h>  #include <linux/slab.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -273,9 +272,8 @@ static struct ata_port_operations pdc_20621_ops = {  static const struct ata_port_info pdc_port_info[] = {  	/* board_20621 */  	{ -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_SRST | ATA_FLAG_MMIO | -				  ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING, +		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_ATAPI | +				  ATA_FLAG_PIO_POLLING,  		.pio_mask	= ATA_PIO4,  		.mwdma_mask	= ATA_MWDMA2,  		.udma_mask	= ATA_UDMA6, @@ -316,9 +314,8 @@ static int pdc_port_start(struct ata_port *ap)  	return 0;  } -static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, -				   unsigned int portno, -					   unsigned int total_len) +static inline void pdc20621_ata_sg(u8 *buf, unsigned int portno, +				   unsigned int total_len)  {  	u32 addr;  	unsigned int dw = PDC_DIMM_APKT_PRD >> 2; @@ -338,9 +335,8 @@ static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,  		buf32[dw], buf32[dw + 1]);  } -static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf, -				    unsigned int portno, -					    unsigned int total_len) +static inline void pdc20621_host_sg(u8 *buf, unsigned int portno, +				    unsigned int total_len)  {  	u32 addr;  	unsigned int dw = PDC_DIMM_HPKT_PRD >> 2; @@ -487,10 +483,10 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)  	/*  	 * Build ATA, host DMA packets  	 */ -	pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len); +	pdc20621_host_sg(&pp->dimm_buf[0], portno, total_len);  	pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno); -	pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len); +	pdc20621_ata_sg(&pp->dimm_buf[0], portno, total_len);  	i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);  	if (qc->tf.flags & ATA_TFLAG_LBA48) @@ -1024,8 +1020,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,  	idx++;  	dist = ((long) (window_size - (offset + size))) >= 0 ? size :  		(long) (window_size - offset); -	memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4), -		      dist); +	memcpy_fromio(psource, dimm_mmio + offset / 4, dist);  	psource += dist;  	size -= dist; @@ -1034,8 +1029,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,  		readl(mmio + PDC_GENERAL_CTLR);  		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);  		readl(mmio + PDC_DIMM_WINDOW_CTLR); -		memcpy_fromio((char *) psource, (char *) (dimm_mmio), -			      window_size / 4); +		memcpy_fromio(psource, dimm_mmio, window_size / 4);  		psource += window_size;  		size -= window_size;  		idx++; @@ -1046,8 +1040,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,  		readl(mmio + PDC_GENERAL_CTLR);  		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);  		readl(mmio + PDC_DIMM_WINDOW_CTLR); -		memcpy_fromio((char *) psource, (char *) (dimm_mmio), -			      size / 4); +		memcpy_fromio(psource, dimm_mmio, size / 4);  	}  }  #endif @@ -1441,15 +1434,13 @@ static void pdc_20621_init(struct ata_host *host)  static int pdc_sata_init_one(struct pci_dev *pdev,  			     const struct pci_device_id *ent)  { -	static int printed_version;  	const struct ata_port_info *ppi[] =  		{ &pdc_port_info[ent->driver_data], NULL };  	struct ata_host *host;  	struct pdc_host_priv *hpriv;  	int i, rc; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* allocate host */  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4); @@ -1501,24 +1492,10 @@ static int pdc_sata_init_one(struct pci_dev *pdev,  				 IRQF_SHARED, &pdc_sata_sht);  } - -static int __init pdc_sata_init(void) -{ -	return pci_register_driver(&pdc_sata_pci_driver); -} - - -static void __exit pdc_sata_exit(void) -{ -	pci_unregister_driver(&pdc_sata_pci_driver); -} - +module_pci_driver(pdc_sata_pci_driver);  MODULE_AUTHOR("Jeff Garzik");  MODULE_DESCRIPTION("Promise SATA low-level driver");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl);  MODULE_VERSION(DRV_VERSION); - -module_init(pdc_sata_init); -module_exit(pdc_sata_exit); diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index b8578c32d34..08f98c3ed5c 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -28,7 +28,6 @@  #include <linux/module.h>  #include <linux/gfp.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -88,8 +87,7 @@ static struct ata_port_operations uli_ops = {  };  static const struct ata_port_info uli_port_info = { -	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -			  ATA_FLAG_IGN_SIMPLEX, +	.flags		= ATA_FLAG_SATA | ATA_FLAG_IGN_SIMPLEX,  	.pio_mask       = ATA_PIO4,  	.udma_mask      = ATA_UDMA6,  	.port_ops       = &uli_ops, @@ -146,7 +144,6 @@ static int uli_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)  static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	const struct ata_port_info *ppi[] = { &uli_port_info, NULL };  	unsigned int board_idx = (unsigned int) ent->driver_data;  	struct ata_host *host; @@ -155,8 +152,7 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	struct ata_ioports *ioaddr;  	int n_ports, rc; -	if (!printed_version++) -		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -246,16 +242,4 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  				 IRQF_SHARED, &uli_sht);  } -static int __init uli_init(void) -{ -	return pci_register_driver(&uli_pci_driver); -} - -static void __exit uli_exit(void) -{ -	pci_unregister_driver(&uli_pci_driver); -} - - -module_init(uli_init); -module_exit(uli_exit); +module_pci_driver(uli_pci_driver); diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index c21589986c6..47bf89464ce 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -1,7 +1,7 @@  /*   *  sata_via.c - VIA Serial ATA controllers   * - *  Maintained by:  Jeff Garzik <jgarzik@pobox.com> + *  Maintained by:  Tejun Heo <tj@kernel.org>   * 		   Please ALWAYS copy linux-ide@vger.kernel.org   *		   on emails.   * @@ -36,7 +36,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/device.h> @@ -104,7 +103,7 @@ static struct pci_driver svia_pci_driver = {  	.name			= DRV_NAME,  	.id_table		= svia_pci_tbl,  	.probe			= svia_init_one, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  	.suspend		= ata_pci_device_suspend,  	.resume			= ata_pci_device_resume,  #endif @@ -148,7 +147,7 @@ static struct ata_port_operations vt8251_ops = {  };  static const struct ata_port_info vt6420_port_info = { -	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, +	.flags		= ATA_FLAG_SATA,  	.pio_mask	= ATA_PIO4,  	.mwdma_mask	= ATA_MWDMA2,  	.udma_mask	= ATA_UDMA6, @@ -156,7 +155,7 @@ static const struct ata_port_info vt6420_port_info = {  };  static struct ata_port_info vt6421_sport_info = { -	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, +	.flags		= ATA_FLAG_SATA,  	.pio_mask	= ATA_PIO4,  	.mwdma_mask	= ATA_MWDMA2,  	.udma_mask	= ATA_UDMA6, @@ -164,7 +163,7 @@ static struct ata_port_info vt6421_sport_info = {  };  static struct ata_port_info vt6421_pport_info = { -	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY, +	.flags		= ATA_FLAG_SLAVE_POSS,  	.pio_mask	= ATA_PIO4,  	/* No MWDMA */  	.udma_mask	= ATA_UDMA6, @@ -172,8 +171,7 @@ static struct ata_port_info vt6421_pport_info = {  };  static struct ata_port_info vt8251_port_info = { -	.flags		= ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS | -			  ATA_FLAG_NO_LEGACY, +	.flags		= ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS,  	.pio_mask	= ATA_PIO4,  	.mwdma_mask	= ATA_MWDMA2,  	.udma_mask	= ATA_UDMA6, @@ -361,9 +359,9 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline)  	online = (sstatus & 0xf) == 0x3; -	ata_port_printk(ap, KERN_INFO, -			"SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n", -			online ? "up" : "down", sstatus, scontrol); +	ata_port_info(ap, +		      "SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n", +		      online ? "up" : "down", sstatus, scontrol);  	/* SStatus is read one more time */  	svia_scr_read(link, SCR_STATUS, &sstatus); @@ -470,7 +468,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)  	rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);  	if (rc) { -		dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n"); +		dev_err(&pdev->dev, "failed to iomap PCI BAR 5\n");  		return rc;  	} @@ -489,14 +487,14 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)  	*r_host = host = ata_host_alloc_pinfo(&pdev->dev, ppi, ARRAY_SIZE(ppi));  	if (!host) { -		dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host\n"); +		dev_err(&pdev->dev, "failed to allocate host\n");  		return -ENOMEM;  	}  	rc = pcim_iomap_regions(pdev, 0x3f, DRV_NAME);  	if (rc) { -		dev_printk(KERN_ERR, &pdev->dev, "failed to request/iomap " -			   "PCI BARs (errno=%d)\n", rc); +		dev_err(&pdev->dev, "failed to request/iomap PCI BARs (errno=%d)\n", +			rc);  		return rc;  	}  	host->iomap = pcim_iomap_table(pdev); @@ -527,7 +525,7 @@ static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)  	rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);  	if (rc) { -		dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n"); +		dev_err(&pdev->dev, "failed to iomap PCI BAR 5\n");  		return rc;  	} @@ -538,20 +536,19 @@ static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)  	return 0;  } -static void svia_configure(struct pci_dev *pdev) +static void svia_configure(struct pci_dev *pdev, int board_id)  {  	u8 tmp8;  	pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8); -	dev_printk(KERN_INFO, &pdev->dev, "routed to hard irq line %d\n", -	       (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f); +	dev_info(&pdev->dev, "routed to hard irq line %d\n", +		 (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);  	/* make sure SATA channels are enabled */  	pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);  	if ((tmp8 & ALL_PORTS) != ALL_PORTS) { -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "enabling SATA channels (0x%x)\n", -			   (int) tmp8); +		dev_dbg(&pdev->dev, "enabling SATA channels (0x%x)\n", +			(int)tmp8);  		tmp8 |= ALL_PORTS;  		pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);  	} @@ -559,9 +556,8 @@ static void svia_configure(struct pci_dev *pdev)  	/* make sure interrupts for each channel sent to us */  	pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);  	if ((tmp8 & ALL_PORTS) != ALL_PORTS) { -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "enabling SATA channel interrupts (0x%x)\n", -			   (int) tmp8); +		dev_dbg(&pdev->dev, "enabling SATA channel interrupts (0x%x)\n", +			(int) tmp8);  		tmp8 |= ALL_PORTS;  		pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);  	} @@ -569,21 +565,21 @@ static void svia_configure(struct pci_dev *pdev)  	/* make sure native mode is enabled */  	pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);  	if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) { -		dev_printk(KERN_DEBUG, &pdev->dev, -			   "enabling SATA channel native mode (0x%x)\n", -			   (int) tmp8); +		dev_dbg(&pdev->dev, +			"enabling SATA channel native mode (0x%x)\n", +			(int) tmp8);  		tmp8 |= NATIVE_MODE_ALL;  		pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);  	}  	/* -	 * vt6421 has problems talking to some drives.  The following +	 * vt6420/1 has problems talking to some drives.  The following  	 * is the fix from Joseph Chan <JosephChan@via.com.tw>.  	 *  	 * When host issues HOLD, device may send up to 20DW of data  	 * before acknowledging it with HOLDA and the host should be  	 * able to buffer them in FIFO.  Unfortunately, some WD drives -	 * send upto 40DW before acknowledging HOLD and, in the +	 * send up to 40DW before acknowledging HOLD and, in the  	 * default configuration, this ends up overflowing vt6421's  	 * FIFO, making the controller abort the transaction with  	 * R_ERR. @@ -596,8 +592,9 @@ static void svia_configure(struct pci_dev *pdev)  	 *  	 * https://bugzilla.kernel.org/show_bug.cgi?id=15173  	 * http://article.gmane.org/gmane.linux.ide/46352 +	 * http://thread.gmane.org/gmane.linux.kernel/1062139  	 */ -	if (pdev->device == 0x3249) { +	if (board_id == vt6420 || board_id == vt6421) {  		pci_read_config_byte(pdev, 0x52, &tmp8);  		tmp8 |= 1 << 2;  		pci_write_config_byte(pdev, 0x52, tmp8); @@ -606,15 +603,13 @@ static void svia_configure(struct pci_dev *pdev)  static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  { -	static int printed_version;  	unsigned int i;  	int rc;  	struct ata_host *host = NULL;  	int board_id = (int) ent->driver_data;  	const unsigned *bar_sizes; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	rc = pcim_enable_device(pdev);  	if (rc) @@ -628,7 +623,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)  		if ((pci_resource_start(pdev, i) == 0) ||  		    (pci_resource_len(pdev, i) < bar_sizes[i])) { -			dev_printk(KERN_ERR, &pdev->dev, +			dev_err(&pdev->dev,  				"invalid PCI BAR %u (sz 0x%llx, val 0x%llx)\n",  				i,  				(unsigned long long)pci_resource_start(pdev, i), @@ -652,22 +647,11 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (rc)  		return rc; -	svia_configure(pdev); +	svia_configure(pdev, board_id);  	pci_set_master(pdev);  	return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,  				 IRQF_SHARED, &svia_sht);  } -static int __init svia_init(void) -{ -	return pci_register_driver(&svia_pci_driver); -} - -static void __exit svia_exit(void) -{ -	pci_unregister_driver(&svia_pci_driver); -} - -module_init(svia_init); -module_exit(svia_exit); +module_pci_driver(svia_pci_driver); diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index b777176ff49..29e847aac34 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -37,7 +37,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/init.h>  #include <linux/blkdev.h>  #include <linux/delay.h>  #include <linux/interrupt.h> @@ -273,9 +272,8 @@ static irqreturn_t vsc_sata_interrupt(int irq, void *dev_instance)  	if (unlikely(status == 0xffffffff || status == 0)) {  		if (status) -			dev_printk(KERN_ERR, host->dev, -				": IRQ status == 0xffffffff, " -				"PCI fault or device removal?\n"); +			dev_err(host->dev, +				": IRQ status == 0xffffffff, PCI fault or device removal?\n");  		goto out;  	} @@ -313,8 +311,7 @@ static struct ata_port_operations vsc_sata_ops = {  	.scr_write		= vsc_sata_scr_write,  }; -static void __devinit vsc_sata_setup_port(struct ata_ioports *port, -					  void __iomem *base) +static void vsc_sata_setup_port(struct ata_ioports *port, void __iomem *base)  {  	port->cmd_addr		= base + VSC_SATA_TF_CMD_OFFSET;  	port->data_addr		= base + VSC_SATA_TF_DATA_OFFSET; @@ -336,26 +333,23 @@ static void __devinit vsc_sata_setup_port(struct ata_ioports *port,  } -static int __devinit vsc_sata_init_one(struct pci_dev *pdev, -				       const struct pci_device_id *ent) +static int vsc_sata_init_one(struct pci_dev *pdev, +			     const struct pci_device_id *ent)  {  	static const struct ata_port_info pi = { -		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | -				  ATA_FLAG_MMIO, +		.flags		= ATA_FLAG_SATA,  		.pio_mask	= ATA_PIO4,  		.mwdma_mask	= ATA_MWDMA2,  		.udma_mask	= ATA_UDMA6,  		.port_ops	= &vsc_sata_ops,  	};  	const struct ata_port_info *ppi[] = { &pi, NULL }; -	static int printed_version;  	struct ata_host *host;  	void __iomem *mmio_base;  	int i, rc;  	u8 cls; -	if (!printed_version++) -		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); +	ata_print_version_once(&pdev->dev, DRV_VERSION);  	/* allocate host */  	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4); @@ -370,7 +364,7 @@ static int __devinit vsc_sata_init_one(struct pci_dev *pdev,  	if (pci_resource_len(pdev, 0) == 0)  		return -ENODEV; -	/* map IO regions and intialize host accordingly */ +	/* map IO regions and initialize host accordingly */  	rc = pcim_iomap_regions(pdev, 1 << VSC_MMIO_BAR, DRV_NAME);  	if (rc == -EBUSY)  		pcim_pin_device(pdev); @@ -440,21 +434,10 @@ static struct pci_driver vsc_sata_pci_driver = {  	.remove			= ata_pci_remove_one,  }; -static int __init vsc_sata_init(void) -{ -	return pci_register_driver(&vsc_sata_pci_driver); -} - -static void __exit vsc_sata_exit(void) -{ -	pci_unregister_driver(&vsc_sata_pci_driver); -} +module_pci_driver(vsc_sata_pci_driver);  MODULE_AUTHOR("Jeremy Higdon");  MODULE_DESCRIPTION("low-level driver for Vitesse VSC7174 SATA controller");  MODULE_LICENSE("GPL");  MODULE_DEVICE_TABLE(pci, vsc_sata_pci_tbl);  MODULE_VERSION(DRV_VERSION); - -module_init(vsc_sata_init); -module_exit(vsc_sata_exit);  | 
