Commit 8019aa94 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: (79 commits)
  ata-acpi: don't call _GTF for disabled drive
  sata_mv add temporary 3 second init delay for SiliconImage PMs
  sata_mv remove redundant edma init code
  sata_mv add basic port multiplier support
  sata_mv fix SOC flags, enable NCQ on SOC
  sata_mv disable hotplug for now
  sata_mv cosmetics
  sata_mv hardreset rework
  [libata] improve Kconfig help text for new PMP, SFF options
  libata: make EH fail gracefully if no reset method is available
  libata: Be a bit more slack about early devices
  libata: cable logic
  libata: move link onlineness check out of softreset methods
  libata: kill dead code paths in reset path
  pata_scc: fix build breakage
  libata: make PMP support optional
  libata: implement PMP helpers
  libata: separate PMP support code from core code
  libata: make SFF support optional
  libata: don't use ap->ioaddr in non-SFF drivers
  ...
parents 73e3e648 48feb3c4
Loading
Loading
Loading
Loading
+46 −18
Original line number Original line Diff line number Diff line
@@ -28,7 +28,7 @@ config ATA_NONSTANDARD
       default n
       default n


config ATA_ACPI
config ATA_ACPI
	bool
	bool "ATA ACPI Support"
	depends on ACPI && PCI
	depends on ACPI && PCI
	select ACPI_DOCK
	select ACPI_DOCK
	default y
	default y
@@ -41,6 +41,13 @@ config ATA_ACPI
	  You can disable this at kernel boot time by using the
	  You can disable this at kernel boot time by using the
	  option libata.noacpi=1
	  option libata.noacpi=1


config SATA_PMP
	bool "SATA Port Multiplier support"
	default y
	help
	  This option adds support for SATA Port Multipliers
	  (the SATA version of an ethernet hub, or SAS expander).

config SATA_AHCI
config SATA_AHCI
	tristate "AHCI SATA support"
	tristate "AHCI SATA support"
	depends on PCI
	depends on PCI
@@ -49,6 +56,43 @@ config SATA_AHCI


	  If unsure, say N.
	  If unsure, say N.


config SATA_SIL24
	tristate "Silicon Image 3124/3132 SATA support"
	depends on PCI
	help
	  This option enables support for Silicon Image 3124/3132 Serial ATA.

	  If unsure, say N.

config SATA_FSL
	tristate "Freescale 3.0Gbps SATA support"
	depends on FSL_SOC
	help
	  This option enables support for Freescale 3.0Gbps SATA controller.
	  It can be found on MPC837x and MPC8315.

	  If unsure, say N.

config ATA_SFF
	bool "ATA SFF support"
	default y
	help
	  This option adds support for ATA controllers with SFF
	  compliant or similar programming interface.

	  SFF is the legacy IDE interface that has been around since
	  the dawn of time.  Almost all PATA controllers have an
	  SFF interface.  Many SATA controllers have an SFF interface
	  when configured into a legacy compatibility mode.

	  For users with exclusively modern controllers like AHCI,
	  Silicon Image 3124, or Marvell 6440, you may choose to
	  disable this uneeded SFF support.

	  If unsure, say Y.

if ATA_SFF

config SATA_SVW
config SATA_SVW
	tristate "ServerWorks Frodo / Apple K2 SATA support"
	tristate "ServerWorks Frodo / Apple K2 SATA support"
	depends on PCI
	depends on PCI
@@ -125,14 +169,6 @@ config SATA_SIL


	  If unsure, say N.
	  If unsure, say N.


config SATA_SIL24
	tristate "Silicon Image 3124/3132 SATA support"
	depends on PCI
	help
	  This option enables support for Silicon Image 3124/3132 Serial ATA.

	  If unsure, say N.

config SATA_SIS
config SATA_SIS
	tristate "SiS 964/965/966/180 SATA support"
	tristate "SiS 964/965/966/180 SATA support"
	depends on PCI
	depends on PCI
@@ -183,15 +219,6 @@ config PATA_ACPI
	  firmware in the BIOS. This driver can sometimes handle
	  firmware in the BIOS. This driver can sometimes handle
	  otherwise unsupported hardware.
	  otherwise unsupported hardware.


config SATA_FSL
	tristate "Freescale 3.0Gbps SATA support"
	depends on FSL_SOC
	help
	  This option enables support for Freescale 3.0Gbps SATA controller.
	  It can be found on MPC837x and MPC8315.

	  If unsure, say N.

config PATA_ALI
config PATA_ALI
	tristate "ALi PATA support (Experimental)"
	tristate "ALi PATA support (Experimental)"
	depends on PCI && EXPERIMENTAL
	depends on PCI && EXPERIMENTAL
