diff options
Diffstat (limited to 'drivers/ata/ahci.c')
| -rw-r--r-- | drivers/ata/ahci.c | 566 | 
1 files changed, 406 insertions, 160 deletions
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);  | 