@@ -679,4 +706,5 @@ config PATA_BF54X


	  If unsure, say N.
	  If unsure, say N.


endif # ATA_SFF
endif # ATA
endif # ATA
+3 −2
Original line number Original line Diff line number Diff line
@@ -78,6 +78,7 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o
# Should be last libata driver
# Should be last libata driver
obj-$(CONFIG_PATA_LEGACY)	+= pata_legacy.o
obj-$(CONFIG_PATA_LEGACY)	+= pata_legacy.o


libata-objs	:= libata-core.o libata-scsi.o libata-sff.o libata-eh.o \
libata-objs	:= libata-core.o libata-scsi.o libata-eh.o
		   libata-pmp.o
libata-$(CONFIG_ATA_SFF)	+= libata-sff.o
libata-$(CONFIG_SATA_PMP)	+= libata-pmp.o
libata-$(CONFIG_ATA_ACPI)	+= libata-acpi.o
libata-$(CONFIG_ATA_ACPI)	+= libata-acpi.o
+83 −226
Original line number Original line Diff line number Diff line
@@ -62,7 +62,6 @@ enum {
	AHCI_MAX_PORTS		= 32,
	AHCI_MAX_PORTS		= 32,
	AHCI_MAX_SG		= 168, /* hardware max is 64K */
	AHCI_MAX_SG		= 168, /* hardware max is 64K */
	AHCI_DMA_BOUNDARY	= 0xffffffff,
	AHCI_DMA_BOUNDARY	= 0xffffffff,
	AHCI_USE_CLUSTERING	= 1,
	AHCI_MAX_CMDS		= 32,
	AHCI_MAX_CMDS		= 32,
	AHCI_CMD_SZ		= 32,
	AHCI_CMD_SZ		= 32,
	AHCI_CMD_SLOT_SZ	= AHCI_MAX_CMDS * AHCI_CMD_SZ,
	AHCI_CMD_SLOT_SZ	= AHCI_MAX_CMDS * AHCI_CMD_SZ,
@@ -198,7 +197,6 @@ enum {
					  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
					  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
					  ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
					  ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
					  ATA_FLAG_IPM,
					  ATA_FLAG_IPM,
	AHCI_LFLAG_COMMON		= ATA_LFLAG_SKIP_D2H_BSY,


	ICH_MAP				= 0x90, /* ICH MAP register */
	ICH_MAP				= 0x90, /* ICH MAP register */
};
};
@@ -245,19 +243,24 @@ static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
static void ahci_irq_clear(struct ata_port *ap);
static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
static int ahci_port_start(struct ata_port *ap);
static int ahci_port_start(struct ata_port *ap);
static void ahci_port_stop(struct ata_port *ap);
static void ahci_port_stop(struct ata_port *ap);
static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
static void ahci_qc_prep(struct ata_queued_cmd *qc);
static void ahci_qc_prep(struct ata_queued_cmd *qc);
static u8 ahci_check_status(struct ata_port *ap);
static void ahci_freeze(struct ata_port *ap);
static void ahci_freeze(struct ata_port *ap);
static void ahci_thaw(struct ata_port *ap);
static void ahci_thaw(struct ata_port *ap);
static void ahci_pmp_attach(struct ata_port *ap);
static void ahci_pmp_attach(struct ata_port *ap);
static void ahci_pmp_detach(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_hardreset(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 int ahci_p5wdh_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_error_handler(struct ata_port *ap);
static void ahci_vt8251_error_handler(struct ata_port *ap);
static void ahci_p5wdh_error_handler(struct ata_port *ap);
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
static int ahci_port_resume(struct ata_port *ap);
static int ahci_port_resume(struct ata_port *ap);
static void ahci_dev_config(struct ata_device *dev);
static void ahci_dev_config(struct ata_device *dev);
@@ -276,129 +279,54 @@ static struct class_device_attribute *ahci_shost_attrs[] = {
};
};


static struct scsi_host_template ahci_sht = {
static struct scsi_host_template ahci_sht = {
	.module			= THIS_MODULE,
	ATA_NCQ_SHT(DRV_NAME),
	.name			= DRV_NAME,
	.ioctl			= ata_scsi_ioctl,
	.queuecommand		= ata_scsi_queuecmd,
	.change_queue_depth	= ata_scsi_change_queue_depth,
	.can_queue		= AHCI_MAX_CMDS - 1,
	.can_queue		= AHCI_MAX_CMDS - 1,
	.this_id		= ATA_SHT_THIS_ID,
	.sg_tablesize		= AHCI_MAX_SG,
	.sg_tablesize		= AHCI_MAX_SG,
	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
	.emulated		= ATA_SHT_EMULATED,
	.use_clustering		= AHCI_USE_CLUSTERING,
	.proc_name		= DRV_NAME,
	.dma_boundary		= AHCI_DMA_BOUNDARY,
	.dma_boundary		= AHCI_DMA_BOUNDARY,
	.slave_configure	= ata_scsi_slave_config,
	.slave_destroy		= ata_scsi_slave_destroy,
	.bios_param		= ata_std_bios_param,
	.shost_attrs		= ahci_shost_attrs,
	.shost_attrs		= ahci_shost_attrs,
};
};


static const struct ata_port_operations ahci_ops = {
static struct ata_port_operations ahci_ops = {
	.check_status		= ahci_check_status,
	.inherits		= &sata_pmp_port_ops,
	.check_altstatus	= ahci_check_status,
	.dev_select		= ata_noop_dev_select,

	.dev_config		= ahci_dev_config,

	.tf_read		= ahci_tf_read,


	.qc_defer		= sata_pmp_qc_defer_cmd_switch,
	.qc_defer		= sata_pmp_qc_defer_cmd_switch,
	.qc_prep		= ahci_qc_prep,
	.qc_prep		= ahci_qc_prep,
	.qc_issue		= ahci_qc_issue,
	.qc_issue		= ahci_qc_issue,

	.qc_fill_rtf		= ahci_qc_fill_rtf,
	.irq_clear		= ahci_irq_clear,

	.scr_read		= ahci_scr_read,
	.scr_write		= ahci_scr_write,


	.freeze			= ahci_freeze,
	.freeze			= ahci_freeze,
	.thaw			= ahci_thaw,
	.thaw			= ahci_thaw,

	.softreset		= ahci_softreset,
	.hardreset		= ahci_hardreset,
	.postreset		= ahci_postreset,
	.pmp_softreset		= ahci_softreset,
	.error_handler		= ahci_error_handler,
	.error_handler		= ahci_error_handler,
	.post_internal_cmd	= ahci_post_internal_cmd,
	.post_internal_cmd	= ahci_post_internal_cmd,

	.dev_config		= ahci_dev_config,
	.pmp_attach		= ahci_pmp_attach,
	.pmp_detach		= ahci_pmp_detach,

#ifdef CONFIG_PM
	.port_suspend		= ahci_port_suspend,
	.port_resume		= ahci_port_resume,
#endif
	.enable_pm		= ahci_enable_alpm,
	.disable_pm		= ahci_disable_alpm,

	.port_start		= ahci_port_start,
	.port_stop		= ahci_port_stop,
};

static const struct ata_port_operations ahci_vt8251_ops = {
	.check_status		= ahci_check_status,
	.check_altstatus	= ahci_check_status,
	.dev_select		= ata_noop_dev_select,

	.tf_read		= ahci_tf_read,

	.qc_defer		= sata_pmp_qc_defer_cmd_switch,
	.qc_prep		= ahci_qc_prep,
	.qc_issue		= ahci_qc_issue,

	.irq_clear		= ahci_irq_clear,


	.scr_read		= ahci_scr_read,
	.scr_read		= ahci_scr_read,
	.scr_write		= ahci_scr_write,
	.scr_write		= ahci_scr_write,

	.freeze			= ahci_freeze,
	.thaw			= ahci_thaw,

	.error_handler		= ahci_vt8251_error_handler,
	.post_internal_cmd	= ahci_post_internal_cmd,

	.pmp_attach		= ahci_pmp_attach,
	.pmp_attach		= ahci_pmp_attach,
	.pmp_detach		= ahci_pmp_detach,
	.pmp_detach		= ahci_pmp_detach,


	.enable_pm		= ahci_enable_alpm,
	.disable_pm		= ahci_disable_alpm,
#ifdef CONFIG_PM
#ifdef CONFIG_PM
	.port_suspend		= ahci_port_suspend,
	.port_suspend		= ahci_port_suspend,
	.port_resume		= ahci_port_resume,
	.port_resume		= ahci_port_resume,
#endif
#endif

	.port_start		= ahci_port_start,
	.port_start		= ahci_port_start,
	.port_stop		= ahci_port_stop,
	.port_stop		= ahci_port_stop,
};
};


static const struct ata_port_operations ahci_p5wdh_ops = {
static struct ata_port_operations ahci_vt8251_ops = {
	.check_status		= ahci_check_status,
	.inherits		= &ahci_ops,
	.check_altstatus	= ahci_check_status,
	.hardreset		= ahci_vt8251_hardreset,
	.dev_select		= ata_noop_dev_select,
};

	.tf_read		= ahci_tf_read,

	.qc_defer		= sata_pmp_qc_defer_cmd_switch,
	.qc_prep		= ahci_qc_prep,
	.qc_issue		= ahci_qc_issue,

	.irq_clear		= ahci_irq_clear,

	.scr_read		= ahci_scr_read,
	.scr_write		= ahci_scr_write,

	.freeze			= ahci_freeze,
	.thaw			= ahci_thaw,

	.error_handler		= ahci_p5wdh_error_handler,
	.post_internal_cmd	= ahci_post_internal_cmd,

	.pmp_attach		= ahci_pmp_attach,
	.pmp_detach		= ahci_pmp_detach,

#ifdef CONFIG_PM
	.port_suspend		= ahci_port_suspend,
	.port_resume		= ahci_port_resume,
#endif


	.port_start		= ahci_port_start,
static struct ata_port_operations ahci_p5wdh_ops = {
	.port_stop		= ahci_port_stop,
	.inherits		= &ahci_ops,
	.hardreset		= ahci_p5wdh_hardreset,
};
};


#define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags)
#define AHCI_HFLAGS(flags)	.private_data	= (void *)(flags)
@@ -407,7 +335,6 @@ static const struct ata_port_info ahci_port_info[] = {
	/* board_ahci */
	/* board_ahci */
	{
	{
		.flags		= AHCI_FLAG_COMMON,
		.flags		= AHCI_FLAG_COMMON,
		.link_flags	= AHCI_LFLAG_COMMON,
		.pio_mask	= 0x1f, /* pio0-4 */
		.pio_mask	= 0x1f, /* pio0-4 */
		.udma_mask	= ATA_UDMA6,
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_ops,
		.port_ops	= &ahci_ops,
@@ -416,7 +343,6 @@ static const struct ata_port_info ahci_port_info[] = {
	{
	{
		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP),
		.flags		= AHCI_FLAG_COMMON,
		.flags		= AHCI_FLAG_COMMON,
		.link_flags	= AHCI_LFLAG_COMMON | ATA_LFLAG_HRST_TO_RESUME,
		.pio_mask	= 0x1f, /* pio0-4 */
		.pio_mask	= 0x1f, /* pio0-4 */
		.udma_mask	= ATA_UDMA6,
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_vt8251_ops,
		.port_ops	= &ahci_vt8251_ops,
@@ -425,7 +351,6 @@ static const struct ata_port_info ahci_port_info[] = {
	{
	{
		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
		.flags		= AHCI_FLAG_COMMON,
		.flags		= AHCI_FLAG_COMMON,
		.link_flags	= AHCI_LFLAG_COMMON,
		.pio_mask	= 0x1f, /* pio0-4 */
		.pio_mask	= 0x1f, /* pio0-4 */
		.udma_mask	= ATA_UDMA6,
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_ops,
		.port_ops	= &ahci_ops,
@@ -436,7 +361,6 @@ static const struct ata_port_info ahci_port_info[] = {
				 AHCI_HFLAG_32BIT_ONLY |
				 AHCI_HFLAG_32BIT_ONLY |
				 AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP),
				 AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP),
		.flags		= AHCI_FLAG_COMMON,
		.flags		= AHCI_FLAG_COMMON,
		.link_flags	= AHCI_LFLAG_COMMON,
		.pio_mask	= 0x1f, /* pio0-4 */
		.pio_mask	= 0x1f, /* pio0-4 */
		.udma_mask	= ATA_UDMA6,
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_ops,
		.port_ops	= &ahci_ops,
@@ -447,7 +371,6 @@ static const struct ata_port_info ahci_port_info[] = {
				 AHCI_HFLAG_MV_PATA),
				 AHCI_HFLAG_MV_PATA),
		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
		.link_flags	= AHCI_LFLAG_COMMON,
		.pio_mask	= 0x1f, /* pio0-4 */
		.pio_mask	= 0x1f, /* pio0-4 */
		.udma_mask	= ATA_UDMA6,
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_ops,
		.port_ops	= &ahci_ops,
@@ -457,7 +380,6 @@ static const struct ata_port_info ahci_port_info[] = {
		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
		AHCI_HFLAGS	(AHCI_HFLAG_IGN_SERR_INTERNAL |
				 AHCI_HFLAG_NO_PMP),
				 AHCI_HFLAG_NO_PMP),
		.flags		= AHCI_FLAG_COMMON,
		.flags		= AHCI_FLAG_COMMON,
		.link_flags	= AHCI_LFLAG_COMMON,
		.pio_mask	= 0x1f, /* pio0-4 */
		.pio_mask	= 0x1f, /* pio0-4 */
		.udma_mask	= ATA_UDMA6,
		.udma_mask	= ATA_UDMA6,
		.port_ops	= &ahci_ops,
		.port_ops	= &ahci_ops,
@@ -1255,13 +1177,14 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,


static int ahci_kick_engine(struct ata_port *ap, int force_restart)
static int ahci_kick_engine(struct ata_port *ap, int force_restart)
{
{
	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
	void __iomem *port_mmio = ahci_port_base(ap);
	struct ahci_host_priv *hpriv = ap->host->private_data;
	struct ahci_host_priv *hpriv = ap->host->private_data;
	u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
	u32 tmp;
	u32 tmp;
	int busy, rc;
	int busy, rc;


	/* do we need to kick the port? */
	/* do we need to kick the port? */
	busy = ahci_check_status(ap) & (ATA_BUSY | ATA_DRQ);
	busy = status & (ATA_BUSY | ATA_DRQ);
	if (!busy && !force_restart)
	if (!busy && !force_restart)
		return 0;
		return 0;


@@ -1328,10 +1251,21 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
	return 0;
	return 0;
}
}


static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
static int ahci_check_ready(struct ata_link *link)
			     int pmp, unsigned long deadline)
{
	void __iomem *port_mmio = ahci_port_base(link->ap);
	u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;

	if (!(status & ATA_BUSY))
		return 1;
	return 0;
}

static int ahci_softreset(struct ata_link *link, unsigned int *class,
			  unsigned long deadline)
{
{
	struct ata_port *ap = link->ap;
	struct ata_port *ap = link->ap;
	int pmp = sata_srst_pmp(link);
	const char *reason = NULL;
	const char *reason = NULL;
	unsigned long now, msecs;
	unsigned long now, msecs;
	struct ata_taskfile tf;
	struct ata_taskfile tf;
@@ -1339,12 +1273,6 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,


	DPRINTK("ENTER\n");
	DPRINTK("ENTER\n");


	if (ata_link_offline(link)) {
		DPRINTK("PHY reports no device\n");
		*class = ATA_DEV_NONE;
		return 0;
	}

	/* prepare for SRST (AHCI-1.1 10.4.1) */
	/* prepare for SRST (AHCI-1.1 10.4.1) */
	rc = ahci_kick_engine(ap, 1);
	rc = ahci_kick_engine(ap, 1);
	if (rc && rc != -EOPNOTSUPP)
	if (rc && rc != -EOPNOTSUPP)
@@ -1374,10 +1302,8 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
	tf.ctl &= ~ATA_SRST;
	tf.ctl &= ~ATA_SRST;
	ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
	ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);


	/* wait a while before checking status */
	/* wait for link to become ready */
	ata_wait_after_reset(ap, deadline);
	rc = ata_wait_after_reset(link, deadline, ahci_check_ready);

	rc = ata_wait_ready(ap, deadline);
	/* link occupied, -ENODEV too is an error */
	/* link occupied, -ENODEV too is an error */
	if (rc) {
	if (rc) {
		reason = "device not ready";
		reason = "device not ready";
@@ -1393,24 +1319,15 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
	return rc;
	return rc;
}
}


static int ahci_softreset(struct ata_link *link, unsigned int *class,
			  unsigned long deadline)
{
	int pmp = 0;

	if (link->ap->flags & ATA_FLAG_PMP)
		pmp = SATA_PMP_CTRL_PORT;

	return ahci_do_softreset(link, class, pmp, deadline);
}

static int ahci_hardreset(struct ata_link *link, unsigned int *class,
static int ahci_hardreset(struct ata_link *link, unsigned int *class,
			  unsigned long deadline)
			  unsigned long deadline)
{
{
	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
	struct ata_port *ap = link->ap;
	struct ata_port *ap = link->ap;
	struct ahci_port_priv *pp = ap->private_data;
	struct ahci_port_priv *pp = ap->private_data;
	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
	struct ata_taskfile tf;
	struct ata_taskfile tf;
	bool online;
	int rc;
	int rc;


	DPRINTK("ENTER\n");
	DPRINTK("ENTER\n");
@@ -1422,14 +1339,13 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
	tf.command = 0x80;
	tf.command = 0x80;
	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
	ata_tf_to_fis(&tf, 0, 0, d2h_fis);


	rc = sata_std_hardreset(link, class, deadline);
	rc = sata_link_hardreset(link, timing, deadline, &online,
				 ahci_check_ready);


	ahci_start_engine(ap);
	ahci_start_engine(ap);


	if (rc == 0 && ata_link_online(link))
	if (online)
		*class = ahci_dev_classify(ap);
		*class = ahci_dev_classify(ap);
	if (rc != -EAGAIN && *class == ATA_DEV_UNKNOWN)
		*class = ATA_DEV_NONE;


	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
	return rc;
	return rc;
@@ -1439,7 +1355,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
				 unsigned long deadline)
				 unsigned long deadline)
{
{
	struct ata_port *ap = link->ap;
	struct ata_port *ap = link->ap;
	u32 serror;
	bool online;
	int rc;
	int rc;


	DPRINTK("ENTER\n");
	DPRINTK("ENTER\n");
@@ -1447,11 +1363,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
	ahci_stop_engine(ap);
	ahci_stop_engine(ap);


	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
				 deadline);
				 deadline, &online, NULL);

	/* vt8251 needs SError cleared for the port to operate */
	ahci_scr_read(ap, SCR_ERROR, &serror);
	ahci_scr_write(ap, SCR_ERROR, serror);


	ahci_start_engine(ap);
	ahci_start_engine(ap);


@@ -1460,7 +1372,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
	/* vt8251 doesn't clear BSY on signature FIS reception,
	/* vt8251 doesn't clear BSY on signature FIS reception,
	 * request follow-up softreset.
	 * request follow-up softreset.
	 */
	 */
	return rc ?: -EAGAIN;
	return online ? -EAGAIN : rc;
}
}


static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
@@ -1470,6 +1382,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
	struct ahci_port_priv *pp = ap->private_data;
	struct ahci_port_priv *pp = ap->private_data;
	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
	struct ata_taskfile tf;
	struct ata_taskfile tf;
	bool online;
	int rc;
	int rc;


	ahci_stop_engine(ap);
	ahci_stop_engine(ap);
@@ -1480,16 +1393,10 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
	ata_tf_to_fis(&tf, 0, 0, d2h_fis);


	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
	rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
				 deadline);
				 deadline, &online, NULL);


	ahci_start_engine(ap);
	ahci_start_engine(ap);


	if (rc || ata_link_offline(link))
		return rc;

	/* spec mandates ">= 2ms" before checking status */
	msleep(150);

	/* The pseudo configuration device on SIMG4726 attached to
	/* The pseudo configuration device on SIMG4726 attached to
	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
	 * ASUS P5W-DH Deluxe doesn't send signature FIS after
	 * hardreset if no device is attached to the first downstream
	 * hardreset if no device is attached to the first downstream
@@ -1503,11 +1410,13 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
	 * have to be reset again.  For most cases, this should
	 * have to be reset again.  For most cases, this should
	 * suffice while making probing snappish enough.
	 * suffice while making probing snappish enough.
	 */
	 */
	rc = ata_wait_ready(ap, jiffies + 2 * HZ);
	if (online) {
		rc = ata_wait_after_reset(link, jiffies + 2 * HZ,
					  ahci_check_ready);
		if (rc)
		if (rc)
			ahci_kick_engine(ap, 0);
			ahci_kick_engine(ap, 0);

	}
	return 0;
	return rc;
}
}


static void ahci_postreset(struct ata_link *link, unsigned int *class)
static void ahci_postreset(struct ata_link *link, unsigned int *class)
@@ -1530,27 +1439,6 @@ static void ahci_postreset(struct ata_link *link, unsigned int *class)
	}
	}
}
}


static int ahci_pmp_softreset(struct ata_link *link, unsigned int *class,
			      unsigned long deadline)
{
	return ahci_do_softreset(link, class, link->pmp, deadline);
}

static u8 ahci_check_status(struct ata_port *ap)
{
	void __iomem *mmio = ap->ioaddr.cmd_addr;

	return readl(mmio + PORT_TFDATA) & 0xFF;
}

static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
	struct ahci_port_priv *pp = ap->private_data;
	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;

	ata_tf_from_fis(d2h_fis, tf);
}

static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
{
{
	struct scatterlist *sg;
	struct scatterlist *sg;
@@ -1663,27 +1551,27 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
		u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
		u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);


		active_ehi->err_mask |= AC_ERR_HSM;
		active_ehi->err_mask |= AC_ERR_HSM;
		active_ehi->action |= ATA_EH_SOFTRESET;
		active_ehi->action |= ATA_EH_RESET;
		ata_ehi_push_desc(active_ehi,
		ata_ehi_push_desc(active_ehi,
				  "unknown FIS %08x %08x %08x %08x" ,
				  "unknown FIS %08x %08x %08x %08x" ,
				  unk[0], unk[1], unk[2], unk[3]);
				  unk[0], unk[1], unk[2], unk[3]);
	}
	}


	if (ap->nr_pmp_links && (irq_stat & PORT_IRQ_BAD_PMP)) {
	if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) {
		active_ehi->err_mask |= AC_ERR_HSM;
		active_ehi->err_mask |= AC_ERR_HSM;
		active_ehi->action |= ATA_EH_SOFTRESET;
		active_ehi->action |= ATA_EH_RESET;
		ata_ehi_push_desc(active_ehi, "incorrect PMP");
		ata_ehi_push_desc(active_ehi, "incorrect PMP");
	}
	}


	if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
	if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
		host_ehi->err_mask |= AC_ERR_HOST_BUS;
		host_ehi->err_mask |= AC_ERR_HOST_BUS;
		host_ehi->action |= ATA_EH_SOFTRESET;
		host_ehi->action |= ATA_EH_RESET;
		ata_ehi_push_desc(host_ehi, "host bus error");
		ata_ehi_push_desc(host_ehi, "host bus error");
	}
	}


	if (irq_stat & PORT_IRQ_IF_ERR) {
	if (irq_stat & PORT_IRQ_IF_ERR) {
		host_ehi->err_mask |= AC_ERR_ATA_BUS;
		host_ehi->err_mask |= AC_ERR_ATA_BUS;
		host_ehi->action |= ATA_EH_SOFTRESET;
		host_ehi->action |= ATA_EH_RESET;
		ata_ehi_push_desc(host_ehi, "interface fatal error");
		ata_ehi_push_desc(host_ehi, "interface fatal error");
	}
	}


@@ -1704,7 +1592,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)


static void ahci_port_intr(struct ata_port *ap)
static void ahci_port_intr(struct ata_port *ap)
{
{
	void __iomem *port_mmio = ap->ioaddr.cmd_addr;
	void __iomem *port_mmio = ahci_port_base(ap);
	struct ata_eh_info *ehi = &ap->link.eh_info;
	struct ata_eh_info *ehi = &ap->link.eh_info;
	struct ahci_port_priv *pp = ap->private_data;
	struct ahci_port_priv *pp = ap->private_data;
	struct ahci_host_priv *hpriv = ap->host->private_data;
	struct ahci_host_priv *hpriv = ap->host->private_data;
@@ -1766,21 +1654,16 @@ static void ahci_port_intr(struct ata_port *ap)
	else
	else
		qc_active = readl(port_mmio + PORT_CMD_ISSUE);
		qc_active = readl(port_mmio + PORT_CMD_ISSUE);


	rc = ata_qc_complete_multiple(ap, qc_active, NULL);
	rc = ata_qc_complete_multiple(ap, qc_active);


	/* while resetting, invalid completions are expected */
	/* while resetting, invalid completions are expected */
	if (unlikely(rc < 0 && !resetting)) {
	if (unlikely(rc < 0 && !resetting)) {
		ehi->err_mask |= AC_ERR_HSM;
		ehi->err_mask |= AC_ERR_HSM;
		ehi->action |= ATA_EH_SOFTRESET;
		ehi->action |= ATA_EH_RESET;
		ata_port_freeze(ap);
		ata_port_freeze(ap);
	}
	}
}
}


static void ahci_irq_clear(struct ata_port *ap)
{
	/* TODO */
}

static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
{
{
	struct ata_host *host = dev_instance;
	struct ata_host *host = dev_instance;
@@ -1854,6 +1737,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
	return 0;
	return 0;
}
}


static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
{
	struct ahci_port_priv *pp = qc->ap->private_data;
	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;

	ata_tf_from_fis(d2h_fis, &qc->result_tf);
	return true;
}

static void ahci_freeze(struct ata_port *ap)
static void ahci_freeze(struct ata_port *ap)
{
{
	void __iomem *port_mmio = ahci_port_base(ap);
	void __iomem *port_mmio = ahci_port_base(ap);
@@ -1886,37 +1778,7 @@ static void ahci_error_handler(struct ata_port *ap)
		ahci_start_engine(ap);
		ahci_start_engine(ap);
	}
	}


	/* perform recovery */
	sata_pmp_error_handler(ap);
	sata_pmp_do_eh(ap, ata_std_prereset, ahci_softreset,
		       ahci_hardreset, ahci_postreset,
		       sata_pmp_std_prereset, ahci_pmp_softreset,
		       sata_pmp_std_hardreset, sata_pmp_std_postreset);
}

static void ahci_vt8251_error_handler(struct ata_port *ap)
{
	if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
		/* restart engine */
		ahci_stop_engine(ap);
		ahci_start_engine(ap);
	}

	/* perform recovery */
	ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_vt8251_hardreset,
		  ahci_postreset);
}

static void ahci_p5wdh_error_handler(struct ata_port *ap)
{
	if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
		/* restart engine */
		ahci_stop_engine(ap);
		ahci_start_engine(ap);
	}

	/* perform recovery */
	ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_p5wdh_hardreset,
		  ahci_postreset);
}
}


static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
@@ -1961,7 +1823,7 @@ static int ahci_port_resume(struct ata_port *ap)
	ahci_power_up(ap);
	ahci_power_up(ap);
	ahci_start_port(ap);
	ahci_start_port(ap);


	if (ap->nr_pmp_links)
	if (sata_pmp_attached(ap))
		ahci_pmp_attach(ap);
		ahci_pmp_attach(ap);
	else
	else
		ahci_pmp_detach(ap);
		ahci_pmp_detach(ap);
@@ -2324,7 +2186,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)


	for (i = 0; i < host->n_ports; i++) {
	for (i = 0; i < host->n_ports; i++) {
		struct ata_port *ap = host->ports[i];
		struct ata_port *ap = host->ports[i];
		void __iomem *port_mmio = ahci_port_base(ap);


		ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar");
		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,
@@ -2333,12 +2194,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
		/* set initial link pm policy */
		/* set initial link pm policy */
		ap->pm_policy = NOT_AVAILABLE;
		ap->pm_policy = NOT_AVAILABLE;


		/* standard SATA port setup */
		if (hpriv->port_map & (1 << i))
			ap->ioaddr.cmd_addr = port_mmio;

		/* disabled/not-implemented port */
		/* disabled/not-implemented port */
		else
		if (!(hpriv->port_map & (1 << i)))
			ap->ops = &ata_dummy_port_ops;
			ap->ops = &ata_dummy_port_ops;
	}
	}


+5 −46
Original line number Original line Diff line number Diff line
@@ -95,53 +95,13 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
}
}


static struct scsi_host_template generic_sht = {
static struct scsi_host_template generic_sht = {
	.module			= THIS_MODULE,
	ATA_BMDMA_SHT(DRV_NAME),
	.name			= DRV_NAME,
	.ioctl			= ata_scsi_ioctl,
	.queuecommand		= ata_scsi_queuecmd,
	.can_queue		= ATA_DEF_QUEUE,
	.this_id		= ATA_SHT_THIS_ID,
	.sg_tablesize		= LIBATA_MAX_PRD,
	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
	.emulated		= ATA_SHT_EMULATED,
	.use_clustering		= ATA_SHT_USE_CLUSTERING,
	.proc_name		= DRV_NAME,
	.dma_boundary		= ATA_DMA_BOUNDARY,
	.slave_configure	= ata_scsi_slave_config,
	.slave_destroy		= ata_scsi_slave_destroy,
	.bios_param		= ata_std_bios_param,
};
};


static struct ata_port_operations generic_port_ops = {
static struct ata_port_operations generic_port_ops = {
	.set_mode	= generic_set_mode,
	.inherits	= &ata_bmdma_port_ops,

	.tf_load	= ata_tf_load,
	.tf_read	= ata_tf_read,
	.check_status 	= ata_check_status,
	.exec_command	= ata_exec_command,
	.dev_select 	= ata_std_dev_select,

	.bmdma_setup 	= ata_bmdma_setup,
	.bmdma_start 	= ata_bmdma_start,
	.bmdma_stop	= ata_bmdma_stop,
	.bmdma_status 	= ata_bmdma_status,

	.data_xfer	= ata_data_xfer,

	.freeze		= ata_bmdma_freeze,
	.thaw		= ata_bmdma_thaw,
	.error_handler	= ata_bmdma_error_handler,
	.post_internal_cmd = ata_bmdma_post_internal_cmd,
	.cable_detect	= ata_cable_unknown,
	.cable_detect	= ata_cable_unknown,

	.set_mode	= generic_set_mode,
	.qc_prep 	= ata_qc_prep,
	.qc_issue	= ata_qc_issue_prot,

	.irq_handler	= ata_interrupt,
	.irq_clear	= ata_bmdma_irq_clear,
	.irq_on		= ata_irq_on,

	.port_start	= ata_sff_port_start,
};
};


static int all_generic_ide;		/* Set to claim all devices */
static int all_generic_ide;		/* Set to claim all devices */
@@ -160,7 +120,6 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
{
{
	u16 command;
	u16 command;
	static const struct ata_port_info info = {
	static const struct ata_port_info info = {
		.sht = &generic_sht,
		.flags = ATA_FLAG_SLAVE_POSS,
		.flags = ATA_FLAG_SLAVE_POSS,
		.pio_mask = 0x1f,
		.pio_mask = 0x1f,
		.mwdma_mask = 0x07,
		.mwdma_mask = 0x07,
@@ -191,9 +150,9 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
		return -ENODEV;
		return -ENODEV;


	if (dev->vendor == PCI_VENDOR_ID_AL)
	if (dev->vendor == PCI_VENDOR_ID_AL)
	    	ata_pci_clear_simplex(dev);
		ata_pci_bmdma_clear_simplex(dev);


	return ata_pci_init_one(dev, ppi);
	return ata_pci_sff_init_one(dev, ppi, &generic_sht, NULL);
}
}


static struct pci_device_id ata_generic[] = {
static struct pci_device_id ata_generic[] = {
+64 −248

File changed.

Preview size limit exceeded, changes collapsed.

Loading